diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp index 52147a75bcaa6d24dc1760e982ccb8d707c210f6..83486bbaf99d7c172d339f2bb57f4b0477068277 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.cpp +++ b/src/plugins/qmlprojectmanager/qmlproject.cpp @@ -132,7 +132,7 @@ void QmlProject::refresh(RefreshOptions options) pinfo.importPaths = importPaths(); if (pinfo.qmlDumpPath.isNull()) { - pinfo.qmlDumpPath = Qt4ProjectManager::QmlDumpTool::qmlDumpPath(); + pinfo.qmlDumpPath = Qt4ProjectManager::QmlDumpTool::qmlDumpPath(this); } m_modelManager->updateProjectInfo(pinfo); diff --git a/src/plugins/qt4projectmanager/qmldumptool.cpp b/src/plugins/qt4projectmanager/qmldumptool.cpp index 5d11f0dec9bb326ec714cad35b5318495e064d82..02200c33d8039ba428c65b888e4a9f5f52f93ade 100644 --- a/src/plugins/qt4projectmanager/qmldumptool.cpp +++ b/src/plugins/qt4projectmanager/qmldumptool.cpp @@ -30,14 +30,90 @@ #include "qmldumptool.h" #include "qt4project.h" #include "qt4projectmanagerconstants.h" +#include "qtversionmanager.h" #include <coreplugin/icore.h> +#include <coreplugin/progressmanager/progressmanager.h> #include <projectexplorer/project.h> #include <projectexplorer/projectexplorer.h> +#include <qtconcurrent/runextensions.h> +#include <qmljs/qmljsmodelmanagerinterface.h> #include <QDesktopServices> #include <QCoreApplication> #include <QDir> #include <QDebug> +#include <QHash> + +namespace { +using namespace Qt4ProjectManager; + +class QmlDumpBuildTask; + +typedef QHash<int, QmlDumpBuildTask *> QmlDumpByVersion; +Q_GLOBAL_STATIC(QmlDumpByVersion, runningQmlDumpBuilds); + +// A task suitable to be run by QtConcurrent to build qmldump. +class QmlDumpBuildTask : public QObject { + Q_DISABLE_COPY(QmlDumpBuildTask) + Q_OBJECT +public: + explicit QmlDumpBuildTask(QtVersion *version) + : m_version(*version) + { + runningQmlDumpBuilds()->insert(m_version.uniqueId(), this); + } + + void run(QFutureInterface<void> &future) + { + future.setProgressRange(0, 5); + future.setProgressValue(1); + const QString output = m_version.buildDebuggingHelperLibrary(future, true); + + const QString qtInstallData = m_version.versionInfo().value("QT_INSTALL_DATA"); + QString path = QmlDumpTool::toolByInstallData(qtInstallData); + if (path.isEmpty()) { + qWarning() << "Could not build QML plugin dumping helper for " << m_version.displayName() + << "\nOutput:\n" << output; + } + + // proceed in gui thread + metaObject()->invokeMethod(this, "finish", Qt::QueuedConnection, Q_ARG(QString, path)); + } + + void updateProjectWhenDone(ProjectExplorer::Project *project) + { + m_projectsToUpdate.insert(project); + } + +public slots: + void finish(QString qmldumpPath) + { + deleteLater(); + runningQmlDumpBuilds()->remove(m_version.uniqueId()); + + if (qmldumpPath.isEmpty()) + return; + + // update qmldump path for all the project + QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance(); + if (!modelManager) + return; + + foreach (ProjectExplorer::Project *project, m_projectsToUpdate) { + QmlJS::ModelManagerInterface::ProjectInfo projectInfo = modelManager->projectInfo(project); + if (projectInfo.qmlDumpPath.isEmpty()) { + projectInfo.qmlDumpPath = qmldumpPath; + modelManager->updateProjectInfo(projectInfo); + } + } + } + +private: + QSet<ProjectExplorer::Project *> m_projectsToUpdate; + QtVersion m_version; +}; +} // end of anonymous namespace + namespace Qt4ProjectManager { @@ -55,20 +131,48 @@ bool QmlDumpTool::canBuild(QtVersion *qtVersion) return checkMinimumQtVersion(qtVersion->qtVersionString(), 4, 7, 0); } -QString QmlDumpTool::toolForProject(ProjectExplorer::Project *project) +static QtVersion *qtVersionForProject(ProjectExplorer::Project *project) { if (project && project->id() == Qt4ProjectManager::Constants::QT4PROJECT_ID) { Qt4Project *qt4Project = static_cast<Qt4Project*>(project); if (qt4Project && qt4Project->activeTarget() - && qt4Project->activeTarget()->activeBuildConfiguration()) { + && qt4Project->activeTarget()->activeBuildConfiguration()) { QtVersion *version = qt4Project->activeTarget()->activeBuildConfiguration()->qtVersion(); - if (version->isValid()) { - QString qtInstallData = version->versionInfo().value("QT_INSTALL_DATA"); - QString toolPath = toolByInstallData(qtInstallData); - return toolPath; + if (version->isValid()) + return version; + } + return 0; + } + + // else, find any desktop Qt version that has qmldump, or - if there isn't any - + // one that could build it + QtVersion *desktopQt = 0; + QtVersionManager *qtVersions = QtVersionManager::instance(); + foreach (QtVersion *version, qtVersions->validVersions()) { + if (version->supportsTargetId(Constants::DESKTOP_TARGET_ID)) { + const QString qtInstallData = version->versionInfo().value("QT_INSTALL_DATA"); + const QString path = QmlDumpTool::toolByInstallData(qtInstallData); + if (!path.isEmpty()) + return version; + + if (!desktopQt && QmlDumpTool::canBuild(version)) { + desktopQt = version; } } } + + return desktopQt; +} + +QString QmlDumpTool::toolForProject(ProjectExplorer::Project *project) +{ + QtVersion *version = qtVersionForProject(project); + if (version) { + QString qtInstallData = version->versionInfo().value("QT_INSTALL_DATA"); + QString toolPath = toolByInstallData(qtInstallData); + return toolPath; + } + return QString(); } @@ -139,38 +243,41 @@ QStringList QmlDumpTool::installDirectories(const QString &qtInstallData) return directories; } -QString QmlDumpTool::qmlDumpPath() +QString QmlDumpTool::qmlDumpPath(ProjectExplorer::Project *project) { QString path; - ProjectExplorer::Project *activeProject = ProjectExplorer::ProjectExplorerPlugin::instance()->startupProject(); - path = Qt4ProjectManager::QmlDumpTool::toolForProject(activeProject); - - // ### this is needed for qmlproject and cmake project support, but may not work in all cases. - if (path.isEmpty()) { - // Try to locate default path in Qt Versions - QtVersionManager *qtVersions = QtVersionManager::instance(); - foreach (QtVersion *version, qtVersions->validVersions()) { - if (version->supportsTargetId(Constants::DESKTOP_TARGET_ID)) { - const QString qtInstallData = version->versionInfo().value("QT_INSTALL_DATA"); - path = QmlDumpTool::toolByInstallData(qtInstallData); - - if (!path.isEmpty()) { - break; - } - } + path = Qt4ProjectManager::QmlDumpTool::toolForProject(project); + + QtVersion *version = qtVersionForProject(project); + if (version && path.isEmpty()) { + if (runningQmlDumpBuilds()->contains(version->uniqueId())) { + runningQmlDumpBuilds()->value(version->uniqueId())->updateProjectWhenDone(project); + } else { + QmlDumpBuildTask *buildTask = new QmlDumpBuildTask(version); + buildTask->updateProjectWhenDone(project); + QFuture<void> task = QtConcurrent::run(&QmlDumpBuildTask::run, buildTask); + const QString taskName = QmlDumpBuildTask::tr("Building helper"); + Core::ICore::instance()->progressManager()->addTask(task, taskName, + QLatin1String("Qt4ProjectManager::BuildHelpers")); } + return path; } - QFileInfo qmldumpFileInfo(path); - if (!qmldumpFileInfo.exists()) { - //qWarning() << "QmlDumpTool::qmlDumpPath: qmldump executable does not exist at" << path; - path.clear(); - } else if (!qmldumpFileInfo.isFile()) { - qWarning() << "QmlDumpTool::qmlDumpPath: " << path << " is not a file"; - path.clear(); + + if (!path.isEmpty()) { + QFileInfo qmldumpFileInfo(path); + if (!qmldumpFileInfo.exists()) { + qWarning() << "QmlDumpTool::qmlDumpPath: qmldump executable does not exist at" << path; + path.clear(); + } else if (!qmldumpFileInfo.isFile()) { + qWarning() << "QmlDumpTool::qmlDumpPath: " << path << " is not a file"; + path.clear(); + } } return path; } -} // namespace +} // namespace Qt4ProjectManager + +#include "qmldumptool.moc" diff --git a/src/plugins/qt4projectmanager/qmldumptool.h b/src/plugins/qt4projectmanager/qmldumptool.h index dc9914780770067b791b9eebf296d403155d8d1c..3201f7ba3e6c764bd403c342b34ab7a83b525a30 100644 --- a/src/plugins/qt4projectmanager/qmldumptool.h +++ b/src/plugins/qt4projectmanager/qmldumptool.h @@ -60,7 +60,7 @@ public: // Copy the source files to a target location and return the chosen target location. static QString copy(const QString &qtInstallData, QString *errorMessage); - static QString qmlDumpPath(); + static QString qmlDumpPath(ProjectExplorer::Project *project); private: static QStringList installDirectories(const QString &qtInstallData); diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp index a11fc013e2a92d4124b48df6f5dc935844e852d7..408a259ba86170cebea457507509b98d109fd668 100644 --- a/src/plugins/qt4projectmanager/qt4project.cpp +++ b/src/plugins/qt4projectmanager/qt4project.cpp @@ -569,6 +569,9 @@ void Qt4Project::updateCppCodeModel() void Qt4Project::updateQmlJSCodeModel() { + if (m_projectFiles->files[QMLType].isEmpty()) + return; + QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance(); if (!modelManager) return; @@ -587,7 +590,7 @@ void Qt4Project::updateQmlJSCodeModel() projectInfo.importPaths.removeDuplicates(); if (projectInfo.qmlDumpPath.isNull()) { - projectInfo.qmlDumpPath = QmlDumpTool::qmlDumpPath(); + projectInfo.qmlDumpPath = QmlDumpTool::qmlDumpPath(this); } modelManager->updateProjectInfo(projectInfo); diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp index 283f52ba44e92a9d45678bda0e220bc8fc5d42b8..2e9fb6ce027bb894ff0f71384a537db58067c357 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.cpp +++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp @@ -1746,7 +1746,7 @@ bool QtVersion::isQt64Bit() const #endif } -QString QtVersion::buildDebuggingHelperLibrary(QFutureInterface<void> &future) +QString QtVersion::buildDebuggingHelperLibrary(QFutureInterface<void> &future, bool onlyQmlDump) { QString qtInstallHeaders = versionInfo().value("QT_INSTALL_HEADERS"); QString qtInstallData = versionInfo().value("QT_INSTALL_DATA"); @@ -1762,13 +1762,28 @@ QString QtVersion::buildDebuggingHelperLibrary(QFutureInterface<void> &future) return QCoreApplication::translate("QtVersion", "The Qt Version has no toolchain."); tc->addToEnvironment(env); QString output; - QString gdbHelperDirectory = DebuggingHelperLibrary::copy(qtInstallData, &output); - if (!gdbHelperDirectory.isEmpty()) { - output += DebuggingHelperLibrary::build(gdbHelperDirectory, tc->makeCommand(), - qmakeCommand(), mkspec(), env, - (tc->type() == ToolChain::GCC_MAEMO ? QLatin1String("-unix") : QLatin1String(""))); + + if (!onlyQmlDump) { + QString gdbHelperDirectory = DebuggingHelperLibrary::copy(qtInstallData, &output); + if (!gdbHelperDirectory.isEmpty()) { + output += DebuggingHelperLibrary::build(gdbHelperDirectory, tc->makeCommand(), + qmakeCommand(), mkspec(), env, + (tc->type() == ToolChain::GCC_MAEMO ? QLatin1String("-unix") : QLatin1String(""))); + } + future.setProgressValue(2); + + if (QmlObserverTool::canBuild(this)) { + QString toolDirectory = QmlObserverTool::copy(qtInstallData, &output); + if (!toolDirectory.isEmpty()) { + output += QmlObserverTool::build(toolDirectory, tc->makeCommand(), + qmakeCommand(), mkspec(), env, + (tc->type() == ToolChain::GCC_MAEMO ? QLatin1String("-unix") : QLatin1String(""))); + } + } else { + output += QCoreApplication::tr("Cannot build QMLObserver; Qt version must be 4.7.1 or higher."); + } + future.setProgressValue(3); } - future.setProgressValue(2); if (QmlDumpTool::canBuild(this)) { QString toolDirectory = QmlDumpTool::copy(qtInstallData, &output); @@ -1780,28 +1795,17 @@ QString QtVersion::buildDebuggingHelperLibrary(QFutureInterface<void> &future) } else { output += QCoreApplication::tr("Cannot build qmldump; Qt version must be 4.7.1 or higher."); } - future.setProgressValue(3); - - if (QmlObserverTool::canBuild(this)) { - QString toolDirectory = QmlObserverTool::copy(qtInstallData, &output); - if (!toolDirectory.isEmpty()) { - output += QmlObserverTool::build(toolDirectory, tc->makeCommand(), - qmakeCommand(), mkspec(), env, - (tc->type() == ToolChain::GCC_MAEMO ? QLatin1String("-unix") : QLatin1String(""))); - } - } else { - output += QCoreApplication::tr("Cannot build QMLObserver; Qt version must be 4.7.1 or higher."); - } future.setProgressValue(4); // invalidate version before updating version info m_versionInfoUpToDate = false; updateVersionInfo(); - m_hasDebuggingHelper = !debuggingHelperLibrary().isEmpty(); + if (!onlyQmlDump) { + m_hasDebuggingHelper = !debuggingHelperLibrary().isEmpty(); + m_hasQmlObserver = !qmlObserverTool().isEmpty(); + } m_hasQmlDump = !qmlDumpTool().isEmpty(); - m_hasQmlObserver = !qmlObserverTool().isEmpty(); return output; } - diff --git a/src/plugins/qt4projectmanager/qtversionmanager.h b/src/plugins/qt4projectmanager/qtversionmanager.h index 4e9f0ac156007983c4901cbe26fb5630191b50ff..1c90205f0e5f54769f47f0cfaae5d6b1998cbde0 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.h +++ b/src/plugins/qt4projectmanager/qtversionmanager.h @@ -122,7 +122,7 @@ public: // Builds a debugging library // returns the output of the commands - QString buildDebuggingHelperLibrary(QFutureInterface<void> &future); + QString buildDebuggingHelperLibrary(QFutureInterface<void> &future, bool onlyQmlDump = false); bool hasExamples() const; QString examplesPath() const;