You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

167 lines
4.3 KiB
C++

#include <QDir>
#include <QApplication>
#include <QPluginLoader>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlResult>
#include <QSqlError>
#include <QDebug>
#include <odb/sqlite/database.hxx>
#include "core.h"
#include "coreplugin.h"
Context &Context::instance()
{
static Context ctx;
return ctx;
}
QList<IPlugin *> Context::plugins()
{
return m_plugins;
}
IPlugin *Context::plugin(const QString &pluginId)
{
QList<IPlugin*>::iterator it = std::find_if(ALL(m_plugins), [&pluginId](IPlugin *p) { return p->pluginId() == pluginId; });
if (it != m_plugins.end())
{
return *it;
}
return NULL;
}
void Context::loadPlugins()
{
IPlugin *corePlugin = new CorePlugin();
m_plugins.append(corePlugin);
QDir pluginsDir(qApp->applicationDirPath() + "/../plugins");
foreach (QString fileName, pluginsDir.entryList(QStringList() << "*.so" << "*.dll")) {
QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
QObject *p = pluginLoader.instance();
if (p != NULL) {
IPlugin *plugin = qobject_cast<IPlugin*>(p);
if (plugin != NULL) {
plugin->init(pluginLoader.metaData());
m_plugins.append(plugin);
}
}
}
}
void Context::openDb(const QString &path)
{
if (m_db != NULL) {
delete m_db;
}
checkDb(path);
m_db = new odb::sqlite::database(path.toStdString());
}
Context::Context()
{
m_db = NULL;
}
void Context::checkDb(const QString &path)
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(path);
db.open();
QSqlQuery q(db);
QString verSql = "SELECT pluginId, schemaVersion FROM system";
QString createSysSql = "CREATE TABLE \"system\" (\"id\" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, \"pluginId\" TEXT NULL, \"schemaVersion\" TEXT NULL)";
if (q.exec(verSql))
{
QMap<QString, int> schemas;
while (q.next())
{
schemas[q.value("pluginId").toString()] = q.value("schemaVersion").toInt();
}
checkSchema(db, schemas);
}
else
{
q.exec(createSysSql);
checkSchema(db, QMap<QString, int>());
}
db.close();
}
void Context::checkSchema(const QSqlDatabase &db, const QMap<QString, int> &schemaMap)
{
foreach (IPlugin *plugin, m_plugins) {
solveDep(plugin, db, schemaMap);
}
}
void Context::solveDep(IPlugin *plugin, const QSqlDatabase &db, const QMap<QString, int> &schemaMap)
{
foreach (QString dep, plugin->dependsOn()) {
QList<IPlugin*>::iterator it = std::find_if(ALL(m_plugins), [&dep](IPlugin *p) { return p->pluginId() == dep; });
if (it != m_plugins.end())
{
solveDep(*it, db, schemaMap);
}
if (m_solved.contains(plugin->pluginId()))
{
createSchema(plugin, db, schemaMap);
m_solved.append(plugin->pluginId());
}
}
}
void Context::createSchema(IPlugin *plugin, const QSqlDatabase &db, const QMap<QString, int> &schemaMap)
{
if (!schemaMap.contains(plugin->pluginId()) || schemaMap[plugin->pluginId()] < plugin->schemaVersion())
{
int ver = schemaMap[plugin->pluginId()];
for (int i = 0; i < plugin->schemas().count(); i++)
{
if (!schemaMap.contains(plugin->pluginId()) || i >= ver)
{
QString sql = plugin->schemas()[i];
QSqlQuery q(db);
QStringList sqlList = sql.split(";");
bool error = false;
foreach (QString s, sqlList) {
if (!q.exec(s))
{
qDebug() << q.lastError().text();
error = true;
}
}
if (error)
{
continue;
}
if (ver == 0)
{
sql = "INSERT INTO system(pluginId, schemaVersion) VALUES('" + plugin->pluginId() + "', 1)";
}
else
{
sql = "UPDATE system SET schemaVersion = " + QString::number(i + 1) + " WHERE pluginId = '" + plugin->pluginId() + "'";
}
q.exec(sql);
}
}
}
}