OSDN Git Service

Merge remote-tracking branch 'origin/2.3'
[qt-creator-jp/qt-creator-jp.git] / src / plugins / qmlprojectmanager / qmlproject.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 (info@qt.nokia.com)
8 **
9 **
10 ** GNU Lesser General Public License Usage
11 **
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 **
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 **
23 ** Other Usage
24 **
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at info@qt.nokia.com.
30 **
31 **************************************************************************/
32
33 #include "qmlproject.h"
34 #include "qmlprojectfile.h"
35 #include "qmlprojectmanagerconstants.h"
36 #include "fileformat/qmlprojectitem.h"
37 #include "qmlprojectrunconfiguration.h"
38 #include "qmlprojecttarget.h"
39 #include "qmlprojectconstants.h"
40
41 #include <coreplugin/icore.h>
42 #include <coreplugin/messagemanager.h>
43 #include <extensionsystem/pluginmanager.h>
44 #include <qtsupport/qmldumptool.h>
45 #include <qtsupport/baseqtversion.h>
46 #include <qtsupport/qtversionmanager.h>
47 #include <qmljs/qmljsmodelmanagerinterface.h>
48 #include <utils/fileutils.h>
49
50 #include <utils/filesystemwatcher.h>
51
52 #include <QtCore/QTextStream>
53 #include <QtDeclarative/QDeclarativeComponent>
54 #include <QtCore/QtDebug>
55
56 namespace QmlProjectManager {
57
58 QmlProject::QmlProject(Internal::Manager *manager, const QString &fileName)
59     : m_manager(manager),
60       m_fileName(fileName),
61       m_modelManager(ExtensionSystem::PluginManager::instance()->getObject<QmlJS::ModelManagerInterface>()),
62       m_fileWatcher(new Utils::FileSystemWatcher(this))
63 {
64     m_fileWatcher->setObjectName(QLatin1String("QmlProjectWatcher"));
65     setProjectContext(Core::Context(QmlProjectManager::Constants::PROJECTCONTEXT));
66     setProjectLanguage(Core::Context(QmlProjectManager::Constants::LANG_QML));
67
68     QFileInfo fileInfo(m_fileName);
69     m_projectName = fileInfo.completeBaseName();
70
71     m_file = new Internal::QmlProjectFile(this, fileName);
72     m_rootNode = new Internal::QmlProjectNode(this, m_file);
73
74     m_fileWatcher->addFile(fileName, Utils::FileSystemWatcher::WatchModifiedDate);
75     connect(m_fileWatcher, SIGNAL(fileChanged(QString)),
76             this, SLOT(refreshProjectFile()));
77
78     m_manager->registerProject(this);
79 }
80
81 QmlProject::~QmlProject()
82 {
83     m_manager->unregisterProject(this);
84
85     delete m_projectItem.data();
86     delete m_rootNode;
87 }
88
89 QDir QmlProject::projectDir() const
90 {
91     return QFileInfo(file()->fileName()).dir();
92 }
93
94 QString QmlProject::filesFileName() const
95 { return m_fileName; }
96
97 void QmlProject::parseProject(RefreshOptions options)
98 {
99     Core::MessageManager *messageManager = Core::ICore::instance()->messageManager();
100     if (options & Files) {
101         if (options & ProjectFile)
102             delete m_projectItem.data();
103         if (!m_projectItem) {
104             Utils::FileReader reader;
105             if (reader.fetch(m_fileName)) {
106                 QDeclarativeComponent *component = new QDeclarativeComponent(&m_engine, this);
107                 component->setData(reader.data(), QUrl::fromLocalFile(m_fileName));
108                 if (component->isReady()
109                     && qobject_cast<QmlProjectItem*>(component->create())) {
110                     m_projectItem = qobject_cast<QmlProjectItem*>(component->create());
111                     connect(m_projectItem.data(), SIGNAL(qmlFilesChanged(QSet<QString>, QSet<QString>)),
112                             this, SLOT(refreshFiles(QSet<QString>, QSet<QString>)));
113                 } else {
114                     messageManager->printToOutputPane(tr("Error while loading project file %1.").arg(m_fileName));
115                     messageManager->printToOutputPane(component->errorString(), true);
116                 }
117             } else {
118                 messageManager->printToOutputPane(tr("QML project: %1").arg(reader.errorString()), true);
119             }
120         }
121         if (m_projectItem) {
122             m_projectItem.data()->setSourceDirectory(projectDir().path());
123             m_modelManager->updateSourceFiles(m_projectItem.data()->files(), true);
124         }
125         m_rootNode->refresh();
126     }
127
128     if (options & Configuration) {
129         // update configuration
130     }
131
132     if (options & Files)
133         emit fileListChanged();
134 }
135
136 void QmlProject::refresh(RefreshOptions options)
137 {
138     parseProject(options);
139
140     if (options & Files)
141         m_rootNode->refresh();
142
143     QmlJS::ModelManagerInterface::ProjectInfo pinfo(this);
144     pinfo.sourceFiles = files();
145     pinfo.importPaths = importPaths();
146     QtSupport::BaseQtVersion *version = 0;
147     if (activeTarget()) {
148         if (QmlProjectRunConfiguration *rc = qobject_cast<QmlProjectRunConfiguration *>(activeTarget()->activeRunConfiguration()))
149             version = rc->qtVersion();
150         QtSupport::QmlDumpTool::pathAndEnvironment(this, version, false, &pinfo.qmlDumpPath, &pinfo.qmlDumpEnvironment);
151     }
152     if (version) {
153         pinfo.qtImportsPath = version->versionInfo().value("QT_INSTALL_IMPORTS");
154         pinfo.qtVersionString = version->qtVersionString();
155     }
156     m_modelManager->updateProjectInfo(pinfo);
157 }
158
159 QStringList QmlProject::convertToAbsoluteFiles(const QStringList &paths) const
160 {
161     const QDir projectDir(QFileInfo(m_fileName).dir());
162     QStringList absolutePaths;
163     foreach (const QString &file, paths) {
164         QFileInfo fileInfo(projectDir, file);
165         absolutePaths.append(fileInfo.absoluteFilePath());
166     }
167     absolutePaths.removeDuplicates();
168     return absolutePaths;
169 }
170
171 QStringList QmlProject::files() const
172 {
173     QStringList files;
174     if (m_projectItem) {
175         files = m_projectItem.data()->files();
176     } else {
177         files = m_files;
178     }
179     return files;
180 }
181
182 QString QmlProject::mainFile() const
183 {
184     if (m_projectItem)
185         return m_projectItem.data()->mainFile();
186     return QString();
187 }
188
189 bool QmlProject::validProjectFile() const
190 {
191     return !m_projectItem.isNull();
192 }
193
194 QStringList QmlProject::importPaths() const
195 {
196     QStringList importPaths;
197     if (m_projectItem)
198         importPaths = m_projectItem.data()->importPaths();
199
200     // add the default import path for the target Qt version
201     if (activeTarget()) {
202         const QmlProjectRunConfiguration *runConfig =
203                 qobject_cast<QmlProjectRunConfiguration*>(activeTarget()->activeRunConfiguration());
204         if (runConfig) {
205             const QtSupport::BaseQtVersion *qtVersion = runConfig->qtVersion();
206             if (qtVersion && qtVersion->isValid()) {
207                 const QString qtVersionImportPath = qtVersion->versionInfo().value("QT_INSTALL_IMPORTS");
208                 if (!qtVersionImportPath.isEmpty())
209                     importPaths += qtVersionImportPath;
210             }
211         }
212     }
213
214     return importPaths;
215 }
216
217 bool QmlProject::addFiles(const QStringList &filePaths)
218 {
219     QStringList toAdd;
220     foreach (const QString &filePath, filePaths) {
221         if (!m_projectItem.data()->matchesFile(filePath))
222             toAdd << filePaths;
223     }
224     return toAdd.isEmpty();
225 }
226
227 void QmlProject::refreshProjectFile()
228 {
229     refresh(QmlProject::ProjectFile | Files);
230 }
231
232 void QmlProject::refreshFiles(const QSet<QString> &/*added*/, const QSet<QString> &removed)
233 {
234     refresh(Files);
235     if (!removed.isEmpty())
236         m_modelManager->removeFiles(removed.toList());
237 }
238
239 QString QmlProject::displayName() const
240 {
241     return m_projectName;
242 }
243
244 QString QmlProject::id() const
245 {
246     return QLatin1String("QmlProjectManager.QmlProject");
247 }
248
249 Core::IFile *QmlProject::file() const
250 {
251     return m_file;
252 }
253
254 Internal::Manager *QmlProject::projectManager() const
255 {
256     return m_manager;
257 }
258
259 QList<ProjectExplorer::Project *> QmlProject::dependsOn()
260 {
261     return QList<Project *>();
262 }
263
264 QList<ProjectExplorer::BuildConfigWidget*> QmlProject::subConfigWidgets()
265 {
266     return QList<ProjectExplorer::BuildConfigWidget*>();
267 }
268
269 Internal::QmlProjectTarget *QmlProject::activeTarget() const
270 {
271     return static_cast<Internal::QmlProjectTarget *>(Project::activeTarget());
272 }
273
274 Internal::QmlProjectNode *QmlProject::rootProjectNode() const
275 {
276     return m_rootNode;
277 }
278
279 QStringList QmlProject::files(FilesMode) const
280 {
281     return files();
282 }
283
284 bool QmlProject::fromMap(const QVariantMap &map)
285 {
286     if (!Project::fromMap(map))
287         return false;
288
289     if (targets().isEmpty()) {
290         Internal::QmlProjectTargetFactory *factory
291                 = ExtensionSystem::PluginManager::instance()->getObject<Internal::QmlProjectTargetFactory>();
292         Internal::QmlProjectTarget *target = factory->create(this, QLatin1String(Constants::QML_VIEWER_TARGET_ID));
293         addTarget(target);
294     }
295
296     refresh(Everything);
297     // FIXME workaround to guarantee that run/debug actions are enabled if a valid file exists
298     if (activeTarget()) {
299         QmlProjectRunConfiguration *runConfig = qobject_cast<QmlProjectRunConfiguration*>(activeTarget()->activeRunConfiguration());
300         if (runConfig)
301             runConfig->changeCurrentFile(0);
302     }
303
304     return true;
305 }
306
307 } // namespace QmlProjectManager
308