working on manual sorting, it is starting to get shape, some problems arised but I will either solve them or declare them to actually be features
This commit is contained in:
parent
659cb4cbf7
commit
84aa24255c
@ -26,7 +26,7 @@
|
||||
<url type="donation">https://github.com/sponsors/martinrotter</url>
|
||||
<content_rating type="oars-1.1" />
|
||||
<releases>
|
||||
<release version="4.1.2" date="2022-03-03"/>
|
||||
<release version="4.1.2" date="2022-03-04"/>
|
||||
</releases>
|
||||
<content_rating type="oars-1.0">
|
||||
<content_attribute id="violence-cartoon">none</content_attribute>
|
||||
|
@ -27,6 +27,13 @@ FROM backup_Feeds;
|
||||
-- !
|
||||
DROP TABLE backup_Feeds;
|
||||
-- !
|
||||
UPDATE Feeds
|
||||
SET ordr = (
|
||||
SELECT COUNT(*)
|
||||
FROM Feeds ct
|
||||
WHERE Feeds.account_id = ct.account_id AND Feeds.category = ct.category AND ct.id < Feeds.id
|
||||
);
|
||||
-- !
|
||||
ALTER TABLE Categories RENAME TO backup_Categories;
|
||||
-- !
|
||||
CREATE TABLE Categories (
|
||||
@ -49,6 +56,13 @@ FROM backup_Categories;
|
||||
-- !
|
||||
DROP TABLE backup_Categories;
|
||||
-- !
|
||||
UPDATE Categories
|
||||
SET ordr = (
|
||||
SELECT COUNT(*)
|
||||
FROM Categories ct
|
||||
WHERE Categories.account_id = ct.account_id AND Categories.parent_id = ct.parent_id AND ct.id < Categories.id
|
||||
);
|
||||
-- !
|
||||
ALTER TABLE Accounts RENAME TO backup_Accounts;
|
||||
-- !
|
||||
CREATE TABLE Accounts (
|
||||
@ -65,7 +79,7 @@ CREATE TABLE Accounts (
|
||||
);
|
||||
-- !
|
||||
INSERT INTO Accounts (id, ordr, type, proxy_type, proxy_host, proxy_port, proxy_username, proxy_password, custom_data)
|
||||
SELECT id, id, type, proxy_type, proxy_host, proxy_port, proxy_username, proxy_password, custom_data
|
||||
SELECT id, id - 1, type, proxy_type, proxy_host, proxy_port, proxy_username, proxy_password, custom_data
|
||||
FROM backup_Accounts;
|
||||
-- !
|
||||
DROP TABLE backup_Accounts;
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "3rd-party/boolinq/boolinq.h"
|
||||
#include "database/databasefactory.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "definitions/definitions.h"
|
||||
#include "gui/dialogs/formmain.h"
|
||||
#include "miscellaneous/feedreader.h"
|
||||
@ -523,6 +524,12 @@ bool FeedsModel::emptyAllBins() {
|
||||
return result;
|
||||
}
|
||||
|
||||
void FeedsModel::changeSortOrder(RootItem* item, bool move_top, bool move_bottom, int new_sort_order) {
|
||||
QSqlDatabase db = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
DatabaseQueries::moveItem(item, move_top, move_bottom, new_sort_order, db);
|
||||
}
|
||||
|
||||
void FeedsModel::loadActivatedServiceAccounts() {
|
||||
auto serv = qApp->feedReader()->feedServices();
|
||||
|
||||
|
@ -107,6 +107,8 @@ class RSSGUARD_DLLSPEC FeedsModel : public QAbstractItemModel {
|
||||
bool restoreAllBins();
|
||||
bool emptyAllBins();
|
||||
|
||||
void changeSortOrder(RootItem* item, bool move_top, bool move_bottom, int new_sort_order);
|
||||
|
||||
// Feeds operations.
|
||||
bool markItemRead(RootItem* item, RootItem::ReadStatus read);
|
||||
bool markItemCleared(RootItem* item, bool clean_read_only);
|
||||
|
@ -1939,6 +1939,23 @@ void DatabaseQueries::createOverwriteCategory(const QSqlDatabase& db, Category*
|
||||
|
||||
if (category->id() <= 0) {
|
||||
// We need to insert category first.
|
||||
if (category->sortOrder() < 0) {
|
||||
q.exec(QSL("SELECT MAX(ordr) FROM Categories WHERE account_id = :account_id AND parent_id = :parent_id;"));
|
||||
q.bindValue(QSL(":account_id"), account_id);
|
||||
q.bindValue(QSL(":parent_id"), parent_id);
|
||||
|
||||
if (!q.exec()) {
|
||||
throw ApplicationException(q.lastError().text());
|
||||
}
|
||||
|
||||
q.next();
|
||||
|
||||
int next_order = (q.value(0).isNull() ? 0 : q.value(0).toInt()) + 1;
|
||||
|
||||
category->setSortOrder(next_order);
|
||||
q.finish();
|
||||
}
|
||||
|
||||
q.prepare(QSL("INSERT INTO "
|
||||
"Categories (parent_id, ordr, title, date_created, account_id) "
|
||||
"VALUES (0, 0, 'new', 0, %1);").arg(QString::number(account_id)));
|
||||
@ -1975,6 +1992,23 @@ void DatabaseQueries::createOverwriteFeed(const QSqlDatabase& db, Feed* feed, in
|
||||
|
||||
if (feed->id() <= 0) {
|
||||
// We need to insert feed first.
|
||||
if (feed->sortOrder() < 0) {
|
||||
q.exec(QSL("SELECT MAX(ordr) FROM Feeds WHERE account_id = :account_id AND category = :category;"));
|
||||
q.bindValue(QSL(":account_id"), account_id);
|
||||
q.bindValue(QSL(":category"), parent_id);
|
||||
|
||||
if (!q.exec()) {
|
||||
throw ApplicationException(q.lastError().text());
|
||||
}
|
||||
|
||||
q.next();
|
||||
|
||||
int next_order = (q.value(0).isNull() ? 0 : q.value(0).toInt()) + 1;
|
||||
|
||||
feed->setSortOrder(next_order);
|
||||
q.finish();
|
||||
}
|
||||
|
||||
q.prepare(QSL("INSERT INTO "
|
||||
"Feeds (title, ordr, date_created, category, update_type, update_interval, account_id, custom_id) "
|
||||
"VALUES ('new', 0, 0, 0, 0, 1, %1, 'new');").arg(QString::number(account_id)));
|
||||
@ -2008,6 +2042,9 @@ void DatabaseQueries::createOverwriteFeed(const QSqlDatabase& db, Feed* feed, in
|
||||
q.bindValue(QSL(":account_id"), account_id);
|
||||
q.bindValue(QSL(":custom_id"), feed->customId());
|
||||
q.bindValue(QSL(":id"), feed->id());
|
||||
|
||||
// TODO: upravit set na ordr = (SELECT MAX(ordr) FROM Feeds WHERE account_id = :account_id AND category = :category) + 1;
|
||||
// to ale pokud je sortOrder < 0
|
||||
q.bindValue(QSL(":ordr"), feed->sortOrder());
|
||||
q.bindValue(QSL(":is_off"), feed->isSwitchedOff());
|
||||
q.bindValue(QSL(":open_articles"), feed->openArticlesDirectly());
|
||||
@ -2026,8 +2063,22 @@ void DatabaseQueries::createOverwriteAccount(const QSqlDatabase& db, ServiceRoot
|
||||
QSqlQuery q(db);
|
||||
|
||||
if (account->accountId() <= 0) {
|
||||
// We need to insert account first.
|
||||
q.prepare(QSL("INSERT INTO Accounts (ordr, type) VALUES (0, :type);"));
|
||||
// We need to insert account and generate sort order first.
|
||||
if (account->sortOrder() < 0) {
|
||||
if (!q.exec(QSL("SELECT MAX(ordr) FROM Accounts;"))) {
|
||||
throw ApplicationException(q.lastError().text());
|
||||
}
|
||||
|
||||
q.next();
|
||||
|
||||
int next_order = (q.value(0).isNull() ? 0 : q.value(0).toInt()) + 1;
|
||||
|
||||
account->setSortOrder(next_order);
|
||||
q.finish();
|
||||
}
|
||||
|
||||
q.prepare(QSL("INSERT INTO Accounts (ordr, type) "
|
||||
"VALUES (0, :type);"));
|
||||
q.bindValue(QSL(":type"), account->code());
|
||||
|
||||
if (!q.exec()) {
|
||||
@ -2095,36 +2146,80 @@ bool DatabaseQueries::deleteCategory(const QSqlDatabase& db, int id) {
|
||||
return q.exec();
|
||||
}
|
||||
|
||||
void DatabaseQueries::fixupOrders(const QSqlDatabase& db) {
|
||||
// We first determine if there are same orders assigned to some items
|
||||
// which have same parent category/acc.
|
||||
QSqlQuery res = db.exec(QSL("SELECT COUNT(*) FROM Accounts GROUP BY ordr HAVING COUNT(*) > 1 "
|
||||
"UNION ALL "
|
||||
"SELECT COUNT(*) FROM Categories GROUP BY account_id, parent_id, ordr HAVING COUNT(*) > 1 "
|
||||
"UNION ALL "
|
||||
"SELECT COUNT(*) FROM Feeds GROUP BY account_id, category, ordr HAVING COUNT(*) > 1;"));
|
||||
bool should_fixup = res.lastError().isValid() || res.size() > 0;
|
||||
void DatabaseQueries::moveItem(RootItem* item, bool move_top, bool move_bottom, int move_index, const QSqlDatabase& db) {
|
||||
switch (item->kind()) {
|
||||
case RootItem::Kind::Feed:
|
||||
moveFeed(item->toFeed(), move_top, move_bottom, move_index, db);
|
||||
break;
|
||||
|
||||
if (should_fixup) {
|
||||
// Some orders are messed up, fix.
|
||||
qCriticalNN << LOGSEC_DB << "Order of items is messed up, fixing.";
|
||||
case RootItem::Kind::Category:
|
||||
break;
|
||||
|
||||
for (const QString& table : { QSL("Accounts"), QSL("Categories"), QSL("Feeds") }) {
|
||||
QSqlQuery q = db.exec(QSL("UPDATE %1 SET ordr = id;").arg(table));
|
||||
case RootItem::Kind::ServiceRoot:
|
||||
|
||||
if (q.lastError().isValid()) {
|
||||
qFatal("Fixup of messed up order failed: '%s'.", qPrintable(q.lastError().text()));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
qDebugNN << LOGSEC_DB << "No fixing of item order is needed.";
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseQueries::moveItemUp(RootItem* item, const QSqlDatabase& db) {}
|
||||
void DatabaseQueries::moveFeed(Feed* feed, bool move_top, bool move_bottom, int move_index, const QSqlDatabase& db) {
|
||||
if (feed->sortOrder() == move_index || /* Item is already sorted OK. */
|
||||
(!move_top && !move_bottom && move_index < 0 ) || /* Order cannot be smaller than 0 if we do not move to begin/end. */
|
||||
(move_top && feed->sortOrder() == 0)) { /* Item is already on top. */
|
||||
return;
|
||||
}
|
||||
|
||||
void DatabaseQueries::moveItemDown(RootItem* item, const QSqlDatabase& db) {}
|
||||
QSqlQuery q(db);
|
||||
|
||||
q.prepare(QSL("SELECT MAX(ordr) FROM Feeds WHERE account_id = :account_id AND category = :category;"));
|
||||
q.bindValue(QSL(":account_id"), feed->getParentServiceRoot()->accountId());
|
||||
q.bindValue(QSL(":category"), feed->parent()->id());
|
||||
|
||||
int max_sort_order;
|
||||
|
||||
if (q.exec() && q.next()) {
|
||||
max_sort_order = q.value(0).toInt();
|
||||
}
|
||||
else {
|
||||
throw ApplicationException(q.lastError().text());
|
||||
}
|
||||
|
||||
if (max_sort_order == 0 || /* We only have 1 item, nothing to sort. */
|
||||
max_sort_order == feed->sortOrder() || /* Item is already sorted OK. */
|
||||
move_index > max_sort_order) { /* Cannot move past biggest sort order. */
|
||||
return;
|
||||
}
|
||||
|
||||
if (move_top) {
|
||||
move_index = 0;
|
||||
}
|
||||
else if (move_bottom) {
|
||||
move_index = max_sort_order;
|
||||
}
|
||||
|
||||
int move_low = qMin(move_index, feed->sortOrder());
|
||||
int move_high = qMax(move_index, feed->sortOrder());
|
||||
|
||||
if (feed->sortOrder() > move_index) {
|
||||
q.prepare(QSL("UPDATE Feeds SET ordr = ordr + 1 "
|
||||
"WHERE account_id = :account_id AND category = :category AND ordr < :move_high AND ordr >= :move_low;"));
|
||||
}
|
||||
else {
|
||||
q.prepare(QSL("UPDATE Feeds SET ordr = ordr - 1 "
|
||||
"WHERE account_id = :account_id AND category = :category AND ordr > :move_low AND ordr <= :move_high;"));
|
||||
}
|
||||
|
||||
q.bindValue(QSL(":account_id"), feed->getParentServiceRoot()->accountId());
|
||||
q.bindValue(QSL(":category"), feed->parent()->id());
|
||||
q.bindValue(QSL(":move_low"), move_low);
|
||||
q.bindValue(QSL(":move_high"), move_high);
|
||||
|
||||
if (!q.exec()) {
|
||||
throw ApplicationException(q.lastError().text());
|
||||
}
|
||||
}
|
||||
|
||||
MessageFilter* DatabaseQueries::addMessageFilter(const QSqlDatabase& db, const QString& title,
|
||||
const QString& script) {
|
||||
|
@ -135,9 +135,8 @@ class DatabaseQueries {
|
||||
int account_id, bool* ok = nullptr);
|
||||
|
||||
// Item order methods.
|
||||
static void fixupOrders(const QSqlDatabase& db);
|
||||
static void moveItemUp(RootItem* item, const QSqlDatabase& db);
|
||||
static void moveItemDown(RootItem* item, const QSqlDatabase& db);
|
||||
static void moveItem(RootItem* item, bool move_top, bool move_bottom, int move_index, const QSqlDatabase& db);
|
||||
static void moveFeed(Feed* feed, bool move_top, bool move_bottom, int move_index, const QSqlDatabase& db);
|
||||
|
||||
// Message filters operators.
|
||||
static bool purgeLeftoverMessageFilterAssignments(const QSqlDatabase& db, int account_id);
|
||||
@ -338,9 +337,6 @@ Assignment DatabaseQueries::getFeeds(const QSqlDatabase& db,
|
||||
template<typename Categ, typename Fee>
|
||||
void DatabaseQueries::loadRootFromDatabase(ServiceRoot* root) {
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(root->metaObject()->className());
|
||||
|
||||
fixupOrders(database);
|
||||
|
||||
Assignment categories = DatabaseQueries::getCategories<Categ>(database, root->accountId());
|
||||
Assignment feeds = DatabaseQueries::getFeeds<Fee>(database, qApp->feedReader()->messageFilters(), root->accountId());
|
||||
auto labels = DatabaseQueries::getLabelsForAccount(database, root->accountId());
|
||||
|
@ -897,6 +897,8 @@ void FormMain::createConnections() {
|
||||
qApp->feedReader()->showMessageFiltersManager();
|
||||
tabWidget()->feedMessageViewer()->messagesView()->reloadSelections();
|
||||
});
|
||||
connect(m_ui->m_actionFeedMoveUp, &QAction::triggered,
|
||||
tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::moveSelectedItemUp);
|
||||
}
|
||||
|
||||
void FormMain::backupDatabaseSettings() {
|
||||
|
@ -288,6 +288,10 @@ void FeedsView::deleteSelectedItem() {
|
||||
qApp->feedUpdateLock()->unlock();
|
||||
}
|
||||
|
||||
void FeedsView::moveSelectedItemUp() {
|
||||
m_sourceModel->changeSortOrder(selectedItem(), false, false, selectedItem()->sortOrder() - 1);
|
||||
}
|
||||
|
||||
void FeedsView::markSelectedItemReadStatus(RootItem::ReadStatus read) {
|
||||
m_sourceModel->markItemRead(selectedItem(), read);
|
||||
}
|
||||
|
@ -66,6 +66,9 @@ class RSSGUARD_DLLSPEC FeedsView : public BaseTreeView {
|
||||
void editSelectedItem();
|
||||
void deleteSelectedItem();
|
||||
|
||||
// Sort order manipulations.
|
||||
void moveSelectedItemUp();
|
||||
|
||||
// Selects next/previous item (feed/category) in the list.
|
||||
void selectNextItem();
|
||||
void selectPreviousItem();
|
||||
|
@ -16,7 +16,7 @@
|
||||
RootItem::RootItem(RootItem* parent_item)
|
||||
: QObject(nullptr), m_kind(RootItem::Kind::Root), m_id(NO_PARENT_CATEGORY), m_customId(QL1S("")),
|
||||
m_title(QString()), m_description(QString()), m_creationDate(QDateTime::currentDateTimeUtc()),
|
||||
m_keepOnTop(false), m_sortOrder(0), m_childItems(QList<RootItem*>()), m_parentItem(parent_item) {}
|
||||
m_keepOnTop(false), m_sortOrder(NO_PARENT_CATEGORY), m_childItems(QList<RootItem*>()), m_parentItem(parent_item) {}
|
||||
|
||||
RootItem::RootItem(const RootItem& other) : RootItem(nullptr) {
|
||||
setTitle(other.title());
|
||||
|
Loading…
x
Reference in New Issue
Block a user