Commit b7442f19 authored by Karel Slaný's avatar Karel Slaný

Merge branch 'zfo-storage-wip' into 'develop'

Add ZFO storage

See merge request !70
parents 0955098e 7ea3b201
......@@ -121,6 +121,7 @@ SOURCES += \
src/sqlite/file_db.cpp \
src/sqlite/message_db_container.cpp \
src/sqlite/message_db.cpp \
src/sqlite/zfo_db.cpp \
src/worker/emitter.cpp \
src/worker/pool.cpp \
src/worker/task.cpp \
......@@ -132,7 +133,8 @@ SOURCES += \
src/worker/task_find_databox.cpp \
src/worker/task_find_databox_fulltext.cpp \
src/worker/task_keep_alive.cpp \
src/worker/task_send_sms.cpp
src/worker/task_send_sms.cpp \
src/zfo.cpp
HEADERS += \
src/accounts.h \
......@@ -174,6 +176,7 @@ HEADERS += \
src/sqlite/file_db.h \
src/sqlite/message_db_container.h \
src/sqlite/message_db.h \
src/sqlite/zfo_db.h \
src/worker/emitter.h \
src/worker/pool.h \
src/worker/task.h \
......@@ -185,7 +188,8 @@ HEADERS += \
src/worker/task_find_databox.h \
src/worker/task_find_databox_fulltext.h \
src/worker/task_keep_alive.h \
src/worker/task_send_sms.h
src/worker/task_send_sms.h \
src/zfo.h
android {
SOURCES += \
......
......@@ -35,6 +35,8 @@ Item {
property var accountModel: null
property string sectionName: "storage"
property int currentZfoSize: 0
Component.onCompleted: {
settings.loadSettings(sectionName)
}
......@@ -66,8 +68,14 @@ Item {
anchors.fill: parent
onClicked: {
settings.updateSettingsStorage(messageLifeSpinBox.val().toString(),
attachLifeSpinBox.val().toString(), dbPathText.text.toString())
attachLifeSpinBox.val().toString(), zfoLifeSpinBox.value.toString(),
dbPathText.text.toString())
settings.saveAllSettings(accountModel)
// if ZFO storage limit was changed and it is less,
// reduce zfo database size
if (currentZfoSize > zfoLifeSpinBox.value) {
zfo.reduceZfoDbSize(currentZfoSize-zfoLifeSpinBox.value);
}
pageView.pop(StackView.Immediate)
}
}
......@@ -137,6 +145,30 @@ Item {
}
wrapMode: Text.Wrap
}
Text {
id: zfoLifeLabel
color: datovkaPalette.text
text: qsTr("ZFO storage size limit in MB")
}
SpinBox {
/* Holds value in days. */
id: zfoLifeSpinBox
height: inputItemHeight
font.pointSize: defaultTextFont.font.pointSize
from: 0
to: 1000
stepSize: 100
}
Text {
color: datovkaPalette.mid
width: parent.width
text: if (zfoLifeSpinBox.value === 0) {
qsTr("Message ZFO data won't be automatically stored.")
} else {
qsTr("Maximum size of stored message ZFO data is set to %1 MB. Default is %2 MB.").arg(zfoLifeSpinBox.value).arg(200)
}
wrapMode: Text.Wrap
}
Text {
id: dbPathLabel
color: datovkaPalette.text
......@@ -209,6 +241,8 @@ Item {
onSendSettingsStorageData: {
messageLifeSpinBox.setVal(msgLifeDays)
attachLifeSpinBox.setVal(fileLifeDays)
zfoLifeSpinBox.value = maxZfoSizeMB
currentZfoSize = maxZfoSizeMB
dbPathText.text = dbPath
dbPathLabel.visible = showChangeDbLocation
dbPathText.visible = showChangeDbLocation
......
......@@ -50,11 +50,13 @@
#include "src/qml_interaction/interaction_filesystem.h"
#include "src/qml_interaction/interaction_zfo_file.h"
#include "src/settings.h"
#include "src/setwrapper.h"
#include "src/sqlite/db_tables.h"
#include "src/sqlite/account_db.h"
#include "src/sqlite/message_db_container.h"
#include "src/sqlite/file_db_container.h"
#include "src/setwrapper.h"
#include "src/sqlite/message_db_container.h"
#include "src/sqlite/zfo_db.h"
#include "src/zfo.h"
/* iOS app_delegate - for interaction with iOS action Open in... */
#if defined Q_OS_IOS
......@@ -258,6 +260,7 @@ int main(int argc, char *argv[])
Files files;
IsdsWrapper isds;
GlobalSettingsQmlWrapper settings;
Zfo zfo;
/* Connect slot for isds cxt delete when account was deleted or updated */
QObject::connect(&accounts, SIGNAL(removeIsdsCtx(QString)),
......@@ -315,6 +318,7 @@ int main(int argc, char *argv[])
ctx->setContextProperty("locker", &locker);
ctx->setContextProperty("interactionZfoFile", &interactionZfoFile);
ctx->setContextProperty("dlgEmitter", QmlDlgHelper::dlgEmitter);
ctx->setContextProperty("zfo", &zfo);
/* register and set models in QML */
ctx->setContextProperty(accountModelPtr->objectName(), accountModelPtr);
......@@ -325,6 +329,7 @@ int main(int argc, char *argv[])
msgsTbl.reloadLocalisedDescription();
flsTbl.reloadLocalisedDescription();
evntsTbl.reloadLocalisedDescription();
msgZfoTbl.reloadLocalisedDescription();
/* init and open account database */
AccountDb globAccountDb("ACCOUNTS");
......@@ -344,6 +349,10 @@ int main(int argc, char *argv[])
FileDbContainer globFileDb("FILES");
globFileDbsPtr = &globFileDb;
/* init zfo db database */
ZfoDb globZfoDb("ZFOS");
globZfoDbPtr = &globZfoDb;
/* Load accounts from settings to account model. */
{
QSettings settings(Settings::settingsPath(),
......@@ -355,6 +364,14 @@ int main(int argc, char *argv[])
*/
}
/*
* Open ZFO database, the second parameter means: true = zfo db will
* store in disk, false = only in memory
*/
if (!globZfoDbPtr->openDb(ZFO_DB_NAME, (globSet.zfoDbSizeMBs > 0))) {
qDebug() << "ERROR: zfo db not found!";
}
/* load UI (QML) */
engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
......
......@@ -26,6 +26,7 @@
#include "src/net/db_wrapper.h"
#include "src/settings.h"
#include "src/sqlite/account_db.h"
#include "src/sqlite/zfo_db.h"
DbWrapper::DbWrapper(QObject *parent)
: QObject(parent)
......@@ -336,3 +337,10 @@ bool DbWrapper::insertMesasgeDeliveryInfoToDb(const QString &userName,
return ret;
}
bool DbWrapper::insertZfoToDb(qint64 msgId, bool isTestAccount, int zfoSize,
const QByteArray &zfoData)
{
return globZfoDbPtr->insertZfoToDb(msgId, isTestAccount, zfoSize,
zfoData.toBase64(), (globSet.zfoDbSizeMBs * 1000000));
}
......@@ -193,6 +193,18 @@ public:
bool insertMesasgeDeliveryInfoToDb(const QString &userName,
const QList<Messages::Event> &eventList, qint64 msgId,
QString &txt);
/*!
* @brief Insert or update zfo file info to db.
*
* @param[in] msgId message ID.
* @param[in] isTestAccount True if account is ISDS test enviroment.
* @param[in] zfoSize Real size of zfo in Bytes.
* @param[in] zfoData Zfo data.
* @return true if success.
*/
bool insertZfoToDb(qint64 msgId, bool isTestAccount, int zfoSize,
const QByteArray &zfoData);
};
......
......@@ -684,7 +684,8 @@ void IsdsWrapper::downloadMessage(MessageListModel *messageModel,
TaskDownloadMessage *task;
task = new (std::nothrow) TaskDownloadMessage(
m_isdsSession.isdsCtxMap[userName], &m_netLayer, &m_dbWrapper,
msgId, messageType, messageModel);
msgId, messageType, messageModel, (globSet.zfoDbSizeMBs > 0),
AccountListModel::globAccounts[userName].isTestAccount());
task->setAutoDelete(true);
m_workPool.assignLo(task);
}
......@@ -896,7 +897,9 @@ void IsdsWrapper::syncSingleAccount(const QVariant &acntModelVariant,
m_isdsSession.isdsCtxMap[userName], &m_netLayer, &m_dbWrapper,
msgDirect, (globSet.downloadOnlyNewMsgs) ? DOWNLOAD_NEW_MESSAGES : DOWNLOAD_ALL_MESSAGES,
1, MESSAGE_LIST_LIMIT, &m_workPool, messageModel, accountModel,
globSet.downloadCompleteMsgs, globSet.dbsLocation);
globSet.downloadCompleteMsgs, globSet.dbsLocation,
(globSet.zfoDbSizeMBs > 0),
AccountListModel::globAccounts[userName].isTestAccount());
task->setAutoDelete(true);
m_workPool.assignHi(task);
}
......@@ -556,7 +556,8 @@ bool XmlLayer::parseLoginResponse(const QByteArray &xmlData, QString &txt)
}
bool XmlLayer::parseSignedMessageDownloadResponse(const QByteArray &xmlData,
Messages::Message &msg, QList<Files::File> &fileList, QString &txt)
Messages::Message &msg, QList<Files::File> &fileList, QString &txt,
QByteArray &zfoData)
{
qDebug("%s()", __func__);
......@@ -585,6 +586,8 @@ bool XmlLayer::parseSignedMessageDownloadResponse(const QByteArray &xmlData,
/* decode signature from base64 and obtain something cms message */
QByteArray cmsData = QByteArray::fromBase64(signature);
zfoData = cmsData;
#ifdef Q_OS_WIN
QByteArray newRawData;
......
......@@ -285,11 +285,13 @@ public:
* @param[out] msg Envelope message structure.
* @param[out] fileList List of files structure.
* @param[out] txt Error description if something failed.
* @param[out] zfoData ZFO file content.
* @return true if success.
*/
static
bool parseSignedMessageDownloadResponse(const QByteArray &xmlData,
Messages::Message &msg, QList<Files::File> &fileList, QString &txt);
Messages::Message &msg, QList<Files::File> &fileList, QString &txt,
QByteArray &zfoData);
/*!
* @brief Parse getOwnerInfoFromLogin XML.
......
......@@ -45,6 +45,7 @@ Settings::Settings(void)
pinCode(),
pinInactTimeoutInSecs(DEFAULT_PIN_INACT_TIMEOUT),
dbsLocation(),
zfoDbSizeMBs(DEFAULT_ZFO_LIMIT_MB),
m_lastUpdate()
{
}
......@@ -60,6 +61,7 @@ void Settings::saveToSettings(QSettings &settings) const
settings.setValue(SETTINGS_COMPLETE_MSG, downloadCompleteMsgs);
settings.setValue(SETTINGS_MSG_LIFETIME_IN_DAYS, msgLifeTimeInDays);
settings.setValue(SETTINGS_FILE_LIFETIME_IN_DAYS, fileLifeTimeInDays);
settings.setValue(SETTINGS_ZFO_LIMIT_MB, zfoDbSizeMBs);
if (!_pinVal.isEmpty()) {
//settings.setValue(SETTINGS_PIN_VAL,
......@@ -110,6 +112,9 @@ void Settings::loadFromSettings(const QSettings &settings)
fileLifeTimeInDays = settings.value(
SETTINGS_GLOBAL_GROUP "/" SETTINGS_FILE_LIFETIME_IN_DAYS,
DEFAULT_FILE_LIFETIME).toInt();
zfoDbSizeMBs = settings.value(
SETTINGS_GLOBAL_GROUP "/" SETTINGS_ZFO_LIMIT_MB,
DEFAULT_ZFO_LIMIT_MB).toInt();
//_pinVal = QString::fromUtf8(QByteArray::fromBase64(
// settings.value(SETTINGS_GLOBAL_GROUP "/" SETTINGS_PIN_VAL,
......
......@@ -37,6 +37,7 @@
* attachment files stored in local database (in days)*/
#define DEFAULT_MSG_LIFETIME 90
#define DEFAULT_FILE_LIFETIME 10
#define DEFAULT_ZFO_LIMIT_MB 200
#define DEFAULT_PIN_INACT_TIMEOUT 0
/* Names of setting items in GLOBALS group in the datovka.conf file */
#define SETTINGS_GLOBAL_GROUP "GLOBALS"
......@@ -44,6 +45,7 @@
#define SETTINGS_COMPLETE_MSG "complete_msgs"
#define SETTINGS_MSG_LIFETIME_IN_DAYS "msg_lifetime"
#define SETTINGS_FILE_LIFETIME_IN_DAYS "file_lifetime"
#define SETTINGS_ZFO_LIMIT_MB "zfo_db_max_size"
//#define SETTINGS_PIN_VAL "pin_val" // Don't store readable PIN value into settings.
#define SETTINGS_PIN_ALG "pin_alg"
#define SETTINGS_PIN_SALT "pin_salt"
......@@ -125,7 +127,8 @@ public:
QByteArray pinSalt; /*!< Salt value used to generate PIN hash. */
QByteArray pinCode; /*!< Hashed PIN code. */
int pinInactTimeoutInSecs; /*!< Inactivity locking interval. */
QString dbsLocation;
QString dbsLocation; /*!< Path to databses location. */
int zfoDbSizeMBs; /*!< Zfo database max size in MB. */
private:
QString m_lastUpdate;
......
......@@ -86,8 +86,8 @@ void GlobalSettingsQmlWrapper::loadSettings(const QString &section)
// globSet.fileLifeTimeInDays, globSet.dbsLocation,
// true, showSetDefaulButton);
emit sendSettingsStorageData(globSet.msgLifeTimeInDays,
globSet.fileLifeTimeInDays, globSet.dbsLocation,
false, showSetDefaulButton);
globSet.fileLifeTimeInDays, globSet.zfoDbSizeMBs,
globSet.dbsLocation, false, showSetDefaulButton);
#endif
}
......@@ -113,10 +113,12 @@ void GlobalSettingsQmlWrapper::updateSettingsSync(bool downloadOnlyNewMsgs,
}
void GlobalSettingsQmlWrapper::updateSettingsStorage(const QString &msgLifeDays,
const QString &fileLifeDays, const QString &dbPath)
const QString &fileLifeDays, const QString &maxZfoSizeMB,
const QString &dbPath)
{
globSet.msgLifeTimeInDays = msgLifeDays.toInt();
globSet.fileLifeTimeInDays = fileLifeDays.toInt();
globSet.zfoDbSizeMBs = maxZfoSizeMB.toInt();
globSet.dbsLocation = dbPath;
}
......
......@@ -90,13 +90,15 @@ public:
/*!
* @brief Save storage settings from QML.
*
* @param[in] msgLifeDays - How many days are messages stored in db.
* @param[in] fileLifeDays - How many days are attachments stored in db.
* @param[in] dbPath - Current path to databases.
* @param[in] msgLifeDays How many days are messages stored in db.
* @param[in] fileLifeDays How many days are attachments stored in db.
* @param[in] maxZfoSizeMB Maximal size of zfo storage.
* @param[in] dbPath Current path to databases.
*/
Q_INVOKABLE
void updateSettingsStorage(const QString &msgLifeDays,
const QString &fileLifeDays, const QString &dbPath);
const QString &fileLifeDays, const QString &maxZfoSizeMB,
const QString &dbPath);
/*!
* @brief Save PIN settings from QML.
......@@ -195,15 +197,16 @@ signals:
/*!
* @brief Send current storage settings to QML.
*
* @param[in] msgLifeDays - How many days are messages stored in db.
* @param[in] fileLifeDays - How many days are attachments stored in db.
* @param[in] dbPath - Current path to databases for QML.
* @param[in] showChangeDbLocation - true = Allow changing of database location.
* @param[in] showSetDefaulButton - true = Show setDefaultLocation button.
* @param[in] msgLifeDays How many days are messages stored in db.
* @param[in] fileLifeDays How many days are attachments stored in db.
* @param[in] maxZfoSizeMB Maximal size of zfo storage.
* @param[in] dbPath Current path to databases for QML.
* @param[in] showChangeDbLocation True = Allow changing of database location.
* @param[in] showSetDefaulButton True = Show setDefaultLocation button.
*/
void sendSettingsStorageData(int msgLifeDays,
int fileLifeDays, QString dbPath, bool showChangeDbLocation,
bool showSetDefaulButton);
int fileLifeDays, int maxZfoSizeMB, QString dbPath,
bool showChangeDbLocation, bool showSetDefaulButton);
/*!
* @brief Send PIN verification result to QML.
......
/*
* Copyright (C) 2014-2016 CZ.NIC
* Copyright (C) 2014-2017 CZ.NIC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -104,7 +104,6 @@ SQLiteTbl accntinfTbl(AccntinfTbl::tabName, AccntinfTbl::knownAttrs,
AccntinfTbl::attrProps, AccntinfTbl::colConstraints,
AccntinfTbl::tblConstraint);
namespace UserinfTbl {
const QString tabName("user_info");
......@@ -169,7 +168,6 @@ SQLiteTbl userinfTbl(UserinfTbl::tabName, UserinfTbl::knownAttrs,
UserinfTbl::attrProps, UserinfTbl::colConstraints,
UserinfTbl::tblConstraint);
namespace MsgsTbl {
const QString tabName("messages");
......@@ -272,7 +270,6 @@ namespace MsgsTbl {
SQLiteTbl msgsTbl(MsgsTbl::tabName, MsgsTbl::knownAttrs, MsgsTbl::attrProps,
MsgsTbl::colConstraints, MsgsTbl::tblConstraint);
namespace EvntsTbl {
const QString tabName("events");
......@@ -308,7 +305,6 @@ namespace EvntsTbl {
SQLiteTbl evntsTbl(EvntsTbl::tabName, EvntsTbl::knownAttrs,
EvntsTbl::attrProps, EvntsTbl::colConstraints, EvntsTbl::tblConstraint);
namespace FlsTbl {
const QString tabName("files");
......@@ -359,3 +355,71 @@ namespace FlsTbl {
} /* namespace FlsTbl */
SQLiteTbl flsTbl(FlsTbl::tabName, FlsTbl::knownAttrs, FlsTbl::attrProps,
FlsTbl::colConstraints, FlsTbl::tblConstraint);
namespace MsgZfoTbl {
const QString tabName("message_zfos");
const QVector< QPair<QString, enum EntryType> > knownAttrs = {
{"dmID", DB_INTEGER}, /* NOT NULL*/
{"testEnv", DB_BOOLEAN}, /* NOT NULL */
{"lastAccessTime", DB_INTEGER}, /* NOT NULL*/
{"size", DB_INTEGER}, /* NOT NULL*/
{"data", DB_TEXT} /* NOT NULL*/
/*
* CHECK (testEnv IN (0, 1)),
* UNIQUE (dmID, testEnv)
*/
};
const QMap<QString, QString> colConstraints = {
{"dmID", "NOT NULL"},
{"testEnv", "NOT NULL"},
{"lastAccessTime", "NOT NULL"},
{"size", "NOT NULL"},
{"data", "NOT NULL"}
};
const QString &tblConstraint(
",\n"
" CHECK (testEnv IN (0, 1)),\n"
" UNIQUE (dmID, testEnv)"
);
const QMap<QString, SQLiteTbl::AttrProp> attrProps = {
{"dmID", {DB_INTEGER, ""}},
{"testEnv", {DB_BOOLEAN, ""}},
{"lastAccessTime", {DB_INTEGER, ""}},
{"size", {DB_INTEGER, ""}},
{"data", {DB_TEXT, ""}}
};
} /* namespace MsgZfoTbl */
SQLiteTbl msgZfoTbl(MsgZfoTbl::tabName, MsgZfoTbl::knownAttrs,
MsgZfoTbl::attrProps, MsgZfoTbl::colConstraints, MsgZfoTbl::tblConstraint);
namespace ZfoSizeCntTbl {
const QString tabName("zfo_size_cnt");
const QVector< QPair<QString, enum EntryType> > knownAttrs = {
{"id", DB_INTEGER},
{"totalSize", DB_INTEGER}
};
const QMap<QString, QString> colConstraints = {
{"id", "NOT NULL"},
{"totalSize", "NOT NULL"}
};
const QString &tblConstraint(
",\n"
" PRIMARY KEY (id),\n"
" CHECK (id = 0)"
);
const QMap<QString, SQLiteTbl::AttrProp> attrProps = {
{"id", {DB_INTEGER, ""}},
{"totalSize", {DB_INTEGER, ""}}
};
} /* namespace ZfoSizeCntTbl */
SQLiteTbl zfoSizeCntTbl(ZfoSizeCntTbl::tabName, ZfoSizeCntTbl::knownAttrs,
ZfoSizeCntTbl::attrProps, ZfoSizeCntTbl::colConstraints,
ZfoSizeCntTbl::tblConstraint);
/*
* Copyright (C) 2014-2016 CZ.NIC
* Copyright (C) 2014-2017 CZ.NIC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -43,4 +43,14 @@ extern SQLiteTbl evntsTbl; /*!< Table 'events'. */
*/
extern SQLiteTbl flsTbl; /*!< Table 'files'. */
/*
* Zfo database.
*/
extern SQLiteTbl msgZfoTbl; /*!< Table 'message_zfos'. */
/*
* Zfo database.
*/
extern SQLiteTbl zfoSizeCntTbl; /*!< Table 'zfo_size_cnt'. */
#endif /* _DB_TABLES_H_ */
/*
* Copyright (C) 2014-2017 CZ.NIC
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations including
* the two.
*/
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QStandardPaths>
#include "src/io/filesystem.h"
#include "src/sqlite/db_tables.h"
#include "src/sqlite/dbs.h"
#include "src/sqlite/zfo_db.h"
ZfoDb::ZfoDb(const QString &connectionName)
: SQLiteDb(connectionName)
{
}
bool ZfoDb::openDb(const QString &fileName, bool storeToDisk)
{
QString dirName(existingWritableLocation(
QStandardPaths::AppDataLocation));
if (storeToDisk && dirName.isEmpty() & fileName.isEmpty()) {
Q_ASSERT(0);
return false;
}
bool ret = SQLiteDb::openDb(
dirName + QDir::separator() + QDir::toNativeSeparators(fileName),
!storeToDisk, listOfTables());
if (!ret) {
return ret;
}
/* Insert zfo size count row into table if not exists */
QSqlQuery query(m_db);
QString queryStr = "SELECT count(*) FROM zfo_size_cnt";
if (!query.prepare(queryStr)) {
qCritical() << "Cannot prepare SQL query:" <<
query.lastError().text().toUtf8().constData();
goto fail;
}
if (query.exec() && query.isActive() && query.first() && query.isValid()) {
if (0 == query.value(0).toInt()) {
queryStr = "INSERT INTO zfo_size_cnt (id,totalSize) "
"VALUES (0,0)";
if (!query.prepare(queryStr)) {
qCritical() << "Cannot prepare SQL query:" <<
query.lastError().text().toUtf8().constData();
goto fail;
}
return query.exec();
}
return true;
} else {
qCritical() <<
"Cannot execute SQL query and/or read SQL data: %s.",
query.lastError().text().toUtf8().constData();
}
fail:
return false;
}
bool ZfoDb::deleteCurrentDbCreateNew(const QString &newLocDir)
{
bool open_ret;
/* Close database. */
m_db.close();
/* Backup old file name. */
QString oldFileName = fileName();
QFileInfo fi(oldFileName);
QString fileName = fi.fileName();
QString newFileName =
newLocDir + QDir::separator() + QDir::toNativeSeparators(fileName);
/* Fail if target equals the source. */
/* TODO -- Perform a more reliable check than string comparison. */
if (oldFileName == newFileName) {
return false;
}
/* Erase target if exists. */
QFile::remove(newFileName);
/*
* Open database in the new location.
* If error durring opening of new dabatase, open back old database.