Work on cleaning, is able to vacuum in worker thread. Added GUI & logic.

This commit is contained in:
Martin Rotter 2015-06-05 09:24:50 +02:00
parent a0482868ca
commit 81d01f3cda
13 changed files with 368 additions and 67 deletions

View File

@ -56,7 +56,7 @@
#define ID_RECYCLE_BIN -2
#define TRAY_ICON_BUBBLE_TIMEOUT 20000
#define KEY_MESSAGES_VIEW "messages_view_column_"
#define CLOSE_LOCK_TIMEOUT 3000
#define CLOSE_LOCK_TIMEOUT 1500
#define DOWNLOAD_TIMEOUT 5000
#define MESSAGES_VIEW_DEFAULT_COL 170
#define FEEDS_VIEW_COLUMN_COUNT 2

View File

@ -22,6 +22,7 @@
#include "miscellaneous/systemfactory.h"
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/mutex.h"
#include "miscellaneous/databasecleaner.h"
#include "core/messagesproxymodel.h"
#include "core/feeddownloader.h"
#include "core/feedsmodelfeed.h"
@ -65,7 +66,8 @@ FeedMessageViewer::FeedMessageViewer(QWidget *parent)
m_messagesBrowser(new WebBrowser(this)),
m_dbCleanerThread(NULL),
m_feedDownloaderThread(NULL),
m_feedDownloader(NULL) {
m_feedDownloader(NULL),
m_dbCleaner(NULL) {
initialize();
initializeViews();
createConnections();
@ -78,6 +80,23 @@ FeedMessageViewer::~FeedMessageViewer() {
qDebug("Destroying FeedMessageViewer instance.");
}
DatabaseCleaner *FeedMessageViewer::databaseCleaner() {
if (m_dbCleaner == NULL) {
m_dbCleaner = new DatabaseCleaner();
m_dbCleanerThread = new QThread();
// Downloader setup.
qRegisterMetaType<CleanerOrders>("CleanerOrders");
m_dbCleaner->moveToThread(m_dbCleanerThread);
connect(m_dbCleanerThread, SIGNAL(finished()), m_dbCleanerThread, SLOT(deleteLater()));
// Connections are made, start the feed downloader thread.
m_dbCleanerThread->start();
}
return m_dbCleaner;
}
void FeedMessageViewer::saveSize() {
Settings *settings = qApp->settings();
@ -125,23 +144,38 @@ void FeedMessageViewer::quit() {
// Quit the feeds view (stops auto-update timer etc.).
m_feedsView->quit();
// Close worker threads.
if (m_feedDownloaderThread != NULL && m_feedDownloaderThread->isRunning()) {
qDebug("Quitting feed downloader thread.");
m_feedDownloaderThread->quit();
m_feedDownloaderThread->wait();
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();
m_dbCleanerThread->wait();
if (!m_dbCleanerThread->wait(CLOSE_LOCK_TIMEOUT)) {
qCritical("Database cleaner thread is running despite it was told to quit. Terminating it.");
m_dbCleanerThread->terminate();
}
}
// Close workers.
if (m_feedDownloader != NULL) {
qDebug("Feed downloader thread aborted. Deleting it from memory.");
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();
}
@ -407,10 +441,12 @@ void FeedMessageViewer::initializeViews() {
void FeedMessageViewer::showDbCleanupAssistant() {
if (qApp->feedUpdateLock()->tryLock()) {
QPointer<FormDatabaseCleanup> form_pointer = new FormDatabaseCleanup(this);
form_pointer.data()->setCleaner(databaseCleaner());
form_pointer.data()->exec();
delete form_pointer.data();
qApp->feedUpdateLock()->unlock();
m_messagesView->reloadSelections(true);
}
else {
qApp->showGuiMessage(tr("Cannot cleanup database"),

View File

@ -29,6 +29,7 @@ class MessagesToolBar;
class FeedsToolBar;
class FeedsView;
class FeedDownloader;
class DatabaseCleaner;
class FeedsModelFeed;
class QToolBar;
class QSplitter;
@ -64,6 +65,8 @@ class FeedMessageViewer : public TabContent {
return m_toolBarFeeds;
}
DatabaseCleaner *databaseCleaner();
// Loads/saves sizes and states of ALL
// underlying widgets, this contains primarily
// splitters, toolbar and views.
@ -145,6 +148,7 @@ class FeedMessageViewer : public TabContent {
QThread *m_feedDownloaderThread;
QThread *m_dbCleanerThread;
FeedDownloader *m_feedDownloader;
DatabaseCleaner *m_dbCleaner;
};
#endif // FEEDMESSAGEVIEWER_H

View File

@ -104,7 +104,7 @@
<locale language="English" country="UnitedStates"/>
</property>
<property name="currentIndex">
<number>0</number>
<number>3</number>
</property>
<widget class="QWidget" name="m_tabInfo">
<attribute name="title">
@ -132,8 +132,8 @@
<string notr="true">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="acceptRichText">
<bool>false</bool>
@ -166,12 +166,12 @@ p, li { white-space: pre-wrap; }
<rect>
<x>0</x>
<y>0</y>
<width>693</width>
<height>196</height>
<width>685</width>
<height>184</height>
</rect>
</property>
<property name="autoFillBackground">
<bool>false</bool>
<bool>true</bool>
</property>
<attribute name="label">
<string>GNU GPL License (applies to RSS Guard source code)</string>
@ -180,7 +180,16 @@ p, li { white-space: pre-wrap; }
<string>GNU GPL License</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@ -215,8 +224,8 @@ p, li { white-space: pre-wrap; }
<string notr="true">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans Mono'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif';&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans Mono'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
@ -234,14 +243,23 @@ p, li { white-space: pre-wrap; }
<x>0</x>
<y>0</y>
<width>83</width>
<height>72</height>
<height>69</height>
</rect>
</property>
<attribute name="label">
<string>BSD License (applies to QtSingleApplication source code)</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@ -276,8 +294,8 @@ p, li { white-space: pre-wrap; }
<string notr="true">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans Mono'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif';&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans Mono'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
@ -317,8 +335,8 @@ p, li { white-space: pre-wrap; }
<string notr="true">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="acceptRichText">
<bool>false</bool>
@ -342,7 +360,7 @@ p, li { white-space: pre-wrap; }
</widget>
<widget class="QWidget" name="m_tabPaths">
<attribute name="title">
<string>Paths</string>
<string>Resources</string>
</attribute>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">

View File

@ -2,9 +2,12 @@
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/databasefactory.h"
#include <QCloseEvent>
FormDatabaseCleanup::FormDatabaseCleanup(QWidget *parent) : QDialog(parent), m_ui(new Ui::FormDatabaseCleanup) {
FormDatabaseCleanup::FormDatabaseCleanup(QWidget *parent) : QDialog(parent), m_ui(new Ui::FormDatabaseCleanup), m_cleaner(NULL) {
m_ui->setupUi(this);
// Set flags and attributes.
@ -12,22 +15,100 @@ FormDatabaseCleanup::FormDatabaseCleanup(QWidget *parent) : QDialog(parent), m_u
setWindowIcon(qApp->icons()->fromTheme("cleanup-database"));
connect(m_ui->m_spinDays, SIGNAL(valueChanged(int)), this, SLOT(updateDaysSuffix(int)));
m_ui->m_spinDays->setValue(DEFAULT_DAYS_TO_DELETE_MSG);
// 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ě.
m_ui->m_lblResult->setStatus(WidgetWithStatus::Information, tr("I am ready."), tr("I am ready."));
loadDatabaseInfo();
}
FormDatabaseCleanup::~FormDatabaseCleanup() {
delete m_ui;
}
void FormDatabaseCleanup::setCleaner(DatabaseCleaner *cleaner) {
if (m_cleaner != NULL) {
disconnect(this, 0, m_cleaner, 0);
disconnect(m_cleaner, 0, this, 0);
}
m_cleaner = cleaner;
connect(m_ui->m_btnBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(startPurging()));
connect(this, SIGNAL(purgeRequested(CleanerOrders)), m_cleaner, SLOT(purgeDatabaseData(CleanerOrders)));
connect(m_cleaner, SIGNAL(purgeStarted()), this, SLOT(onPurgeStarted()));
connect(m_cleaner, SIGNAL(purgeProgress(int)), this, SLOT(onPurgeProgress(int)));
connect(m_cleaner, SIGNAL(purgeFinished(bool)), this, SLOT(onPurgeFinished(bool)));
}
void FormDatabaseCleanup::closeEvent(QCloseEvent *event) {
if (m_ui->m_progressBar->isEnabled()) {
event->ignore();
}
else {
QDialog::closeEvent(event);
}
}
void FormDatabaseCleanup::keyPressEvent(QKeyEvent *event) {
if (m_ui->m_progressBar->isEnabled()) {
event->ignore();
}
else {
QDialog::keyPressEvent(event);
}
}
void FormDatabaseCleanup::updateDaysSuffix(int number) {
m_ui->m_spinDays->setSuffix(tr(" day(s)", 0, number));
}
void FormDatabaseCleanup::startPurging() {
CleanerOrders orders;
orders.m_removeOldMessages = m_ui->m_checkRemoveOldMessages->isChecked();
orders.m_barrierForRemovingOldMessagesInDays = m_ui->m_spinDays->value();
orders.m_removeReadMessages = m_ui->m_checkRemoveReadMessages->isChecked();
orders.m_shrinkDatabase = m_ui->m_checkShrink->isEnabled() && m_ui->m_checkShrink->isChecked();
emit purgeRequested(orders);
}
void FormDatabaseCleanup::onPurgeStarted() {
m_ui->m_progressBar->setValue(0);
m_ui->m_progressBar->setEnabled(true);
m_ui->m_btnBox->setEnabled(false);
m_ui->m_lblResult->setStatus(WidgetWithStatus::Information, tr("Database cleanup is running."), tr("Database cleanup is running."));
}
void FormDatabaseCleanup::onPurgeProgress(int progress) {
m_ui->m_progressBar->setValue(progress);
}
void FormDatabaseCleanup::onPurgeFinished(bool finished) {
m_ui->m_progressBar->setEnabled(false);
m_ui->m_progressBar->setValue(0);
m_ui->m_btnBox->setEnabled(true);
if (finished) {
m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, tr("Database cleanup is completed."), tr("Database cleanup is completed."));
}
else {
m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, tr("Database cleanup failed."), tr("Database cleanup failed."));
}
loadDatabaseInfo();
}
void FormDatabaseCleanup::loadDatabaseInfo() {
qint64 db_size = qApp->database()->getDatabaseSize();
if (db_size > 0) {
m_ui->m_txtFileSize->setText(QString::number(db_size / 1000000.0) + " MB");
}
else {
m_ui->m_txtFileSize->setText("-");
}
m_ui->m_txtDatabaseType->setText(qApp->database()->humanDriverName(qApp->database()->activeDatabaseDriver()));
m_ui->m_checkShrink->setEnabled(qApp->database()->activeDatabaseDriver() == DatabaseFactory::SQLITE);
m_ui->m_checkShrink->setChecked(m_ui->m_checkShrink->isEnabled());
}

View File

@ -5,6 +5,8 @@
#include "ui_formdatabasecleanup.h"
#include "miscellaneous/databasecleaner.h"
namespace Ui {
class FormDatabaseCleanup;
@ -17,11 +19,29 @@ class FormDatabaseCleanup : public QDialog {
explicit FormDatabaseCleanup(QWidget *parent = 0);
virtual ~FormDatabaseCleanup();
void setCleaner(DatabaseCleaner *cleaner);
protected:
void closeEvent(QCloseEvent *event);
void keyPressEvent(QKeyEvent *event);
private slots:
void updateDaysSuffix(int number);
void startPurging();
void onPurgeStarted();
void onPurgeProgress(int progress);
void onPurgeFinished(bool finished);
signals:
void purgeRequested(const CleanerOrders &which_data);
private:
void loadDatabaseInfo();
private:
Ui::FormDatabaseCleanup *m_ui;
DatabaseCleaner *m_cleaner;
};
#endif // FORMDATABASECLEANUP_H

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
<height>313</height>
</rect>
</property>
<property name="windowTitle">
@ -21,7 +21,7 @@
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox_2">
<widget class="QCheckBox" name="m_checkShrink">
<property name="text">
<string>Shrink database file.</string>
</property>
@ -41,17 +41,23 @@
</spacer>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="checkBox_3">
<widget class="QCheckBox" name="m_checkRemoveOldMessages">
<property name="text">
<string>Remove all messages older than</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="checkBox">
<widget class="QCheckBox" name="m_checkRemoveReadMessages">
<property name="text">
<string>Remove all read messages.</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
@ -67,72 +73,136 @@
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Database information</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="m_lblFileSize">
<property name="text">
<string>Database file size</string>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="m_txtFileSize">
<property name="readOnly">
<bool>true</bool>
</property>
</spacer>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="m_lblDatabaseType">
<property name="text">
<string>Database type</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="m_txtDatabaseType">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QProgressBar" name="m_progressBar">
<property name="value">
<number>24</number>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Progress</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="LabelWithStatus" name="m_lblResult" native="true">
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="m_progressBar">
<property name="enabled">
<bool>false</bool>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="m_btnBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
<set>QDialogButtonBox::Close|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LabelWithStatus</class>
<extends>QWidget</extends>
<header>labelwithstatus.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>m_btnBox</sender>
<signal>accepted()</signal>
<signal>rejected()</signal>
<receiver>FormDatabaseCleanup</receiver>
<slot>accept()</slot>
<slot>close()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
<x>199</x>
<y>271</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
<x>199</x>
<y>145</y>
</hint>
</hints>
</connection>
<connection>
<sender>m_btnBox</sender>
<signal>rejected()</signal>
<receiver>FormDatabaseCleanup</receiver>
<slot>reject()</slot>
<sender>m_checkRemoveOldMessages</sender>
<signal>toggled(bool)</signal>
<receiver>m_spinDays</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
<x>107</x>
<y>87</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
<x>226</x>
<y>87</y>
</hint>
</hints>
</connection>

View File

@ -509,7 +509,7 @@ void FormSettings::loadDataStorage() {
m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Information, tr("No connection test triggered so far."), tr("You did not executed any connection test yet."));
// Load SQLite.
m_ui->m_cmbDatabaseDriver->addItem(tr("SQLite (embedded database)"), APP_DB_SQLITE_DRIVER);
m_ui->m_cmbDatabaseDriver->addItem(qApp->database()->humanDriverName(DatabaseFactory::SQLITE), APP_DB_SQLITE_DRIVER);
// Load in-memory database status.
Settings *settings = qApp->settings();
@ -523,7 +523,7 @@ void FormSettings::loadDataStorage() {
onMysqlDatabaseChanged(QString());
// Load MySQL.
m_ui->m_cmbDatabaseDriver->addItem(tr("MySQL/MariaDB (dedicated database)"), APP_DB_MYSQL_DRIVER);
m_ui->m_cmbDatabaseDriver->addItem(qApp->database()->humanDriverName(DatabaseFactory::MYSQL), APP_DB_MYSQL_DRIVER);
// Setup placeholders.
m_ui->m_txtMysqlHostname->lineEdit()->setPlaceholderText(tr("Hostname of your MySQL server"));

View File

@ -195,7 +195,7 @@ void Application::onSaveState(QSessionManager &manager) {
void Application::onAboutToQuit() {
// Make sure that we obtain close lock BEFORE even trying to quit the application.
bool locked_safely = feedUpdateLock()->tryLock(CLOSE_LOCK_TIMEOUT);
bool locked_safely = feedUpdateLock()->tryLock(4 * CLOSE_LOCK_TIMEOUT);
processEvents();

View File

@ -17,6 +17,12 @@
#include "miscellaneous/databasecleaner.h"
#include "miscellaneous/application.h"
#include "miscellaneous/databasefactory.h"
#include <QDebug>
#include <QThread>
DatabaseCleaner::DatabaseCleaner(QObject *parent) : QObject(parent) {
}
@ -24,3 +30,19 @@ DatabaseCleaner::DatabaseCleaner(QObject *parent) : QObject(parent) {
DatabaseCleaner::~DatabaseCleaner() {
}
void DatabaseCleaner::purgeDatabaseData(const CleanerOrders &which_data) {
qDebug().nospace() << "Performing database cleanup in thread: \'" << QThread::currentThreadId() << "\'.";
bool result = true;
int progress = 0;
emit purgeStarted();
if (which_data.m_shrinkDatabase) {
result &= qApp->database()->vacuumDatabase();
progress += 25;
emit purgeProgress(progress);
}
emit purgeFinished(result);
}

View File

@ -21,6 +21,13 @@
#include <QObject>
struct CleanerOrders {
bool m_removeReadMessages;
bool m_shrinkDatabase;
bool m_removeOldMessages;
int m_barrierForRemovingOldMessagesInDays;
};
class DatabaseCleaner : public QObject {
Q_OBJECT
@ -29,8 +36,12 @@ class DatabaseCleaner : public QObject {
virtual ~DatabaseCleaner();
signals:
void purgeStarted();
void purgeProgress(int progress);
void purgeFinished(bool result);
public slots:
void purgeDatabaseData(const CleanerOrders &which_data);
};
#endif // DATABASECLEANER_H

View File

@ -38,6 +38,16 @@ DatabaseFactory::DatabaseFactory(QObject *parent)
DatabaseFactory::~DatabaseFactory() {
}
qint64 DatabaseFactory::getDatabaseSize() {
if (m_activeDatabaseDriver == SQLITE || m_activeDatabaseDriver == SQLITE_MEMORY) {
qint64 size = QFileInfo(sqliteDatabaseFilePath()).size();
return size;
}
else {
return 0;
}
}
DatabaseFactory::MySQLError DatabaseFactory::mysqlTestConnection(const QString &hostname, int port, const QString &w_database,
const QString &username, const QString &password) {
QSqlDatabase database = QSqlDatabase::addDatabase(APP_DB_MYSQL_DRIVER, APP_DB_MYSQL_TEST);
@ -416,6 +426,30 @@ QSqlDatabase DatabaseFactory::connection(const QString &connection_name, Desired
}
}
QString DatabaseFactory::humanDriverName(DatabaseFactory::UsedDriver driver) {
switch (driver) {
case MYSQL:
return tr("MySQL/MariaDB (dedicated database)");
case SQLITE:
case SQLITE_MEMORY:
default:
return tr("SQLite (embedded database)");
}
}
QString DatabaseFactory::humanDriverName(const QString &driver_code) {
if (driver_code == APP_DB_SQLITE_DRIVER) {
return humanDriverName(SQLITE);
}
else if (driver_code == APP_DB_MYSQL_DRIVER) {
return humanDriverName(MYSQL);
}
else {
return humanDriverName(SQLITE);
}
}
void DatabaseFactory::removeConnection(const QString &connection_name) {
qDebug("Removing database connection '%s'.", qPrintable(connection_name));
QSqlDatabase::removeDatabase(connection_name);

View File

@ -60,11 +60,16 @@ class DatabaseFactory : public QObject {
// Destructor.
virtual ~DatabaseFactory();
qint64 getDatabaseSize();
// If in-memory is true, then :memory: database is returned
// In-memory database is DEFAULT database.
// NOTE: This always returns OPENED database.
QSqlDatabase connection(const QString &connection_name, DesiredType desired_type);
QString humanDriverName(UsedDriver driver);
QString humanDriverName(const QString &driver_code);
// Removes connection.
void removeConnection(const QString &connection_name = QString());