Commit 00a8d9c3 authored by Christian Kamm's avatar Christian Kamm
Browse files

QmlJS: Try to build qmldump when opening a Qml project.

To make plugin dumping work without having to compile the debugging
helpers explicitly.

Reviewed-by: Kai Koehne
parent bb543b32
......@@ -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);
......
......@@ -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"
......@@ -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);
......
......@@ -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);
......
......@@ -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;
}
......@@ -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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment