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/iconfactory.h"
#include "miscellaneous/mutex.h" #include "miscellaneous/mutex.h"
#include "gui/messagebox.h" #include "gui/messagebox.h"
#include "gui/statusbar.h"
#include "gui/dialogs/formmain.h"
#include "core/feeddownloader.h"
#include <QThread>
#include <QSqlError> #include <QSqlError>
#include <QSqlQuery> #include <QSqlQuery>
#include <QSqlRecord> #include <QSqlRecord>
@ -40,7 +44,7 @@
FeedsModel::FeedsModel(QObject *parent) 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")); setObjectName(QSL("FeedsModel"));
// Create root item. // Create root item.
@ -64,6 +68,11 @@ FeedsModel::FeedsModel(QObject *parent)
loadActivatedServiceAccounts(); loadActivatedServiceAccounts();
updateAutoUpdateStatus(); 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() { FeedsModel::~FeedsModel() {
@ -77,6 +86,85 @@ void FeedsModel::quit() {
if (m_autoUpdateTimer->isActive()) { if (m_autoUpdateTimer->isActive()) {
m_autoUpdateTimer->stop(); 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() { void FeedsModel::executeNextAutoUpdate() {

View file

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

View file

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

View file

@ -65,17 +65,12 @@ FeedMessageViewer::FeedMessageViewer(QWidget *parent)
m_messagesView(new MessagesView(this)), m_messagesView(new MessagesView(this)),
m_feedsView(new FeedsView(this)), m_feedsView(new FeedsView(this)),
m_messagesBrowser(new WebBrowser(this)), m_messagesBrowser(new WebBrowser(this)),
m_feedDownloaderThread(NULL),
m_dbCleanerThread(NULL), m_dbCleanerThread(NULL),
m_feedDownloader(NULL),
m_dbCleaner(NULL) { m_dbCleaner(NULL) {
initialize(); initialize();
initializeViews(); initializeViews();
loadMessageViewerFonts(); loadMessageViewerFonts();
createConnections(); createConnections();
// Now, update all feeds if user has set it.
m_feedsView->updateAllItemsOnStartup();
} }
FeedMessageViewer::~FeedMessageViewer() { FeedMessageViewer::~FeedMessageViewer() {
@ -86,38 +81,38 @@ DatabaseCleaner *FeedMessageViewer::databaseCleaner() {
if (m_dbCleaner == NULL) { if (m_dbCleaner == NULL) {
m_dbCleaner = new DatabaseCleaner(); m_dbCleaner = new DatabaseCleaner();
m_dbCleanerThread = new QThread(); m_dbCleanerThread = new QThread();
// Downloader setup. // Downloader setup.
qRegisterMetaType<CleanerOrders>("CleanerOrders"); qRegisterMetaType<CleanerOrders>("CleanerOrders");
m_dbCleaner->moveToThread(m_dbCleanerThread); m_dbCleaner->moveToThread(m_dbCleanerThread);
connect(m_dbCleanerThread, SIGNAL(finished()), m_dbCleanerThread, SLOT(deleteLater())); connect(m_dbCleanerThread, SIGNAL(finished()), m_dbCleanerThread, SLOT(deleteLater()));
// Connections are made, start the feed downloader thread. // Connections are made, start the feed downloader thread.
m_dbCleanerThread->start(); m_dbCleanerThread->start();
} }
return m_dbCleaner; return m_dbCleaner;
} }
void FeedMessageViewer::saveSize() { void FeedMessageViewer::saveSize() {
Settings *settings = qApp->settings(); Settings *settings = qApp->settings();
m_feedsView->saveExpandedStates(); m_feedsView->saveExpandedStates();
// Store offsets of splitters. // Store offsets of splitters.
settings->setValue(GROUP(GUI), GUI::SplitterFeeds, QString(m_feedSplitter->saveState().toBase64())); settings->setValue(GROUP(GUI), GUI::SplitterFeeds, QString(m_feedSplitter->saveState().toBase64()));
settings->setValue(GROUP(GUI), GUI::SplitterMessages, QString(m_messageSplitter->saveState().toBase64())); settings->setValue(GROUP(GUI), GUI::SplitterMessages, QString(m_messageSplitter->saveState().toBase64()));
// States of splitters are stored, let's store // States of splitters are stored, let's store
// widths of columns. // widths of columns.
int width_column_author = m_messagesView->columnWidth(MSG_DB_AUTHOR_INDEX); int width_column_author = m_messagesView->columnWidth(MSG_DB_AUTHOR_INDEX);
int width_column_date = m_messagesView->columnWidth(MSG_DB_DCREATED_INDEX); int width_column_date = m_messagesView->columnWidth(MSG_DB_DCREATED_INDEX);
if (width_column_author != 0 && width_column_date != 0) { if (width_column_author != 0 && width_column_date != 0) {
settings->setValue(GROUP(GUI), KEY_MESSAGES_VIEW + QString::number(MSG_DB_AUTHOR_INDEX), width_column_author); settings->setValue(GROUP(GUI), KEY_MESSAGES_VIEW + QString::number(MSG_DB_AUTHOR_INDEX), width_column_author);
settings->setValue(GROUP(GUI), KEY_MESSAGES_VIEW + QString::number(MSG_DB_DCREATED_INDEX), width_column_date); settings->setValue(GROUP(GUI), KEY_MESSAGES_VIEW + QString::number(MSG_DB_DCREATED_INDEX), width_column_date);
} }
// Store "visibility" of toolbars and list headers. // Store "visibility" of toolbars and list headers.
settings->setValue(GROUP(GUI), GUI::ToolbarsVisible, m_toolBarsEnabled); settings->setValue(GROUP(GUI), GUI::ToolbarsVisible, m_toolBarsEnabled);
settings->setValue(GROUP(GUI), GUI::ListHeadersVisible, m_listHeadersEnabled); settings->setValue(GROUP(GUI), GUI::ListHeadersVisible, m_listHeadersEnabled);
@ -126,13 +121,13 @@ void FeedMessageViewer::saveSize() {
void FeedMessageViewer::loadSize() { void FeedMessageViewer::loadSize() {
Settings *settings = qApp->settings(); Settings *settings = qApp->settings();
int default_msg_section_size = m_messagesView->header()->defaultSectionSize(); int default_msg_section_size = m_messagesView->header()->defaultSectionSize();
m_feedsView->loadExpandedStates(); m_feedsView->loadExpandedStates();
// Restore offsets of splitters. // Restore offsets of splitters.
m_feedSplitter->restoreState(QByteArray::fromBase64(settings->value(GROUP(GUI), SETTING(GUI::SplitterFeeds)).toString().toLocal8Bit())); m_feedSplitter->restoreState(QByteArray::fromBase64(settings->value(GROUP(GUI), SETTING(GUI::SplitterFeeds)).toString().toLocal8Bit()));
m_messageSplitter->restoreState(QByteArray::fromBase64(settings->value(GROUP(GUI), SETTING(GUI::SplitterMessages)).toString().toLocal8Bit())); m_messageSplitter->restoreState(QByteArray::fromBase64(settings->value(GROUP(GUI), SETTING(GUI::SplitterMessages)).toString().toLocal8Bit()));
// Splitters are restored, now, restore widths of columns. // Splitters are restored, now, restore widths of columns.
m_messagesView->setColumnWidth(MSG_DB_AUTHOR_INDEX, settings->value(GROUP(GUI), m_messagesView->setColumnWidth(MSG_DB_AUTHOR_INDEX, settings->value(GROUP(GUI),
KEY_MESSAGES_VIEW + QString::number(MSG_DB_AUTHOR_INDEX), KEY_MESSAGES_VIEW + QString::number(MSG_DB_AUTHOR_INDEX),
@ -145,7 +140,7 @@ void FeedMessageViewer::loadSize() {
void FeedMessageViewer::loadMessageViewerFonts() { void FeedMessageViewer::loadMessageViewerFonts() {
Settings *settings = qApp->settings(); Settings *settings = qApp->settings();
QWebSettings *view_settings = m_messagesBrowser->view()->settings(); QWebSettings *view_settings = m_messagesBrowser->view()->settings();
view_settings->setFontFamily(QWebSettings::StandardFont, settings->value(GROUP(Messages), view_settings->setFontFamily(QWebSettings::StandardFont, settings->value(GROUP(Messages),
SETTING(Messages::PreviewerFontStandard)).toString()); SETTING(Messages::PreviewerFontStandard)).toString());
} }
@ -153,42 +148,21 @@ void FeedMessageViewer::loadMessageViewerFonts() {
void FeedMessageViewer::quit() { void FeedMessageViewer::quit() {
// Quit the feeds model (stops auto-update timer etc.). // Quit the feeds model (stops auto-update timer etc.).
m_feedsView->sourceModel()->quit(); 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()) { if (m_dbCleanerThread != NULL && m_dbCleanerThread->isRunning()) {
qDebug("Quitting database cleaner thread."); qDebug("Quitting database cleaner thread.");
m_dbCleanerThread->quit(); m_dbCleanerThread->quit();
if (!m_dbCleanerThread->wait(CLOSE_LOCK_TIMEOUT)) { if (!m_dbCleanerThread->wait(CLOSE_LOCK_TIMEOUT)) {
qCritical("Database cleaner thread is running despite it was told to quit. Terminating it."); qCritical("Database cleaner thread is running despite it was told to quit. Terminating it.");
m_dbCleanerThread->terminate(); m_dbCleanerThread->terminate();
} }
} }
// Close workers.
if (m_feedDownloader != NULL) {
qDebug("Feed downloader exists. Deleting it from memory.");
m_feedDownloader->deleteLater();
}
if (m_dbCleaner != NULL) { if (m_dbCleaner != NULL) {
qDebug("Database cleaner exists. Deleting it from memory."); qDebug("Database cleaner exists. Deleting it from memory.");
m_dbCleaner->deleteLater(); m_dbCleaner->deleteLater();
} }
if (qApp->settings()->value(GROUP(Messages), SETTING(Messages::ClearReadOnExit)).toBool()) {
m_feedsView->clearAllReadMessages();
}
} }
bool FeedMessageViewer::areToolBarsEnabled() const { bool FeedMessageViewer::areToolBarsEnabled() const {
@ -220,37 +194,13 @@ void FeedMessageViewer::setListHeadersEnabled(bool enable) {
m_messagesView->header()->setVisible(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() { void FeedMessageViewer::switchFeedComponentVisibility() {
m_feedsWidget->setVisible(!m_feedsWidget->isVisible()); m_feedsWidget->setVisible(!m_feedsWidget->isVisible());
} }
void FeedMessageViewer::toggleShowOnlyUnreadFeeds() { void FeedMessageViewer::toggleShowOnlyUnreadFeeds() {
QAction *origin = qobject_cast<QAction*>(sender()); QAction *origin = qobject_cast<QAction*>(sender());
if (origin == NULL) { if (origin == NULL) {
m_feedsView->model()->invalidateReadFeedsFilter(true, false); m_feedsView->model()->invalidateReadFeedsFilter(true, false);
} }
@ -263,7 +213,7 @@ void FeedMessageViewer::updateMessageButtonsAvailability() {
bool one_message_selected = m_messagesView->selectionModel()->selectedRows().size() == 1; bool one_message_selected = m_messagesView->selectionModel()->selectedRows().size() == 1;
bool atleast_one_message_selected = !m_messagesView->selectionModel()->selectedRows().isEmpty(); bool atleast_one_message_selected = !m_messagesView->selectionModel()->selectedRows().isEmpty();
FormMain *form_main = qApp->mainForm(); FormMain *form_main = qApp->mainForm();
form_main->m_ui->m_actionDeleteSelectedMessages->setEnabled(atleast_one_message_selected); form_main->m_ui->m_actionDeleteSelectedMessages->setEnabled(atleast_one_message_selected);
form_main->m_ui->m_actionMarkSelectedMessagesAsRead->setEnabled(atleast_one_message_selected); form_main->m_ui->m_actionMarkSelectedMessagesAsRead->setEnabled(atleast_one_message_selected);
form_main->m_ui->m_actionMarkSelectedMessagesAsUnread->setEnabled(atleast_one_message_selected); form_main->m_ui->m_actionMarkSelectedMessagesAsUnread->setEnabled(atleast_one_message_selected);
@ -282,7 +232,7 @@ void FeedMessageViewer::updateFeedButtonsAvailability() {
bool category_selected = anything_selected && selected_item->kind() == RootItemKind::Category; bool category_selected = anything_selected && selected_item->kind() == RootItemKind::Category;
bool service_selected = anything_selected && selected_item->kind() == RootItemKind::ServiceRoot; bool service_selected = anything_selected && selected_item->kind() == RootItemKind::ServiceRoot;
FormMain *form_main = qApp->mainForm(); FormMain *form_main = qApp->mainForm();
form_main->m_ui->m_actionServiceEdit->setEnabled(!critical_action_running && service_selected); form_main->m_ui->m_actionServiceEdit->setEnabled(!critical_action_running && service_selected);
form_main->m_ui->m_actionServiceDelete->setEnabled(!critical_action_running && service_selected); form_main->m_ui->m_actionServiceDelete->setEnabled(!critical_action_running && service_selected);
form_main->m_ui->m_actionBackupDatabaseSettings->setEnabled(!critical_action_running); form_main->m_ui->m_actionBackupDatabaseSettings->setEnabled(!critical_action_running);
@ -301,27 +251,28 @@ void FeedMessageViewer::updateFeedButtonsAvailability() {
void FeedMessageViewer::createConnections() { void FeedMessageViewer::createConnections() {
FormMain *form_main = qApp->mainForm(); FormMain *form_main = qApp->mainForm();
// Filtering & searching. // Filtering & searching.
connect(m_toolBarMessages, SIGNAL(messageSearchPatternChanged(QString)), m_messagesView, SLOT(searchMessages(QString))); connect(m_toolBarMessages, SIGNAL(messageSearchPatternChanged(QString)), m_messagesView, SLOT(searchMessages(QString)));
connect(m_toolBarMessages, SIGNAL(messageFilterChanged(MessagesModel::MessageHighlighter)), m_messagesView, SLOT(filterMessages(MessagesModel::MessageHighlighter))); connect(m_toolBarMessages, SIGNAL(messageFilterChanged(MessagesModel::MessageHighlighter)), m_messagesView, SLOT(filterMessages(MessagesModel::MessageHighlighter)));
// Message changers. // Message changers.
connect(m_messagesView, SIGNAL(currentMessagesRemoved()), m_messagesBrowser, SLOT(clear())); connect(m_messagesView, SIGNAL(currentMessagesRemoved()), m_messagesBrowser, SLOT(clear()));
connect(m_messagesView, SIGNAL(currentMessagesChanged(QList<Message>)), m_messagesBrowser, SLOT(navigateToMessages(QList<Message>))); connect(m_messagesView, SIGNAL(currentMessagesChanged(QList<Message>)), m_messagesBrowser, SLOT(navigateToMessages(QList<Message>)));
connect(m_messagesView, SIGNAL(currentMessagesRemoved()), this, SLOT(updateMessageButtonsAvailability())); connect(m_messagesView, SIGNAL(currentMessagesRemoved()), this, SLOT(updateMessageButtonsAvailability()));
connect(m_messagesView, SIGNAL(currentMessagesChanged(QList<Message>)), this, SLOT(updateMessageButtonsAvailability())); connect(m_messagesView, SIGNAL(currentMessagesChanged(QList<Message>)), this, SLOT(updateMessageButtonsAvailability()));
connect(m_feedsView, SIGNAL(itemSelected(RootItem*)), this, SLOT(updateFeedButtonsAvailability())); connect(m_feedsView, SIGNAL(itemSelected(RootItem*)), this, SLOT(updateFeedButtonsAvailability()));
connect(qApp->feedUpdateLock(), SIGNAL(locked()), this, SLOT(updateFeedButtonsAvailability())); connect(qApp->feedUpdateLock(), SIGNAL(locked()), this, SLOT(updateFeedButtonsAvailability()));
connect(qApp->feedUpdateLock(), SIGNAL(unlocked()), this, SLOT(updateFeedButtonsAvailability())); connect(qApp->feedUpdateLock(), SIGNAL(unlocked()), this, SLOT(updateFeedButtonsAvailability()));
// If user selects feeds, load their messages. // If user selects feeds, load their messages.
connect(m_feedsView, SIGNAL(itemSelected(RootItem*)), m_messagesView, SLOT(loadFeeds(RootItem*))); connect(m_feedsView, SIGNAL(itemSelected(RootItem*)), m_messagesView, SLOT(loadFeeds(RootItem*)));
// State of many messages is changed, then we need // State of many messages is changed, then we need
// to reload selections. // to reload selections.
connect(m_feedsView->sourceModel(), SIGNAL(reloadMessageListRequested(bool)), m_messagesView, SLOT(reloadSelections(bool))); connect(m_feedsView->sourceModel(), SIGNAL(reloadMessageListRequested(bool)), m_messagesView, SLOT(reloadSelections(bool)));
connect(m_feedsView->sourceModel(), SIGNAL(feedsUpdateFinished()), this, SLOT(onFeedsUpdateFinished()));
// Message openers. // Message openers.
connect(m_messagesView, SIGNAL(openLinkMiniBrowser(QString)), m_messagesBrowser, SLOT(navigateToUrl(QString))); connect(m_messagesView, SIGNAL(openLinkMiniBrowser(QString)), m_messagesBrowser, SLOT(navigateToUrl(QString)));
@ -331,10 +282,11 @@ void FeedMessageViewer::createConnections() {
form_main->m_ui->m_tabWidget, SLOT(addLinkedBrowser(QString))); form_main->m_ui->m_tabWidget, SLOT(addLinkedBrowser(QString)));
connect(m_feedsView, SIGNAL(openMessagesInNewspaperView(QList<Message>)), connect(m_feedsView, SIGNAL(openMessagesInNewspaperView(QList<Message>)),
form_main->m_ui->m_tabWidget, SLOT(addBrowserWithMessages(QList<Message>))); form_main->m_ui->m_tabWidget, SLOT(addBrowserWithMessages(QList<Message>)));
// Downloader connections. // 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. // Toolbar forwardings.
connect(form_main->m_ui->m_actionCleanupDatabase, connect(form_main->m_ui->m_actionCleanupDatabase,
SIGNAL(triggered()), this, SLOT(showDbCleanupAssistant())); SIGNAL(triggered()), this, SLOT(showDbCleanupAssistant()));
@ -402,15 +354,15 @@ void FeedMessageViewer::initialize() {
m_toolBarFeeds->setMovable(false); m_toolBarFeeds->setMovable(false);
m_toolBarFeeds->setAllowedAreas(Qt::TopToolBarArea); m_toolBarFeeds->setAllowedAreas(Qt::TopToolBarArea);
m_toolBarFeeds->loadChangeableActions(); m_toolBarFeeds->loadChangeableActions();
m_toolBarMessages->setFloatable(false); m_toolBarMessages->setFloatable(false);
m_toolBarMessages->setMovable(false); m_toolBarMessages->setMovable(false);
m_toolBarMessages->setAllowedAreas(Qt::TopToolBarArea); m_toolBarMessages->setAllowedAreas(Qt::TopToolBarArea);
m_toolBarMessages->loadChangeableActions(); m_toolBarMessages->loadChangeableActions();
// Finish web/message browser setup. // Finish web/message browser setup.
m_messagesBrowser->setNavigationBarVisible(false); m_messagesBrowser->setNavigationBarVisible(false);
// Now refresh visual setup. // Now refresh visual setup.
refreshVisualProperties(); refreshVisualProperties();
} }
@ -420,12 +372,12 @@ void FeedMessageViewer::initializeViews() {
m_messagesWidget = new QWidget(this); m_messagesWidget = new QWidget(this);
m_feedSplitter = new QSplitter(Qt::Horizontal, this); m_feedSplitter = new QSplitter(Qt::Horizontal, this);
m_messageSplitter = new QSplitter(Qt::Vertical, this); m_messageSplitter = new QSplitter(Qt::Vertical, this);
// Instantiate needed components. // Instantiate needed components.
QVBoxLayout *central_layout = new QVBoxLayout(this); QVBoxLayout *central_layout = new QVBoxLayout(this);
QVBoxLayout *feed_layout = new QVBoxLayout(m_feedsWidget); QVBoxLayout *feed_layout = new QVBoxLayout(m_feedsWidget);
QVBoxLayout *message_layout = new QVBoxLayout(m_messagesWidget); QVBoxLayout *message_layout = new QVBoxLayout(m_messagesWidget);
// Set layout properties. // Set layout properties.
central_layout->setMargin(0); central_layout->setMargin(0);
central_layout->setSpacing(0); central_layout->setSpacing(0);
@ -433,11 +385,11 @@ void FeedMessageViewer::initializeViews() {
feed_layout->setSpacing(0); feed_layout->setSpacing(0);
message_layout->setMargin(0); message_layout->setMargin(0);
message_layout->setSpacing(0); message_layout->setSpacing(0);
// Set views. // Set views.
m_feedsView->setFrameStyle(QFrame::NoFrame); m_feedsView->setFrameStyle(QFrame::NoFrame);
m_messagesView->setFrameStyle(QFrame::NoFrame); m_messagesView->setFrameStyle(QFrame::NoFrame);
// Setup message splitter. // Setup message splitter.
m_messageSplitter->setObjectName(QSL("MessageSplitter")); m_messageSplitter->setObjectName(QSL("MessageSplitter"));
m_messageSplitter->setHandleWidth(1); m_messageSplitter->setHandleWidth(1);
@ -445,30 +397,30 @@ void FeedMessageViewer::initializeViews() {
m_messageSplitter->setChildrenCollapsible(false); m_messageSplitter->setChildrenCollapsible(false);
m_messageSplitter->addWidget(m_messagesView); m_messageSplitter->addWidget(m_messagesView);
m_messageSplitter->addWidget(m_messagesBrowser); m_messageSplitter->addWidget(m_messagesBrowser);
// Assemble message-related components to single widget. // Assemble message-related components to single widget.
message_layout->addWidget(m_toolBarMessages); message_layout->addWidget(m_toolBarMessages);
message_layout->addWidget(m_messageSplitter); message_layout->addWidget(m_messageSplitter);
// Assemble feed-related components to another widget. // Assemble feed-related components to another widget.
feed_layout->addWidget(m_toolBarFeeds); feed_layout->addWidget(m_toolBarFeeds);
feed_layout->addWidget(m_feedsView); feed_layout->addWidget(m_feedsView);
// Assembler everything together. // Assembler everything together.
m_feedSplitter->setHandleWidth(1); m_feedSplitter->setHandleWidth(1);
m_feedSplitter->setOpaqueResize(false); m_feedSplitter->setOpaqueResize(false);
m_feedSplitter->setChildrenCollapsible(false); m_feedSplitter->setChildrenCollapsible(false);
m_feedSplitter->addWidget(m_feedsWidget); m_feedSplitter->addWidget(m_feedsWidget);
m_feedSplitter->addWidget(m_messagesWidget); m_feedSplitter->addWidget(m_messagesWidget);
// Add toolbar and main feeds/messages widget to main layout. // Add toolbar and main feeds/messages widget to main layout.
central_layout->addWidget(m_feedSplitter); central_layout->addWidget(m_feedSplitter);
setTabOrder(m_feedsView, m_messagesView); setTabOrder(m_feedsView, m_messagesView);
setTabOrder(m_messagesView, m_toolBarFeeds); setTabOrder(m_messagesView, m_toolBarFeeds);
setTabOrder(m_toolBarFeeds, m_toolBarMessages); setTabOrder(m_toolBarFeeds, m_toolBarMessages);
setTabOrder(m_toolBarMessages, m_messagesBrowser); setTabOrder(m_toolBarMessages, m_messagesBrowser);
updateMessageButtonsAvailability(); updateMessageButtonsAvailability();
updateFeedButtonsAvailability(); updateFeedButtonsAvailability();
} }
@ -478,10 +430,10 @@ void FeedMessageViewer::showDbCleanupAssistant() {
QPointer<FormDatabaseCleanup> form_pointer = new FormDatabaseCleanup(this); QPointer<FormDatabaseCleanup> form_pointer = new FormDatabaseCleanup(this);
form_pointer.data()->setCleaner(databaseCleaner()); form_pointer.data()->setCleaner(databaseCleaner());
form_pointer.data()->exec(); form_pointer.data()->exec();
delete form_pointer.data(); delete form_pointer.data();
qApp->feedUpdateLock()->unlock(); qApp->feedUpdateLock()->unlock();
m_messagesView->reloadSelections(false); m_messagesView->reloadSelections(false);
m_feedsView->sourceModel()->reloadCountsOfWholeModel(); m_feedsView->sourceModel()->reloadCountsOfWholeModel();
} }
@ -495,36 +447,11 @@ void FeedMessageViewer::showDbCleanupAssistant() {
void FeedMessageViewer::refreshVisualProperties() { void FeedMessageViewer::refreshVisualProperties() {
Qt::ToolButtonStyle button_style = static_cast<Qt::ToolButtonStyle>(qApp->settings()->value(GROUP(GUI), Qt::ToolButtonStyle button_style = static_cast<Qt::ToolButtonStyle>(qApp->settings()->value(GROUP(GUI),
SETTING(GUI::ToolbarStyle)).toInt()); SETTING(GUI::ToolbarStyle)).toInt());
m_toolBarFeeds->setToolButtonStyle(button_style); m_toolBarFeeds->setToolButtonStyle(button_style);
m_toolBarMessages->setToolButtonStyle(button_style); m_toolBarMessages->setToolButtonStyle(button_style);
} }
void FeedMessageViewer::updateFeeds(QList<Feed*> feeds) { void FeedMessageViewer::onFeedsUpdateFinished() {
if (!qApp->feedUpdateLock()->tryLock()) { m_messagesView->reloadSelections(true);
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);
} }

View file

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

View file

@ -54,7 +54,6 @@ FeedsView::FeedsView(QWidget *parent)
m_sourceModel = m_proxyModel->sourceModel(); m_sourceModel = m_proxyModel->sourceModel();
// Connections. // 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))); connect(header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), this, SLOT(saveSortState(int,Qt::SortOrder)));
setModel(m_proxyModel); setModel(m_proxyModel);
@ -153,18 +152,11 @@ void FeedsView::expandCollapseCurrentItem() {
} }
void FeedsView::updateAllItems() { void FeedsView::updateAllItems() {
emit feedsUpdateRequested(allFeeds()); m_sourceModel->updateAllFeeds();
} }
void FeedsView::updateSelectedItems() { void FeedsView::updateSelectedItems() {
emit feedsUpdateRequested(selectedFeeds()); m_sourceModel->updateFeeds(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()));
}
} }
void FeedsView::clearSelectedFeeds() { void FeedsView::clearSelectedFeeds() {
@ -290,10 +282,6 @@ void FeedsView::markAllItemsRead() {
markAllItemsReadStatus(RootItem::Read); markAllItemsReadStatus(RootItem::Read);
} }
void FeedsView::clearAllReadMessages() {
m_sourceModel->markItemCleared(m_sourceModel->rootItem(), true);
}
void FeedsView::openSelectedItemsInNewspaperMode() { void FeedsView::openSelectedItemsInNewspaperMode() {
QList<Message> messages = m_sourceModel->messagesForFeeds(selectedFeeds()); QList<Message> messages = m_sourceModel->messagesForFeeds(selectedFeeds());

View file

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