diff --git a/resources/misc/db_init_mysql.sql b/resources/misc/db_init_mysql.sql index 44521f763..262d65e89 100644 --- a/resources/misc/db_init_mysql.sql +++ b/resources/misc/db_init_mysql.sql @@ -74,6 +74,8 @@ CREATE TABLE IF NOT EXISTS Messages ( contents TEXT, is_pdeleted INTEGER(1) NOT NULL DEFAULT 0 CHECK (is_pdeleted >= 0 AND is_pdeleted <= 1), enclosures TEXT, + account_id INTEGER NOT NULL, - FOREIGN KEY (feed) REFERENCES Feeds (id) + FOREIGN KEY (feed) REFERENCES Feeds (id), + FOREIGN KEY (account_id) REFERENCES Accounts (id) ); \ No newline at end of file diff --git a/resources/misc/db_init_sqlite.sql b/resources/misc/db_init_sqlite.sql index 88bcd1c0f..c5d9f3fe8 100644 --- a/resources/misc/db_init_sqlite.sql +++ b/resources/misc/db_init_sqlite.sql @@ -69,6 +69,8 @@ CREATE TABLE IF NOT EXISTS Messages ( contents TEXT, is_pdeleted INTEGER(1) NOT NULL DEFAULT 0 CHECK (is_pdeleted >= 0 AND is_pdeleted <= 1), enclosures TEXT, + account_id INTEGER NOT NULL, - FOREIGN KEY (feed) REFERENCES Feeds (id) + FOREIGN KEY (feed) REFERENCES Feeds (id), + FOREIGN KEY (account_id) REFERENCES Accounts (id) ); \ No newline at end of file diff --git a/resources/misc/db_update_mysql_3_4.sql b/resources/misc/db_update_mysql_3_4.sql index 7324a89d0..cb66ceb81 100644 --- a/resources/misc/db_update_mysql_3_4.sql +++ b/resources/misc/db_update_mysql_3_4.sql @@ -16,4 +16,8 @@ CREATE TABLE IF NOT EXISTS TtRssAccounts ( FOREIGN KEY (id) REFERENCES Accounts (id) ); -- ! +ALTER TABLE Messages +ADD COLUMN account_id INTEGER NOT NULL DEFAULT (1); +-- ! + UPDATE Information SET inf_value = '4' WHERE inf_key = 'schema_version'; \ No newline at end of file diff --git a/resources/misc/db_update_sqlite_3_4.sql b/resources/misc/db_update_sqlite_3_4.sql index 7324a89d0..41f2135e7 100644 --- a/resources/misc/db_update_sqlite_3_4.sql +++ b/resources/misc/db_update_sqlite_3_4.sql @@ -16,4 +16,7 @@ CREATE TABLE IF NOT EXISTS TtRssAccounts ( FOREIGN KEY (id) REFERENCES Accounts (id) ); -- ! +ALTER TABLE Messages +ADD COLUMN account_id INTEGER NOT NULL DEFAULT (1); +-- ! UPDATE Information SET inf_value = '4' WHERE inf_key = 'schema_version'; \ No newline at end of file diff --git a/src/core/messagesmodel.cpp b/src/core/messagesmodel.cpp index 0046c73e4..9716ec781 100755 --- a/src/core/messagesmodel.cpp +++ b/src/core/messagesmodel.cpp @@ -71,8 +71,6 @@ void MessagesModel::setupFonts() { m_boldFont.setBold(true); } - - void MessagesModel::loadMessages(RootItem *item) { m_selectedItem = item; @@ -159,7 +157,8 @@ void MessagesModel::setupHeaderData() { /*: Tooltip for creation date of message.*/ tr("Created on") << /*: Tooltip for contents of message.*/ tr("Contents") << /*: Tooltip for "pdeleted" column in msg list.*/ tr("Permanently deleted") << - /*: Tooltip for attachments of message.*/ tr("Attachments"); + /*: Tooltip for attachments of message.*/ tr("Attachments") << + /*: Tooltip for account ID of message.*/ tr("Account ID"); m_tooltipData << tr("Id of the message.") << tr("Is message read?") << tr("Is message deleted?") << tr("Is message important?") << @@ -167,7 +166,7 @@ void MessagesModel::setupHeaderData() { tr("Title of the message.") << tr("Url of the message.") << tr("Author of the message.") << tr("Creation date of the message.") << tr("Contents of the message.") << tr("Is message permanently deleted from recycle bin?") << - tr("List of attachments."); + tr("List of attachments.") << tr("Account ID of message."); } Qt::ItemFlags MessagesModel::flags(const QModelIndex &index) const { diff --git a/src/definitions/definitions.h.in b/src/definitions/definitions.h.in index f084a00d9..f096b4033 100755 --- a/src/definitions/definitions.h.in +++ b/src/definitions/definitions.h.in @@ -183,6 +183,7 @@ #define MSG_DB_CONTENTS_INDEX 9 #define MSG_DB_PDELETED_INDEX 10 #define MSG_DB_ENCLOSURES_INDEX 11 +#define MSG_DB_ACCOUNT_ID_INDEX 12 // Indexes of columns as they are DEFINED IN THE TABLE for CATEGORIES. #define CAT_DB_ID_INDEX 0 diff --git a/src/gui/messagesview.cpp b/src/gui/messagesview.cpp index 17aad6651..ab62393c6 100755 --- a/src/gui/messagesview.cpp +++ b/src/gui/messagesview.cpp @@ -547,6 +547,7 @@ void MessagesView::adjustColumns() { hideColumn(MSG_DB_CONTENTS_INDEX); hideColumn(MSG_DB_PDELETED_INDEX); hideColumn(MSG_DB_ENCLOSURES_INDEX); + hideColumn(MSG_DB_ACCOUNT_ID_INDEX); qDebug("Adjusting column resize modes for MessagesView."); } diff --git a/src/miscellaneous/databasefactory.cpp b/src/miscellaneous/databasefactory.cpp index 0fa294735..1656d382c 100755 --- a/src/miscellaneous/databasefactory.cpp +++ b/src/miscellaneous/databasefactory.cpp @@ -205,7 +205,7 @@ QSqlDatabase DatabaseFactory::sqliteInitializeInMemoryDatabase() { // Copy all stuff. // WARNING: All tables belong here. QStringList tables; tables << QSL("Information") << QSL("Categories") << QSL("Feeds") << - QSL("FeedsData") << QSL("Messages") << QSL("Accounts") << QSL("TtRssAccounts"); + QSL("Accounts") << QSL("TtRssAccounts") << QSL("Messages"); foreach (const QString &table, tables) { copy_contents.exec(QString("INSERT INTO main.%1 SELECT * FROM storage.%1;").arg(table)); @@ -471,8 +471,8 @@ void DatabaseFactory::sqliteSaveMemoryDatabase() { // Copy all stuff. // WARNING: All tables belong here. - QStringList tables; tables << QSL("Categories") << QSL("Feeds") << QSL("FeedsData") << - QSL("Messages") << QSL("Accounts") << QSL("TtRssAccounts"); + QStringList tables; tables << QSL("Information") << QSL("Categories") << QSL("Feeds") << + QSL("Accounts") << QSL("TtRssAccounts") << QSL("Messages"); foreach (const QString &table, tables) { copy_contents.exec(QString(QSL("DELETE FROM storage.%1;")).arg(table)); diff --git a/src/services/standard/standardfeed.cpp b/src/services/standard/standardfeed.cpp index 91125f8c3..cfaae4e08 100755 --- a/src/services/standard/standardfeed.cpp +++ b/src/services/standard/standardfeed.cpp @@ -140,9 +140,12 @@ QList StandardFeed::undeletedMessages() const { query_read_msg.setForwardOnly(true); query_read_msg.prepare("SELECT title, url, author, date_created, contents " "FROM Messages " - "WHERE is_deleted = 0 AND feed = :feed;"); + "WHERE is_deleted = 0 AND feed = :feed AND account_id = :account_id;"); query_read_msg.bindValue(QSL(":feed"), id()); + query_read_msg.bindValue(QSL(":account_id"), const_cast(this)->serviceRoot()->accountId()); + + // FIXME: Fix those const functions, this is fucking ugly. if (query_read_msg.exec()) { while (query_read_msg.next()) { @@ -186,13 +189,15 @@ void StandardFeed::updateCounts(bool including_total_count) { query_all.setForwardOnly(true); if (including_total_count) { - if (query_all.exec(QString("SELECT count(*) FROM Messages WHERE feed = %1 AND is_deleted = 0;").arg(id())) && query_all.next()) { + if (query_all.exec(QString("SELECT count(*) FROM Messages WHERE feed = %1 AND is_deleted = 0 AND account_id = %2;").arg(QString::number(id()), + QString::number(const_cast(this)->serviceRoot()->accountId()))) && query_all.next()) { m_totalCount = query_all.value(0).toInt(); } } // Obtain count of unread messages. - if (query_all.exec(QString("SELECT count(*) FROM Messages WHERE feed = %1 AND is_deleted = 0 AND is_read = 0;").arg(id())) && query_all.next()) { + if (query_all.exec(QString("SELECT count(*) FROM Messages WHERE feed = %1 AND is_deleted = 0 AND is_read = 0 AND account_id = %2;").arg(QString::number(id()), + QString::number(const_cast(this)->serviceRoot()->accountId()))) && query_all.next()) { int new_unread_count = query_all.value(0).toInt(); if (status() == NewMessages && new_unread_count < m_unreadCount) { @@ -514,8 +519,9 @@ bool StandardFeed::removeItself() { query_remove.setForwardOnly(true); // Remove all messages from this standard feed. - query_remove.prepare(QSL("DELETE FROM Messages WHERE feed = :feed;")); + query_remove.prepare(QSL("DELETE FROM Messages WHERE feed = :feed AND account_id = :account_id;")); query_remove.bindValue(QSL(":feed"), id()); + query_remove.bindValue(QSL(":account_id"), const_cast(this)->serviceRoot()->accountId()); if (!query_remove.exec()) { return false; @@ -638,6 +644,7 @@ int StandardFeed::updateMessages(const QList &messages) { int updated_messages = 0; QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); bool remove_duplicates = qApp->settings()->value(GROUP(Messages), SETTING(Messages::RemoveDuplicates)).toBool(); + int account_id = serviceRoot()->accountId(); // Prepare queries. QSqlQuery query_select(database); @@ -648,13 +655,13 @@ int StandardFeed::updateMessages(const QList &messages) { // WARNING: One feed CANNOT contain two (or more) messages with same AUTHOR AND TITLE AND URL AND DATE_CREATED. query_select.setForwardOnly(true); query_select.prepare("SELECT id, feed, date_created FROM Messages " - "WHERE feed = :feed AND title = :title AND url = :url AND author = :author;"); + "WHERE feed = :feed AND title = :title AND url = :url AND author = :author AND account_id = :account_id;"); // Used to insert new messages. query_insert.setForwardOnly(true); query_insert.prepare("INSERT INTO Messages " - "(feed, title, url, author, date_created, contents, enclosures) " - "VALUES (:feed, :title, :url, :author, :date_created, :contents, :enclosures);"); + "(feed, title, url, author, date_created, contents, enclosures, account_id) " + "VALUES (:feed, :title, :url, :author, :date_created, :contents, :enclosures, :account_id);"); if (remove_duplicates) { query_update.setForwardOnly(true); @@ -685,6 +692,7 @@ int StandardFeed::updateMessages(const QList &messages) { query_select.bindValue(QSL(":title"), message.m_title); query_select.bindValue(QSL(":url"), message.m_url); query_select.bindValue(QSL(":author"), message.m_author); + query_select.bindValue(QSL(":account_id"), account_id); query_select.exec(); QList datetime_stamps; @@ -706,6 +714,7 @@ int StandardFeed::updateMessages(const QList &messages) { query_insert.bindValue(QSL(":date_created"), message.m_created.toMSecsSinceEpoch()); query_insert.bindValue(QSL(":contents"), message.m_contents); query_insert.bindValue(QSL(":enclosures"), Enclosures::encodeEnclosuresToString(message.m_enclosures)); + query_insert.bindValue(QSL(":account_id"), account_id); if (query_insert.exec() && query_insert.numRowsAffected() == 1) { setStatus(NewMessages); @@ -790,5 +799,4 @@ StandardFeed::StandardFeed(const QSqlRecord &record) : Feed(NULL) { setAutoUpdateType(static_cast(record.value(FDS_DB_UPDATE_TYPE_INDEX).toInt())); setAutoUpdateInitialInterval(record.value(FDS_DB_UPDATE_INTERVAL_INDEX).toInt()); - updateCounts(true); } diff --git a/src/services/standard/standardrecyclebin.cpp b/src/services/standard/standardrecyclebin.cpp index 6086a80b7..bd0df5175 100755 --- a/src/services/standard/standardrecyclebin.cpp +++ b/src/services/standard/standardrecyclebin.cpp @@ -27,7 +27,6 @@ StandardRecycleBin::StandardRecycleBin(RootItem *parent) : RecycleBin(parent) { setId(ID_RECYCLE_BIN); - updateCounts(true); } StandardRecycleBin::~StandardRecycleBin() { @@ -63,7 +62,7 @@ void StandardRecycleBin::updateCounts(bool update_total_count) { QSqlQuery query_all(database); query_all.setForwardOnly(true); - if (query_all.exec(QSL("SELECT count(*) FROM Messages WHERE is_read = 0 AND is_deleted = 1 AND is_pdeleted = 0;")) && query_all.next()) { + if (query_all.exec(QString("SELECT count(*) FROM Messages WHERE is_read = 0 AND is_deleted = 1 AND is_pdeleted = 0 AND account_id = %1;").arg(serviceRoot()->accountId())) && query_all.next()) { m_unreadCount = query_all.value(0).toInt(); } else { @@ -71,7 +70,7 @@ void StandardRecycleBin::updateCounts(bool update_total_count) { } if (update_total_count) { - if (query_all.exec(QSL("SELECT count(*) FROM Messages WHERE is_deleted = 1 AND is_pdeleted = 0;")) && query_all.next()) { + if (query_all.exec(QString("SELECT count(*) FROM Messages WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = %1;").arg(serviceRoot()->accountId())) && query_all.next()) { m_totalCount = query_all.value(0).toInt(); } else { diff --git a/src/services/standard/standardserviceentrypoint.cpp b/src/services/standard/standardserviceentrypoint.cpp index 730255b73..ca3615619 100755 --- a/src/services/standard/standardserviceentrypoint.cpp +++ b/src/services/standard/standardserviceentrypoint.cpp @@ -73,8 +73,9 @@ ServiceRoot *StandardServiceEntryPoint::createNewRoot() { if (query.exec(QString("INSERT INTO Accounts (id, type) VALUES (%1, '%2');").arg(QString::number(id_to_assing), SERVICE_CODE_STD_RSS))) { - StandardServiceRoot *root = new StandardServiceRoot(true); + StandardServiceRoot *root = new StandardServiceRoot(); root->setAccountId(id_to_assing); + root->loadFromDatabase(); return root; } else { @@ -90,8 +91,9 @@ QList StandardServiceEntryPoint::initializeSubtree() { if (query.exec(QString("SELECT id FROM Accounts WHERE type = '%1';").arg(SERVICE_CODE_STD_RSS))) { while (query.next()) { - StandardServiceRoot *root = new StandardServiceRoot(true); + StandardServiceRoot *root = new StandardServiceRoot(); root->setAccountId(query.value(0).toInt()); + root->loadFromDatabase(); roots.append(root); } } diff --git a/src/services/standard/standardserviceroot.cpp b/src/services/standard/standardserviceroot.cpp index 7752375da..d02680f62 100755 --- a/src/services/standard/standardserviceroot.cpp +++ b/src/services/standard/standardserviceroot.cpp @@ -43,7 +43,7 @@ #include -StandardServiceRoot::StandardServiceRoot(bool load_from_db, RootItem *parent) +StandardServiceRoot::StandardServiceRoot(RootItem *parent) : ServiceRoot(parent), m_recycleBin(new StandardRecycleBin(this)), m_actionExportFeeds(NULL), m_actionImportFeeds(NULL), m_serviceMenu(QList()), m_addItemMenu(QList()), m_feedContextMenu(QList()), m_actionFeedFetchMetadata(NULL) { @@ -52,10 +52,6 @@ StandardServiceRoot::StandardServiceRoot(bool load_from_db, RootItem *parent) setIcon(StandardServiceEntryPoint().icon()); setDescription(tr("This is obligatory service account for standard RSS/RDF/ATOM feeds.")); setCreationDate(QDateTime::currentDateTime()); - - if (load_from_db) { - loadFromDatabase(); - } } StandardServiceRoot::~StandardServiceRoot() { @@ -116,10 +112,12 @@ bool StandardServiceRoot::deleteViaGui() { QSqlDatabase connection = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); // Remove all messages. - if (!QSqlQuery(connection).exec(QSL("DELETE FROM Messages;"))) { + if (!QSqlQuery(connection).exec(QString("DELETE FROM Messages WHERE account_id = %1;").arg(accountId()))) { return false; } + // TODO: todo + // Remove all feeds. if (!QSqlQuery(connection).exec(QSL("DELETE FROM Feeds;"))) { return false; @@ -131,7 +129,7 @@ bool StandardServiceRoot::deleteViaGui() { } // Switch "existence" flag. - bool data_removed = QSqlQuery(connection).exec(QString("DELETE FROM Accounts WHERE id = %1;").arg(QString::number(id()))); + bool data_removed = QSqlQuery(connection).exec(QString("DELETE FROM Accounts WHERE id = %1;").arg(accountId())); if (data_removed) { requestItemRemoval(this); @@ -223,7 +221,7 @@ bool StandardServiceRoot::markRecycleBinReadUnread(RootItem::ReadStatus read) { QSqlQuery query_read_msg(db_handle); query_read_msg.setForwardOnly(true); - if (!query_read_msg.prepare("UPDATE Messages SET is_read = :read WHERE is_deleted = 1;")) { + if (!query_read_msg.prepare("UPDATE Messages SET is_read = :read WHERE is_deleted = 1 AND account_id = :account_id;")) { qWarning("Query preparation failed for recycle bin read change."); db_handle.rollback(); @@ -231,6 +229,7 @@ bool StandardServiceRoot::markRecycleBinReadUnread(RootItem::ReadStatus read) { } query_read_msg.bindValue(QSL(":read"), read == RootItem::Read ? 1 : 0); + query_read_msg.bindValue(QSL(":account_id"), accountId()); if (!query_read_msg.exec()) { qDebug("Query execution for recycle bin read change failed."); @@ -305,7 +304,7 @@ bool StandardServiceRoot::restoreBin() { QSqlQuery query_empty_bin(db_handle); query_empty_bin.setForwardOnly(true); - if (!query_empty_bin.exec(QSL("UPDATE Messages SET is_deleted = 0 WHERE is_deleted = 1 AND is_pdeleted = 0;"))) { + if (!query_empty_bin.exec(QString("UPDATE Messages SET is_deleted = 0 WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = %1;").arg(accountId()))) { qWarning("Query execution failed for recycle bin restoring."); db_handle.rollback(); @@ -336,7 +335,7 @@ bool StandardServiceRoot::emptyBin() { QSqlQuery query_empty_bin(db_handle); query_empty_bin.setForwardOnly(true); - if (!query_empty_bin.exec(QSL("UPDATE Messages SET is_pdeleted = 1 WHERE is_deleted = 1;"))) { + if (!query_empty_bin.exec(QString("UPDATE Messages SET is_pdeleted = 1 WHERE is_deleted = 1 AND account_id = %1;").arg(accountId()))) { qWarning("Query execution failed for recycle bin emptying."); db_handle.rollback(); @@ -415,6 +414,7 @@ void StandardServiceRoot::loadFromDatabase(){ // As the last item, add recycle bin, which is needed. appendChild(m_recycleBin); + m_recycleBin->updateCounts(true); } QHash StandardServiceRoot::categoriesForItem(RootItem *root) { @@ -468,10 +468,12 @@ void StandardServiceRoot::assembleFeeds(FeedAssignment feeds) { if (feed.first == NO_PARENT_CATEGORY) { // This is top-level feed, add it to the root item. appendChild(feed.second); + feed.second->updateCounts(true); } else if (categories.contains(feed.first)) { // This feed belongs to this category. categories.value(feed.first)->appendChild(feed.second); + feed.second->updateCounts(true); } else { qWarning("Feed '%s' is loose, skipping it.", qPrintable(feed.second->title())); diff --git a/src/services/standard/standardserviceroot.h b/src/services/standard/standardserviceroot.h index 0d0903118..c03461dfc 100755 --- a/src/services/standard/standardserviceroot.h +++ b/src/services/standard/standardserviceroot.h @@ -40,7 +40,7 @@ class StandardServiceRoot : public ServiceRoot { Q_OBJECT public: - explicit StandardServiceRoot(bool load_from_db, RootItem *parent = NULL); + explicit StandardServiceRoot(RootItem *parent = NULL); virtual ~StandardServiceRoot(); // Start/stop root. @@ -104,6 +104,8 @@ class StandardServiceRoot : public ServiceRoot { bool restoreBin(); bool emptyBin(); + void loadFromDatabase(); + public slots: void addNewCategory(); void addNewFeed(); @@ -115,8 +117,6 @@ class StandardServiceRoot : public ServiceRoot { // which are suitable as IN clause for SQL queries. QStringList textualFeedIds(const QList &feeds); - void loadFromDatabase(); - // Takes lists of feeds/categories and assembles // them into the tree structure. void assembleCategories(CategoryAssignment categories);