diff --git a/src/libs/extensionsystem/iplugin.cpp b/src/libs/extensionsystem/iplugin.cpp index 5060b0a68d6..e6ee6e4a6b9 100644 --- a/src/libs/extensionsystem/iplugin.cpp +++ b/src/libs/extensionsystem/iplugin.cpp @@ -98,6 +98,7 @@ describing the reason. \sa extensionsInitialized() + \sa delayedInitialize() */ /*! @@ -112,6 +113,28 @@ been provided by dependent plugins. \sa initialize() + \sa delayedInitialize() +*/ + +/*! + \fn bool IPlugin::delayedInitialize() + \brief Called after all plugins' IPlugin::extensionsInitialized() method has been called, + and after the IPlugin::delayedInitialize() method of plugins that depend on this plugin + have been called. + + The plugins' delayedInitialize() methods are called after the application is already running, + with a few milliseconds delay to application startup, and between individual delayedInitialize + method calls. To avoid unnecessary delays, a plugin should return true from the method if it + actually implements it, to indicate that the next plugins' delayedInitialize() call should + be delayed a few milliseconds to give input and paint events a chance to be processed. + + This method can be used if a plugin needs to do non-trivial setup that doesn't + necessarily needs to be done directly at startup, but still should be done within a + short time afterwards. This can increase the felt plugin/application startup + time a lot, with very little effort. + + \sa initialize() + \sa extensionsInitialized() */ /*! diff --git a/src/libs/extensionsystem/iplugin.h b/src/libs/extensionsystem/iplugin.h index b3652aed3f3..8d251820fd2 100644 --- a/src/libs/extensionsystem/iplugin.h +++ b/src/libs/extensionsystem/iplugin.h @@ -62,6 +62,7 @@ public: virtual bool initialize(const QStringList &arguments, QString *errorString) = 0; virtual void extensionsInitialized() = 0; + virtual bool delayedInitialize() { return false; } virtual ShutdownFlag aboutToShutdown() { return SynchronousShutdown; } virtual void remoteCommand(const QStringList & /* options */, const QStringList & /* arguments */) { } diff --git a/src/libs/extensionsystem/pluginmanager.cpp b/src/libs/extensionsystem/pluginmanager.cpp index 7d19c9ffbee..9420af85b46 100644 --- a/src/libs/extensionsystem/pluginmanager.cpp +++ b/src/libs/extensionsystem/pluginmanager.cpp @@ -55,6 +55,7 @@ static const char C_IGNORED_PLUGINS[] = "Plugins/Ignored"; static const char C_FORCEENABLED_PLUGINS[] = "Plugins/ForceEnabled"; +static const int DELAYED_INITIALIZE_INTERVAL = 20; // ms typedef QList PluginSpecSet; @@ -782,12 +783,32 @@ PluginSpecPrivate *PluginManagerPrivate::privateSpec(PluginSpec *spec) return spec->d; } +void PluginManagerPrivate::nextDelayedInitialize() +{ + while (!delayedInitializeQueue.isEmpty()) { + PluginSpec *spec = delayedInitializeQueue.takeFirst(); + profilingReport(">delayedInitialize", spec); + bool delay = spec->d->delayedInitialize(); + profilingReport("start(); + } +} + /*! \fn PluginManagerPrivate::PluginManagerPrivate(PluginManager *pluginManager) \internal */ PluginManagerPrivate::PluginManagerPrivate(PluginManager *pluginManager) : extension(QLatin1String("xml")), + delayedInitializeTimer(0), + shutdownEventLoop(0), m_profileElapsedMS(0), m_profilingVerbosity(0), settings(0), @@ -849,6 +870,11 @@ void PluginManagerPrivate::readSettings() */ void PluginManagerPrivate::stopAll() { + if (delayedInitializeTimer && delayedInitializeTimer->isActive()) { + delayedInitializeTimer->stop(); + delete delayedInitializeTimer; + delayedInitializeTimer = 0; + } QList queue = loadQueue(); foreach (PluginSpec *spec, queue) { loadPlugin(spec, PluginSpec::Stopped); @@ -941,9 +967,19 @@ void PluginManagerPrivate::loadPlugins() QListIterator it(queue); it.toBack(); while (it.hasPrevious()) { - loadPlugin(it.previous(), PluginSpec::Running); + PluginSpec *spec = it.previous(); + loadPlugin(spec, PluginSpec::Running); + if (spec->state() == PluginSpec::Running) + delayedInitializeQueue.append(spec); } emit q->pluginsChanged(); + + delayedInitializeTimer = new QTimer; + delayedInitializeTimer->setInterval(DELAYED_INITIALIZE_INTERVAL); + delayedInitializeTimer->setSingleShot(true); + connect(delayedInitializeTimer, SIGNAL(timeout()), + this, SLOT(nextDelayedInitialize())); + delayedInitializeTimer->start(); } /*! diff --git a/src/libs/extensionsystem/pluginmanager_p.h b/src/libs/extensionsystem/pluginmanager_p.h index 95f1db47c04..be33e8ad793 100644 --- a/src/libs/extensionsystem/pluginmanager_p.h +++ b/src/libs/extensionsystem/pluginmanager_p.h @@ -42,6 +42,7 @@ QT_BEGIN_NAMESPACE class QTime; +class QTimer; class QSettings; class QEventLoop; QT_END_NAMESPACE @@ -90,6 +91,10 @@ public: QStringList defaultDisabledPlugins; QStringList disabledPlugins; QStringList forceEnabledPlugins; + // delayed initialization + QTimer *delayedInitializeTimer; + QList delayedInitializeQueue; + // ansynchronous shutdown QList asynchronousPlugins; // plugins that have requested async shutdown QEventLoop *shutdownEventLoop; // used for async shutdown @@ -109,6 +114,7 @@ public: static PluginSpecPrivate *privateSpec(PluginSpec *spec); private slots: + void nextDelayedInitialize(); void asyncShutdownFinished(); private: diff --git a/src/libs/extensionsystem/pluginspec.cpp b/src/libs/extensionsystem/pluginspec.cpp index eed4413b952..57c58992037 100644 --- a/src/libs/extensionsystem/pluginspec.cpp +++ b/src/libs/extensionsystem/pluginspec.cpp @@ -1013,6 +1013,25 @@ bool PluginSpecPrivate::initializeExtensions() return true; } +/*! + \fn bool PluginSpecPrivate::delayedInitialize() + \internal +*/ +bool PluginSpecPrivate::delayedInitialize() +{ + if (hasError) + return false; + if (state != PluginSpec::Running) { + return false; + } + if (!plugin) { + errorString = QCoreApplication::translate("PluginSpec", "Internal error: have no plugin instance to perform delayedInitialize"); + hasError = true; + return false; + } + return plugin->delayedInitialize(); +} + /*! \fn bool PluginSpecPrivate::stop() \internal diff --git a/src/libs/extensionsystem/pluginspec_p.h b/src/libs/extensionsystem/pluginspec_p.h index 25842ad563c..2ae53438e18 100644 --- a/src/libs/extensionsystem/pluginspec_p.h +++ b/src/libs/extensionsystem/pluginspec_p.h @@ -60,6 +60,7 @@ public: bool loadLibrary(); bool initializePlugin(); bool initializeExtensions(); + bool delayedInitialize(); IPlugin::ShutdownFlag stop(); void kill(); diff --git a/src/plugins/coreplugin/coreplugin.cpp b/src/plugins/coreplugin/coreplugin.cpp index 85d49a94788..3fe8bd19322 100644 --- a/src/plugins/coreplugin/coreplugin.cpp +++ b/src/plugins/coreplugin/coreplugin.cpp @@ -31,13 +31,14 @@ **************************************************************************/ #include "coreplugin.h" +#include "designmode.h" #include "editmode.h" #include "editormanager.h" -#include "mainwindow.h" -#include "modemanager.h" #include "fileiconprovider.h" -#include "designmode.h" +#include "helpmanager.h" +#include "mainwindow.h" #include "mimedatabase.h" +#include "modemanager.h" #include @@ -105,6 +106,12 @@ void CorePlugin::extensionsInitialized() m_mainWindow->extensionsInitialized(); } +bool CorePlugin::delayedInitialize() +{ + HelpManager::instance()->setupHelpManager(); + return true; +} + void CorePlugin::remoteCommand(const QStringList & /* options */, const QStringList &args) { m_mainWindow->openFiles(args, ICore::SwitchMode); diff --git a/src/plugins/coreplugin/coreplugin.h b/src/plugins/coreplugin/coreplugin.h index b3f27a2bd98..947abf800f6 100644 --- a/src/plugins/coreplugin/coreplugin.h +++ b/src/plugins/coreplugin/coreplugin.h @@ -50,10 +50,11 @@ public: CorePlugin(); ~CorePlugin(); - virtual bool initialize(const QStringList &arguments, QString *errorMessage = 0); - virtual void extensionsInitialized(); - virtual ShutdownFlag aboutToShutdown(); - virtual void remoteCommand(const QStringList & /* options */, const QStringList &args); + bool initialize(const QStringList &arguments, QString *errorMessage = 0); + void extensionsInitialized(); + bool delayedInitialize(); + ShutdownFlag aboutToShutdown(); + void remoteCommand(const QStringList & /* options */, const QStringList &args); public slots: void fileOpenRequest(const QString&); diff --git a/src/plugins/coreplugin/helpmanager.cpp b/src/plugins/coreplugin/helpmanager.cpp index f32032488ba..7f54267e0b0 100644 --- a/src/plugins/coreplugin/helpmanager.cpp +++ b/src/plugins/coreplugin/helpmanager.cpp @@ -40,7 +40,6 @@ #include #include #include -#include #include @@ -91,7 +90,6 @@ HelpManager::HelpManager(QObject *parent) : { Q_ASSERT(!m_instance); m_instance = this; - connect(Core::ICore::instance(), SIGNAL(coreOpened()), SLOT(delayedSetupHelpManager())); } HelpManager::~HelpManager() @@ -102,11 +100,6 @@ HelpManager::~HelpManager() delete d; } -void HelpManager::delayedSetupHelpManager() -{ - QTimer::singleShot(100, this, SLOT(setupHelpManager())); -} - HelpManager *HelpManager::instance() { Q_ASSERT(m_instance); diff --git a/src/plugins/coreplugin/helpmanager.h b/src/plugins/coreplugin/helpmanager.h index f72faa5d20e..90924ae52eb 100644 --- a/src/plugins/coreplugin/helpmanager.h +++ b/src/plugins/coreplugin/helpmanager.h @@ -46,6 +46,10 @@ QT_FORWARD_DECLARE_CLASS(QUrl) namespace Core { struct HelpManagerPrivate; +namespace Internal { +class CorePlugin; +} + class CORE_EXPORT HelpManager : public QObject { Q_OBJECT @@ -91,13 +95,11 @@ signals: void collectionFileChanged(); void helpRequested(const QUrl &url); -private slots: - void delayedSetupHelpManager(); - void setupHelpManager(); - private: + void setupHelpManager(); void verifyDocumenation(); HelpManagerPrivate *d; + friend class Internal::CorePlugin; // setupHelpManager }; } // Core diff --git a/src/plugins/locator/locatorplugin.cpp b/src/plugins/locator/locatorplugin.cpp index 9291901635d..868135e3d1c 100644 --- a/src/plugins/locator/locatorplugin.cpp +++ b/src/plugins/locator/locatorplugin.cpp @@ -139,7 +139,6 @@ bool LocatorPlugin::initialize(const QStringList &, QString *) addAutoReleasedObject(new LocatorFiltersFilter(this, m_locatorWidget)); - connect(Core::ICore::instance(), SIGNAL(coreOpened()), this, SLOT(startSettingsLoad())); return true; } @@ -167,10 +166,11 @@ void LocatorPlugin::extensionsInitialized() setFilters(m_filters); } -void LocatorPlugin::startSettingsLoad() +bool LocatorPlugin::delayedInitialize() { connect(&m_loadWatcher, SIGNAL(finished()), this, SLOT(settingsLoaded())); m_loadWatcher.setFuture(QtConcurrent::run(this, &LocatorPlugin::loadSettings)); + return true; } void LocatorPlugin::loadSettings() diff --git a/src/plugins/locator/locatorplugin.h b/src/plugins/locator/locatorplugin.h index 09e6e140b21..59ca5164449 100644 --- a/src/plugins/locator/locatorplugin.h +++ b/src/plugins/locator/locatorplugin.h @@ -63,6 +63,7 @@ public: bool initialize(const QStringList &arguments, QString *errorMessage); void extensionsInitialized(); + bool delayedInitialize(); QList filters(); QList customFilters(); @@ -77,7 +78,6 @@ public slots: void openLocator(); private slots: - void startSettingsLoad(); void settingsLoaded(); void updatePlaceholderText(Core::Command *command = 0); diff --git a/src/plugins/qtsupport/qtsupportplugin.cpp b/src/plugins/qtsupport/qtsupportplugin.cpp index 84a19b1d724..21426016ded 100644 --- a/src/plugins/qtsupport/qtsupportplugin.cpp +++ b/src/plugins/qtsupport/qtsupportplugin.cpp @@ -80,7 +80,11 @@ bool QtSupportPlugin::initialize(const QStringList &arguments, QString *errorMes void QtSupportPlugin::extensionsInitialized() { QtVersionManager::instance()->extensionsInitialized(); +} +bool QtSupportPlugin::delayedInitialize() +{ + return QtVersionManager::instance()->delayedInitialize(); } Q_EXPORT_PLUGIN(QtSupportPlugin) diff --git a/src/plugins/qtsupport/qtsupportplugin.h b/src/plugins/qtsupport/qtsupportplugin.h index 12726fda01f..8ea327febde 100644 --- a/src/plugins/qtsupport/qtsupportplugin.h +++ b/src/plugins/qtsupport/qtsupportplugin.h @@ -49,6 +49,7 @@ class QtSupportPlugin : public ExtensionSystem::IPlugin public: bool initialize(const QStringList &arguments, QString *errorMessage); void extensionsInitialized(); + bool delayedInitialize(); private slots: #ifdef WITH_TESTS diff --git a/src/plugins/qtsupport/qtversionmanager.cpp b/src/plugins/qtsupport/qtversionmanager.cpp index bb8242ca77e..757cc131afe 100644 --- a/src/plugins/qtsupport/qtversionmanager.cpp +++ b/src/plugins/qtsupport/qtversionmanager.cpp @@ -138,10 +138,15 @@ void QtVersionManager::extensionsInitialized() findSystemQt(); } - connect(Core::ICore::instance(), SIGNAL(coreOpened()), this, SLOT(delayedUpdateDocumentation())); saveQtVersions(); } +bool QtVersionManager::delayedInitialize() +{ + updateDocumentation(); + return true; +} + QtVersionManager::~QtVersionManager() { qDeleteAll(m_versions); @@ -513,11 +518,6 @@ void QtVersionManager::updateDumpFor(const Utils::FileName &qmakeCommand) emit dumpUpdatedFor(qmakeCommand); } -void QtVersionManager::delayedUpdateDocumentation() -{ - QTimer::singleShot(100, this, SLOT(updateDocumentation())); -} - int QtVersionManager::getUniqueId() { return m_idcount++; diff --git a/src/plugins/qtsupport/qtversionmanager.h b/src/plugins/qtsupport/qtversionmanager.h index 611d82f379f..97690293adb 100644 --- a/src/plugins/qtsupport/qtversionmanager.h +++ b/src/plugins/qtsupport/qtversionmanager.h @@ -62,6 +62,7 @@ public: QtVersionManager(); ~QtVersionManager(); void extensionsInitialized(); + bool delayedInitialize(); // This will *always* return at least one (Qt in Path), even if that is // unconfigured. @@ -110,10 +111,6 @@ signals: public slots: void updateDumpFor(const Utils::FileName &qmakeCommand); -private slots: - void delayedUpdateDocumentation(); - void updateDocumentation(); - private: // This function is really simplistic... static bool equals(BaseQtVersion *a, BaseQtVersion *b); @@ -130,6 +127,7 @@ private: void findSystemQt(); void updateFromInstaller(); void saveQtVersions(); + void updateDocumentation(); // Used by QtOptionsPage void setNewQtVersions(QList newVersions); // Used by QtVersion