diff --git a/src/core/feedsmodel.cpp b/src/core/feedsmodel.cpp index de6b68a1c..75947b081 100644 --- a/src/core/feedsmodel.cpp +++ b/src/core/feedsmodel.cpp @@ -196,6 +196,17 @@ void FeedsModel::reloadChangedLayout(QModelIndexList list) { } } +QStringList FeedsModel::textualFeedIds(const QList &feeds) { + QStringList stringy_ids; + stringy_ids.reserve(feeds.size()); + + foreach (FeedsModelFeed *feed, feeds) { + stringy_ids.append(QString::number(feed->id())); + } + + return stringy_ids; +} + void FeedsModel::reloadWholeLayout() { // NOTE: Take a look at docs about this. // I have tested that this is LITTLE slower than code above, @@ -291,6 +302,75 @@ bool FeedsModel::isEqual(FeedsModelFeed *lhs, FeedsModelFeed *rhs) { return lhs->id() == rhs->id(); } +bool FeedsModel::markFeedsRead(const QList &feeds, + int read) { + QSqlDatabase db_handle = DatabaseFactory::getInstance()->addConnection(objectName()); + + if (!db_handle.transaction()) { + qWarning("Starting transaction for feeds read change."); + return false; + } + + QSqlQuery query_read_msg(db_handle); + if (!query_read_msg.prepare(QString("UPDATE messages SET read = :read " + "WHERE feed IN (%1) AND deleted = 0").arg(textualFeedIds(feeds).join(", ")))) { + qWarning("Query preparation failed for feeds read change."); + + db_handle.rollback(); + return false; + } + + query_read_msg.bindValue(":read", read); + + if (!query_read_msg.exec()) { + qDebug("Query execution for feeds read change failed."); + db_handle.rollback(); + } + + // Commit changes. + if (db_handle.commit()) { + return true; + } + else { + return db_handle.rollback(); + } +} + +bool FeedsModel::markFeedsDeleted(const QList &feeds, + int deleted) { + QSqlDatabase db_handle = DatabaseFactory::getInstance()->addConnection(objectName()); + + if (!db_handle.transaction()) { + qWarning("Starting transaction for feeds clearing."); + return false; + } + + QSqlQuery query_delete_msg(db_handle); + if (!query_delete_msg.prepare(QString("UPDATE messages SET deleted = :deleted " + "WHERE feed IN (%1) AND deleted = 0").arg(textualFeedIds(feeds).join(", ")))) { + qWarning("Query preparation failed for feeds clearing."); + + db_handle.rollback(); + return false; + } + + query_delete_msg.bindValue(":deleted", deleted); + + if (!query_delete_msg.exec()) { + qDebug("Query execution for feeds clearing failed."); + db_handle.rollback(); + } + + // Commit changes. + if (db_handle.commit()) { + return true; + } + else { + return db_handle.rollback(); + } +} + + QList FeedsModel::feedsForIndexes(const QModelIndexList &indexes) { QList feeds; diff --git a/src/core/feedsmodel.h b/src/core/feedsmodel.h index ee33cd6eb..f5a144174 100644 --- a/src/core/feedsmodel.h +++ b/src/core/feedsmodel.h @@ -59,6 +59,9 @@ class FeedsModel : public QAbstractItemModel { static bool isEqual(FeedsModelFeed *lhs, FeedsModelFeed *rhs); public slots: + bool markFeedsRead(const QList &feeds, int read); + bool markFeedsDeleted(const QList &feeds, int deleted); + // Signals that properties (probably counts) // of ALL items have changed. void reloadWholeLayout(); @@ -68,6 +71,8 @@ class FeedsModel : public QAbstractItemModel { void reloadChangedLayout(QModelIndexList list); protected: + QStringList textualFeedIds(const QList &feeds); + // Returns feed/category which lies at the specified index or // null if index is invalid. FeedsModelRootItem *itemForIndex(const QModelIndex &index) const; diff --git a/src/gui/feedmessageviewer.cpp b/src/gui/feedmessageviewer.cpp index ed3b05fdc..47807c664 100644 --- a/src/gui/feedmessageviewer.cpp +++ b/src/gui/feedmessageviewer.cpp @@ -147,6 +147,8 @@ void FeedMessageViewer::createConnections() { m_messagesView, SLOT(loadFeeds(QList))); connect(m_messagesView, SIGNAL(feedCountsChanged()), m_feedsView, SLOT(updateCountsOfSelectedFeeds())); + connect(m_feedsView, SIGNAL(feedsNeedToBeReloaded(int)), + m_messagesView, SLOT(reloadSelections(int))); // Downloader connections. connect(m_feedDownloaderThread, SIGNAL(finished()), @@ -174,11 +176,11 @@ void FeedMessageViewer::createConnections() { connect(FormMain::getInstance()->m_ui->m_actionOpenSelectedMessagesInternally, SIGNAL(triggered()), m_messagesView, SLOT(openSelectedMessagesInternally())); connect(FormMain::getInstance()->m_ui->m_actionMarkFeedsAsRead, - SIGNAL(triggered()), m_messagesView, SLOT(setAllMessagesRead())); + SIGNAL(triggered()), m_feedsView, SLOT(markSelectedFeedsRead())); connect(FormMain::getInstance()->m_ui->m_actionMarkFeedsAsUnread, - SIGNAL(triggered()), m_messagesView, SLOT(setAllMessagesUnread())); + SIGNAL(triggered()), m_feedsView, SLOT(markSelectedFeedsUnread())); connect(FormMain::getInstance()->m_ui->m_actionClearFeeds, - SIGNAL(triggered()), m_messagesView, SLOT(setAllMessagesDeleted())); + SIGNAL(triggered()), m_feedsView, SLOT(clearSelectedFeeds())); connect(FormMain::getInstance()->m_ui->m_actionUpdateSelectedFeeds, SIGNAL(triggered()), this, SLOT(updateSelectedFeeds())); connect(FormMain::getInstance()->m_ui->m_actionUpdateAllFeeds, diff --git a/src/gui/feedsview.cpp b/src/gui/feedsview.cpp index d9c72c4fb..358359e50 100644 --- a/src/gui/feedsview.cpp +++ b/src/gui/feedsview.cpp @@ -38,6 +38,32 @@ QList FeedsView::allFeeds() const { return m_sourceModel->getAllFeeds(); } +void FeedsView::setSelectedFeedsClearStatus(int clear) { + m_sourceModel->markFeedsDeleted(selectedFeeds(), clear); + updateCountsOfSelectedFeeds(); + + emit feedsNeedToBeReloaded(1); +} + +void FeedsView::clearSelectedFeeds() { + setSelectedFeedsClearStatus(1); +} + +void FeedsView::markSelectedFeedsReadStatus(int read) { + m_sourceModel->markFeedsRead(selectedFeeds(), read); + updateCountsOfSelectedFeeds(false); + + emit feedsNeedToBeReloaded(read); +} + +void FeedsView::markSelectedFeedsRead() { + markSelectedFeedsReadStatus(1); +} + +void FeedsView::markSelectedFeedsUnread() { + markSelectedFeedsReadStatus(0); +} + void FeedsView::updateCountsOfSelectedFeeds(bool update_total_too) { foreach (FeedsModelFeed *feed, selectedFeeds()) { feed->updateCounts(update_total_too); diff --git a/src/gui/feedsview.h b/src/gui/feedsview.h index 0a3689e82..e757daf98 100644 --- a/src/gui/feedsview.h +++ b/src/gui/feedsview.h @@ -24,6 +24,15 @@ class FeedsView : public QTreeView { QList allFeeds() const; public slots: + // Feed read/unread manipulators. + void markSelectedFeedsReadStatus(int read); + void markSelectedFeedsRead(); + void markSelectedFeedsUnread(); + + // Feed clearers. + void setSelectedFeedsClearStatus(int clear); + void clearSelectedFeeds(); + // Reloads counts for selected feeds. void updateCountsOfSelectedFeeds(bool update_total_too = true); @@ -38,6 +47,7 @@ class FeedsView : public QTreeView { const QItemSelection &deselected); signals: + void feedsNeedToBeReloaded(int mark_current_index_read); void feedsSelected(const QList &feed_ids); private: diff --git a/src/gui/messagesview.cpp b/src/gui/messagesview.cpp index d4326af39..9cad9a416 100644 --- a/src/gui/messagesview.cpp +++ b/src/gui/messagesview.cpp @@ -46,6 +46,37 @@ void MessagesView::createConnections() { this, SLOT(adjustColumns())); } +void MessagesView::reloadSelections(int mark_current_index_read) { + QModelIndex current_index = selectionModel()->currentIndex(); + QModelIndex mapped_current_index = m_proxyModel->mapToSource(current_index); + QModelIndexList selected_indexes = selectionModel()->selectedRows(); + QModelIndexList mapped_indexes = m_proxyModel->mapListToSource(selected_indexes); + + // Reload the model now. + m_sourceModel->select(); + m_sourceModel->fetchAll(); + + sortByColumn(header()->sortIndicatorSection(), header()->sortIndicatorOrder()); + + selected_indexes = m_proxyModel->mapListFromSource(mapped_indexes, true); + current_index = m_proxyModel->mapFromSource(m_sourceModel->index(mapped_current_index.row(), + mapped_current_index.column())); + + if (mark_current_index_read == 0) { + // User selected to mark some messages as unread, if one + // of them will be marked as current, then it will be read again. + m_batchUnreadSwitch = true; + setCurrentIndex(current_index); + m_batchUnreadSwitch = false; + } + else { + setCurrentIndex(current_index); + } + + scrollTo(current_index); + reselectIndexes(selected_indexes); +} + MessagesModel *MessagesView::sourceModel() { return m_sourceModel; } diff --git a/src/gui/messagesview.h b/src/gui/messagesview.h index 46656c96e..7b4ee6560 100755 --- a/src/gui/messagesview.h +++ b/src/gui/messagesview.h @@ -25,6 +25,12 @@ class MessagesView : public QTreeView { void createConnections(); public slots: + // Called after data got changed externally + // and it needs to be reloaded to the view. + // If "mark_current_index_read" is 0, then message with + // "current" index is not marked as read. + void reloadSelections(int mark_current_index_read); + // Loads un-deleted messages from selected feeds. void loadFeeds(const QList &feed_ids);