Changed: #1206 Update plugin system. Now plugin manager takes into account dependencies between plug-ins. Update core, object viewer and example plugin.

This commit is contained in:
dnk-88 2011-02-28 21:01:35 +02:00
parent b1535e1981
commit b9df3fb0f5
16 changed files with 457 additions and 263 deletions

View file

@ -1,27 +1,27 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
#ifndef IPLUGIN_H
#define IPLUGIN_H
#include <QtCore/QtPlugin>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include "iplugin_manager.h"
@ -46,17 +46,61 @@ class IPlugin
public:
virtual ~IPlugin() {}
/**
@brief Called after the plugin has been loaded and the IPlugin instance has been created.
@details The initialize methods of plugins that depend
on this plugin are called after the initialize method of this plugin
has been called. Plugins should initialize their internal state in this
method. Returns if initialization of successful. If it wasn't successful,
the \a errorString should be set to a user-readable message
describing the reason.
*/
virtual bool initialize(IPluginManager *pluginManager, QString *errorString) = 0;
/**
@brief Called after the IPlugin::initialize() method has been called,
and after both the IPlugin::initialize() and IPlugin::extensionsInitialized()
methods of plugins that depend on this plugin have been called.
@details In this method, the plugin can assume that plugins that depend on
this plugin are fully 'up and running'. It is a good place to
look in the plugin manager's object pool for objects that have
been provided by dependent plugins.
*/
virtual void extensionsInitialized() = 0;
/**
@\brief Called during a shutdown sequence in the same order as initialization
before the plugins get deleted in reverse order.
@details This method should be used to disconnect from other plugins,
hide all UI, and optimize shutdown in general.
*/
virtual void shutdown() { }
/**
@\brief This method should be implemented to work properly NeL singletons.
Called immediately after loading the plugin.
@code
void Plugin::setNelContext(NLMISC::INelContext *nelContext)
{
#ifdef NL_OS_WINDOWS
// Ensure that a context doesn't exist yet.
// This only applies to platforms without PIC, e.g. Windows.
nlassert(!NLMISC::INelContext::isContextInitialised());
#endif // NL_OS_WINDOWS
_LibContext = new NLMISC::CLibraryContext(*nelContext);
}
@endcode
*/
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 QList<QString> dependencies() const = 0;
virtual QStringList dependencies() const = 0;
};
}; //namespace ExtensionSystem

View file

@ -1,26 +1,25 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
#ifndef IPLUGINMANAGER_H
#define IPLUGINMANAGER_H
#include "plugin_spec.h"
#include "iplugin_spec.h"
#include <QtCore/QList>
#include <QtCore/QObject>
@ -62,6 +61,8 @@ public:
virtual QSettings *settings() const = 0;
// Auxiliary operations
/// Retrieve all objects of a given type from the object pool.
template <typename T>
QList<T *> getObjects() const
{
@ -76,6 +77,7 @@ public:
return objects;
}
/// Retrieve the object of a given type from the object pool.
template <typename T>
T *getObject() const
{
@ -124,9 +126,13 @@ public:
}
Q_SIGNALS:
/// Signal that \a obj has been added to the object pool.
void objectAdded(QObject *obj);
/// Signal that \a obj will be removed from the object pool.
void aboutToRemoveObject(QObject *obj);
/// Signal that the list of available plugins has changed.
void pluginsChanged();
};

View file

@ -1,21 +1,20 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
#ifndef IPLUGINSPEC_H
#define IPLUGINSPEC_H
@ -39,6 +38,7 @@ struct State
Invalid = 1,
Read,
Loaded,
Resolved,
Initialized,
Running,
Stopped,

View file

@ -1,23 +1,23 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
#include "plugin_manager.h"
#include "plugin_spec.h"
#include <QtCore/QDir>
@ -28,7 +28,7 @@ namespace ExtensionSystem
CPluginManager::CPluginManager(QObject *parent)
:IPluginManager(parent),
_settings(0)
m_settings(0)
{
}
@ -36,25 +36,25 @@ CPluginManager::~CPluginManager()
{
stopAll();
deleteAll();
qDeleteAll(_pluginSpecs);
qDeleteAll(m_pluginSpecs);
}
void CPluginManager::addObject(QObject *obj)
{
QWriteLocker lock(&_lock);
QWriteLocker lock(&m_lock);
if (obj == 0)
{
nlwarning("trying to add null object");
return;
}
if (_allObjects.contains(obj))
if (m_allObjects.contains(obj))
{
nlwarning("trying to add duplicate object");
return;
}
nlinfo(QString("addObject: " + obj->objectName()).toStdString().c_str());
_allObjects.append(obj);
m_allObjects.append(obj);
Q_EMIT objectAdded(obj);
}
@ -67,7 +67,7 @@ void CPluginManager::removeObject(QObject *obj)
return;
}
if (!_allObjects.contains(obj))
if (!m_allObjects.contains(obj))
{
nlinfo(QString("object not in list: " + obj->objectName()).toStdString().c_str());
return;
@ -75,24 +75,29 @@ void CPluginManager::removeObject(QObject *obj)
nlinfo(QString("removeObject: " + obj->objectName()).toStdString().c_str());
Q_EMIT aboutToRemoveObject(obj);
QWriteLocker lock(&_lock);
_allObjects.removeAll(obj);
QWriteLocker lock(&m_lock);
m_allObjects.removeAll(obj);
}
QList<QObject *> CPluginManager::allObjects() const
{
return _allObjects;
return m_allObjects;
}
void CPluginManager::loadPlugins()
{
Q_FOREACH (CPluginSpec *spec, _pluginSpecs)
Q_FOREACH (CPluginSpec *spec, m_pluginSpecs)
setPluginState(spec, State::Loaded);
Q_FOREACH (CPluginSpec *spec, _pluginSpecs)
Q_FOREACH (CPluginSpec *spec, m_pluginSpecs)
setPluginState(spec, State::Resolved);
QList<CPluginSpec *> queue = loadQueue();
Q_FOREACH (CPluginSpec *spec, queue)
setPluginState(spec, State::Initialized);
QListIterator<CPluginSpec *> it(_pluginSpecs);
QListIterator<CPluginSpec *> it(queue);
it.toBack();
while (it.hasPrevious())
setPluginState(it.previous(), State::Running);
@ -102,28 +107,28 @@ void CPluginManager::loadPlugins()
QStringList CPluginManager::getPluginPaths() const
{
return _pluginPaths;
return m_pluginPaths;
}
void CPluginManager::setPluginPaths(const QStringList &paths)
{
_pluginPaths = paths;
m_pluginPaths = paths;
readPluginPaths();
}
QList<IPluginSpec *> CPluginManager::plugins() const
{
return _ipluginSpecs;
return m_ipluginSpecs;
}
void CPluginManager::setSettings(QSettings *settings)
{
_settings = settings;
m_settings = settings;
}
QSettings *CPluginManager::settings() const
{
return _settings;
return m_settings;
}
void CPluginManager::readSettings()
@ -136,12 +141,12 @@ void CPluginManager::writeSettings()
void CPluginManager::readPluginPaths()
{
qDeleteAll(_pluginSpecs);
_pluginSpecs.clear();
_ipluginSpecs.clear();
qDeleteAll(m_pluginSpecs);
m_pluginSpecs.clear();
m_ipluginSpecs.clear();
QStringList pluginsList;
QStringList searchPaths = _pluginPaths;
QStringList searchPaths = m_pluginPaths;
while (!searchPaths.isEmpty())
{
const QDir dir(searchPaths.takeFirst());
@ -161,9 +166,9 @@ void CPluginManager::readPluginPaths()
{
CPluginSpec *spec = new CPluginSpec;
spec->setFileName(pluginFile);
spec->_pluginManager = this;
_pluginSpecs.append(spec);
_ipluginSpecs.append(spec);
spec->m_pluginManager = this;
m_pluginSpecs.append(spec);
m_ipluginSpecs.append(spec);
}
Q_EMIT pluginsChanged();
@ -171,36 +176,115 @@ void CPluginManager::readPluginPaths()
void CPluginManager::setPluginState(CPluginSpec *spec, int destState)
{
if (spec->hasError())
if (spec->hasError() || spec->getState() != destState-1)
return;
if (destState == State::Running)
switch (destState)
{
case State::Loaded:
spec->loadLibrary();
return;
case State::Resolved:
spec->resolveDependencies(m_pluginSpecs);
return;
case State::Running:
spec->initializeExtensions();
return;
}
else if (destState == State::Deleted)
{
case State::Deleted:
spec->kill();
return;
default:
break;
}
Q_FOREACH (const CPluginSpec *depSpec, spec->dependencySpecs())
{
if (depSpec->getState() != destState)
{
spec->m_hasError = true;
spec->m_errorString = tr("Cannot initializing plugin because dependency failed to load: %1\nReason: %2")
.arg(depSpec->name()).arg(depSpec->errorString());
return;
}
}
switch (destState)
{
case State::Initialized:
spec->initializePlugin();
break;
case State::Stopped:
spec->stop();
break;
default:
break;
}
}
if (destState == State::Loaded)
spec->loadLibrary();
else if (destState == State::Initialized)
spec->initializePlugin();
else if (destState == State::Stopped)
spec->stop();
QList<CPluginSpec *> CPluginManager::loadQueue()
{
QList<CPluginSpec *> queue;
Q_FOREACH(CPluginSpec *spec, m_pluginSpecs)
{
QList<CPluginSpec *> circularityCheckQueue;
loadQueue(spec, queue, circularityCheckQueue);
}
return queue;
}
bool CPluginManager::loadQueue(CPluginSpec *spec, QList<CPluginSpec *> &queue,
QList<CPluginSpec *> &circularityCheckQueue)
{
if (queue.contains(spec))
return true;
// check for circular dependencies
if (circularityCheckQueue.contains(spec))
{
spec->m_hasError = true;
spec->m_errorString = tr("Circular dependency detected:\n");
int index = circularityCheckQueue.indexOf(spec);
for (int i = index; i < circularityCheckQueue.size(); ++i)
{
spec->m_errorString.append(tr("%1(%2) depends on\n")
.arg(circularityCheckQueue.at(i)->name()).arg(circularityCheckQueue.at(i)->version()));
}
spec->m_errorString.append(tr("%1(%2)").arg(spec->name()).arg(spec->version()));
return false;
}
circularityCheckQueue.append(spec);
// check if we have the dependencies
if (spec->getState() == State::Invalid || spec->getState() == State::Read)
{
queue.append(spec);
return false;
}
// add dependencies
Q_FOREACH (CPluginSpec *depSpec, spec->dependencySpecs())
{
if (!loadQueue(depSpec, queue, circularityCheckQueue))
{
spec->m_hasError = true;
spec->m_errorString =
tr("Cannot load plugin because dependency failed to load: %1(%2)\nReason: %3")
.arg(depSpec->name()).arg(depSpec->version()).arg(depSpec->errorString());
return false;
}
}
// add self
queue.append(spec);
return true;
}
void CPluginManager::stopAll()
{
Q_FOREACH (CPluginSpec *spec, _pluginSpecs)
QList<CPluginSpec *> queue = loadQueue();
Q_FOREACH (CPluginSpec *spec, queue)
setPluginState(spec, State::Stopped);
}
void CPluginManager::deleteAll()
{
QListIterator<CPluginSpec *> it(_pluginSpecs);
QList<CPluginSpec *> queue = loadQueue();
QListIterator<CPluginSpec *> it(queue);
it.toBack();
while (it.hasPrevious())
{

View file

@ -1,21 +1,20 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
#ifndef PLUGINMANAGER_H
#define PLUGINMANAGER_H
@ -50,6 +49,7 @@ public:
virtual QStringList getPluginPaths() const;
virtual void setPluginPaths(const QStringList &paths);
virtual QList<IPluginSpec *> plugins() const;
QList<CPluginSpec *> loadQueue();
// Settings
virtual void setSettings(QSettings *settings);
@ -60,16 +60,17 @@ public:
private:
void setPluginState(CPluginSpec *spec, int destState);
void readPluginPaths();
bool loadQueue(CPluginSpec *spec, QList<CPluginSpec *> &queue, QList<CPluginSpec *> &circularityCheckQueue);
void stopAll();
void deleteAll();
mutable QReadWriteLock _lock;
mutable QReadWriteLock m_lock;
QSettings *_settings;
QList<CPluginSpec *> _pluginSpecs;
QList<IPluginSpec *> _ipluginSpecs;
QStringList _pluginPaths;
QList<QObject *> _allObjects;
QSettings *m_settings;
QList<CPluginSpec *> m_pluginSpecs;
QList<IPluginSpec *> m_ipluginSpecs;
QStringList m_pluginPaths;
QList<QObject *> m_allObjects;
}; // class CPluginManager

View file

@ -1,22 +1,20 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
#include "plugin_spec.h"
#include <QtCore/QList>
@ -34,74 +32,79 @@ namespace ExtensionSystem
{
CPluginSpec::CPluginSpec()
: _location(""),
_filePath(""),
_fileName(""),
_name(""),
_version(""),
_vendor(""),
_description(""),
_state(State::Invalid),
_hasError(false),
_errorString(""),
_plugin(0),
_pluginManager(0)
: m_location(""),
m_filePath(""),
m_fileName(""),
m_name(""),
m_version(""),
m_vendor(""),
m_description(""),
m_state(State::Invalid),
m_hasError(false),
m_errorString(""),
m_plugin(0),
m_pluginManager(0)
{
}
QString CPluginSpec::name() const
{
return _name;
return m_name;
}
QString CPluginSpec::version() const
{
return _version;
return m_version;
}
QString CPluginSpec::vendor() const
{
return _vendor;
return m_vendor;
}
QString CPluginSpec::description() const
{
return _description;
return m_description;
}
QString CPluginSpec::location() const
{
return _location;
return m_location;
}
QString CPluginSpec::filePath() const
{
return _filePath;
return m_filePath;
}
QString CPluginSpec::fileName() const
{
return _fileName;
return m_fileName;
}
IPlugin* CPluginSpec::plugin() const
{
return _plugin;
return m_plugin;
}
int CPluginSpec::getState() const
{
return _state;
return m_state;
}
bool CPluginSpec::hasError() const
{
return _hasError;
return m_hasError;
}
QString CPluginSpec::errorString() const
{
return _errorString;
return m_errorString;
}
QList<CPluginSpec *> CPluginSpec::dependencySpecs() const
{
return m_dependencySpecs;
}
bool CPluginSpec::setFileName(const QString &fileName)
@ -113,26 +116,26 @@ bool CPluginSpec::setFileName(const QString &fileName)
return reportError(QCoreApplication::translate("CPluginSpec", "Could not open file for read: %1").arg(file.fileName()));
QFileInfo fileInfo(file);
_location = fileInfo.absolutePath();
_filePath = fileInfo.absoluteFilePath();
_fileName = fileInfo.fileName();
m_location = fileInfo.absolutePath();
m_filePath = fileInfo.absoluteFilePath();
m_fileName = fileInfo.fileName();
_state = State::Read;
m_state = State::Read;
return true;
}
bool CPluginSpec::loadLibrary()
{
if (_hasError)
if (m_hasError)
return false;
if (_state != State::Read)
if (m_state != State::Read)
{
if (_state == State::Loaded)
if (m_state == State::Loaded)
return true;
return reportError(QCoreApplication::translate("CPluginSpec", "Loading the library failed because state != Resolved"));
}
QPluginLoader loader(_filePath);
QPluginLoader loader(m_filePath);
if (!loader.load())
return reportError(loader.errorString());
@ -145,76 +148,121 @@ bool CPluginSpec::loadLibrary()
pluginObject->setNelContext(&NLMISC::INelContext::getInstance());
_name = pluginObject->name();
_version = pluginObject->version();
_vendor = pluginObject->vendor();
_description = pluginObject->description();
m_name = pluginObject->name();
m_version = pluginObject->version();
m_vendor = pluginObject->vendor();
m_description = pluginObject->description();
m_state = State::Loaded;
m_plugin = pluginObject;
return true;
}
bool CPluginSpec::resolveDependencies(const QList<CPluginSpec *> &specs)
{
if (m_hasError)
return false;
if (m_state != State::Loaded)
{
m_errorString = QCoreApplication::translate("CPluginSpec", "Resolving dependencies failed because state != Read");
m_hasError = true;
return false;
}
QList<CPluginSpec *> resolvedDependencies;
QStringList dependencies = m_plugin->dependencies();
Q_FOREACH(const QString &dependency, dependencies)
{
CPluginSpec *found = 0;
Q_FOREACH(CPluginSpec *spec, specs)
{
if (QString::compare(dependency, spec->name(), Qt::CaseInsensitive) == 0)
{
found = spec;
break;
}
}
if (!found)
{
m_hasError = true;
if (!m_errorString.isEmpty())
m_errorString.append(QLatin1Char('\n'));
m_errorString.append(QCoreApplication::translate("CPluginSpec", "Could not resolve dependency '%1'")
.arg(dependency));
continue;
}
resolvedDependencies.append(found);
}
if (m_hasError)
return false;
m_dependencySpecs = resolvedDependencies;
m_state = State::Resolved;
_state = State::Loaded;
_plugin = pluginObject;
return true;
}
bool CPluginSpec::initializePlugin()
{
if (_hasError)
if (m_hasError)
return false;
if (_state != State::Loaded)
if (m_state != State::Resolved)
{
if (_state == State::Initialized)
if (m_state == State::Initialized)
return true;
return reportError(QCoreApplication::translate("CPluginSpec", "Initializing the plugin failed because state != Loaded)"));
return reportError(QCoreApplication::translate("CPluginSpec", "Initializing the plugin failed because state != Resolved)"));
}
if (!_plugin)
if (!m_plugin)
return reportError(QCoreApplication::translate("CPluginSpec", "Internal error: have no plugin instance to initialize"));
QString err;
if (!_plugin->initialize(_pluginManager, &err))
if (!m_plugin->initialize(m_pluginManager, &err))
return reportError(QCoreApplication::translate("CPluginSpec", "Plugin initialization failed: %1").arg(err));
_state = State::Initialized;
m_state = State::Initialized;
return true;
}
bool CPluginSpec::initializeExtensions()
{
if (_hasError)
if (m_hasError)
return false;
if (_state != State::Initialized)
if (m_state != State::Initialized)
{
if (_state == State::Running)
if (m_state == State::Running)
return true;
return reportError(QCoreApplication::translate("CPluginSpec", "Cannot perform extensionsInitialized because state != Initialized"));
}
if (!_plugin)
if (!m_plugin)
return reportError(QCoreApplication::translate("CPluginSpec", "Internal error: have no plugin instance to perform extensionsInitialized"));
_plugin->extensionsInitialized();
_state = State::Running;
m_plugin->extensionsInitialized();
m_state = State::Running;
return true;
}
void CPluginSpec::stop()
{
if (!_plugin)
if (!m_plugin)
return;
_plugin->shutdown();
_state = State::Stopped;
m_plugin->shutdown();
m_state = State::Stopped;
}
void CPluginSpec::kill()
{
if (!_plugin)
if (!m_plugin)
return;
delete _plugin;
_plugin = 0;
_state = State::Deleted;
delete m_plugin;
m_plugin = 0;
m_state = State::Deleted;
}
bool CPluginSpec::reportError(const QString &err)
{
_errorString = err;
_hasError = true;
m_errorString = err;
m_hasError = true;
return false;
}

View file

@ -1,27 +1,28 @@
/*
Object Viewer Qt
Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
#ifndef PLUGINSPEC_H
#define PLUGINSPEC_H
#include "iplugin_spec.h"
#include "QtCore/QList"
namespace ExtensionSystem
{
@ -43,12 +44,14 @@ public:
virtual int getState() const;
virtual bool hasError() const;
virtual QString errorString() const;
QList<CPluginSpec *> dependencySpecs() const;
private:
CPluginSpec();
bool setFileName(const QString &fileName);
bool loadLibrary();
bool resolveDependencies(const QList<CPluginSpec *> &specs);
bool initializePlugin();
bool initializeExtensions();
void stop();
@ -56,21 +59,22 @@ private:
bool reportError(const QString &err);
QString _location;
QString _filePath;
QString _fileName;
QString m_location;
QString m_filePath;
QString m_fileName;
QString _name;
QString _version;
QString _vendor;
QString _description;
QString m_name;
QString m_version;
QString m_vendor;
QString m_description;
int _state;
bool _hasError;
QString _errorString;
int m_state;
bool m_hasError;
QString m_errorString;
IPlugin *_plugin;
IPluginManager *_pluginManager;
IPlugin *m_plugin;
IPluginManager *m_pluginManager;
QList<CPluginSpec *> m_dependencySpecs;
friend class CPluginManager;
};

View file

@ -26,6 +26,7 @@ namespace Constants
const char * const OVQT_VERSION_LONG = "0.0.1";
const char * const OVQT_VENDOR = "Dzmitry Kamiahin";
const char * const OVQT_YEAR = "2010, 2011";
const char * const OVQT_CORE_PLUGIN = "Core";
//mainwindow
const char * const MAIN_WINDOW = "ObjectViewerQt.MainWindow";

View file

@ -63,7 +63,8 @@ bool CorePlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QStr
QtWin::extendFrameIntoClientArea(_mainWindow);
_mainWindow->setContentsMargins(0, 0, 0, 0);
}
*/ bool success = _mainWindow->initialize(errorString);
*/
bool success = _mainWindow->initialize(errorString);
CSearchPathsSettingsPage *serchPathPage = new CSearchPathsSettingsPage(this);
serchPathPage->applySearchPaths();
addAutoReleasedObject(serchPathPage);
@ -91,7 +92,7 @@ void CorePlugin::setNelContext(NLMISC::INelContext *nelContext)
QString CorePlugin::name() const
{
return QLatin1String("Core");
return QLatin1String(Constants::OVQT_CORE_PLUGIN);
}
QString CorePlugin::version() const
@ -109,9 +110,9 @@ QString CorePlugin::description() const
return "Core plugin.";
}
QList<QString> CorePlugin::dependencies() const
QStringList CorePlugin::dependencies() const
{
return QList<QString>();
return QStringList();
}
void CorePlugin::addAutoReleasedObject(QObject *obj)

View file

@ -57,7 +57,7 @@ public:
QString version() const;
QString vendor() const;
QString description() const;
QList<QString> dependencies() const;
QStringList dependencies() const;
void addAutoReleasedObject(QObject *obj);

View file

@ -86,9 +86,12 @@ QString MyPlugin::description() const
return "Example ovqt plugin.";
}
QList<QString> MyPlugin::dependencies() const
QStringList MyPlugin::dependencies() const
{
return QList<QString>();
QStringList list;
list.append(Core::Constants::OVQT_CORE_PLUGIN);
list.append("ObjectViewer");
return list;
}
void MyPlugin::addAutoReleasedObject(QObject *obj)

View file

@ -43,7 +43,7 @@ public:
QString version() const;
QString vendor() const;
QString description() const;
QList<QString> dependencies() const;
QStringList dependencies() const;
void addAutoReleasedObject(QObject *obj);

View file

@ -65,9 +65,11 @@ QString ObjectViewerPlugin::description() const
return "Object Viewer plugin.";
}
QList<QString> ObjectViewerPlugin::dependencies() const
QStringList ObjectViewerPlugin::dependencies() const
{
return QList<QString>();
QStringList list;
list.append(Core::Constants::OVQT_CORE_PLUGIN);
return list;
}
void ObjectViewerPlugin::addAutoReleasedObject(QObject *obj)

View file

@ -42,7 +42,7 @@ public:
QString version() const;
QString vendor() const;
QString description() const;
QList<QString> dependencies() const;
QStringList dependencies() const;
void addAutoReleasedObject(QObject *obj);