1 #include "sqlitestudio.h"
2 #include "plugins/plugin.h"
3 #include "services/pluginmanager.h"
4 #include "common/utils.h"
5 #include "common/utils_sql.h"
6 #include "completionhelper.h"
7 #include "parser/keywords.h"
8 #include "parser/lexer.h"
9 #include "services/notifymanager.h"
10 #include "plugins/codeformatterplugin.h"
11 #include "services/codeformatter.h"
12 #include "plugins/generalpurposeplugin.h"
13 #include "plugins/dbplugin.h"
14 #include "common/unused.h"
15 #include "services/functionmanager.h"
16 #include "plugins/scriptingplugin.h"
17 #include "plugins/exportplugin.h"
18 #include "plugins/scriptingqt.h"
19 #include "plugins/dbpluginsqlite3.h"
20 #include "services/impl/configimpl.h"
21 #include "services/impl/dbmanagerimpl.h"
22 #include "services/impl/functionmanagerimpl.h"
23 #include "services/impl/collationmanagerimpl.h"
24 #include "services/impl/pluginmanagerimpl.h"
25 #include "services/impl/sqliteextensionmanagerimpl.h"
26 #include "services/updatemanager.h"
27 #include "impl/dbattacherimpl.h"
28 #include "services/exportmanager.h"
29 #include "services/importmanager.h"
30 #include "services/populatemanager.h"
31 #include "plugins/scriptingsql.h"
32 #include "plugins/importplugin.h"
33 #include "plugins/populateplugin.h"
34 #include "services/extralicensemanager.h"
35 #include "services/sqliteextensionmanager.h"
36 #include "translations.h"
37 #include <QProcessEnvironment>
38 #include <QThreadPool>
39 #include <QCoreApplication>
40 
41 DEFINE_SINGLETON(SQLiteStudio)
42 
43 static const int sqlitestudioVersion = 30303;
44 
SQLiteStudio()45 SQLiteStudio::SQLiteStudio()
46 {
47     if (qApp) // qApp is null in unit tests
48         connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(cleanUp()));
49 }
50 
~SQLiteStudio()51 SQLiteStudio::~SQLiteStudio()
52 {
53 }
getInitialTranslationFiles() const54 QStringList SQLiteStudio::getInitialTranslationFiles() const
55 {
56     return initialTranslationFiles;
57 }
58 
setInitialTranslationFiles(const QStringList & value)59 void SQLiteStudio::setInitialTranslationFiles(const QStringList& value)
60 {
61     initialTranslationFiles = value;
62 }
63 
64 
getCurrentLang() const65 QString SQLiteStudio::getCurrentLang() const
66 {
67     return currentLang;
68 }
69 
getExtraLicenseManager() const70 ExtraLicenseManager* SQLiteStudio::getExtraLicenseManager() const
71 {
72     return extraLicenseManager;
73 }
74 
setExtraLicenseManager(ExtraLicenseManager * value)75 void SQLiteStudio::setExtraLicenseManager(ExtraLicenseManager* value)
76 {
77     extraLicenseManager = value;
78 }
79 
80 
getImmediateQuit() const81 bool SQLiteStudio::getImmediateQuit() const
82 {
83     return immediateQuit;
84 }
85 
setImmediateQuit(bool value)86 void SQLiteStudio::setImmediateQuit(bool value)
87 {
88     immediateQuit = value;
89 }
90 
91 #ifdef PORTABLE_CONFIG
getUpdateManager() const92 UpdateManager* SQLiteStudio::getUpdateManager() const
93 {
94     return updateManager;
95 }
96 
setUpdateManager(UpdateManager * value)97 void SQLiteStudio::setUpdateManager(UpdateManager* value)
98 {
99     updateManager = value;
100 }
101 #endif
102 
getPopulateManager() const103 PopulateManager* SQLiteStudio::getPopulateManager() const
104 {
105     return populateManager;
106 }
107 
setPopulateManager(PopulateManager * value)108 void SQLiteStudio::setPopulateManager(PopulateManager* value)
109 {
110     populateManager = value;
111 }
112 
getCodeFormatter() const113 CodeFormatter* SQLiteStudio::getCodeFormatter() const
114 {
115     return codeFormatter;
116 }
117 
setCodeFormatter(CodeFormatter * codeFormatter)118 void SQLiteStudio::setCodeFormatter(CodeFormatter* codeFormatter)
119 {
120     this->codeFormatter = codeFormatter;
121 }
122 
getHomePage() const123 QString SQLiteStudio::getHomePage() const
124 {
125     static_qstring(url, "https://sqlitestudio.pl");
126     return url;
127 }
128 
getGitHubReleases() const129 QString SQLiteStudio::getGitHubReleases() const
130 {
131     static_qstring(url, "https://github.com/pawelsalawa/sqlitestudio/releases");
132     return url;
133 }
134 
getUserManualPage() const135 QString SQLiteStudio::getUserManualPage() const
136 {
137     static_qstring(url, "https://github.com/pawelsalawa/sqlitestudio/wiki/User_Manual");
138     return url;
139 }
140 
getSqliteDocsPage() const141 QString SQLiteStudio::getSqliteDocsPage() const
142 {
143     static_qstring(url, "http://sqlite.org/lang.html");
144     return url;
145 }
146 
getIssuesPage() const147 QString SQLiteStudio::getIssuesPage() const
148 {
149     static_qstring(url, "https://github.com/pawelsalawa/sqlitestudio/issues");
150     return url;
151 }
152 
getDonatePage() const153 QString SQLiteStudio::getDonatePage() const
154 {
155     static_qstring(url, "https://sqlitestudio.pl/donate/");
156     return url;
157 }
158 
getNewIssuePage() const159 QString SQLiteStudio::getNewIssuePage() const
160 {
161     static_qstring(url, "https://github.com/pawelsalawa/sqlitestudio/issues/new");
162     return url;
163 }
164 
getImportManager() const165 ImportManager* SQLiteStudio::getImportManager() const
166 {
167     return importManager;
168 }
169 
setImportManager(ImportManager * value)170 void SQLiteStudio::setImportManager(ImportManager* value)
171 {
172     importManager = value;
173 }
174 
getExportManager() const175 ExportManager* SQLiteStudio::getExportManager() const
176 {
177     return exportManager;
178 }
179 
setExportManager(ExportManager * value)180 void SQLiteStudio::setExportManager(ExportManager* value)
181 {
182     exportManager = value;
183 }
184 
getVersion() const185 int SQLiteStudio::getVersion() const
186 {
187     return sqlitestudioVersion;
188 }
189 
getVersionString() const190 QString SQLiteStudio::getVersionString() const
191 {
192     int ver = getVersion();
193     int majorVer = ver / 10000;
194     int minorVer = ver % 10000 / 100;
195     int patchVer = ver % 100;
196     return QString::number(majorVer) + "." + QString::number(minorVer) + "." + QString::number(patchVer);
197 }
198 
getCollationManager() const199 CollationManager* SQLiteStudio::getCollationManager() const
200 {
201     return collationManager;
202 }
203 
setCollationManager(CollationManager * value)204 void SQLiteStudio::setCollationManager(CollationManager* value)
205 {
206     safe_delete(collationManager);
207     collationManager = value;
208 }
209 
getSqliteExtensionManager() const210 SqliteExtensionManager* SQLiteStudio::getSqliteExtensionManager() const
211 {
212     return extensionManager;
213 }
214 
setSqliteExtensionManager(SqliteExtensionManager * value)215 void SQLiteStudio::setSqliteExtensionManager(SqliteExtensionManager* value)
216 {
217     safe_delete(extensionManager);
218     extensionManager = value;
219 }
220 
getDbAttacherFactory() const221 DbAttacherFactory* SQLiteStudio::getDbAttacherFactory() const
222 {
223     return dbAttacherFactory;
224 }
225 
setDbAttacherFactory(DbAttacherFactory * value)226 void SQLiteStudio::setDbAttacherFactory(DbAttacherFactory* value)
227 {
228     safe_delete(dbAttacherFactory);
229     dbAttacherFactory = value;
230 }
231 
getPluginManager() const232 PluginManager* SQLiteStudio::getPluginManager() const
233 {
234     return pluginManager;
235 }
236 
setPluginManager(PluginManager * value)237 void SQLiteStudio::setPluginManager(PluginManager* value)
238 {
239     safe_delete(pluginManager);
240     pluginManager = value;
241 }
242 
getFunctionManager() const243 FunctionManager* SQLiteStudio::getFunctionManager() const
244 {
245     return functionManager;
246 }
247 
setFunctionManager(FunctionManager * value)248 void SQLiteStudio::setFunctionManager(FunctionManager* value)
249 {
250     safe_delete(functionManager);
251     functionManager = value;
252 }
253 
getDbManager() const254 DbManager* SQLiteStudio::getDbManager() const
255 {
256     return dbManager;
257 }
258 
setDbManager(DbManager * value)259 void SQLiteStudio::setDbManager(DbManager* value)
260 {
261     safe_delete(dbManager);
262     dbManager = value;
263 }
264 
getConfig() const265 Config* SQLiteStudio::getConfig() const
266 {
267     return config;
268 }
269 
setConfig(Config * value)270 void SQLiteStudio::setConfig(Config* value)
271 {
272     safe_delete(config);
273     config = value;
274 }
275 
init(const QStringList & cmdListArguments,bool guiAvailable)276 void SQLiteStudio::init(const QStringList& cmdListArguments, bool guiAvailable)
277 {
278     env = new QProcessEnvironment(QProcessEnvironment::systemEnvironment());
279     this->guiAvailable = guiAvailable;
280 
281     QThreadPool::globalInstance()->setMaxThreadCount(10);
282 
283     Q_INIT_RESOURCE(coreSQLiteStudio);
284 
285     CfgLazyInitializer::init();
286 
287     initUtils();
288     CfgMain::staticInit();
289     Db::metaInit();
290     initUtilsSql();
291     SchemaResolver::staticInit();
292     initKeywords();
293     Lexer::staticInit();
294     CompletionHelper::init();
295 
296     qRegisterMetaType<ScriptingPlugin::Context*>();
297 
298     NotifyManager::getInstance();
299 
300     dbAttacherFactory = new DbAttacherDefaultFactory();
301 
302     config = new ConfigImpl();
303     config->init();
304 
305     currentLang = CFG_CORE.General.Language.get();
306     loadTranslations(initialTranslationFiles);
307 
308     pluginManager = new PluginManagerImpl();
309     dbManager = new DbManagerImpl();
310 
311     pluginManager->registerPluginType<GeneralPurposePlugin>(QObject::tr("General purpose", "plugin category name"));
312     pluginManager->registerPluginType<DbPlugin>(QObject::tr("Database support", "plugin category name"));
313     pluginManager->registerPluginType<CodeFormatterPlugin>(QObject::tr("Code formatter", "plugin category name"), "formatterPluginsPage");
314     pluginManager->registerPluginType<ScriptingPlugin>(QObject::tr("Scripting languages", "plugin category name"));
315     pluginManager->registerPluginType<ExportPlugin>(QObject::tr("Exporting", "plugin category name"));
316     pluginManager->registerPluginType<ImportPlugin>(QObject::tr("Importing", "plugin category name"));
317     pluginManager->registerPluginType<PopulatePlugin>(QObject::tr("Table populating", "plugin category name"));
318 
319     codeFormatter = new CodeFormatter();
320     connect(CFG_CORE.General.ActiveCodeFormatter, SIGNAL(changed(QVariant)), this, SLOT(updateCurrentCodeFormatter()));
321     connect(pluginManager, SIGNAL(pluginsInitiallyLoaded()), this, SLOT(updateCodeFormatter()));
322 
323     // FunctionManager needs to be set up before DbManager, cause when DbManager starts up, databases make their
324     // connections and register functions.
325     functionManager = new FunctionManagerImpl();
326 
327     collationManager = new CollationManagerImpl();
328     extensionManager = new SqliteExtensionManagerImpl();
329 
330     cmdLineArgs = cmdListArguments;
331 
332     connect(pluginManager, SIGNAL(pluginsInitiallyLoaded()), DBLIST, SLOT(notifyDatabasesAreLoaded()));
333 
334     DbPluginSqlite3* sqlite3plugin = new DbPluginSqlite3;
335     dynamic_cast<DbManagerImpl*>(dbManager)->setInMemDbCreatorPlugin(sqlite3plugin);
336 
337     pluginManager->loadBuiltInPlugin(new ScriptingQt);
338     pluginManager->loadBuiltInPlugin(new ScriptingSql);
339     pluginManager->loadBuiltInPlugin(sqlite3plugin);
340 
341     exportManager = new ExportManager();
342     importManager = new ImportManager();
343     populateManager = new PopulateManager();
344 #ifdef PORTABLE_CONFIG
345     updateManager = new UpdateManager();
346 #endif
347     extraLicenseManager = new ExtraLicenseManager();
348 
349     extraLicenseManager->addLicense("SQLiteStudio license (GPL v3)", ":/docs/licenses/sqlitestudio_license.txt");
350     extraLicenseManager->addLicense("Fugue icons", ":/docs/licenses/fugue_icons.txt");
351     extraLicenseManager->addLicense("Qt, QHexEdit (LGPL v2.1)", ":/docs/licenses/lgpl.txt");
352     extraLicenseManager->addLicense("diff_match (Apache License v2.0)", ":/docs/licenses/diff_match.txt");
353     extraLicenseManager->addLicense("RSA library (GPL v3)", ":/docs/licenses/gpl.txt");
354     extraLicenseManager->addLicense("SingleApplication (The MIT License)", ":/docs/licenses/mit.txt");
355 }
356 
initPlugins()357 void SQLiteStudio::initPlugins()
358 {
359     pluginManager->init();
360 
361     connect(pluginManager, SIGNAL(loaded(Plugin*,PluginType*)), this, SLOT(pluginLoaded(Plugin*,PluginType*)));
362     connect(pluginManager, SIGNAL(aboutToUnload(Plugin*,PluginType*)), this, SLOT(pluginToBeUnloaded(Plugin*,PluginType*)));
363     connect(pluginManager, SIGNAL(unloaded(QString,PluginType*)), this, SLOT(pluginUnloaded(QString,PluginType*)));
364 }
365 
cleanUp()366 void SQLiteStudio::cleanUp()
367 {
368     emit aboutToQuit();
369     disconnect(pluginManager, SIGNAL(aboutToUnload(Plugin*,PluginType*)), this, SLOT(pluginToBeUnloaded(Plugin*,PluginType*)));
370     disconnect(pluginManager, SIGNAL(unloaded(QString,PluginType*)), this, SLOT(pluginUnloaded(QString,PluginType*)));
371     if (!immediateQuit)
372     {
373         if (pluginManager)
374             pluginManager->deinit();
375 
376         safe_delete(pluginManager); // PluginManager before DbManager, so Db objects are deleted while DbManager still exists
377 #ifdef PORTABLE_CONFIG
378         safe_delete(updateManager);
379 #endif
380         safe_delete(populateManager);
381         safe_delete(importManager);
382         safe_delete(exportManager);
383         safe_delete(functionManager);
384         safe_delete(extraLicenseManager);
385         safe_delete(dbManager);
386         safe_delete(config);
387         safe_delete(codeFormatter);
388         safe_delete(dbAttacherFactory);
389         safe_delete(env);
390         NotifyManager::destroy();
391     }
392     Q_CLEANUP_RESOURCE(coreSQLiteStudio);
393 }
394 
updateCodeFormatter()395 void SQLiteStudio::updateCodeFormatter()
396 {
397     codeFormatter->fullUpdate();
398 }
399 
updateCurrentCodeFormatter()400 void SQLiteStudio::updateCurrentCodeFormatter()
401 {
402     codeFormatter->updateCurrent();
403 }
404 
pluginLoaded(Plugin * plugin,PluginType * pluginType)405 void SQLiteStudio::pluginLoaded(Plugin* plugin, PluginType* pluginType)
406 {
407     UNUSED(plugin);
408     if (pluginType->isForPluginType<CodeFormatterPlugin>()) // TODO move this to slot of CodeFormatter
409         updateCodeFormatter();
410 }
411 
pluginToBeUnloaded(Plugin * plugin,PluginType * pluginType)412 void SQLiteStudio::pluginToBeUnloaded(Plugin* plugin, PluginType* pluginType)
413 {
414     UNUSED(plugin);
415     UNUSED(pluginType);
416 }
417 
pluginUnloaded(const QString & pluginName,PluginType * pluginType)418 void SQLiteStudio::pluginUnloaded(const QString& pluginName, PluginType* pluginType)
419 {
420     UNUSED(pluginName);
421     if (pluginType->isForPluginType<CodeFormatterPlugin>()) // TODO move this to slot of CodeFormatter
422         updateCodeFormatter();
423 }
424 
getEnv(const QString & name,const QString & defaultValue)425 QString SQLiteStudio::getEnv(const QString &name, const QString &defaultValue)
426 {
427     return env->value(name, defaultValue);
428 }
429 
createDbAttacher(Db * db)430 DbAttacher* SQLiteStudio::createDbAttacher(Db* db)
431 {
432     return dbAttacherFactory->create(db);
433 }
434 
isGuiAvailable() const435 bool SQLiteStudio::isGuiAvailable() const
436 {
437     return guiAvailable;
438 }
439