Update feed logic moved to model, cleared.

This commit is contained in:
Martin Rotter 2015-11-23 14:23:51 +01:00
parent 46eba51247
commit ef20ea9774
7 changed files with 159 additions and 152 deletions

View file

@ -27,7 +27,11 @@
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/mutex.h"
#include "gui/messagebox.h"
#include "gui/statusbar.h"
#include "gui/dialogs/formmain.h"
#include "core/feeddownloader.h"
#include <QThread>
#include <QSqlError>
#include <QSqlQuery>
#include <QSqlRecord>
@ -40,7 +44,7 @@
FeedsModel::FeedsModel(QObject *parent)
: QAbstractItemModel(parent), m_autoUpdateTimer(new QTimer(this)) {
: QAbstractItemModel(parent), m_autoUpdateTimer(new QTimer(this)), m_feedDownloaderThread(NULL), m_feedDownloader(NULL) {
setObjectName(QSL("FeedsModel"));
// Create root item.
@ -64,6 +68,11 @@ FeedsModel::FeedsModel(QObject *parent)
loadActivatedServiceAccounts();
updateAutoUpdateStatus();
if (qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::FeedsUpdateOnStartup)).toBool()) {
qDebug("Requesting update for all feeds on application startup.");
QTimer::singleShot(STARTUP_UPDATE_DELAY, this, SLOT(updateAllItems()));
}
}
FeedsModel::~FeedsModel() {
@ -77,6 +86,85 @@ void FeedsModel::quit() {
if (m_autoUpdateTimer->isActive()) {
m_autoUpdateTimer->stop();
}
// Close worker threads.
if (m_feedDownloaderThread != NULL && m_feedDownloaderThread->isRunning()) {
qDebug("Quitting feed downloader thread.");
m_feedDownloaderThread->quit();
if (!m_feedDownloaderThread->wait(CLOSE_LOCK_TIMEOUT)) {
qCritical("Feed downloader thread is running despite it was told to quit. Terminating it.");
m_feedDownloaderThread->terminate();
}
}
// Close workers.
if (m_feedDownloader != NULL) {
qDebug("Feed downloader exists. Deleting it from memory.");
m_feedDownloader->deleteLater();
}
if (qApp->settings()->value(GROUP(Messages), SETTING(Messages::ClearReadOnExit)).toBool()) {
markItemCleared(m_rootItem, true);
}
}
void FeedsModel::updateFeeds(const QList<Feed *> &feeds) {
if (!qApp->feedUpdateLock()->tryLock()) {
qApp->showGuiMessage(tr("Cannot update all items"),
tr("You cannot update all items because another another critical operation is ongoing."),
QSystemTrayIcon::Warning, qApp->mainForm(), true);
return;
}
if (m_feedDownloader == NULL) {
m_feedDownloader = new FeedDownloader();
m_feedDownloaderThread = new QThread();
// Downloader setup.
qRegisterMetaType<QList<Feed*> >("QList<Feed*>");
m_feedDownloader->moveToThread(m_feedDownloaderThread);
connect(this, SIGNAL(feedsUpdateRequested(QList<Feed*>)), m_feedDownloader, SLOT(updateFeeds(QList<Feed*>)));
connect(m_feedDownloaderThread, SIGNAL(finished()), m_feedDownloaderThread, SLOT(deleteLater()));
connect(m_feedDownloader, SIGNAL(finished(FeedDownloadResults)), this, SLOT(onFeedUpdatesFinished(FeedDownloadResults)));
connect(m_feedDownloader, SIGNAL(started()), this, SLOT(onFeedUpdatesStarted()));
connect(m_feedDownloader, SIGNAL(progress(Feed*,int,int)), this, SLOT(onFeedUpdatesProgress(Feed*,int,int)));
// Connections are made, start the feed downloader thread.
m_feedDownloaderThread->start();
}
emit feedsUpdateRequested(feeds);
}
void FeedsModel::onFeedUpdatesStarted() {
//: Text display in status bar when feed update is started.
qApp->mainForm()->statusBar()->showProgressFeeds(0, tr("Feed update started"));
}
void FeedsModel::onFeedUpdatesProgress(Feed *feed, int current, int total) {
// Some feed got updated.
qApp->mainForm()->statusBar()->showProgressFeeds((current * 100.0) / total,
//: Text display in status bar when particular feed is updated.
tr("Updated feed '%1'").arg(feed->title()));
}
void FeedsModel::onFeedUpdatesFinished(FeedDownloadResults results) {
qApp->feedUpdateLock()->unlock();
qApp->mainForm()->statusBar()->clearProgressFeeds();
if (!results.m_updatedFeeds.isEmpty()) {
// Now, inform about results via GUI message/notification.
qApp->showGuiMessage(tr("New messages downloaded"), results.getOverview(10), QSystemTrayIcon::NoIcon,
0, false, qApp->icons()->fromTheme(QSL("item-update-all")));
}
emit feedsUpdateFinished();
}
void FeedsModel::updateAllFeeds() {
updateFeeds(m_rootItem->getSubTreeFeeds());
}
void FeedsModel::executeNextAutoUpdate() {

View file

@ -22,6 +22,7 @@
#include "core/message.h"
#include "core/rootitem.h"
#include "core/feeddownloader.h"
class Category;
@ -132,6 +133,13 @@ class FeedsModel : public QAbstractItemModel {
// Does necessary job before quitting this component.
void quit();
// Schedules given feeds for update.
void updateFeeds(const QList<Feed*> &feeds);
// Schedules all feeds from all accounts for update.
void updateAllFeeds();
// Adds given service root account.
bool addServiceAccount(ServiceRoot *root);
public slots:
@ -161,7 +169,14 @@ class FeedsModel : public QAbstractItemModel {
// Is executed when next auto-update round could be done.
void executeNextAutoUpdate();
// Reacts on feed updates.
void onFeedUpdatesStarted();
void onFeedUpdatesProgress(Feed *feed, int current, int total);
void onFeedUpdatesFinished(FeedDownloadResults results);
signals:
void feedsUpdateFinished();
void readFeedsFilterInvalidationRequested();
// Emitted when model requests update of some feeds.
@ -191,6 +206,9 @@ class FeedsModel : public QAbstractItemModel {
bool m_globalAutoUpdateEnabled;
int m_globalAutoUpdateInitialInterval;
int m_globalAutoUpdateRemainingInterval;
QThread *m_feedDownloaderThread;
FeedDownloader *m_feedDownloader;
};
#endif // FEEDSMODEL_H

View file

@ -68,7 +68,7 @@
#define INTERNAL_URL_BLANK "about:blank"
#define DEFAULT_AUTO_UPDATE_INTERVAL 15
#define AUTO_UPDATE_INTERVAL 60000
#define STARTUP_UPDATE_DELAY 15000
#define STARTUP_UPDATE_DELAY 30000
#define TIMEZONE_OFFSET_LIMIT 6
#define CHANGE_EVENT_DELAY 250
#define FLAG_ICON_SUBFOLDER "flags"

View file

@ -65,17 +65,12 @@ FeedMessageViewer::FeedMessageViewer(QWidget *parent)
m_messagesView(new MessagesView(this)),
m_feedsView(new FeedsView(this)),
m_messagesBrowser(new WebBrowser(this)),
m_feedDownloaderThread(NULL),
m_dbCleanerThread(NULL),
m_feedDownloader(NULL),
m_dbCleaner(NULL) {
initialize();
initializeViews();
loadMessageViewerFonts();
createConnections();
// Now, update all feeds if user has set it.
m_feedsView->updateAllItemsOnStartup();
}
FeedMessageViewer::~FeedMessageViewer() {
@ -154,17 +149,6 @@ void FeedMessageViewer::quit() {
// Quit the feeds model (stops auto-update timer etc.).
m_feedsView->sourceModel()->quit();
// Close worker threads.
if (m_feedDownloaderThread != NULL && m_feedDownloaderThread->isRunning()) {
qDebug("Quitting feed downloader thread.");
m_feedDownloaderThread->quit();
if (!m_feedDownloaderThread->wait(CLOSE_LOCK_TIMEOUT)) {
qCritical("Feed downloader thread is running despite it was told to quit. Terminating it.");
m_feedDownloaderThread->terminate();
}
}
if (m_dbCleanerThread != NULL && m_dbCleanerThread->isRunning()) {
qDebug("Quitting database cleaner thread.");
m_dbCleanerThread->quit();
@ -175,20 +159,10 @@ void FeedMessageViewer::quit() {
}
}
// Close workers.
if (m_feedDownloader != NULL) {
qDebug("Feed downloader exists. Deleting it from memory.");
m_feedDownloader->deleteLater();
}
if (m_dbCleaner != NULL) {
qDebug("Database cleaner exists. Deleting it from memory.");
m_dbCleaner->deleteLater();
}
if (qApp->settings()->value(GROUP(Messages), SETTING(Messages::ClearReadOnExit)).toBool()) {
m_feedsView->clearAllReadMessages();
}
}
bool FeedMessageViewer::areToolBarsEnabled() const {
@ -220,30 +194,6 @@ void FeedMessageViewer::setListHeadersEnabled(bool enable) {
m_messagesView->header()->setVisible(enable);
}
void FeedMessageViewer::onFeedUpdatesStarted() {
//: Text display in status bar when feed update is started.
qApp->mainForm()->statusBar()->showProgressFeeds(0, tr("Feed update started"));
}
void FeedMessageViewer::onFeedUpdatesProgress(Feed *feed, int current, int total) {
// Some feed got updated.
qApp->mainForm()->statusBar()->showProgressFeeds((current * 100.0) / total,
//: Text display in status bar when particular feed is updated.
tr("Updated feed '%1'").arg(feed->title()));
}
void FeedMessageViewer::onFeedUpdatesFinished(FeedDownloadResults results) {
qApp->feedUpdateLock()->unlock();
qApp->mainForm()->statusBar()->clearProgressFeeds();
m_messagesView->reloadSelections(true);
if (!results.m_updatedFeeds.isEmpty()) {
// Now, inform about results via GUI message/notification.
qApp->showGuiMessage(tr("New messages downloaded"), results.getOverview(10), QSystemTrayIcon::NoIcon,
0, false, qApp->icons()->fromTheme(QSL("item-update-all")));
}
}
void FeedMessageViewer::switchFeedComponentVisibility() {
m_feedsWidget->setVisible(!m_feedsWidget->isVisible());
}
@ -322,6 +272,7 @@ void FeedMessageViewer::createConnections() {
// State of many messages is changed, then we need
// to reload selections.
connect(m_feedsView->sourceModel(), SIGNAL(reloadMessageListRequested(bool)), m_messagesView, SLOT(reloadSelections(bool)));
connect(m_feedsView->sourceModel(), SIGNAL(feedsUpdateFinished()), this, SLOT(onFeedsUpdateFinished()));
// Message openers.
connect(m_messagesView, SIGNAL(openLinkMiniBrowser(QString)), m_messagesBrowser, SLOT(navigateToUrl(QString)));
@ -333,7 +284,8 @@ void FeedMessageViewer::createConnections() {
form_main->m_ui->m_tabWidget, SLOT(addBrowserWithMessages(QList<Message>)));
// Downloader connections.
connect(m_feedsView, SIGNAL(feedsUpdateRequested(QList<Feed*>)), this, SLOT(updateFeeds(QList<Feed*>)));
// TODO: přesunout všechny negui věci asi k modelům, tohle je
// hlavně GUI třída, takže přesunout aktualizace feedů do modelu
// Toolbar forwardings.
connect(form_main->m_ui->m_actionCleanupDatabase,
@ -500,31 +452,6 @@ void FeedMessageViewer::refreshVisualProperties() {
m_toolBarMessages->setToolButtonStyle(button_style);
}
void FeedMessageViewer::updateFeeds(QList<Feed*> feeds) {
if (!qApp->feedUpdateLock()->tryLock()) {
qApp->showGuiMessage(tr("Cannot update all items"),
tr("You cannot update all items because another another critical operation is ongoing."),
QSystemTrayIcon::Warning, qApp->mainForm(), true);
return;
}
if (m_feedDownloader == NULL) {
m_feedDownloader = new FeedDownloader();
m_feedDownloaderThread = new QThread();
// Downloader setup.
qRegisterMetaType<QList<Feed*> >("QList<Feed*>");
m_feedDownloader->moveToThread(m_feedDownloaderThread);
connect(this, SIGNAL(feedsUpdateRequested(QList<Feed*>)), m_feedDownloader, SLOT(updateFeeds(QList<Feed*>)));
connect(m_feedDownloaderThread, SIGNAL(finished()), m_feedDownloaderThread, SLOT(deleteLater()));
connect(m_feedDownloader, SIGNAL(finished(FeedDownloadResults)), this, SLOT(onFeedUpdatesFinished(FeedDownloadResults)));
connect(m_feedDownloader, SIGNAL(started()), this, SLOT(onFeedUpdatesStarted()));
connect(m_feedDownloader, SIGNAL(progress(Feed*,int,int)), this, SLOT(onFeedUpdatesProgress(Feed*,int,int)));
// Connections are made, start the feed downloader thread.
m_feedDownloaderThread->start();
}
emit feedsUpdateRequested(feeds);
void FeedMessageViewer::onFeedsUpdateFinished() {
m_messagesView->reloadSelections(true);
}

View file

@ -96,18 +96,15 @@ class FeedMessageViewer : public TabContent {
// Reloads some changeable visual settings.
void refreshVisualProperties();
void updateFeeds(QList<Feed*> feeds);
private slots:
// Reacts on feed updates.
void onFeedUpdatesStarted();
void onFeedUpdatesProgress(Feed *feed, int current, int total);
void onFeedUpdatesFinished(FeedDownloadResults results);
// Called when feed update finishes.
void onFeedsUpdateFinished();
// Switches visibility of feed list and related
// toolbar.
void switchFeedComponentVisibility();
// Toggles displayed feeds.
void toggleShowOnlyUnreadFeeds();
void updateMessageButtonsAvailability();
@ -123,10 +120,6 @@ class FeedMessageViewer : public TabContent {
// Sets up connections.
void createConnections();
signals:
// Emitted if user/application requested updating of some feeds.
void feedsUpdateRequested(const QList<Feed*> feeds);
private:
bool m_toolBarsEnabled;
bool m_listHeadersEnabled;
@ -142,9 +135,7 @@ class FeedMessageViewer : public TabContent {
QWidget *m_messagesWidget;
WebBrowser *m_messagesBrowser;
QThread *m_feedDownloaderThread;
QThread *m_dbCleanerThread;
FeedDownloader *m_feedDownloader;
DatabaseCleaner *m_dbCleaner;
};

View file

@ -54,7 +54,6 @@ FeedsView::FeedsView(QWidget *parent)
m_sourceModel = m_proxyModel->sourceModel();
// Connections.
connect(m_sourceModel, SIGNAL(feedsUpdateRequested(QList<Feed*>)), this, SIGNAL(feedsUpdateRequested(QList<Feed*>)));
connect(header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), this, SLOT(saveSortState(int,Qt::SortOrder)));
setModel(m_proxyModel);
@ -153,18 +152,11 @@ void FeedsView::expandCollapseCurrentItem() {
}
void FeedsView::updateAllItems() {
emit feedsUpdateRequested(allFeeds());
m_sourceModel->updateAllFeeds();
}
void FeedsView::updateSelectedItems() {
emit feedsUpdateRequested(selectedFeeds());
}
void FeedsView::updateAllItemsOnStartup() {
if (qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::FeedsUpdateOnStartup)).toBool()) {
qDebug("Requesting update for all feeds on application startup.");
QTimer::singleShot(STARTUP_UPDATE_DELAY, this, SLOT(updateAllItems()));
}
m_sourceModel->updateFeeds(selectedFeeds());
}
void FeedsView::clearSelectedFeeds() {
@ -290,10 +282,6 @@ void FeedsView::markAllItemsRead() {
markAllItemsReadStatus(RootItem::Read);
}
void FeedsView::clearAllReadMessages() {
m_sourceModel->markItemCleared(m_sourceModel->rootItem(), true);
}
void FeedsView::openSelectedItemsInNewspaperMode() {
QList<Message> messages = m_sourceModel->messagesForFeeds(selectedFeeds());

View file

@ -68,7 +68,6 @@ class FeedsView : public QTreeView {
// Feed updating.
void updateAllItems();
void updateAllItemsOnStartup();
void updateSelectedItems();
// Feed read/unread manipulators.
@ -82,7 +81,6 @@ class FeedsView : public QTreeView {
// Feed clearers.
void clearSelectedFeeds();
void clearAllFeeds();
void clearAllReadMessages();
// Base manipulators.
void editSelectedItem();
@ -96,9 +94,6 @@ class FeedsView : public QTreeView {
void switchVisibility();
signals:
// Emitted if user/application requested updating of some feeds.
void feedsUpdateRequested(const QList<Feed*> feeds);
// Emitted if user selects new feeds.
void itemSelected(RootItem *item);