diff options
Diffstat (limited to 'SQLiteStudio3/coreSQLiteStudio/services/impl')
11 files changed, 245 insertions, 135 deletions
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 <QDebug> +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<CollationPtr> collations; QHash<QString,CollationPtr> 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<QString> 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<QPair<QString,bool>> 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<QString,bool>(customPath + "/" + DB_FILE_NAME, false); - qDebug() << "Using custom configuration directory. The location is stored in" << sett.fileName(); - } - else - paths.append(getStdDbPaths()); + QList<ConfigDirCandidate> paths = getStdDbPaths(); // A fallback to in-memory db - paths << QPair<QString,bool>(memoryDbName, false); + paths << ConfigDirCandidate{memoryDbName, false, false}; // Go through all candidates and pick one QDir dir; - for (const QPair<QString,bool>& 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<QString,bool>(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<QString,bool>& 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<QPair<QString,bool>> ConfigImpl::getStdDbPaths() +QList<ConfigImpl::ConfigDirCandidate> ConfigImpl::getStdDbPaths() { - QList<QPair<QString,bool>> paths; + QList<ConfigDirCandidate> paths; // Portable dir location has always precedense - comes first QString portablePath = getPortableConfigPath(); if (!portablePath.isNull()) - paths << QPair<QString,bool>(portablePath+"/"+DB_FILE_NAME, false); + paths << ConfigDirCandidate{portablePath+"/"+DB_FILE_NAME, false, true}; // Determinate global config location QString globalPath = getConfigPath(); - paths << QPair<QString,bool>(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<QString,bool>(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<QPair<QString,bool>> ConfigImpl::getStdDbPaths() return paths; } -bool ConfigImpl::tryInitDbFile(const QPair<QString, bool> &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<QPair<QString, bool> > getStdDbPaths(); - bool tryInitDbFile(const QPair<QString, bool>& dbPath); + QList<ConfigDirCandidate> 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<InvalidDb*>(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<QString,QVariant> 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<Db*> 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<DbPlugin*>(plugin); dbPlugins.removeOne(dbPlugin); QList<Db*> 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 <QUrl> #include <plugins/importplugin.h> +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<DbAwareScriptingPlugin*>(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<DbAwareScriptingPlugin*>(plugin); + FunctionInfoImpl info(func); ScriptingPlugin::Context* ctx = aggregateStorage["context"].value<ScriptingPlugin::Context*>(); 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<DbAwareScriptingPlugin*>(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<QVariant>& args, Db* db, return tr("Unsupported scripting language: %1").arg(args[0].toString()); } DbAwareScriptingPlugin* dbAwarePlugin = dynamic_cast<DbAwareScriptingPlugin*>(plugin); + FunctionInfoImpl info; QString error; QVariant result; if (dbAwarePlugin) - result = dbAwarePlugin->evaluate(args[1].toString(), QList<QVariant>(), db, false, &error); + result = dbAwarePlugin->evaluate(args[1].toString(), info, QList<QVariant>(), db, false, &error); else - result = plugin->evaluate(args[1].toString(), QList<QVariant>(), &error); + result = plugin->evaluate(args[1].toString(), info, QList<QVariant>(), &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<int>(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<QVariant>& 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<Plugin*>(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<ScriptingPlugin*>(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 <QCoreApplication> +#include <QDir> +#include <QDebug> SqliteExtensionManagerImpl::SqliteExtensionManagerImpl() { @@ -30,21 +32,66 @@ QList<SqliteExtensionManager::ExtensionPtr> 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<QString,QVariant> 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<ExtensionPtr>& newExtensions); QList<ExtensionPtr> getAllExtensions() const; QList<ExtensionPtr> getExtensionForDatabase(const QString& dbName) const; + QStringList getExtensionDirs() const; private: void init(); + void scanExtensionDirs(); void storeInConfig(); void loadFromConfig(); QList<ExtensionPtr> extensions; + QStringList extensionDirs; }; #endif // SQLITEEXTENSIONMANAGERIMPL_H |
