forked from qt-creator/qt-creator
ProjectExplorer: reduce the perceived startup time
... by moving restoreKits to the delayed initialize phase. Change-Id: If72e41b64ee71f2917b3f7a317d9887afc6e29e8 Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
@@ -224,13 +224,19 @@ CMakeKitAspectFactory::CMakeKitAspectFactory()
|
||||
"This setting is ignored when using other build systems."));
|
||||
setPriority(20000);
|
||||
|
||||
auto updateKits = [this] {
|
||||
if (KitManager::isLoaded()) {
|
||||
for (Kit *k : KitManager::kits())
|
||||
fix(k);
|
||||
}
|
||||
};
|
||||
|
||||
//make sure the default value is set if a selected CMake is removed
|
||||
connect(CMakeToolManager::instance(), &CMakeToolManager::cmakeRemoved,
|
||||
this, [this] { for (Kit *k : KitManager::kits()) fix(k); });
|
||||
connect(CMakeToolManager::instance(), &CMakeToolManager::cmakeRemoved, this, updateKits);
|
||||
|
||||
//make sure the default value is set if a new default CMake is set
|
||||
connect(CMakeToolManager::instance(), &CMakeToolManager::defaultCMakeChanged,
|
||||
this, [this] { for (Kit *k : KitManager::kits()) fix(k); });
|
||||
this, updateKits);
|
||||
}
|
||||
|
||||
Id CMakeKitAspect::id()
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
#include <QStyle>
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
const int kInitialWidth = 750;
|
||||
const int kInitialHeight = 450;
|
||||
const int kMaxMinimumWidth = 250;
|
||||
@@ -800,6 +802,14 @@ bool SettingsDialog::execDialog()
|
||||
|
||||
bool executeSettingsDialog(QWidget *parent, Id initialPage)
|
||||
{
|
||||
if (!ExtensionSystem::PluginManager::isInitializationDone()) {
|
||||
QObject::connect(ExtensionSystem::PluginManager::instance(),
|
||||
&ExtensionSystem::PluginManager::initializationDone,
|
||||
parent,
|
||||
[parent, initialPage]() { executeSettingsDialog(parent, initialPage); });
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure all wizards are there when the user might access the keyboard shortcuts:
|
||||
(void) IWizardFactory::allWizardFactories();
|
||||
|
||||
|
||||
@@ -1316,6 +1316,9 @@ static Kit *guessKitFromAbis(const Abis &abis)
|
||||
{
|
||||
Kit *kit = nullptr;
|
||||
|
||||
if (!KitManager::waitForLoaded())
|
||||
return kit;
|
||||
|
||||
// Try to find a kit via ABI.
|
||||
if (!abis.isEmpty()) {
|
||||
// Try exact abis.
|
||||
@@ -1376,9 +1379,11 @@ bool DebuggerPluginPrivate::parseArgument(QStringList::const_iterator &it,
|
||||
return false;
|
||||
}
|
||||
} else if (key == "kit") {
|
||||
kit = KitManager::kit(Id::fromString(val));
|
||||
if (!kit)
|
||||
kit = KitManager::kit(Utils::equal(&Kit::displayName, val));
|
||||
if (KitManager::waitForLoaded()) {
|
||||
kit = KitManager::kit(Id::fromString(val));
|
||||
if (!kit)
|
||||
kit = KitManager::kit(Utils::equal(&Kit::displayName, val));
|
||||
}
|
||||
} else if (key == "server") {
|
||||
startMode = AttachToRemoteServer;
|
||||
remoteChannel = val;
|
||||
|
||||
@@ -84,7 +84,7 @@ UnstartedAppWatcherDialog::UnstartedAppWatcherDialog(QWidget *parent)
|
||||
|
||||
if (kit)
|
||||
m_kitChooser->setCurrentKitId(kit->id());
|
||||
else if (KitManager::defaultKit())
|
||||
else if (KitManager::waitForLoaded() && KitManager::defaultKit())
|
||||
m_kitChooser->setCurrentKitId(KitManager::defaultKit()->id());
|
||||
|
||||
auto pathLayout = new QHBoxLayout;
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
#include <projectexplorer/kitmanager.h>
|
||||
|
||||
#include <texteditor/texteditorconstants.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
@@ -283,7 +285,12 @@ void HelpPlugin::extensionsInitialized()
|
||||
|
||||
bool HelpPlugin::delayedInitialize()
|
||||
{
|
||||
HelpManager::setupHelpManager();
|
||||
if (ProjectExplorer::KitManager::isLoaded()) {
|
||||
HelpManager::setupHelpManager();
|
||||
} else {
|
||||
connect(ProjectExplorer::KitManager::instance(), &ProjectExplorer::KitManager::kitsLoaded,
|
||||
this, &HelpManager::setupHelpManager);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "toolchainmanager.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/progressmanager/progressmanager.h>
|
||||
|
||||
#include <android/androidconstants.h>
|
||||
#include <baremetal/baremetalconstants.h>
|
||||
@@ -421,10 +422,10 @@ void KitManager::restoreKits()
|
||||
if (!k)
|
||||
k = Utils::findOrDefault(resultList, &Kit::isValid);
|
||||
std::swap(resultList, d->m_kitList);
|
||||
d->m_initialized = true;
|
||||
setDefaultKit(k);
|
||||
|
||||
d->m_writer = std::make_unique<PersistentSettingsWriter>(settingsFileName(), "QtCreatorProfiles");
|
||||
d->m_initialized = true;
|
||||
|
||||
kitAspectFactoriesStorage().onKitsLoaded();
|
||||
|
||||
@@ -467,6 +468,33 @@ bool KitManager::isLoaded()
|
||||
return d->m_initialized;
|
||||
}
|
||||
|
||||
bool KitManager::waitForLoaded(const int timeout)
|
||||
{
|
||||
if (isLoaded())
|
||||
return true;
|
||||
showLoadingProgress();
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
while (!isLoaded() && !timer.hasExpired(timeout))
|
||||
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
return KitManager::isLoaded();
|
||||
}
|
||||
|
||||
void KitManager::showLoadingProgress()
|
||||
{
|
||||
if (isLoaded())
|
||||
return;
|
||||
static QFutureInterface<void> futureInterface;
|
||||
if (futureInterface.isRunning())
|
||||
return;
|
||||
futureInterface.reportStarted();
|
||||
Core::ProgressManager::addTimedTask(futureInterface.future(),
|
||||
Tr::tr("Loading Kits"),
|
||||
"LoadingKitsProgress",
|
||||
5);
|
||||
connect(instance(), &KitManager::kitsLoaded, []() { futureInterface.reportFinished(); });
|
||||
}
|
||||
|
||||
void KitManager::setBinaryForKit(const FilePath &binary)
|
||||
{
|
||||
QTC_ASSERT(d, return);
|
||||
@@ -475,6 +503,7 @@ void KitManager::setBinaryForKit(const FilePath &binary)
|
||||
|
||||
const QList<Kit *> KitManager::sortedKits()
|
||||
{
|
||||
QTC_ASSERT(KitManager::isLoaded(), return {});
|
||||
// This method was added to delay the sorting of kits as long as possible.
|
||||
// Since the displayName can contain variables it can be costly (e.g. involve
|
||||
// calling executables to find version information, etc.) to call that
|
||||
@@ -548,6 +577,7 @@ static KitList restoreKitsHelper(const FilePath &fileName)
|
||||
|
||||
const QList<Kit *> KitManager::kits()
|
||||
{
|
||||
QTC_ASSERT(KitManager::isLoaded(), return {});
|
||||
return Utils::toRawPointer<QList>(d->m_kitList);
|
||||
}
|
||||
|
||||
@@ -556,6 +586,7 @@ Kit *KitManager::kit(Id id)
|
||||
if (!id.isValid())
|
||||
return nullptr;
|
||||
|
||||
QTC_ASSERT(KitManager::isLoaded(), return {});
|
||||
return Utils::findOrDefault(d->m_kitList, Utils::equal(&Kit::id, id));
|
||||
}
|
||||
|
||||
@@ -566,6 +597,7 @@ Kit *KitManager::kit(const Kit::Predicate &predicate)
|
||||
|
||||
Kit *KitManager::defaultKit()
|
||||
{
|
||||
QTC_ASSERT(KitManager::isLoaded(), return {});
|
||||
return d->m_defaultKit;
|
||||
}
|
||||
|
||||
@@ -597,7 +629,7 @@ void KitManager::notifyAboutUpdate(Kit *k)
|
||||
|
||||
Kit *KitManager::registerKit(const std::function<void (Kit *)> &init, Utils::Id id)
|
||||
{
|
||||
QTC_ASSERT(isLoaded(), return nullptr);
|
||||
QTC_ASSERT(isLoaded(), return {});
|
||||
|
||||
auto k = std::make_unique<Kit>(id);
|
||||
QTC_ASSERT(k->id().isValid(), return nullptr);
|
||||
@@ -620,6 +652,8 @@ Kit *KitManager::registerKit(const std::function<void (Kit *)> &init, Utils::Id
|
||||
|
||||
void KitManager::deregisterKit(Kit *k)
|
||||
{
|
||||
QTC_ASSERT(KitManager::isLoaded(), return);
|
||||
|
||||
if (!k || !Utils::contains(d->m_kitList, k))
|
||||
return;
|
||||
auto taken = Utils::take(d->m_kitList, k);
|
||||
@@ -632,6 +666,8 @@ void KitManager::deregisterKit(Kit *k)
|
||||
|
||||
void KitManager::setDefaultKit(Kit *k)
|
||||
{
|
||||
QTC_ASSERT(KitManager::isLoaded(), return);
|
||||
|
||||
if (defaultKit() == k)
|
||||
return;
|
||||
if (k && !Utils::contains(d->m_kitList, k))
|
||||
|
||||
@@ -155,6 +155,8 @@ public:
|
||||
static void saveKits();
|
||||
|
||||
static bool isLoaded();
|
||||
static bool waitForLoaded(const int timeout = 60 * 1000); // timeout in ms
|
||||
static void showLoadingProgress();
|
||||
|
||||
signals:
|
||||
void kitAdded(ProjectExplorer::Kit *);
|
||||
|
||||
@@ -197,6 +197,7 @@ signals:
|
||||
void kitStateChanged();
|
||||
|
||||
private:
|
||||
void initializeFromKitManager();
|
||||
void addKit(Kit *k);
|
||||
void updateKit(Kit *k);
|
||||
void removeKit(Kit *k);
|
||||
@@ -227,10 +228,11 @@ KitModel::KitModel(QBoxLayout *parentLayout, QObject *parent)
|
||||
rootItem()->appendChild(m_autoRoot);
|
||||
rootItem()->appendChild(m_manualRoot);
|
||||
|
||||
for (Kit *k : KitManager::sortedKits())
|
||||
addKit(k);
|
||||
|
||||
changeDefaultKit();
|
||||
if (KitManager::isLoaded()) {
|
||||
for (Kit *k : KitManager::sortedKits())
|
||||
addKit(k);
|
||||
changeDefaultKit();
|
||||
}
|
||||
|
||||
connect(KitManager::instance(), &KitManager::kitAdded,
|
||||
this, &KitModel::addKit);
|
||||
|
||||
@@ -24,13 +24,13 @@
|
||||
#include "toolchainmanager.h"
|
||||
#include "userfileaccessor.h"
|
||||
|
||||
#include <coreplugin/idocument.h>
|
||||
#include <coreplugin/documentmanager.h>
|
||||
#include <coreplugin/editormanager/documentmodel.h>
|
||||
#include <coreplugin/icontext.h>
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/idocument.h>
|
||||
#include <coreplugin/iversioncontrol.h>
|
||||
#include <coreplugin/vcsmanager.h>
|
||||
#include <coreplugin/editormanager/documentmodel.h>
|
||||
|
||||
#include <projectexplorer/buildmanager.h>
|
||||
#include <projectexplorer/kitmanager.h>
|
||||
@@ -643,6 +643,12 @@ void Project::saveSettings()
|
||||
|
||||
Project::RestoreResult Project::restoreSettings(QString *errorMessage)
|
||||
{
|
||||
if (!KitManager::waitForLoaded()) {
|
||||
if (errorMessage)
|
||||
*errorMessage = Tr::tr("Could not load kits in a reasonable amount of time.");
|
||||
return RestoreResult::Error;
|
||||
}
|
||||
|
||||
if (!d->m_accessor)
|
||||
d->m_accessor = std::make_unique<Internal::UserFileAccessor>(this);
|
||||
Store map(d->m_accessor->restoreSettings(ICore::dialogParent()));
|
||||
|
||||
@@ -2121,20 +2121,15 @@ void ProjectExplorerPlugin::extensionsInitialized()
|
||||
|
||||
// Load devices immediately, as other plugins might want to use them
|
||||
DeviceManager::instance()->load();
|
||||
|
||||
// delay restoring kits until UI is shown for improved perceived startup performance
|
||||
QTimer::singleShot(0, this, &ProjectExplorerPlugin::restoreKits);
|
||||
}
|
||||
|
||||
void ProjectExplorerPlugin::restoreKits()
|
||||
bool ProjectExplorerPlugin::delayedInitialize()
|
||||
{
|
||||
NANOTRACE_SCOPE("ProjectExplorer", "ProjectExplorerPlugin::restoreKits");
|
||||
ExtraAbi::load(); // Load this before Toolchains!
|
||||
ToolChainManager::restoreToolChains();
|
||||
KitManager::restoreKits();
|
||||
// restoring startup session is supposed to be done as a result of ICore::coreOpened,
|
||||
// and that is supposed to happen after restoring kits:
|
||||
QTC_CHECK(!SessionManager::isStartupSessionRestored());
|
||||
return true;
|
||||
}
|
||||
|
||||
void ProjectExplorerPluginPrivate::updateRunWithoutDeployMenu()
|
||||
@@ -2379,8 +2374,7 @@ ProjectExplorerPlugin::OpenProjectResult ProjectExplorerPlugin::openProjects(con
|
||||
dd->updateActions();
|
||||
|
||||
const bool switchToProjectsMode = Utils::anyOf(openedPro, &Project::needsConfiguration);
|
||||
const bool switchToEditMode = Utils::allOf(openedPro,
|
||||
[](Project *p) { return p->isEditModePreferred(); });
|
||||
const bool switchToEditMode = Utils::allOf(openedPro, &Project::isEditModePreferred);
|
||||
if (!openedPro.isEmpty()) {
|
||||
if (switchToProjectsMode)
|
||||
ModeManager::activateMode(Constants::MODE_SESSION);
|
||||
|
||||
@@ -106,7 +106,7 @@ public:
|
||||
//PluginInterface
|
||||
bool initialize(const QStringList &arguments, QString *errorMessage) override;
|
||||
void extensionsInitialized() override;
|
||||
void restoreKits();
|
||||
bool delayedInitialize() override;
|
||||
ShutdownFlag aboutToShutdown() override;
|
||||
|
||||
static void setProjectExplorerSettings(const ProjectExplorerSettings &pes);
|
||||
|
||||
@@ -129,6 +129,7 @@ void ToolChainManager::saveToolChains()
|
||||
|
||||
const Toolchains &ToolChainManager::toolchains()
|
||||
{
|
||||
QTC_CHECK(d->m_loaded);
|
||||
return d->m_toolChains;
|
||||
}
|
||||
|
||||
@@ -140,11 +141,13 @@ Toolchains ToolChainManager::toolchains(const ToolChain::Predicate &predicate)
|
||||
|
||||
ToolChain *ToolChainManager::toolChain(const ToolChain::Predicate &predicate)
|
||||
{
|
||||
QTC_CHECK(d->m_loaded);
|
||||
return Utils::findOrDefault(d->m_toolChains, predicate);
|
||||
}
|
||||
|
||||
Toolchains ToolChainManager::findToolChains(const Abi &abi)
|
||||
{
|
||||
QTC_CHECK(d->m_loaded);
|
||||
Toolchains result;
|
||||
for (ToolChain *tc : std::as_const(d->m_toolChains)) {
|
||||
bool isCompatible = Utils::anyOf(tc->supportedAbis(), [abi](const Abi &supportedAbi) {
|
||||
@@ -159,6 +162,7 @@ Toolchains ToolChainManager::findToolChains(const Abi &abi)
|
||||
|
||||
ToolChain *ToolChainManager::findToolChain(const QByteArray &id)
|
||||
{
|
||||
QTC_CHECK(d->m_loaded);
|
||||
if (id.isEmpty())
|
||||
return nullptr;
|
||||
|
||||
@@ -214,6 +218,7 @@ bool ToolChainManager::registerToolChain(ToolChain *tc)
|
||||
|
||||
void ToolChainManager::deregisterToolChain(ToolChain *tc)
|
||||
{
|
||||
QTC_CHECK(d->m_loaded);
|
||||
if (!tc || !d->m_toolChains.contains(tc))
|
||||
return;
|
||||
d->m_toolChains.removeOne(tc);
|
||||
|
||||
@@ -179,6 +179,10 @@ static bool getEditorLaunchData(const CommandForQtVersion &commandForQtVersion,
|
||||
// - default kit
|
||||
// - any other kit
|
||||
// As fallback check PATH
|
||||
if (!KitManager::waitForLoaded()) {
|
||||
*errorMessage = Tr::tr("Could not load kits in a reasonable amount of time.");
|
||||
return false;
|
||||
}
|
||||
data->workingDirectory.clear();
|
||||
QVector<QtSupport::QtVersion *> qtVersionsToCheck; // deduplicated after being filled
|
||||
if (const Project *project = ProjectManager::projectForFile(filePath)) {
|
||||
|
||||
Reference in New Issue
Block a user