From 3565aad630864ecdbe53fdaa501ea708555b3c7c Mon Sep 17 00:00:00 2001 From: Unit 193 Date: Sun, 30 Apr 2023 18:30:36 -0400 Subject: New upstream version 3.4.4+dfsg. --- .../services/codesnippetmanager.cpp | 119 +++++++++++++++++++++ .../coreSQLiteStudio/services/codesnippetmanager.h | 42 ++++++++ .../coreSQLiteStudio/services/collationmanager.h | 1 - SQLiteStudio3/coreSQLiteStudio/services/config.cpp | 59 ++++++++++ SQLiteStudio3/coreSQLiteStudio/services/config.h | 11 +- .../coreSQLiteStudio/services/functionmanager.h | 2 +- .../services/impl/collationmanagerimpl.cpp | 22 +++- .../services/impl/collationmanagerimpl.h | 1 + .../coreSQLiteStudio/services/impl/configimpl.cpp | 115 +++++++------------- .../coreSQLiteStudio/services/impl/configimpl.h | 13 ++- .../services/impl/dbmanagerimpl.cpp | 30 +++--- .../services/impl/functionmanagerimpl.cpp | 82 +++++++++++--- .../services/impl/functionmanagerimpl.h | 1 + .../services/impl/pluginmanagerimpl.cpp | 44 ++++---- .../services/impl/pluginmanagerimpl.h | 15 +++ .../services/impl/sqliteextensionmanagerimpl.cpp | 54 +++++++++- .../services/impl/sqliteextensionmanagerimpl.h | 3 + .../coreSQLiteStudio/services/notifymanager.cpp | 2 +- .../coreSQLiteStudio/services/notifymanager.h | 2 +- .../services/sqliteextensionmanager.h | 1 + 20 files changed, 477 insertions(+), 142 deletions(-) create mode 100644 SQLiteStudio3/coreSQLiteStudio/services/codesnippetmanager.cpp create mode 100644 SQLiteStudio3/coreSQLiteStudio/services/codesnippetmanager.h (limited to 'SQLiteStudio3/coreSQLiteStudio/services') diff --git a/SQLiteStudio3/coreSQLiteStudio/services/codesnippetmanager.cpp b/SQLiteStudio3/coreSQLiteStudio/services/codesnippetmanager.cpp new file mode 100644 index 0000000..b50e791 --- /dev/null +++ b/SQLiteStudio3/coreSQLiteStudio/services/codesnippetmanager.cpp @@ -0,0 +1,119 @@ +#include "codesnippetmanager.h" +#include "common/utils.h" +#include "services/config.h" +#include +#include +#include + +CodeSnippetManager::CodeSnippetManager(Config* config) : + config(config) +{ + loadFromConfig(); + if (!CFG_CORE.Internal.DefaultSnippetsCreated.get()) + createDefaultSnippets(); +} + +void CodeSnippetManager::setSnippets(const QList& snippets) +{ + clearSnippets(); + allSnippets = snippets; + refreshNames(); + saveToConfig(); +} + +const QList& CodeSnippetManager::getSnippets() const +{ + return allSnippets; +} + +const QStringList& CodeSnippetManager::getNames() const +{ + return names; +} + +void CodeSnippetManager::saveToConfig() +{ + QVariantList list; + QHash snHash; + for (CodeSnippet*& snip : allSnippets) + { + snHash["name"] = snip->name; + snHash["code"] = snip->code; + snHash["hoteky"] = snip->hotkey; + list << snHash; + } + CFG_CORE.Internal.CodeSnippets.set(list); +} + +QString CodeSnippetManager::getCodeByName(const QString& name) const +{ + CodeSnippet* snippet = findFirst(allSnippets, [name](CodeSnippet* snippet) -> bool + { + return snippet->name == name; + }); + return snippet ? snippet->code : QString(); +} + +void CodeSnippetManager::loadFromConfig() +{ + clearSnippets(); + + QVariantList list = CFG_CORE.Internal.CodeSnippets.get(); + QHash snHash; + CodeSnippet* snip = nullptr; + for (const QVariant& var : list) + { + snHash = var.toHash(); + snip = new CodeSnippet(); + snip->name = snHash["name"].toString(); + snip->code = snHash["code"].toString(); + snip->hotkey = snHash["hoteky"].toString(); + allSnippets << snip; + } + refreshNames(); +} + +void CodeSnippetManager::refreshNames() +{ + names = map(allSnippets, [](CodeSnippet* snippet) -> QString + { + return snippet->name; + }); +} + +void CodeSnippetManager::clearSnippets() +{ + for (CodeSnippet*& snip : allSnippets) + delete snip; + + allSnippets.clear(); +} + +void CodeSnippetManager::createDefaultSnippets() +{ + CodeSnippet* snip = new CodeSnippet(); + snip->name = "Create Table"; + snip->code = "CREATE TABLE tableName (\n" + " id INTEGER PRIMARY KEY AUTOINCREMENT,\n" + " value TEXT,\n" + " image BLOB\n" + ");"; + snip->hotkey = "c"; + allSnippets << snip; + + snip = new CodeSnippet(); + snip->name = "With Recursive"; + snip->code = "WITH RECURSIVE\n" + " cnt(x) AS (\n" + " SELECT 1\n" + " UNION ALL\n" + " SELECT x+1 FROM cnt\n" + " LIMIT 1000000\n" + " )\n" + "SELECT x FROM cnt;"; + snip->hotkey = "w"; + allSnippets << snip; + + saveToConfig(); + CFG_CORE.Internal.DefaultSnippetsCreated.set(true); +} diff --git a/SQLiteStudio3/coreSQLiteStudio/services/codesnippetmanager.h b/SQLiteStudio3/coreSQLiteStudio/services/codesnippetmanager.h new file mode 100644 index 0000000..ade14bd --- /dev/null +++ b/SQLiteStudio3/coreSQLiteStudio/services/codesnippetmanager.h @@ -0,0 +1,42 @@ +#ifndef CODESNIPPETMANAGER_H +#define CODESNIPPETMANAGER_H + +#include "coreSQLiteStudio_global.h" +#include + +class Config; + +class API_EXPORT CodeSnippetManager : public QObject +{ + Q_OBJECT + + public: + struct API_EXPORT CodeSnippet + { + QString name; + QString code; + QString hotkey; + }; + + CodeSnippetManager(Config* config); + + void setSnippets(const QList& snippets); + const QList& getSnippets() const; + const QStringList& getNames() const; + void saveToConfig(); + QString getCodeByName(const QString& name) const; + + private: + void loadFromConfig(); + void refreshNames(); + void clearSnippets(); + void createDefaultSnippets(); + + Config* config = nullptr; + QList allSnippets; + QStringList names; +}; + +#define CODESNIPPETS SQLITESTUDIO->getCodeSnippetManager() + +#endif // CODESNIPPETMANAGER_H diff --git a/SQLiteStudio3/coreSQLiteStudio/services/collationmanager.h b/SQLiteStudio3/coreSQLiteStudio/services/collationmanager.h index 5a05b0f..ef1f57a 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/collationmanager.h +++ b/SQLiteStudio3/coreSQLiteStudio/services/collationmanager.h @@ -2,7 +2,6 @@ #define COLLATIONMANAGER_H #include "coreSQLiteStudio_global.h" -#include "common/global.h" #include #include #include diff --git a/SQLiteStudio3/coreSQLiteStudio/services/config.cpp b/SQLiteStudio3/coreSQLiteStudio/services/config.cpp index c03847a..8abd762 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/config.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/services/config.cpp @@ -1,10 +1,14 @@ #include "services/config.h" +#include +#include +#include CFG_DEFINE(Core) static const QString DB_FILE_NAME = QStringLiteral("settings3"); static QString MASTER_CONFIG_FILE = QString(); Config::AskUserForConfigDirFunc Config::askUserForConfigDirFunc; +QSettings* globalSettingsInstance = nullptr; Config::~Config() { @@ -24,3 +28,58 @@ void Config::setAskUserForConfigDirFunc(const AskUserForConfigDirFunc& value) { askUserForConfigDirFunc = value; } + +QString Config::getPortableConfigPath() +{ + QStringList paths = QStringList({"./sqlitestudio-cfg", qApp->applicationDirPath() + "/sqlitestudio-cfg"}); + QSet pathSet; + QDir dir; + for (const QString& path : paths) + { + dir = QDir(path); + pathSet << dir.absolutePath(); + } + + QString potentialPath; + QFileInfo file; + for (const QString& path : pathSet) + { + dir = QDir(path); + file = QFileInfo(dir.absolutePath()); + if (!file.exists()) + { + if (potentialPath.isNull()) + potentialPath = dir.absolutePath(); + + continue; + } + + if (!file.isDir() || !file.isReadable() || !file.isWritable()) + continue; + + for (QFileInfo& entryFile : dir.entryInfoList()) + { + if (!entryFile.isReadable() || !entryFile.isWritable()) + continue; + } + + return dir.absolutePath(); + } + + return potentialPath; +} + +QSettings* Config::getSettings() +{ + if (globalSettingsInstance == nullptr) + { + QString portableConfigPath = Config::getPortableConfigPath(); + QFileInfo portableConfigInfo(portableConfigPath); + if (portableConfigInfo.exists() && portableConfigInfo.isDir() && portableConfigInfo.isReadable()) + globalSettingsInstance = new QSettings(portableConfigPath + "/settings.ini", QSettings::IniFormat); + else + globalSettingsInstance = new QSettings(); + } + + return globalSettingsInstance; +} diff --git a/SQLiteStudio3/coreSQLiteStudio/services/config.h b/SQLiteStudio3/coreSQLiteStudio/services/config.h index 9d1e567..bd001c2 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/config.h +++ b/SQLiteStudio3/coreSQLiteStudio/services/config.h @@ -3,8 +3,6 @@ #include "coreSQLiteStudio_global.h" #include "config_builder.h" -#include "services/functionmanager.h" -#include "collationmanager.h" #include "sqlitestudio.h" #include "common/utils.h" #include @@ -34,11 +32,16 @@ CFG_CATEGORIES(Core, CFG_ENTRY(QVariantList, Functions, QVariantList()) CFG_ENTRY(QVariantList, Collations, QVariantList()) CFG_ENTRY(QVariantList, Extensions, QVariantList()) + CFG_ENTRY(QVariantList, CodeSnippets, QVariantList()) CFG_ENTRY(QString, BugReportUser, QString()) CFG_ENTRY(QString, BugReportPassword, QString()) CFG_ENTRY(QString, BugReportRecentTitle, QString()) CFG_ENTRY(QString, BugReportRecentContents, QString()) CFG_ENTRY(bool, BugReportRecentError, false) + CFG_ENTRY(bool, DefaultSnippetsCreated, false) + ) + CFG_CATEGORY(CodeAssistant, + CFG_ENTRY(bool, AutoTrigger, true) ) ) @@ -46,6 +49,7 @@ CFG_CATEGORIES(Core, class QAbstractItemModel; class DdlHistoryModel; +class QSettings; class API_EXPORT Config : public QObject { @@ -113,9 +117,10 @@ class API_EXPORT Config : public QObject static void setMasterConfigFile(const QString& path); static QString getMasterConfigFile(); static void setAskUserForConfigDirFunc(const AskUserForConfigDirFunc& value); + static QString getPortableConfigPath(); + static QSettings* getSettings(); virtual void init() = 0; - virtual void cleanUp() = 0; virtual const QString& getConfigDir() const = 0; virtual QString getConfigFilePath() const = 0; virtual bool isInMemory() const = 0; diff --git a/SQLiteStudio3/coreSQLiteStudio/services/functionmanager.h b/SQLiteStudio3/coreSQLiteStudio/services/functionmanager.h index 5fb4908..4680b74 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/functionmanager.h +++ b/SQLiteStudio3/coreSQLiteStudio/services/functionmanager.h @@ -2,7 +2,6 @@ #define FUNCTIONMANAGER_H #include "coreSQLiteStudio_global.h" -#include "common/global.h" #include #include #include @@ -37,6 +36,7 @@ class API_EXPORT FunctionManager : public QObject QStringList arguments; Type type = SCALAR; bool undefinedArgs = true; + bool deterministic = false; }; struct API_EXPORT ScriptFunction : public FunctionBase diff --git a/SQLiteStudio3/coreSQLiteStudio/services/impl/collationmanagerimpl.cpp b/SQLiteStudio3/coreSQLiteStudio/services/impl/collationmanagerimpl.cpp index 7d24e47..1cdc59f 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/impl/collationmanagerimpl.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/services/impl/collationmanagerimpl.cpp @@ -6,6 +6,16 @@ #include "common/utils.h" #include +class CollationFunctionInfoImpl : public ScriptingPlugin::FunctionInfo +{ + public: + QString getName() const {return QString();} + QStringList getArguments() const {return {"first", "second"};} + bool getUndefinedArgs() const {return false;} +}; + +CollationFunctionInfoImpl collationFunctionInfo; + CollationManagerImpl::CollationManagerImpl() { init(); @@ -51,7 +61,7 @@ int CollationManagerImpl::evaluate(const QString& name, const QString& value1, c } QString err; - QVariant result = plugin->evaluate(collationsByKey[name]->code, {value1, value2}, &err); + QVariant result = plugin->evaluate(collationsByKey[name]->code, collationFunctionInfo, {value1, value2}, &err); if (!err.isNull()) { @@ -109,7 +119,7 @@ void CollationManagerImpl::loadFromConfig() collHash = var.toHash(); coll = CollationPtr::create(); coll->name = collHash["name"].toString(); - coll->lang = collHash["lang"].toString(); + coll->lang = updateScriptingQtLang(collHash["lang"].toString()); coll->code = collHash["code"].toString(); coll->databases = collHash["databases"].toStringList(); coll->allDatabases = collHash["allDatabases"].toBool(); @@ -123,3 +133,11 @@ void CollationManagerImpl::refreshCollationsByKey() for (CollationPtr collation : collations) collationsByKey[collation->name] = collation; } + +QString CollationManagerImpl::updateScriptingQtLang(const QString& lang) const +{ + if (lang == "QtScript") + return QStringLiteral("JavaScript"); + + return lang; +} diff --git a/SQLiteStudio3/coreSQLiteStudio/services/impl/collationmanagerimpl.h b/SQLiteStudio3/coreSQLiteStudio/services/impl/collationmanagerimpl.h index f5a5937..27adffb 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/impl/collationmanagerimpl.h +++ b/SQLiteStudio3/coreSQLiteStudio/services/impl/collationmanagerimpl.h @@ -23,6 +23,7 @@ class API_EXPORT CollationManagerImpl : public CollationManager void storeInConfig(); void loadFromConfig(); void refreshCollationsByKey(); + QString updateScriptingQtLang(const QString& lang) const; QList collations; QHash collationsByKey; diff --git a/SQLiteStudio3/coreSQLiteStudio/services/impl/configimpl.cpp b/SQLiteStudio3/coreSQLiteStudio/services/impl/configimpl.cpp index 570395a..a7f8d2b 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/impl/configimpl.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/services/impl/configimpl.cpp @@ -610,55 +610,12 @@ QString ConfigImpl::getConfigPath() QString ConfigImpl::getLegacyConfigPath() { #ifdef Q_OS_WIN - if (QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) - return SQLITESTUDIO->getEnv("APPDATA")+"/sqlitestudio"; - else - return SQLITESTUDIO->getEnv("HOME")+"/sqlitestudio"; + return SQLITESTUDIO->getEnv("APPDATA")+"/sqlitestudio"; #else return SQLITESTUDIO->getEnv("HOME")+"/.config/sqlitestudio"; #endif } -QString ConfigImpl::getPortableConfigPath() -{ - QStringList paths = QStringList({"./sqlitestudio-cfg", qApp->applicationDirPath() + "/sqlitestudio-cfg"}); - QSet pathSet; - QDir dir; - for (const QString& path : paths) - { - dir = QDir(path); - pathSet << dir.absolutePath(); - } - - QString potentialPath; - QFileInfo file; - for (const QString& path : pathSet) - { - dir = QDir(path); - file = QFileInfo(dir.absolutePath()); - if (!file.exists()) - { - if (potentialPath.isNull()) - potentialPath = dir.absolutePath(); - - continue; - } - - if (!file.isDir() || !file.isReadable() || !file.isWritable()) - continue; - - for (const QFileInfo& entryFile : dir.entryInfoList()) - { - if (!entryFile.isReadable() || !entryFile.isWritable()) - continue; - } - - return dir.absolutePath(); - } - - return potentialPath; -} - void ConfigImpl::initTables() { SqlQueryPtr results = db->exec("SELECT lower(name) AS name FROM sqlite_master WHERE type = 'table'"); @@ -729,29 +686,18 @@ void ConfigImpl::initTables() void ConfigImpl::initDbFile() { - QList> paths; - - // 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(customPath + "/" + DB_FILE_NAME, false); - qDebug() << "Using custom configuration directory. The location is stored in" << sett.fileName(); - } - else - paths.append(getStdDbPaths()); + QList paths = getStdDbPaths(); // A fallback to in-memory db - paths << QPair(memoryDbName, false); + paths << ConfigDirCandidate{memoryDbName, false, false}; // Go through all candidates and pick one QDir dir; - for (const QPair& path : paths) + for (ConfigDirCandidate& path : paths) { - dir = QDir(path.first); - if (path.first != memoryDbName) - dir = QFileInfo(path.first).dir(); + dir = QDir(path.path); + if (path.path != memoryDbName) + dir = QFileInfo(path.path).dir(); if (tryInitDbFile(path)) { @@ -760,6 +706,19 @@ void ConfigImpl::initDbFile() } } + // If not one of std paths, look for the one from previously saved. + if (configDir == memoryDbName) + { + // Do we have path selected by user? (because app was unable to find writable location before) + QSettings* sett = getSettings(); + QString path = sett->value(CONFIG_DIR_SETTING).toString(); + if (!path.isEmpty()) + { + paths << ConfigDirCandidate{path + "/" + DB_FILE_NAME, false, false}; + qDebug() << "Using custom configuration directory. The location is stored in" << sett->fileName(); + } + } + // Failed to use any of predefined directories. Let's ask the user. while (configDir == memoryDbName) { @@ -768,12 +727,12 @@ void ConfigImpl::initDbFile() break; dir = QDir(path); - if (tryInitDbFile(QPair(path + "/" + DB_FILE_NAME, false))) + if (tryInitDbFile(ConfigDirCandidate{path + "/" + DB_FILE_NAME, false, false})) { configDir = dir.absolutePath(); - QSettings sett; - sett.setValue(CONFIG_DIR_SETTING, configDir); - qDebug() << "Using custom configuration directory. The location is stored in" << sett.fileName(); + QSettings* sett = getSettings(); + sett->setValue(CONFIG_DIR_SETTING, configDir); + qDebug() << "Using custom configuration directory. The location is stored in" << sett->fileName(); } } @@ -782,35 +741,35 @@ void ConfigImpl::initDbFile() { paths.removeLast(); QStringList pathStrings; - for (const QPair& path : paths) - pathStrings << path.first; + for (ConfigDirCandidate& path : paths) + pathStrings << path.path; notifyError(QObject::tr("Could not initialize configuration file. Any configuration changes and queries history will be lost after application restart." " Unable to create a file at following locations: %1.").arg(pathStrings.join(", "))); } - qDebug() << "Using configuration directory:" << configDir; + qDebug().noquote() << "Using configuration directory:" << toNativePath(configDir); db->exec("PRAGMA foreign_keys = 1;"); } -QList> ConfigImpl::getStdDbPaths() +QList ConfigImpl::getStdDbPaths() { - QList> paths; + QList paths; // Portable dir location has always precedense - comes first QString portablePath = getPortableConfigPath(); if (!portablePath.isNull()) - paths << QPair(portablePath+"/"+DB_FILE_NAME, false); + paths << ConfigDirCandidate{portablePath+"/"+DB_FILE_NAME, false, true}; // Determinate global config location QString globalPath = getConfigPath(); - paths << QPair(globalPath, true); + paths << ConfigDirCandidate{globalPath, true, false}; // 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(legacyGlobalPath+"/"+DB_FILE_NAME, true); + paths << ConfigDirCandidate{legacyGlobalPath+"/"+DB_FILE_NAME, true, false}; if (!QFile::exists(globalPath)) tryToMigrateOldGlobalPath(legacyGlobalPath, globalPath); } @@ -818,17 +777,17 @@ QList> ConfigImpl::getStdDbPaths() return paths; } -bool ConfigImpl::tryInitDbFile(const QPair &dbPath) +bool ConfigImpl::tryInitDbFile(const ConfigDirCandidate& dbPath) { // Create global config directory if not existing - if (dbPath.second && !dbPath.first.isNull()) + if (dbPath.createIfNotExists && !dbPath.path.isNull()) { - QDir dir(dbPath.first.mid(0, dbPath.first.length() - DB_FILE_NAME.length() - 1)); + QDir dir(dbPath.path.mid(0, dbPath.path.length() - DB_FILE_NAME.length() - 1)); if (!dir.exists()) QDir::root().mkpath(dir.absolutePath()); } - db = new DbSqlite3("SQLiteStudio settings", dbPath.first, {{DB_PURE_INIT, true}}); + db = new DbSqlite3("SQLiteStudio settings", dbPath.path, {{DB_PURE_INIT, true}}); if (!db->open()) { safe_delete(db); @@ -1185,7 +1144,7 @@ bool ConfigImpl::tryToMigrateOldGlobalPath(const QString& oldPath, const QString if (!QFileInfo::exists(oldPath)) return false; - qDebug() << "Attempting to migrate legacy config location" << oldPath << "to new location" << newPath; + qDebug().noquote() << "Attempting to migrate legacy config location" << toNativePath(oldPath) << "to new location" << toNativePath(newPath); QDir dir = QFileInfo(newPath).dir(); if (!dir.exists()) QDir::root().mkpath(dir.absolutePath()); diff --git a/SQLiteStudio3/coreSQLiteStudio/services/impl/configimpl.h b/SQLiteStudio3/coreSQLiteStudio/services/impl/configimpl.h index 710fbb3..9f0f36e 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/impl/configimpl.h +++ b/SQLiteStudio3/coreSQLiteStudio/services/impl/configimpl.h @@ -8,6 +8,7 @@ class AsyncConfigHandler; class SqlHistoryModel; +class QSettings; class API_EXPORT ConfigImpl : public Config { @@ -90,6 +91,13 @@ class API_EXPORT ConfigImpl : public Config void rollback(); private: + struct ConfigDirCandidate + { + QString path; + bool createIfNotExists; + bool isPortable; + }; + /** * @brief Stores error from query in class member. * @param query Query to get error from. @@ -102,11 +110,10 @@ class API_EXPORT ConfigImpl : public Config void storeGroup(const DbGroupPtr& group, qint64 parentId = -1); void readGroupRecursively(DbGroupPtr group); QString getConfigPath(); - QString getPortableConfigPath(); void initTables(); void initDbFile(); - QList > getStdDbPaths(); - bool tryInitDbFile(const QPair& dbPath); + QList getStdDbPaths(); + bool tryInitDbFile(const ConfigDirCandidate& dbPath); QVariant deserializeValue(const QVariant& value) const; void asyncAddSqlHistory(qint64 id, const QString& sql, const QString& dbName, int timeSpentMillis, int rowsAffected); diff --git a/SQLiteStudio3/coreSQLiteStudio/services/impl/dbmanagerimpl.cpp b/SQLiteStudio3/coreSQLiteStudio/services/impl/dbmanagerimpl.cpp index 9086257..6258f71 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/impl/dbmanagerimpl.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/services/impl/dbmanagerimpl.cpp @@ -24,7 +24,7 @@ DbManagerImpl::DbManagerImpl(QObject *parent) : DbManagerImpl::~DbManagerImpl() { // qDebug() << "DbManagerImpl::~DbManagerImpl()"; - for (Db* db : dbList) + for (Db*& db : dbList) { disconnect(db, SIGNAL(disconnected()), this, SLOT(dbDisconnectedSlot())); disconnect(db, SIGNAL(aboutToDisconnect(bool&)), this, SLOT(dbAboutToDisconnect(bool&))); @@ -61,7 +61,7 @@ bool DbManagerImpl::addDb(const QString &name, const QString &path, const QHash< Db* db = createDb(name, path, options, &errorMessage); if (!db) { - notifyError(tr("Could not add database %1: %2").arg(path).arg(errorMessage)); + notifyError(tr("Could not add database %1: %2").arg(path, errorMessage)); return false; } @@ -93,8 +93,6 @@ bool DbManagerImpl::updateDb(Db* db, const QString &name, const QString &path, c nameToDb.remove(db->getName(), Qt::CaseInsensitive); pathToDb.remove(db->getPath()); - bool pathDifferent = db->getPath() != normalizedPath; - QString oldName = db->getName(); db->setName(name); db->setPath(normalizedPath); @@ -114,7 +112,7 @@ bool DbManagerImpl::updateDb(Db* db, const QString &name, const QString &path, c InvalidDb* invalidDb = dynamic_cast(db); bool wasReloaded = false; Db* reloadedDb = db; - if (pathDifferent && invalidDb) + if (invalidDb) { reloadedDb = tryToLoadDb(invalidDb, false); if (reloadedDb) // we need to know that, so we can emit dbLoaded() signal later, out of the listLock @@ -136,7 +134,7 @@ bool DbManagerImpl::updateDb(Db* db, const QString &name, const QString &path, c if (result && reloadedDb) emit dbUpdated(oldName, db); else if (reloadedDb) // database reloaded correctly, but update failed - notifyError(tr("Database %1 could not be updated, because of an error: %2").arg(oldName).arg(CFG->getLastErrorString())); + notifyError(tr("Database %1 could not be updated, because of an error: %2").arg(oldName, CFG->getLastErrorString())); return result; } @@ -297,7 +295,7 @@ DbPlugin* DbManagerImpl::getPluginForDbFile(const QString& filePath) QHash options; Db* probeDb = nullptr; - for (DbPlugin* plugin : dbPlugins) + for (DbPlugin*& plugin : dbPlugins) { probeDb = plugin->getInstance("", filePath, options); if (probeDb) @@ -346,7 +344,7 @@ void DbManagerImpl::loadInitialDbList() { QUrl url; InvalidDb* db = nullptr; - for (const Config::CfgDbPtr& cfgDb : CFG->dbList()) + for (Config::CfgDbPtr& cfgDb : CFG->dbList()) { db = new InvalidDb(cfgDb->name, cfgDb->path, cfgDb->options); @@ -372,7 +370,7 @@ void DbManagerImpl::scanForNewDatabasesInConfig() QUrl url; InvalidDb* db = nullptr; - for (const Config::CfgDbPtr& cfgDb : cfgDbList) + for (Config::CfgDbPtr& cfgDb : cfgDbList) { if (getByName(cfgDb->name) || getByPath(cfgDb->path)) continue; @@ -402,13 +400,13 @@ void DbManagerImpl::rescanInvalidDatabasesForPlugin(DbPlugin* dbPlugin) QUrl url; QString errorMessages; - for (Db* invalidDb : getInvalidDatabases()) + for (Db*& invalidDb : getInvalidDatabases()) { if (invalidDb->getConnectionOptions().contains(DB_PLUGIN) && invalidDb->getConnectionOptions()[DB_PLUGIN].toString() != dbPlugin->getName()) continue; url = QUrl::fromUserInput(invalidDb->getPath()); - if (url.isLocalFile() && !QFile::exists(invalidDb->getPath())) + if (url.isLocalFile() && !QFile::exists(invalidDb->getPath()) && invalidDb->getPath() != ":memory:") continue; errorMessages = QString(); @@ -424,7 +422,7 @@ void DbManagerImpl::rescanInvalidDatabasesForPlugin(DbPlugin* dbPlugin) if (!dbPlugin->checkIfDbServedByPlugin(db)) { - qDebug() << "Managed to load database" << db->getPath() << " (" << db->getName() << ")" + qDebug().noquote() << "Managed to load database" << toNativePath(db->getPath()) << " (" << db->getName() << ")" << "but it doesn't use DbPlugin that was just loaded, so it will not be loaded to the db manager"; delete db; @@ -473,10 +471,6 @@ QList DbManagerImpl::getInvalidDatabases() const Db* DbManagerImpl::tryToLoadDb(InvalidDb* invalidDb, bool emitNotifySignal) { - QUrl url = QUrl::fromUserInput(invalidDb->getPath()); - if (url.isLocalFile() && !QFile::exists(invalidDb->getPath())) - return nullptr; - Db* db = createDb(invalidDb->getName(), invalidDb->getPath(), invalidDb->getConnectionOptions()); if (!db) return nullptr; @@ -588,7 +582,7 @@ void DbManagerImpl::aboutToUnload(Plugin* plugin, PluginType* type) DbPlugin* dbPlugin = dynamic_cast(plugin); dbPlugins.removeOne(dbPlugin); QList toRemove; - for (Db* db : dbList) + for (Db*& db : dbList) { if (!dbPlugin->checkIfDbServedByPlugin(db)) continue; @@ -596,7 +590,7 @@ void DbManagerImpl::aboutToUnload(Plugin* plugin, PluginType* type) toRemove << db; } - for (Db* db : toRemove) + for (Db*& db : toRemove) { emit dbAboutToBeUnloaded(db, dbPlugin); diff --git a/SQLiteStudio3/coreSQLiteStudio/services/impl/functionmanagerimpl.cpp b/SQLiteStudio3/coreSQLiteStudio/services/impl/functionmanagerimpl.cpp index 2fcc689..1b49f3b 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/impl/functionmanagerimpl.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/services/impl/functionmanagerimpl.cpp @@ -18,6 +18,50 @@ #include #include +class FunctionInfoImpl : public ScriptingPlugin::FunctionInfo +{ + public: + FunctionInfoImpl(FunctionManager::FunctionBase* fn); + FunctionInfoImpl(); + + QString getName() const; + QStringList getArguments() const; + bool getUndefinedArgs() const; + + private: + QString name; + QStringList arguments; + bool undefinedArgs = true; +}; + +FunctionInfoImpl::FunctionInfoImpl(FunctionManager::FunctionBase* fn) +{ + name = fn->name; + arguments = fn->arguments; + undefinedArgs = fn->undefinedArgs; +} + +FunctionInfoImpl::FunctionInfoImpl() +{ +} + +QString FunctionInfoImpl::getName() const +{ + return name; +} + +QStringList FunctionInfoImpl::getArguments() const +{ + return arguments; +} + +bool FunctionInfoImpl::getUndefinedArgs() const +{ + return undefinedArgs; +} + + + FunctionManagerImpl::FunctionManagerImpl() { init(); @@ -120,14 +164,15 @@ QVariant FunctionManagerImpl::evaluateScriptScalar(ScriptFunction* func, const Q return langUnsupportedError(name, argCount, func->lang); } DbAwareScriptingPlugin* dbAwarePlugin = dynamic_cast(plugin); + FunctionInfoImpl info(func); QString error; QVariant result; if (dbAwarePlugin) - result = dbAwarePlugin->evaluate(func->code, args, db, false, &error); + result = dbAwarePlugin->evaluate(func->code, info, args, db, false, &error); else - result = plugin->evaluate(func->code, args, &error); + result = plugin->evaluate(func->code, info, args, &error); if (!error.isEmpty()) { @@ -147,11 +192,12 @@ void FunctionManagerImpl::evaluateScriptAggregateInitial(ScriptFunction* func, D ScriptingPlugin::Context* ctx = plugin->createContext(); aggregateStorage["context"] = QVariant::fromValue(ctx); + FunctionInfoImpl info(func); if (dbAwarePlugin) - dbAwarePlugin->evaluate(ctx, func->initCode, {}, db, false); + dbAwarePlugin->evaluate(ctx, func->initCode, info, {}, db, false); else - plugin->evaluate(ctx, func->initCode, {}); + plugin->evaluate(ctx, func->initCode, info, {}); if (plugin->hasError(ctx)) { @@ -170,12 +216,13 @@ void FunctionManagerImpl::evaluateScriptAggregateStep(ScriptFunction* func, cons return; DbAwareScriptingPlugin* dbAwarePlugin = dynamic_cast(plugin); + FunctionInfoImpl info(func); ScriptingPlugin::Context* ctx = aggregateStorage["context"].value(); if (dbAwarePlugin) - dbAwarePlugin->evaluate(ctx, func->code, args, db, false); + dbAwarePlugin->evaluate(ctx, func->code, info, args, db, false); else - plugin->evaluate(ctx, func->code, args); + plugin->evaluate(ctx, func->code, info, args); if (plugin->hasError(ctx)) { @@ -203,11 +250,13 @@ QVariant FunctionManagerImpl::evaluateScriptAggregateFinal(ScriptFunction* func, DbAwareScriptingPlugin* dbAwarePlugin = dynamic_cast(plugin); + FunctionInfoImpl info(func); + QVariant result; if (dbAwarePlugin) - result = dbAwarePlugin->evaluate(ctx, func->finalCode, {}, db, false); + result = dbAwarePlugin->evaluate(ctx, func->finalCode, info, {}, db, false); else - result = plugin->evaluate(ctx, func->finalCode, {}); + result = plugin->evaluate(ctx, func->finalCode, info, {}); if (plugin->hasError(ctx)) { @@ -320,7 +369,7 @@ void FunctionManagerImpl::loadFromConfig() fnHash = var.toHash(); func = new ScriptFunction(); func->name = fnHash["name"].toString(); - func->lang = fnHash["lang"].toString(); + func->lang = updateScriptingQtLang(fnHash["lang"].toString()); func->code = fnHash["code"].toString(); func->initCode = fnHash["initCode"].toString(); func->finalCode = fnHash["finalCode"].toString(); @@ -335,7 +384,7 @@ void FunctionManagerImpl::loadFromConfig() void FunctionManagerImpl::clearFunctions() { - for (ScriptFunction* fn : functions) + for (ScriptFunction*& fn : functions) delete fn; functions.clear(); @@ -483,14 +532,15 @@ QVariant FunctionManagerImpl::nativeScript(const QList& args, Db* db, return tr("Unsupported scripting language: %1").arg(args[0].toString()); } DbAwareScriptingPlugin* dbAwarePlugin = dynamic_cast(plugin); + FunctionInfoImpl info; QString error; QVariant result; if (dbAwarePlugin) - result = dbAwarePlugin->evaluate(args[1].toString(), QList(), db, false, &error); + result = dbAwarePlugin->evaluate(args[1].toString(), info, QList(), db, false, &error); else - result = plugin->evaluate(args[1].toString(), QList(), &error); + result = plugin->evaluate(args[1].toString(), info, QList(), &error); if (!error.isEmpty()) { @@ -781,6 +831,14 @@ void FunctionManagerImpl::registerNativeFunction(const QString& name, const QStr nativeFunctions << nf; } +QString FunctionManagerImpl::updateScriptingQtLang(const QString& lang) const +{ + if (lang == "QtScript") + return QStringLiteral("JavaScript"); + + return lang; +} + int qHash(const FunctionManagerImpl::Key& key) { return qHash(key.name) ^ key.argCount ^ static_cast(key.type); diff --git a/SQLiteStudio3/coreSQLiteStudio/services/impl/functionmanagerimpl.h b/SQLiteStudio3/coreSQLiteStudio/services/impl/functionmanagerimpl.h index 0e5e103..26f4ae2 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/impl/functionmanagerimpl.h +++ b/SQLiteStudio3/coreSQLiteStudio/services/impl/functionmanagerimpl.h @@ -56,6 +56,7 @@ class API_EXPORT FunctionManagerImpl : public FunctionManager QString cannotFindFunctionError(const QString& name, int argCount); QString langUnsupportedError(const QString& name, int argCount, const QString& lang); void registerNativeFunction(const QString& name, const QStringList& args, NativeFunction::ImplementationFunction funcPtr); + QString updateScriptingQtLang(const QString& lang) const; static QStringList getArgMarkers(int argCount); static QVariant nativeRegExp(const QList& args, Db* db, bool& ok); diff --git a/SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.cpp b/SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.cpp index 324f549..dc36980 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.cpp @@ -38,7 +38,7 @@ void PluginManagerImpl::init() #endif #ifdef Q_OS_MACX - pluginDirs += QCoreApplication::applicationDirPath()+"/../PlugIns"; + pluginDirs += QDir(QCoreApplication::applicationDirPath()+"/../PlugIns").absolutePath(); #endif scanPlugins(); @@ -50,7 +50,7 @@ void PluginManagerImpl::deinit() emit aboutToQuit(); // Plugin containers and their plugins - for (PluginContainer* container : pluginContainer.values()) + for (PluginContainer*& container : pluginContainer.values()) { if (container->builtIn) { @@ -61,13 +61,13 @@ void PluginManagerImpl::deinit() unload(container->name); } - for (PluginContainer* container : pluginContainer.values()) + for (PluginContainer*& container : pluginContainer.values()) delete container; pluginContainer.clear(); // Types - for (PluginType* type : registeredPluginTypes) + for (PluginType*& type : registeredPluginTypes) delete type; registeredPluginTypes.clear(); @@ -109,14 +109,11 @@ PluginType* PluginManagerImpl::getPluginType(Plugin* plugin) const void PluginManagerImpl::scanPlugins() { - QStringList nameFilters; - nameFilters << "*.so" << "*.dll" << "*.dylib"; - QPluginLoader* loader = nullptr; - for (QString pluginDirPath : pluginDirs) + for (QString& pluginDirPath : pluginDirs) { QDir pluginDir(pluginDirPath); - for (QString fileName : pluginDir.entryList(nameFilters, QDir::Files)) + for (QString& fileName : pluginDir.entryList(sharedLibFileFilters(), QDir::Files)) { fileName = pluginDir.absoluteFilePath(fileName); loader = new QPluginLoader(fileName); @@ -131,7 +128,7 @@ void PluginManagerImpl::scanPlugins() } QStringList names; - for (PluginContainer* container : pluginContainer.values()) + for (PluginContainer*& container : pluginContainer.values()) { if (!container->builtIn) names << container->name; @@ -143,7 +140,7 @@ void PluginManagerImpl::scanPlugins() void PluginManagerImpl::loadPlugins() { QStringList alreadyAttempted; - for (const QString& pluginName : pluginContainer.keys()) + for (QString& pluginName : pluginContainer.keys()) { if (shouldAutoLoad(pluginName)) load(pluginName, alreadyAttempted); @@ -158,7 +155,7 @@ bool PluginManagerImpl::initPlugin(QPluginLoader* loader, const QString& fileNam QJsonObject pluginMetaData = loader->metaData(); QString pluginTypeName = pluginMetaData.value("MetaData").toObject().value("type").toString(); PluginType* pluginType = nullptr; - for (PluginType* type : registeredPluginTypes) + for (PluginType*& type : registeredPluginTypes) { if (type->getName() == pluginTypeName) { @@ -453,12 +450,12 @@ void PluginManagerImpl::unload(const QString& pluginName) return; // Unloading depdendent plugins - for (PluginContainer* otherContainer : pluginContainer.values()) + for (PluginContainer*& otherContainer : pluginContainer.values()) { if (otherContainer == container) continue; - for (const PluginDependency& dep : otherContainer->dependencies) + for (PluginDependency& dep : otherContainer->dependencies) { if (dep.name == pluginName) { @@ -472,9 +469,9 @@ void PluginManagerImpl::unload(const QString& pluginName) removePluginFromCollections(container->plugin); // Deinitializing and unloading plugin + unloadTranslation(container->name); emit aboutToUnload(container->plugin, container->type); container->plugin->deinit(); - unloadTranslation(container->name); QPluginLoader* loader = container->loader; if (!loader->isLoaded()) @@ -491,7 +488,7 @@ void PluginManagerImpl::unload(const QString& pluginName) emit unloaded(container->name, container->type); - qDebug() << pluginName << "unloaded:" << container->filePath; + qDebug().noquote() << pluginName << "unloaded:" << toNativePath(container->filePath); } bool PluginManagerImpl::load(const QString& pluginName) @@ -596,7 +593,15 @@ void PluginManagerImpl::pluginLoaded(PluginManagerImpl::PluginContainer* contain { if (!container->builtIn) { - loadTranslation(container->name); + QString tsName = container->translationName.isEmpty() ? + ( + container->name.endsWith("Plugin") ? + container->name.left(container->name.length() - 6) : + container->name + ) : + container->translationName; + + loadTranslation(tsName); container->plugin = dynamic_cast(container->loader->instance()); container->loaded = true; } @@ -604,7 +609,7 @@ void PluginManagerImpl::pluginLoaded(PluginManagerImpl::PluginContainer* contain emit loaded(container->plugin, container->type); if (!container->builtIn) - qDebug() << container->name << "loaded:" << container->filePath; + qDebug().noquote() << container->name << "loaded:" << toNativePath(container->filePath); } void PluginManagerImpl::addPluginToCollections(Plugin* plugin) @@ -618,7 +623,7 @@ void PluginManagerImpl::removePluginFromCollections(Plugin* plugin) { ScriptingPlugin* scriptingPlugin = dynamic_cast(plugin); if (scriptingPlugin && scriptingPlugins.contains(scriptingPlugin->getLanguage())) - scriptingPlugins.remove(plugin->getName()); + scriptingPlugins.remove(scriptingPlugin->getLanguage()); } bool PluginManagerImpl::readMetaData(PluginManagerImpl::PluginContainer* container) @@ -633,6 +638,7 @@ bool PluginManagerImpl::readMetaData(PluginManagerImpl::PluginContainer* contain container->description = metaData["description"].toString(); container->title = metaData["title"].toString(); container->loadByDefault = metaData.contains("loadByDefault") ? metaData["loadByDefault"].toBool() : true; + container->translationName = metaData.contains("translationName") ? metaData["translationName"].toString() : QString(); } else if (container->plugin) { diff --git a/SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.h b/SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.h index c9d56aa..7a8ba4f 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.h +++ b/SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.h @@ -156,6 +156,21 @@ class API_EXPORT PluginManagerImpl : public PluginManager * @brief Names of plugins that this plugin conflicts with. */ QStringList conflicts; + + /** + * @brief If not empty, contains Plugin's project name to be used for loading translation resource file. + * + * For typical SQLiteStudio plugin the auto-generated translation resource name is the same + * as the name of the plugin project. Typically, name of loaded plugin class is made of + * the name of the plugin project and the "Plugin" word suffix. Therefore SQLiteStudio + * by default just removes the "Plugin" suffix (if it has such) and attempts to load the translation + * named this way. + * + * If the main Plugin class does not follow this naming strategy (project name + Plugin suffix), + * then the translationName should be specified in plugin's metadata, + * giving actual name of translation resource (i.e. name of Plugin's source code project) to be loaded. + */ + QString translationName; }; /** diff --git a/SQLiteStudio3/coreSQLiteStudio/services/impl/sqliteextensionmanagerimpl.cpp b/SQLiteStudio3/coreSQLiteStudio/services/impl/sqliteextensionmanagerimpl.cpp index 63dbaf6..d5cc4f6 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/impl/sqliteextensionmanagerimpl.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/services/impl/sqliteextensionmanagerimpl.cpp @@ -1,6 +1,8 @@ #include "sqliteextensionmanagerimpl.h" -#include "services/notifymanager.h" #include "services/dbmanager.h" +#include +#include +#include SqliteExtensionManagerImpl::SqliteExtensionManagerImpl() { @@ -30,21 +32,66 @@ QList SqliteExtensionManagerImpl::getExten return results; } +QStringList SqliteExtensionManagerImpl::getExtensionDirs() const +{ + return extensionDirs; +} + void SqliteExtensionManagerImpl::init() { loadFromConfig(); + scanExtensionDirs(); +} + +void SqliteExtensionManagerImpl::scanExtensionDirs() +{ + extensionDirs += qApp->applicationDirPath() + "/extensions"; + extensionDirs += qApp->applicationDirPath() + "/ext"; + extensionDirs += QDir(CFG->getConfigDir()).absoluteFilePath("ext"); + extensionDirs += QDir(CFG->getConfigDir()).absoluteFilePath("extensions"); +#ifdef Q_OS_MACX + extensionDirs += QDir(QCoreApplication::applicationDirPath()+"/../extensions").absolutePath(); +#endif + + QString envDirs = SQLITESTUDIO->getEnv("SQLITESTUDIO_SQLITE_EXTENSIONS"); + if (!envDirs.isNull()) + extensionDirs += envDirs.split(PATH_LIST_SEPARATOR); + +#ifdef SQLITE_EXTENSIONS_DIR + extensionDirs += STRINGIFY(SQLITE_EXTENSIONS_DIR); +#endif + + for (QString& extDirPath : extensionDirs) + { + QDir extDir(extDirPath); + for (QString& fileName : extDir.entryList(sharedLibFileFilters(), QDir::Files)) + { + QString path = extDir.absoluteFilePath(fileName); + auto findIt = std::find_if(extensions.begin(), extensions.end(), [path](ExtensionPtr& ext) {return ext->filePath == path;}); + if (findIt != extensions.end()) + continue; // already on the list + + ExtensionPtr ext = ExtensionPtr::create(); + ext->filePath = path; + ext->initFunc = QString(); + ext->databases = QStringList(); + ext->allDatabases = false; + extensions << ext; + qDebug() << "SQLite extension:" << path; + } + } } void SqliteExtensionManagerImpl::storeInConfig() { QVariantList list; QHash extHash; - for (ExtensionPtr ext : extensions) + for (ExtensionPtr& ext : extensions) { extHash["filePath"] = ext->filePath; extHash["initFunc"] = ext->initFunc; extHash["allDatabases"] = ext->allDatabases; - extHash["databases"] =common(DBLIST->getDbNames(), ext->databases); + extHash["databases"] = common(DBLIST->getDbNames(), ext->databases); list << extHash; } CFG_CORE.Internal.Extensions.set(list); @@ -66,5 +113,6 @@ void SqliteExtensionManagerImpl::loadFromConfig() ext->databases = extHash["databases"].toStringList(); ext->allDatabases = extHash["allDatabases"].toBool(); extensions << ext; + qDebug() << "SQLite extension from config:" << ext->filePath; } } diff --git a/SQLiteStudio3/coreSQLiteStudio/services/impl/sqliteextensionmanagerimpl.h b/SQLiteStudio3/coreSQLiteStudio/services/impl/sqliteextensionmanagerimpl.h index 6fd7f46..9414c0a 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/impl/sqliteextensionmanagerimpl.h +++ b/SQLiteStudio3/coreSQLiteStudio/services/impl/sqliteextensionmanagerimpl.h @@ -11,13 +11,16 @@ class SqliteExtensionManagerImpl : public SqliteExtensionManager void setExtensions(const QList& newExtensions); QList getAllExtensions() const; QList getExtensionForDatabase(const QString& dbName) const; + QStringList getExtensionDirs() const; private: void init(); + void scanExtensionDirs(); void storeInConfig(); void loadFromConfig(); QList extensions; + QStringList extensionDirs; }; #endif // SQLITEEXTENSIONMANAGERIMPL_H diff --git a/SQLiteStudio3/coreSQLiteStudio/services/notifymanager.cpp b/SQLiteStudio3/coreSQLiteStudio/services/notifymanager.cpp index f8b7f25..977897f 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/notifymanager.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/services/notifymanager.cpp @@ -36,7 +36,7 @@ void NotifyManager::deleted(Db* db, const QString& database, const QString& obje emit objectDeleted(db, database, object); } -void NotifyManager::createded(Db* db, const QString& database, const QString& object) +void NotifyManager::created(Db* db, const QString& database, const QString& object) { emit objectCreated(db, database, object); } diff --git a/SQLiteStudio3/coreSQLiteStudio/services/notifymanager.h b/SQLiteStudio3/coreSQLiteStudio/services/notifymanager.h index 5bb4571..517ecf4 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/notifymanager.h +++ b/SQLiteStudio3/coreSQLiteStudio/services/notifymanager.h @@ -36,7 +36,7 @@ class API_EXPORT NotifyManager : public QObject void modified(Db* db, const QString& database, const QString& object); void deleted(Db* db, const QString& database, const QString& object); - void createded(Db* db, const QString& database, const QString& object); + void created(Db* db, const QString& database, const QString& object); void renamed(Db* db, const QString& database, const QString& oldObject, const QString& newObject); private: diff --git a/SQLiteStudio3/coreSQLiteStudio/services/sqliteextensionmanager.h b/SQLiteStudio3/coreSQLiteStudio/services/sqliteextensionmanager.h index a135f3b..9d5cd1c 100644 --- a/SQLiteStudio3/coreSQLiteStudio/services/sqliteextensionmanager.h +++ b/SQLiteStudio3/coreSQLiteStudio/services/sqliteextensionmanager.h @@ -24,6 +24,7 @@ class API_EXPORT SqliteExtensionManager : public QObject virtual void setExtensions(const QList& newExtensions) = 0; virtual QList getAllExtensions() const = 0; virtual QList getExtensionForDatabase(const QString& dbName) const = 0; + virtual QStringList getExtensionDirs() const = 0; signals: void extensionListChanged(); -- cgit v1.2.3