1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
34 #include "pluginspec.h"
36 #include "pluginspec_p.h"
38 #include "iplugin_p.h"
39 #include "pluginmanager.h"
41 #include <QtCore/QDir>
42 #include <QtCore/QFile>
43 #include <QtCore/QFileInfo>
44 #include <QtCore/QXmlStreamReader>
45 #include <QtCore/QRegExp>
46 #include <QtCore/QCoreApplication>
50 // Using the patched version breaks on Fedora 10, KDE4.2.2/Qt4.5.
51 # define USE_UNPATCHED_QPLUGINLOADER 1
53 # define USE_UNPATCHED_QPLUGINLOADER 1
56 #if USE_UNPATCHED_QPLUGINLOADER
58 # include <QtCore/QPluginLoader>
59 typedef QT_PREPEND_NAMESPACE(QPluginLoader) PluginLoader;
63 # include "patchedpluginloader.cpp"
64 typedef PatchedPluginLoader PluginLoader;
69 \class ExtensionSystem::PluginDependency
70 \brief Struct that contains the name and required compatible version number of a plugin's dependency.
72 This reflects the data of a dependency tag in the plugin's xml description file.
73 The name and version are used to resolve the dependency, i.e. a plugin with the given name and
74 plugin \c {compatibility version <= dependency version <= plugin version} is searched for.
76 See also ExtensionSystem::IPlugin for more information about plugin dependencies and
81 \variable ExtensionSystem::PluginDependency::name
82 String identifier of the plugin.
86 \variable ExtensionSystem::PluginDependency::version
87 Version string that a plugin must match to fill this dependency.
91 \variable ExtensionSystem::PluginDependency::type
92 Defines whether the dependency is required or optional.
93 \sa ExtensionSystem::PluginDependency::Type
97 \enum ExtensionSystem::PluginDependency::Type
98 Whether the dependency is required or optional.
100 Dependency needs to be there.
102 Dependency is not necessarily needed. You need to make sure that
103 the plugin is able to load without this dependency installed, so
104 for example you may not link to the dependency's library.
108 \class ExtensionSystem::PluginSpec
109 \brief Contains the information of the plugins xml description file and
110 information about the plugin's current state.
112 The plugin spec is also filled with more information as the plugin
113 goes through its loading process (see PluginSpec::State).
114 If an error occurs, the plugin spec is the place to look for the
119 \enum ExtensionSystem::PluginSpec::State
121 The plugin goes through several steps while being loaded.
122 The state gives a hint on what went wrong in case of an error.
125 Starting point: Even the xml description file was not read.
127 The xml description file has been successfully read, and its
128 information is available via the PluginSpec.
130 The dependencies given in the description file have been
131 successfully found, and are available via the dependencySpecs() method.
133 The plugin's library is loaded and the plugin instance created
134 (available through plugin()).
136 The plugin instance's IPlugin::initialize() method has been called
137 and returned a success value.
139 The plugin's dependencies are successfully initialized and
140 extensionsInitialized has been called. The loading process is
143 The plugin has been shut down, i.e. the plugin's IPlugin::aboutToShutdown() method has been called.
145 The plugin instance has been deleted.
148 using namespace ExtensionSystem;
149 using namespace ExtensionSystem::Internal;
152 \fn uint qHash(const ExtensionSystem::PluginDependency &value)
155 uint ExtensionSystem::qHash(const ExtensionSystem::PluginDependency &value)
157 return qHash(value.name);
161 \fn bool PluginDependency::operator==(const PluginDependency &other)
164 bool PluginDependency::operator==(const PluginDependency &other) const
166 return name == other.name && version == other.version && type == other.type;
170 \fn PluginSpec::PluginSpec()
173 PluginSpec::PluginSpec()
174 : d(new PluginSpecPrivate(this))
179 \fn PluginSpec::~PluginSpec()
182 PluginSpec::~PluginSpec()
189 \fn QString PluginSpec::name() const
190 The plugin name. This is valid after the PluginSpec::Read state is reached.
192 QString PluginSpec::name() const
198 \fn QString PluginSpec::version() const
199 The plugin version. This is valid after the PluginSpec::Read state is reached.
201 QString PluginSpec::version() const
207 \fn QString PluginSpec::compatVersion() const
208 The plugin compatibility version. This is valid after the PluginSpec::Read state is reached.
210 QString PluginSpec::compatVersion() const
212 return d->compatVersion;
216 \fn QString PluginSpec::vendor() const
217 The plugin vendor. This is valid after the PluginSpec::Read state is reached.
219 QString PluginSpec::vendor() const
225 \fn QString PluginSpec::copyright() const
226 The plugin copyright. This is valid after the PluginSpec::Read state is reached.
228 QString PluginSpec::copyright() const
234 \fn QString PluginSpec::license() const
235 The plugin license. This is valid after the PluginSpec::Read state is reached.
237 QString PluginSpec::license() const
243 \fn QString PluginSpec::description() const
244 The plugin description. This is valid after the PluginSpec::Read state is reached.
246 QString PluginSpec::description() const
248 return d->description;
252 \fn QString PluginSpec::url() const
253 The plugin url where you can find more information about the plugin. This is valid after the PluginSpec::Read state is reached.
255 QString PluginSpec::url() const
261 \fn QString PluginSpec::category() const
262 The category that the plugin belongs to. Categories are groups of plugins which allow for keeping them together in the UI.
263 Returns an empty string if the plugin does not belong to a category.
265 QString PluginSpec::category() const
271 \fn bool PluginSpec::isExperimental() const
272 Returns if the plugin has its experimental flag set.
274 bool PluginSpec::isExperimental() const
276 return d->experimental;
280 \fn bool PluginSpec::isEnabled() const
281 Returns if the plugin is loaded at startup. True by default - the user can change it from the Plugin settings.
283 bool PluginSpec::isEnabled() const
289 \fn bool PluginSpec::isDisabledIndirectly() const
290 Returns true if loading was not done due to user unselecting this plugin or its dependencies,
291 or if command-line parameter -noload was used.
293 bool PluginSpec::isDisabledIndirectly() const
295 return d->disabledIndirectly;
299 \fn QList<PluginDependency> PluginSpec::dependencies() const
300 The plugin dependencies. This is valid after the PluginSpec::Read state is reached.
302 QList<PluginDependency> PluginSpec::dependencies() const
304 return d->dependencies;
308 \fn PluginSpec::PluginArgumentDescriptions PluginSpec::argumentDescriptions() const
309 Returns a list of descriptions of command line arguments the plugin processes.
312 PluginSpec::PluginArgumentDescriptions PluginSpec::argumentDescriptions() const
314 return d->argumentDescriptions;
318 \fn QString PluginSpec::location() const
319 The absolute path to the directory containing the plugin xml description file
320 this PluginSpec corresponds to.
322 QString PluginSpec::location() const
328 \fn QString PluginSpec::filePath() const
329 The absolute path to the plugin xml description file (including the file name)
330 this PluginSpec corresponds to.
332 QString PluginSpec::filePath() const
338 \fn QStringList PluginSpec::arguments() const
339 Command line arguments specific to that plugin. Set at startup
342 QStringList PluginSpec::arguments() const
348 \fn void PluginSpec::setArguments(const QStringList &arguments)
349 Set the command line arguments specific to that plugin to \a arguments.
352 void PluginSpec::setArguments(const QStringList &arguments)
354 d->arguments = arguments;
358 \fn PluginSpec::addArgument(const QString &argument)
359 Adds \a argument to the command line arguments specific to that plugin.
362 void PluginSpec::addArgument(const QString &argument)
364 d->arguments.push_back(argument);
369 \fn PluginSpec::State PluginSpec::state() const
370 The state in which the plugin currently is.
371 See the description of the PluginSpec::State enum for details.
373 PluginSpec::State PluginSpec::state() const
379 \fn bool PluginSpec::hasError() const
380 Returns whether an error occurred while reading/starting the plugin.
382 bool PluginSpec::hasError() const
388 \fn QString PluginSpec::errorString() const
389 Detailed, possibly multi-line, error description in case of an error.
391 QString PluginSpec::errorString() const
393 return d->errorString;
397 \fn bool PluginSpec::provides(const QString &pluginName, const QString &version) const
398 Returns if this plugin can be used to fill in a dependency of the given
399 \a pluginName and \a version.
401 \sa PluginSpec::dependencies()
403 bool PluginSpec::provides(const QString &pluginName, const QString &version) const
405 return d->provides(pluginName, version);
409 \fn IPlugin *PluginSpec::plugin() const
410 The corresponding IPlugin instance, if the plugin library has already been successfully loaded,
411 i.e. the PluginSpec::Loaded state is reached.
413 IPlugin *PluginSpec::plugin() const
419 \fn QList<PluginSpec *> PluginSpec::dependencySpecs() const
420 Returns the list of dependencies, already resolved to existing plugin specs.
421 Valid if PluginSpec::Resolved state is reached.
423 \sa PluginSpec::dependencies()
425 QHash<PluginDependency, PluginSpec *> PluginSpec::dependencySpecs() const
427 return d->dependencySpecs;
430 //==========PluginSpecPrivate==================
433 const char * const PLUGIN = "plugin";
434 const char * const PLUGIN_NAME = "name";
435 const char * const PLUGIN_VERSION = "version";
436 const char * const PLUGIN_COMPATVERSION = "compatVersion";
437 const char * const PLUGIN_EXPERIMENTAL = "experimental";
438 const char * const VENDOR = "vendor";
439 const char * const COPYRIGHT = "copyright";
440 const char * const LICENSE = "license";
441 const char * const DESCRIPTION = "description";
442 const char * const URL = "url";
443 const char * const CATEGORY = "category";
444 const char * const DEPENDENCYLIST = "dependencyList";
445 const char * const DEPENDENCY = "dependency";
446 const char * const DEPENDENCY_NAME = "name";
447 const char * const DEPENDENCY_VERSION = "version";
448 const char * const DEPENDENCY_TYPE = "type";
449 const char * const DEPENDENCY_TYPE_SOFT = "optional";
450 const char * const DEPENDENCY_TYPE_HARD = "required";
451 const char * const ARGUMENTLIST = "argumentList";
452 const char * const ARGUMENT = "argument";
453 const char * const ARGUMENT_NAME = "name";
454 const char * const ARGUMENT_PARAMETER = "parameter";
457 \fn PluginSpecPrivate::PluginSpecPrivate(PluginSpec *spec)
460 PluginSpecPrivate::PluginSpecPrivate(PluginSpec *spec)
463 disabledIndirectly(false),
465 state(PluginSpec::Invalid),
472 \fn bool PluginSpecPrivate::read(const QString &fileName)
475 bool PluginSpecPrivate::read(const QString &fileName)
488 state = PluginSpec::Invalid;
491 dependencies.clear();
492 QFile file(fileName);
494 return reportError(tr("File does not exist: %1").arg(file.fileName()));
495 if (!file.open(QIODevice::ReadOnly))
496 return reportError(tr("Could not open file for read: %1").arg(file.fileName()));
497 QFileInfo fileInfo(file);
498 location = fileInfo.absolutePath();
499 filePath = fileInfo.absoluteFilePath();
500 QXmlStreamReader reader(&file);
501 while (!reader.atEnd()) {
503 switch (reader.tokenType()) {
504 case QXmlStreamReader::StartElement:
505 readPluginSpec(reader);
511 if (reader.hasError())
512 return reportError(tr("Error parsing file %1: %2, at line %3, column %4")
513 .arg(file.fileName())
514 .arg(reader.errorString())
515 .arg(reader.lineNumber())
516 .arg(reader.columnNumber()));
517 state = PluginSpec::Read;
521 void PluginSpec::setEnabled(bool value)
526 void PluginSpec::setDisabledIndirectly(bool value)
528 d->disabledIndirectly = value;
532 \fn bool PluginSpecPrivate::reportError(const QString &err)
535 bool PluginSpecPrivate::reportError(const QString &err)
542 static inline QString msgAttributeMissing(const char *elt, const char *attribute)
544 return QCoreApplication::translate("PluginSpec", "'%1' misses attribute '%2'").arg(QLatin1String(elt), QLatin1String(attribute));
547 static inline QString msgInvalidFormat(const char *content)
549 return QCoreApplication::translate("PluginSpec", "'%1' has invalid format").arg(content);
552 static inline QString msgInvalidElement(const QString &name)
554 return QCoreApplication::translate("PluginSpec", "Invalid element '%1'").arg(name);
557 static inline QString msgUnexpectedClosing(const QString &name)
559 return QCoreApplication::translate("PluginSpec", "Unexpected closing element '%1'").arg(name);
562 static inline QString msgUnexpectedToken()
564 return QCoreApplication::translate("PluginSpec", "Unexpected token");
568 \fn void PluginSpecPrivate::readPluginSpec(QXmlStreamReader &reader)
571 void PluginSpecPrivate::readPluginSpec(QXmlStreamReader &reader)
573 QString element = reader.name().toString();
574 if (element != QString(PLUGIN)) {
575 reader.raiseError(QCoreApplication::translate("PluginSpec", "Expected element '%1' as top level element").arg(PLUGIN));
578 name = reader.attributes().value(PLUGIN_NAME).toString();
579 if (name.isEmpty()) {
580 reader.raiseError(msgAttributeMissing(PLUGIN, PLUGIN_NAME));
583 version = reader.attributes().value(PLUGIN_VERSION).toString();
584 if (version.isEmpty()) {
585 reader.raiseError(msgAttributeMissing(PLUGIN, PLUGIN_VERSION));
588 if (!isValidVersion(version)) {
589 reader.raiseError(msgInvalidFormat(PLUGIN_VERSION));
592 compatVersion = reader.attributes().value(PLUGIN_COMPATVERSION).toString();
593 if (!compatVersion.isEmpty() && !isValidVersion(compatVersion)) {
594 reader.raiseError(msgInvalidFormat(PLUGIN_COMPATVERSION));
596 } else if (compatVersion.isEmpty()) {
597 compatVersion = version;
599 QString experimentalString = reader.attributes().value(PLUGIN_EXPERIMENTAL).toString();
600 experimental = (experimentalString.compare(QLatin1String("true"), Qt::CaseInsensitive) == 0);
601 if (!experimentalString.isEmpty() && !experimental
602 && experimentalString.compare(QLatin1String("false"), Qt::CaseInsensitive) != 0) {
603 reader.raiseError(msgInvalidFormat(PLUGIN_EXPERIMENTAL));
606 enabled = !experimental;
607 while (!reader.atEnd()) {
609 switch (reader.tokenType()) {
610 case QXmlStreamReader::StartElement:
611 element = reader.name().toString();
612 if (element == VENDOR)
613 vendor = reader.readElementText().trimmed();
614 else if (element == COPYRIGHT)
615 copyright = reader.readElementText().trimmed();
616 else if (element == LICENSE)
617 license = reader.readElementText().trimmed();
618 else if (element == DESCRIPTION)
619 description = reader.readElementText().trimmed();
620 else if (element == URL)
621 url = reader.readElementText().trimmed();
622 else if (element == CATEGORY)
623 category = reader.readElementText().trimmed();
624 else if (element == DEPENDENCYLIST)
625 readDependencies(reader);
626 else if (element == ARGUMENTLIST)
627 readArgumentDescriptions(reader);
629 reader.raiseError(msgInvalidElement(name));
631 case QXmlStreamReader::EndDocument:
632 case QXmlStreamReader::Comment:
633 case QXmlStreamReader::EndElement:
634 case QXmlStreamReader::Characters:
637 reader.raiseError(msgUnexpectedToken());
644 \fn void PluginSpecPrivate::readArgumentDescriptions(QXmlStreamReader &reader)
648 void PluginSpecPrivate::readArgumentDescriptions(QXmlStreamReader &reader)
651 while (!reader.atEnd()) {
653 switch (reader.tokenType()) {
654 case QXmlStreamReader::StartElement:
655 element = reader.name().toString();
656 if (element == ARGUMENT) {
657 readArgumentDescription(reader);
659 reader.raiseError(msgInvalidElement(name));
662 case QXmlStreamReader::Comment:
663 case QXmlStreamReader::Characters:
665 case QXmlStreamReader::EndElement:
666 element = reader.name().toString();
667 if (element == ARGUMENTLIST)
669 reader.raiseError(msgUnexpectedClosing(element));
672 reader.raiseError(msgUnexpectedToken());
679 \fn void PluginSpecPrivate::readArgumentDescription(QXmlStreamReader &reader)
682 void PluginSpecPrivate::readArgumentDescription(QXmlStreamReader &reader)
684 PluginArgumentDescription arg;
685 arg.name = reader.attributes().value(ARGUMENT_NAME).toString();
686 if (arg.name.isEmpty()) {
687 reader.raiseError(msgAttributeMissing(ARGUMENT, ARGUMENT_NAME));
690 arg.parameter = reader.attributes().value(ARGUMENT_PARAMETER).toString();
691 arg.description = reader.readElementText();
692 if (reader.tokenType() != QXmlStreamReader::EndElement)
693 reader.raiseError(msgUnexpectedToken());
694 argumentDescriptions.push_back(arg);
698 \fn void PluginSpecPrivate::readDependencies(QXmlStreamReader &reader)
701 void PluginSpecPrivate::readDependencies(QXmlStreamReader &reader)
704 while (!reader.atEnd()) {
706 switch (reader.tokenType()) {
707 case QXmlStreamReader::StartElement:
708 element = reader.name().toString();
709 if (element == DEPENDENCY) {
710 readDependencyEntry(reader);
712 reader.raiseError(msgInvalidElement(name));
715 case QXmlStreamReader::Comment:
716 case QXmlStreamReader::Characters:
718 case QXmlStreamReader::EndElement:
719 element = reader.name().toString();
720 if (element == DEPENDENCYLIST)
722 reader.raiseError(msgUnexpectedClosing(element));
725 reader.raiseError(msgUnexpectedToken());
732 \fn void PluginSpecPrivate::readDependencyEntry(QXmlStreamReader &reader)
735 void PluginSpecPrivate::readDependencyEntry(QXmlStreamReader &reader)
737 PluginDependency dep;
738 dep.name = reader.attributes().value(DEPENDENCY_NAME).toString();
739 if (dep.name.isEmpty()) {
740 reader.raiseError(msgAttributeMissing(DEPENDENCY, DEPENDENCY_NAME));
743 dep.version = reader.attributes().value(DEPENDENCY_VERSION).toString();
744 if (!dep.version.isEmpty() && !isValidVersion(dep.version)) {
745 reader.raiseError(msgInvalidFormat(DEPENDENCY_VERSION));
748 dep.type = PluginDependency::Required;
749 if (reader.attributes().hasAttribute(DEPENDENCY_TYPE)) {
750 QString typeValue = reader.attributes().value(DEPENDENCY_TYPE).toString();
751 if (typeValue == QLatin1String(DEPENDENCY_TYPE_HARD)) {
752 dep.type = PluginDependency::Required;
753 } else if (typeValue == QLatin1String(DEPENDENCY_TYPE_SOFT)) {
754 dep.type = PluginDependency::Optional;
756 reader.raiseError(msgInvalidFormat(DEPENDENCY_TYPE));
760 dependencies.append(dep);
762 if (reader.tokenType() != QXmlStreamReader::EndElement)
763 reader.raiseError(msgUnexpectedToken());
767 \fn bool PluginSpecPrivate::provides(const QString &pluginName, const QString &pluginVersion) const
770 bool PluginSpecPrivate::provides(const QString &pluginName, const QString &pluginVersion) const
772 if (QString::compare(pluginName, name, Qt::CaseInsensitive) != 0)
774 return (versionCompare(version, pluginVersion) >= 0) && (versionCompare(compatVersion, pluginVersion) <= 0);
778 \fn QRegExp &PluginSpecPrivate::versionRegExp()
781 QRegExp &PluginSpecPrivate::versionRegExp()
783 static QRegExp reg("([0-9]+)(?:[.]([0-9]+))?(?:[.]([0-9]+))?(?:_([0-9]+))?");
787 \fn bool PluginSpecPrivate::isValidVersion(const QString &version)
790 bool PluginSpecPrivate::isValidVersion(const QString &version)
792 return versionRegExp().exactMatch(version);
796 \fn int PluginSpecPrivate::versionCompare(const QString &version1, const QString &version2)
799 int PluginSpecPrivate::versionCompare(const QString &version1, const QString &version2)
801 QRegExp reg1 = versionRegExp();
802 QRegExp reg2 = versionRegExp();
803 if (!reg1.exactMatch(version1))
805 if (!reg2.exactMatch(version2))
809 for (int i = 0; i < 4; ++i) {
810 number1 = reg1.cap(i+1).toInt();
811 number2 = reg2.cap(i+1).toInt();
812 if (number1 < number2)
814 if (number1 > number2)
821 \fn bool PluginSpecPrivate::resolveDependencies(const QList<PluginSpec *> &specs)
824 bool PluginSpecPrivate::resolveDependencies(const QList<PluginSpec *> &specs)
828 if (state == PluginSpec::Resolved)
829 state = PluginSpec::Read; // Go back, so we just re-resolve the dependencies.
830 if (state != PluginSpec::Read) {
831 errorString = QCoreApplication::translate("PluginSpec", "Resolving dependencies failed because state != Read");
835 QHash<PluginDependency, PluginSpec *> resolvedDependencies;
836 foreach (const PluginDependency &dependency, dependencies) {
837 PluginSpec *found = 0;
839 foreach (PluginSpec *spec, specs) {
840 if (spec->provides(dependency.name, dependency.version)) {
846 if (dependency.type == PluginDependency::Required) {
848 if (!errorString.isEmpty())
849 errorString.append(QLatin1Char('\n'));
850 errorString.append(QCoreApplication::translate("PluginSpec", "Could not resolve dependency '%1(%2)'")
851 .arg(dependency.name).arg(dependency.version));
855 resolvedDependencies.insert(dependency, found);
860 dependencySpecs = resolvedDependencies;
862 state = PluginSpec::Resolved;
867 void PluginSpecPrivate::disableIndirectlyIfDependencyDisabled()
872 if (disabledIndirectly)
875 QHashIterator<PluginDependency, PluginSpec *> it(dependencySpecs);
876 while (it.hasNext()) {
878 if (it.key().type == PluginDependency::Optional)
880 PluginSpec *dependencySpec = it.value();
881 if (dependencySpec->isDisabledIndirectly() || !dependencySpec->isEnabled()) {
882 disabledIndirectly = true;
889 \fn bool PluginSpecPrivate::loadLibrary()
892 bool PluginSpecPrivate::loadLibrary()
896 if (state != PluginSpec::Resolved) {
897 if (state == PluginSpec::Loaded)
899 errorString = QCoreApplication::translate("PluginSpec", "Loading the library failed because state != Resolved");
906 QString libName = QString("%1/%2.dll").arg(location).arg(name);
907 #elif defined(Q_OS_MAC)
908 QString libName = QString("%1/lib%2.dylib").arg(location).arg(name);
910 QString libName = QString("%1/lib%2.so").arg(location).arg(name);
916 QString libName = QString("%1/%2d.dll").arg(location).arg(name);
917 #elif defined(Q_OS_MAC)
918 QString libName = QString("%1/lib%2_debug.dylib").arg(location).arg(name);
920 QString libName = QString("%1/lib%2.so").arg(location).arg(name);
925 PluginLoader loader(libName);
926 if (!loader.load()) {
928 errorString = QDir::toNativeSeparators(libName)
929 + QString::fromLatin1(": ") + loader.errorString();
932 IPlugin *pluginObject = qobject_cast<IPlugin*>(loader.instance());
935 errorString = QCoreApplication::translate("PluginSpec", "Plugin is not valid (does not derive from IPlugin)");
939 state = PluginSpec::Loaded;
940 plugin = pluginObject;
941 plugin->d->pluginSpec = q;
946 \fn bool PluginSpecPrivate::initializePlugin()
949 bool PluginSpecPrivate::initializePlugin()
953 if (state != PluginSpec::Loaded) {
954 if (state == PluginSpec::Initialized)
956 errorString = QCoreApplication::translate("PluginSpec", "Initializing the plugin failed because state != Loaded");
961 errorString = QCoreApplication::translate("PluginSpec", "Internal error: have no plugin instance to initialize");
966 if (!plugin->initialize(arguments, &err)) {
967 errorString = QCoreApplication::translate("PluginSpec", "Plugin initialization failed: %1").arg(err);
971 state = PluginSpec::Initialized;
976 \fn bool PluginSpecPrivate::initializeExtensions()
979 bool PluginSpecPrivate::initializeExtensions()
983 if (state != PluginSpec::Initialized) {
984 if (state == PluginSpec::Running)
986 errorString = QCoreApplication::translate("PluginSpec", "Cannot perform extensionsInitialized because state != Initialized");
991 errorString = QCoreApplication::translate("PluginSpec", "Internal error: have no plugin instance to perform extensionsInitialized");
995 plugin->extensionsInitialized();
996 state = PluginSpec::Running;
1001 \fn bool PluginSpecPrivate::stop()
1004 IPlugin::ShutdownFlag PluginSpecPrivate::stop()
1007 return IPlugin::SynchronousShutdown;
1008 state = PluginSpec::Stopped;
1009 return plugin->aboutToShutdown();
1013 \fn bool PluginSpecPrivate::kill()
1016 void PluginSpecPrivate::kill()
1022 state = PluginSpec::Deleted;