Experimental feature: database/settings backup.
This commit is contained in:
parent
145a1d8e04
commit
11e74a0b6a
@ -75,6 +75,9 @@
|
||||
#define FEEDS_VIEW_INDENTATION 10
|
||||
#define ACCEPT_HEADER_FOR_FEED_DOWNLOADER "application/atom+xml,application/xml;q=0.9,text/xml;q=0.8,*/*;q=0.7"
|
||||
|
||||
#define BACKUP_SUFFIX_SETTINGS ".ini.backup"
|
||||
#define BACKUP_SUFFIX_DATABASE ".db.backup"
|
||||
|
||||
#define APP_DB_MYSQL_DRIVER "QMYSQL"
|
||||
#define APP_DB_MYSQL_INIT "db_init_mysql.sql"
|
||||
#define APP_DB_MYSQL_TEST "MySQLTest"
|
||||
|
@ -43,6 +43,7 @@ FormBackupDatabaseSettings::FormBackupDatabaseSettings(QWidget *parent) : QDialo
|
||||
|
||||
selectFolder(qApp->documentsFolderPath());
|
||||
m_ui->m_txtBackupName->lineEdit()->setText(QString(APP_LOW_NAME) + "_" + QDateTime::currentDateTime().toString("yyyyMMddHHmm"));
|
||||
m_ui->m_lblResult->setStatus(WidgetWithStatus::Warning, tr("No operation executed yet."), tr("No operation executed yet."));
|
||||
|
||||
if (qApp->database()->activeDatabaseDriver() != DatabaseFactory::SQLITE &&
|
||||
qApp->database()->activeDatabaseDriver() != DatabaseFactory::SQLITE_MEMORY) {
|
||||
@ -55,7 +56,20 @@ FormBackupDatabaseSettings::~FormBackupDatabaseSettings() {
|
||||
}
|
||||
|
||||
void FormBackupDatabaseSettings::performBackup() {
|
||||
// TODO: Backup.
|
||||
if (qApp->backupDatabaseSettings(m_ui->m_checkBackupDatabase->isChecked(),
|
||||
m_ui->m_checkBackupSettings->isChecked(),
|
||||
m_ui->m_lblSelectFolder->label()->text(),
|
||||
m_ui->m_txtBackupName->lineEdit()->text())) {
|
||||
m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok,
|
||||
tr("Backup was created successfully and stored in target folder."),
|
||||
tr("Backup was created successfully."));
|
||||
}
|
||||
else {
|
||||
m_ui->m_lblResult->setStatus(WidgetWithStatus::Error,
|
||||
tr("Backup failed, database and/or settings is probably not backed."),
|
||||
tr("Backup failed. Check the output folder if your database\nand/or "
|
||||
"settings were backed or not. Also make sure that target foder is writable."));
|
||||
}
|
||||
}
|
||||
|
||||
void FormBackupDatabaseSettings::selectFolder(QString path) {
|
||||
@ -64,7 +78,8 @@ void FormBackupDatabaseSettings::selectFolder(QString path) {
|
||||
}
|
||||
|
||||
if (!path.isEmpty()) {
|
||||
m_ui->m_lblSelectFolder->setStatus(WidgetWithStatus::Ok, QDir::toNativeSeparators(path), tr("Good destination folder is specified."));
|
||||
m_ui->m_lblSelectFolder->setStatus(WidgetWithStatus::Ok, QDir::toNativeSeparators(path),
|
||||
tr("Good destination folder is specified."));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,22 +140,6 @@
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>m_buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>FormBackupDatabaseSettings</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>199</x>
|
||||
<y>283</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>199</x>
|
||||
<y>149</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>m_buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "miscellaneous/application.h"
|
||||
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/iofactory.h"
|
||||
#include "gui/feedsview.h"
|
||||
#include "gui/feedmessageviewer.h"
|
||||
#include "gui/messagebox.h"
|
||||
@ -58,9 +59,34 @@ IconFactory *Application::icons() {
|
||||
return m_icons;
|
||||
}
|
||||
|
||||
bool Application::backupDatabaseSettings(bool backup_database, bool backup_settings,
|
||||
const QString &target_path, const QString &backup_name) {
|
||||
if (!QFileInfo(target_path).isWritable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool final_result = true;
|
||||
|
||||
if (backup_settings) {
|
||||
settings()->sync();
|
||||
final_result = final_result && IOFactory::copyFile(settings()->fileName(),
|
||||
target_path + QDir::separator() + backup_name + BACKUP_SUFFIX_SETTINGS);
|
||||
}
|
||||
|
||||
if (backup_database &&
|
||||
(database()->activeDatabaseDriver() == DatabaseFactory::SQLITE ||
|
||||
database()->activeDatabaseDriver() == DatabaseFactory::SQLITE_MEMORY)) {
|
||||
// We need to save the database first.
|
||||
database()->saveDatabase();
|
||||
final_result = final_result && IOFactory::copyFile(database()->sqliteDatabaseFilePath(),
|
||||
target_path + QDir::separator() + backup_name + BACKUP_SUFFIX_DATABASE);
|
||||
}
|
||||
|
||||
return final_result;
|
||||
}
|
||||
|
||||
void Application::processExecutionMessage(const QString &message) {
|
||||
qDebug("Received '%s' execution message from another application instance.",
|
||||
qPrintable(message));
|
||||
qDebug("Received '%s' execution message from another application instance.", qPrintable(message));
|
||||
|
||||
if (message == APP_IS_RUNNING) {
|
||||
if (SystemTrayIcon::isSystemTrayActivated()) {
|
||||
|
@ -145,6 +145,8 @@ class Application : public QtSingleApplication {
|
||||
return home_path;
|
||||
}
|
||||
|
||||
bool backupDatabaseSettings(bool backup_database, bool backup_settings, const QString &target_path, const QString &backup_name);
|
||||
|
||||
// Access to application tray icon. Always use this in cooperation with
|
||||
// SystemTrayIcon::isSystemTrayActivated().
|
||||
SystemTrayIcon *trayIcon();
|
||||
|
@ -82,9 +82,7 @@ QString DatabaseFactory::mysqlInterpretErrorCode(MySQLError error_code) {
|
||||
|
||||
void DatabaseFactory::sqliteAssemblyDatabaseFilePath() {
|
||||
if (qApp->settings()->type() == Settings::Portable) {
|
||||
m_sqliteDatabaseFilePath = qApp->applicationDirPath() +
|
||||
QDir::separator() +
|
||||
QString(APP_DB_SQLITE_PATH);
|
||||
m_sqliteDatabaseFilePath = qApp->applicationDirPath() + QDir::separator() + QString(APP_DB_SQLITE_PATH);
|
||||
}
|
||||
else {
|
||||
m_sqliteDatabaseFilePath = qApp->homeFolderPath() + QDir::separator() +
|
||||
@ -267,6 +265,9 @@ QSqlDatabase DatabaseFactory::sqliteInitializeFileBasedDatabase(const QString &c
|
||||
return database;
|
||||
}
|
||||
|
||||
QString DatabaseFactory::sqliteDatabaseFilePath() const {
|
||||
return m_sqliteDatabaseFilePath + QDir::separator() + APP_DB_SQLITE_FILE;
|
||||
}
|
||||
|
||||
QSqlDatabase DatabaseFactory::connection(const QString &connection_name,
|
||||
DesiredType desired_type) {
|
||||
@ -315,8 +316,7 @@ void DatabaseFactory::determineDriver() {
|
||||
"database_driver",
|
||||
APP_DB_SQLITE_DRIVER).toString();
|
||||
|
||||
if (db_driver == APP_DB_MYSQL_DRIVER &&
|
||||
QSqlDatabase::isDriverAvailable(APP_DB_SQLITE_DRIVER)) {
|
||||
if (db_driver == APP_DB_MYSQL_DRIVER && QSqlDatabase::isDriverAvailable(APP_DB_SQLITE_DRIVER)) {
|
||||
// User wants to use MySQL and MySQL is actually available. Use it.
|
||||
m_activeDatabaseDriver = MYSQL;
|
||||
|
||||
@ -355,8 +355,7 @@ QSqlDatabase DatabaseFactory::mysqlConnection(const QString &connection_name) {
|
||||
QSqlDatabase database;
|
||||
|
||||
if (QSqlDatabase::contains(connection_name)) {
|
||||
qDebug("MySQL connection '%s' is already active.",
|
||||
qPrintable(connection_name));
|
||||
qDebug("MySQL connection '%s' is already active.", qPrintable(connection_name));
|
||||
|
||||
// This database connection was added previously, no need to
|
||||
// setup its properties.
|
||||
@ -390,8 +389,7 @@ QSqlDatabase DatabaseFactory::mysqlConnection(const QString &connection_name) {
|
||||
|
||||
QSqlDatabase DatabaseFactory::mysqlInitializeDatabase(const QString &connection_name) {
|
||||
// Folders are created. Create new QSQLDatabase object.
|
||||
QSqlDatabase database = QSqlDatabase::addDatabase(APP_DB_MYSQL_DRIVER,
|
||||
connection_name);
|
||||
QSqlDatabase database = QSqlDatabase::addDatabase(APP_DB_MYSQL_DRIVER, connection_name);
|
||||
|
||||
database.setHostName(qApp->settings()->value(APP_CFG_DB, "mysql_hostname").toString());
|
||||
database.setPort(qApp->settings()->value(APP_CFG_DB, "mysql_port", APP_DB_MYSQL_PORT).toInt());
|
||||
@ -407,8 +405,7 @@ QSqlDatabase DatabaseFactory::mysqlInitializeDatabase(const QString &connection_
|
||||
|
||||
query_db.setForwardOnly(true);
|
||||
|
||||
if (!query_db.exec("USE rssguard") ||
|
||||
!query_db.exec("SELECT inf_value FROM Information WHERE inf_key = 'schema_version'")) {
|
||||
if (!query_db.exec("USE rssguard") || !query_db.exec("SELECT inf_value FROM Information WHERE inf_key = 'schema_version'")) {
|
||||
// If no "rssguard" database exists
|
||||
// or schema version is wrong, then initialize it.
|
||||
qWarning("Error occurred. MySQL database is not initialized. Initializing now.");
|
||||
@ -422,8 +419,7 @@ QSqlDatabase DatabaseFactory::mysqlInitializeDatabase(const QString &connection_
|
||||
qPrintable(APP_MISC_PATH));
|
||||
}
|
||||
|
||||
QStringList statements = QString(file_init.readAll()).split(APP_DB_COMMENT_SPLIT,
|
||||
QString::SkipEmptyParts);
|
||||
QStringList statements = QString(file_init.readAll()).split(APP_DB_COMMENT_SPLIT, QString::SkipEmptyParts);
|
||||
database.transaction();
|
||||
|
||||
foreach(const QString &statement, statements) {
|
||||
@ -441,8 +437,7 @@ QSqlDatabase DatabaseFactory::mysqlInitializeDatabase(const QString &connection_
|
||||
else {
|
||||
query_db.next();
|
||||
|
||||
qDebug("MySQL database connection '%s' seems to be established.",
|
||||
qPrintable(connection_name));
|
||||
qDebug("MySQL database connection '%s' seems to be established.", qPrintable(connection_name));
|
||||
qDebug("MySQL database has version '%s'.", qPrintable(query_db.value(0).toString()));
|
||||
}
|
||||
|
||||
@ -462,8 +457,7 @@ bool DatabaseFactory::mysqlVacuumDatabase() {
|
||||
return query_vacuum.exec("OPTIMIZE TABLE rssguard.feeds;") && query_vacuum.exec("OPTIMIZE TABLE rssguard.messages;");
|
||||
}
|
||||
|
||||
QSqlDatabase DatabaseFactory::sqliteConnection(const QString &connection_name,
|
||||
DatabaseFactory::DesiredType desired_type) {
|
||||
QSqlDatabase DatabaseFactory::sqliteConnection(const QString &connection_name, DatabaseFactory::DesiredType desired_type) {
|
||||
if (desired_type == DatabaseFactory::StrictlyInMemory ||
|
||||
(desired_type == DatabaseFactory::FromSettings && m_activeDatabaseDriver == SQLITE_MEMORY)) {
|
||||
// We request in-memory database (either user explicitly
|
||||
@ -498,8 +492,7 @@ QSqlDatabase DatabaseFactory::sqliteConnection(const QString &connection_name,
|
||||
QSqlDatabase database;
|
||||
|
||||
if (QSqlDatabase::contains(connection_name)) {
|
||||
qDebug("SQLite connection '%s' is already active.",
|
||||
qPrintable(connection_name));
|
||||
qDebug("SQLite connection '%s' is already active.", qPrintable(connection_name));
|
||||
|
||||
// This database connection was added previously, no need to
|
||||
// setup its properties.
|
||||
|
@ -74,6 +74,14 @@ class DatabaseFactory : public QObject {
|
||||
// Performs cleanup of the database.
|
||||
bool vacuumDatabase();
|
||||
|
||||
// Returns identification of currently active database driver.
|
||||
UsedDriver activeDatabaseDriver() const;
|
||||
|
||||
//
|
||||
// SQLITE stuff.
|
||||
//
|
||||
QString sqliteDatabaseFilePath() const;
|
||||
|
||||
//
|
||||
// MySQL stuff.
|
||||
//
|
||||
@ -85,8 +93,6 @@ class DatabaseFactory : public QObject {
|
||||
|
||||
QString mysqlInterpretErrorCode(MySQLError error_code);
|
||||
|
||||
UsedDriver activeDatabaseDriver() const;
|
||||
|
||||
private:
|
||||
//
|
||||
// GENERAL stuff.
|
||||
|
@ -25,6 +25,16 @@
|
||||
IOFactory::IOFactory() {
|
||||
}
|
||||
|
||||
bool IOFactory::copyFile(const QString &source, const QString &destination) {
|
||||
if (QFile::exists(destination)) {
|
||||
if (!QFile::remove(destination)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return QFile::copy(source, destination);
|
||||
}
|
||||
|
||||
bool IOFactory::removeFolder(const QString& directory_name,
|
||||
const QStringList& exception_file_list,
|
||||
const QStringList& exception_folder_list) {
|
||||
@ -59,7 +69,7 @@ bool IOFactory::removeFolder(const QString& directory_name,
|
||||
return result;
|
||||
}
|
||||
|
||||
bool IOFactory::copyFolder(QString source, QString destination) {
|
||||
bool IOFactory::copyFolder(const QString &source, const QString &destination) {
|
||||
QDir dir_source(source);
|
||||
|
||||
if (!dir_source.exists()) {
|
||||
|
@ -26,9 +26,11 @@ class IOFactory {
|
||||
IOFactory();
|
||||
|
||||
public:
|
||||
static bool copyFile(const QString &source, const QString &destination);
|
||||
|
||||
// Copy whole directory recursively.
|
||||
// Destination path is created if it does not exist.
|
||||
static bool copyFolder(QString source, QString destination);
|
||||
static bool copyFolder(const QString &source, const QString &destination);
|
||||
|
||||
// Removes directory recursively and skips given folders/files.
|
||||
static bool removeFolder(const QString &directory_name,
|
||||
|
Loading…
x
Reference in New Issue
Block a user