diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2017-11-28 15:57:15 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2018-01-29 09:04:45 +0000 |
commit | e44504371c99960e05ca42bae4ce404bcc18998a (patch) | |
tree | 458c9a9e7bddf3dc113e72fcd2794d71bcd4fd82 | |
parent | c535cce8c670c17d018571e7f32a4f624b0c09a9 (diff) |
QmlProjectManager: Prepare for running on remote devices
We add a "targetDirectory" property to the file format and fill in the
deployment data.
(cherry picked from commit fba61c5b55052c382e030748fa6e2703abb5401d)
Change-Id: If207cd5c77175c54cffdb5df92ea85c425cd3191
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
9 files changed, 141 insertions, 53 deletions
diff --git a/share/qtcreator/qml-type-descriptions/qmlproject.qmltypes b/share/qtcreator/qml-type-descriptions/qmlproject.qmltypes index a0dbed2b56..c7e7cdf937 100644 --- a/share/qtcreator/qml-type-descriptions/qmlproject.qmltypes +++ b/share/qtcreator/qml-type-descriptions/qmlproject.qmltypes @@ -11,6 +11,7 @@ Module { "QmlProject/Project 1.1" ] Property { name: "sourceDirectory"; type: "string" } + Property { name: "targetDirectory": type: "string" } Property { name: "mainFile"; type: "string" } Property { name: "importPaths"; type: "string"; isList: true } Property { name: "content"; type: "QmlProjectItem"; isList: true } diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp index 7893abc266..6154ecd3d7 100644 --- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp +++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp @@ -88,6 +88,10 @@ QmlProjectItem *QmlProjectFileFormat::parseProjectFile(const Utils::FileName &fi if (importPathsProperty.isValid()) projectItem->setImportPaths(importPathsProperty.toStringList()); + const QVariant targetDirectoryPropery = rootNode->property("targetDirectory"); + if (targetDirectoryPropery.isValid()) + projectItem->setTargetDirectory(targetDirectoryPropery.toString()); + if (debug) qDebug() << "importPath:" << importPathsProperty << "mainFile:" << mainFileProperty; diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp index 0d8d4e1550..8e9e99475f 100644 --- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp +++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp @@ -51,6 +51,11 @@ void QmlProjectItem::setSourceDirectory(const QString &directoryPath) setImportPaths(m_importPaths); } +void QmlProjectItem::setTargetDirectory(const QString &directoryPath) +{ + m_targetDirectory = directoryPath; +} + void QmlProjectItem::setImportPaths(const QStringList &importPaths) { if (m_importPaths != importPaths) diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h index 09298174a7..757e571468 100644 --- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h +++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h @@ -46,6 +46,8 @@ class QmlProjectItem : public QObject public: QString sourceDirectory() const { return m_sourceDirectory; } void setSourceDirectory(const QString &directoryPath); + QString targetDirectory() const { return m_targetDirectory; } + void setTargetDirectory(const QString &directoryPath); QStringList importPaths() const { return m_absoluteImportPaths; } void setImportPaths(const QStringList &paths); @@ -63,6 +65,7 @@ signals: protected: QString m_sourceDirectory; + QString m_targetDirectory; QStringList m_importPaths; QStringList m_absoluteImportPaths; QString m_mainFile; diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp index d1b32f8c36..2f9ab498da 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.cpp +++ b/src/plugins/qmlprojectmanager/qmlproject.cpp @@ -36,6 +36,7 @@ #include <coreplugin/messagemanager.h> #include <coreplugin/documentmanager.h> +#include <projectexplorer/deploymentdata.h> #include <projectexplorer/kitinformation.h> #include <projectexplorer/kitmanager.h> #include <projectexplorer/target.h> @@ -59,6 +60,10 @@ QmlProject::QmlProject(const Utils::FileName &fileName) : Project(QString::fromLatin1(Constants::QMLPROJECT_MIMETYPE), fileName, [this]() { refreshProjectFile(); }) { + const QString normalized + = Utils::FileUtils::normalizePathName(fileName.toFileInfo().canonicalFilePath()); + m_canonicalProjectDir = Utils::FileName::fromString(normalized).parentDir(); + setId(QmlProjectManager::Constants::QML_PROJECT_ID); setProjectLanguages(Context(ProjectExplorer::Constants::QMLJS_LANGUAGE_ID)); setDisplayName(fileName.toFileInfo().completeBaseName()); @@ -75,6 +80,7 @@ void QmlProject::addedTarget(Target *target) this, &QmlProject::addedRunConfiguration); foreach (RunConfiguration *rc, target->runConfigurations()) addedRunConfiguration(rc); + updateDeploymentData(target); } void QmlProject::onActiveTargetChanged(Target *target) @@ -104,9 +110,9 @@ void QmlProject::addedRunConfiguration(RunConfiguration *rc) qmlrc->updateEnabledState(); } -QDir QmlProject::projectDir() const +Utils::FileName QmlProject::canonicalProjectDir() const { - return projectFilePath().toFileInfo().dir(); + return m_canonicalProjectDir; } void QmlProject::parseProject(RefreshOptions options) @@ -129,13 +135,17 @@ void QmlProject::parseProject(RefreshOptions options) } } if (m_projectItem) { - m_projectItem.data()->setSourceDirectory(projectDir().path()); + m_projectItem.data()->setSourceDirectory(canonicalProjectDir().toString()); + if (m_projectItem->targetDirectory().isEmpty()) + m_projectItem->setTargetDirectory(canonicalProjectDir().toString()); + if (auto modelManager = QmlJS::ModelManagerInterface::instance()) modelManager->updateSourceFiles(m_projectItem.data()->files(), true); QString mainFilePath = m_projectItem.data()->mainFile(); if (!mainFilePath.isEmpty()) { - mainFilePath = projectDir().absoluteFilePath(mainFilePath); + mainFilePath + = QDir(canonicalProjectDir().toString()).absoluteFilePath(mainFilePath); Utils::FileReader reader; QString errorMessage; if (!reader.fetch(mainFilePath, &errorMessage)) { @@ -183,6 +193,26 @@ QString QmlProject::mainFile() const return QString(); } +Utils::FileName QmlProject::targetDirectory(const Target *target) const +{ + if (DeviceTypeKitInformation::deviceTypeId(target->kit()) + == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) + return canonicalProjectDir(); + + return m_projectItem ? Utils::FileName::fromString(m_projectItem->targetDirectory()) + : Utils::FileName(); +} + +Utils::FileName QmlProject::targetFile(const Utils::FileName &sourceFile, + const Target *target) const +{ + const QDir sourceDir(m_projectItem ? m_projectItem->sourceDirectory() + : canonicalProjectDir().toString()); + const QDir targetDir(targetDirectory(target).toString()); + const QString relative = sourceDir.relativeFilePath(sourceFile.toString()); + return Utils::FileName::fromString(QDir::cleanPath(targetDir.absoluteFilePath(relative))); +} + bool QmlProject::validProjectFile() const { return !m_projectItem.isNull(); @@ -219,17 +249,18 @@ void QmlProject::refreshFiles(const QSet<QString> &/*added*/, const QSet<QString if (auto modelManager = QmlJS::ModelManagerInterface::instance()) modelManager->removeFiles(removed.toList()); } + refreshTargetDirectory(); } -bool QmlProject::supportsKit(Kit *k, QString *errorMessage) const +void QmlProject::refreshTargetDirectory() { - Id deviceType = DeviceTypeKitInformation::deviceTypeId(k); - if (deviceType != ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) { - if (errorMessage) - *errorMessage = tr("Device type is not desktop."); - return false; - } + const QList<Target *> targetList = targets(); + for (Target *target : targetList) + updateDeploymentData(target); +} +bool QmlProject::supportsKit(Kit *k, QString *errorMessage) const +{ QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k); if (!version) { if (errorMessage) @@ -262,15 +293,28 @@ Project::RestoreResult QmlProject::fromMap(const QVariantMap &map, QString *erro return false; IDevice::ConstPtr dev = DeviceKitInformation::device(k); - if (dev.isNull() || dev->type() != ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) + if (dev.isNull()) return false; + QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k); - if (!version || version->type() != QLatin1String(QtSupport::Constants::DESKTOPQT)) + if (!version || version->qtVersion() < QtSupport::QtVersionNumber(5, 0, 0)) return false; - return version->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0) - && !static_cast<QtSupport::DesktopQtVersion *>(version) - ->qmlsceneCommand().isEmpty(); + if (dev->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) { + if (version->type() != QLatin1String(QtSupport::Constants::DESKTOPQT)) { + return !static_cast<QtSupport::DesktopQtVersion *>(version) + ->qmlsceneCommand().isEmpty(); + } else { + // Non-desktop Qt on a desktop device? We don't support that. + return false; + } + } + + // If not a desktop device, don't check the Qt version for qmlscene. + // The device is responsible for providing it and we assume qmlscene can be found + // in $PATH if it's not explicitly given. + return true; + }) ); @@ -322,7 +366,27 @@ void QmlProject::generateProjectTree() newRoot->addNestedNode(new FileNode(projectFilePath(), FileType::Project, false)); setRootProjectNode(newRoot); + refreshTargetDirectory(); } +void QmlProject::updateDeploymentData(ProjectExplorer::Target *target) +{ + if (!m_projectItem) + return; + + if (DeviceTypeKitInformation::deviceTypeId(target->kit()) + == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) { + return; + } + + ProjectExplorer::DeploymentData deploymentData; + for (const QString &file : m_projectItem->files()) { + deploymentData.addFile( + file, + targetFile(Utils::FileName::fromString(file), target).parentDir().toString()); + } + + target->setDeploymentData(deploymentData); +} } // namespace QmlProjectManager diff --git a/src/plugins/qmlprojectmanager/qmlproject.h b/src/plugins/qmlprojectmanager/qmlproject.h index 62c7980a28..c1b667d21a 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.h +++ b/src/plugins/qmlprojectmanager/qmlproject.h @@ -60,8 +60,11 @@ public: void refresh(RefreshOptions options); - QDir projectDir() const; + Utils::FileName canonicalProjectDir() const; QString mainFile() const; + Utils::FileName targetDirectory(const ProjectExplorer::Target *target) const; + Utils::FileName targetFile(const Utils::FileName &sourceFile, + const ProjectExplorer::Target *target) const; QStringList customImportPaths() const; bool addFiles(const QStringList &filePaths); @@ -74,7 +77,9 @@ protected: private: void generateProjectTree(); + void updateDeploymentData(ProjectExplorer::Target *target); void refreshFiles(const QSet<QString> &added, const QSet<QString> &removed); + void refreshTargetDirectory(); void addedTarget(ProjectExplorer::Target *target); void onActiveTargetChanged(ProjectExplorer::Target *target); void onKitChanged(); @@ -86,6 +91,7 @@ private: ProjectExplorer::Target *m_activeTarget = nullptr; QPointer<QmlProjectItem> m_projectItem; + Utils::FileName m_canonicalProjectDir; }; } // namespace QmlProjectManager diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp index 3cf0aaec9d..11afeee224 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp @@ -80,8 +80,7 @@ Runnable QmlProjectRunConfiguration::runnable() const r.commandLineArguments = commandLineArguments(); r.runMode = ApplicationLauncher::Gui; r.environment = extraAspect<QmlProjectEnvironmentAspect>()->environment(); - r.workingDirectory = canonicalCapsPath(target()->project()->projectFilePath() - .toFileInfo().absolutePath()); + r.workingDirectory = static_cast<QmlProject *>(project())->targetDirectory(target()).toString(); return r; } @@ -89,48 +88,60 @@ QString QmlProjectRunConfiguration::disabledReason() const { if (mainScript().isEmpty()) return tr("No script file to execute."); - if (!QFileInfo::exists(executable())) + if (DeviceTypeKitInformation::deviceTypeId(target()->kit()) + == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE + && !QFileInfo::exists(executable())) { return tr("No qmlscene found."); + } + if (executable().isEmpty()) + return tr("No qmlscene binary specified for target device."); return RunConfiguration::disabledReason(); } QString QmlProjectRunConfiguration::executable() const { BaseQtVersion *version = QtKitInformation::qtVersion(target()->kit()); - if (!version) + if (!version) // No Qt version in Kit. Don't try to run qmlscene. + return QString(); + + const Id deviceType = DeviceTypeKitInformation::deviceTypeId(target()->kit()); + if (deviceType == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) { + // If not given explicitly by Qt Version, try to pick it from $PATH. + return version->type() == QtSupport::Constants::DESKTOPQT + ? static_cast<QtSupport::DesktopQtVersion *>(version)->qmlsceneCommand() + : QString("qmlscene"); + } + + IDevice::ConstPtr dev = DeviceKitInformation::device(target()->kit()); + if (dev.isNull()) // No device set. We don't know where to run qmlscene. return QString(); - QTC_ASSERT(version->type() == QLatin1String(QtSupport::Constants::DESKTOPQT), return QString()); - return static_cast<QtSupport::DesktopQtVersion *>(version)->qmlsceneCommand(); + const QString qmlscene = dev->qmlsceneCommand(); + // If not given explicitly by device, try to pick it from $PATH. + return qmlscene.isEmpty() ? QString("qmlscene") : qmlscene; } QString QmlProjectRunConfiguration::commandLineArguments() const { // arguments in .user file QString args = m_qmlViewerArgs; + const IDevice::ConstPtr device = DeviceKitInformation::device(target()->kit()); + const Utils::OsType osType = device ? device->osType() : Utils::HostOsInfo::hostOs(); // arguments from .qmlproject file QmlProject *project = static_cast<QmlProject *>(target()->project()); foreach (const QString &importPath, project->customImportPaths()) { - Utils::QtcProcess::addArg(&args, QLatin1String("-I")); - Utils::QtcProcess::addArg(&args, importPath); + Utils::QtcProcess::addArg(&args, QLatin1String("-I"), osType); + Utils::QtcProcess::addArg(&args, importPath, osType); } - QString s = mainScript(); - if (!s.isEmpty()) { - s = canonicalCapsPath(s); - Utils::QtcProcess::addArg(&args, s); - } + const QString main + = project->targetFile(Utils::FileName::fromString(mainScript()), target()).toString(); ; + if (!main.isEmpty()) + Utils::QtcProcess::addArg(&args, main, osType); return args; } -/* QtDeclarative checks explicitly that the capitalization for any URL / path - is exactly like the capitalization on disk.*/ -QString QmlProjectRunConfiguration::canonicalCapsPath(const QString &fileName) -{ - return Utils::FileUtils::normalizePathName(QFileInfo(fileName).canonicalFilePath()); -} - QWidget *QmlProjectRunConfiguration::createConfigurationWidget() { return new QmlProjectRunConfigurationWidget(this); @@ -164,7 +175,7 @@ QString QmlProjectRunConfiguration::mainScript() const if (QFileInfo(pathInProject).isAbsolute()) return pathInProject; else - return project->projectDir().absoluteFilePath(pathInProject); + return QDir(project->canonicalProjectDir().toString()).absoluteFilePath(pathInProject); } if (!m_mainScriptFilename.isEmpty()) @@ -272,17 +283,16 @@ void QmlProjectRunConfiguration::updateEnabledState() qmlFileFound = !mainScript().isEmpty(); } - if (QFileInfo::exists(executable()) && qmlFileFound) - RunConfiguration::updateEnabledState(); - else + if (!qmlFileFound) { setEnabled(false); -} - -bool QmlProjectRunConfiguration::isValidVersion(QtSupport::BaseQtVersion *version) -{ - return version - && version->type() == QLatin1String(QtSupport::Constants::DESKTOPQT) - && !static_cast<QtSupport::DesktopQtVersion *>(version)->qmlsceneCommand().isEmpty(); + } else { + const QString exe = executable(); + if (exe.isEmpty()) { + setEnabled(false); + } else { + RunConfiguration::updateEnabledState(); + } + } } } // namespace QmlProjectManager diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h index 17a6dfcb52..7e8181c0ab 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h +++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h @@ -80,10 +80,6 @@ private: QString executable() const; QString commandLineArguments() const; - static bool isValidVersion(QtSupport::BaseQtVersion *version); - - static QString canonicalCapsPath(const QString &filePath); - // absolute path to current file (if being used) QString m_currentFileFilename; // absolute path to selected main script (if being used) diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationfactory.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationfactory.cpp index dcfd2c5163..436ec3dc2d 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationfactory.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationfactory.cpp @@ -37,7 +37,6 @@ QmlProjectRunConfigurationFactory::QmlProjectRunConfigurationFactory(QObject *pa setObjectName("QmlProjectRunConfigurationFactory"); registerRunConfiguration<QmlProjectRunConfiguration>(Constants::QML_SCENE_RC_ID); addSupportedProjectType(QmlProjectManager::Constants::QML_PROJECT_ID); - setSupportedTargetDeviceTypes({ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE}); addFixedBuildTarget(tr("QML Scene")); } |