2009-02-25 09:15:00 +01:00
|
|
|
/**************************************************************************
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
|
|
|
** This file is part of Qt Creator
|
|
|
|
**
|
2011-01-11 16:28:15 +01:00
|
|
|
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2011-04-13 08:42:33 +02:00
|
|
|
** Contact: Nokia Corporation (info@qt.nokia.com)
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2009-02-25 09:15:00 +01:00
|
|
|
** GNU Lesser General Public License Usage
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2011-04-13 08:42:33 +02:00
|
|
|
** This file may be used under the terms of the GNU Lesser General Public
|
|
|
|
** License version 2.1 as published by the Free Software Foundation and
|
|
|
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
|
|
** Please review the following information to ensure the GNU Lesser General
|
|
|
|
** Public License version 2.1 requirements will be met:
|
|
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2010-12-17 16:01:08 +01:00
|
|
|
** In addition, as a special exception, Nokia gives you certain additional
|
2011-04-13 08:42:33 +02:00
|
|
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
2010-12-17 16:01:08 +01:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
**
|
2011-04-13 08:42:33 +02:00
|
|
|
** Other Usage
|
|
|
|
**
|
|
|
|
** Alternatively, this file may be used in accordance with the terms and
|
|
|
|
** conditions contained in a signed written agreement between you and Nokia.
|
|
|
|
**
|
2010-12-17 16:01:08 +01:00
|
|
|
** If you have questions regarding the use of this file, please contact
|
2011-05-06 15:05:37 +02:00
|
|
|
** Nokia at info@qt.nokia.com.
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2009-02-25 09:15:00 +01:00
|
|
|
**************************************************************************/
|
2008-12-02 16:19:05 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
#include "qt4project.h"
|
2008-12-02 16:19:05 +01:00
|
|
|
|
2010-02-08 15:50:06 +01:00
|
|
|
#include "qt4projectmanager.h"
|
2011-08-18 16:46:44 +02:00
|
|
|
#include "qt4target.h"
|
2008-12-02 12:01:29 +01:00
|
|
|
#include "makestep.h"
|
|
|
|
#include "qmakestep.h"
|
|
|
|
#include "qt4nodes.h"
|
2009-04-20 17:21:31 +02:00
|
|
|
#include "qt4projectconfigwidget.h"
|
2008-12-02 12:01:29 +01:00
|
|
|
#include "qt4projectmanagerconstants.h"
|
|
|
|
#include "projectloadwizard.h"
|
2009-11-23 12:11:48 +01:00
|
|
|
#include "qt4buildconfiguration.h"
|
2010-08-16 18:23:30 +02:00
|
|
|
#include "findqt4profiles.h"
|
2009-06-22 14:32:54 +02:00
|
|
|
|
2009-01-20 11:52:04 +01:00
|
|
|
#include <coreplugin/icore.h>
|
2011-08-18 16:46:44 +02:00
|
|
|
#include <coreplugin/ifile.h>
|
2011-04-12 12:17:19 +02:00
|
|
|
#include <coreplugin/icontext.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <coreplugin/messagemanager.h>
|
|
|
|
#include <coreplugin/coreconstants.h>
|
2010-03-10 16:55:37 +01:00
|
|
|
#include <coreplugin/progressmanager/progressmanager.h>
|
2009-01-19 12:39:20 +01:00
|
|
|
#include <extensionsystem/pluginmanager.h>
|
2010-12-03 13:49:35 +01:00
|
|
|
#include <cplusplus/ModelManagerInterface.h>
|
2010-09-21 14:28:55 +02:00
|
|
|
#include <qmljs/qmljsmodelmanagerinterface.h>
|
2010-11-01 14:14:17 +01:00
|
|
|
#include <projectexplorer/toolchain.h>
|
2011-02-28 16:50:14 +01:00
|
|
|
#include <projectexplorer/headerpath.h>
|
2011-08-18 16:46:44 +02:00
|
|
|
#include <projectexplorer/target.h>
|
2010-03-11 17:47:09 +01:00
|
|
|
#include <projectexplorer/buildenvironmentwidget.h>
|
2010-02-08 15:50:06 +01:00
|
|
|
#include <projectexplorer/customexecutablerunconfiguration.h>
|
2010-09-27 17:22:57 +02:00
|
|
|
#include <projectexplorer/projectexplorer.h>
|
2011-04-12 12:17:19 +02:00
|
|
|
#include <projectexplorer/projectexplorerconstants.h>
|
2009-09-24 16:02:02 +02:00
|
|
|
#include <utils/qtcassert.h>
|
2011-05-20 21:40:53 +02:00
|
|
|
#include <qtsupport/qmldumptool.h>
|
|
|
|
#include <qtsupport/baseqtversion.h>
|
|
|
|
#include <qtsupport/profilereader.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
#include <QtCore/QDebug>
|
2009-01-19 12:39:20 +01:00
|
|
|
#include <QtCore/QDir>
|
2011-08-18 16:46:44 +02:00
|
|
|
#include <QtCore/QFileSystemWatcher>
|
2009-01-19 12:39:20 +01:00
|
|
|
#include <QtGui/QFileDialog>
|
2009-09-24 16:02:02 +02:00
|
|
|
#include <QtGui/QInputDialog>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
using namespace Qt4ProjectManager;
|
|
|
|
using namespace Qt4ProjectManager::Internal;
|
|
|
|
using namespace ProjectExplorer;
|
|
|
|
|
2011-09-19 09:15:52 +02:00
|
|
|
enum { debug = 0 };
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
namespace Qt4ProjectManager {
|
|
|
|
namespace Internal {
|
|
|
|
|
2011-08-18 16:46:44 +02:00
|
|
|
class Qt4ProjectFile : public Core::IFile
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
public:
|
|
|
|
Qt4ProjectFile(Qt4Project *project, const QString &filePath, QObject *parent = 0);
|
|
|
|
|
|
|
|
bool save(QString *errorString, const QString &fileName, bool autoSave);
|
|
|
|
QString fileName() const;
|
|
|
|
virtual void rename(const QString &newName);
|
|
|
|
|
|
|
|
QString defaultPath() const;
|
|
|
|
QString suggestedFileName() const;
|
|
|
|
virtual QString mimeType() const;
|
|
|
|
|
|
|
|
bool isModified() const;
|
|
|
|
bool isReadOnly() const;
|
|
|
|
bool isSaveAsAllowed() const;
|
|
|
|
|
|
|
|
ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const;
|
|
|
|
bool reload(QString *errorString, ReloadFlag flag, ChangeType type);
|
|
|
|
|
|
|
|
private:
|
|
|
|
const QString m_mimeType;
|
|
|
|
Qt4Project *m_project;
|
|
|
|
QString m_filePath;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Watches folders for Qt4PriFile nodes
|
|
|
|
/// use one file system watcher to watch all folders
|
|
|
|
/// such minimizing system ressouce usage
|
|
|
|
|
|
|
|
class CentralizedFolderWatcher : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
CentralizedFolderWatcher(QObject *parent);
|
|
|
|
~CentralizedFolderWatcher();
|
|
|
|
void watchFolders(const QList<QString> &folders, Qt4PriFileNode *node);
|
|
|
|
void unwatchFolders(const QList<QString> &folders, Qt4PriFileNode *node);
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
void folderChanged(const QString &folder);
|
|
|
|
void onTimer();
|
|
|
|
void delayedFolderChanged(const QString &folder);
|
|
|
|
|
|
|
|
private:
|
|
|
|
QSet<QString> recursiveDirs(const QString &folder);
|
|
|
|
QFileSystemWatcher m_watcher;
|
|
|
|
QMultiMap<QString, Qt4PriFileNode *> m_map;
|
|
|
|
|
|
|
|
QSet<QString> m_recursiveWatchedFolders;
|
|
|
|
QTimer m_compressTimer;
|
|
|
|
QSet<QString> m_changedFolders;
|
|
|
|
};
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
// Qt4ProjectFiles: Struct for (Cached) lists of files in a project
|
|
|
|
struct Qt4ProjectFiles {
|
|
|
|
void clear();
|
|
|
|
bool equals(const Qt4ProjectFiles &f) const;
|
|
|
|
|
|
|
|
QStringList files[ProjectExplorer::FileTypeSize];
|
|
|
|
QStringList generatedFiles[ProjectExplorer::FileTypeSize];
|
|
|
|
QStringList proFiles;
|
|
|
|
};
|
|
|
|
|
|
|
|
void Qt4ProjectFiles::clear()
|
|
|
|
{
|
|
|
|
for (int i = 0; i < FileTypeSize; ++i) {
|
|
|
|
files[i].clear();
|
|
|
|
generatedFiles[i].clear();
|
|
|
|
}
|
|
|
|
proFiles.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Qt4ProjectFiles::equals(const Qt4ProjectFiles &f) const
|
|
|
|
{
|
|
|
|
for (int i = 0; i < FileTypeSize; ++i)
|
|
|
|
if (files[i] != f.files[i] || generatedFiles[i] != f.generatedFiles[i])
|
|
|
|
return false;
|
|
|
|
if (proFiles != f.proFiles)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool operator==(const Qt4ProjectFiles &f1, const Qt4ProjectFiles &f2)
|
|
|
|
{ return f1.equals(f2); }
|
|
|
|
|
|
|
|
inline bool operator!=(const Qt4ProjectFiles &f1, const Qt4ProjectFiles &f2)
|
|
|
|
{ return !f1.equals(f2); }
|
|
|
|
|
|
|
|
QDebug operator<<(QDebug d, const Qt4ProjectFiles &f)
|
|
|
|
{
|
|
|
|
QDebug nsp = d.nospace();
|
|
|
|
nsp << "Qt4ProjectFiles: proFiles=" << f.proFiles << '\n';
|
|
|
|
for (int i = 0; i < FileTypeSize; ++i)
|
|
|
|
nsp << "Type " << i << " files=" << f.files[i] << " generated=" << f.generatedFiles[i] << '\n';
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
// A visitor to collect all files of a project in a Qt4ProjectFiles struct
|
|
|
|
class ProjectFilesVisitor : public ProjectExplorer::NodesVisitor
|
|
|
|
{
|
|
|
|
ProjectFilesVisitor(Qt4ProjectFiles *files);
|
2011-07-13 18:02:35 +02:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
public:
|
|
|
|
|
|
|
|
static void findProjectFiles(Qt4ProFileNode *rootNode, Qt4ProjectFiles *files);
|
|
|
|
|
|
|
|
void visitProjectNode(ProjectNode *projectNode);
|
|
|
|
void visitFolderNode(FolderNode *folderNode);
|
|
|
|
|
|
|
|
private:
|
|
|
|
Qt4ProjectFiles *m_files;
|
|
|
|
};
|
|
|
|
|
|
|
|
ProjectFilesVisitor::ProjectFilesVisitor(Qt4ProjectFiles *files) :
|
|
|
|
m_files(files)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProjectFilesVisitor::findProjectFiles(Qt4ProFileNode *rootNode, Qt4ProjectFiles *files)
|
|
|
|
{
|
|
|
|
files->clear();
|
|
|
|
ProjectFilesVisitor visitor(files);
|
|
|
|
rootNode->accept(&visitor);
|
|
|
|
for (int i = 0; i < FileTypeSize; ++i) {
|
|
|
|
qSort(files->files[i]);
|
|
|
|
qSort(files->generatedFiles[i]);
|
|
|
|
}
|
|
|
|
qSort(files->proFiles);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProjectFilesVisitor::visitProjectNode(ProjectNode *projectNode)
|
|
|
|
{
|
|
|
|
const QString path = projectNode->path();
|
|
|
|
if (!m_files->proFiles.contains(path))
|
|
|
|
m_files->proFiles.append(path);
|
|
|
|
visitFolderNode(projectNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProjectFilesVisitor::visitFolderNode(FolderNode *folderNode)
|
|
|
|
{
|
|
|
|
foreach (FileNode *fileNode, folderNode->fileNodes()) {
|
|
|
|
const QString path = fileNode->path();
|
|
|
|
const int type = fileNode->fileType();
|
|
|
|
QStringList &targetList = fileNode->isGenerated() ? m_files->generatedFiles[type] : m_files->files[type];
|
|
|
|
if (!targetList.contains(path))
|
|
|
|
targetList.push_back(path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// ----------- Qt4ProjectFile
|
2011-08-18 16:55:45 +02:00
|
|
|
namespace Internal {
|
2008-12-02 12:01:29 +01:00
|
|
|
Qt4ProjectFile::Qt4ProjectFile(Qt4Project *project, const QString &filePath, QObject *parent)
|
|
|
|
: Core::IFile(parent),
|
|
|
|
m_mimeType(QLatin1String(Qt4ProjectManager::Constants::PROFILE_MIMETYPE)),
|
|
|
|
m_project(project),
|
|
|
|
m_filePath(filePath)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2011-05-10 20:43:03 +02:00
|
|
|
bool Qt4ProjectFile::save(QString *, const QString &, bool)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2008-12-05 14:29:18 +01:00
|
|
|
// This is never used
|
|
|
|
return false;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
2010-05-11 14:13:38 +02:00
|
|
|
void Qt4ProjectFile::rename(const QString &newName)
|
|
|
|
{
|
|
|
|
// Can't happen
|
|
|
|
Q_UNUSED(newName);
|
|
|
|
Q_ASSERT(false);
|
|
|
|
}
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
QString Qt4ProjectFile::fileName() const
|
|
|
|
{
|
|
|
|
return m_filePath;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Qt4ProjectFile::defaultPath() const
|
|
|
|
{
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Qt4ProjectFile::suggestedFileName() const
|
|
|
|
{
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Qt4ProjectFile::mimeType() const
|
|
|
|
{
|
|
|
|
return m_mimeType;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Qt4ProjectFile::isModified() const
|
|
|
|
{
|
2008-12-05 14:29:18 +01:00
|
|
|
return false; // we save after changing anyway
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Qt4ProjectFile::isReadOnly() const
|
|
|
|
{
|
2008-12-02 18:14:06 +01:00
|
|
|
QFileInfo fi(m_filePath);
|
|
|
|
return !fi.isWritable();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Qt4ProjectFile::isSaveAsAllowed() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-03-19 10:28:05 +01:00
|
|
|
Core::IFile::ReloadBehavior Qt4ProjectFile::reloadBehavior(ChangeTrigger state, ChangeType type) const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2010-03-19 10:28:05 +01:00
|
|
|
Q_UNUSED(state)
|
|
|
|
Q_UNUSED(type)
|
|
|
|
return BehaviorSilent;
|
|
|
|
}
|
|
|
|
|
2011-04-04 15:24:13 +02:00
|
|
|
bool Qt4ProjectFile::reload(QString *errorString, ReloadFlag flag, ChangeType type)
|
2010-03-19 10:28:05 +01:00
|
|
|
{
|
2011-04-04 15:24:13 +02:00
|
|
|
Q_UNUSED(errorString)
|
2010-03-19 10:28:05 +01:00
|
|
|
Q_UNUSED(flag)
|
|
|
|
Q_UNUSED(type)
|
2011-04-04 15:24:13 +02:00
|
|
|
return true;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
2011-08-18 16:46:44 +02:00
|
|
|
} // namespace Internal
|
2008-12-02 12:01:29 +01:00
|
|
|
/*!
|
2009-07-14 15:25:30 +02:00
|
|
|
\class Qt4Project
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
Qt4Project manages information about an individual Qt 4 (.pro) project file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Qt4Project::Qt4Project(Qt4Manager *manager, const QString& fileName) :
|
|
|
|
m_manager(manager),
|
2009-03-12 15:01:01 +01:00
|
|
|
m_rootProjectNode(0),
|
2008-12-02 12:01:29 +01:00
|
|
|
m_nodesWatcher(new Internal::Qt4NodesWatcher(this)),
|
|
|
|
m_fileInfo(new Qt4ProjectFile(this, fileName, this)),
|
2009-12-03 18:37:27 +01:00
|
|
|
m_projectFiles(new Qt4ProjectFiles),
|
2010-03-10 16:55:37 +01:00
|
|
|
m_proFileOption(0),
|
|
|
|
m_asyncUpdateFutureInterface(0),
|
|
|
|
m_pendingEvaluateFuturesCount(0),
|
|
|
|
m_asyncUpdateState(NoState),
|
2011-05-30 13:11:31 +02:00
|
|
|
m_cancelEvaluate(false),
|
2011-08-18 16:46:44 +02:00
|
|
|
m_codeModelCanceled(false),
|
|
|
|
m_centralizedFolderWatcher(0)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2011-04-12 12:17:19 +02:00
|
|
|
setProjectContext(Core::Context(Qt4ProjectManager::Constants::PROJECT_ID));
|
|
|
|
setProjectLanguage(Core::Context(ProjectExplorer::Constants::LANG_CXX));
|
|
|
|
|
2010-03-10 16:55:37 +01:00
|
|
|
m_asyncUpdateTimer.setSingleShot(true);
|
|
|
|
m_asyncUpdateTimer.setInterval(3000);
|
|
|
|
connect(&m_asyncUpdateTimer, SIGNAL(timeout()), this, SLOT(asyncUpdate()));
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Qt4Project::~Qt4Project()
|
|
|
|
{
|
2010-04-22 18:57:43 +02:00
|
|
|
m_codeModelFuture.cancel();
|
2010-03-11 17:01:06 +01:00
|
|
|
m_asyncUpdateState = ShuttingDown;
|
2008-12-02 18:14:06 +01:00
|
|
|
m_manager->unregisterProject(this);
|
2008-12-02 12:01:29 +01:00
|
|
|
delete m_projectFiles;
|
2010-03-11 17:01:06 +01:00
|
|
|
m_cancelEvaluate = true;
|
|
|
|
delete m_rootProjectNode;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Qt4Project::updateFileList()
|
|
|
|
{
|
|
|
|
Qt4ProjectFiles newFiles;
|
|
|
|
ProjectFilesVisitor::findProjectFiles(m_rootProjectNode, &newFiles);
|
|
|
|
if (newFiles != *m_projectFiles) {
|
|
|
|
*m_projectFiles = newFiles;
|
|
|
|
emit fileListChanged();
|
|
|
|
if (debug)
|
|
|
|
qDebug() << Q_FUNC_INFO << *m_projectFiles;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-19 16:33:44 +01:00
|
|
|
bool Qt4Project::fromMap(const QVariantMap &map)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2010-01-19 16:33:44 +01:00
|
|
|
if (!Project::fromMap(map))
|
|
|
|
return false;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-02-08 15:50:06 +01:00
|
|
|
// Prune targets without buildconfigurations:
|
|
|
|
// This can happen esp. when updating from a old version of Qt Creator
|
2010-12-06 16:24:29 +01:00
|
|
|
QList<Target *>ts = targets();
|
2010-02-08 15:50:06 +01:00
|
|
|
foreach (Target *t, ts) {
|
2010-02-18 18:37:11 +01:00
|
|
|
if (t->buildConfigurations().isEmpty()) {
|
|
|
|
qWarning() << "Removing" << t->id() << "since it has no buildconfigurations!";
|
2010-02-08 15:50:06 +01:00
|
|
|
removeTarget(t);
|
2010-02-18 18:37:11 +01:00
|
|
|
}
|
2010-02-08 15:50:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add buildconfigurations so we can parse the pro-files.
|
|
|
|
if (targets().isEmpty())
|
2009-10-15 19:06:51 +02:00
|
|
|
addDefaultBuild();
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-02-19 11:07:15 +01:00
|
|
|
if (targets().isEmpty()) {
|
|
|
|
qWarning() << "Unable to create targets!";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-02-08 15:50:06 +01:00
|
|
|
Q_ASSERT(activeTarget());
|
|
|
|
Q_ASSERT(activeTarget()->activeBuildConfiguration());
|
2009-10-06 17:16:18 +02:00
|
|
|
|
2010-03-10 16:55:37 +01:00
|
|
|
m_manager->registerProject(this);
|
|
|
|
|
|
|
|
m_rootProjectNode = new Qt4ProFileNode(this, m_fileInfo->fileName(), this);
|
|
|
|
m_rootProjectNode->registerWatcher(m_nodesWatcher);
|
|
|
|
|
2010-02-08 15:50:06 +01:00
|
|
|
update();
|
|
|
|
updateFileList();
|
2011-09-15 12:15:10 +02:00
|
|
|
// This might be incorrect, need a full update
|
|
|
|
updateCodeModels();
|
2010-06-10 14:48:59 +02:00
|
|
|
|
2010-12-10 19:02:19 +01:00
|
|
|
foreach (Target *t, targets())
|
|
|
|
static_cast<Qt4BaseTarget *>(t)->createApplicationProFiles();
|
2009-03-12 15:01:01 +01:00
|
|
|
|
2010-03-10 16:55:37 +01:00
|
|
|
foreach (Target *t, targets())
|
|
|
|
onAddedTarget(t);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-06-10 15:37:10 +02:00
|
|
|
connect(m_nodesWatcher, SIGNAL(proFileUpdated(Qt4ProjectManager::Qt4ProFileNode*,bool,bool)),
|
|
|
|
this, SIGNAL(proFileUpdated(Qt4ProjectManager::Qt4ProFileNode *,bool,bool)));
|
2009-12-03 18:37:27 +01:00
|
|
|
|
2010-11-02 16:39:45 +01:00
|
|
|
// Now we emit update once :)
|
2011-09-12 12:40:53 +02:00
|
|
|
m_rootProjectNode->emitProFileUpdatedRecursive();
|
2010-11-02 16:39:45 +01:00
|
|
|
|
|
|
|
|
|
|
|
// Setup Qt versions supported (== possible targets).
|
|
|
|
connect(this, SIGNAL(addedTarget(ProjectExplorer::Target*)),
|
|
|
|
this, SLOT(onAddedTarget(ProjectExplorer::Target*)));
|
|
|
|
|
2010-02-08 15:50:06 +01:00
|
|
|
connect(this, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
|
|
|
|
this, SLOT(activeTargetWasChanged()));
|
|
|
|
|
2011-03-18 16:36:25 +01:00
|
|
|
emit fromMapFinished();
|
|
|
|
|
2009-07-03 16:46:01 +02:00
|
|
|
return true;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
2010-12-10 19:02:19 +01:00
|
|
|
Qt4BaseTarget *Qt4Project::activeTarget() const
|
2009-10-09 18:14:12 +02:00
|
|
|
{
|
2010-12-10 19:02:19 +01:00
|
|
|
return static_cast<Qt4BaseTarget *>(Project::activeTarget());
|
2009-10-09 18:14:12 +02:00
|
|
|
}
|
|
|
|
|
2010-02-08 15:50:06 +01:00
|
|
|
void Qt4Project::onAddedTarget(ProjectExplorer::Target *t)
|
|
|
|
{
|
|
|
|
Q_ASSERT(t);
|
2010-12-10 19:02:19 +01:00
|
|
|
Qt4BaseTarget *qt4target = qobject_cast<Qt4BaseTarget *>(t);
|
2010-02-15 17:33:56 +01:00
|
|
|
Q_ASSERT(qt4target);
|
|
|
|
connect(qt4target, SIGNAL(buildDirectoryInitialized()),
|
|
|
|
this, SIGNAL(buildDirectoryInitialized()));
|
2010-12-10 19:02:19 +01:00
|
|
|
connect(qt4target, SIGNAL(proFileEvaluateNeeded(Qt4ProjectManager::Qt4BaseTarget*)),
|
|
|
|
this, SLOT(proFileEvaluateNeeded(Qt4ProjectManager::Qt4BaseTarget*)));
|
2010-03-10 16:55:37 +01:00
|
|
|
}
|
|
|
|
|
2010-12-10 19:02:19 +01:00
|
|
|
void Qt4Project::proFileEvaluateNeeded(Qt4ProjectManager::Qt4BaseTarget *target)
|
2010-03-10 16:55:37 +01:00
|
|
|
{
|
|
|
|
if (activeTarget() == target)
|
|
|
|
scheduleAsyncUpdate();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// equalFileList compares two file lists ignoring
|
|
|
|
/// <configuration> without generating temporary lists
|
|
|
|
|
|
|
|
bool Qt4Project::equalFileList(const QStringList &a, const QStringList &b)
|
|
|
|
{
|
|
|
|
if (abs(a.length() - b.length()) > 1)
|
|
|
|
return false;
|
|
|
|
QStringList::const_iterator ait = a.constBegin();
|
|
|
|
QStringList::const_iterator bit = b.constBegin();
|
|
|
|
QStringList::const_iterator aend = a.constEnd();
|
|
|
|
QStringList::const_iterator bend = b.constEnd();
|
|
|
|
|
|
|
|
while (ait != aend && bit != bend) {
|
|
|
|
if (*ait == QLatin1String("<configuration>"))
|
|
|
|
++ait;
|
|
|
|
else if (*bit == QLatin1String("<configuration>"))
|
|
|
|
++bit;
|
|
|
|
else if (*ait == *bit)
|
|
|
|
++ait, ++bit;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return (ait == aend && bit == bend);
|
2010-02-08 15:50:06 +01:00
|
|
|
}
|
|
|
|
|
2010-09-21 14:28:55 +02:00
|
|
|
void Qt4Project::updateCodeModels()
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
|
|
|
if (debug)
|
|
|
|
qDebug()<<"Qt4Project::updateCodeModel()";
|
|
|
|
|
2010-02-08 15:50:06 +01:00
|
|
|
if (!activeTarget() || !activeTarget()->activeBuildConfiguration())
|
|
|
|
return;
|
|
|
|
|
2010-09-21 14:28:55 +02:00
|
|
|
updateCppCodeModel();
|
|
|
|
updateQmlJSCodeModel();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Qt4Project::updateCppCodeModel()
|
|
|
|
{
|
2011-08-18 16:46:44 +02:00
|
|
|
Qt4BuildConfiguration *activeBC = activeTarget()->activeQt4BuildConfiguration();
|
2009-11-25 18:50:20 +01:00
|
|
|
|
2010-12-03 13:49:35 +01:00
|
|
|
CPlusPlus::CppModelManagerInterface *modelmanager =
|
2011-01-04 18:50:18 +01:00
|
|
|
CPlusPlus::CppModelManagerInterface::instance();
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2009-01-20 15:31:33 +01:00
|
|
|
if (!modelmanager)
|
2008-12-02 12:01:29 +01:00
|
|
|
return;
|
|
|
|
|
2010-01-12 12:15:06 +01:00
|
|
|
// Collect global headers/defines
|
2009-05-04 18:22:40 +02:00
|
|
|
QStringList predefinedIncludePaths;
|
|
|
|
QStringList predefinedFrameworkPaths;
|
|
|
|
QByteArray predefinedMacros;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-05-04 13:14:46 +02:00
|
|
|
QString qtFrameworkPath;
|
|
|
|
if (activeBC->qtVersion())
|
|
|
|
qtFrameworkPath = activeBC->qtVersion()->frameworkInstallPath();
|
2010-10-18 17:12:44 +02:00
|
|
|
if (!qtFrameworkPath.isEmpty())
|
|
|
|
predefinedFrameworkPaths.append(qtFrameworkPath);
|
|
|
|
|
2009-11-26 14:43:27 +01:00
|
|
|
ToolChain *tc = activeBC->toolChain();
|
2009-02-12 12:39:19 +01:00
|
|
|
if (tc) {
|
|
|
|
predefinedMacros = tc->predefinedMacros();
|
2011-02-01 18:36:00 +01:00
|
|
|
|
|
|
|
QList<HeaderPath> headers = tc->systemHeaderPaths();
|
2011-05-12 12:25:25 +02:00
|
|
|
if (activeBC->qtVersion())
|
2011-05-04 13:14:46 +02:00
|
|
|
headers.append(activeBC->qtVersion()->systemHeaderPathes());
|
2011-02-01 18:36:00 +01:00
|
|
|
foreach (const HeaderPath &headerPath, headers) {
|
2010-03-10 16:55:37 +01:00
|
|
|
if (headerPath.kind() == HeaderPath::FrameworkHeaderPath)
|
|
|
|
predefinedFrameworkPaths.append(headerPath.path());
|
|
|
|
else
|
|
|
|
predefinedIncludePaths.append(headerPath.path());
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
2009-05-05 10:17:32 +02:00
|
|
|
FindQt4ProFiles findQt4ProFiles;
|
|
|
|
QList<Qt4ProFileNode *> proFiles = findQt4ProFiles(rootProjectNode());
|
2010-03-10 16:55:37 +01:00
|
|
|
QByteArray allDefinedMacros = predefinedMacros;
|
|
|
|
QStringList allIncludePaths;
|
2009-05-05 10:17:32 +02:00
|
|
|
QStringList allFrameworkPaths = predefinedFrameworkPaths;
|
2010-01-12 13:13:22 +01:00
|
|
|
QStringList allPrecompileHeaders;
|
2009-05-05 10:17:32 +02:00
|
|
|
|
2010-01-12 12:15:06 +01:00
|
|
|
// Collect per .pro file information
|
2008-12-02 12:01:29 +01:00
|
|
|
foreach (Qt4ProFileNode *pro, proFiles) {
|
2011-02-22 20:17:41 +01:00
|
|
|
allPrecompileHeaders.append(pro->variableValue(PrecompiledHeaderVar));
|
2010-01-12 13:13:22 +01:00
|
|
|
|
2009-05-04 18:22:40 +02:00
|
|
|
// Add custom defines
|
2010-03-10 16:55:37 +01:00
|
|
|
|
2010-02-01 14:00:07 +01:00
|
|
|
foreach (const QString &def, pro->variableValue(DefinesVar)) {
|
2010-03-10 16:55:37 +01:00
|
|
|
allDefinedMacros += "#define ";
|
2008-12-02 12:01:29 +01:00
|
|
|
const int index = def.indexOf(QLatin1Char('='));
|
|
|
|
if (index == -1) {
|
2010-03-10 16:55:37 +01:00
|
|
|
allDefinedMacros += def.toLatin1();
|
|
|
|
allDefinedMacros += " 1\n";
|
2008-12-02 12:01:29 +01:00
|
|
|
} else {
|
|
|
|
const QString name = def.left(index);
|
|
|
|
const QString value = def.mid(index + 1);
|
2010-03-10 16:55:37 +01:00
|
|
|
allDefinedMacros += name.toLatin1();
|
|
|
|
allDefinedMacros += ' ';
|
|
|
|
allDefinedMacros += value.toLocal8Bit();
|
|
|
|
allDefinedMacros += '\n';
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const QStringList proIncludePaths = pro->variableValue(IncludePathVar);
|
2009-05-13 18:09:47 +02:00
|
|
|
foreach (const QString &includePath, proIncludePaths) {
|
2009-05-04 18:22:40 +02:00
|
|
|
if (!allIncludePaths.contains(includePath))
|
2009-11-04 12:51:02 +01:00
|
|
|
allIncludePaths.append(includePath);
|
2009-05-04 18:22:40 +02:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
2008-12-08 12:44:28 +01:00
|
|
|
// Add mkspec directory
|
2011-05-04 13:14:46 +02:00
|
|
|
if (activeBC->qtVersion())
|
|
|
|
allIncludePaths.append(activeBC->qtVersion()->mkspecPath());
|
2008-12-08 12:44:28 +01:00
|
|
|
|
2010-03-10 16:55:37 +01:00
|
|
|
allIncludePaths.append(predefinedIncludePaths);
|
2009-05-04 18:22:40 +02:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
QStringList files;
|
|
|
|
files += m_projectFiles->files[HeaderType];
|
|
|
|
files += m_projectFiles->generatedFiles[HeaderType];
|
|
|
|
files += m_projectFiles->files[SourceType];
|
|
|
|
files += m_projectFiles->generatedFiles[SourceType];
|
|
|
|
|
2010-12-03 13:49:35 +01:00
|
|
|
CPlusPlus::CppModelManagerInterface::ProjectInfo pinfo = modelmanager->projectInfo(this);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-01-12 13:13:22 +01:00
|
|
|
//qDebug()<<"Using precompiled header"<<allPrecompileHeaders;
|
|
|
|
|
2010-03-10 16:55:37 +01:00
|
|
|
bool fileList = equalFileList(pinfo.sourceFiles, files);
|
|
|
|
|
|
|
|
if (pinfo.defines == allDefinedMacros
|
2010-01-12 13:13:22 +01:00
|
|
|
&& pinfo.includePaths == allIncludePaths
|
|
|
|
&& pinfo.frameworkPaths == allFrameworkPaths
|
2010-03-10 16:55:37 +01:00
|
|
|
&& fileList
|
2011-05-30 13:11:31 +02:00
|
|
|
&& pinfo.precompiledHeaders == allPrecompileHeaders
|
|
|
|
&& !m_codeModelCanceled) {
|
2009-10-26 15:31:43 +01:00
|
|
|
// Nothing to update...
|
2008-12-02 12:01:29 +01:00
|
|
|
} else {
|
2010-03-10 16:55:37 +01:00
|
|
|
pinfo.sourceFiles.clear();
|
|
|
|
if (pinfo.defines != allDefinedMacros
|
|
|
|
|| pinfo.includePaths != allIncludePaths
|
|
|
|
|| pinfo.frameworkPaths != allFrameworkPaths
|
|
|
|
|| pinfo.precompiledHeaders != allPrecompileHeaders)
|
|
|
|
{
|
2009-05-04 18:22:40 +02:00
|
|
|
pinfo.sourceFiles.append(QLatin1String("<configuration>"));
|
|
|
|
}
|
|
|
|
|
2010-03-10 16:55:37 +01:00
|
|
|
//pinfo.defines = predefinedMacros;
|
|
|
|
pinfo.defines = allDefinedMacros;
|
2008-12-08 10:44:56 +01:00
|
|
|
pinfo.includePaths = allIncludePaths;
|
|
|
|
pinfo.frameworkPaths = allFrameworkPaths;
|
2010-03-10 16:55:37 +01:00
|
|
|
pinfo.sourceFiles += files;
|
2010-01-12 13:13:22 +01:00
|
|
|
pinfo.precompiledHeaders = allPrecompileHeaders;
|
2008-12-08 10:44:56 +01:00
|
|
|
|
|
|
|
modelmanager->updateProjectInfo(pinfo);
|
2010-03-02 12:51:47 +01:00
|
|
|
m_codeModelFuture = modelmanager->updateSourceFiles(pinfo.sourceFiles);
|
2011-05-30 13:11:31 +02:00
|
|
|
m_codeModelCanceled = false;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2009-05-04 18:22:40 +02:00
|
|
|
}
|
|
|
|
|
2010-09-21 14:28:55 +02:00
|
|
|
void Qt4Project::updateQmlJSCodeModel()
|
|
|
|
{
|
2010-09-27 11:16:43 +01:00
|
|
|
QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance();
|
2010-09-21 14:28:55 +02:00
|
|
|
if (!modelManager)
|
|
|
|
return;
|
|
|
|
|
2010-09-27 11:16:43 +01:00
|
|
|
QmlJS::ModelManagerInterface::ProjectInfo projectInfo = modelManager->projectInfo(this);
|
2010-11-09 14:29:43 +01:00
|
|
|
projectInfo.sourceFiles = m_projectFiles->files[QMLType];
|
2010-09-21 14:28:55 +02:00
|
|
|
|
|
|
|
FindQt4ProFiles findQt4ProFiles;
|
|
|
|
QList<Qt4ProFileNode *> proFiles = findQt4ProFiles(rootProjectNode());
|
|
|
|
|
2011-06-23 15:09:38 +02:00
|
|
|
projectInfo.importPaths.clear();
|
2010-09-21 14:28:55 +02:00
|
|
|
foreach (Qt4ProFileNode *node, proFiles) {
|
|
|
|
projectInfo.importPaths.append(node->variableValue(QmlImportPathVar));
|
|
|
|
}
|
2011-01-24 13:16:27 +01:00
|
|
|
bool preferDebugDump = false;
|
2010-10-13 13:05:36 +02:00
|
|
|
if (activeTarget() && activeTarget()->activeBuildConfiguration()) {
|
2011-08-18 16:46:44 +02:00
|
|
|
preferDebugDump = activeTarget()->activeQt4BuildConfiguration()->qmakeBuildConfiguration() & QtSupport::BaseQtVersion::DebugBuild;
|
|
|
|
QtSupport::BaseQtVersion *qtVersion = activeTarget()->activeQt4BuildConfiguration()->qtVersion();
|
2011-05-04 13:14:46 +02:00
|
|
|
if (qtVersion && qtVersion->isValid()) {
|
2011-06-28 12:01:56 +02:00
|
|
|
projectInfo.qtImportsPath = qtVersion->versionInfo().value("QT_INSTALL_IMPORTS");
|
|
|
|
if (!projectInfo.qtImportsPath.isEmpty())
|
|
|
|
projectInfo.importPaths += projectInfo.qtImportsPath;
|
|
|
|
projectInfo.qtVersionString = qtVersion->qtVersionString();
|
2010-10-13 13:05:36 +02:00
|
|
|
}
|
2011-08-18 16:46:44 +02:00
|
|
|
|
2010-10-13 13:05:36 +02:00
|
|
|
}
|
2011-08-18 16:46:44 +02:00
|
|
|
const Qt4BuildConfiguration *bc = activeTarget()->activeQt4BuildConfiguration();
|
|
|
|
QtSupport::QmlDumpTool::pathAndEnvironment(this, bc->qtVersion(), bc->toolChain(),
|
2011-05-20 21:40:53 +02:00
|
|
|
preferDebugDump, &projectInfo.qmlDumpPath, &projectInfo.qmlDumpEnvironment);
|
2010-09-21 14:28:55 +02:00
|
|
|
projectInfo.importPaths.removeDuplicates();
|
|
|
|
|
2010-09-27 11:16:43 +01:00
|
|
|
modelManager->updateProjectInfo(projectInfo);
|
2010-09-21 14:28:55 +02:00
|
|
|
}
|
|
|
|
|
2008-12-09 17:17:12 +01:00
|
|
|
///*!
|
|
|
|
// Updates complete project
|
|
|
|
// */
|
2008-12-02 12:01:29 +01:00
|
|
|
void Qt4Project::update()
|
|
|
|
{
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<"Doing sync update";
|
2008-12-02 12:01:29 +01:00
|
|
|
m_rootProjectNode->update();
|
2010-10-27 16:27:22 +02:00
|
|
|
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<"State is now Base";
|
2010-03-10 16:55:37 +01:00
|
|
|
m_asyncUpdateState = Base;
|
2011-08-18 16:46:44 +02:00
|
|
|
activeTarget()->activeQt4BuildConfiguration()->setEnabled(true);
|
2011-09-12 13:25:12 +02:00
|
|
|
emit proParsingDone();
|
2010-03-10 16:55:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Qt4Project::scheduleAsyncUpdate(Qt4ProFileNode *node)
|
|
|
|
{
|
2010-10-25 17:26:41 +02:00
|
|
|
if (m_asyncUpdateState == ShuttingDown)
|
|
|
|
return;
|
2010-10-27 16:27:22 +02:00
|
|
|
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
2011-09-12 12:40:53 +02:00
|
|
|
qDebug()<<"schduleAsyncUpdate (node)"<<node->path();
|
2010-03-10 16:55:37 +01:00
|
|
|
Q_ASSERT(m_asyncUpdateState != NoState);
|
|
|
|
|
|
|
|
if (m_cancelEvaluate) {
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" Already canceling, nothing to do";
|
2010-03-10 16:55:37 +01:00
|
|
|
// A cancel is in progress
|
|
|
|
// That implies that a full update is going to happen afterwards
|
|
|
|
// So we don't need to do anything
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-08-18 16:46:44 +02:00
|
|
|
activeTarget()->activeQt4BuildConfiguration()->setEnabled(false);
|
2011-01-19 15:46:01 +01:00
|
|
|
|
2010-03-10 16:55:37 +01:00
|
|
|
if (m_asyncUpdateState == AsyncFullUpdatePending) {
|
|
|
|
// Just postpone
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" full update pending, restarting timer";
|
2010-03-10 16:55:37 +01:00
|
|
|
m_asyncUpdateTimer.start();
|
|
|
|
} else if (m_asyncUpdateState == AsyncPartialUpdatePending
|
|
|
|
|| m_asyncUpdateState == Base) {
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" adding node to async update list, setting state to AsyncPartialUpdatePending";
|
2010-03-10 16:55:37 +01:00
|
|
|
// Add the node
|
|
|
|
m_asyncUpdateState = AsyncPartialUpdatePending;
|
|
|
|
|
2011-05-25 11:23:25 +02:00
|
|
|
QList<Qt4ProFileNode *>::iterator it;
|
2010-03-10 16:55:37 +01:00
|
|
|
bool add = true;
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<"scheduleAsyncUpdate();"<<m_partialEvaluate.size()<<"nodes";
|
2010-03-10 16:55:37 +01:00
|
|
|
it = m_partialEvaluate.begin();
|
|
|
|
while (it != m_partialEvaluate.end()) {
|
|
|
|
if (*it == node) {
|
|
|
|
add = false;
|
|
|
|
break;
|
|
|
|
} else if (node->isParent(*it)) { // We already have the parent in the list, nothing to do
|
2011-09-12 12:40:53 +02:00
|
|
|
it = m_partialEvaluate.erase(it);
|
|
|
|
} else if ((*it)->isParent(node)) { // The node is the parent of a child already in the list
|
2010-03-10 16:55:37 +01:00
|
|
|
add = false;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (add)
|
|
|
|
m_partialEvaluate.append(node);
|
|
|
|
// and start the timer anew
|
|
|
|
m_asyncUpdateTimer.start();
|
|
|
|
} else if (m_asyncUpdateState == AsyncUpdateInProgress) {
|
|
|
|
// A update is in progress
|
|
|
|
// And this slot only gets called if a file changed on disc
|
|
|
|
// So we'll play it safe and schedule a complete evaluate
|
|
|
|
// This might trigger if due to version control a few files
|
|
|
|
// change a partial update gets in progress and then another
|
|
|
|
// batch of changes come in, which triggers a full update
|
|
|
|
// even if that's not really needed
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" Async update in progress, scheduling new one afterwards";
|
2010-03-10 16:55:37 +01:00
|
|
|
scheduleAsyncUpdate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Qt4Project::scheduleAsyncUpdate()
|
|
|
|
{
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<"scheduleAsyncUpdate";
|
2010-10-25 17:26:41 +02:00
|
|
|
if (m_asyncUpdateState == ShuttingDown)
|
|
|
|
return;
|
2010-10-27 16:27:22 +02:00
|
|
|
|
2010-03-10 16:55:37 +01:00
|
|
|
Q_ASSERT(m_asyncUpdateState != NoState);
|
|
|
|
if (m_cancelEvaluate) { // we are in progress of canceling
|
|
|
|
// and will start the evaluation after that
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" canceling is in progress, doing nothing";
|
2010-03-10 16:55:37 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (m_asyncUpdateState == AsyncUpdateInProgress) {
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" update in progress, canceling and setting state to full update pending";
|
2010-03-10 16:55:37 +01:00
|
|
|
m_cancelEvaluate = true;
|
|
|
|
m_asyncUpdateState = AsyncFullUpdatePending;
|
2011-08-18 16:46:44 +02:00
|
|
|
activeTarget()->activeQt4BuildConfiguration()->setEnabled(false);
|
2011-09-12 12:40:53 +02:00
|
|
|
m_rootProjectNode->setParseInProgressRecursive(true);
|
2010-03-10 16:55:37 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" starting timer for full update, setting state to full update pending";
|
2010-03-10 16:55:37 +01:00
|
|
|
m_partialEvaluate.clear();
|
2011-08-18 16:46:44 +02:00
|
|
|
activeTarget()->activeQt4BuildConfiguration()->setEnabled(false);
|
2011-09-12 12:40:53 +02:00
|
|
|
m_rootProjectNode->setParseInProgressRecursive(true);
|
2010-03-10 16:55:37 +01:00
|
|
|
m_asyncUpdateState = AsyncFullUpdatePending;
|
|
|
|
m_asyncUpdateTimer.start();
|
2010-04-22 18:57:43 +02:00
|
|
|
|
|
|
|
// Cancel running code model update
|
|
|
|
m_codeModelFuture.cancel();
|
2011-05-30 13:11:31 +02:00
|
|
|
m_codeModelCanceled = true;
|
2010-03-10 16:55:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Qt4Project::incrementPendingEvaluateFutures()
|
|
|
|
{
|
|
|
|
++m_pendingEvaluateFuturesCount;
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<"incrementPendingEvaluateFutures to"<<m_pendingEvaluateFuturesCount;
|
2010-03-10 16:55:37 +01:00
|
|
|
|
|
|
|
m_asyncUpdateFutureInterface->setProgressRange(m_asyncUpdateFutureInterface->progressMinimum(),
|
|
|
|
m_asyncUpdateFutureInterface->progressMaximum() + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Qt4Project::decrementPendingEvaluateFutures()
|
|
|
|
{
|
|
|
|
--m_pendingEvaluateFuturesCount;
|
|
|
|
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<"decrementPendingEvaluateFutures to"<<m_pendingEvaluateFuturesCount;
|
2010-03-10 16:55:37 +01:00
|
|
|
|
|
|
|
m_asyncUpdateFutureInterface->setProgressValue(m_asyncUpdateFutureInterface->progressValue() + 1);
|
|
|
|
if (m_pendingEvaluateFuturesCount == 0) {
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" WOHOO, no pending futures, cleaning up";
|
2010-03-10 16:55:37 +01:00
|
|
|
// We are done!
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" reporting finished";
|
2010-03-10 16:55:37 +01:00
|
|
|
m_asyncUpdateFutureInterface->reportFinished();
|
|
|
|
delete m_asyncUpdateFutureInterface;
|
|
|
|
m_asyncUpdateFutureInterface = 0;
|
|
|
|
m_cancelEvaluate = false;
|
|
|
|
|
|
|
|
// TODO clear the profile cache ?
|
|
|
|
if (m_asyncUpdateState == AsyncFullUpdatePending || m_asyncUpdateState == AsyncPartialUpdatePending) {
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" Oh update is pending start the timer";
|
2010-03-10 16:55:37 +01:00
|
|
|
m_asyncUpdateTimer.start();
|
2010-03-11 17:01:06 +01:00
|
|
|
} else if (m_asyncUpdateState != ShuttingDown){
|
2010-10-30 21:54:23 +02:00
|
|
|
// After being done, we need to call:
|
2011-09-12 13:25:12 +02:00
|
|
|
m_asyncUpdateState = Base;
|
2011-08-18 16:46:44 +02:00
|
|
|
activeTarget()->activeQt4BuildConfiguration()->setEnabled(true);
|
2010-12-10 19:02:19 +01:00
|
|
|
foreach (Target *t, targets())
|
|
|
|
static_cast<Qt4BaseTarget *>(t)->createApplicationProFiles();
|
2010-03-11 17:01:06 +01:00
|
|
|
updateFileList();
|
2011-09-15 12:15:10 +02:00
|
|
|
updateCodeModels();
|
2011-09-12 13:25:12 +02:00
|
|
|
emit proParsingDone();
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" Setting state to Base";
|
2010-03-10 16:55:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Qt4Project::wasEvaluateCanceled()
|
|
|
|
{
|
|
|
|
return m_cancelEvaluate;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Qt4Project::asyncUpdate()
|
|
|
|
{
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<"async update, timer expired, doing now";
|
2010-03-10 16:55:37 +01:00
|
|
|
Q_ASSERT(!m_asyncUpdateFutureInterface);
|
|
|
|
m_asyncUpdateFutureInterface = new QFutureInterface<void>();
|
|
|
|
|
|
|
|
Core::ProgressManager *progressManager = Core::ICore::instance()->progressManager();
|
|
|
|
|
2010-04-13 16:32:01 +02:00
|
|
|
m_asyncUpdateFutureInterface->setProgressRange(0, 0);
|
|
|
|
progressManager->addTask(m_asyncUpdateFutureInterface->future(), tr("Evaluating"), Constants::PROFILE_EVALUATE);
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" adding task";
|
2010-03-10 16:55:37 +01:00
|
|
|
|
|
|
|
m_asyncUpdateFutureInterface->reportStarted();
|
|
|
|
|
|
|
|
if (m_asyncUpdateState == AsyncFullUpdatePending) {
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" full update, starting with root node";
|
2010-03-10 16:55:37 +01:00
|
|
|
m_rootProjectNode->asyncUpdate();
|
|
|
|
} else {
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" partial update,"<<m_partialEvaluate.size()<<"nodes to update";
|
2010-03-10 16:55:37 +01:00
|
|
|
foreach(Qt4ProFileNode *node, m_partialEvaluate)
|
|
|
|
node->asyncUpdate();
|
|
|
|
}
|
|
|
|
|
|
|
|
m_partialEvaluate.clear();
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" Setting state to AsyncUpdateInProgress";
|
2010-03-10 16:55:37 +01:00
|
|
|
m_asyncUpdateState = AsyncUpdateInProgress;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ProjectExplorer::IProjectManager *Qt4Project::projectManager() const
|
|
|
|
{
|
|
|
|
return m_manager;
|
|
|
|
}
|
|
|
|
|
|
|
|
Qt4Manager *Qt4Project::qt4ProjectManager() const
|
|
|
|
{
|
|
|
|
return m_manager;
|
|
|
|
}
|
|
|
|
|
2010-01-07 18:17:24 +01:00
|
|
|
QString Qt4Project::displayName() const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
|
|
|
return QFileInfo(file()->fileName()).completeBaseName();
|
|
|
|
}
|
|
|
|
|
2010-01-22 15:59:44 +01:00
|
|
|
QString Qt4Project::id() const
|
|
|
|
{
|
2010-07-16 14:00:41 +02:00
|
|
|
return QLatin1String(Constants::QT4PROJECT_ID);
|
2010-01-22 15:59:44 +01:00
|
|
|
}
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
Core::IFile *Qt4Project::file() const
|
|
|
|
{
|
|
|
|
return m_fileInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
QStringList Qt4Project::files(FilesMode fileMode) const
|
|
|
|
{
|
|
|
|
QStringList files;
|
|
|
|
for (int i = 0; i < FileTypeSize; ++i) {
|
|
|
|
files += m_projectFiles->files[i];
|
|
|
|
if (fileMode == AllFiles)
|
|
|
|
files += m_projectFiles->generatedFiles[i];
|
|
|
|
}
|
|
|
|
return files;
|
|
|
|
}
|
|
|
|
|
2009-12-03 16:23:15 +01:00
|
|
|
// Find the folder that contains a file a certain type (recurse down)
|
|
|
|
static FolderNode *folderOf(FolderNode *in, FileType fileType, const QString &fileName)
|
|
|
|
{
|
|
|
|
foreach(FileNode *fn, in->fileNodes())
|
|
|
|
if (fn->fileType() == fileType && fn->path() == fileName)
|
|
|
|
return in;
|
|
|
|
foreach(FolderNode *folder, in->subFolderNodes())
|
|
|
|
if (FolderNode *pn = folderOf(folder, fileType, fileName))
|
|
|
|
return pn;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the Qt4ProFileNode that contains a file of a certain type.
|
|
|
|
// First recurse down to folder, then find the pro-file.
|
|
|
|
static Qt4ProFileNode *proFileNodeOf(Qt4ProFileNode *in, FileType fileType, const QString &fileName)
|
|
|
|
{
|
|
|
|
for (FolderNode *folder = folderOf(in, fileType, fileName); folder; folder = folder->parentFolderNode())
|
|
|
|
if (Qt4ProFileNode *proFile = qobject_cast<Qt4ProFileNode *>(folder))
|
|
|
|
return proFile;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Qt4Project::generatedUiHeader(const QString &formFile) const
|
|
|
|
{
|
|
|
|
// Look in sub-profiles as SessionManager::projectForFile returns
|
|
|
|
// the top-level project only.
|
|
|
|
if (m_rootProjectNode)
|
|
|
|
if (const Qt4ProFileNode *pro = proFileNodeOf(m_rootProjectNode, FormType, formFile))
|
|
|
|
return Qt4ProFileNode::uiHeaderFile(pro->uiDirectory(), formFile);
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
QList<ProjectExplorer::Project*> Qt4Project::dependsOn()
|
|
|
|
{
|
|
|
|
// NBS implement dependsOn
|
|
|
|
return QList<Project *>();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Qt4Project::addDefaultBuild()
|
|
|
|
{
|
2009-10-15 19:06:51 +02:00
|
|
|
// TODO this could probably refactored
|
|
|
|
// That is the ProjectLoadWizard divided into useful bits
|
|
|
|
// and this code then called here, instead of that strange forwarding
|
|
|
|
// to a wizard, which doesn't even show up
|
|
|
|
ProjectLoadWizard wizard(this);
|
|
|
|
wizard.execDialog();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Qt4Project::proFileParseError(const QString &errorMessage)
|
|
|
|
{
|
2011-03-11 12:27:42 +01:00
|
|
|
Core::ICore::instance()->messageManager()->printToOutputPanePopup(errorMessage);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
2011-05-20 21:40:53 +02:00
|
|
|
QtSupport::ProFileReader *Qt4Project::createProFileReader(Qt4ProFileNode *qt4ProFileNode, Qt4BuildConfiguration *bc)
|
2009-12-07 20:49:39 +01:00
|
|
|
{
|
|
|
|
if (!m_proFileOption) {
|
|
|
|
m_proFileOption = new ProFileOption;
|
|
|
|
m_proFileOptionRefCnt = 0;
|
|
|
|
|
2011-03-18 18:42:22 +01:00
|
|
|
if (!bc && activeTarget())
|
2011-08-18 16:46:44 +02:00
|
|
|
bc = activeTarget()->activeQt4BuildConfiguration();
|
2011-01-21 15:37:05 +01:00
|
|
|
|
|
|
|
if (bc) {
|
2011-05-20 21:40:53 +02:00
|
|
|
QtSupport::BaseQtVersion *version = bc->qtVersion();
|
2011-05-04 13:14:46 +02:00
|
|
|
if (version && version->isValid()) {
|
2009-12-07 20:49:39 +01:00
|
|
|
m_proFileOption->properties = version->versionInfo();
|
2011-01-21 15:37:05 +01:00
|
|
|
if (bc->toolChain())
|
|
|
|
m_proFileOption->sysroot = bc->qtVersion()->systemRoot();
|
2011-01-05 17:56:49 +01:00
|
|
|
}
|
2011-03-18 19:32:57 +01:00
|
|
|
|
2011-04-20 21:16:17 +02:00
|
|
|
Utils::Environment env = bc->environment();
|
|
|
|
Utils::Environment::const_iterator eit = env.constBegin(), eend = env.constEnd();
|
|
|
|
for (; eit != eend; ++eit)
|
|
|
|
m_proFileOption->environment.insert(env.key(eit), env.value(eit));
|
|
|
|
|
2011-03-18 19:32:57 +01:00
|
|
|
QStringList args;
|
|
|
|
if (QMakeStep *qs = bc->qmakeStep())
|
|
|
|
args = qs->parserArguments();
|
|
|
|
else
|
|
|
|
args = bc->configCommandLineArguments();
|
|
|
|
m_proFileOption->setCommandLineArguments(args);
|
2009-12-07 20:49:39 +01:00
|
|
|
}
|
2009-12-07 22:58:47 +01:00
|
|
|
|
2011-05-20 21:40:53 +02:00
|
|
|
QtSupport::ProFileCacheManager::instance()->incRefCount();
|
2009-12-07 20:49:39 +01:00
|
|
|
}
|
|
|
|
++m_proFileOptionRefCnt;
|
|
|
|
|
2011-05-20 21:40:53 +02:00
|
|
|
QtSupport::ProFileReader *reader = new QtSupport::ProFileReader(m_proFileOption);
|
2009-12-07 20:49:39 +01:00
|
|
|
|
|
|
|
reader->setOutputDir(qt4ProFileNode->buildDir());
|
|
|
|
|
|
|
|
return reader;
|
|
|
|
}
|
|
|
|
|
2011-05-20 21:40:53 +02:00
|
|
|
void Qt4Project::destroyProFileReader(QtSupport::ProFileReader *reader)
|
2009-12-07 20:49:39 +01:00
|
|
|
{
|
|
|
|
delete reader;
|
|
|
|
if (!--m_proFileOptionRefCnt) {
|
2009-12-07 22:58:47 +01:00
|
|
|
QString dir = QFileInfo(m_fileInfo->fileName()).absolutePath();
|
|
|
|
if (!dir.endsWith(QLatin1Char('/')))
|
|
|
|
dir += QLatin1Char('/');
|
2011-05-20 21:40:53 +02:00
|
|
|
QtSupport::ProFileCacheManager::instance()->discardFiles(dir);
|
|
|
|
QtSupport::ProFileCacheManager::instance()->decRefCount();
|
2009-12-07 22:58:47 +01:00
|
|
|
|
2009-12-07 20:49:39 +01:00
|
|
|
delete m_proFileOption;
|
|
|
|
m_proFileOption = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-18 16:46:44 +02:00
|
|
|
ProjectExplorer::ProjectNode *Qt4Project::rootProjectNode() const
|
|
|
|
{
|
|
|
|
return m_rootProjectNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
Qt4ProFileNode *Qt4Project::rootQt4ProjectNode() const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
|
|
|
return m_rootProjectNode;
|
|
|
|
}
|
|
|
|
|
2010-10-27 16:27:22 +02:00
|
|
|
bool Qt4Project::validParse(const QString &proFilePath) const
|
|
|
|
{
|
2010-10-29 12:15:30 +02:00
|
|
|
if (!m_rootProjectNode)
|
|
|
|
return false;
|
2010-10-27 16:27:22 +02:00
|
|
|
const Qt4ProFileNode *node = m_rootProjectNode->findProFileFor(proFilePath);
|
|
|
|
return node && node->validParse();
|
|
|
|
}
|
|
|
|
|
2011-06-10 15:37:10 +02:00
|
|
|
bool Qt4Project::parseInProgress(const QString &proFilePath) const
|
|
|
|
{
|
|
|
|
if (!m_rootProjectNode)
|
|
|
|
return false;
|
|
|
|
const Qt4ProFileNode *node = m_rootProjectNode->findProFileFor(proFilePath);
|
|
|
|
return node && node->parseInProgress();
|
|
|
|
}
|
|
|
|
|
2009-08-06 15:31:32 +02:00
|
|
|
QList<BuildConfigWidget*> Qt4Project::subConfigWidgets()
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2009-08-06 15:31:32 +02:00
|
|
|
QList<BuildConfigWidget*> subWidgets;
|
2010-03-11 17:47:09 +01:00
|
|
|
subWidgets << new BuildEnvironmentWidget;
|
2008-12-02 12:01:29 +01:00
|
|
|
return subWidgets;
|
|
|
|
}
|
|
|
|
|
2011-01-24 15:36:46 +01:00
|
|
|
void Qt4Project::collectAllfProFiles(QList<Qt4ProFileNode *> &list, Qt4ProFileNode *node)
|
2010-07-23 16:37:10 +02:00
|
|
|
{
|
2011-01-24 15:36:46 +01:00
|
|
|
list.append(node);
|
2010-07-23 16:37:10 +02:00
|
|
|
foreach (ProjectNode *n, node->subProjectNodes()) {
|
|
|
|
Qt4ProFileNode *qt4ProFileNode = qobject_cast<Qt4ProFileNode *>(n);
|
|
|
|
if (qt4ProFileNode)
|
2011-01-24 15:36:46 +01:00
|
|
|
collectAllfProFiles(list, qt4ProFileNode);
|
2010-07-23 16:37:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
void Qt4Project::collectApplicationProFiles(QList<Qt4ProFileNode *> &list, Qt4ProFileNode *node)
|
|
|
|
{
|
2011-05-25 11:23:25 +02:00
|
|
|
if (node->projectType() == ApplicationTemplate
|
|
|
|
|| node->projectType() == ScriptTemplate) {
|
2008-12-02 12:01:29 +01:00
|
|
|
list.append(node);
|
|
|
|
}
|
|
|
|
foreach (ProjectNode *n, node->subProjectNodes()) {
|
|
|
|
Qt4ProFileNode *qt4ProFileNode = qobject_cast<Qt4ProFileNode *>(n);
|
|
|
|
if (qt4ProFileNode)
|
|
|
|
collectApplicationProFiles(list, qt4ProFileNode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-24 15:36:46 +01:00
|
|
|
QList<Qt4ProFileNode *> Qt4Project::allProFiles() const
|
2010-07-23 16:37:10 +02:00
|
|
|
{
|
|
|
|
QList<Qt4ProFileNode *> list;
|
|
|
|
if (!rootProjectNode())
|
|
|
|
return list;
|
2011-08-18 16:46:44 +02:00
|
|
|
collectAllfProFiles(list, rootQt4ProjectNode());
|
2010-07-23 16:37:10 +02:00
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
QList<Qt4ProFileNode *> Qt4Project::applicationProFiles() const
|
|
|
|
{
|
|
|
|
QList<Qt4ProFileNode *> list;
|
2010-02-08 15:50:06 +01:00
|
|
|
if (!rootProjectNode())
|
|
|
|
return list;
|
2011-08-18 16:46:44 +02:00
|
|
|
collectApplicationProFiles(list, rootQt4ProjectNode());
|
2008-12-02 12:01:29 +01:00
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2010-01-19 13:41:02 +01:00
|
|
|
bool Qt4Project::hasApplicationProFile(const QString &path) const
|
|
|
|
{
|
|
|
|
if (path.isEmpty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
QList<Qt4ProFileNode *> list = applicationProFiles();
|
|
|
|
foreach (Qt4ProFileNode * node, list)
|
|
|
|
if (node->path() == path)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
QStringList Qt4Project::applicationProFilePathes(const QString &prepend) const
|
|
|
|
{
|
|
|
|
QStringList proFiles;
|
|
|
|
foreach (Qt4ProFileNode *node, applicationProFiles())
|
|
|
|
proFiles.append(prepend + node->path());
|
|
|
|
return proFiles;
|
|
|
|
}
|
|
|
|
|
2010-02-08 15:50:06 +01:00
|
|
|
void Qt4Project::activeTargetWasChanged()
|
|
|
|
{
|
|
|
|
if (!activeTarget())
|
|
|
|
return;
|
|
|
|
|
2010-03-10 16:55:37 +01:00
|
|
|
scheduleAsyncUpdate();
|
2010-02-08 15:50:06 +01:00
|
|
|
}
|
|
|
|
|
2008-12-05 14:29:18 +01:00
|
|
|
bool Qt4Project::hasSubNode(Qt4PriFileNode *root, const QString &path)
|
2008-12-02 18:14:06 +01:00
|
|
|
{
|
2008-12-05 14:29:18 +01:00
|
|
|
if (root->path() == path)
|
|
|
|
return true;
|
|
|
|
foreach (FolderNode *fn, root->subFolderNodes()) {
|
|
|
|
if (qobject_cast<Qt4ProFileNode *>(fn)) {
|
|
|
|
// we aren't interested in pro file nodes
|
2008-12-09 11:07:24 +01:00
|
|
|
} else if (Qt4PriFileNode *qt4prifilenode = qobject_cast<Qt4PriFileNode *>(fn)) {
|
2008-12-05 14:29:18 +01:00
|
|
|
if (hasSubNode(qt4prifilenode, path))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2008-12-02 18:14:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Qt4Project::findProFile(const QString& fileName, Qt4ProFileNode *root, QList<Qt4ProFileNode *> &list)
|
|
|
|
{
|
2008-12-05 14:29:18 +01:00
|
|
|
if (hasSubNode(root, fileName))
|
2008-12-02 18:14:06 +01:00
|
|
|
list.append(root);
|
|
|
|
|
|
|
|
foreach (FolderNode *fn, root->subFolderNodes())
|
|
|
|
if (Qt4ProFileNode *qt4proFileNode = qobject_cast<Qt4ProFileNode *>(fn))
|
|
|
|
findProFile(fileName, qt4proFileNode, list);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Qt4Project::notifyChanged(const QString &name)
|
|
|
|
{
|
2008-12-05 14:29:18 +01:00
|
|
|
if (files(Qt4Project::ExcludeGeneratedFiles).contains(name)) {
|
|
|
|
QList<Qt4ProFileNode *> list;
|
2011-08-18 16:46:44 +02:00
|
|
|
findProFile(name, rootQt4ProjectNode(), list);
|
2009-12-07 22:58:47 +01:00
|
|
|
foreach(Qt4ProFileNode *node, list) {
|
2011-05-20 21:40:53 +02:00
|
|
|
QtSupport::ProFileCacheManager::instance()->discardFile(name);
|
2008-12-05 14:29:18 +01:00
|
|
|
node->update();
|
2009-12-07 22:58:47 +01:00
|
|
|
}
|
2011-05-25 12:54:14 +02:00
|
|
|
updateFileList();
|
2008-12-05 14:29:18 +01:00
|
|
|
}
|
2008-12-02 18:14:06 +01:00
|
|
|
}
|
2009-03-19 15:04:43 +01:00
|
|
|
|
2011-08-18 16:46:44 +02:00
|
|
|
void Qt4Project::watchFolders(const QStringList &l, Qt4PriFileNode *node)
|
|
|
|
{
|
|
|
|
if (l.isEmpty())
|
|
|
|
return;
|
|
|
|
if (!m_centralizedFolderWatcher)
|
|
|
|
m_centralizedFolderWatcher = new Internal::CentralizedFolderWatcher(this);
|
|
|
|
m_centralizedFolderWatcher->watchFolders(l, node);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Qt4Project::unwatchFolders(const QStringList &l, Qt4PriFileNode *node)
|
2010-08-10 16:27:35 +02:00
|
|
|
{
|
2011-08-18 16:46:44 +02:00
|
|
|
if (m_centralizedFolderWatcher && !l.isEmpty())
|
|
|
|
m_centralizedFolderWatcher->unwatchFolders(l, node);
|
2010-08-10 16:27:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/////////////
|
|
|
|
/// Centralized Folder Watcher
|
|
|
|
////////////
|
|
|
|
|
|
|
|
// All the folder have a trailing slash!
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
bool debugCFW = false;
|
|
|
|
}
|
|
|
|
|
2011-08-18 16:46:44 +02:00
|
|
|
CentralizedFolderWatcher::CentralizedFolderWatcher(QObject *parent) : QObject(parent)
|
2010-08-10 16:27:35 +02:00
|
|
|
{
|
2010-10-13 15:33:51 +02:00
|
|
|
m_compressTimer.setSingleShot(true);
|
|
|
|
m_compressTimer.setInterval(200);
|
|
|
|
connect(&m_compressTimer, SIGNAL(timeout()),
|
|
|
|
this, SLOT(onTimer()));
|
2010-08-10 16:27:35 +02:00
|
|
|
connect (&m_watcher, SIGNAL(directoryChanged(QString)),
|
|
|
|
this, SLOT(folderChanged(QString)));
|
|
|
|
}
|
|
|
|
|
|
|
|
CentralizedFolderWatcher::~CentralizedFolderWatcher()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
QSet<QString> CentralizedFolderWatcher::recursiveDirs(const QString &folder)
|
|
|
|
{
|
|
|
|
QSet<QString> result;
|
|
|
|
QDir dir(folder);
|
|
|
|
QStringList list = dir.entryList(QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot);
|
|
|
|
foreach (const QString &f, list) {
|
2011-02-25 15:27:13 +01:00
|
|
|
const QString a = folder + f + '/';
|
|
|
|
result.insert(a);
|
|
|
|
result += recursiveDirs(a);
|
2010-08-10 16:27:35 +02:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CentralizedFolderWatcher::watchFolders(const QList<QString> &folders, Qt4PriFileNode *node)
|
|
|
|
{
|
|
|
|
if (debugCFW)
|
|
|
|
qDebug()<<"CFW::watchFolders()"<<folders<<"for node"<<node->path();
|
|
|
|
m_watcher.addPaths(folders);
|
|
|
|
|
|
|
|
foreach (const QString &f, folders) {
|
|
|
|
QString folder = f;
|
|
|
|
if (!folder.endsWith('/'))
|
|
|
|
folder.append('/');
|
|
|
|
m_map.insert(folder, node);
|
|
|
|
|
|
|
|
// Support for recursive watching
|
|
|
|
// we add the recursive directories we find
|
|
|
|
QSet<QString> tmp = recursiveDirs(folder);
|
2010-08-12 13:38:21 +02:00
|
|
|
if (!tmp.isEmpty())
|
|
|
|
m_watcher.addPaths(tmp.toList());
|
2010-08-10 16:27:35 +02:00
|
|
|
m_recursiveWatchedFolders += tmp;
|
|
|
|
|
|
|
|
if (debugCFW)
|
|
|
|
qDebug()<<"adding recursive dirs for"<< folder<<":"<<tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CentralizedFolderWatcher::unwatchFolders(const QList<QString> &folders, Qt4PriFileNode *node)
|
|
|
|
{
|
|
|
|
if (debugCFW)
|
|
|
|
qDebug()<<"CFW::unwatchFolders()"<<folders<<"for node"<<node->path();
|
|
|
|
foreach (const QString &f, folders) {
|
|
|
|
QString folder = f;
|
|
|
|
if (!folder.endsWith('/'))
|
|
|
|
folder.append('/');
|
|
|
|
m_map.remove(folder, node);
|
|
|
|
if (!m_map.contains(folder)) {
|
|
|
|
m_watcher.removePath(folder);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Figure out which recursive directories we can remove
|
|
|
|
// TODO this might not scale. I'm pretty sure it doesn't
|
|
|
|
// A scaling implementation would need to save more information
|
|
|
|
// where a given directory watcher actual comes from...
|
|
|
|
|
|
|
|
QStringList toRemove;
|
|
|
|
foreach (const QString &rwf, m_recursiveWatchedFolders) {
|
|
|
|
if (rwf.startsWith(folder)) {
|
|
|
|
// So the rwf is a subdirectory of a folder we aren't watching
|
|
|
|
// but maybe someone else wants us to watch
|
|
|
|
bool needToWatch = false;
|
|
|
|
QMultiMap<QString, Qt4PriFileNode *>::const_iterator it, end;
|
|
|
|
end = m_map.constEnd();
|
|
|
|
for (it = m_map.constEnd(); it != end; ++it) {
|
|
|
|
if (rwf.startsWith(it.key())) {
|
|
|
|
needToWatch = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!needToWatch) {
|
|
|
|
m_watcher.removePath(rwf);
|
|
|
|
toRemove << rwf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (debugCFW)
|
|
|
|
qDebug()<<"removing recursive dirs for"<<folder<<":"<<toRemove;
|
|
|
|
|
|
|
|
foreach (const QString &tr, toRemove) {
|
|
|
|
m_recursiveWatchedFolders.remove(tr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CentralizedFolderWatcher::folderChanged(const QString &folder)
|
2010-10-13 15:33:51 +02:00
|
|
|
{
|
|
|
|
m_changedFolders.insert(folder);
|
|
|
|
m_compressTimer.start();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CentralizedFolderWatcher::onTimer()
|
|
|
|
{
|
|
|
|
foreach(const QString &folder, m_changedFolders)
|
|
|
|
delayedFolderChanged(folder);
|
|
|
|
m_changedFolders.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CentralizedFolderWatcher::delayedFolderChanged(const QString &folder)
|
2010-08-10 16:27:35 +02:00
|
|
|
{
|
|
|
|
if (debugCFW)
|
|
|
|
qDebug()<<"CFW::folderChanged"<<folder;
|
|
|
|
// Figure out whom to inform
|
|
|
|
|
2010-08-18 12:53:37 +02:00
|
|
|
QString dir = folder;
|
2010-08-10 16:27:35 +02:00
|
|
|
while (true) {
|
2010-08-18 12:53:37 +02:00
|
|
|
if (!dir.endsWith('/'))
|
|
|
|
dir.append('/');
|
|
|
|
QList<Qt4PriFileNode *> nodes = m_map.values(dir);
|
2010-08-10 16:27:35 +02:00
|
|
|
foreach (Qt4PriFileNode *node, nodes) {
|
|
|
|
node->folderChanged(folder);
|
|
|
|
}
|
|
|
|
|
2010-08-18 12:53:37 +02:00
|
|
|
// Chop off last part, and break if there's nothing to chop off
|
|
|
|
//
|
|
|
|
if (dir.length() < 2)
|
2010-08-10 16:27:35 +02:00
|
|
|
break;
|
2010-08-18 12:53:37 +02:00
|
|
|
|
|
|
|
// We start before the last slash
|
|
|
|
int index = dir.lastIndexOf('/', dir.length() - 2);
|
|
|
|
if (index == -1)
|
|
|
|
break;
|
|
|
|
dir = dir.left(index + 1);
|
2010-08-10 16:27:35 +02:00
|
|
|
}
|
|
|
|
|
2010-08-18 12:53:37 +02:00
|
|
|
|
2010-08-16 13:01:36 +02:00
|
|
|
QString folderWithSlash = folder;
|
|
|
|
if (!folder.endsWith('/'))
|
|
|
|
folderWithSlash.append('/');
|
|
|
|
|
2010-08-10 16:27:35 +02:00
|
|
|
// If a subdirectory was added, watch it too
|
2010-08-16 13:01:36 +02:00
|
|
|
QSet<QString> tmp = recursiveDirs(folderWithSlash);
|
2010-08-10 16:27:35 +02:00
|
|
|
if (!tmp.isEmpty()) {
|
|
|
|
if (debugCFW)
|
|
|
|
qDebug()<<"found new recursive dirs"<<tmp;
|
2010-10-13 14:44:32 +02:00
|
|
|
|
|
|
|
QSet<QString> alreadyAdded = m_watcher.directories().toSet();
|
|
|
|
tmp.subtract(alreadyAdded);
|
|
|
|
if (!tmp.isEmpty())
|
|
|
|
m_watcher.addPaths(tmp.toList());
|
2010-08-10 16:27:35 +02:00
|
|
|
m_recursiveWatchedFolders += tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-19 15:04:43 +01:00
|
|
|
/*!
|
|
|
|
Handle special case were a subproject of the qt directory is opened, and
|
|
|
|
qt was configured to be built as a shadow build -> also build in the sub-
|
|
|
|
project in the correct shadow build directory.
|
|
|
|
*/
|
|
|
|
|
|
|
|
// TODO this function should be called on project first load
|
|
|
|
// and it should check against all configured qt versions ?
|
|
|
|
//void Qt4Project::detectQtShadowBuild(const QString &buildConfiguration) const
|
|
|
|
//{
|
|
|
|
// if (project()->activeBuildConfiguration() == buildConfiguration)
|
|
|
|
// return;
|
|
|
|
//
|
|
|
|
// const QString currentQtDir = static_cast<Qt4Project *>(project())->qtDir(buildConfiguration);
|
|
|
|
// const QString qtSourceDir = static_cast<Qt4Project *>(project())->qtVersion(buildConfiguration)->sourcePath();
|
|
|
|
//
|
|
|
|
// // if the project is a sub-project of Qt and Qt was shadow-built then automatically
|
|
|
|
// // adjust the build directory of the sub-project.
|
|
|
|
// if (project()->file()->fileName().startsWith(qtSourceDir) && qtSourceDir != currentQtDir) {
|
|
|
|
// project()->setValue(buildConfiguration, "useShadowBuild", true);
|
2010-03-25 13:19:27 +01:00
|
|
|
// QString buildDir = project()->projectDirectory();
|
2009-03-19 15:04:43 +01:00
|
|
|
// buildDir.replace(qtSourceDir, currentQtDir);
|
|
|
|
// project()->setValue(buildConfiguration, "buildDirectory", buildDir);
|
|
|
|
// project()->setValue(buildConfiguration, "autoShadowBuild", true);
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
|
2011-08-18 16:55:45 +02:00
|
|
|
} // namespace Qt4ProjectManager
|
|
|
|
|
2011-08-18 16:46:44 +02:00
|
|
|
#include "qt4project.moc"
|