1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
34 #include "qmlprojectrunconfiguration.h"
35 #include "qmlproject.h"
36 #include "qmlprojectmanagerconstants.h"
37 #include "qmlprojecttarget.h"
38 #include "qmlprojectrunconfigurationwidget.h"
39 #include <coreplugin/mimedatabase.h>
40 #include <coreplugin/editormanager/editormanager.h>
41 #include <coreplugin/editormanager/ieditor.h>
42 #include <coreplugin/icore.h>
43 #include <utils/qtcassert.h>
44 #include <utils/qtcprocess.h>
45 #include <qt4projectmanager/qtversionmanager.h>
46 #include <qt4projectmanager/qtoutputformatter.h>
47 #include <qt4projectmanager/qt4projectmanagerconstants.h>
50 #include <utils/winutils.h>
53 using Core::EditorManager;
56 using Qt4ProjectManager::QtVersionManager;
58 using namespace QmlProjectManager::Internal;
60 namespace QmlProjectManager {
62 const char * const M_CURRENT_FILE = "CurrentFile";
64 QmlProjectRunConfiguration::QmlProjectRunConfiguration(QmlProjectTarget *parent) :
65 ProjectExplorer::RunConfiguration(parent, QLatin1String(Constants::QML_RC_ID)),
67 m_scriptFile(M_CURRENT_FILE),
68 m_projectTarget(parent),
69 m_usingCurrentFile(true),
76 QmlProjectRunConfiguration::QmlProjectRunConfiguration(QmlProjectTarget *parent,
77 QmlProjectRunConfiguration *source) :
78 ProjectExplorer::RunConfiguration(parent, source),
79 m_qtVersionId(source->m_qtVersionId),
80 m_scriptFile(source->m_scriptFile),
81 m_qmlViewerArgs(source->m_qmlViewerArgs),
82 m_projectTarget(parent),
83 m_usingCurrentFile(source->m_usingCurrentFile),
84 m_userEnvironmentChanges(source->m_userEnvironmentChanges)
90 bool QmlProjectRunConfiguration::isEnabled(ProjectExplorer::BuildConfiguration *bc) const
97 void QmlProjectRunConfiguration::ctor()
99 // reset default settings in constructor
100 setUseCppDebugger(false);
101 setUseQmlDebugger(true);
103 EditorManager *em = Core::EditorManager::instance();
104 connect(em, SIGNAL(currentEditorChanged(Core::IEditor*)),
105 this, SLOT(changeCurrentFile(Core::IEditor*)));
107 QtVersionManager *qtVersions = QtVersionManager::instance();
108 connect(qtVersions, SIGNAL(qtVersionsChanged(QList<int>)), this, SLOT(updateQtVersions()));
110 setDisplayName(tr("QML Viewer", "QMLRunConfiguration display name."));
113 QmlProjectRunConfiguration::~QmlProjectRunConfiguration()
117 QmlProjectTarget *QmlProjectRunConfiguration::qmlTarget() const
119 return static_cast<QmlProjectTarget *>(target());
122 QString QmlProjectRunConfiguration::viewerPath() const
124 Qt4ProjectManager::QtVersion *version = qtVersion();
128 return version->qmlviewerCommand();
132 QString QmlProjectRunConfiguration::observerPath() const
134 Qt4ProjectManager::QtVersion *version = qtVersion();
138 return version->qmlObserverTool();
142 QString QmlProjectRunConfiguration::viewerArguments() const
144 // arguments in .user file
145 QString args = m_qmlViewerArgs;
147 // arguments from .qmlproject file
148 foreach (const QString &importPath, qmlTarget()->qmlProject()->importPaths()) {
149 Utils::QtcProcess::addArg(&args, "-I");
150 Utils::QtcProcess::addArg(&args, importPath);
153 QString s = mainScript();
155 s = canonicalCapsPath(s);
156 Utils::QtcProcess::addArg(&args, s);
161 QString QmlProjectRunConfiguration::workingDirectory() const
163 QFileInfo projectFile(qmlTarget()->qmlProject()->file()->fileName());
164 return canonicalCapsPath(projectFile.absolutePath());
167 int QmlProjectRunConfiguration::qtVersionId() const
169 return m_qtVersionId;
172 void QmlProjectRunConfiguration::setQtVersionId(int id)
174 if (m_qtVersionId == id)
178 qmlTarget()->qmlProject()->refresh(QmlProject::Configuration);
179 if (m_configurationWidget)
180 m_configurationWidget.data()->updateQtVersionComboBox();
183 /* QtDeclarative checks explicitly that the capitalization for any URL / path
184 is exactly like the capitalization on disk. This method is uses the same
185 native Windows API's to get the exact canonical path. */
186 QString QmlProjectRunConfiguration::canonicalCapsPath(const QString &fileName)
188 QString canonicalPath = QFileInfo(fileName).canonicalFilePath();
190 #if defined(Q_OS_WIN32)
191 // don't know whether the shortpath step is really needed,
192 // but we do this in QtDeclarative too.
193 QString path = Utils::getShortPathName(canonicalPath);
195 path = Utils::getLongPathName(canonicalPath);
197 canonicalPath = path;
200 return canonicalPath;
204 Qt4ProjectManager::QtVersion *QmlProjectRunConfiguration::qtVersion() const
206 if (m_qtVersionId == -1)
209 QtVersionManager *versionManager = QtVersionManager::instance();
210 Qt4ProjectManager::QtVersion *version = versionManager->version(m_qtVersionId);
211 QTC_ASSERT(version, return 0);
216 QWidget *QmlProjectRunConfiguration::createConfigurationWidget()
218 QTC_ASSERT(m_configurationWidget.isNull(), return m_configurationWidget.data());
219 m_configurationWidget = new QmlProjectRunConfigurationWidget(this);
220 return m_configurationWidget.data();
223 ProjectExplorer::OutputFormatter *QmlProjectRunConfiguration::createOutputFormatter() const
225 return new Qt4ProjectManager::QtOutputFormatter(qmlTarget()->qmlProject());
228 QmlProjectRunConfiguration::MainScriptSource QmlProjectRunConfiguration::mainScriptSource() const
230 if (m_usingCurrentFile) {
233 if (!m_mainScriptFilename.isEmpty()) {
234 return FileInSettings;
236 return FileInProjectFile;
240 Returns absolute path to main script file.
242 QString QmlProjectRunConfiguration::mainScript() const
244 if (m_usingCurrentFile) {
245 return m_currentFileFilename;
248 if (!m_mainScriptFilename.isEmpty()) {
249 return m_mainScriptFilename;
252 QString path = qmlTarget()->qmlProject()->mainFile();
253 if (QFileInfo(path).isAbsolute()) {
256 return qmlTarget()->qmlProject()->projectDir().absoluteFilePath(path);
260 void QmlProjectRunConfiguration::setScriptSource(MainScriptSource source,
261 const QString &settingsPath)
263 if (source == FileInEditor) {
264 m_scriptFile = M_CURRENT_FILE;
265 m_mainScriptFilename.clear();
266 m_usingCurrentFile = true;
267 } else if (source == FileInProjectFile) {
268 m_scriptFile.clear();
269 m_mainScriptFilename.clear();
270 m_usingCurrentFile = false;
271 } else { // FileInSettings
272 m_scriptFile = settingsPath;
274 = qmlTarget()->qmlProject()->projectDir().absoluteFilePath(m_scriptFile);
275 m_usingCurrentFile = false;
278 if (m_configurationWidget)
279 m_configurationWidget.data()->updateFileComboBox();
282 Utils::Environment QmlProjectRunConfiguration::environment() const
284 Utils::Environment env = baseEnvironment();
285 env.modify(userEnvironmentChanges());
289 ProjectExplorer::Abi QmlProjectRunConfiguration::abi() const
291 ProjectExplorer::Abi hostAbi = ProjectExplorer::Abi::hostAbi();
292 return ProjectExplorer::Abi(hostAbi.architecture(), hostAbi.os(), hostAbi.osFlavor(),
293 ProjectExplorer::Abi::RuntimeQmlFormat, hostAbi.wordWidth());
296 QVariantMap QmlProjectRunConfiguration::toMap() const
298 QVariantMap map(ProjectExplorer::RunConfiguration::toMap());
300 map.insert(QLatin1String(Constants::QML_VIEWER_QT_KEY), m_qtVersionId);
301 map.insert(QLatin1String(Constants::QML_VIEWER_ARGUMENTS_KEY), m_qmlViewerArgs);
302 map.insert(QLatin1String(Constants::QML_MAINSCRIPT_KEY), m_scriptFile);
303 map.insert(QLatin1String(Constants::USER_ENVIRONMENT_CHANGES_KEY),
304 Utils::EnvironmentItem::toStringList(m_userEnvironmentChanges));
308 bool QmlProjectRunConfiguration::fromMap(const QVariantMap &map)
310 setQtVersionId(map.value(QLatin1String(Constants::QML_VIEWER_QT_KEY), -1).toInt());
311 m_qmlViewerArgs = map.value(QLatin1String(Constants::QML_VIEWER_ARGUMENTS_KEY)).toString();
312 m_scriptFile = map.value(QLatin1String(Constants::QML_MAINSCRIPT_KEY), M_CURRENT_FILE).toString();
313 m_userEnvironmentChanges = Utils::EnvironmentItem::fromStringList(
314 map.value(QLatin1String(Constants::USER_ENVIRONMENT_CHANGES_KEY)).toStringList());
318 if (m_scriptFile == M_CURRENT_FILE) {
319 setScriptSource(FileInEditor);
320 } else if (m_scriptFile.isEmpty()) {
321 setScriptSource(FileInProjectFile);
323 setScriptSource(FileInSettings, m_scriptFile);
326 return RunConfiguration::fromMap(map);
329 void QmlProjectRunConfiguration::changeCurrentFile(Core::IEditor * /*editor*/)
334 void QmlProjectRunConfiguration::updateEnabled()
336 bool qmlFileFound = false;
337 if (m_usingCurrentFile) {
338 Core::IEditor *editor = Core::EditorManager::instance()->currentEditor();
339 Core::MimeDatabase *db = ICore::instance()->mimeDatabase();
341 m_currentFileFilename = editor->file()->fileName();
342 if (db->findByFile(mainScript()).type() == QLatin1String("application/x-qml"))
346 || db->findByFile(mainScript()).type() == QLatin1String("application/x-qmlproject")) {
347 // find a qml file with lowercase filename. This is slow, but only done
348 // in initialization/other border cases.
349 foreach(const QString &filename, m_projectTarget->qmlProject()->files()) {
350 const QFileInfo fi(filename);
352 if (!filename.isEmpty() && fi.baseName()[0].isLower()
353 && db->findByFile(fi).type() == QLatin1String("application/x-qml"))
355 m_currentFileFilename = filename;
362 } else { // use default one
363 qmlFileFound = !mainScript().isEmpty();
366 bool newValue = (QFileInfo(viewerPath()).exists()
367 || QFileInfo(observerPath()).exists()) && qmlFileFound;
370 // Always emit change signal to force reevaluation of run/debug buttons
371 m_isEnabled = newValue;
372 emit isEnabledChanged(m_isEnabled);
375 void QmlProjectRunConfiguration::updateQtVersions()
377 QtVersionManager *qtVersions = QtVersionManager::instance();
380 // update m_qtVersionId
382 if (!qtVersions->isValidId(m_qtVersionId)
383 || !isValidVersion(qtVersions->version(m_qtVersionId))) {
384 int newVersionId = -1;
385 // take first one you find
386 foreach (Qt4ProjectManager::QtVersion *version, qtVersions->validVersions()) {
387 if (isValidVersion(version)) {
388 newVersionId = version->uniqueId();
392 setQtVersionId(newVersionId);
398 bool QmlProjectRunConfiguration::isValidVersion(Qt4ProjectManager::QtVersion *version)
401 && (version->supportsTargetId(Qt4ProjectManager::Constants::DESKTOP_TARGET_ID)
402 || version->supportsTargetId(Qt4ProjectManager::Constants::QT_SIMULATOR_TARGET_ID))
403 && !version->qmlviewerCommand().isEmpty()) {
409 Utils::Environment QmlProjectRunConfiguration::baseEnvironment() const
411 Utils::Environment env;
413 env = qtVersion()->qmlToolsEnvironment();
417 void QmlProjectRunConfiguration::setUserEnvironmentChanges(const QList<Utils::EnvironmentItem> &diff)
419 if (m_userEnvironmentChanges != diff) {
420 m_userEnvironmentChanges = diff;
421 if (m_configurationWidget)
422 m_configurationWidget.data()->userEnvironmentChangesChanged();
426 QList<Utils::EnvironmentItem> QmlProjectRunConfiguration::userEnvironmentChanges() const
428 return m_userEnvironmentChanges;
431 } // namespace QmlProjectManager