OSDN Git Service

6106a975ed7dce6ebabed2b33919cc304b2279b1
[qt-creator-jp/qt-creator-jp.git] / src / plugins / qmlprojectmanager / qmlprojectrunconfiguration.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** No Commercial Usage
10 **
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
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 **
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.
24 **
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.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **************************************************************************/
33
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>
48
49 #ifdef Q_OS_WIN32
50 #include <utils/winutils.h>
51 #endif
52
53 using Core::EditorManager;
54 using Core::ICore;
55 using Core::IEditor;
56 using Qt4ProjectManager::QtVersionManager;
57
58 using namespace QmlProjectManager::Internal;
59
60 namespace QmlProjectManager {
61
62 const char * const M_CURRENT_FILE = "CurrentFile";
63
64 QmlProjectRunConfiguration::QmlProjectRunConfiguration(QmlProjectTarget *parent) :
65     ProjectExplorer::RunConfiguration(parent, QLatin1String(Constants::QML_RC_ID)),
66     m_qtVersionId(-1),
67     m_scriptFile(M_CURRENT_FILE),
68     m_projectTarget(parent),
69     m_usingCurrentFile(true),
70     m_isEnabled(false)
71 {
72     ctor();
73     updateQtVersions();
74 }
75
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)
85 {
86     ctor();
87     updateQtVersions();
88 }
89
90 bool QmlProjectRunConfiguration::isEnabled(ProjectExplorer::BuildConfiguration *bc) const
91 {
92     Q_UNUSED(bc);
93
94     return m_isEnabled;
95 }
96
97 void QmlProjectRunConfiguration::ctor()
98 {
99     // reset default settings in constructor
100     setUseCppDebugger(false);
101     setUseQmlDebugger(true);
102
103     EditorManager *em = Core::EditorManager::instance();
104     connect(em, SIGNAL(currentEditorChanged(Core::IEditor*)),
105             this, SLOT(changeCurrentFile(Core::IEditor*)));
106
107     QtVersionManager *qtVersions = QtVersionManager::instance();
108     connect(qtVersions, SIGNAL(qtVersionsChanged(QList<int>)), this, SLOT(updateQtVersions()));
109
110     setDisplayName(tr("QML Viewer", "QMLRunConfiguration display name."));
111 }
112
113 QmlProjectRunConfiguration::~QmlProjectRunConfiguration()
114 {
115 }
116
117 QmlProjectTarget *QmlProjectRunConfiguration::qmlTarget() const
118 {
119     return static_cast<QmlProjectTarget *>(target());
120 }
121
122 QString QmlProjectRunConfiguration::viewerPath() const
123 {
124     Qt4ProjectManager::QtVersion *version = qtVersion();
125     if (!version) {
126         return QString();
127     } else {
128         return version->qmlviewerCommand();
129     }
130 }
131
132 QString QmlProjectRunConfiguration::observerPath() const
133 {
134     Qt4ProjectManager::QtVersion *version = qtVersion();
135     if (!version) {
136         return QString();
137     } else {
138         return version->qmlObserverTool();
139     }
140 }
141
142 QString QmlProjectRunConfiguration::viewerArguments() const
143 {
144     // arguments in .user file
145     QString args = m_qmlViewerArgs;
146
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);
151     }
152
153     QString s = mainScript();
154     if (!s.isEmpty()) {
155         s = canonicalCapsPath(s);
156         Utils::QtcProcess::addArg(&args, s);
157     }
158     return args;
159 }
160
161 QString QmlProjectRunConfiguration::workingDirectory() const
162 {
163     QFileInfo projectFile(qmlTarget()->qmlProject()->file()->fileName());
164     return canonicalCapsPath(projectFile.absolutePath());
165 }
166
167 int QmlProjectRunConfiguration::qtVersionId() const
168 {
169     return m_qtVersionId;
170 }
171
172 void QmlProjectRunConfiguration::setQtVersionId(int id)
173 {
174     if (m_qtVersionId == id)
175         return;
176
177     m_qtVersionId = id;
178     qmlTarget()->qmlProject()->refresh(QmlProject::Configuration);
179     if (m_configurationWidget)
180         m_configurationWidget.data()->updateQtVersionComboBox();
181 }
182
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)
187 {
188     QString canonicalPath = QFileInfo(fileName).canonicalFilePath();
189
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);
194     if (!path.isEmpty())
195         path = Utils::getLongPathName(canonicalPath);
196     if (!path.isEmpty())
197         canonicalPath = path;
198 #endif
199
200     return canonicalPath;
201 }
202
203
204 Qt4ProjectManager::QtVersion *QmlProjectRunConfiguration::qtVersion() const
205 {
206     if (m_qtVersionId == -1)
207         return 0;
208
209     QtVersionManager *versionManager = QtVersionManager::instance();
210     Qt4ProjectManager::QtVersion *version = versionManager->version(m_qtVersionId);
211     QTC_ASSERT(version, return 0);
212
213     return version;
214 }
215
216 QWidget *QmlProjectRunConfiguration::createConfigurationWidget()
217 {
218     QTC_ASSERT(m_configurationWidget.isNull(), return m_configurationWidget.data());
219     m_configurationWidget = new QmlProjectRunConfigurationWidget(this);
220     return m_configurationWidget.data();
221 }
222
223 ProjectExplorer::OutputFormatter *QmlProjectRunConfiguration::createOutputFormatter() const
224 {
225     return new Qt4ProjectManager::QtOutputFormatter(qmlTarget()->qmlProject());
226 }
227
228 QmlProjectRunConfiguration::MainScriptSource QmlProjectRunConfiguration::mainScriptSource() const
229 {
230     if (m_usingCurrentFile) {
231         return FileInEditor;
232     }
233     if (!m_mainScriptFilename.isEmpty()) {
234         return FileInSettings;
235     }
236     return FileInProjectFile;
237 }
238
239 /**
240   Returns absolute path to main script file.
241   */
242 QString QmlProjectRunConfiguration::mainScript() const
243 {
244     if (m_usingCurrentFile) {
245         return m_currentFileFilename;
246     }
247
248     if (!m_mainScriptFilename.isEmpty()) {
249         return m_mainScriptFilename;
250     }
251
252     QString path = qmlTarget()->qmlProject()->mainFile();
253     if (QFileInfo(path).isAbsolute()) {
254         return path;
255     } else {
256         return qmlTarget()->qmlProject()->projectDir().absoluteFilePath(path);
257     }
258 }
259
260 void QmlProjectRunConfiguration::setScriptSource(MainScriptSource source,
261                                                  const QString &settingsPath)
262 {
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;
273         m_mainScriptFilename
274                 = qmlTarget()->qmlProject()->projectDir().absoluteFilePath(m_scriptFile);
275         m_usingCurrentFile = false;
276     }
277     updateEnabled();
278     if (m_configurationWidget)
279         m_configurationWidget.data()->updateFileComboBox();
280 }
281
282 Utils::Environment QmlProjectRunConfiguration::environment() const
283 {
284     Utils::Environment env = baseEnvironment();
285     env.modify(userEnvironmentChanges());
286     return env;
287 }
288
289 ProjectExplorer::Abi QmlProjectRunConfiguration::abi() const
290 {
291     ProjectExplorer::Abi hostAbi = ProjectExplorer::Abi::hostAbi();
292     return ProjectExplorer::Abi(hostAbi.architecture(), hostAbi.os(), hostAbi.osFlavor(),
293                                 ProjectExplorer::Abi::RuntimeQmlFormat, hostAbi.wordWidth());
294 }
295
296 QVariantMap QmlProjectRunConfiguration::toMap() const
297 {
298     QVariantMap map(ProjectExplorer::RunConfiguration::toMap());
299
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));
305     return map;
306 }
307
308 bool QmlProjectRunConfiguration::fromMap(const QVariantMap &map)
309 {
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());
315
316
317     updateQtVersions();
318     if (m_scriptFile == M_CURRENT_FILE) {
319         setScriptSource(FileInEditor);
320     } else if (m_scriptFile.isEmpty()) {
321         setScriptSource(FileInProjectFile);
322     } else {
323         setScriptSource(FileInSettings, m_scriptFile);
324     }
325
326     return RunConfiguration::fromMap(map);
327 }
328
329 void QmlProjectRunConfiguration::changeCurrentFile(Core::IEditor * /*editor*/)
330 {
331     updateEnabled();
332 }
333
334 void QmlProjectRunConfiguration::updateEnabled()
335 {
336     bool qmlFileFound = false;
337     if (m_usingCurrentFile) {
338         Core::IEditor *editor = Core::EditorManager::instance()->currentEditor();
339         Core::MimeDatabase *db = ICore::instance()->mimeDatabase();
340         if (editor) {
341             m_currentFileFilename = editor->file()->fileName();
342             if (db->findByFile(mainScript()).type() == QLatin1String("application/x-qml"))
343                 qmlFileFound = true;
344         }
345         if (!editor
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);
351
352                 if (!filename.isEmpty() && fi.baseName()[0].isLower()
353                         && db->findByFile(fi).type() == QLatin1String("application/x-qml"))
354                 {
355                     m_currentFileFilename = filename;
356                     qmlFileFound = true;
357                     break;
358                 }
359
360             }
361         }
362     } else { // use default one
363         qmlFileFound = !mainScript().isEmpty();
364     }
365
366     bool newValue = (QFileInfo(viewerPath()).exists()
367                      || QFileInfo(observerPath()).exists()) && qmlFileFound;
368
369
370     // Always emit change signal to force reevaluation of run/debug buttons
371     m_isEnabled = newValue;
372     emit isEnabledChanged(m_isEnabled);
373 }
374
375 void QmlProjectRunConfiguration::updateQtVersions()
376 {
377     QtVersionManager *qtVersions = QtVersionManager::instance();
378
379     //
380     // update m_qtVersionId
381     //
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();
389                 break;
390             }
391         }
392         setQtVersionId(newVersionId);
393     }
394
395     updateEnabled();
396 }
397
398 bool QmlProjectRunConfiguration::isValidVersion(Qt4ProjectManager::QtVersion *version)
399 {
400     if (version
401             && (version->supportsTargetId(Qt4ProjectManager::Constants::DESKTOP_TARGET_ID)
402                 || version->supportsTargetId(Qt4ProjectManager::Constants::QT_SIMULATOR_TARGET_ID))
403             && !version->qmlviewerCommand().isEmpty()) {
404         return true;
405     }
406     return false;
407 }
408
409 Utils::Environment QmlProjectRunConfiguration::baseEnvironment() const
410 {
411     Utils::Environment env;
412     if (qtVersion())
413         env = qtVersion()->qmlToolsEnvironment();
414     return env;
415 }
416
417 void QmlProjectRunConfiguration::setUserEnvironmentChanges(const QList<Utils::EnvironmentItem> &diff)
418 {
419     if (m_userEnvironmentChanges != diff) {
420         m_userEnvironmentChanges = diff;
421         if (m_configurationWidget)
422             m_configurationWidget.data()->userEnvironmentChangesChanged();
423     }
424 }
425
426 QList<Utils::EnvironmentItem> QmlProjectRunConfiguration::userEnvironmentChanges() const
427 {
428     return m_userEnvironmentChanges;
429 }
430
431 } // namespace QmlProjectManager