Switchable memory/file-based database.
This commit is contained in:
parent
d21b5318a1
commit
46979667a4
11 changed files with 189 additions and 41 deletions
|
@ -35,13 +35,13 @@ DatabaseFactory *DatabaseFactory::instance() {
|
|||
void DatabaseFactory::assemblyDatabaseFilePath() {
|
||||
if (Settings::instance()->type() == Settings::Portable) {
|
||||
m_databaseFilePath = qApp->applicationDirPath() +
|
||||
QDir::separator() +
|
||||
QString(APP_DB_PATH);
|
||||
QDir::separator() +
|
||||
QString(APP_DB_PATH);
|
||||
}
|
||||
else {
|
||||
m_databaseFilePath = QDir::homePath() + QDir::separator() +
|
||||
QString(APP_LOW_H_NAME) + QDir::separator() +
|
||||
QString(APP_DB_PATH);
|
||||
QString(APP_LOW_H_NAME) + QDir::separator() +
|
||||
QString(APP_DB_PATH);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,7 @@ QSqlDatabase DatabaseFactory::initializeInMemoryDatabase() {
|
|||
}
|
||||
|
||||
// Loading messages from file-based database.
|
||||
QSqlDatabase file_database = connection(objectName(), false);
|
||||
QSqlDatabase file_database = connection(objectName(), StrictlyFileBased);
|
||||
QSqlQuery copy_contents(database);
|
||||
|
||||
// Attach database.
|
||||
|
@ -135,7 +135,7 @@ QSqlDatabase DatabaseFactory::initializeInMemoryDatabase() {
|
|||
|
||||
QSqlDatabase DatabaseFactory::initializeFileBasedDatabase(const QString &connection_name) {
|
||||
// Prepare file paths.
|
||||
QDir db_path(getDatabasePath());
|
||||
QDir db_path(databaseFilePath());
|
||||
QFile db_file(db_path.absoluteFilePath(APP_DB_FILE));
|
||||
|
||||
// Check if database directory exists.
|
||||
|
@ -222,9 +222,11 @@ QSqlDatabase DatabaseFactory::initializeFileBasedDatabase(const QString &connect
|
|||
}
|
||||
|
||||
QSqlDatabase DatabaseFactory::connection(const QString &connection_name,
|
||||
bool in_memory) {
|
||||
if (in_memory) {
|
||||
// We request in-memory database.
|
||||
DesiredType desired_type) {
|
||||
if (desired_type == DatabaseFactory::StrictlyInMemory ||
|
||||
(desired_type == DatabaseFactory::FromSettings && m_inMemoryEnabled)) {
|
||||
// We request in-memory database (either user don't care
|
||||
// about the type or user overrided it in the settings).
|
||||
if (!m_inMemoryInitialized) {
|
||||
// It is not initialized yet.
|
||||
return initializeInMemoryDatabase();
|
||||
|
@ -267,7 +269,7 @@ QSqlDatabase DatabaseFactory::connection(const QString &connection_name,
|
|||
// yet, add it and set it up.
|
||||
database = QSqlDatabase::addDatabase(DATABASE_DRIVER, connection_name);
|
||||
|
||||
QDir db_path(getDatabasePath());
|
||||
QDir db_path(databaseFilePath());
|
||||
QFile db_file(db_path.absoluteFilePath(APP_DB_FILE));
|
||||
|
||||
// Setup database file path.
|
||||
|
@ -296,8 +298,14 @@ void DatabaseFactory::removeConnection(const QString &connection_name) {
|
|||
}
|
||||
|
||||
void DatabaseFactory::saveMemoryDatabase() {
|
||||
QSqlDatabase database = connection();
|
||||
QSqlDatabase file_database = connection(objectName(), false);
|
||||
if (!m_inMemoryEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("Saving in-memory working database back to persistent file-based storage.");
|
||||
|
||||
QSqlDatabase database = connection(objectName(), StrictlyInMemory);
|
||||
QSqlDatabase file_database = connection(objectName(), StrictlyFileBased);
|
||||
QSqlQuery copy_contents(database);
|
||||
|
||||
// Attach database.
|
||||
|
@ -316,3 +324,10 @@ void DatabaseFactory::saveMemoryDatabase() {
|
|||
copy_contents.exec("DETACH 'storage'");
|
||||
copy_contents.finish();
|
||||
}
|
||||
|
||||
void DatabaseFactory::determineInMemoryDatabase() {
|
||||
m_inMemoryEnabled = Settings::instance()->value(APP_CFG_GEN, "use_in_memory_db", false).toBool();
|
||||
|
||||
qDebug("Working database source was determined as %s.",
|
||||
m_inMemoryEnabled ? "in-memory database" : "file-based database");
|
||||
}
|
||||
|
|
|
@ -10,19 +10,26 @@ class DatabaseFactory : public QObject {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
// Describes what type of database user wants.
|
||||
enum DesiredType {
|
||||
StrictlyFileBased,
|
||||
StrictlyInMemory,
|
||||
FromSettings
|
||||
};
|
||||
|
||||
// Destructor.
|
||||
virtual ~DatabaseFactory();
|
||||
|
||||
// Returns absolute file path to database file.
|
||||
inline QString getDatabasePath() {
|
||||
inline QString databaseFilePath() {
|
||||
return m_databaseFilePath;
|
||||
}
|
||||
|
||||
// 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 = QString(),
|
||||
bool in_memory = true);
|
||||
QSqlDatabase connection(const QString &connection_name,
|
||||
DesiredType desired_type);
|
||||
|
||||
// Removes connection.
|
||||
void removeConnection(const QString &connection_name = QString());
|
||||
|
@ -31,6 +38,9 @@ class DatabaseFactory : public QObject {
|
|||
// to file-based database.
|
||||
void saveMemoryDatabase();
|
||||
|
||||
// Sets m_inMemoryEnabled according to user settings.
|
||||
void determineInMemoryDatabase();
|
||||
|
||||
// Singleton getter.
|
||||
static DatabaseFactory *instance();
|
||||
|
||||
|
@ -53,6 +63,10 @@ class DatabaseFactory : public QObject {
|
|||
bool m_fileBasedinitialized;
|
||||
bool m_inMemoryInitialized;
|
||||
|
||||
// Is true when user selected in-memory database.
|
||||
// NOTE: This is set only on application startup.
|
||||
bool m_inMemoryEnabled;
|
||||
|
||||
// Private singleton value.
|
||||
static QPointer<DatabaseFactory> s_instance;
|
||||
};
|
||||
|
|
|
@ -176,7 +176,7 @@ QList<Message> FeedsModel::messagesForFeeds(const QList<FeedsModelFeed*> &feeds)
|
|||
QList<Message> messages;
|
||||
|
||||
QSqlDatabase database = DatabaseFactory::instance()->connection(objectName(),
|
||||
false);
|
||||
DatabaseFactory::FromSettings);
|
||||
QSqlQuery query_read_msg(database);
|
||||
query_read_msg.setForwardOnly(true);
|
||||
query_read_msg.prepare("SELECT title, url, author, date_created, contents "
|
||||
|
@ -319,7 +319,7 @@ void FeedsModel::loadFromDatabase() {
|
|||
m_rootItem->clearChildren();
|
||||
|
||||
QSqlDatabase database = DatabaseFactory::instance()->connection(objectName(),
|
||||
false);
|
||||
DatabaseFactory::FromSettings);
|
||||
CategoryAssignment categories;
|
||||
FeedAssignment feeds;
|
||||
|
||||
|
@ -432,7 +432,7 @@ QList<FeedsModelFeed*> FeedsModel::feedsForIndexes(const QModelIndexList &indexe
|
|||
bool FeedsModel::markFeedsRead(const QList<FeedsModelFeed*> &feeds,
|
||||
int read) {
|
||||
QSqlDatabase db_handle = DatabaseFactory::instance()->connection(objectName(),
|
||||
false);
|
||||
DatabaseFactory::FromSettings);
|
||||
|
||||
if (!db_handle.transaction()) {
|
||||
qWarning("Starting transaction for feeds read change.");
|
||||
|
@ -469,7 +469,7 @@ bool FeedsModel::markFeedsRead(const QList<FeedsModelFeed*> &feeds,
|
|||
bool FeedsModel::markFeedsDeleted(const QList<FeedsModelFeed *> &feeds,
|
||||
int deleted) {
|
||||
QSqlDatabase db_handle = DatabaseFactory::instance()->connection(objectName(),
|
||||
false);
|
||||
DatabaseFactory::FromSettings);
|
||||
|
||||
if (!db_handle.transaction()) {
|
||||
qWarning("Starting transaction for feeds clearing.");
|
||||
|
|
|
@ -48,7 +48,7 @@ QString FeedsModelFeed::typeToString(FeedsModelFeed::Type type) {
|
|||
|
||||
void FeedsModelFeed::updateCounts(bool including_total_count) {
|
||||
QSqlDatabase database = DatabaseFactory::instance()->connection("FeedsModelFeed",
|
||||
false);
|
||||
DatabaseFactory::FromSettings);
|
||||
QSqlQuery query_all(database);
|
||||
query_all.setForwardOnly(true);
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ QVariant FeedsModelStandardCategory::data(int column, int role) const {
|
|||
bool FeedsModelStandardCategory::addItself() {
|
||||
// Children are removed, remove this standard category too.
|
||||
QSqlDatabase database = DatabaseFactory::instance()->connection("FeedsModelStandardCategory",
|
||||
false);
|
||||
DatabaseFactory::FromSettings);
|
||||
QSqlQuery query_add(database);
|
||||
|
||||
query_add.setForwardOnly(true);
|
||||
|
@ -139,7 +139,7 @@ bool FeedsModelStandardCategory::removeItself() {
|
|||
|
||||
// Children are removed, remove this standard category too.
|
||||
QSqlDatabase database = DatabaseFactory::instance()->connection("FeedsModelStandardCategory",
|
||||
false);
|
||||
DatabaseFactory::FromSettings);
|
||||
QSqlQuery query_remove(database);
|
||||
|
||||
query_remove.setForwardOnly(true);
|
||||
|
|
|
@ -164,7 +164,7 @@ void FeedsModelStandardFeed::update() {
|
|||
|
||||
bool FeedsModelStandardFeed::removeItself() {
|
||||
QSqlDatabase database = DatabaseFactory::instance()->connection("FeedsModelStandardFeed",
|
||||
false);
|
||||
DatabaseFactory::FromSettings);
|
||||
QSqlQuery query_remove(database);
|
||||
|
||||
query_remove.setForwardOnly(true);
|
||||
|
@ -188,7 +188,7 @@ void FeedsModelStandardFeed::updateMessages(const QList<Message> &messages) {
|
|||
int feed_id = id(), message_id;
|
||||
qint64 message_creation_date;
|
||||
QSqlDatabase database = DatabaseFactory::instance()->connection("FeedsModelStandardFeed",
|
||||
false);
|
||||
DatabaseFactory::FromSettings);
|
||||
|
||||
// Prepare queries.
|
||||
QSqlQuery query_select(database);
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
MessagesModel::MessagesModel(QObject *parent)
|
||||
: QSqlTableModel(parent,
|
||||
DatabaseFactory::instance()->connection("MessagesModel",
|
||||
false)) {
|
||||
DatabaseFactory::FromSettings)) {
|
||||
setObjectName("MessagesModel");
|
||||
|
||||
setupFonts();
|
||||
|
|
|
@ -193,7 +193,7 @@ void FormMain::onAboutToQuit() {
|
|||
|
||||
m_ui->m_tabWidget->feedMessageViewer()->quitDownloader();
|
||||
|
||||
//DatabaseFactory::instance()->saveMemoryDatabase();
|
||||
DatabaseFactory::instance()->saveMemoryDatabase();
|
||||
|
||||
saveSize();
|
||||
}
|
||||
|
|
|
@ -437,6 +437,9 @@ void FormSettings::loadGeneral() {
|
|||
tr(" (not supported on this platform)"));
|
||||
break;
|
||||
}
|
||||
|
||||
// Load in-memory database status.
|
||||
m_ui->m_cmbUseInMemoryDatabase->setChecked(Settings::instance()->value(APP_CFG_GEN, "use_in_memory_db", false).toBool());
|
||||
}
|
||||
|
||||
void FormSettings::saveGeneral() {
|
||||
|
@ -448,6 +451,16 @@ void FormSettings::saveGeneral() {
|
|||
else {
|
||||
SystemFactory::getInstance()->setAutoStartStatus(SystemFactory::Disabled);
|
||||
}
|
||||
|
||||
// Setup in-memory database status.
|
||||
bool original_inmemory = Settings::instance()->value(APP_CFG_GEN, "use_in_memory_db", false).toBool();
|
||||
bool new_inmemory = m_ui->m_cmbUseInMemoryDatabase->isChecked();
|
||||
|
||||
if (original_inmemory != new_inmemory) {
|
||||
m_changedDataTexts.append(tr("in-memory database switched"));
|
||||
}
|
||||
|
||||
Settings::instance()->setValue(APP_CFG_GEN, "use_in_memory_db", new_inmemory);
|
||||
}
|
||||
|
||||
void FormSettings::loadInterface() {
|
||||
|
|
|
@ -21,7 +21,16 @@
|
|||
</property>
|
||||
<widget class="QWidget" name="m_pageGeneral">
|
||||
<layout class="QFormLayout" name="formLayout_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 row="0" column="0">
|
||||
|
@ -31,11 +40,53 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="m_cmbUseInMemoryDatabase">
|
||||
<property name="text">
|
||||
<string>Use in-memory database as the working database</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Usage of in-memory working database has several advantages and pitfalls. Make sure that you are familiar with these before you turn this feature on. Advantages:
|
||||
<ul>
|
||||
<li>higher speed for feed/message manipulations (especially with thousands of messages displayed),</li>
|
||||
<li>whole database stored in RAM, thus your hard drive can rest more.</li>
|
||||
</ul>
|
||||
Disadvantages:
|
||||
<ul>
|
||||
<li>if application crashes, your changes from last session are lost,</li>
|
||||
<li>application startup and shutdown can take little longer (max. 2 seconds).</li>
|
||||
</ul>
|
||||
Authors of this application are NOT responsible for lost data.</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="indent">
|
||||
<number>20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="m_pageShortcuts">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_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>
|
||||
|
@ -51,12 +102,21 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>576</width>
|
||||
<height>373</height>
|
||||
<width>564</width>
|
||||
<height>363</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<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>
|
||||
|
@ -70,7 +130,16 @@
|
|||
</widget>
|
||||
<widget class="QWidget" name="m_pageUi">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<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>
|
||||
|
@ -86,7 +155,16 @@
|
|||
<string>Icons && skins</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<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>
|
||||
|
@ -102,8 +180,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>568</width>
|
||||
<height>344</height>
|
||||
<width>558</width>
|
||||
<height>337</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
|
@ -301,7 +379,16 @@
|
|||
</widget>
|
||||
<widget class="QWidget" name="m_pageLanguages">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<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>
|
||||
|
@ -330,7 +417,16 @@
|
|||
</widget>
|
||||
<widget class="QWidget" name="m_pageProxy">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_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>
|
||||
|
@ -387,7 +483,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QLabel" name="m_lblMouseGestures">
|
||||
<property name="text">
|
||||
<string>Mouse gestures work with middle mouse button. Possible gestures are:
|
||||
|
@ -559,7 +655,16 @@
|
|||
</widget>
|
||||
<widget class="QWidget" name="m_pageFeedsMessages">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||
<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>
|
||||
|
@ -655,8 +760,6 @@
|
|||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>groupBox_3</zorder>
|
||||
<zorder>label</zorder>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -74,6 +74,9 @@ int main(int argc, char *argv[]) {
|
|||
IconThemeFactory::instance()->loadCurrentIconTheme();
|
||||
SkinFactory::instance()->loadCurrentSkin();
|
||||
|
||||
// Decide whether user decided to use in-memory database or not.
|
||||
DatabaseFactory::instance()->determineInMemoryDatabase();
|
||||
|
||||
// Load localization and setup locale before any widget is constructed.
|
||||
LoadLocalization();
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue