diff options
| author | 2014-12-06 17:33:25 -0500 | |
|---|---|---|
| committer | 2014-12-06 17:33:25 -0500 | |
| commit | 7167ce41b61d2ba2cdb526777a4233eb84a3b66a (patch) | |
| tree | a35c14143716e1f2c98f808c81f89426045a946f /Plugins/ConfigMigration | |
Imported Upstream version 2.99.6upstream/2.99.6
Diffstat (limited to 'Plugins/ConfigMigration')
| -rw-r--r-- | Plugins/ConfigMigration/ConfigMigration.pro | 31 | ||||
| -rw-r--r-- | Plugins/ConfigMigration/config_migration.png | bin | 0 -> 24844 bytes | |||
| -rw-r--r-- | Plugins/ConfigMigration/configmigartion.json | 0 | ||||
| -rw-r--r-- | Plugins/ConfigMigration/configmigration.cpp | 188 | ||||
| -rw-r--r-- | Plugins/ConfigMigration/configmigration.h | 49 | ||||
| -rw-r--r-- | Plugins/ConfigMigration/configmigration.json | 8 | ||||
| -rw-r--r-- | Plugins/ConfigMigration/configmigration.qrc | 5 | ||||
| -rw-r--r-- | Plugins/ConfigMigration/configmigration_global.h | 12 | ||||
| -rw-r--r-- | Plugins/ConfigMigration/configmigrationitem.h | 20 | ||||
| -rw-r--r-- | Plugins/ConfigMigration/configmigrationwizard.cpp | 407 | ||||
| -rw-r--r-- | Plugins/ConfigMigration/configmigrationwizard.h | 52 | ||||
| -rw-r--r-- | Plugins/ConfigMigration/configmigrationwizard.ui | 109 |
12 files changed, 881 insertions, 0 deletions
diff --git a/Plugins/ConfigMigration/ConfigMigration.pro b/Plugins/ConfigMigration/ConfigMigration.pro new file mode 100644 index 0000000..965cfeb --- /dev/null +++ b/Plugins/ConfigMigration/ConfigMigration.pro @@ -0,0 +1,31 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-09-15T15:02:05 +# +#------------------------------------------------- + +include($$PWD/../../SQLiteStudio3/plugins.pri) + +QT += widgets + +TARGET = ConfigMigration +TEMPLATE = lib + +DEFINES += CONFIGMIGRATION_LIBRARY + +SOURCES += configmigration.cpp \ + configmigrationwizard.cpp + +HEADERS += configmigration.h\ + configmigration_global.h \ + configmigrationwizard.h \ + configmigrationitem.h + +OTHER_FILES += \ + configmigration.json + +FORMS += \ + configmigrationwizard.ui + +RESOURCES += \ + configmigration.qrc diff --git a/Plugins/ConfigMigration/config_migration.png b/Plugins/ConfigMigration/config_migration.png Binary files differnew file mode 100644 index 0000000..eb75995 --- /dev/null +++ b/Plugins/ConfigMigration/config_migration.png diff --git a/Plugins/ConfigMigration/configmigartion.json b/Plugins/ConfigMigration/configmigartion.json new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Plugins/ConfigMigration/configmigartion.json diff --git a/Plugins/ConfigMigration/configmigration.cpp b/Plugins/ConfigMigration/configmigration.cpp new file mode 100644 index 0000000..cd49d24 --- /dev/null +++ b/Plugins/ConfigMigration/configmigration.cpp @@ -0,0 +1,188 @@ +#include "configmigration.h" +#include "services/notifymanager.h" +#include "sqlitestudio.h" +#include "mainwindow.h" +#include "statusfield.h" +#include "configmigrationwizard.h" +#include "db/dbsqlite3.h" +#include <QCoreApplication> +#include <QDir> +#include <QFileInfo> +#include <QDebug> + +ConfigMigration::ConfigMigration() +{ +} + +bool ConfigMigration::init() +{ + Q_INIT_RESOURCE(configmigration); + + if (cfg.CfgMigration.Migrated.get()) + { + qDebug() << "ConfigMigration: already migrated. Skipping."; + return true; + } + + QString oldCfg = findOldConfig(); + if (!oldCfg.isNull()) + { + db = new DbSqlite3("Old SQLiteStudio settings", oldCfg, {{DB_PURE_INIT, true}}); + if (db->open()) + { + itemsToMigrate = findItemsToMigrate(); + notifyInfo(tr("A configuration from old SQLiteStudio 2.x.x has been detected. " + "Would you like to migrate old settings into the current version? " + "<a href=\"%1\">Click here to do that</a>.").arg(ACTION_LINK)); + + connect(MAINWINDOW->getStatusField(), SIGNAL(linkActivated(QString)), this, SLOT(linkActivated(QString))); + db->close(); + } + } + + return true; +} + +void ConfigMigration::deinit() +{ + Q_CLEANUP_RESOURCE(configmigration); + safe_delete(db); + + for (ConfigMigrationItem* item : itemsToMigrate) + delete item; + + itemsToMigrate.clear(); + GenericPlugin::deinit(); +} + +QString ConfigMigration::findOldConfig() +{ + QString output; + QString dirPath; + + // Portable path 1 check + dirPath = QDir::currentPath() + "/sqlitestudio-cfg"; + if (checkOldDir(dirPath, output)) + return output; + + // Portable path 2 check + dirPath = QCoreApplication::applicationDirPath() + "/sqlitestudio-cfg"; + if (checkOldDir(dirPath, output)) + return output; + + // Portable path 3 check + dirPath = QCoreApplication::applicationDirPath() + "/../sqlitestudio-cfg"; + if (checkOldDir(dirPath, output)) + return output; + + if (getDistributionType() == DistributionType::OSX_BOUNDLE) + { + // Portable path 4 check + dirPath = QCoreApplication::applicationDirPath() + "/../../sqlitestudio-cfg"; + if (checkOldDir(dirPath, output)) + return output; + + // Portable path 5 check + dirPath = QCoreApplication::applicationDirPath() + "/../../../sqlitestudio-cfg"; + if (checkOldDir(dirPath, output)) + return output; + } + + // Global path check +#ifdef Q_OS_WIN + if (QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) + dirPath = SQLITESTUDIO->getEnv("APPDATA")+"/sqlitestudio"; + else + dirPath = SQLITESTUDIO->getEnv("HOME")+"/sqlitestudio"; +#else + dirPath = SQLITESTUDIO->getEnv("HOME")+"/.sqlitestudio"; +#endif + + if (checkOldDir(dirPath, output)) + return output; + + return QString(); +} + +bool ConfigMigration::checkOldDir(const QString &dir, QString &output) +{ + QFileInfo fi(dir + "/settings"); + if (fi.exists() && fi.isReadable()) + { + output = fi.absoluteFilePath(); + return true; + } + + return false; +} + +QList<ConfigMigrationItem*> ConfigMigration::findItemsToMigrate() +{ + static_qstring(bugsHistoryQuery, "SELECT count(*) FROM bugs"); + static_qstring(dbListQuery, "SELECT count(*) FROM dblist"); + static_qstring(funcListQuery, "SELECT count(*) FROM functions"); + static_qstring(sqlHistoryQuery, "SELECT count(*) FROM history"); + + ConfigMigrationItem* item = nullptr; + QList<ConfigMigrationItem*> results; + + int bugReports = db->exec(bugsHistoryQuery)->getSingleCell().toInt(); + if (bugReports > 0) + { + item = new ConfigMigrationItem; + item->type = ConfigMigrationItem::Type::BUG_REPORTS; + item->label = tr("Bug reports history (%1)").arg(bugReports); + results << item; + } + + int dbCount = db->exec(dbListQuery)->getSingleCell().toInt(); + if (dbCount > 0) + { + item = new ConfigMigrationItem; + item->type = ConfigMigrationItem::Type::DATABASES; + item->label = tr("Database list (%1)").arg(dbCount); + results << item; + } + + int funcCount = db->exec(funcListQuery)->getSingleCell().toInt(); + if (funcCount > 0) + { + item = new ConfigMigrationItem; + item->type = ConfigMigrationItem::Type::FUNCTION_LIST; + item->label = tr("Custom SQL functions (%1)").arg(funcCount); + results << item; + } + + int sqlHistory = db->exec(sqlHistoryQuery)->getSingleCell().toInt(); + if (sqlHistory > 0) + { + item = new ConfigMigrationItem; + item->type = ConfigMigrationItem::Type::SQL_HISTORY; + item->label = tr("SQL queries history (%1)").arg(sqlHistory); + results << item; + } + + return results; +} + +Db* ConfigMigration::getOldCfgDb() const +{ + return db; +} + +QList<ConfigMigrationItem*> ConfigMigration::getItemsToMigrate() const +{ + return itemsToMigrate; +} + +void ConfigMigration::linkActivated(const QString &link) +{ + if (link != ACTION_LINK) + return; + + ConfigMigrationWizard wizard(MAINWINDOW, this); + wizard.exec(); + + if (wizard.didMigrate()) + cfg.CfgMigration.Migrated.set(true); +} diff --git a/Plugins/ConfigMigration/configmigration.h b/Plugins/ConfigMigration/configmigration.h new file mode 100644 index 0000000..828de3d --- /dev/null +++ b/Plugins/ConfigMigration/configmigration.h @@ -0,0 +1,49 @@ +#ifndef CONFIGMIGRATION_H +#define CONFIGMIGRATION_H + +#include "configmigration_global.h" +#include "plugins/generalpurposeplugin.h" +#include "plugins/genericplugin.h" +#include "configmigrationitem.h" +#include "config_builder.h" +#include <QList> + +class Db; + +CFG_CATEGORIES(ConfigMigration, + CFG_CATEGORY(CfgMigration, + CFG_ENTRY(bool, Migrated, false); + ) +) + +class CONFIGMIGRATIONSHARED_EXPORT ConfigMigration : public GenericPlugin, public GeneralPurposePlugin +{ + Q_OBJECT + SQLITESTUDIO_PLUGIN("configmigration.json") + + public: + ConfigMigration(); + + bool init(); + void deinit(); + + QList<ConfigMigrationItem*> getItemsToMigrate() const; + + Db* getOldCfgDb() const; + + private: + QString findOldConfig(); + bool checkOldDir(const QString& dir, QString& output); + QList<ConfigMigrationItem*> findItemsToMigrate(); + + static const constexpr char* ACTION_LINK = "migrateOldConfig"; + + Db* db = nullptr; + QList<ConfigMigrationItem*> itemsToMigrate; + CFG_LOCAL_PERSISTABLE(ConfigMigration, cfg) + + private slots: + void linkActivated(const QString& link); +}; + +#endif // CONFIGMIGRATION_H diff --git a/Plugins/ConfigMigration/configmigration.json b/Plugins/ConfigMigration/configmigration.json new file mode 100644 index 0000000..14e5d4b --- /dev/null +++ b/Plugins/ConfigMigration/configmigration.json @@ -0,0 +1,8 @@ +{ + "type": "GeneralPurposePlugin", + "title": "Configuration migration", + "description": "Performs migration from SQLiteStudio 2.1.x configuration to version 3.0.0.", + "version": 10001, + "author": "SalSoft", + "gui": true +} diff --git a/Plugins/ConfigMigration/configmigration.qrc b/Plugins/ConfigMigration/configmigration.qrc new file mode 100644 index 0000000..9df7d5e --- /dev/null +++ b/Plugins/ConfigMigration/configmigration.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/icons"> + <file>config_migration.png</file> + </qresource> +</RCC> diff --git a/Plugins/ConfigMigration/configmigration_global.h b/Plugins/ConfigMigration/configmigration_global.h new file mode 100644 index 0000000..7c43a97 --- /dev/null +++ b/Plugins/ConfigMigration/configmigration_global.h @@ -0,0 +1,12 @@ +#ifndef CONFIGMIGRATION_GLOBAL_H +#define CONFIGMIGRATION_GLOBAL_H + +#include <QtCore/qglobal.h> + +#if defined(CONFIGMIGRATION_LIBRARY) +# define CONFIGMIGRATIONSHARED_EXPORT Q_DECL_EXPORT +#else +# define CONFIGMIGRATIONSHARED_EXPORT Q_DECL_IMPORT +#endif + +#endif // CONFIGMIGRATION_GLOBAL_H diff --git a/Plugins/ConfigMigration/configmigrationitem.h b/Plugins/ConfigMigration/configmigrationitem.h new file mode 100644 index 0000000..ef08065 --- /dev/null +++ b/Plugins/ConfigMigration/configmigrationitem.h @@ -0,0 +1,20 @@ +#ifndef CONFIGMIGRATIONITEM_H +#define CONFIGMIGRATIONITEM_H + +#include <QString> + +struct ConfigMigrationItem +{ + enum class Type + { + SQL_HISTORY, + DATABASES, + FUNCTION_LIST, + BUG_REPORTS + }; + + QString label; + Type type; +}; + +#endif // CONFIGMIGRATIONITEM_H diff --git a/Plugins/ConfigMigration/configmigrationwizard.cpp b/Plugins/ConfigMigration/configmigrationwizard.cpp new file mode 100644 index 0000000..afdf705 --- /dev/null +++ b/Plugins/ConfigMigration/configmigrationwizard.cpp @@ -0,0 +1,407 @@ +#include "configmigrationwizard.h" +#include "ui_configmigrationwizard.h" +#include "configmigration.h" +#include "configmigrationitem.h" +#include "iconmanager.h" +#include "uiutils.h" +#include "dbtree/dbtree.h" +#include "dbtree/dbtreemodel.h" +#include "services/config.h" +#include "sqlitestudio.h" +#include "db/dbsqlite3.h" +#include "services/notifymanager.h" +#include "services/dbmanager.h" + +ConfigMigrationWizard::ConfigMigrationWizard(QWidget *parent, ConfigMigration* cfgMigration) : + QWizard(parent), + ui(new Ui::ConfigMigrationWizard), + cfgMigration(cfgMigration) +{ + init(); +} + +ConfigMigrationWizard::~ConfigMigrationWizard() +{ + clearFunctions(); + delete ui; +} + +bool ConfigMigrationWizard::didMigrate() +{ + return migrated; +} + +void ConfigMigrationWizard::accept() +{ + migrate(); + QWizard::accept(); +} + +void ConfigMigrationWizard::init() +{ + ui->setupUi(this); + +#ifdef Q_OS_MACX + resize(width() + 150, height()); + setPixmap(QWizard::BackgroundPixmap, addOpacity(ICONMANAGER->getIcon("config_migration")->pixmap(180, 180), 0.4)); +#endif + + ui->optionsPage->setValidator([=]() -> bool + { + QString grpName = ui->groupNameEdit->text(); + + bool grpOk = true; + QString grpErrorMsg; + if (ui->dbGroup->isEnabled() && ui->dbGroup->isChecked()) + { + if (grpName.isEmpty()) + { + grpOk = false; + grpErrorMsg = tr("Enter a non-empty name."); + } + else + { + DbTreeItem* item = DBTREE->getModel()->findItem(DbTreeItem::Type::DIR, grpName); + if (item && !item->parentDbTreeItem()) + { + grpOk = false; + grpErrorMsg = tr("Top level group named '%1' already exists. Enter a group name that does not exist yet.").arg(grpName); + } + } + } + + setValidState(ui->groupNameEdit, grpOk, grpErrorMsg); + + return grpOk; + }); + + + QTreeWidgetItem* treeItem = nullptr; + for (ConfigMigrationItem* cfgItem : cfgMigration->getItemsToMigrate()) + { + treeItem = new QTreeWidgetItem({cfgItem->label}); + treeItem->setData(0, Qt::UserRole, static_cast<int>(cfgItem->type)); + treeItem->setFlags(treeItem->flags() | Qt::ItemIsUserCheckable); + treeItem->setCheckState(0, Qt::Checked); + ui->itemsTree->addTopLevelItem(treeItem); + } + + connect(ui->dbGroup, SIGNAL(clicked()), ui->optionsPage, SIGNAL(completeChanged())); + connect(ui->groupNameEdit, SIGNAL(textChanged(QString)), ui->optionsPage, SIGNAL(completeChanged())); + connect(this, SIGNAL(updateOptionsValidation()), ui->optionsPage, SIGNAL(completeChanged())); + connect(this, SIGNAL(currentIdChanged(int)), this, SLOT(updateOptions())); + + emit updateOptionsValidation(); +} + +void ConfigMigrationWizard::migrate() +{ + Db* oldCfgDb = cfgMigration->getOldCfgDb(); + if (!oldCfgDb->open()) + { + notifyError(tr("Could not open old configuration file in order to migrate settings from it.")); + return; + } + + QString cfgFilePath = SQLITESTUDIO->getConfig()->getConfigFilePath(); + Db* newCfgDb = new DbSqlite3("Config migration connection", cfgFilePath, {{DB_PURE_INIT, true}}); + if (!newCfgDb->open()) + { + notifyError(tr("Could not open current configuration file in order to migrate settings from old configuration file.")); + delete newCfgDb; + return; + } + + newCfgDb->begin(); + bool migrated = migrateSelected(oldCfgDb, newCfgDb); + if (migrated && !newCfgDb->commit()) + { + notifyError(tr("Could not commit migrated data into new configuration file: %1").arg(newCfgDb->getErrorText())); + newCfgDb->rollback(); + } + else if (!migrated) + { + newCfgDb->rollback(); + } + else + { + finalize(); + } + oldCfgDb->close(); + newCfgDb->close(); + delete newCfgDb; + clearFunctions(); +} + +bool ConfigMigrationWizard::migrateSelected(Db* oldCfgDb, Db* newCfgDb) +{ + if (checkedTypes.contains(ConfigMigrationItem::Type::BUG_REPORTS) && !migrateBugReports(oldCfgDb, newCfgDb)) + return false; + + if (checkedTypes.contains(ConfigMigrationItem::Type::DATABASES) && !migrateDatabases(oldCfgDb, newCfgDb)) + return false; + + if (checkedTypes.contains(ConfigMigrationItem::Type::FUNCTION_LIST) && !migrateFunction(oldCfgDb, newCfgDb)) + return false; + + if (checkedTypes.contains(ConfigMigrationItem::Type::SQL_HISTORY) && !migrateSqlHistory(oldCfgDb, newCfgDb)) + return false; + + return true; +} + +bool ConfigMigrationWizard::migrateBugReports(Db* oldCfgDb, Db* newCfgDb) +{ + static_qstring(oldBugsQuery, "SELECT created_on, brief, url, type FROM bugs"); + static_qstring(newBugsInsert, "INSERT INTO reports_history (timestamp, feature_request, title, url) VALUES (?, ?, ?, ?)"); + + SqlQueryPtr insertResults; + SqlResultsRowPtr row; + SqlQueryPtr results = oldCfgDb->exec(oldBugsQuery); + if (results->isError()) + { + notifyError(tr("Could not read bug reports history from old configuration file in order to migrate it: %1").arg(results->getErrorText())); + return false; + } + + bool feature; + QString url; + while (results->hasNext()) + { + row = results->next(); + feature = (row->value("type").toString().toUpper() == "FEATURE"); + url = row->value("url").toString().trimmed(); + if (url.startsWith("http://") && url.contains("sqlitestudio.one.pl")) + url.replace("sqlitestudio.one.pl", "sqlitestudio.pl").replace("report_bug.rvt", "report_bug3.rvt"); + + insertResults = newCfgDb->exec(newBugsInsert, {row->value("created_on"), feature, row->value("brief"), url}); + if (insertResults->isError()) + { + notifyError(tr("Could not insert a bug reports history entry into new configuration file: %1").arg(insertResults->getErrorText())); + return false; + } + } + + return true; +} + +bool ConfigMigrationWizard::migrateDatabases(Db* oldCfgDb, Db* newCfgDb) +{ + static_qstring(oldDbListQuery, "SELECT name, path FROM dblist"); + static_qstring(newDbListInsert, "INSERT INTO dblist (name, path) VALUES (?, ?)"); + static_qstring(groupOrderQuery, "SELECT max([order]) + 1 FROM groups WHERE parent %1"); + static_qstring(groupInsert, "INSERT INTO groups (name, [order], parent, open, dbname) VALUES (?, ?, ?, ?, ?)"); + + SqlQueryPtr groupResults; + SqlQueryPtr insertResults; + SqlResultsRowPtr row; + SqlQueryPtr results = oldCfgDb->exec(oldDbListQuery); + if (results->isError()) + { + notifyError(tr("Could not read database list from old configuration file in order to migrate it: %1").arg(results->getErrorText())); + return false; + } + + // Creating containing group + bool putInGroup = ui->dbGroup->isEnabled() && ui->dbGroup->isChecked(); + qint64 groupId = -1; + int order; + if (putInGroup) + { + // Query order + groupResults = newCfgDb->exec(groupOrderQuery.arg("IS NULL")); + if (groupResults->isError()) + { + notifyError(tr("Could query for available order for containing group in new configuration file in order to migrate the database list: %1") + .arg(groupResults->getErrorText())); + return false; + } + + order = groupResults->getSingleCell().toInt(); + + // Insert group + groupResults = newCfgDb->exec(groupInsert, {ui->groupNameEdit->text(), order, QVariant(), 1, QVariant()}); + if (groupResults->isError()) + { + notifyError(tr("Could not create containing group in new configuration file in order to migrate the database list: %1").arg(groupResults->getErrorText())); + return false; + } + groupId = groupResults->getRegularInsertRowId(); + } + + // Migrating the list + QString name; + QString path; + while (results->hasNext()) + { + row = results->next(); + name = row->value("name").toString(); + path = row->value("path").toString(); + + if (DBLIST->getByName(name) || DBLIST->getByPath(path)) // already on the new list + continue; + + insertResults = newCfgDb->exec(newDbListInsert, {name, path}); + if (insertResults->isError()) + { + notifyError(tr("Could not insert a database entry into new configuration file: %1").arg(insertResults->getErrorText())); + return false; + } + + // Query order + if (putInGroup) + groupResults = newCfgDb->exec(groupOrderQuery.arg("= ?"), {groupId}); + else + groupResults = newCfgDb->exec(groupOrderQuery.arg("IS NULL")); + + if (groupResults->isError()) + { + notifyError(tr("Could query for available order for next database in new configuration file in order to migrate the database list: %1") + .arg(groupResults->getErrorText())); + return false; + } + + order = groupResults->getSingleCell().toInt(); + + // Insert group + groupResults = newCfgDb->exec(groupInsert, {QVariant(), order, putInGroup ? QVariant(groupId) : QVariant(), 0, name}); + if (groupResults->isError()) + { + notifyError(tr("Could not create group referencing the database in new configuration file: %1").arg(groupResults->getErrorText())); + return false; + } + } + + return true; +} + +bool ConfigMigrationWizard::migrateFunction(Db* oldCfgDb, Db* newCfgDb) +{ + UNUSED(newCfgDb); + + static_qstring(oldFunctionsQuery, "SELECT name, type, code FROM functions"); + + SqlResultsRowPtr row; + SqlQueryPtr results = oldCfgDb->exec(oldFunctionsQuery); + if (results->isError()) + { + notifyError(tr("Could not read function list from old configuration file in order to migrate it: %1").arg(results->getErrorText())); + return false; + } + + clearFunctions(); + for (FunctionManager::ScriptFunction* fn : FUNCTIONS->getAllScriptFunctions()) + fnList << new FunctionManager::ScriptFunction(*fn); + + FunctionManager::ScriptFunction* fn = nullptr; + while (results->hasNext()) + { + row = results->next(); + + fn = new FunctionManager::ScriptFunction(); + fn->type = FunctionManager::ScriptFunction::SCALAR; + fn->lang = row->value("type").toString(); + fn->name = row->value("name").toString(); + fn->code = row->value("code").toString(); + fnList << fn; + } + + return true; +} + +bool ConfigMigrationWizard::migrateSqlHistory(Db* oldCfgDb, Db* newCfgDb) +{ + static_qstring(historyIdQuery, "SELECT CASE WHEN max(id) IS NULL THEN 0 ELSE max(id) + 1 END FROM sqleditor_history"); + static_qstring(oldHistoryQuery, "SELECT dbname, date, time, rows, sql FROM history"); + static_qstring(newHistoryInsert, "INSERT INTO sqleditor_history (id, dbname, date, time_spent, rows, sql) VALUES (?, ?, ?, ?, ?, ?)"); + + SqlQueryPtr insertResults; + SqlResultsRowPtr row; + SqlQueryPtr results = oldCfgDb->exec(oldHistoryQuery); + if (results->isError()) + { + notifyError(tr("Could not read SQL queries history from old configuration file in order to migrate it: %1").arg(results->getErrorText())); + return false; + } + + SqlQueryPtr idResults = newCfgDb->exec(historyIdQuery); + if (idResults->isError()) + { + notifyError(tr("Could not read next ID for SQL queries history in new configuration file: %1").arg(idResults->getErrorText())); + return false; + } + qint64 nextId = idResults->getSingleCell().toLongLong(); + + int timeSpent; + int date; + while (results->hasNext()) + { + row = results->next(); + timeSpent = qRound(row->value("time").toDouble() * 1000); + date = QDateTime::fromString(row->value("date").toString(), "yyyy-MM-dd HH:mm").toTime_t(); + + insertResults = newCfgDb->exec(newHistoryInsert, {nextId++, row->value("dbname"), date, timeSpent, row->value("rows"), row->value("sql")}); + if (insertResults->isError()) + { + notifyError(tr("Could not insert SQL history entry into new configuration file: %1").arg(insertResults->getErrorText())); + return false; + } + } + + return true; +} + +void ConfigMigrationWizard::finalize() +{ + if (checkedTypes.contains(ConfigMigrationItem::Type::FUNCTION_LIST)) + { + FUNCTIONS->setScriptFunctions(fnList); + fnList.clear(); + } + + if (checkedTypes.contains(ConfigMigrationItem::Type::SQL_HISTORY)) + CFG->refreshSqlHistory(); + + if (checkedTypes.contains(ConfigMigrationItem::Type::DATABASES)) + { + bool ignore = DBTREE->getModel()->getIgnoreDbLoadedSignal(); + DBTREE->getModel()->setIgnoreDbLoadedSignal(true); + DBLIST->scanForNewDatabasesInConfig(); + DBTREE->getModel()->setIgnoreDbLoadedSignal(ignore); + DBTREE->getModel()->loadDbList(); + } + + migrated = true; +} + +void ConfigMigrationWizard::collectCheckedTypes() +{ + checkedTypes.clear(); + + QTreeWidgetItem* item = nullptr; + for (int i = 0, total = ui->itemsTree->topLevelItemCount(); i < total; ++i) + { + item = ui->itemsTree->topLevelItem(i); + if (item->checkState(0) != Qt::Checked) + continue; + + checkedTypes << static_cast<ConfigMigrationItem::Type>(item->data(0, Qt::UserRole).toInt()); + } +} + +void ConfigMigrationWizard::clearFunctions() +{ + for (FunctionManager::ScriptFunction* fn : fnList) + delete fn; + + fnList.clear(); +} + +void ConfigMigrationWizard::updateOptions() +{ + if (currentPage() == ui->optionsPage) + { + collectCheckedTypes(); + ui->dbGroup->setEnabled(checkedTypes.contains(ConfigMigrationItem::Type::DATABASES)); + } +} diff --git a/Plugins/ConfigMigration/configmigrationwizard.h b/Plugins/ConfigMigration/configmigrationwizard.h new file mode 100644 index 0000000..44a9f16 --- /dev/null +++ b/Plugins/ConfigMigration/configmigrationwizard.h @@ -0,0 +1,52 @@ +#ifndef CONFIGMIGRATIONWIZARD_H +#define CONFIGMIGRATIONWIZARD_H + +#include "configmigrationitem.h" +#include "services/functionmanager.h" +#include <QWizard> + +namespace Ui { +class ConfigMigrationWizard; +} + +class ConfigMigration; +class Db; + +class ConfigMigrationWizard : public QWizard +{ + Q_OBJECT + + public: + ConfigMigrationWizard(QWidget *parent, ConfigMigration* cfgMigration); + ~ConfigMigrationWizard(); + bool didMigrate(); + + private: + void init(); + void migrate(); + bool migrateSelected(Db* oldCfgDb, Db* newCfgDb); + bool migrateBugReports(Db* oldCfgDb, Db* newCfgDb); + bool migrateDatabases(Db* oldCfgDb, Db* newCfgDb); + bool migrateFunction(Db* oldCfgDb, Db* newCfgDb); + bool migrateSqlHistory(Db* oldCfgDb, Db* newCfgDb); + void finalize(); + void collectCheckedTypes(); + void clearFunctions(); + + Ui::ConfigMigrationWizard *ui = nullptr; + ConfigMigration* cfgMigration = nullptr; + QList<ConfigMigrationItem::Type> checkedTypes; + QList<FunctionManager::ScriptFunction*> fnList; + bool migrated = false; + + private slots: + void updateOptions(); + + public slots: + void accept(); + + signals: + void updateOptionsValidation(); +}; + +#endif // CONFIGMIGRATIONWIZARD_H diff --git a/Plugins/ConfigMigration/configmigrationwizard.ui b/Plugins/ConfigMigration/configmigrationwizard.ui new file mode 100644 index 0000000..ce35430 --- /dev/null +++ b/Plugins/ConfigMigration/configmigrationwizard.ui @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ConfigMigrationWizard</class> + <widget class="QWizard" name="ConfigMigrationWizard"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>392</width> + <height>282</height> + </rect> + </property> + <property name="windowTitle"> + <string>Configuration migration</string> + </property> + <property name="styleSheet"> + <string notr="true">QTreeView::item {margin-top: 5px;}</string> + </property> + <property name="options"> + <set>QWizard::NoDefaultButton</set> + </property> + <widget class="QWizardPage" name="itemsPage"> + <property name="title"> + <string>Items to migrate</string> + </property> + <property name="subTitle"> + <string>This is a list of items found in the old configuration file, which can be migrated into the current configuration.</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QTreeWidget" name="itemsTree"> + <property name="indentation"> + <number>0</number> + </property> + <property name="rootIsDecorated"> + <bool>false</bool> + </property> + <property name="itemsExpandable"> + <bool>false</bool> + </property> + <property name="expandsOnDoubleClick"> + <bool>false</bool> + </property> + <attribute name="headerVisible"> + <bool>false</bool> + </attribute> + <column> + <property name="text"> + <string notr="true">1</string> + </property> + </column> + </widget> + </item> + </layout> + </widget> + <widget class="VerifiableWizardPage" name="optionsPage"> + <property name="title"> + <string>Options</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QGroupBox" name="dbGroup"> + <property name="title"> + <string>Put imported databases into separate group</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QLineEdit" name="groupNameEdit"> + <property name="placeholderText"> + <string>Group name</string> + </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>205</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </widget> + <customwidgets> + <customwidget> + <class>VerifiableWizardPage</class> + <extends>QWizardPage</extends> + <header>common/verifiablewizardpage.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> |
