Some work on optimizations and database cleaning.

This commit is contained in:
Martin Rotter 2015-06-04 08:07:48 +02:00
parent cee624ac0d
commit 4c8e9a021e
16 changed files with 268 additions and 42 deletions

View File

@ -364,6 +364,7 @@ set(APP_SOURCES
src/gui/formrestoredatabasesettings.cpp
src/gui/edittableview.cpp
src/gui/squeezelabel.cpp
src/gui/formdatabasecleanup.cpp
# DYNAMIC-SHORTCUTS sources.
src/dynamic-shortcuts/shortcutcatcher.cpp
@ -384,6 +385,7 @@ set(APP_SOURCES
src/miscellaneous/iofactory.cpp
src/miscellaneous/autosaver.cpp
src/miscellaneous/mutex.cpp
src/miscellaneous/databasecleaner.cpp
# EXCEPTIONS sources.
src/exceptions/applicationexception.cpp
@ -462,6 +464,7 @@ set(APP_HEADERS
src/gui/formrestoredatabasesettings.h
src/gui/edittableview.h
src/gui/squeezelabel.h
src/gui/formdatabasecleanup.h
# DYNAMIC-SHORTCUTS headers.
src/dynamic-shortcuts/dynamicshortcutswidget.h
@ -478,6 +481,7 @@ set(APP_HEADERS
src/miscellaneous/skinfactory.h
src/miscellaneous/autosaver.h
src/miscellaneous/mutex.h
src/miscellaneous/databasecleaner.h
# CORE headers.
src/core/messagesmodel.h
@ -513,6 +517,7 @@ set(APP_FORMS
src/gui/formimportexport.ui
src/gui/formbackupdatabasesettings.ui
src/gui/formrestoredatabasesettings.ui
src/gui/formdatabasecleanup.ui
src/network-web/downloadmanager.ui
src/network-web/downloaditem.ui
)

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -7,12 +7,15 @@ Added:
<li>All feeds are by default checked when exporting/importing them.</li>
<li>Message previewer now displays MIME type of all podcasts too. This MIME type is also stored in DB.</li>
<li>Ability to fetch only new icon for feed from its online source.</li>
<li>Message view now automatically scrolls to selected message when changing filter string.</li>
<li>Some small memory footprint enhancements.</li>
<li>Option to search highlighted text in web browser via Google, available from context menu. (issue #72)</li>
</ul>
Fixed:
<ul>
<li>Reworked DB initialization scripts.</li>
<li>Threads for feed updating are created only when really needed.</li>
<li>Reworked DB initialization scripts which allow to use OPML to do initial feed population.</li>
<li>Titles and descriptions of feeds are now fetched correctly in feed add/edit dialog.</li>
</ul>

View File

@ -61,15 +61,13 @@ FeedMessageViewer::FeedMessageViewer(QWidget *parent)
m_messagesView(new MessagesView(this)),
m_feedsView(new FeedsView(this)),
m_messagesBrowser(new WebBrowser(this)),
m_feedDownloaderThread(new QThread()),
m_feedDownloader(new FeedDownloader()) {
m_dbCleanerThread(NULL),
m_feedDownloaderThread(NULL),
m_feedDownloader(NULL) {
initialize();
initializeViews();
createConnections();
// Start the feed downloader thread.
m_feedDownloaderThread->start();
// Now, update all feeds if user has set it.
m_feedsView->updateAllFeedsOnStartup();
}
@ -125,12 +123,22 @@ void FeedMessageViewer::quit() {
// Quit the feeds view (stops auto-update timer etc.).
m_feedsView->quit();
qDebug("Quitting feed downloader thread.");
m_feedDownloaderThread->quit();
m_feedDownloaderThread->wait();
if (m_feedDownloaderThread != NULL && m_feedDownloaderThread->isRunning()) {
qDebug("Quitting feed downloader thread.");
m_feedDownloaderThread->quit();
m_feedDownloaderThread->wait();
}
qDebug("Feed downloader thread aborted. Deleting it from memory.");
m_feedDownloader->deleteLater();
if (m_dbCleanerThread != NULL && m_dbCleanerThread->isRunning()) {
qDebug("Quitting database cleaner thread.");
m_dbCleanerThread->quit();
m_dbCleanerThread->wait();
}
if (m_feedDownloader != NULL) {
qDebug("Feed downloader thread aborted. Deleting it from memory.");
m_feedDownloader->deleteLater();
}
if (qApp->settings()->value(GROUP(Messages), SETTING(Messages::ClearReadOnExit)).toBool()) {
m_feedsView->clearAllReadMessages();
@ -161,7 +169,7 @@ void FeedMessageViewer::loadInitialFeeds() {
}
}
catch (ApplicationException &ex) {
MessageBox::show(this, QMessageBox::Critical, tr("Error when loading initial feeds"), ex.message());
MessageBox::show(this, QMessageBox::Critical, tr("Error when loading initial feeds"), ex.message());
}
}
@ -203,8 +211,8 @@ void FeedMessageViewer::onFeedUpdatesProgress(FeedsModelFeed *feed, int current,
// Some feed got updated.
m_feedsView->updateCountsOfParticularFeed(feed, true);
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()));
//: Text display in status bar when particular feed is updated.
tr("Updated feed '%1'").arg(feed->title()));
}
void FeedMessageViewer::onFeedUpdatesFinished() {
@ -251,11 +259,7 @@ void FeedMessageViewer::createConnections() {
form_main->m_ui->m_tabWidget, SLOT(addBrowserWithMessages(QList<Message>)));
// Downloader connections.
connect(m_feedDownloaderThread, SIGNAL(finished()), m_feedDownloaderThread, SLOT(deleteLater()));
connect(m_feedsView, SIGNAL(feedsUpdateRequested(QList<FeedsModelFeed*>)), m_feedDownloader, SLOT(updateFeeds(QList<FeedsModelFeed*>)));
connect(m_feedDownloader, SIGNAL(finished()), this, SLOT(onFeedUpdatesFinished()));
connect(m_feedDownloader, SIGNAL(started()), this, SLOT(onFeedUpdatesStarted()));
connect(m_feedDownloader, SIGNAL(progress(FeedsModelFeed*,int,int)), this, SLOT(onFeedUpdatesProgress(FeedsModelFeed*,int,int)));
connect(m_feedsView, SIGNAL(feedsUpdateRequested(QList<FeedsModelFeed*>)), this, SLOT(updateFeeds(QList<FeedsModelFeed*>)));
// Toolbar forwardings.
connect(form_main->m_ui->m_actionSwitchImportanceOfSelectedMessages,
@ -318,8 +322,6 @@ void FeedMessageViewer::createConnections() {
SIGNAL(triggered()), m_messagesView, SLOT(selectNextItem()));
connect(form_main->m_ui->m_actionSelectPreviousMessage,
SIGNAL(triggered()), m_messagesView, SLOT(selectPreviousItem()));
connect(form_main->m_ui->m_actionDefragmentDatabase,
SIGNAL(triggered()), this, SLOT(vacuumDatabase()));
connect(form_main->m_ui->m_actionSwitchMessageListOrientation, SIGNAL(triggered()),
this, SLOT(switchMessageSplitterOrientation()));
}
@ -339,9 +341,7 @@ void FeedMessageViewer::initialize() {
// Finish web/message browser setup.
m_messagesBrowser->setNavigationBarVisible(false);
// Downloader setup.
qRegisterMetaType<QList<FeedsModelFeed*> >("QList<FeedsModelFeed*>");
m_feedDownloader->moveToThread(m_feedDownloaderThread);
// Now refresh visual setup.
refreshVisualProperties();
}
@ -435,3 +435,25 @@ void FeedMessageViewer::refreshVisualProperties() {
m_toolBarFeeds->setToolButtonStyle(button_style);
m_toolBarMessages->setToolButtonStyle(button_style);
}
void FeedMessageViewer::updateFeeds(QList<FeedsModelFeed *> feeds) {
if (m_feedDownloader == NULL) {
m_feedDownloader = new FeedDownloader();
m_feedDownloaderThread = new QThread();
// Downloader setup.
qRegisterMetaType<QList<FeedsModelFeed*> >("QList<FeedsModelFeed*>");
m_feedDownloader->moveToThread(m_feedDownloaderThread);
connect(this, SIGNAL(feedsUpdateRequested(QList<FeedsModelFeed*>)), m_feedDownloader, SLOT(updateFeeds(QList<FeedsModelFeed*>)));
connect(m_feedDownloaderThread, SIGNAL(finished()), m_feedDownloaderThread, SLOT(deleteLater()));
connect(m_feedDownloader, SIGNAL(finished()), this, SLOT(onFeedUpdatesFinished()));
connect(m_feedDownloader, SIGNAL(started()), this, SLOT(onFeedUpdatesStarted()));
connect(m_feedDownloader, SIGNAL(progress(FeedsModelFeed*,int,int)), this, SLOT(onFeedUpdatesProgress(FeedsModelFeed*,int,int)));
// Connections are made, start the feed downloader thread.
m_feedDownloaderThread->start();
}
emit feedsUpdateRequested(feeds);
}

View File

@ -98,6 +98,8 @@ class FeedMessageViewer : public TabContent {
// Reloads some changeable visual settings.
void refreshVisualProperties();
void updateFeeds(QList<FeedsModelFeed*> feeds);
protected slots:
// Updates counts of messages for example in tray icon.
void updateTrayIconStatus(int unread_messages, int total_messages, bool any_unread_messages);
@ -121,6 +123,10 @@ class FeedMessageViewer : public TabContent {
// Sets up connections.
void createConnections();
signals:
// Emitted if user/application requested updating of some feeds.
void feedsUpdateRequested(const QList<FeedsModelFeed*> feeds);
private:
bool m_toolBarsEnabled;
bool m_listHeadersEnabled;
@ -137,6 +143,7 @@ class FeedMessageViewer : public TabContent {
WebBrowser *m_messagesBrowser;
QThread *m_feedDownloaderThread;
QThread *m_dbCleanerThread;
FeedDownloader *m_feedDownloader;
};

View File

@ -0,0 +1,27 @@
#include "gui/formdatabasecleanup.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
FormDatabaseCleanup::FormDatabaseCleanup(QWidget *parent) : QDialog(parent), m_ui(new Ui::FormDatabaseCleanup) {
m_ui->setupUi(this);
// Set flags and attributes.
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint);
setWindowIcon(qApp->icons()->fromTheme("cleanup-database"));
// TODO: Vytvořil jsem základ okna pro mazání.
// v tomto okně se nastaví parametry mazání - jak staré zprávy, zda přečtené, zda vakuovat db
// do třídy DatabaseCleaner se dodělají metody, které budou samotné mazání provádět
// ve FeedMessageViewer se udělá instance cleaneru stejně jako FeedDownloader (vlákno už tam mam
// deklarovano (m_dbCleanerThread). Po "OK" tady v tomdle dialogu se pošle signal
// do instance cleaneru ve feedmessagevieweru.
// před otevřením tohodle dialogu se zamkne hlavní lock, po oddělání dialogu se odemkne.
// databasecleaner by mohl reportovat i progress, poběží ve svém vlákně.
}
FormDatabaseCleanup::~FormDatabaseCleanup() {
delete m_ui;
}

View File

@ -0,0 +1,24 @@
#ifndef FORMDATABASECLEANUP_H
#define FORMDATABASECLEANUP_H
#include <QDialog>
#include "ui_formdatabasecleanup.h"
namespace Ui {
class FormDatabaseCleanup;
}
class FormDatabaseCleanup : public QDialog {
Q_OBJECT
public:
explicit FormDatabaseCleanup(QWidget *parent = 0);
virtual ~FormDatabaseCleanup();
private:
Ui::FormDatabaseCleanup *m_ui;
};
#endif // FORMDATABASECLEANUP_H

View File

@ -0,0 +1,71 @@
<ui version="4.0">
<author/>
<comment/>
<exportmacro/>
<class>FormDatabaseCleanup</class>
<widget name="FormDatabaseCleanup" class="QDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget name="buttonBox" class="QDialogButtonBox">
<property name="geometry">
<rect>
<x>30</x>
<y>240</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</widget>
<pixmapfunction/>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>FormDatabaseCleanup</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>FormDatabaseCleanup</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -132,7 +132,6 @@ QList<QAction*> FormMain::allActions() {
actions << m_ui->m_actionSelectPreviousFeedCategory;
actions << m_ui->m_actionSelectNextMessage;
actions << m_ui->m_actionSelectPreviousMessage;
actions << m_ui->m_actionDefragmentDatabase;
// Add recycle bin actions.
actions << m_ui->m_actionRestoreRecycleBin;
@ -214,7 +213,7 @@ void FormMain::setupIcons() {
m_ui->m_actionRestart->setIcon(icon_theme_factory->fromTheme("go-refresh"));
m_ui->m_actionAboutGuard->setIcon(icon_theme_factory->fromTheme("application-about"));
m_ui->m_actionCheckForUpdates->setIcon(icon_theme_factory->fromTheme("check-for-updates"));
m_ui->m_actionDefragmentDatabase->setIcon(icon_theme_factory->fromTheme("defragment-database"));
m_ui->m_actionCleanupDatabase->setIcon(icon_theme_factory->fromTheme("cleanup-database"));
m_ui->m_actionReportBugGitHub->setIcon(icon_theme_factory->fromTheme("application-report-bug"));
m_ui->m_actionReportBugBitBucket->setIcon(icon_theme_factory->fromTheme("application-report-bug"));
m_ui->m_actionExportFeeds->setIcon(icon_theme_factory->fromTheme("document-export"));
@ -369,12 +368,13 @@ void FormMain::createConnections() {
connect(m_ui->m_actionCloseCurrentTab, SIGNAL(triggered()), m_ui->m_tabWidget, SLOT(closeCurrentTab()));
connect(m_ui->m_actionAddBrowser, SIGNAL(triggered()), m_ui->m_tabWidget, SLOT(addEmptyBrowser()));
connect(m_ui->m_actionCloseAllTabs, SIGNAL(triggered()), m_ui->m_tabWidget, SLOT(closeAllTabsExceptCurrent()));
connect(WebFactory::instance(), SIGNAL(imagesLoadingSwitched(bool)), m_ui->m_actionWebAutoloadImages, SLOT(setChecked(bool)));
connect(WebFactory::instance(), SIGNAL(javascriptSwitched(bool)), m_ui->m_actionWebEnableJavascript, SLOT(setChecked(bool)));
connect(WebFactory::instance(), SIGNAL(pluginsSwitched(bool)), m_ui->m_actionWebEnableExternalPlugins, SLOT(setChecked(bool)));
connect(m_ui->m_actionWebAutoloadImages, SIGNAL(toggled(bool)), WebFactory::instance(), SLOT(switchImages(bool)));
connect(m_ui->m_actionWebEnableExternalPlugins, SIGNAL(toggled(bool)), WebFactory::instance(), SLOT(switchPlugins(bool)));
connect(m_ui->m_actionWebEnableJavascript, SIGNAL(toggled(bool)), WebFactory::instance(), SLOT(switchJavascript(bool)));
connect(WebFactory::instance(), SIGNAL(imagesLoadingSwitched(bool)), m_ui->m_actionWebAutoloadImages, SLOT(setChecked(bool)));
connect(WebFactory::instance(), SIGNAL(javascriptSwitched(bool)), m_ui->m_actionWebEnableJavascript, SLOT(setChecked(bool)));
connect(WebFactory::instance(), SIGNAL(pluginsSwitched(bool)), m_ui->m_actionWebEnableExternalPlugins, SLOT(setChecked(bool)));
}
void FormMain::loadWebBrowserMenu(int index) {

View File

@ -99,7 +99,7 @@
</property>
<addaction name="m_actionSettings"/>
<addaction name="separator"/>
<addaction name="m_actionDefragmentDatabase"/>
<addaction name="m_actionCleanupDatabase"/>
<addaction name="m_actionDownloadManager"/>
</widget>
<widget class="QMenu" name="m_menuWebBrowser">
@ -405,14 +405,6 @@
<string>Hides main window if it is visible and shows it if it is hidden.</string>
</property>
</action>
<action name="m_actionDefragmentDatabase">
<property name="text">
<string>&amp;Defragment database</string>
</property>
<property name="toolTip">
<string>Defragment database file so that its size decreases.</string>
</property>
</action>
<action name="m_actionSwitchFeedsList">
<property name="checkable">
<bool>true</bool>
@ -649,6 +641,14 @@
<string>Send selected message via e-mail</string>
</property>
</action>
<action name="m_actionCleanupDatabase">
<property name="text">
<string>&amp;Cleanup database</string>
</property>
<property name="shortcut">
<string notr="true">Ctrl+Shift+Del</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

View File

@ -469,6 +469,10 @@ void MessagesView::searchMessages(const QString &pattern) {
if (selectionModel()->selectedRows().size() == 0) {
emit currentMessagesRemoved();
}
else {
// Scroll to selected message, it could become scrolled out due to filter change.
scrollTo(selectionModel()->selectedRows().at(0));
}
}
void MessagesView::filterMessages(MessagesModel::MessageFilter filter) {

View File

@ -100,6 +100,7 @@ void SystemTrayIcon::showPrivate() {
// Display the tray icon.
QSystemTrayIcon::show();
emit shown();
qDebug("Tray icon displayed.");
}

View File

@ -74,6 +74,9 @@ class SystemTrayIcon : public QSystemTrayIcon {
void showPrivate();
void onActivated(const QSystemTrayIcon::ActivationReason &reason);
signals:
void shown();
private:
QIcon m_normalIcon;
QPixmap m_plainPixmap;

View File

@ -143,6 +143,7 @@ void Application::processExecutionMessage(const QString &message) {
SystemTrayIcon *Application::trayIcon() {
if (m_trayIcon == NULL) {
m_trayIcon = new SystemTrayIcon(APP_ICON_PATH, APP_ICON_PLAIN_PATH, m_mainForm);
connect(m_trayIcon, SIGNAL(shown()), m_mainForm->tabWidget()->feedMessageViewer()->feedsView(), SLOT(notifyWithCounts()));
}
return m_trayIcon;
@ -151,10 +152,6 @@ SystemTrayIcon *Application::trayIcon() {
void Application::showTrayIcon() {
qDebug("Showing tray icon.");
trayIcon()->show();
if (m_mainForm != NULL) {
m_mainForm->tabWidget()->feedMessageViewer()->feedsView()->notifyWithCounts();
}
}
void Application::deleteTrayIcon() {

View File

@ -0,0 +1,26 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2015 by Martin Rotter <rotter.martinos@gmail.com>
//
// RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "miscellaneous/databasecleaner.h"
DatabaseCleaner::DatabaseCleaner(QObject *parent) : QObject(parent) {
}
DatabaseCleaner::~DatabaseCleaner() {
}

View File

@ -0,0 +1,36 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2015 by Martin Rotter <rotter.martinos@gmail.com>
//
// RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef DATABASECLEANER_H
#define DATABASECLEANER_H
#include <QObject>
class DatabaseCleaner : public QObject {
Q_OBJECT
public:
explicit DatabaseCleaner(QObject *parent = 0);
virtual ~DatabaseCleaner();
signals:
public slots:
};
#endif // DATABASECLEANER_H