diff --git a/src/libs/extensionsystem/iplugin.cpp b/src/libs/extensionsystem/iplugin.cpp index 5060b0a68d60dfdfb46856ec9185968173ded02d..e6ee6e4a6b95d3f575a38e9647865b94c79bffbf 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 b3652aed3f386a0f6f53f69ad7eb6de39c1d5461..8d251820fd207ead5f06f32d9501afec9e68086f 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 7d19c9ffbee2f86b720290d280d26f8cd3c1f37e..9420af85b46e93b5fc41e7ce7f39c548aed38f9e 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<ExtensionSystem::PluginSpec *> 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("<delayedInitialize", spec); + if (delay) + break; // do next delayedInitialize after a delay + } + if (delayedInitializeQueue.isEmpty()) { + delete delayedInitializeTimer; + delayedInitializeTimer = 0; + } else { + delayedInitializeTimer->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<PluginSpec *> queue = loadQueue(); foreach (PluginSpec *spec, queue) { loadPlugin(spec, PluginSpec::Stopped); @@ -941,9 +967,19 @@ void PluginManagerPrivate::loadPlugins() QListIterator<PluginSpec *> 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 95f1db47c0424615f085cb8dd6382b54ad8161cc..be33e8ad793fdf94afa49c02a90808e082f5d44d 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<PluginSpec *> delayedInitializeQueue; + // ansynchronous shutdown QList<PluginSpec *> 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 eed4413b952969f7bc35dc45dd483326e74f6580..57c58992037af98005725ffc2d57711616dce5ca 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 25842ad563cd5d52d714cc8ca3df9b458668f6b3..2ae53438e18054b4df3abbfd9e71ec0e3bb2b708 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 85d49a947889e4924eaa67b6b4d996374bcefa07..3fe8bd193224285c159ef612f83d917fea6d6262 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 <extensionsystem/pluginmanager.h> @@ -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 b3f27a2bd98e666ba5ad27678710c67998dca230..947abf800f61766b2c3f693417b66b186680ff1e 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 f32032488ba94b4fc38d40d3ec60802c37ddb192..7f54267e0b08aaafafadf4645d25f5f39293664c 100644 --- a/src/plugins/coreplugin/helpmanager.cpp +++ b/src/plugins/coreplugin/helpmanager.cpp @@ -40,7 +40,6 @@ #include <QtCore/QDir> #include <QtCore/QFileInfo> #include <QtCore/QStringList> -#include <QtCore/QTimer> #include <QtHelp/QHelpEngineCore> @@ -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 f72faa5d20e28d403966a63a495544a37b508a88..90924ae52eb0c837dcddd3015673e5a3183d87b2 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 9291901635dd7c6661afa022f1aaad4856d526c4..868135e3d1cc85cf1cb72e81763f5cc4d744b853 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 09e6e140b21c4b8f3ef6049edb96514ac879f690..59ca5164449fcd0f4d0634944598fc7807dcc37d 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<ILocatorFilter*> filters(); QList<ILocatorFilter*> 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 84a19b1d72446a20461a8b82319a76e2a7807b57..21426016ded0876e5748dd6d7c7d4a518f38a645 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 12726fda01ffb105f91e68f3911687c5517019b9..8ea327febdeb90b175f8bcadce5b687f77c7533e 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 bb8242ca77ed9ece028678a690985b28f47fdf99..757cc131afee700d38bbb015e5626bd4a5c6718f 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 611d82f379ff4f94e589701be8a33f9d09c647ca..97690293adb9fdfd0bed1fc841504b59f577dc89 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<BaseQtVersion *> newVersions); // Used by QtVersion