OSDN Git Service

Merge remote-tracking branch 'origin/2.2'
[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     m_modelManager->updateProjectInfo(pinfo);
153 }
154
155 QStringList QmlProject::convertToAbsoluteFiles(const QStringList &paths) const
156 {
157     const QDir projectDir(QFileInfo(m_fileName).dir());
158     QStringList absolutePaths;
159     foreach (const QString &file, paths) {
160         QFileInfo fileInfo(projectDir, file);
161         absolutePaths.append(fileInfo.absoluteFilePath());
162     }
163     absolutePaths.removeDuplicates();
164     return absolutePaths;
165 }
166
167 QStringList QmlProject::files() const
168 {
169     QStringList files;
170     if (m_projectItem) {
171         files = m_projectItem.data()->files();
172     } else {
173         files = m_files;
174     }
175     return files;
176 }
177
178 QString QmlProject::mainFile() const
179 {
180     if (m_projectItem)
181         return m_projectItem.data()->mainFile();
182     return QString();
183 }
184
185 bool QmlProject::validProjectFile() const
186 {
187     return !m_projectItem.isNull();
188 }
189
190 QStringList QmlProject::importPaths() const
191 {
192     QStringList importPaths;
193     if (m_projectItem)
194         importPaths = m_projectItem.data()->importPaths();
195
196     // add the default import path for the target Qt version
197     if (activeTarget()) {
198         const QmlProjectRunConfiguration *runConfig =
199                 qobject_cast<QmlProjectRunConfiguration*>(activeTarget()->activeRunConfiguration());
200         if (runConfig) {
201             const QtSupport::BaseQtVersion *qtVersion = runConfig->qtVersion();
202             if (qtVersion && qtVersion->isValid()) {
203                 const QString qtVersionImportPath = qtVersion->versionInfo().value("QT_INSTALL_IMPORTS");
204                 if (!qtVersionImportPath.isEmpty())
205                     importPaths += qtVersionImportPath;
206             }
207         }
208     }
209
210     return importPaths;
211 }
212
213 bool QmlProject::addFiles(const QStringList &filePaths)
214 {
215     QStringList toAdd;
216     foreach (const QString &filePath, filePaths) {
217         if (!m_projectItem.data()->matchesFile(filePath))
218             toAdd << filePaths;
219     }
220     return toAdd.isEmpty();
221 }
222
223 void QmlProject::refreshProjectFile()
224 {
225     refresh(QmlProject::ProjectFile | Files);
226 }
227
228 void QmlProject::refreshFiles(const QSet<QString> &/*added*/, const QSet<QString> &removed)
229 {
230     refresh(Files);
231     if (!removed.isEmpty())
232         m_modelManager->removeFiles(removed.toList());
233 }
234
235 QString QmlProject::displayName() const
236 {
237     return m_projectName;
238 }
239
240 QString QmlProject::id() const
241 {
242     return QLatin1String("QmlProjectManager.QmlProject");
243 }
244
245 Core::IFile *QmlProject::file() const
246 {
247     return m_file;
248 }
249
250 Internal::Manager *QmlProject::projectManager() const
251 {
252     return m_manager;
253 }
254
255 QList<ProjectExplorer::Project *> QmlProject::dependsOn()
256 {
257     return QList<Project *>();
258 }
259
260 QList<ProjectExplorer::BuildConfigWidget*> QmlProject::subConfigWidgets()
261 {
262     return QList<ProjectExplorer::BuildConfigWidget*>();
263 }
264
265 Internal::QmlProjectTarget *QmlProject::activeTarget() const
266 {
267     return static_cast<Internal::QmlProjectTarget *>(Project::activeTarget());
268 }
269
270 Internal::QmlProjectNode *QmlProject::rootProjectNode() const
271 {
272     return m_rootNode;
273 }
274
275 QStringList QmlProject::files(FilesMode) const
276 {
277     return files();
278 }
279
280 bool QmlProject::fromMap(const QVariantMap &map)
281 {
282     if (!Project::fromMap(map))
283         return false;
284
285     if (targets().isEmpty()) {
286         Internal::QmlProjectTargetFactory *factory
287                 = ExtensionSystem::PluginManager::instance()->getObject<Internal::QmlProjectTargetFactory>();
288         Internal::QmlProjectTarget *target = factory->create(this, QLatin1String(Constants::QML_VIEWER_TARGET_ID));
289         addTarget(target);
290     }
291
292     refresh(Everything);
293     // FIXME workaround to guarantee that run/debug actions are enabled if a valid file exists
294     if (activeTarget()) {
295         QmlProjectRunConfiguration *runConfig = qobject_cast<QmlProjectRunConfiguration*>(activeTarget()->activeRunConfiguration());
296         if (runConfig)
297             runConfig->changeCurrentFile(0);
298     }
299
300     return true;
301 }
302
303 } // namespace QmlProjectManager
304