diff options
| author | 2021-12-17 07:06:30 -0500 | |
|---|---|---|
| committer | 2021-12-17 07:06:30 -0500 | |
| commit | 1fdc150116cad39aae5c5da407c3312b47a59e3a (patch) | |
| tree | 123c79a4d7ad2d45781ba03ce939f7539fb428d8 /SQLiteStudio3/coreSQLiteStudio/services | |
| parent | feda8a7db8d1d7c5439aa8f8feef7cc0dd2b59a0 (diff) | |
New upstream version 3.3.3+dfsg1.upstream/3.3.3+dfsg1
Diffstat (limited to 'SQLiteStudio3/coreSQLiteStudio/services')
14 files changed, 204 insertions, 166 deletions
diff --git a/SQLiteStudio3/coreSQLiteStudio/services/codeformatter.cpp b/SQLiteStudio3/coreSQLiteStudio/services/codeformatter.cpp index e02508f..e17032b 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/codeformatter.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/services/codeformatter.cpp @@ -2,6 +2,7 @@ #include "parser/parser.h"
#include "plugins/codeformatterplugin.h"
#include "services/pluginmanager.h"
+#include "common/compatibility.h"
#include <QDebug>
void CodeFormatter::setFormatter(const QString& lang, CodeFormatterPlugin *formatterPlugin)
@@ -44,7 +45,7 @@ void CodeFormatter::updateCurrent() QHash<QString,QVariant> config = CFG_CORE.General.ActiveCodeFormatter.get();
QString name;
QStringList names = availableFormatters.keys();
- qSort(names);
+ sSort(names);
for (const QString& lang : names)
{
name = config[lang].toString();
diff --git a/SQLiteStudio3/coreSQLiteStudio/services/config.cpp b/SQLiteStudio3/coreSQLiteStudio/services/config.cpp index 60a80d5..c03847a 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/config.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/services/config.cpp @@ -4,6 +4,7 @@ CFG_DEFINE(Core) static const QString DB_FILE_NAME = QStringLiteral("settings3"); static QString MASTER_CONFIG_FILE = QString(); +Config::AskUserForConfigDirFunc Config::askUserForConfigDirFunc; Config::~Config() { @@ -18,3 +19,8 @@ QString Config::getMasterConfigFile() { return MASTER_CONFIG_FILE; } + +void Config::setAskUserForConfigDirFunc(const AskUserForConfigDirFunc& value) +{ + askUserForConfigDirFunc = value; +} diff --git a/SQLiteStudio3/coreSQLiteStudio/services/config.h b/SQLiteStudio3/coreSQLiteStudio/services/config.h index 202120a..9d1e567 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/config.h +++ b/SQLiteStudio3/coreSQLiteStudio/services/config.h @@ -14,7 +14,7 @@ #include <QSharedPointer> #include <QDateTime> -const int SQLITESTUDIO_CONFIG_VERSION = 2; +const int SQLITESTUDIO_CONFIG_VERSION = 3; CFG_CATEGORIES(Core, CFG_CATEGORY(General, @@ -74,6 +74,7 @@ class API_EXPORT Config : public QObject QList<DbGroupPtr> childs; int order; bool open = false; + bool dbExpanded = false; }; struct SqlHistoryEntry @@ -107,13 +108,17 @@ class API_EXPORT Config : public QObject typedef QSharedPointer<ReportHistoryEntry> ReportHistoryEntryPtr; + typedef std::function<QString()> AskUserForConfigDirFunc; + static void setMasterConfigFile(const QString& path); static QString getMasterConfigFile(); + static void setAskUserForConfigDirFunc(const AskUserForConfigDirFunc& value); virtual void init() = 0; virtual void cleanUp() = 0; virtual const QString& getConfigDir() const = 0; virtual QString getConfigFilePath() const = 0; + virtual bool isInMemory() const = 0; virtual void beginMassSave() = 0; virtual void commitMassSave() = 0; @@ -191,6 +196,10 @@ class API_EXPORT Config : public QObject public slots: virtual void refreshSqlHistory() = 0; virtual void refreshDdlHistory() = 0; + + protected: + static AskUserForConfigDirFunc askUserForConfigDirFunc; + }; #define CFG SQLITESTUDIO->getConfig() diff --git a/SQLiteStudio3/coreSQLiteStudio/services/extralicensemanager.cpp b/SQLiteStudio3/coreSQLiteStudio/services/extralicensemanager.cpp index 2bdc712..9710673 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/extralicensemanager.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/services/extralicensemanager.cpp @@ -55,7 +55,7 @@ bool ExtraLicenseManager::isViolatedLicense(const QString& title) QString ExtraLicenseManager::getViolationMessage(const QString& title) { if (!licenses.contains(title)) - return QString::null; + return QString(); return licenses[title]->violationMessage; } @@ -109,7 +109,7 @@ QString ExtraLicenseManager::readLicenseFile(const QString& path) const if (!file.open(QIODevice::ReadOnly)) { qCritical() << "Error opening" << file.fileName(); - return QString::null; + return QString(); } QString contents = QString::fromLatin1(file.readAll()); file.close(); diff --git a/SQLiteStudio3/coreSQLiteStudio/services/functionmanager.cpp b/SQLiteStudio3/coreSQLiteStudio/services/functionmanager.cpp index 10db318..f45e803 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/functionmanager.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/services/functionmanager.cpp @@ -24,7 +24,7 @@ QString FunctionManager::FunctionBase::typeString(Type type) case ScriptFunction::AGGREGATE: return "AGGREGATE"; } - return QString::null; + return QString(); } FunctionManager::ScriptFunction::Type FunctionManager::FunctionBase::typeString(const QString& type) diff --git a/SQLiteStudio3/coreSQLiteStudio/services/impl/configimpl.cpp b/SQLiteStudio3/coreSQLiteStudio/services/impl/configimpl.cpp index 860e828..570395a 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/impl/configimpl.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/services/impl/configimpl.cpp @@ -15,10 +15,15 @@ #include <QDateTime> #include <QSysInfo> #include <QCoreApplication> +#include <QStandardPaths> +#include <QSettings> #include <QtConcurrent/QtConcurrentRun> +#include <QtWidgets/QFileDialog> static_qstring(DB_FILE_NAME, "settings3"); +static_qstring(CONFIG_DIR_SETTING, "SQLiteStudioConfigDir"); qint64 ConfigImpl::sqlHistoryId = -1; +QString ConfigImpl::memoryDbName = QStringLiteral(":memory:"); ConfigImpl::~ConfigImpl() { @@ -43,7 +48,7 @@ void ConfigImpl::cleanUp() if (db->isOpen()) db->close(); - safe_delete(db); + safe_delete(db) } const QString &ConfigImpl::getConfigDir() const @@ -59,6 +64,11 @@ QString ConfigImpl::getConfigFilePath() const return db->getPath(); } +bool ConfigImpl::isInMemory() const +{ + return db->getPath() == memoryDbName; +} + void ConfigImpl::beginMassSave() { if (isMassSaving()) @@ -243,8 +253,8 @@ void ConfigImpl::storeGroup(const ConfigImpl::DbGroupPtr &group, qint64 parentId if (parentId > -1) parent = parentId; - SqlQueryPtr results = db->exec("INSERT INTO groups (name, [order], parent, open, dbname) VALUES (?, ?, ?, ?, ?)", - {group->name, group->order, parent, group->open, group->referencedDbName}); + SqlQueryPtr results = db->exec("INSERT INTO groups (name, [order], parent, open, dbname, db_expanded) VALUES (?, ?, ?, ?, ?, ?)", + {group->name, group->order, parent, group->open, group->referencedDbName, group->dbExpanded}); qint64 newParentId = results->getRegularInsertRowId(); for (const DbGroupPtr& childGroup : group->childs) @@ -261,7 +271,7 @@ QList<ConfigImpl::DbGroupPtr> ConfigImpl::getGroups() ConfigImpl::DbGroupPtr ConfigImpl::getDbGroup(const QString& dbName) { - SqlQueryPtr results = db->exec("SELECT id, name, [order], open, dbname FROM groups WHERE dbname = ? LIMIT 1", {dbName}); + SqlQueryPtr results = db->exec("SELECT id, name, [order], open, dbname, db_expanded FROM groups WHERE dbname = ? LIMIT 1", {dbName}); DbGroupPtr group = DbGroupPtr::create(); group->referencedDbName = dbName; @@ -274,6 +284,7 @@ ConfigImpl::DbGroupPtr ConfigImpl::getDbGroup(const QString& dbName) group->name = row->value("name").toString(); group->order = row->value("order").toInt(); group->open = row->value("open").toBool(); + group->dbExpanded = row->value("db_expanded").toBool(); return group; } @@ -553,9 +564,9 @@ void ConfigImpl::readGroupRecursively(ConfigImpl::DbGroupPtr group) { SqlQueryPtr results; if (group->id < 0) - results = db->exec("SELECT id, name, [order], open, dbname FROM groups WHERE parent IS NULL ORDER BY [order]"); + results = db->exec("SELECT id, name, [order], open, dbname, db_expanded FROM groups WHERE parent IS NULL ORDER BY [order]"); else - results = db->exec("SELECT id, name, [order], open, dbname FROM groups WHERE parent = ? ORDER BY [order]", {group->id}); + results = db->exec("SELECT id, name, [order], open, dbname, db_expanded FROM groups WHERE parent = ? ORDER BY [order]", {group->id}); DbGroupPtr childGroup; SqlResultsRowPtr row; @@ -568,6 +579,7 @@ void ConfigImpl::readGroupRecursively(ConfigImpl::DbGroupPtr group) childGroup->order = row->value("order").toInt(); childGroup->open = row->value("open").toBool(); childGroup->referencedDbName = row->value("dbname").toString(); + childGroup->dbExpanded = row->value("db_expanded").toBool(); group->childs += childGroup; } @@ -592,6 +604,11 @@ void ConfigImpl::rollback() QString ConfigImpl::getConfigPath() { + return QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/" + DB_FILE_NAME; +} + +QString ConfigImpl::getLegacyConfigPath() +{ #ifdef Q_OS_WIN if (QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) return SQLITESTUDIO->getEnv("APPDATA")+"/sqlitestudio"; @@ -669,7 +686,7 @@ void ConfigImpl::initTables() if (!tables.contains("groups")) db->exec("CREATE TABLE groups (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, parent INTEGER REFERENCES groups(id), " "[order] INTEGER, open INTEGER DEFAULT 0, dbname TEXT UNIQUE REFERENCES dblist(name) ON UPDATE CASCADE ON DELETE CASCADE, " - "UNIQUE(name, parent))"); + "db_expanded INTEGER DEFAULT 0, UNIQUE(name, parent))"); if (!tables.contains("ddl_history")) db->exec("CREATE TABLE ddl_history (id INTEGER PRIMARY KEY AUTOINCREMENT, dbname TEXT, file TEXT, timestamp INTEGER, " @@ -712,43 +729,29 @@ void ConfigImpl::initTables() void ConfigImpl::initDbFile() { - // Determinate global config location and portable one - QString globalPath = getConfigPath(); - QString portablePath = getPortableConfigPath(); - QList<QPair<QString,bool>> paths; - if (!globalPath.isNull() && !portablePath.isNull()) - { - if (QFileInfo(portablePath).exists()) - { - paths << QPair<QString,bool>(portablePath+"/"+DB_FILE_NAME, false); - paths << QPair<QString,bool>(globalPath+"/"+DB_FILE_NAME, true); - } - else - { - paths << QPair<QString,bool>(globalPath+"/"+DB_FILE_NAME, true); - paths << QPair<QString,bool>(portablePath+"/"+DB_FILE_NAME, false); - } - } - else if (!globalPath.isNull()) + + // Do we have path selected by user? (because app was unable to find writable location before) + QSettings sett; + QString customPath = sett.value(CONFIG_DIR_SETTING).toString(); + if (!customPath.isEmpty()) { - paths << QPair<QString,bool>(globalPath+"/"+DB_FILE_NAME, true); - } - else if (!portablePath.isNull()) - { - paths << QPair<QString,bool>(portablePath+"/"+DB_FILE_NAME, false); + paths << QPair<QString,bool>(customPath + "/" + DB_FILE_NAME, false); + qDebug() << "Using custom configuration directory. The location is stored in" << sett.fileName(); } + else + paths.append(getStdDbPaths()); // A fallback to in-memory db - paths << QPair<QString,bool>(":memory:", false); + paths << QPair<QString,bool>(memoryDbName, false); // Go through all candidates and pick one QDir dir; for (const QPair<QString,bool>& path : paths) { dir = QDir(path.first); - if (path.first != ":memory:") - dir.cdUp(); + if (path.first != memoryDbName) + dir = QFileInfo(path.first).dir(); if (tryInitDbFile(path)) { @@ -757,8 +760,25 @@ void ConfigImpl::initDbFile() } } + // Failed to use any of predefined directories. Let's ask the user. + while (configDir == memoryDbName) + { + QString path = askUserForConfigDirFunc(); + if (path.isNull()) + break; + + dir = QDir(path); + if (tryInitDbFile(QPair<QString,bool>(path + "/" + DB_FILE_NAME, false))) + { + configDir = dir.absolutePath(); + QSettings sett; + sett.setValue(CONFIG_DIR_SETTING, configDir); + qDebug() << "Using custom configuration directory. The location is stored in" << sett.fileName(); + } + } + // We ended up with in-memory one? That's not good. - if (configDir == ":memory:") + if (configDir == memoryDbName) { paths.removeLast(); QStringList pathStrings; @@ -766,13 +786,38 @@ void ConfigImpl::initDbFile() pathStrings << path.first; notifyError(QObject::tr("Could not initialize configuration file. Any configuration changes and queries history will be lost after application restart." - " Tried to initialize the file at following localizations: %1.").arg(pathStrings.join(", "))); + " Unable to create a file at following locations: %1.").arg(pathStrings.join(", "))); } qDebug() << "Using configuration directory:" << configDir; db->exec("PRAGMA foreign_keys = 1;"); } +QList<QPair<QString,bool>> ConfigImpl::getStdDbPaths() +{ + QList<QPair<QString,bool>> paths; + + // Portable dir location has always precedense - comes first + QString portablePath = getPortableConfigPath(); + if (!portablePath.isNull()) + paths << QPair<QString,bool>(portablePath+"/"+DB_FILE_NAME, false); + + // Determinate global config location + QString globalPath = getConfigPath(); + paths << QPair<QString,bool>(globalPath, true); + + // If needed, migrate configuration from legacy location (pre-3.3) to new location (3.3 and later) + QString legacyGlobalPath = getLegacyConfigPath(); + if (!legacyGlobalPath.isNull()) + { + paths << QPair<QString,bool>(legacyGlobalPath+"/"+DB_FILE_NAME, true); + if (!QFile::exists(globalPath)) + tryToMigrateOldGlobalPath(legacyGlobalPath, globalPath); + } + + return paths; +} + bool ConfigImpl::tryInitDbFile(const QPair<QString, bool> &dbPath) { // Create global config directory if not existing @@ -1118,6 +1163,12 @@ void ConfigImpl::updateConfigDb() // 1->2 db->exec("UPDATE settings SET [key] = 'DataUncommittedError' WHERE [key] = 'DataUncommitedError'"); db->exec("UPDATE settings SET [key] = 'DataUncommitted' WHERE [key] = 'DataUncommited'"); + __attribute__((__fallthrough__)); + } + case 2: + { + // 2->3 + db->exec("ALTER TABLE groups ADD db_expanded INTEGER DEFAULT 0"); } // Add cases here for next versions, // without a "break" instruction, @@ -1129,6 +1180,30 @@ void ConfigImpl::updateConfigDb() db->commit(); } +bool ConfigImpl::tryToMigrateOldGlobalPath(const QString& oldPath, const QString& newPath) +{ + if (!QFileInfo::exists(oldPath)) + return false; + + qDebug() << "Attempting to migrate legacy config location" << oldPath << "to new location" << newPath; + QDir dir = QFileInfo(newPath).dir(); + if (!dir.exists()) + QDir::root().mkpath(dir.absolutePath()); + + if (QFile::copy(oldPath, dir.absoluteFilePath(DB_FILE_NAME))) + { + qDebug() << "Migration successful. Renaming old location file so it has '.old' suffix."; + if (QFile::rename(oldPath, oldPath+".old")) + qDebug() << "Renaming successful."; + else + qDebug() << "Renaming did not work, but it's okay. It will just remain with original name there."; + } + else + qDebug() << "Migration (copying) failed."; + + return true; +} + void ConfigImpl::refreshSqlHistory() { if (sqlHistoryModel) diff --git a/SQLiteStudio3/coreSQLiteStudio/services/impl/configimpl.h b/SQLiteStudio3/coreSQLiteStudio/services/impl/configimpl.h index 561aab4..710fbb3 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/impl/configimpl.h +++ b/SQLiteStudio3/coreSQLiteStudio/services/impl/configimpl.h @@ -22,6 +22,7 @@ class API_EXPORT ConfigImpl : public Config void cleanUp(); const QString& getConfigDir() const; QString getConfigFilePath() const; + bool isInMemory() const; void beginMassSave(); void commitMassSave(); @@ -104,6 +105,7 @@ class API_EXPORT ConfigImpl : public Config QString getPortableConfigPath(); void initTables(); void initDbFile(); + QList<QPair<QString, bool> > getStdDbPaths(); bool tryInitDbFile(const QPair<QString, bool>& dbPath); QVariant deserializeValue(const QVariant& value) const; @@ -131,9 +133,12 @@ class API_EXPORT ConfigImpl : public Config void mergeMasterConfig(); void updateConfigDb(); + bool tryToMigrateOldGlobalPath(const QString& oldPath, const QString& newPath); + QString getLegacyConfigPath(); static Config* instance; static qint64 sqlHistoryId; + static QString memoryDbName; Db* db = nullptr; QString configDir; diff --git a/SQLiteStudio3/coreSQLiteStudio/services/impl/dbmanagerimpl.cpp b/SQLiteStudio3/coreSQLiteStudio/services/impl/dbmanagerimpl.cpp index 217c2b7..9086257 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/impl/dbmanagerimpl.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/services/impl/dbmanagerimpl.cpp @@ -284,7 +284,7 @@ QString DbManagerImpl::quickAddDb(const QString& path, const QHash<QString, QVar QString newName = DbManager::generateDbName(path); newName = generateUniqueName(newName, DBLIST->getDbNames()); if (!DBLIST->addDb(newName, path, options, false)) - return QString::null; + return QString(); return newName; } diff --git a/SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.cpp b/SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.cpp index c67156c..324f549 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.cpp @@ -87,7 +87,7 @@ QStringList PluginManagerImpl::getPluginDirs() const QString PluginManagerImpl::getFilePath(Plugin* plugin) const { if (!pluginContainer.contains(plugin->getName())) - return QString::null; + return QString(); return pluginContainer[plugin->getName()]->filePath; } @@ -339,7 +339,13 @@ bool PluginManagerImpl::initPlugin(Plugin* plugin) bool PluginManagerImpl::shouldAutoLoad(const QString& pluginName) { - QStringList loadedPlugins = CFG_CORE.General.LoadedPlugins.get().split(",", QString::SkipEmptyParts); + QStringList loadedPlugins = CFG_CORE.General.LoadedPlugins.get().split(",", +#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) + Qt::SkipEmptyParts +#else + QString::SkipEmptyParts +#endif + ); QStringList pair; for (const QString& loadedPlugin : loadedPlugins) { @@ -385,7 +391,7 @@ PluginType* PluginManagerImpl::getPluginType(const QString& pluginName) const QString PluginManagerImpl::getAuthor(const QString& pluginName) const { if (!pluginContainer.contains(pluginName)) - return QString::null; + return QString(); return pluginContainer[pluginName]->author; } @@ -393,7 +399,7 @@ QString PluginManagerImpl::getAuthor(const QString& pluginName) const QString PluginManagerImpl::getTitle(const QString& pluginName) const { if (!pluginContainer.contains(pluginName)) - return QString::null; + return QString(); return pluginContainer[pluginName]->title; } @@ -401,7 +407,7 @@ QString PluginManagerImpl::getTitle(const QString& pluginName) const QString PluginManagerImpl::getPrintableVersion(const QString& pluginName) const { if (!pluginContainer.contains(pluginName)) - return QString::null; + return QString(); return pluginContainer[pluginName]->printableVersion; } @@ -417,7 +423,7 @@ int PluginManagerImpl::getVersion(const QString& pluginName) const QString PluginManagerImpl::getDescription(const QString& pluginName) const { if (!pluginContainer.contains(pluginName)) - return QString::null; + return QString(); return pluginContainer[pluginName]->description; } diff --git a/SQLiteStudio3/coreSQLiteStudio/services/importmanager.cpp b/SQLiteStudio3/coreSQLiteStudio/services/importmanager.cpp index b9aa947..a06a743 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/importmanager.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/services/importmanager.cpp @@ -67,7 +67,7 @@ void ImportManager::importToTable(Db* db, const QString& table, bool async) importInProgress = true; ImportWorker* worker = new ImportWorker(plugin, &importConfig, db, table); - connect(worker, SIGNAL(finished(bool)), this, SLOT(finalizeImport(bool))); + connect(worker, SIGNAL(finished(bool, int)), this, SLOT(finalizeImport(bool, int))); connect(worker, SIGNAL(createdTable(Db*,QString)), this, SLOT(handleTableCreated(Db*,QString))); connect(this, SIGNAL(orderWorkerToInterrupt()), worker, SLOT(interrupt())); @@ -87,13 +87,13 @@ bool ImportManager::isAnyPluginAvailable() return PLUGINS->getLoadedPlugins<ImportPlugin>().size() > 0; } -void ImportManager::finalizeImport(bool result) +void ImportManager::finalizeImport(bool result, int rowCount) { importInProgress = false; emit importFinished(); if (result) { - notifyInfo(tr("Imported data to the table '%1' successfully.").arg(table)); + notifyInfo(tr("Imported data to the table '%1' successfully. Number of imported rows: %2").arg(table, QString::number(rowCount))); emit importSuccessful(); } else diff --git a/SQLiteStudio3/coreSQLiteStudio/services/importmanager.h b/SQLiteStudio3/coreSQLiteStudio/services/importmanager.h index 5c6a73e..9e9b160 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/importmanager.h +++ b/SQLiteStudio3/coreSQLiteStudio/services/importmanager.h @@ -70,7 +70,7 @@ class API_EXPORT ImportManager : public PluginServiceBase void interrupt(); private slots: - void finalizeImport(bool result); + void finalizeImport(bool result, int rowCount); void handleTableCreated(Db* db, const QString& table); signals: diff --git a/SQLiteStudio3/coreSQLiteStudio/services/pluginmanager.h b/SQLiteStudio3/coreSQLiteStudio/services/pluginmanager.h index f771c2c..65aa8fa 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/pluginmanager.h +++ b/SQLiteStudio3/coreSQLiteStudio/services/pluginmanager.h @@ -344,7 +344,7 @@ class API_EXPORT PluginManager : public QObject * the other one, if the first one is already loaded - and vice versa. * * Declaring conflicts for a plugin can be useful for example if somebody wants to proivde an alternative - * implementation of SQLite2 database plugin, etc. In that case SQLiteStudio won't get confused in + * implementation of SQLCipher database plugin, etc. In that case SQLiteStudio won't get confused in * deciding which plugin to use for supporting such databases. */ virtual QStringList getConflicts(const QString& pluginName) const = 0; diff --git a/SQLiteStudio3/coreSQLiteStudio/services/updatemanager.cpp b/SQLiteStudio3/coreSQLiteStudio/services/updatemanager.cpp index 87df73b..867ef58 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/updatemanager.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/services/updatemanager.cpp @@ -7,29 +7,18 @@ #include <QRegularExpression> #include <QCoreApplication> #include <QFileInfo> +#include <QNetworkRequest> +#include <QNetworkAccessManager> +#include <QNetworkReply> +#include <QJsonDocument> +#include <QJsonObject> #include <QtConcurrent/QtConcurrentRun> UpdateManager::UpdateManager(QObject *parent) : QObject(parent) { - qRegisterMetaType<QList<UpdateManager::UpdateEntry>>(); - - connect(this, SIGNAL(updatingError(QString)), NOTIFY_MANAGER, SLOT(error(QString))); - - QString updateBinary = -#if defined(Q_OS_WIN) - "UpdateSQLiteStudio.exe"; -#elif defined(Q_OS_LINUX) - "UpdateSQLiteStudio"; -#elif defined(Q_OS_OSX) - "../../UpdateSQLiteStudio.app/Contents/MacOS/UpdateSQLiteStudio"; -#else - ""; -#endif - - if (!updateBinary.isEmpty()) { - updateBinaryAbsolutePath = QFileInfo(QCoreApplication::applicationDirPath() + "/" + updateBinary).absoluteFilePath(); - } + connect(this, SIGNAL(updatingError(QString)), this, SLOT(handleUpdatingError(QString))); + netManager = new QNetworkAccessManager(this); } UpdateManager::~UpdateManager() @@ -42,54 +31,14 @@ void UpdateManager::checkForUpdates() if (!CFG_CORE.General.CheckUpdatesOnStartup.get()) return; - if (updateBinaryAbsolutePath.isEmpty()) { - qDebug() << "Updater binary not defined. Skipping updates checking."; - return; - } - - if (!QFileInfo(updateBinaryAbsolutePath).exists()) { - QString errorDetails = tr("Updates installer executable is missing."); - emit updatingError(tr("Unable to check for updates (%1)").arg(errorDetails.trimmed())); - qWarning() << "Error while checking for updates: " << errorDetails; - return; - } - - QtConcurrent::run(this, &UpdateManager::checkForUpdatesAsync); -} - -void UpdateManager::checkForUpdatesAsync() -{ - QProcess proc; - proc.start(updateBinaryAbsolutePath, {"--checkupdates"}); - if (!waitForProcess(proc)) + static_qstring(url, "https://sqlitestudio.pl/rest/updates"); + QNetworkRequest request(url); + QNetworkReply* response = netManager->get(request); + connect(response, &QNetworkReply::finished, [this, response]() { - QString errorDetails = QString::fromLocal8Bit(proc.readAllStandardError()); - - if (errorDetails.toLower().contains("no updates")) { - emit noUpdatesAvailable(); - return; - } - - if (errorDetails.isEmpty()) - errorDetails = tr("details are unknown"); - - emit updatingError(tr("Unable to check for updates (%1)").arg(errorDetails.trimmed())); - qWarning() << "Error while checking for updates: " << errorDetails; - return; - } - - processCheckResults(proc.readAllStandardOutput()); -} - -void UpdateManager::update() -{ - bool success = QProcess::startDetached(updateBinaryAbsolutePath, {"--updater"}); - if (!success) - { - emit updatingError(tr("Unable to run updater application (%1). Please report this.").arg(updateBinaryAbsolutePath)); - return; - } - qApp->exit(0); + response->deleteLater(); + handleUpdatesResponse(response); + }); } bool UpdateManager::isPlatformEligibleForUpdate() const @@ -97,56 +46,50 @@ bool UpdateManager::isPlatformEligibleForUpdate() const return getDistributionType() != DistributionType::OS_MANAGED; } -bool UpdateManager::waitForProcess(QProcess& proc) +void UpdateManager::handleUpdatesResponse(QNetworkReply* response) { - if (!proc.waitForFinished(-1)) + if (response->error() != QNetworkReply::NoError) { - qDebug() << "Update QProcess timed out."; - return false; + emit updatingError(response->errorString()); + return; } - if (proc.exitStatus() == QProcess::CrashExit) - { - qDebug() << "Update QProcess finished by crashing."; - return false; - } + QJsonParseError parsingError; + QJsonDocument json = QJsonDocument::fromJson(response->readAll(), &parsingError); - if (proc.exitCode() != 0) + if (parsingError.error != QJsonParseError::NoError) { - qDebug() << "Update QProcess finished with code:" << proc.exitCode(); - return false; + emit updatingError(parsingError.errorString()); + return; } - return true; -} + QString version = json["version"].toString(); + QStringList versionParts = version.split("."); + QString alignedVersion = versionParts[0] + versionParts[1].rightJustified(2, '0') + versionParts[2].rightJustified(2, '0'); + int versionNumber = alignedVersion.toInt(); -void UpdateManager::processCheckResults(const QByteArray &results) -{ - if (results.trimmed().isEmpty()) { + if (SQLITESTUDIO->getVersion() >= versionNumber) + { emit noUpdatesAvailable(); return; } - QRegularExpression re(R"(\<update\s+([^\>]+)\>)"); - QRegularExpression versionRe(R"(version\=\"([\d\.]+)\")"); - QRegularExpression nameRe(R"(name\=\"([^\"]+)\")"); +#if defined(Q_OS_WIN) + QString url = json["win"].toString(); +#elif defined(Q_OS_LINUX) + QString url = json["lin"].toString(); +#elif defined(Q_OS_OSX) + QString url = json["mac"].toString(); +#else + QString url = jsonQString(); +#endif - QRegularExpressionMatchIterator reIter = re.globalMatch(results); - QString updateNode; - UpdateEntry theUpdate; - QList<UpdateEntry> updates; - while (reIter.hasNext()) - { - updateNode = reIter.next().captured(1); - theUpdate.version = versionRe.match(updateNode).captured(1); - theUpdate.compontent = nameRe.match(updateNode).captured(1); - updates << theUpdate; - } + emit updateAvailable(version, url); +} - if (updates.isEmpty()) - emit noUpdatesAvailable(); - else - emit updatesAvailable(updates); +void UpdateManager::handleUpdatingError(const QString& errorMessage) +{ + NOTIFY_MANAGER->warn(tr("Could not check for updates (%1).").arg(errorMessage)); } #endif // PORTABLE_CONFIG diff --git a/SQLiteStudio3/coreSQLiteStudio/services/updatemanager.h b/SQLiteStudio3/coreSQLiteStudio/services/updatemanager.h index 50f4b6b..d7f59ca 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/updatemanager.h +++ b/SQLiteStudio3/coreSQLiteStudio/services/updatemanager.h @@ -9,8 +9,8 @@ #include <functional> #include <QProcess> -class QNetworkAccessManager; class QNetworkReply; +class QNetworkAccessManager; class QTemporaryDir; class QFile; @@ -18,34 +18,27 @@ class API_EXPORT UpdateManager : public QObject { Q_OBJECT public: - struct UpdateEntry - { - QString compontent; - QString version; - }; - explicit UpdateManager(QObject *parent = 0); ~UpdateManager(); void checkForUpdates(); - void update(); bool isPlatformEligibleForUpdate() const; private: QString updateBinaryAbsolutePath; + QNetworkAccessManager *netManager = nullptr; - void checkForUpdatesAsync(); - bool waitForProcess(QProcess& proc); - void processCheckResults(const QByteArray& results); + void handleUpdatesResponse(QNetworkReply* response); + + private slots: + void handleUpdatingError(const QString& errorMessage); signals: - void updatesAvailable(const QList<UpdateManager::UpdateEntry>& updates); + void updateAvailable(const QString& version, const QString& url); void noUpdatesAvailable(); void updatingError(const QString& errorMessage); }; -Q_DECLARE_METATYPE(QList<UpdateManager::UpdateEntry>) - #define UPDATES SQLITESTUDIO->getUpdateManager() #endif // PORTABLE_CONFIG |
