Changed: #1193 Now plugin system reads plugin information from plugin-spec file(ovqt_plugin_*.xml) for each plugin.

This commit is contained in:
dnk-88 2011-09-26 00:55:00 +03:00
parent ab4468c48f
commit 2eac5ab064
7 changed files with 222 additions and 125 deletions

View file

@ -95,12 +95,6 @@ public:
@endcode @endcode
*/ */
virtual void setNelContext(NLMISC::INelContext *nelContext) = 0; virtual void setNelContext(NLMISC::INelContext *nelContext) = 0;
virtual QString name() const = 0;
virtual QString version() const = 0;
virtual QString vendor() const = 0;
virtual QString description() const = 0;
virtual QStringList dependencies() const = 0;
}; };
}; //namespace ExtensionSystem }; //namespace ExtensionSystem

View file

@ -37,8 +37,8 @@ struct State
{ {
Invalid = 1, Invalid = 1,
Read, Read,
Loaded,
Resolved, Resolved,
Loaded,
Initialized, Initialized,
Running, Running,
Stopped, Stopped,

View file

@ -26,13 +26,14 @@
namespace ExtensionSystem namespace ExtensionSystem
{ {
CPluginManager::CPluginManager(QObject *parent) PluginManager::PluginManager(QObject *parent)
:IPluginManager(parent), :IPluginManager(parent),
m_settings(0) m_settings(0),
m_extension("xml")
{ {
} }
CPluginManager::~CPluginManager() PluginManager::~PluginManager()
{ {
writeSettings(); writeSettings();
stopAll(); stopAll();
@ -40,7 +41,7 @@ CPluginManager::~CPluginManager()
qDeleteAll(m_pluginSpecs); qDeleteAll(m_pluginSpecs);
} }
void CPluginManager::addObject(QObject *obj) void PluginManager::addObject(QObject *obj)
{ {
QWriteLocker lock(&m_lock); QWriteLocker lock(&m_lock);
if (obj == 0) if (obj == 0)
@ -60,7 +61,7 @@ void CPluginManager::addObject(QObject *obj)
Q_EMIT objectAdded(obj); Q_EMIT objectAdded(obj);
} }
void CPluginManager::removeObject(QObject *obj) void PluginManager::removeObject(QObject *obj)
{ {
if (obj == 0) if (obj == 0)
{ {
@ -80,25 +81,25 @@ void CPluginManager::removeObject(QObject *obj)
m_allObjects.removeAll(obj); m_allObjects.removeAll(obj);
} }
QList<QObject *> CPluginManager::allObjects() const QList<QObject *> PluginManager::allObjects() const
{ {
return m_allObjects; return m_allObjects;
} }
void CPluginManager::loadPlugins() void PluginManager::loadPlugins()
{ {
Q_FOREACH (CPluginSpec *spec, m_pluginSpecs) Q_FOREACH (PluginSpec *spec, m_pluginSpecs)
setPluginState(spec, State::Loaded);
Q_FOREACH (CPluginSpec *spec, m_pluginSpecs)
setPluginState(spec, State::Resolved); setPluginState(spec, State::Resolved);
QList<CPluginSpec *> queue = loadQueue(); QList<PluginSpec *> queue = loadQueue();
Q_FOREACH (CPluginSpec *spec, queue) Q_FOREACH (PluginSpec *spec, queue)
setPluginState(spec, State::Loaded);
Q_FOREACH (PluginSpec *spec, queue)
setPluginState(spec, State::Initialized); setPluginState(spec, State::Initialized);
QListIterator<CPluginSpec *> it(queue); QListIterator<PluginSpec *> it(queue);
it.toBack(); it.toBack();
while (it.hasPrevious()) while (it.hasPrevious())
setPluginState(it.previous(), State::Running); setPluginState(it.previous(), State::Running);
@ -106,34 +107,34 @@ void CPluginManager::loadPlugins()
Q_EMIT pluginsChanged(); Q_EMIT pluginsChanged();
} }
QStringList CPluginManager::getPluginPaths() const QStringList PluginManager::getPluginPaths() const
{ {
return m_pluginPaths; return m_pluginPaths;
} }
void CPluginManager::setPluginPaths(const QStringList &paths) void PluginManager::setPluginPaths(const QStringList &paths)
{ {
m_pluginPaths = paths; m_pluginPaths = paths;
readPluginPaths(); readPluginPaths();
readSettings(); readSettings();
} }
QList<IPluginSpec *> CPluginManager::plugins() const QList<IPluginSpec *> PluginManager::plugins() const
{ {
return m_ipluginSpecs; return m_ipluginSpecs;
} }
void CPluginManager::setSettings(QSettings *settings) void PluginManager::setSettings(QSettings *settings)
{ {
m_settings = settings; m_settings = settings;
} }
QSettings *CPluginManager::settings() const QSettings *PluginManager::settings() const
{ {
return m_settings; return m_settings;
} }
void CPluginManager::readSettings() void PluginManager::readSettings()
{ {
if (m_settings) if (m_settings)
{ {
@ -141,7 +142,7 @@ void CPluginManager::readSettings()
m_settings->beginGroup("PluginManager"); m_settings->beginGroup("PluginManager");
blackList = m_settings->value("BlackList").toStringList(); blackList = m_settings->value("BlackList").toStringList();
m_settings->endGroup(); m_settings->endGroup();
Q_FOREACH (CPluginSpec *spec, m_pluginSpecs) Q_FOREACH (PluginSpec *spec, m_pluginSpecs)
{ {
QString pluginName = spec->fileName(); QString pluginName = spec->fileName();
@ -154,14 +155,13 @@ void CPluginManager::readSettings()
} }
} }
void CPluginManager::writeSettings() void PluginManager::writeSettings()
{ {
if (m_settings) if (m_settings)
{ {
QStringList blackList; QStringList blackList;
Q_FOREACH(CPluginSpec *spec, m_pluginSpecs) Q_FOREACH(PluginSpec *spec, m_pluginSpecs)
{ {
nlinfo(spec->fileName().toStdString().c_str());
if (!spec->isEnabled()) if (!spec->isEnabled())
blackList.push_back(spec->fileName()); blackList.push_back(spec->fileName());
} }
@ -172,7 +172,7 @@ void CPluginManager::writeSettings()
} }
} }
void CPluginManager::readPluginPaths() void PluginManager::readPluginPaths()
{ {
qDeleteAll(m_pluginSpecs); qDeleteAll(m_pluginSpecs);
m_pluginSpecs.clear(); m_pluginSpecs.clear();
@ -183,11 +183,7 @@ void CPluginManager::readPluginPaths()
while (!searchPaths.isEmpty()) while (!searchPaths.isEmpty())
{ {
const QDir dir(searchPaths.takeFirst()); const QDir dir(searchPaths.takeFirst());
#ifdef Q_OS_WIN const QFileInfoList files = dir.entryInfoList(QStringList() << QString("ovqt_plugin_*.%1").arg(m_extension), QDir::Files);
const QFileInfoList files = dir.entryInfoList(QStringList() << QString("ovqt_plugin_*.dll"), QDir::Files);
#else
const QFileInfoList files = dir.entryInfoList(QStringList() << QString("libovqt_plugin_*.so"), QDir::Files);
#endif
Q_FOREACH (const QFileInfo &file, files) Q_FOREACH (const QFileInfo &file, files)
pluginsList << file.absoluteFilePath(); pluginsList << file.absoluteFilePath();
const QFileInfoList dirs = dir.entryInfoList(QDir::Dirs|QDir::NoDotAndDotDot); const QFileInfoList dirs = dir.entryInfoList(QDir::Dirs|QDir::NoDotAndDotDot);
@ -197,9 +193,9 @@ void CPluginManager::readPluginPaths()
Q_FOREACH (const QString &pluginFile, pluginsList) Q_FOREACH (const QString &pluginFile, pluginsList)
{ {
CPluginSpec *spec = new CPluginSpec; PluginSpec *spec = new PluginSpec;
spec->setFileName(pluginFile);
spec->m_pluginManager = this; spec->m_pluginManager = this;
spec->setSpecFileName(pluginFile);
m_pluginSpecs.append(spec); m_pluginSpecs.append(spec);
m_ipluginSpecs.append(spec); m_ipluginSpecs.append(spec);
} }
@ -207,7 +203,7 @@ void CPluginManager::readPluginPaths()
Q_EMIT pluginsChanged(); Q_EMIT pluginsChanged();
} }
void CPluginManager::setPluginState(CPluginSpec *spec, int destState) void PluginManager::setPluginState(PluginSpec *spec, int destState)
{ {
if (spec->hasError() || spec->state() != destState-1) if (spec->hasError() || spec->state() != destState-1)
return; return;
@ -233,7 +229,7 @@ void CPluginManager::setPluginState(CPluginSpec *spec, int destState)
default: default:
break; break;
} }
Q_FOREACH (const CPluginSpec *depSpec, spec->dependencySpecs()) Q_FOREACH (const PluginSpec *depSpec, spec->dependencySpecs())
{ {
if (depSpec->state() != destState) if (depSpec->state() != destState)
{ {
@ -256,19 +252,19 @@ void CPluginManager::setPluginState(CPluginSpec *spec, int destState)
} }
} }
QList<CPluginSpec *> CPluginManager::loadQueue() QList<PluginSpec *> PluginManager::loadQueue()
{ {
QList<CPluginSpec *> queue; QList<PluginSpec *> queue;
Q_FOREACH(CPluginSpec *spec, m_pluginSpecs) Q_FOREACH(PluginSpec *spec, m_pluginSpecs)
{ {
QList<CPluginSpec *> circularityCheckQueue; QList<PluginSpec *> circularityCheckQueue;
loadQueue(spec, queue, circularityCheckQueue); loadQueue(spec, queue, circularityCheckQueue);
} }
return queue; return queue;
} }
bool CPluginManager::loadQueue(CPluginSpec *spec, QList<CPluginSpec *> &queue, bool PluginManager::loadQueue(PluginSpec *spec, QList<PluginSpec *> &queue,
QList<CPluginSpec *> &circularityCheckQueue) QList<PluginSpec *> &circularityCheckQueue)
{ {
if (queue.contains(spec)) if (queue.contains(spec))
return true; return true;
@ -295,7 +291,7 @@ bool CPluginManager::loadQueue(CPluginSpec *spec, QList<CPluginSpec *> &queue,
} }
// add dependencies // add dependencies
Q_FOREACH (CPluginSpec *depSpec, spec->dependencySpecs()) Q_FOREACH (PluginSpec *depSpec, spec->dependencySpecs())
{ {
if (!loadQueue(depSpec, queue, circularityCheckQueue)) if (!loadQueue(depSpec, queue, circularityCheckQueue))
{ {
@ -311,17 +307,17 @@ bool CPluginManager::loadQueue(CPluginSpec *spec, QList<CPluginSpec *> &queue,
return true; return true;
} }
void CPluginManager::stopAll() void PluginManager::stopAll()
{ {
QList<CPluginSpec *> queue = loadQueue(); QList<PluginSpec *> queue = loadQueue();
Q_FOREACH (CPluginSpec *spec, queue) Q_FOREACH (PluginSpec *spec, queue)
setPluginState(spec, State::Stopped); setPluginState(spec, State::Stopped);
} }
void CPluginManager::deleteAll() void PluginManager::deleteAll()
{ {
QList<CPluginSpec *> queue = loadQueue(); QList<PluginSpec *> queue = loadQueue();
QListIterator<CPluginSpec *> it(queue); QListIterator<PluginSpec *> it(queue);
it.toBack(); it.toBack();
while (it.hasPrevious()) while (it.hasPrevious())
{ {

View file

@ -29,15 +29,15 @@ namespace ExtensionSystem
{ {
class IPlugin; class IPlugin;
class CPluginSpec; class PluginSpec;
class CPluginManager : public IPluginManager class PluginManager : public IPluginManager
{ {
Q_OBJECT Q_OBJECT
public: public:
CPluginManager(QObject *parent = 0); PluginManager(QObject *parent = 0);
~CPluginManager(); ~PluginManager();
// Object pool operations // Object pool operations
virtual void addObject(QObject *obj); virtual void addObject(QObject *obj);
@ -49,7 +49,7 @@ public:
virtual QStringList getPluginPaths() const; virtual QStringList getPluginPaths() const;
virtual void setPluginPaths(const QStringList &paths); virtual void setPluginPaths(const QStringList &paths);
virtual QList<IPluginSpec *> plugins() const; virtual QList<IPluginSpec *> plugins() const;
QList<CPluginSpec *> loadQueue(); QList<PluginSpec *> loadQueue();
// Settings // Settings
virtual void setSettings(QSettings *settings); virtual void setSettings(QSettings *settings);
@ -58,21 +58,22 @@ public:
void writeSettings(); void writeSettings();
private: private:
void setPluginState(CPluginSpec *spec, int destState); void setPluginState(PluginSpec *spec, int destState);
void readPluginPaths(); void readPluginPaths();
bool loadQueue(CPluginSpec *spec, QList<CPluginSpec *> &queue, QList<CPluginSpec *> &circularityCheckQueue); bool loadQueue(PluginSpec *spec, QList<PluginSpec *> &queue, QList<PluginSpec *> &circularityCheckQueue);
void stopAll(); void stopAll();
void deleteAll(); void deleteAll();
mutable QReadWriteLock m_lock; mutable QReadWriteLock m_lock;
QSettings *m_settings; QSettings *m_settings;
QList<CPluginSpec *> m_pluginSpecs; QString m_extension;
QList<PluginSpec *> m_pluginSpecs;
QList<IPluginSpec *> m_ipluginSpecs; QList<IPluginSpec *> m_ipluginSpecs;
QStringList m_pluginPaths; QStringList m_pluginPaths;
QList<QObject *> m_allObjects; QList<QObject *> m_allObjects;
}; // class CPluginManager }; // class PluginManager
} // namespace ExtensionSystem } // namespace ExtensionSystem

View file

@ -16,12 +16,15 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
// Project includes
#include "plugin_spec.h" #include "plugin_spec.h"
#include "iplugin.h" #include "iplugin.h"
#include "iplugin_manager.h" #include "iplugin_manager.h"
#include "nel/misc/app_context.h" #include "nel/misc/app_context.h"
#include "nel/misc/debug.h"
// Qt includes
#include <QtCore/QList> #include <QtCore/QList>
#include <QtCore/QFile> #include <QtCore/QFile>
#include <QtCore/QFileInfo> #include <QtCore/QFileInfo>
@ -30,8 +33,17 @@
namespace ExtensionSystem namespace ExtensionSystem
{ {
const char *const PLUGIN_SPEC_NAME = "name";
const char *const PLUGIN_SPEC_VENDOR = "vendor";
const char *const PLUGIN_SPEC_VERSION = "version";
const char *const PLUGIN_SPEC_LIBRARY_NAME = "library-name";
const char *const PLUGIN_SPEC_DESCRIPTION = "description";
const char *const PLUGIN_SPEC_DEPENDENCIES = "dependencies";
const char *const PLUGIN_SPEC_DEPENDENCY = "dependency";
const char *const PLUGIN_SPEC_DEPENDENCY_NAME = "plugin-name";
const char *const PLUGIN_SPEC_DEPENDENCY_VERSION = "version";
CPluginSpec::CPluginSpec() PluginSpec::PluginSpec()
: m_location(""), : m_location(""),
m_filePath(""), m_filePath(""),
m_fileName(""), m_fileName(""),
@ -39,6 +51,8 @@ CPluginSpec::CPluginSpec()
m_version(""), m_version(""),
m_vendor(""), m_vendor(""),
m_description(""), m_description(""),
m_nameSpecFile(""),
m_suffix(""),
m_state(State::Invalid), m_state(State::Invalid),
m_enabled(true), m_enabled(true),
m_enabledStartup(true), m_enabledStartup(true),
@ -47,104 +61,195 @@ CPluginSpec::CPluginSpec()
m_plugin(0), m_plugin(0),
m_pluginManager(0) m_pluginManager(0)
{ {
#ifdef Q_OS_WIN
# ifdef DEBUG
m_suffix = "_d.dll";
# else
m_suffix = "_r.dll";
# endif
#else
m_suffix = ".so";
#endif
} }
QString CPluginSpec::name() const QString PluginSpec::name() const
{ {
return m_name; return m_name;
} }
QString CPluginSpec::version() const QString PluginSpec::version() const
{ {
return m_version; return m_version;
} }
QString CPluginSpec::vendor() const QString PluginSpec::vendor() const
{ {
return m_vendor; return m_vendor;
} }
QString CPluginSpec::description() const QString PluginSpec::description() const
{ {
return m_description; return m_description;
} }
QString CPluginSpec::location() const QString PluginSpec::location() const
{ {
return m_location; return m_location;
} }
QString CPluginSpec::filePath() const QString PluginSpec::filePath() const
{ {
return m_filePath; return m_filePath;
} }
QString CPluginSpec::fileName() const QString PluginSpec::fileName() const
{ {
return m_fileName; return m_fileName;
} }
IPlugin *CPluginSpec::plugin() const IPlugin *PluginSpec::plugin() const
{ {
return m_plugin; return m_plugin;
} }
int CPluginSpec::state() const int PluginSpec::state() const
{ {
return m_state; return m_state;
} }
bool CPluginSpec::hasError() const bool PluginSpec::hasError() const
{ {
return m_hasError; return m_hasError;
} }
QString CPluginSpec::errorString() const QString PluginSpec::errorString() const
{ {
return m_errorString; return m_errorString;
} }
QList<CPluginSpec *> CPluginSpec::dependencySpecs() const QList<PluginSpec *> PluginSpec::dependencySpecs() const
{ {
return m_dependencySpecs; return m_dependencySpecs;
} }
bool CPluginSpec::setFileName(const QString &fileName) bool PluginSpec::setFileName(const QString &fileName)
{ {
QFile file(fileName); m_fileName = fileName + m_suffix;
m_filePath = m_location + "/" + m_fileName;
nlinfo(m_filePath.toStdString().c_str());
QFile file(m_filePath);
if (!file.exists()) if (!file.exists())
return reportError(QCoreApplication::translate("CPluginSpec", "File does not exist: %1").arg(file.fileName())); return reportError(QCoreApplication::translate("PluginSpec", "File does not exist: %1").arg(file.fileName()));
if (!file.open(QIODevice::ReadOnly)) if (!file.open(QIODevice::ReadOnly))
return reportError(QCoreApplication::translate("CPluginSpec", "Could not open file for read: %1").arg(file.fileName())); return reportError(QCoreApplication::translate("PluginSpec", "Could not open file for read: %1").arg(file.fileName()));
return true;
}
bool PluginSpec::setSpecFileName(const QString &specFileName)
{
m_nameSpecFile = specFileName;
QFile file(specFileName);
if (!file.exists())
return reportError(QCoreApplication::translate("PluginSpec", "Spec file does not exist: %1").arg(file.fileName()));
QFileInfo fileInfo(file); QFileInfo fileInfo(file);
m_location = fileInfo.absolutePath(); m_location = fileInfo.absolutePath();
m_filePath = fileInfo.absoluteFilePath(); readSpec();
m_fileName = fileInfo.fileName(); return true;
}
bool PluginSpec::readSpec()
{
QFile file(m_nameSpecFile);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return reportError(QCoreApplication::translate("PluginSpec", "Could not open spec file for read: %1").arg(file.fileName()));
QXmlStreamReader reader(&file);
while (!reader.atEnd())
{
if (reader.isStartElement())
parseSpec(reader);
reader.readNext();
}
if (reader.hasError())
return reportError(QCoreApplication::translate("PluginSpec", "Error parsing file %1: %2, at line %3, column %4")
.arg(file.fileName())
.arg(reader.errorString())
.arg(reader.lineNumber())
.arg(reader.columnNumber()));
m_state = State::Read; m_state = State::Read;
return true; return true;
} }
void CPluginSpec::setEnabled(bool enabled) void PluginSpec::parseSpec(QXmlStreamReader &reader)
{
QString elemName = reader.name().toString();
reader.readNext();
if (reader.isCharacters())
{
QString elemText = reader.text().toString();
if (elemName == PLUGIN_SPEC_LIBRARY_NAME)
setFileName(elemText);
if (elemName == PLUGIN_SPEC_NAME)
m_name = elemText;
if (elemName == PLUGIN_SPEC_VERSION)
m_version = elemText;
if (elemName == PLUGIN_SPEC_VENDOR)
m_vendor = elemText;
if (elemName == PLUGIN_SPEC_DESCRIPTION)
m_description = elemText;
if (elemName == PLUGIN_SPEC_DEPENDENCIES)
parseDependency(reader);
}
}
void PluginSpec::parseDependency(QXmlStreamReader &reader)
{
QString elemName;
while (!reader.atEnd() && (elemName != PLUGIN_SPEC_DEPENDENCIES))
{
reader.readNext();
elemName = reader.name().toString();
if (reader.isStartElement() && (elemName == PLUGIN_SPEC_DEPENDENCY))
{
// Read name dependency plugin
QString dependencyName = reader.attributes().value(PLUGIN_SPEC_DEPENDENCY_NAME).toString();
if (dependencyName.isEmpty())
{
reader.raiseError(QCoreApplication::translate("CPluginSpec", "'%1' misses attribute '%2'")
.arg(PLUGIN_SPEC_DEPENDENCY)
.arg(PLUGIN_SPEC_DEPENDENCY_NAME));
return;
}
// Read version dependency plugin
QString dependencyVersion = reader.attributes().value(PLUGIN_SPEC_DEPENDENCY_VERSION).toString();
m_dependencies.push_back(dependencyName);
}
}
}
void PluginSpec::setEnabled(bool enabled)
{ {
m_enabled = enabled; m_enabled = enabled;
} }
bool CPluginSpec::isEnabled() const bool PluginSpec::isEnabled() const
{ {
return m_enabled; return m_enabled;
} }
bool CPluginSpec::loadLibrary() bool PluginSpec::loadLibrary()
{ {
if (m_hasError) if (m_hasError)
return false; return false;
if (m_state != State::Read) if (m_state != State::Resolved)
{ {
if (m_state == State::Loaded) if (m_state == State::Loaded)
return true; return true;
return reportError(QCoreApplication::translate("CPluginSpec", "Loading the library failed because state != Resolved")); return reportError(QCoreApplication::translate("PluginSpec", "Loading the library failed because state != Resolved"));
} }
QPluginLoader loader(m_filePath); QPluginLoader loader(m_filePath);
@ -155,38 +260,32 @@ bool CPluginSpec::loadLibrary()
if (!pluginObject) if (!pluginObject)
{ {
loader.unload(); loader.unload();
return reportError(QCoreApplication::translate("CPluginSpec", "Plugin is not valid (does not derive from IPlugin)")); return reportError(QCoreApplication::translate("PluginSpec", "Plugin is not valid (does not derive from IPlugin)"));
} }
pluginObject->setNelContext(&NLMISC::INelContext::getInstance()); pluginObject->setNelContext(&NLMISC::INelContext::getInstance());
m_name = pluginObject->name();
m_version = pluginObject->version();
m_vendor = pluginObject->vendor();
m_description = pluginObject->description();
m_state = State::Loaded; m_state = State::Loaded;
m_plugin = pluginObject; m_plugin = pluginObject;
return true; return true;
} }
bool CPluginSpec::resolveDependencies(const QList<CPluginSpec *> &specs) bool PluginSpec::resolveDependencies(const QList<PluginSpec *> &specs)
{ {
if (m_hasError) if (m_hasError)
return false; return false;
if (m_state != State::Loaded) if (m_state != State::Read)
{ {
m_errorString = QCoreApplication::translate("CPluginSpec", "Resolving dependencies failed because state != Read"); m_errorString = QCoreApplication::translate("PluginSpec", "Resolving dependencies failed because state != Read");
m_hasError = true; m_hasError = true;
return false; return false;
} }
QList<CPluginSpec *> resolvedDependencies; QList<PluginSpec *> resolvedDependencies;
QStringList dependencies = m_plugin->dependencies(); Q_FOREACH(const QString &dependency, m_dependencies)
Q_FOREACH(const QString &dependency, dependencies)
{ {
CPluginSpec *found = 0; PluginSpec *found = 0;
Q_FOREACH(CPluginSpec *spec, specs) Q_FOREACH(PluginSpec *spec, specs)
{ {
if (QString::compare(dependency, spec->name(), Qt::CaseInsensitive) == 0) if (QString::compare(dependency, spec->name(), Qt::CaseInsensitive) == 0)
{ {
@ -199,7 +298,7 @@ bool CPluginSpec::resolveDependencies(const QList<CPluginSpec *> &specs)
m_hasError = true; m_hasError = true;
if (!m_errorString.isEmpty()) if (!m_errorString.isEmpty())
m_errorString.append(QLatin1Char('\n')); m_errorString.append(QLatin1Char('\n'));
m_errorString.append(QCoreApplication::translate("CPluginSpec", "Could not resolve dependency '%1'") m_errorString.append(QCoreApplication::translate("PluginSpec", "Could not resolve dependency '%1'")
.arg(dependency)); .arg(dependency));
continue; continue;
} }
@ -209,34 +308,32 @@ bool CPluginSpec::resolveDependencies(const QList<CPluginSpec *> &specs)
return false; return false;
m_dependencySpecs = resolvedDependencies; m_dependencySpecs = resolvedDependencies;
m_state = State::Resolved; m_state = State::Resolved;
return true; return true;
} }
bool CPluginSpec::initializePlugin() bool PluginSpec::initializePlugin()
{ {
if (m_hasError) if (m_hasError)
return false; return false;
if (m_state != State::Resolved) if (m_state != State::Loaded)
{ {
if (m_state == State::Initialized) if (m_state == State::Initialized)
return true; return true;
return reportError(QCoreApplication::translate("CPluginSpec", "Initializing the plugin failed because state != Resolved)")); return reportError(QCoreApplication::translate("PluginSpec", "Initializing the plugin failed because state != Loaded)"));
} }
if (!m_plugin) if (!m_plugin)
return reportError(QCoreApplication::translate("CPluginSpec", "Internal error: have no plugin instance to initialize")); return reportError(QCoreApplication::translate("PluginSpec", "Internal error: have no plugin instance to initialize"));
QString err; QString err;
if (!m_plugin->initialize(m_pluginManager, &err)) if (!m_plugin->initialize(m_pluginManager, &err))
return reportError(QCoreApplication::translate("CPluginSpec", "Plugin initialization failed: %1").arg(err)); return reportError(QCoreApplication::translate("PluginSpec", "Plugin initialization failed: %1").arg(err));
m_state = State::Initialized; m_state = State::Initialized;
return true; return true;
} }
bool CPluginSpec::initializeExtensions() bool PluginSpec::initializeExtensions()
{ {
if (m_hasError) if (m_hasError)
return false; return false;
@ -244,17 +341,17 @@ bool CPluginSpec::initializeExtensions()
{ {
if (m_state == State::Running) if (m_state == State::Running)
return true; return true;
return reportError(QCoreApplication::translate("CPluginSpec", "Cannot perform extensionsInitialized because state != Initialized")); return reportError(QCoreApplication::translate("PluginSpec", "Cannot perform extensionsInitialized because state != Initialized"));
} }
if (!m_plugin) if (!m_plugin)
return reportError(QCoreApplication::translate("CPluginSpec", "Internal error: have no plugin instance to perform extensionsInitialized")); return reportError(QCoreApplication::translate("PluginSpec", "Internal error: have no plugin instance to perform extensionsInitialized"));
m_plugin->extensionsInitialized(); m_plugin->extensionsInitialized();
m_state = State::Running; m_state = State::Running;
return true; return true;
} }
void CPluginSpec::stop() void PluginSpec::stop()
{ {
if (!m_plugin) if (!m_plugin)
return; return;
@ -262,7 +359,7 @@ void CPluginSpec::stop()
m_state = State::Stopped; m_state = State::Stopped;
} }
void CPluginSpec::kill() void PluginSpec::kill()
{ {
if (!m_plugin) if (!m_plugin)
return; return;
@ -271,17 +368,17 @@ void CPluginSpec::kill()
m_state = State::Deleted; m_state = State::Deleted;
} }
void CPluginSpec::setEnabledStartup(bool enabled) void PluginSpec::setEnabledStartup(bool enabled)
{ {
m_enabledStartup = enabled; m_enabledStartup = enabled;
} }
bool CPluginSpec::isEnabledStartup() const bool PluginSpec::isEnabledStartup() const
{ {
return m_enabledStartup; return m_enabledStartup;
} }
bool CPluginSpec::reportError(const QString &err) bool PluginSpec::reportError(const QString &err)
{ {
m_errorString = err; m_errorString = err;
m_hasError = true; m_hasError = true;

View file

@ -21,12 +21,14 @@
#include "iplugin_spec.h" #include "iplugin_spec.h"
#include "QtCore/QList" #include <QtCore/QList>
#include <QtCore/QStringList>
#include <QtCore/QXmlStreamReader>
namespace ExtensionSystem namespace ExtensionSystem
{ {
class CPluginSpec: public IPluginSpec class PluginSpec: public IPluginSpec
{ {
public: public:
virtual QString name() const; virtual QString name() const;
@ -44,18 +46,22 @@ public:
virtual int state() const; virtual int state() const;
virtual bool hasError() const; virtual bool hasError() const;
virtual QString errorString() const; virtual QString errorString() const;
QList<CPluginSpec *> dependencySpecs() const; QList<PluginSpec *> dependencySpecs() const;
/// Enables/disables load this plugin after restart the program /// Enables/disables load this plugin after restart the program
virtual void setEnabled(bool enabled); virtual void setEnabled(bool enabled);
virtual bool isEnabled() const; virtual bool isEnabled() const;
private: private:
CPluginSpec(); PluginSpec();
bool setFileName(const QString &fileName); bool setFileName(const QString &fileName);
bool setSpecFileName(const QString &specFileName);
bool readSpec();
void parseSpec(QXmlStreamReader &reader);
void parseDependency(QXmlStreamReader &reader);
bool loadLibrary(); bool loadLibrary();
bool resolveDependencies(const QList<CPluginSpec *> &specs); bool resolveDependencies(const QList<PluginSpec *> &specs);
bool initializePlugin(); bool initializePlugin();
bool initializeExtensions(); bool initializeExtensions();
void stop(); void stop();
@ -77,16 +83,19 @@ private:
QString m_vendor; QString m_vendor;
QString m_description; QString m_description;
QString m_nameSpecFile;
QString m_suffix;
int m_state; int m_state;
bool m_enabled, m_enabledStartup; bool m_enabled, m_enabledStartup;
bool m_hasError; bool m_hasError;
QString m_errorString; QString m_errorString;
QStringList m_dependencies;
IPlugin *m_plugin; IPlugin *m_plugin;
IPluginManager *m_pluginManager; IPluginManager *m_pluginManager;
QList<CPluginSpec *> m_dependencySpecs; QList<PluginSpec *> m_dependencySpecs;
friend class CPluginManager; friend class PluginManager;
}; };
} // namespace ExtensionSystem } // namespace ExtensionSystem

View file

@ -148,7 +148,7 @@ sint main(int argc, char **argv)
NLMISC::CLibrary::addLibPath((qApp->applicationDirPath() + QString("/../PlugIns/nel")).toStdString()); NLMISC::CLibrary::addLibPath((qApp->applicationDirPath() + QString("/../PlugIns/nel")).toStdString());
#endif #endif
ExtensionSystem::CPluginManager pluginManager; ExtensionSystem::PluginManager pluginManager;
pluginManager.setSettings(settings); pluginManager.setSettings(settings);
QStringList pluginPaths; QStringList pluginPaths;
#if !defined(NL_OS_MAC) #if !defined(NL_OS_MAC)