diff --git a/resources/text/CHANGELOG b/resources/text/CHANGELOG index 2905053eb..9a9cac1ed 100755 --- a/resources/text/CHANGELOG +++ b/resources/text/CHANGELOG @@ -10,6 +10,7 @@ http://goo.gl/forms/GcvPYgS2a8 Added: ▪ User is now able to delete TT-RSS feeds. (issue #151) +▪ Added ability to stop running batch feed update. (issue #157) Fixed: diff --git a/src/core/feeddownloader.cpp b/src/core/feeddownloader.cpp index 673d290b4..05d949d74 100755 --- a/src/core/feeddownloader.cpp +++ b/src/core/feeddownloader.cpp @@ -25,7 +25,7 @@ #include -FeedDownloader::FeedDownloader(QObject *parent) : QObject(parent) { +FeedDownloader::FeedDownloader(QObject *parent) : QObject(parent), m_stopUpdate(false), m_isUpdateRunning(false) { qRegisterMetaType("FeedDownloadResults"); } @@ -33,15 +33,29 @@ FeedDownloader::~FeedDownloader() { qDebug("Destroying FeedDownloader instance."); } +bool FeedDownloader::isUpdateRunning() const { + return m_isUpdateRunning; +} + void FeedDownloader::updateFeeds(const QList &feeds) { qDebug().nospace() << "Performing feed updates in thread: \'" << QThread::currentThreadId() << "\'."; + // It may be good to disable "stop" action when batch feed update + // starts. + m_isUpdateRunning = true; + m_stopUpdate = false; + // Job starts now. emit started(); FeedDownloadResults results; for (int i = 0, total = feeds.size(); i < total; i++) { + if (m_stopUpdate) { + qDebug("Stopping batch feed update now."); + break; + } + int updated_messages = feeds.at(i)->update(); if (updated_messages > 0) { @@ -56,6 +70,10 @@ void FeedDownloader::updateFeeds(const QList &feeds) { results.sort(); + // Make sure that there is not "stop" action pending. + m_isUpdateRunning = false; + m_stopUpdate = false; + // Update of feeds has finished. // NOTE: This means that now "update lock" can be unlocked // and feeds can be added/edited/deleted and application @@ -63,6 +81,10 @@ void FeedDownloader::updateFeeds(const QList &feeds) { emit finished(results); } +void FeedDownloader::stopRunningUpdate() { + m_stopUpdate = true; +} + FeedDownloadResults::FeedDownloadResults() : m_updatedFeeds(QList >()) { } diff --git a/src/core/feeddownloader.h b/src/core/feeddownloader.h index 2c673d3a1..892f61127 100755 --- a/src/core/feeddownloader.h +++ b/src/core/feeddownloader.h @@ -53,6 +53,8 @@ class FeedDownloader : public QObject { explicit FeedDownloader(QObject *parent = 0); virtual ~FeedDownloader(); + bool isUpdateRunning() const; + public slots: // Performs update of all feeds from the "feeds" parameter. // New messages are downloaded for each feed and they @@ -60,6 +62,9 @@ class FeedDownloader : public QObject { // Appropriate signals are emitted. void updateFeeds(const QList &feeds); + // Stops running update. + void stopRunningUpdate(); + signals: // Emitted if feed updates started. void started(); @@ -73,6 +78,10 @@ class FeedDownloader : public QObject { // and "total" number indicates total number of feeds // which were in the initial queue. void progress(const Feed *feed, int current, int total); + + private: + bool m_isUpdateRunning; + bool m_stopUpdate; }; #endif // FEEDDOWNLOADER_H diff --git a/src/core/feedsmodel.cpp b/src/core/feedsmodel.cpp index a6fd4a42a..acfd1838d 100755 --- a/src/core/feedsmodel.cpp +++ b/src/core/feedsmodel.cpp @@ -157,6 +157,8 @@ void FeedsModel::updateFeeds(const QList &feeds) { void FeedsModel::onFeedUpdatesStarted() { //: Text display in status bar when feed update is started. qApp->mainForm()->statusBar()->showProgressFeeds(0, tr("Feed update started")); + + emit feedsUpdateStarted(); } void FeedsModel::onFeedUpdatesProgress(const Feed *feed, int current, int total) { @@ -610,6 +612,10 @@ bool FeedsModel::hasAnyFeedNewMessages() const { return false; } +bool FeedsModel::isFeedUpdateRunning() const { + return m_feedDownloader != NULL && m_feedDownloader->isUpdateRunning(); +} + void FeedsModel::reloadChangedLayout(QModelIndexList list) { while (!list.isEmpty()) { QModelIndex indx = list.takeFirst(); @@ -721,6 +727,12 @@ void FeedsModel::loadActivatedServiceAccounts() { } } +void FeedsModel::stopRunningFeedUpdate() { + if (m_feedDownloader != NULL) { + m_feedDownloader->stopRunningUpdate(); + } +} + QList FeedsModel::feedsForIndex(const QModelIndex &index) const { return itemForIndex(index)->getSubTreeFeeds(); } diff --git a/src/core/feedsmodel.h b/src/core/feedsmodel.h index 26e317e5c..4d5f014fa 100755 --- a/src/core/feedsmodel.h +++ b/src/core/feedsmodel.h @@ -125,6 +125,8 @@ class FeedsModel : public QAbstractItemModel { return m_rootItem; } + bool isFeedUpdateRunning() const; + // Resets global auto-update intervals according to settings // and starts/stop the timer as needed. void updateAutoUpdateStatus(); @@ -142,6 +144,8 @@ class FeedsModel : public QAbstractItemModel { void loadActivatedServiceAccounts(); public slots: + void stopRunningFeedUpdate(); + // Schedules all feeds from all accounts for update. void updateAllFeeds(); @@ -191,6 +195,8 @@ class FeedsModel : public QAbstractItemModel { // Update of feeds is finished. void feedsUpdateFinished(); + void feedsUpdateStarted(); + // Emitted when model requests update of some feeds. void feedsUpdateRequested(QList feeds); diff --git a/src/gui/dialogs/formmain.cpp b/src/gui/dialogs/formmain.cpp index 6545b3294..a44e3f98f 100755 --- a/src/gui/dialogs/formmain.cpp +++ b/src/gui/dialogs/formmain.cpp @@ -130,6 +130,7 @@ QList FormMain::allActions() const { actions << m_ui->m_actionDeleteSelectedMessages; actions << m_ui->m_actionUpdateAllItems; actions << m_ui->m_actionUpdateSelectedItems; + actions << m_ui->m_actionStopRunningItemsUpdate; actions << m_ui->m_actionEditSelectedItem; actions << m_ui->m_actionDeleteSelectedItem; actions << m_ui->m_actionServiceAdd; @@ -372,6 +373,7 @@ void FormMain::setupIcons() { // Feeds/messages. m_ui->m_menuAddItem->setIcon(icon_theme_factory->fromTheme(QSL("item-new"))); + m_ui->m_actionStopRunningItemsUpdate->setIcon(icon_theme_factory->fromTheme(QSL("go-stop"))); m_ui->m_actionUpdateAllItems->setIcon(icon_theme_factory->fromTheme(QSL("item-update-all"))); m_ui->m_actionUpdateSelectedItems->setIcon(icon_theme_factory->fromTheme(QSL("item-update-selected"))); m_ui->m_actionClearSelectedItems->setIcon(icon_theme_factory->fromTheme(QSL("mail-remove"))); diff --git a/src/gui/dialogs/formmain.ui b/src/gui/dialogs/formmain.ui index 982560d6e..9db204175 100755 --- a/src/gui/dialogs/formmain.ui +++ b/src/gui/dialogs/formmain.ui @@ -135,6 +135,7 @@ + @@ -797,6 +798,14 @@ + + + Stop running update + + + + + diff --git a/src/gui/feedmessageviewer.cpp b/src/gui/feedmessageviewer.cpp index bf7942c97..08b3cad85 100755 --- a/src/gui/feedmessageviewer.cpp +++ b/src/gui/feedmessageviewer.cpp @@ -191,6 +191,7 @@ void FeedMessageViewer::updateMessageButtonsAvailability() { } void FeedMessageViewer::updateFeedButtonsAvailability() { + const bool is_update_running = feedsView()->sourceModel()->isFeedUpdateRunning(); const bool critical_action_running = qApp->feedUpdateLock()->isLocked(); const RootItem *selected_item = feedsView()->selectedItem(); const bool anything_selected = selected_item != NULL; @@ -199,6 +200,7 @@ void FeedMessageViewer::updateFeedButtonsAvailability() { const bool service_selected = anything_selected && selected_item->kind() == RootItemKind::ServiceRoot; const FormMain *form_main = qApp->mainForm(); + form_main->m_ui->m_actionStopRunningItemsUpdate->setEnabled(is_update_running); form_main->m_ui->m_actionBackupDatabaseSettings->setEnabled(!critical_action_running); form_main->m_ui->m_actionCleanupDatabase->setEnabled(!critical_action_running); form_main->m_ui->m_actionClearSelectedItems->setEnabled(anything_selected); @@ -245,6 +247,7 @@ void FeedMessageViewer::createConnections() { // to reload selections. connect(m_feedsView->sourceModel(), SIGNAL(reloadMessageListRequested(bool)), m_messagesView, SLOT(reloadSelections(bool))); connect(m_feedsView->sourceModel(), SIGNAL(feedsUpdateFinished()), this, SLOT(onFeedsUpdateFinished())); + connect(m_feedsView->sourceModel(), SIGNAL(feedsUpdateStarted()), this, SLOT(onFeedsUpdateStarted())); // Message openers. connect(m_messagesView, SIGNAL(openLinkMiniBrowser(QString)), m_messagesBrowser, SLOT(navigateToUrl(QString))); @@ -294,6 +297,8 @@ void FeedMessageViewer::createConnections() { SIGNAL(triggered()), m_feedsView, SLOT(updateSelectedItems())); connect(form_main->m_ui->m_actionUpdateAllItems, SIGNAL(triggered()), m_feedsView, SLOT(updateAllItems())); + connect(form_main->m_ui->m_actionStopRunningItemsUpdate, + SIGNAL(triggered()), m_feedsView->sourceModel(), SLOT(stopRunningFeedUpdate())); connect(form_main->m_ui->m_actionEditSelectedItem, SIGNAL(triggered()), m_feedsView, SLOT(editSelectedItem())); connect(form_main->m_ui->m_actionViewSelectedItemsNewspaperMode, @@ -434,3 +439,10 @@ void FeedMessageViewer::refreshVisualProperties() { void FeedMessageViewer::onFeedsUpdateFinished() { m_messagesView->reloadSelections(true); } + +void FeedMessageViewer::onFeedsUpdateStarted() { + // Check only "Stop running update" button. + const bool is_update_running = feedsView()->sourceModel()->isFeedUpdateRunning(); + + qApp->mainForm()->m_ui->m_actionStopRunningItemsUpdate->setEnabled(is_update_running); +} diff --git a/src/gui/feedmessageviewer.h b/src/gui/feedmessageviewer.h index f6a4034fb..c5442347e 100755 --- a/src/gui/feedmessageviewer.h +++ b/src/gui/feedmessageviewer.h @@ -97,6 +97,8 @@ class FeedMessageViewer : public TabContent { // Called when feed update finishes. void onFeedsUpdateFinished(); + void onFeedsUpdateStarted(); + // Switches visibility of feed list and related // toolbar. void switchFeedComponentVisibility(); diff --git a/src/miscellaneous/settings.cpp b/src/miscellaneous/settings.cpp index 1494b49db..10424ccba 100755 --- a/src/miscellaneous/settings.cpp +++ b/src/miscellaneous/settings.cpp @@ -85,7 +85,7 @@ DKEY GUI::ToolbarStyle = "toolbar_style"; DVALUE(Qt::ToolButtonStyle) GUI::ToolbarStyleDef = Qt::ToolButtonIconOnly; DKEY GUI::FeedsToolbarActions = "feeds_toolbar"; -DVALUE(char*) GUI::FeedsToolbarActionsDef = "m_actionUpdateAllItems,m_actionMarkAllItemsRead"; +DVALUE(char*) GUI::FeedsToolbarActionsDef = "m_actionUpdateAllItems,m_actionStopRunningItemsUpdate,m_actionMarkAllItemsRead"; DKEY GUI::MainWindowInitialSize = "window_size"; DKEY GUI::MainWindowInitialPosition = "window_position";