aboutsummaryrefslogtreecommitdiffstats
path: root/SQLiteStudio3/coreSQLiteStudio/services/impl
diff options
context:
space:
mode:
Diffstat (limited to 'SQLiteStudio3/coreSQLiteStudio/services/impl')
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/services/impl/collationmanagerimpl.cpp22
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/services/impl/collationmanagerimpl.h1
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/services/impl/configimpl.cpp115
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/services/impl/configimpl.h13
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/services/impl/dbmanagerimpl.cpp30
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/services/impl/functionmanagerimpl.cpp82
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/services/impl/functionmanagerimpl.h1
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.cpp44
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.h15
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/services/impl/sqliteextensionmanagerimpl.cpp54
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/services/impl/sqliteextensionmanagerimpl.h3
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