summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/plugins/projectexplorer/projectnodes.cpp1
-rw-r--r--src/plugins/qt4projectmanager/profilereader.cpp23
-rw-r--r--src/plugins/qt4projectmanager/profilereader.h5
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp49
-rw-r--r--src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h4
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp139
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h8
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp54
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h3
-rw-r--r--src/plugins/qt4projectmanager/qt4buildconfiguration.cpp12
-rw-r--r--src/plugins/qt4projectmanager/qt4buildconfiguration.h9
-rw-r--r--src/plugins/qt4projectmanager/qt4nodes.cpp484
-rw-r--r--src/plugins/qt4projectmanager/qt4nodes.h66
-rw-r--r--src/plugins/qt4projectmanager/qt4project.cpp438
-rw-r--r--src/plugins/qt4projectmanager/qt4project.h64
-rw-r--r--src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp4
-rw-r--r--src/plugins/qt4projectmanager/qt4projectmanager.cpp1
-rw-r--r--src/plugins/qt4projectmanager/qt4projectmanagerconstants.h3
-rw-r--r--src/plugins/qt4projectmanager/qt4runconfiguration.cpp54
-rw-r--r--src/plugins/qt4projectmanager/qt4runconfiguration.h10
-rw-r--r--src/plugins/qt4projectmanager/qt4target.cpp100
-rw-r--r--src/plugins/qt4projectmanager/qt4target.h27
-rw-r--r--src/plugins/qt4projectmanager/qtversionmanager.cpp2
23 files changed, 868 insertions, 692 deletions
diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp
index c552b11235..d9cd9b11a1 100644
--- a/src/plugins/projectexplorer/projectnodes.cpp
+++ b/src/plugins/projectexplorer/projectnodes.cpp
@@ -61,6 +61,7 @@ Node::Node(NodeType nodeType,
m_folderNode(0),
m_path(filePath)
{
+
}
NodeType Node::nodeType() const
diff --git a/src/plugins/qt4projectmanager/profilereader.cpp b/src/plugins/qt4projectmanager/profilereader.cpp
index cb7cb52715..30c7ad70ea 100644
--- a/src/plugins/qt4projectmanager/profilereader.cpp
+++ b/src/plugins/qt4projectmanager/profilereader.cpp
@@ -116,12 +116,27 @@ ProFileCacheManager *ProFileCacheManager::s_instance = 0;
ProFileCacheManager::ProFileCacheManager(QObject *parent) :
QObject(parent),
- m_cache(0)
+ m_cache(0),
+ m_refCount(0)
{
s_instance = this;
- m_timer.setSingleShot(true);
m_timer.setInterval(5000);
- connect(&m_timer, SIGNAL(timeout()), SLOT(clear()));
+ m_timer.setSingleShot(true);
+ connect(&m_timer, SIGNAL(timeout()),
+ this, SLOT(clear()));
+}
+
+void ProFileCacheManager::incRefCount()
+{
+ ++m_refCount;
+ m_timer.stop();
+}
+
+void ProFileCacheManager::decRefCount()
+{
+ --m_refCount;
+ if (!m_refCount)
+ m_timer.start();
}
ProFileCacheManager::~ProFileCacheManager()
@@ -132,7 +147,6 @@ ProFileCacheManager::~ProFileCacheManager()
ProFileCache *ProFileCacheManager::cache()
{
- m_timer.start();
if (!m_cache)
m_cache = new ProFileCache;
return m_cache;
@@ -140,6 +154,7 @@ ProFileCache *ProFileCacheManager::cache()
void ProFileCacheManager::clear()
{
+ Q_ASSERT(m_refCount == 0);
// Just deleting the cache will be safe as long as the sequence of
// obtaining a cache pointer and using it is atomic as far as the main
// loop is concerned. Use a shared pointer once this is not true anymore.
diff --git a/src/plugins/qt4projectmanager/profilereader.h b/src/plugins/qt4projectmanager/profilereader.h
index 0e8fda774f..b749bc3e56 100644
--- a/src/plugins/qt4projectmanager/profilereader.h
+++ b/src/plugins/qt4projectmanager/profilereader.h
@@ -77,13 +77,16 @@ public:
ProFileCache *cache();
void discardFiles(const QString &prefix);
void discardFile(const QString &fileName);
+ void incRefCount();
+ void decRefCount();
private:
ProFileCacheManager(QObject *parent);
~ProFileCacheManager();
Q_SLOT void clear();
- QTimer m_timer;
ProFileCache *m_cache;
+ int m_refCount;
+ QTimer m_timer;
static ProFileCacheManager *s_instance;
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp
index 9d02d33efb..68862439fc 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp
@@ -52,7 +52,6 @@ MaemoRunConfiguration::MaemoRunConfiguration(Qt4Target *parent,
const QString &proFilePath)
: RunConfiguration(parent, QLatin1String(MAEMO_RC_ID))
, m_proFilePath(proFilePath)
- , m_cachedTargetInformationValid(false)
, m_cachedSimulatorInformationValid(false)
, qemu(0)
{
@@ -62,9 +61,7 @@ MaemoRunConfiguration::MaemoRunConfiguration(Qt4Target *parent,
MaemoRunConfiguration::MaemoRunConfiguration(Qt4Target *parent,
MaemoRunConfiguration *source)
: RunConfiguration(parent, source)
- , m_executable(source->m_executable)
, m_proFilePath(source->m_proFilePath)
- , m_cachedTargetInformationValid(false)
, m_simulator(source->m_simulator)
, m_simulatorArgs(source->m_simulatorArgs)
, m_simulatorPath(source->m_simulatorPath)
@@ -95,8 +92,8 @@ void MaemoRunConfiguration::init()
connect(&MaemoDeviceConfigurations::instance(), SIGNAL(updated()), this,
SLOT(updateDeviceConfigurations()));
- connect(qt4Target(), SIGNAL(targetInformationChanged()), this,
- SLOT(invalidateCachedTargetInformation()));
+ connect(qt4Target()->qt4Project(), SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
+ this, SLOT(proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode*)));
connect(qt4Target()->qt4Project(),
SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
@@ -148,7 +145,7 @@ QWidget *MaemoRunConfiguration::configurationWidget()
void MaemoRunConfiguration::proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro)
{
if (m_proFilePath == pro->path())
- invalidateCachedTargetInformation();
+ emit targetInformationChanged();
}
QVariantMap MaemoRunConfiguration::toMap() const
@@ -329,8 +326,11 @@ const QString MaemoRunConfiguration::dumperLib() const
QString MaemoRunConfiguration::executable() const
{
- updateTarget();
- return m_executable;
+ TargetInformation ti = qt4Target()->qt4Project()->rootProjectNode()->targetInformation(m_proFilePath);
+ if (!ti.valid)
+ return QString();
+
+ return QDir::cleanPath(ti.workingDir + QLatin1Char('/') + ti.target);
}
QString MaemoRunConfiguration::simulatorSshPort() const
@@ -379,39 +379,6 @@ bool MaemoRunConfiguration::isQemuRunning() const
return (qemu && qemu->state() != QProcess::NotRunning);
}
-void MaemoRunConfiguration::invalidateCachedTargetInformation()
-{
- m_cachedTargetInformationValid = false;
- emit targetInformationChanged();
-}
-
-void MaemoRunConfiguration::updateTarget() const
-{
- if (m_cachedTargetInformationValid)
- return;
-
- m_executable.clear();
- m_cachedTargetInformationValid = true;
-
- Qt4TargetInformation info =
- qt4Target()->targetInformation(activeQt4BuildConfiguration(),
- m_proFilePath);
- if (info.error != Qt4TargetInformation::NoError) {
- if (info.error == Qt4TargetInformation::ProParserError) {
- Core::ICore::instance()->messageManager()->printToOutputPane(tr(
- "Could not parse %1. The Maemo run configuration %2 "
- "can not be started.").arg(m_proFilePath).arg(displayName()));
- }
- emit targetInformationChanged();
- return;
- }
-
- m_executable
- = QDir::cleanPath(info.workingDir % QLatin1Char('/') % info.target);
-
- emit targetInformationChanged();
-}
-
void MaemoRunConfiguration::updateSimulatorInformation() const
{
if (m_cachedSimulatorInformationValid)
diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h
index 6c7ae254ab..b2734459d9 100644
--- a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h
+++ b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h
@@ -114,14 +114,12 @@ protected:
private slots:
void proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro);
void updateDeviceConfigurations();
- void invalidateCachedTargetInformation();
void startStopQemu();
void qemuProcessFinished();
private:
void init();
- void updateTarget() const;
void updateSimulatorInformation() const;
const QString cmd(const QString &cmdName) const;
const MaemoToolChain *toolchain() const;
@@ -133,9 +131,7 @@ private:
QMap<QString, QDateTime> &deployTimes,
const QVariantMap &map);
- mutable QString m_executable;
QString m_proFilePath;
- mutable bool m_cachedTargetInformationValid;
mutable QString m_simulator;
mutable QString m_simulatorArgs;
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
index c4cdaa6dab..1420e039ea 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
@@ -112,7 +112,6 @@ QString pathToId(const QString &path)
S60DeviceRunConfiguration::S60DeviceRunConfiguration(Target *parent, const QString &proFilePath) :
RunConfiguration(parent, QLatin1String(S60_DEVICE_RC_ID)),
m_proFilePath(proFilePath),
- m_cachedTargetInformationValid(false),
#ifdef Q_OS_WIN
m_serialPortName(QLatin1String("COM5")),
#else
@@ -126,7 +125,6 @@ S60DeviceRunConfiguration::S60DeviceRunConfiguration(Target *parent, const QStri
S60DeviceRunConfiguration::S60DeviceRunConfiguration(Target *target, S60DeviceRunConfiguration *source) :
RunConfiguration(target, source),
m_proFilePath(source->m_proFilePath),
- m_cachedTargetInformationValid(false),
m_serialPortName(source->m_serialPortName),
m_signingMode(source->m_signingMode),
m_customSignaturePath(source->m_customSignaturePath),
@@ -135,12 +133,6 @@ S60DeviceRunConfiguration::S60DeviceRunConfiguration(Target *target, S60DeviceRu
ctor();
}
-void S60DeviceRunConfiguration::proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro)
-{
- if (m_proFilePath == pro->path())
- invalidateCachedTargetInformation();
-}
-
void S60DeviceRunConfiguration::ctor()
{
if (!m_proFilePath.isEmpty())
@@ -148,11 +140,17 @@ void S60DeviceRunConfiguration::ctor()
else
setDisplayName(tr("QtS60DeviceRunConfiguration"));
- connect(target(), SIGNAL(targetInformationChanged()),
- this, SLOT(invalidateCachedTargetInformation()));
-
connect(qt4Target()->qt4Project(), SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
this, SLOT(proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode*)));
+
+ connect(qt4Target()->qt4Project(), SIGNAL(targetInformationChanged(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
+ this, SLOT(proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode*)));
+}
+
+void S60DeviceRunConfiguration::proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro)
+{
+ if (m_proFilePath == pro->path())
+ emit targetInformationChanged();
}
@@ -246,32 +244,60 @@ void S60DeviceRunConfiguration::setSerialPortName(const QString &name)
QString S60DeviceRunConfiguration::targetName() const
{
- const_cast<S60DeviceRunConfiguration *>(this)->updateTarget();
- return m_targetName;
+ TargetInformation ti = qt4Target()->qt4Project()->rootProjectNode()->targetInformation(m_proFilePath);
+ if (!ti.valid)
+ return QString();
+ return ti.target;
+}
+
+static inline QString fixBaseNameTarget(const QString &in)
+{
+ if (in == QLatin1String("udeb"))
+ return QLatin1String("debug");
+ if (in == QLatin1String("urel"))
+ return QLatin1String("release");
+ return in;
}
QString S60DeviceRunConfiguration::basePackageFilePath() const
{
- const_cast<S60DeviceRunConfiguration *>(this)->updateTarget();
- return m_baseFileName;
+ TargetInformation ti = qt4Target()->qt4Project()->rootProjectNode()->targetInformation(m_proFilePath);
+ if (!ti.valid)
+ return QString();
+ QString baseFileName = ti.workingDir + QLatin1Char('/') + ti.target;
+ baseFileName += QLatin1Char('_') + fixBaseNameTarget(symbianPlatform()) + QLatin1Char('_') + symbianTarget();
+ return baseFileName;
}
QString S60DeviceRunConfiguration::symbianPlatform() const
{
- const_cast<S60DeviceRunConfiguration *>(this)->updateTarget();
- return m_platform;
+ Qt4BuildConfiguration *qt4bc = qt4Target()->qt4Project()->activeTarget()->activeBuildConfiguration();
+ switch (qt4bc->toolChainType()) {
+ case ToolChain::GCCE:
+ case ToolChain::GCCE_GNUPOC:
+ return QLatin1String("gcce");
+ case ToolChain::RVCT_ARMV5:
+ return QLatin1String("armv5");
+ default: // including ToolChain::RVCT_ARMV6_GNUPOC:
+ return QLatin1String("armv6");
+ }
}
QString S60DeviceRunConfiguration::symbianTarget() const
{
- const_cast<S60DeviceRunConfiguration *>(this)->updateTarget();
- return m_target;
+ Qt4BuildConfiguration *qt4bc = qt4Target()->qt4Project()->activeTarget()->activeBuildConfiguration();
+ if (qt4bc->qmakeBuildConfiguration() & QtVersion::DebugBuild)
+ return QString("udeb");
+ else
+ return QString("urel");
}
QString S60DeviceRunConfiguration::packageTemplateFileName() const
{
- const_cast<S60DeviceRunConfiguration *>(this)->updateTarget();
- return m_packageTemplateFileName;
+ TargetInformation ti = qt4Target()->qt4Project()->rootProjectNode()->targetInformation(m_proFilePath);
+ if (!ti.valid)
+ return QString();
+ return ti.workingDir + QLatin1Char('/') + ti.target + QLatin1String("_template.pkg");
}
S60DeviceRunConfiguration::SigningMode S60DeviceRunConfiguration::signingMode() const
@@ -373,8 +399,7 @@ QString S60DeviceRunConfiguration::localExecutableFileName() const
QString S60DeviceRunConfiguration::signedPackage() const
{
- const_cast<S60DeviceRunConfiguration *>(this)->updateTarget();
- return QDir::toNativeSeparators(m_baseFileName + QLatin1String(".sis"));
+ return QDir::toNativeSeparators(basePackageFilePath() + QLatin1String(".sis"));
}
QStringList S60DeviceRunConfiguration::commandLineArguments() const
@@ -387,74 +412,6 @@ void S60DeviceRunConfiguration::setCommandLineArguments(const QStringList &args)
m_commandLineArguments = args;
}
-// Fix up target specification for "make sis":
-// "udeb"-> "debug", "urel" -> "release"
-static inline QString fixBaseNameTarget(const QString &in)
-{
- if (in == QLatin1String("udeb"))
- return QLatin1String("debug");
- if (in == QLatin1String("urel"))
- return QLatin1String("release");
- return in;
-}
-
-void S60DeviceRunConfiguration::updateTarget()
-{
- if (m_cachedTargetInformationValid)
- return;
- Qt4TargetInformation info = qt4Target()->targetInformation(qt4Target()->activeBuildConfiguration(),
- m_proFilePath);
- if (info.error != Qt4TargetInformation::NoError) {
- if (info.error == Qt4TargetInformation::ProParserError) {
- Core::ICore::instance()->messageManager()->printToOutputPane(
- tr("Could not parse %1. The Qt Symbian Device run configuration %2 can not be started.")
- .arg(m_proFilePath).arg(displayName()));
- }
- m_targetName.clear();
- m_baseFileName.clear();
- m_packageTemplateFileName.clear();
- m_platform.clear();
- m_cachedTargetInformationValid = true;
- emit targetInformationChanged();
- return;
- }
-
- m_targetName = info.target;
-
- m_baseFileName = info.workingDir + QLatin1Char('/') + m_targetName;
- m_packageTemplateFileName = m_baseFileName + QLatin1String("_template.pkg");
-
- Qt4BuildConfiguration *qt4bc = qt4Target()->activeBuildConfiguration();
- switch (qt4bc->toolChainType()) {
- case ToolChain::GCCE:
- case ToolChain::GCCE_GNUPOC:
- m_platform = QLatin1String("gcce");
- break;
- case ToolChain::RVCT_ARMV5:
- case ToolChain::RVCT_ARMV5_GNUPOC:
- m_platform = QLatin1String("armv5");
- break;
- default:
- m_platform = QLatin1String("armv6");
- break;
- }
- if (qt4bc->qmakeBuildConfiguration() & QtVersion::DebugBuild)
- m_target = QLatin1String("udeb");
- else
- m_target = QLatin1String("urel");
- m_baseFileName += QLatin1Char('_') + fixBaseNameTarget(m_target)
- + QLatin1Char('-') + m_platform;
- m_cachedTargetInformationValid = true;
- emit targetInformationChanged();
-}
-
-void S60DeviceRunConfiguration::invalidateCachedTargetInformation()
-{
- m_cachedTargetInformationValid = false;
- emit targetInformationChanged();
-}
-
-
// ======== S60DeviceRunConfigurationFactory
S60DeviceRunConfigurationFactory::S60DeviceRunConfigurationFactory(QObject *parent) :
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h
index 5fc034e3c1..f4a0d2c660 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h
@@ -110,7 +110,6 @@ signals:
void serialPortNameChanged();
private slots:
- void invalidateCachedTargetInformation();
void proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro);
protected:
@@ -119,16 +118,9 @@ protected:
private:
ProjectExplorer::ToolChain::ToolChainType toolChainType(ProjectExplorer::BuildConfiguration *configuration) const;
- void updateTarget();
void ctor();
QString m_proFilePath;
- QString m_targetName;
- QString m_platform;
- QString m_target;
- QString m_baseFileName;
- QString m_packageTemplateFileName;
- bool m_cachedTargetInformationValid;
QString m_serialPortName;
SigningMode m_signingMode;
QString m_customSignaturePath;
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp
index 523cbe60ca..b132284fdc 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp
@@ -76,16 +76,14 @@ QString pathToId(const QString &path)
S60EmulatorRunConfiguration::S60EmulatorRunConfiguration(Target *parent, const QString &proFilePath) :
RunConfiguration(parent, QLatin1String(S60_EMULATOR_RC_ID)),
- m_proFilePath(proFilePath),
- m_cachedTargetInformationValid(false)
+ m_proFilePath(proFilePath)
{
ctor();
}
S60EmulatorRunConfiguration::S60EmulatorRunConfiguration(Target *parent, S60EmulatorRunConfiguration *source) :
RunConfiguration(parent, source),
- m_proFilePath(source->m_proFilePath),
- m_cachedTargetInformationValid(false)
+ m_proFilePath(source->m_proFilePath)
{
ctor();
}
@@ -97,11 +95,11 @@ void S60EmulatorRunConfiguration::ctor()
else
setDisplayName(tr("Qt Symbian Emulator RunConfiguration"));
- connect(qt4Target(), SIGNAL(targetInformationChanged()),
- this, SLOT(invalidateCachedTargetInformation()));
-
connect(qt4Target()->qt4Project(), SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
this, SLOT(proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode*)));
+
+ connect(qt4Target()->qt4Project(), SIGNAL(targetInformationChanged(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
+ this, SLOT(proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode*)));
}
@@ -112,10 +110,9 @@ S60EmulatorRunConfiguration::~S60EmulatorRunConfiguration()
void S60EmulatorRunConfiguration::proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro)
{
if (m_proFilePath == pro->path())
- invalidateCachedTargetInformation();
+ emit targetInformationChanged();
}
-
Qt4Target *S60EmulatorRunConfiguration::qt4Target() const
{
return static_cast<Qt4Target *>(target());
@@ -152,28 +149,6 @@ bool S60EmulatorRunConfiguration::fromMap(const QVariantMap &map)
QString S60EmulatorRunConfiguration::executable() const
{
- const_cast<S60EmulatorRunConfiguration *>(this)->updateTarget();
- return m_executable;
-}
-
-void S60EmulatorRunConfiguration::updateTarget()
-{
- if (m_cachedTargetInformationValid)
- return;
- Qt4TargetInformation info = qt4Target()->targetInformation(qt4Target()->activeBuildConfiguration(),
- m_proFilePath);
- if (info.error != Qt4TargetInformation::NoError) {
- if (info.error == Qt4TargetInformation::ProParserError) {
- Core::ICore::instance()->messageManager()->printToOutputPane(
- tr("Could not parse %1. The Qt for Symbian emulator run configuration %2 can not be started.")
- .arg(m_proFilePath).arg(displayName()));
- }
- m_executable.clear();
- m_cachedTargetInformationValid = true;
- emit targetInformationChanged();
- return;
- }
-
Qt4BuildConfiguration *qt4bc = qt4Target()->activeBuildConfiguration();
QtVersion *qtVersion = qt4bc->qtVersion();
QString baseDir = S60Manager::instance()->deviceForQtVersion(qtVersion).epocRoot;
@@ -182,18 +157,13 @@ void S60EmulatorRunConfiguration::updateTarget()
qmakeBuildConfig = "udeb";
baseDir += "/epoc32/release/winscw/" + qmakeBuildConfig;
- m_executable = QDir::toNativeSeparators(
- QDir::cleanPath(baseDir + QLatin1Char('/') + info.target));
- m_executable += QLatin1String(".exe");
-
- m_cachedTargetInformationValid = true;
- emit targetInformationChanged();
-}
+ TargetInformation ti = qt4Target()->qt4Project()->rootProjectNode()->targetInformation(m_proFilePath);
+ if (!ti.valid)
+ return QString();
+ QString executable = QDir::toNativeSeparators(QDir::cleanPath(baseDir + QLatin1Char('/') + ti.target));
+ executable += QLatin1String(".exe");
-void S60EmulatorRunConfiguration::invalidateCachedTargetInformation()
-{
- m_cachedTargetInformationValid = false;
- emit targetInformationChanged();
+ return executable;
}
// ======== S60EmulatorRunConfigurationWidget
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h
index 8191c1b46b..decd95bcff 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h
@@ -75,7 +75,6 @@ signals:
void targetInformationChanged();
private slots:
- void invalidateCachedTargetInformation();
void proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro);
protected:
@@ -87,8 +86,6 @@ private:
void updateTarget();
QString m_proFilePath;
- QString m_executable;
- bool m_cachedTargetInformationValid;
};
class S60EmulatorRunConfigurationWidget : public QWidget
diff --git a/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp b/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp
index 417280f428..4ca104c5ed 100644
--- a/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp
@@ -277,10 +277,11 @@ void Qt4BuildConfiguration::setShadowBuildAndDirectory(bool shadowBuild, const Q
{
if (m_shadowBuild == shadowBuild && m_buildDirectory == buildDirectory)
return;
+
m_shadowBuild = shadowBuild;
m_buildDirectory = buildDirectory;
emit buildDirectoryChanged();
- emit targetInformationChanged();
+ emit proFileEvaluateNeeded(this);
}
ProjectExplorer::ToolChain *Qt4BuildConfiguration::toolChain() const
@@ -340,8 +341,9 @@ void Qt4BuildConfiguration::setQtVersion(QtVersion *version)
return;
m_qtVersionId = version->uniqueId();
+
+ emit proFileEvaluateNeeded(this);
emit qtVersionChanged();
- emit targetInformationChanged();
emit environmentChanged();
}
@@ -351,8 +353,9 @@ void Qt4BuildConfiguration::setToolChainType(ProjectExplorer::ToolChain::ToolCha
m_toolChainType == type)
return;
m_toolChainType = type;
+
+ emit proFileEvaluateNeeded(this);
emit toolChainTypeChanged();
- emit targetInformationChanged();
emit environmentChanged();
}
@@ -371,8 +374,9 @@ void Qt4BuildConfiguration::setQMakeBuildConfiguration(QtVersion::QmakeBuildConf
if (m_qmakeBuildConfiguration == config)
return;
m_qmakeBuildConfiguration = config;
+
+ emit proFileEvaluateNeeded(this);
emit qmakeBuildConfigurationChanged();
- emit targetInformationChanged();
}
void Qt4BuildConfiguration::emitQMakeBuildConfigurationChanged()
diff --git a/src/plugins/qt4projectmanager/qt4buildconfiguration.h b/src/plugins/qt4projectmanager/qt4buildconfiguration.h
index 8886f48e87..074b031059 100644
--- a/src/plugins/qt4projectmanager/qt4buildconfiguration.h
+++ b/src/plugins/qt4projectmanager/qt4buildconfiguration.h
@@ -84,7 +84,8 @@ public:
QtVersion::QmakeBuildConfigs qmakeBuildConfiguration() const;
void setQMakeBuildConfiguration(QtVersion::QmakeBuildConfigs config);
// used by qmake step to notify that the qmake args have changed
- // not really nice
+ // not really nice, the build configuration should save the arguments
+ // since they are needed for reevaluation
void emitQMakeBuildConfigurationChanged();
// used by qmake step to notify that the build directory was initialized
// not really nice
@@ -119,9 +120,9 @@ signals:
/// if those change the qmakebuildconfig
void qmakeBuildConfigurationChanged();
- /// a covenience signal, emitted if either the qtversion, the toolchainType or the qmake build
- /// configuration changed
- void targetInformationChanged();
+ /// emitted if the build configuration changed in a way that
+ /// should trigger a reevaluation of all .pro files
+ void proFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4BuildConfiguration *);
void buildDirectoryInitialized();
diff --git a/src/plugins/qt4projectmanager/qt4nodes.cpp b/src/plugins/qt4projectmanager/qt4nodes.cpp
index ddb802e214..168517d292 100644
--- a/src/plugins/qt4projectmanager/qt4nodes.cpp
+++ b/src/plugins/qt4projectmanager/qt4nodes.cpp
@@ -58,12 +58,12 @@
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
-#include <QtCore/QTimer>
#include <QtGui/QPainter>
#include <QtGui/QMainWindow>
#include <QtGui/QMessageBox>
#include <QtGui/QPushButton>
+#include <qtconcurrent/QtConcurrentTools>
// Static cached data in struct Qt4NodeStaticData providing information and icons
// for file types and the project. Do some magic via qAddPostRoutine()
@@ -453,22 +453,44 @@ struct InternalNode
}
};
-void Qt4PriFileNode::update(ProFile *includeFile, ProFileReader *reader)
+
+QStringList Qt4PriFileNode::baseVPaths(ProFileReader *reader, const QString &projectDir)
{
- Q_ASSERT(includeFile);
- Q_ASSERT(reader);
+ QStringList result;
+ if (!reader)
+ return result;
+ result += reader->absolutePathValues("VPATH", projectDir);
+ result << projectDir; // QMAKE_ABSOLUTE_SOURCE_PATH
+ result += reader->absolutePathValues("DEPENDPATH", projectDir);
+ result.removeDuplicates();
+ return result;
+}
+QStringList Qt4PriFileNode::fullVPaths(const QStringList &baseVPaths, ProFileReader *reader, FileType type, const QString &qmakeVariable, const QString &projectDir)
+{
+ QStringList vPaths;
+ if (!reader)
+ return vPaths;
+ if (type == ProjectExplorer::SourceType)
+ vPaths = reader->absolutePathValues("VPATH_" + qmakeVariable, projectDir);
+ vPaths += baseVPaths;
+ if (type == ProjectExplorer::HeaderType)
+ vPaths += reader->absolutePathValues("INCLUDEPATH", projectDir);
+ vPaths.removeDuplicates();
+ return vPaths;
+}
+
+
+void Qt4PriFileNode::update(ProFile *includeFileExact, ProFileReader *readerExact, ProFile *includeFileCumlative, ProFileReader *readerCumulative)
+{
// add project file node
if (m_fileNodes.isEmpty())
addFileNodes(QList<FileNode*>() << new FileNode(m_projectFilePath, ProjectFileType, false), this);
const QString &projectDir = m_qt4ProFileNode->m_projectDir;
- QStringList baseVPaths;
- baseVPaths += reader->absolutePathValues("VPATH", projectDir);
- baseVPaths << projectDir; // QMAKE_ABSOLUTE_SOURCE_PATH
- baseVPaths += reader->absolutePathValues("DEPENDPATH", projectDir);
- baseVPaths.removeDuplicates();
+ QStringList baseVPathsExact = baseVPaths(readerExact, projectDir);
+ QStringList baseVPathsCumulative = baseVPaths(readerCumulative, projectDir);
const QVector<Qt4NodeStaticData::FileTypeData> &fileTypes = qt4NodeStaticData()->fileTypeData;
@@ -481,14 +503,14 @@ void Qt4PriFileNode::update(ProFile *includeFile, ProFileReader *reader)
QStringList newFilePaths;
foreach (const QString &qmakeVariable, qmakeVariables) {
- QStringList vPaths;
- if (type == ProjectExplorer::SourceType)
- vPaths = reader->absolutePathValues("VPATH_" + qmakeVariable, projectDir);
- vPaths += baseVPaths;
- if (type == ProjectExplorer::HeaderType)
- vPaths += reader->absolutePathValues("INCLUDEPATH", projectDir);
- vPaths.removeDuplicates();
- newFilePaths += reader->absoluteFileValues(qmakeVariable, projectDir, vPaths, includeFile);
+ QStringList vPathsExact = fullVPaths(baseVPathsExact, readerExact, type, qmakeVariable, projectDir);
+ QStringList vPathsCumulative = fullVPaths(baseVPathsCumulative, readerCumulative, type, qmakeVariable, projectDir);
+
+
+ newFilePaths += readerExact->absoluteFileValues(qmakeVariable, projectDir, vPathsExact, includeFileExact);
+ if (readerCumulative)
+ newFilePaths += readerCumulative->absoluteFileValues(qmakeVariable, projectDir, vPathsCumulative, includeFileCumlative);
+
}
newFilePaths.removeDuplicates();
@@ -773,6 +795,16 @@ Qt4ProFileNode *Qt4ProFileNode::findProFileFor(const QString &fileName)
return 0;
}
+TargetInformation Qt4ProFileNode::targetInformation(const QString &fileName)
+{
+ TargetInformation result;
+ Qt4ProFileNode *qt4ProFileNode = findProFileFor(fileName);
+ if (!qt4ProFileNode)
+ return result;
+
+ return qt4ProFileNode->targetInformation();
+}
+
/*!
\class Qt4ProFileNode
Implements abstract ProjectNode class
@@ -781,20 +813,19 @@ Qt4ProFileNode::Qt4ProFileNode(Qt4Project *project,
const QString &filePath,
QObject *parent)
: Qt4PriFileNode(project, this, filePath),
- // own stuff
- m_projectType(InvalidProject)
+ m_projectType(InvalidProject),
+ m_readerExact(0),
+ m_readerCumulative(0)
{
+
if (parent)
setParent(parent);
- m_updateTimer.setInterval(100);
- m_updateTimer.setSingleShot(true);
-
- connect(&m_updateTimer, SIGNAL(timeout()),
- this, SLOT(update()));
-
connect(ProjectExplorer::ProjectExplorerPlugin::instance()->buildManager(), SIGNAL(buildStateChanged(ProjectExplorer::Project*)),
this, SLOT(buildStateChanged(ProjectExplorer::Project*)));
+
+ connect(&m_parseFutureWatcher, SIGNAL(finished()),
+ this, SLOT(applyAsyncEvaluate()));
}
Qt4ProFileNode::~Qt4ProFileNode()
@@ -807,6 +838,16 @@ Qt4ProFileNode::~Qt4ProFileNode()
modelManager->removeEditorSupport(it.value());
delete it.value();
}
+ m_parseFutureWatcher.waitForFinished();
+}
+
+bool Qt4ProFileNode::isParent(Qt4ProFileNode *node)
+{
+ while (node = qobject_cast<Qt4ProFileNode *>(node->parentFolderNode())) {
+ if (node == this)
+ return true;
+ }
+ return false;
}
void Qt4ProFileNode::buildStateChanged(ProjectExplorer::Project *project)
@@ -834,17 +875,97 @@ QStringList Qt4ProFileNode::variableValue(const Qt4Variable var) const
void Qt4ProFileNode::scheduleUpdate()
{
- m_updateTimer.start();
+ m_project->scheduleAsyncUpdate(this);
+}
+
+void Qt4ProFileNode::asyncUpdate()
+{
+ m_project->incrementPendingEvaluateFutures();
+ setupReader();
+ QFuture<bool> future = QtConcurrent::run(&Qt4ProFileNode::asyncEvaluate, this);
+ m_parseFutureWatcher.setFuture(future);
}
void Qt4ProFileNode::update()
{
- ProFileReader *reader = m_project->createProFileReader(this);
- Q_ASSERT(reader);
- if (!reader->readProFile(m_projectFilePath)) {
+ setupReader();
+ bool parserError = evaluate();
+ applyEvaluate(!parserError, false);
+}
+
+void Qt4ProFileNode::setupReader()
+{
+ Q_ASSERT(!m_readerExact);
+ Q_ASSERT(!m_readerCumulative);
+
+ m_readerExact = m_project->createProFileReader(this);
+ m_readerExact->setCumulative(false);
+
+ m_readerCumulative = m_project->createProFileReader(this);
+
+ // Find out what flags we pass on to qmake
+ QStringList addedUserConfigArguments;
+ QStringList removedUserConfigArguments;
+ m_project->activeTarget()->activeBuildConfiguration()->getConfigCommandLineArguments(&addedUserConfigArguments, &removedUserConfigArguments);
+
+ m_readerExact->setConfigCommandLineArguments(addedUserConfigArguments, removedUserConfigArguments);
+ m_readerCumulative->setConfigCommandLineArguments(addedUserConfigArguments, removedUserConfigArguments);
+}
+
+bool Qt4ProFileNode::evaluate()
+{
+ bool parserError = false;
+ if (!m_readerExact->readProFile(m_projectFilePath)) {
m_project->proFileParseError(tr("Error while parsing file %1. Giving up.").arg(m_projectFilePath));
- m_project->destroyProFileReader(reader);
- invalidate();
+ parserError = true;
+ }
+
+ if (!m_readerCumulative->readProFile(m_projectFilePath)) {
+ m_project->proFileParseError(tr("Error while parsing file %1. Giving up.").arg(m_projectFilePath));
+ parserError = true;
+ }
+ return parserError;
+}
+
+void Qt4ProFileNode::asyncEvaluate(QFutureInterface<bool> &fi)
+{
+ bool parserError = evaluate();
+ fi.reportResult(!parserError);
+}
+
+void Qt4ProFileNode::applyAsyncEvaluate()
+{
+ applyEvaluate(m_parseFutureWatcher.result(), true);
+ m_project->decrementPendingEvaluateFutures();
+}
+
+Qt4ProjectType proFileTemplateTypeToProjectType(ProFileEvaluator::TemplateType type)
+{
+ switch (type) {
+ case ProFileEvaluator::TT_Unknown:
+ case ProFileEvaluator::TT_Application:
+ return ApplicationTemplate;
+ case ProFileEvaluator::TT_Library:
+ return LibraryTemplate;
+ case ProFileEvaluator::TT_Script:
+ return ScriptTemplate;
+ case ProFileEvaluator::TT_Subdirs:
+ return SubDirsTemplate;
+ default:
+ return InvalidProject;
+ }
+}
+
+void Qt4ProFileNode::applyEvaluate(bool parseResult, bool async)
+{
+ if (!parseResult || m_project->wasEvaluateCanceled()) {
+ if (m_readerExact)
+ m_project->destroyProFileReader(m_readerExact);
+ if (m_readerCumulative)
+ m_project->destroyProFileReader(m_readerCumulative);
+ m_readerExact = m_readerCumulative = 0;
+ if (!parseResult) // Invalidate
+ invalidate();
return;
}
@@ -852,29 +973,25 @@ void Qt4ProFileNode::update()
qDebug() << "Qt4ProFileNode - updating files for file " << m_projectFilePath;
Qt4ProjectType projectType = InvalidProject;
- switch (reader->templateType()) {
- case ProFileEvaluator::TT_Unknown:
- case ProFileEvaluator::TT_Application: {
- projectType = ApplicationTemplate;
- break;
- }
- case ProFileEvaluator::TT_Library: {
- projectType = LibraryTemplate;
- break;
- }
- case ProFileEvaluator::TT_Script: {
- projectType = ScriptTemplate;
- break;
- }
- case ProFileEvaluator::TT_Subdirs:
- projectType = SubDirsTemplate;
- break;
+ // Check that both are the same if we have both
+ if (m_readerExact->templateType() != m_readerCumulative->templateType()) {
+ // Now what. The only thing which could be reasonable is that someone
+ // changes between template app and library.
+ // Well, we are conservative here for now.
+ // Let's wait until someone complains and look at what they are doing.
+ m_project->destroyProFileReader(m_readerCumulative);
+ m_readerCumulative = 0;
}
+
+ projectType = proFileTemplateTypeToProjectType(m_readerExact->templateType());
+
if (projectType != m_projectType) {
Qt4ProjectType oldType = m_projectType;
// probably all subfiles/projects have changed anyway ...
clear();
m_projectType = projectType;
+ // really emit here? or at the end? Noone is connected to this signal at the moment
+ // so we kind of can ignore that question for now
foreach (NodesWatcher *watcher, watchers())
if (Qt4NodesWatcher *qt4Watcher = qobject_cast<Qt4NodesWatcher*>(watcher))
emit qt4Watcher->projectTypeChanged(this, oldType, projectType);
@@ -886,97 +1003,165 @@ void Qt4ProFileNode::update()
QList<ProjectNode*> existingProjectNodes = subProjectNodes();
- QList<QString> newProjectFiles;
- QHash<QString, ProFile*> includeFiles;
- ProFile *fileForCurrentProject = 0;
- {
- if (projectType == SubDirsTemplate) {
- foreach (const QString &subDirProject, subDirsPaths(reader))
- newProjectFiles << subDirProject;
+ QStringList newProjectFilesExact;
+ QHash<QString, ProFile*> includeFilesExact;
+ ProFile *fileForCurrentProjectExact = 0;
+ if (m_projectType == SubDirsTemplate)
+ newProjectFilesExact = subDirsPaths(m_readerExact);
+ foreach (ProFile *includeFile, m_readerExact->includeFiles()) {
+ if (includeFile->fileName() == m_projectFilePath) { // this file
+ fileForCurrentProjectExact = includeFile;
+ } else {
+ newProjectFilesExact << includeFile->fileName();
+ includeFilesExact.insert(includeFile->fileName(), includeFile);
}
+ }
- foreach (ProFile *includeFile, reader->includeFiles()) {
- if (includeFile->fileName() == m_projectFilePath) { // this file
- fileForCurrentProject = includeFile;
+
+ QStringList newProjectFilesCumlative;
+ QHash<QString, ProFile*> includeFilesCumlative;
+ ProFile *fileForCurrentProjectCumlative = 0;
+ if (m_readerCumulative) {
+ if (m_projectType == SubDirsTemplate)
+ newProjectFilesCumlative = subDirsPaths(m_readerCumulative);
+ foreach (ProFile *includeFile, m_readerCumulative->includeFiles()) {
+ if (includeFile->fileName() == m_projectFilePath) {
+ fileForCurrentProjectCumlative = includeFile;
} else {
- newProjectFiles << includeFile->fileName();
- includeFiles.insert(includeFile->fileName(), includeFile);
+ newProjectFilesCumlative << includeFile->fileName();
+ includeFilesCumlative.insert(includeFile->fileName(), includeFile);
}
}
}
qSort(existingProjectNodes.begin(), existingProjectNodes.end(),
sortNodesByPath);
- qSort(newProjectFiles.begin(), newProjectFiles.end());
+ qSort(newProjectFilesExact);
+ qSort(newProjectFilesCumlative);
QList<ProjectNode*> toAdd;
QList<ProjectNode*> toRemove;
- QList<ProjectNode*>::const_iterator existingNodeIter = existingProjectNodes.constBegin();
- QList<QString>::const_iterator newProjectFileIter = newProjectFiles.constBegin();
- while (existingNodeIter != existingProjectNodes.constEnd()
- && newProjectFileIter != newProjectFiles.constEnd()) {
- if ((*existingNodeIter)->path() < *newProjectFileIter) {
- toRemove << *existingNodeIter;
- ++existingNodeIter;
- } else if ((*existingNodeIter)->path() > *newProjectFileIter) {
- if (ProFile *file = includeFiles.value(*newProjectFileIter)) {
- Qt4PriFileNode *priFileNode
- = new Qt4PriFileNode(m_project, this,
- *newProjectFileIter);
- priFileNode->update(file, reader);
- toAdd << priFileNode;
+ QList<ProjectNode*>::const_iterator existingIt = existingProjectNodes.constBegin();
+ QStringList::const_iterator newExactIt = newProjectFilesExact.constBegin();
+ QStringList::const_iterator newCumlativeIt = newProjectFilesCumlative.constBegin();
+
+ forever {
+ bool existingAtEnd = (existingIt == existingProjectNodes.constEnd());
+ bool newExactAtEnd = (newExactIt == newProjectFilesExact.constEnd());
+ bool newCumlativeAtEnd = (newCumlativeIt == newProjectFilesCumlative.constEnd());
+
+ if (existingAtEnd && newExactAtEnd && newCumlativeAtEnd)
+ break; // we are done, hurray!
+
+ // So this is one giant loop comparing 3 lists at once and sorting the comparision
+ // into mainly 2 buckets: toAdd and toRemove
+ // We need to distinguish between nodes that came from exact and cumalative
+ // parsing, since the update call is diffrent for them
+ // I believe this code to be correct, be careful in changing it
+
+ QString nodeToAdd;
+ if (! existingAtEnd
+ && (newExactAtEnd || (*existingIt)->path() < *newExactIt)
+ && (newCumlativeAtEnd || (*existingIt)->path() < *newCumlativeIt)) {
+ // Remove case
+ toRemove << *existingIt;
+ ++existingIt;
+ } else if(! newExactAtEnd
+ && (existingAtEnd || *newExactIt < (*existingIt)->path())
+ && (newCumlativeAtEnd || *newExactIt < *newCumlativeIt)) {
+ // Mark node from exact for adding
+ nodeToAdd = *newExactIt;
+ ++newExactIt;
+ } else if (! newCumlativeAtEnd
+ && (existingAtEnd || *newCumlativeIt < (*existingIt)->path())
+ && (newExactAtEnd || *newCumlativeIt < *newExactIt)) {
+ // Mark node from cumalative for adding
+ nodeToAdd = *newCumlativeIt;
+ ++newCumlativeIt;
+ } else if (!newExactAtEnd
+ && !newCumlativeAtEnd
+ && (existingAtEnd || *newExactIt < (*existingIt)->path())
+ && (existingAtEnd || *newCumlativeIt < (*existingIt)->path())) {
+ // Mark node from both for adding
+ nodeToAdd = *newExactIt;
+ ++newExactIt;
+ ++newCumlativeIt;
+ } else {
+ Q_ASSERT(!newExactAtEnd || !newCumlativeAtEnd);
+ // update case, figure out which case exactly
+ if (newExactAtEnd) {
+ ++newCumlativeIt;
+ } else if (newCumlativeAtEnd) {
+ ++newExactIt;
+ } else if(*newExactIt < *newCumlativeIt) {
+ ++newExactIt;
+ } else if (*newCumlativeIt < *newExactIt) {
+ ++newCumlativeIt;
} else {
- toAdd << createSubProFileNode(*newProjectFileIter);
+ ++newExactIt;
+ ++newCumlativeIt;
}
- ++newProjectFileIter;
- } else { // *existingNodeIter->path() == *newProjectFileIter
- if (ProFile *file = includeFiles.value(*newProjectFileIter)) {
- Qt4PriFileNode *priFileNode = static_cast<Qt4PriFileNode*>(*existingNodeIter);
- priFileNode->update(file, reader);
+ // Update existingNodeIte
+ ProFile *fileExact = includeFilesCumlative.value((*existingIt)->path());
+ ProFile *fileCumlative = includeFilesCumlative.value((*existingIt)->path());
+ if (fileExact || fileCumlative) {
+ static_cast<Qt4PriFileNode *>(*existingIt)->update(fileExact, m_readerExact, fileCumlative, m_readerCumulative);
+ } else {
+ // We always parse exactly, because we later when async parsing don't know whether
+ // the .pro file is included in this .pro file
+ // So to compare that later parse with the sync one
+ if (async)
+ static_cast<Qt4ProFileNode *>(*existingIt)->asyncUpdate();
+ else
+ static_cast<Qt4ProFileNode *>(*existingIt)->update();
}
+ ++existingIt;
+ // newCumalativeIt and newExactIt are already incremented
- ++existingNodeIter;
- ++newProjectFileIter;
}
- }
- while (existingNodeIter != existingProjectNodes.constEnd()) {
- toRemove << *existingNodeIter;
- ++existingNodeIter;
- }
- while (newProjectFileIter != newProjectFiles.constEnd()) {
- if (ProFile *file = includeFiles.value(*newProjectFileIter)) {
- Qt4PriFileNode *priFileNode
- = new Qt4PriFileNode(m_project, this,
- *newProjectFileIter);
- priFileNode->update(file, reader);
- toAdd << priFileNode;
- } else {
- toAdd << createSubProFileNode(*newProjectFileIter);
+ // If we found something to add do it
+ if (!nodeToAdd.isEmpty()) {
+ ProFile *fileExact = includeFilesCumlative.value(nodeToAdd);
+ ProFile *fileCumlative = includeFilesCumlative.value(nodeToAdd);
+ if (fileExact || fileCumlative) {
+ Qt4PriFileNode *qt4PriFileNode = new Qt4PriFileNode(m_project, this, nodeToAdd);
+ qt4PriFileNode->update(fileExact, m_readerExact, fileCumlative, m_readerCumulative);
+ toAdd << qt4PriFileNode;
+ } else {
+ Qt4ProFileNode *qt4ProFileNode = new Qt4ProFileNode(m_project, nodeToAdd);
+ if (async)
+ qt4ProFileNode->asyncUpdate();
+ else
+ qt4ProFileNode->update();
+ toAdd << qt4ProFileNode;
+ }
}
- ++newProjectFileIter;
- }
+ } // for
if (!toRemove.isEmpty())
removeProjectNodes(toRemove);
if (!toAdd.isEmpty())
addProjectNodes(toAdd);
- Qt4PriFileNode::update(fileForCurrentProject, reader);
+ Qt4PriFileNode::update(fileForCurrentProjectExact, m_readerExact, fileForCurrentProjectCumlative, m_readerCumulative);
+
+ // update TargetInformation
+ m_qt4targetInformation = targetInformation(m_readerExact);
// update other variables
QHash<Qt4Variable, QStringList> newVarValues;
- newVarValues[DefinesVar] = reader->values(QLatin1String("DEFINES"));
- newVarValues[IncludePathVar] = includePaths(reader);
- newVarValues[UiDirVar] = uiDirPaths(reader);
- newVarValues[MocDirVar] = mocDirPaths(reader);
- newVarValues[PkgConfigVar] = reader->values(QLatin1String("PKGCONFIG"));
+ newVarValues[DefinesVar] = m_readerExact->values(QLatin1String("DEFINES"));
+ newVarValues[IncludePathVar] = includePaths(m_readerExact);
+ newVarValues[UiDirVar] = uiDirPaths(m_readerExact);
+ newVarValues[MocDirVar] = mocDirPaths(m_readerExact);
+ newVarValues[PkgConfigVar] = m_readerExact->values(QLatin1String("PKGCONFIG"));
newVarValues[PrecompiledHeaderVar] =
- reader->absoluteFileValues(QLatin1String("PRECOMPILED_HEADER"),
- m_projectDir,
- QStringList() << m_projectDir,
- 0);
+ m_readerExact->absoluteFileValues(QLatin1String("PRECOMPILED_HEADER"),
+ m_projectDir,
+ QStringList() << m_projectDir,
+ 0);
if (m_varValues != newVarValues) {
m_varValues = newVarValues;
@@ -992,7 +1177,12 @@ void Qt4ProFileNode::update()
if (Qt4NodesWatcher *qt4Watcher = qobject_cast<Qt4NodesWatcher*>(watcher))
emit qt4Watcher->proFileUpdated(this);
- m_project->destroyProFileReader(reader);
+ m_project->destroyProFileReader(m_readerExact);
+ if (m_readerCumulative)
+ m_project->destroyProFileReader(m_readerCumulative);
+
+ m_readerExact = 0;
+ m_readerCumulative = 0;
}
namespace {
@@ -1124,13 +1314,6 @@ QStringList Qt4ProFileNode::updateUiFiles()
return toUpdate;
}
-Qt4ProFileNode *Qt4ProFileNode::createSubProFileNode(const QString &path)
-{
- Qt4ProFileNode *subProFileNode = new Qt4ProFileNode(m_project, path);
- subProFileNode->update();
- return subProFileNode;
-}
-
QStringList Qt4ProFileNode::uiDirPaths(ProFileReader *reader) const
{
QStringList candidates = reader->absolutePathValues(QLatin1String("UI_DIR"),
@@ -1205,6 +1388,73 @@ QStringList Qt4ProFileNode::subDirsPaths(ProFileReader *reader) const
return subProjectPaths;
}
+TargetInformation Qt4ProFileNode::targetInformation(ProFileReader *reader) const
+{
+ TargetInformation result;
+ if (!reader)
+ return result;
+
+ const QString baseDir = buildDir();
+ // qDebug() << "base build dir is:"<<baseDir;
+
+ // Working Directory
+ if (reader->contains("DESTDIR")) {
+ //qDebug() << "reader contains destdir:" << reader->value("DESTDIR");
+ result.workingDir = reader->value("DESTDIR");
+ if (QDir::isRelativePath(result.workingDir)) {
+ result.workingDir = baseDir + QLatin1Char('/') + result.workingDir;
+ //qDebug() << "was relative and expanded to" << result.workingDir;
+ }
+ } else {
+ //qDebug() << "reader didn't contain DESTDIR, setting to " << baseDir;
+ result.workingDir = baseDir;
+ }
+
+ result.target = reader->value("TARGET");
+ if (result.target.isEmpty())
+ result.target = QFileInfo(m_projectFilePath).baseName();
+
+#if defined (Q_OS_MAC)
+ if (reader->values("CONFIG").contains("app_bundle")) {
+ result.workingDir += QLatin1Char('/')
+ + result.target
+ + QLatin1String(".app/Contents/MacOS");
+ }
+#endif
+
+ result.workingDir = QDir::cleanPath(result.workingDir);
+
+ QString wd = result.workingDir;
+ if (!reader->contains("DESTDIR")
+ && reader->values("CONFIG").contains("debug_and_release")
+ && reader->values("CONFIG").contains("debug_and_release_target")) {
+ // If we don't have a destdir and debug and release is set
+ // then the executable is in a debug/release folder
+ //qDebug() << "reader has debug_and_release_target";
+
+ // Hmm can we find out whether it's debug or release in a saner way?
+ // Theoretically it's in CONFIG
+ QString qmakeBuildConfig = "release";
+ if (m_project->activeTarget()->activeBuildConfiguration()->qmakeBuildConfiguration() & QtVersion::DebugBuild)
+ qmakeBuildConfig = "debug";
+ wd += QLatin1Char('/') + qmakeBuildConfig;
+ }
+
+ result.executable = QDir::cleanPath(wd + QLatin1Char('/') + result.target);
+ //qDebug() << "##### updateTarget sets:" << result.workingDir << result.executable;
+
+#if defined (Q_OS_WIN)
+ result.executable += QLatin1String(".exe");
+#endif
+ result.valid = true;
+ return result;
+}
+
+TargetInformation Qt4ProFileNode::targetInformation()
+{
+ return m_qt4targetInformation;
+}
+
QString Qt4ProFileNode::buildDir() const
{
const QDir srcDirRoot = QFileInfo(m_project->rootProjectNode()->path()).absoluteDir();
diff --git a/src/plugins/qt4projectmanager/qt4nodes.h b/src/plugins/qt4projectmanager/qt4nodes.h
index cd830960a4..ea9216a617 100644
--- a/src/plugins/qt4projectmanager/qt4nodes.h
+++ b/src/plugins/qt4projectmanager/qt4nodes.h
@@ -36,9 +36,9 @@
#include <QtCore/QHash>
#include <QtCore/QStringList>
-#include <QtCore/QTimer>
#include <QtCore/QDateTime>
#include <QtCore/QMap>
+#include <QtCore/QFutureWatcher>
// defined in proitems.h
QT_BEGIN_NAMESPACE
@@ -127,7 +127,8 @@ class Qt4PriFileNode : public ProjectExplorer::ProjectNode
public:
Qt4PriFileNode(Qt4Project *project, Qt4ProFileNode* qt4ProFileNode, const QString &filePath);
- void update(ProFile *includeFile, ProFileReader *reader);
+ void update(ProFile *includeFileExact, ProFileReader *readerExact, ProFile *includeFileCumlative, ProFileReader *readerCumalative);
+
// ProjectNode interface
QList<ProjectAction> supportedActions() const;
@@ -169,6 +170,8 @@ private:
void save(const QStringList &lines);
bool priFileWritable(const QString &path);
bool saveModifiedEditors();
+ QStringList baseVPaths(ProFileReader *reader, const QString &projectDir);
+ QStringList fullVPaths(const QStringList &baseVPaths, ProFileReader *reader, FileType type, const QString &qmakeVariable, const QString &projectDir);
Qt4Project *m_project;
Qt4ProFileNode *m_qt4ProFileNode;
@@ -185,6 +188,38 @@ private:
friend struct InternalNode;
};
+struct TargetInformation
+{
+ bool valid;
+ QString workingDir;
+ QString target;
+ QString executable;
+ bool operator==(const TargetInformation &other) const
+ {
+ return workingDir == other.workingDir
+ && target == other.target
+ && executable == other.executable
+ && valid == valid;
+ }
+ bool operator!=(const TargetInformation &other) const
+ {
+ return !(*this == other);
+ }
+
+ TargetInformation()
+ : valid(false)
+ {}
+
+ TargetInformation(const TargetInformation &other)
+ : valid(other.valid),
+ workingDir(other.workingDir),
+ target(other.target),
+ executable(other.executable)
+ {
+ }
+
+};
+
// Implements ProjectNode for qt4 pro files
class Qt4ProFileNode : public Qt4PriFileNode
{
@@ -196,6 +231,8 @@ public:
QObject *parent = 0);
~Qt4ProFileNode();
+ bool isParent(Qt4ProFileNode *node);
+
bool hasBuildTargets() const;
Qt4ProjectType projectType() const;
@@ -211,33 +248,50 @@ public:
static QString uiHeaderFile(const QString &uiDir, const QString &formFile);
Qt4ProFileNode *findProFileFor(const QString &string);
+ TargetInformation targetInformation(const QString &fileName);
+ TargetInformation targetInformation();
-public slots:
- void scheduleUpdate();
void update();
+ void scheduleUpdate();
+
+public slots:
+ void asyncUpdate();
+
private slots:
void buildStateChanged(ProjectExplorer::Project*);
+ void applyAsyncEvaluate();
private:
+ void setupReader();
+ bool evaluate();
+ void applyEvaluate(bool parseResult, bool async);
+
+ void asyncEvaluate(QFutureInterface<bool> &fi);
+
typedef QHash<Qt4Variable, QStringList> Qt4VariablesHash;
void createUiCodeModelSupport();
QStringList updateUiFiles();
- Qt4ProFileNode *createSubProFileNode(const QString &path);
QStringList uiDirPaths(ProFileReader *reader) const;
QStringList mocDirPaths(ProFileReader *reader) const;
QStringList includePaths(ProFileReader *reader) const;
QStringList subDirsPaths(ProFileReader *reader) const;
+ TargetInformation targetInformation(ProFileReader *reader) const;
void invalidate();
Qt4ProjectType m_projectType;
Qt4VariablesHash m_varValues;
- QTimer m_updateTimer;
QMap<QString, QDateTime> m_uitimestamps;
+ TargetInformation m_qt4targetInformation;
friend class Qt4NodeHierarchy;
+
+ // Async stuff
+ QFutureWatcher<bool> m_parseFutureWatcher;
+ ProFileReader *m_readerExact;
+ ProFileReader *m_readerCumulative;
};
class Qt4NodesWatcher : public ProjectExplorer::NodesWatcher
diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp
index 4e4292b014..68b7dc9b37 100644
--- a/src/plugins/qt4projectmanager/qt4project.cpp
+++ b/src/plugins/qt4projectmanager/qt4project.cpp
@@ -44,6 +44,7 @@
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
#include <coreplugin/coreconstants.h>
+#include <coreplugin/progressmanager/progressmanager.h>
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/customexecutablerunconfiguration.h>
#include <projectexplorer/nodesvisitor.h>
@@ -232,21 +233,16 @@ Qt4Project::Qt4Project(Qt4Manager *manager, const QString& fileName) :
m_fileInfo(new Qt4ProjectFile(this, fileName, this)),
m_isApplication(true),
m_projectFiles(new Qt4ProjectFiles),
- m_proFileOption(0)
+ m_proFileOption(0),
+ m_asyncUpdateFutureInterface(0),
+ m_pendingEvaluateFuturesCount(0),
+ m_asyncUpdateState(NoState),
+ m_cancelEvaluate(false)
{
- m_updateCodeModelTimer.setSingleShot(true);
- m_updateCodeModelTimer.setInterval(20);
- connect(&m_updateCodeModelTimer, SIGNAL(timeout()), this, SLOT(updateCodeModel()));
+ m_asyncUpdateTimer.setSingleShot(true);
+ m_asyncUpdateTimer.setInterval(3000);
+ connect(&m_asyncUpdateTimer, SIGNAL(timeout()), this, SLOT(asyncUpdate()));
- m_rootProjectNode = new Qt4ProFileNode(this, m_fileInfo->fileName(), this);
- m_rootProjectNode->registerWatcher(m_nodesWatcher);
-
- connect(this, SIGNAL(addedTarget(ProjectExplorer::Target*)),
- this, SLOT(onAddedTarget(ProjectExplorer::Target*)));
-
- // Setup Qt versions supported (== possible targets).
- connect(QtVersionManager::instance(), SIGNAL(qtVersionsChanged(QList<int>)),
- this, SLOT(qtVersionsChanged()));
setSupportedTargetIds(QtVersionManager::instance()->supportedTargetIds());
}
@@ -295,31 +291,30 @@ bool Qt4Project::fromMap(const QVariantMap &map)
Q_ASSERT(activeTarget());
Q_ASSERT(activeTarget()->activeBuildConfiguration());
+ m_manager->registerProject(this);
+
+ m_rootProjectNode = new Qt4ProFileNode(this, m_fileInfo->fileName(), this);
+ m_rootProjectNode->registerWatcher(m_nodesWatcher);
+
update();
updateFileList();
// This might be incorrect, need a full update
- scheduleUpdateCodeModel(rootProjectNode());
+ updateCodeModel();
- // Now connect
- connect(m_nodesWatcher, SIGNAL(foldersAdded()), this, SLOT(updateFileList()));
- connect(m_nodesWatcher, SIGNAL(foldersRemoved()), this, SLOT(updateFileList()));
- connect(m_nodesWatcher, SIGNAL(filesAdded()), this, SLOT(updateFileList()));
- connect(m_nodesWatcher, SIGNAL(filesRemoved()), this, SLOT(updateFileList()));
- connect(m_nodesWatcher, SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *)),
- this, SLOT(scheduleUpdateCodeModel(Qt4ProjectManager::Internal::Qt4ProFileNode *)));
+ checkForNewApplicationProjects();
+ checkForDeletedApplicationProjects();
- connect(m_nodesWatcher, SIGNAL(foldersAboutToBeAdded(FolderNode *, const QList<FolderNode*> &)),
- this, SLOT(foldersAboutToBeAdded(FolderNode *, const QList<FolderNode*> &)));
- connect(m_nodesWatcher, SIGNAL(foldersAdded()), this, SLOT(checkForNewApplicationProjects()));
+ foreach (Target *t, targets())
+ onAddedTarget(t);
- connect(m_nodesWatcher, SIGNAL(foldersRemoved()), this, SLOT(checkForDeletedApplicationProjects()));
+ setSupportedTargetIds(QtVersionManager::instance()->supportedTargetIds());
- connect(m_nodesWatcher, SIGNAL(projectTypeChanged(Qt4ProjectManager::Internal::Qt4ProFileNode *,
- const Qt4ProjectManager::Internal::Qt4ProjectType,
- const Qt4ProjectManager::Internal::Qt4ProjectType)),
- this, SLOT(projectTypeChanged(Qt4ProjectManager::Internal::Qt4ProFileNode *,
- const Qt4ProjectManager::Internal::Qt4ProjectType,
- const Qt4ProjectManager::Internal::Qt4ProjectType)));
+ // Setup Qt versions supported (== possible targets).
+ connect(this, SIGNAL(addedTarget(ProjectExplorer::Target*)),
+ this, SLOT(onAddedTarget(ProjectExplorer::Target*)));
+
+ connect(QtVersionManager::instance(), SIGNAL(qtVersionsChanged(QList<int>)),
+ this, SLOT(qtVersionsChanged()));
connect(m_nodesWatcher, SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *)),
this, SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *)));
@@ -327,22 +322,6 @@ bool Qt4Project::fromMap(const QVariantMap &map)
connect(this, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
this, SLOT(activeTargetWasChanged()));
- // Add RunConfigurations to targets:
- // If we have no application targets then add a empty CustomExecutableRC as
- // it will ask the user for an executable to run.
- QStringList pathes = applicationProFilePathes();
- foreach (Target *t, targets()) {
- Qt4Target * qt4target = static_cast<Qt4Target*>(t);
- if (t->runConfigurations().isEmpty()) {
- if (pathes.isEmpty()) {
- t->addRunConfiguration(new ProjectExplorer::CustomExecutableRunConfiguration(t));
- } else {
- foreach (const QString &path, pathes)
- qt4target->addRunConfigurationForPath(path);
- }
- }
- }
-
return true;
}
@@ -377,28 +356,46 @@ namespace {
};
}
-void Qt4Project::scheduleUpdateCodeModel(Qt4ProjectManager::Internal::Qt4ProFileNode *pro)
-{
- m_updateCodeModelTimer.start();
- m_proFilesForCodeModelUpdate.append(pro);
-}
-
-void Qt4Project::changeTargetInformation()
-{
- Qt4Target *t(qobject_cast<Qt4Target *>(sender()));
- if (t && t == activeTarget())
- emit targetInformationChanged();
-}
-
void Qt4Project::onAddedTarget(ProjectExplorer::Target *t)
{
Q_ASSERT(t);
- connect(t, SIGNAL(targetInformationChanged()),
- this, SLOT(changeTargetInformation()));
Qt4Target *qt4target = qobject_cast<Qt4Target *>(t);
Q_ASSERT(qt4target);
connect(qt4target, SIGNAL(buildDirectoryInitialized()),
this, SIGNAL(buildDirectoryInitialized()));
+ connect(qt4target, SIGNAL(proFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4Target*)),
+ this, SLOT(proFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4Target*)));
+}
+
+void Qt4Project::proFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4Target *target)
+{
+ 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);
}
void Qt4Project::updateCodeModel()
@@ -406,6 +403,8 @@ void Qt4Project::updateCodeModel()
if (debug)
qDebug()<<"Qt4Project::updateCodeModel()";
+ // TODO cancel still running indexing
+
if (!activeTarget() || !activeTarget()->activeBuildConfiguration())
return;
@@ -424,64 +423,35 @@ void Qt4Project::updateCodeModel()
QByteArray predefinedMacros;
ToolChain *tc = activeBC->toolChain();
- QList<HeaderPath> allHeaderPaths;
if (tc) {
predefinedMacros = tc->predefinedMacros();
- allHeaderPaths = tc->systemHeaderPaths();
//qDebug()<<"Predefined Macros";
//qDebug()<<tc->predefinedMacros();
//qDebug()<<"";
//qDebug()<<"System Header Paths";
//foreach(const HeaderPath &hp, tc->systemHeaderPaths())
// qDebug()<<hp.path();
- }
- foreach (const HeaderPath &headerPath, allHeaderPaths) {
- if (headerPath.kind() == HeaderPath::FrameworkHeaderPath)
- predefinedFrameworkPaths.append(headerPath.path());
- else
- predefinedIncludePaths.append(headerPath.path());
- }
-
- const QHash<QString, QString> versionInfo = activeBC->qtVersion()->versionInfo();
- const QString newQtIncludePath = versionInfo.value(QLatin1String("QT_INSTALL_HEADERS"));
- predefinedIncludePaths.append(newQtIncludePath);
- QDir dir(newQtIncludePath);
- foreach (QFileInfo info, dir.entryInfoList(QDir::Dirs)) {
- const QString path = info.fileName();
-
- if (path == QLatin1String("Qt"))
- continue; // skip $QT_INSTALL_HEADERS/Qt. There's no need to include it.
- else if (path.startsWith(QLatin1String("Qt")) || path == QLatin1String("phonon"))
- predefinedIncludePaths.append(info.absoluteFilePath());
+ foreach (const HeaderPath &headerPath, tc->systemHeaderPaths()) {
+ if (headerPath.kind() == HeaderPath::FrameworkHeaderPath)
+ predefinedFrameworkPaths.append(headerPath.path());
+ else
+ predefinedIncludePaths.append(headerPath.path());
+ }
}
FindQt4ProFiles findQt4ProFiles;
QList<Qt4ProFileNode *> proFiles = findQt4ProFiles(rootProjectNode());
- QByteArray definedMacros = predefinedMacros;
- QStringList allIncludePaths = predefinedIncludePaths;
+ QByteArray allDefinedMacros = predefinedMacros;
+ QStringList allIncludePaths;
QStringList allFrameworkPaths = predefinedFrameworkPaths;
QStringList allPrecompileHeaders;
-#ifdef Q_OS_MAC
- const QString newQtLibsPath = versionInfo.value(QLatin1String("QT_INSTALL_LIBS"));
- allFrameworkPaths.append(newQtLibsPath);
- // put QtXXX.framework/Headers directories in include path since that qmake's behavior
- QDir frameworkDir(newQtLibsPath);
- foreach (QFileInfo info, frameworkDir.entryInfoList(QDir::Dirs)) {
- if (! info.fileName().startsWith(QLatin1String("Qt")))
- continue;
- allIncludePaths.append(info.absoluteFilePath()+"/Headers");
- }
-#endif
-
-
// Collect per .pro file information
m_codeModelInfo.clear();
foreach (Qt4ProFileNode *pro, proFiles) {
Internal::CodeModelInfo info;
info.defines = predefinedMacros;
- info.includes = predefinedIncludePaths;
info.frameworkPaths = predefinedFrameworkPaths;
info.precompiledHeader = pro->variableValue(PrecompiledHeaderVar);
@@ -489,22 +459,23 @@ void Qt4Project::updateCodeModel()
allPrecompileHeaders.append(info.precompiledHeader);
// Add custom defines
+
foreach (const QString &def, pro->variableValue(DefinesVar)) {
- definedMacros += "#define ";
+ allDefinedMacros += "#define ";
info.defines += "#define ";
const int index = def.indexOf(QLatin1Char('='));
if (index == -1) {
- definedMacros += def.toLatin1();
- definedMacros += " 1\n";
+ allDefinedMacros += def.toLatin1();
+ allDefinedMacros += " 1\n";
info.defines += def.toLatin1();
info.defines += " 1\n";
} else {
const QString name = def.left(index);
const QString value = def.mid(index + 1);
- definedMacros += name.toLatin1();
- definedMacros += ' ';
- definedMacros += value.toLocal8Bit();
- definedMacros += '\n';
+ allDefinedMacros += name.toLatin1();
+ allDefinedMacros += ' ';
+ allDefinedMacros += value.toLocal8Bit();
+ allDefinedMacros += '\n';
info.defines += name.toLatin1();
info.defines += ' ';
info.defines += value.toLocal8Bit();
@@ -520,10 +491,7 @@ void Qt4Project::updateCodeModel()
info.includes.append(includePath);
}
-#if 0
- // Disable for now, we need better .pro parsing first
- // Also the information gathered here isn't used
- // by the codemodel yet
+#if 0 // Experimental PKGCONFIG support
{ // Pkg Config support
QStringList pkgConfig = pro->variableValue(PkgConfigVar);
if (!pkgConfig.isEmpty()) {
@@ -541,8 +509,14 @@ void Qt4Project::updateCodeModel()
// Add mkspec directory
info.includes.append(activeBC->qtVersion()->mkspecPath());
+ info.includes.append(predefinedIncludePaths);
- info.frameworkPaths = allFrameworkPaths;
+// qDebug()<<"Dumping code model information";
+// qDebug()<<"for .pro file"<< pro->path();
+// qDebug()<<info.defines;
+// qDebug()<<info.includes;
+// qDebug()<<info.frameworkPaths;
+// qDebug()<<"\n";
#if 0
//Disable for now, we need better .pro file parsing first, and code model
@@ -564,15 +538,7 @@ void Qt4Project::updateCodeModel()
// Add mkspec directory
allIncludePaths.append(activeBC->qtVersion()->mkspecPath());
- // Dump things out
- // This is debugging output...
-// qDebug()<<"CodeModel stuff:";
-// QMap<QString, CodeModelInfo>::const_iterator it, end;
-// end = m_codeModelInfo.constEnd();
-// for(it = m_codeModelInfo.constBegin(); it != end; ++it) {
-// qDebug()<<"File: "<<it.key()<<"\nIncludes:"<<it.value().includes<<"\nDefines"<<it.value().defines<<"\n";
-// }
-// qDebug()<<"----------------------------";
+ allIncludePaths.append(predefinedIncludePaths);
QStringList files;
files += m_projectFiles->files[HeaderType];
@@ -584,37 +550,34 @@ void Qt4Project::updateCodeModel()
//qDebug()<<"Using precompiled header"<<allPrecompileHeaders;
- if (pinfo.defines == predefinedMacros
+ bool fileList = equalFileList(pinfo.sourceFiles, files);
+
+ if (pinfo.defines == allDefinedMacros
&& pinfo.includePaths == allIncludePaths
&& pinfo.frameworkPaths == allFrameworkPaths
- && pinfo.sourceFiles == files
+ && fileList
&& pinfo.precompiledHeaders == allPrecompileHeaders) {
// Nothing to update...
} else {
- if (pinfo.defines != predefinedMacros ||
- pinfo.includePaths != allIncludePaths ||
- pinfo.frameworkPaths != allFrameworkPaths) {
+ pinfo.sourceFiles.clear();
+ if (pinfo.defines != allDefinedMacros
+ || pinfo.includePaths != allIncludePaths
+ || pinfo.frameworkPaths != allFrameworkPaths
+ || pinfo.precompiledHeaders != allPrecompileHeaders)
+ {
pinfo.sourceFiles.append(QLatin1String("<configuration>"));
}
-
- pinfo.defines = predefinedMacros;
- // pinfo.defines += definedMacros; // ### FIXME: me
+ //pinfo.defines = predefinedMacros;
+ pinfo.defines = allDefinedMacros;
pinfo.includePaths = allIncludePaths;
pinfo.frameworkPaths = allFrameworkPaths;
- pinfo.sourceFiles = files;
+ pinfo.sourceFiles += files;
pinfo.precompiledHeaders = allPrecompileHeaders;
modelmanager->updateProjectInfo(pinfo);
modelmanager->updateSourceFiles(pinfo.sourceFiles);
}
-
- // TODO use this information
- // These are the pro files that were actually changed
- // if the list is empty we are at the initial stage
- // TODO check that this also works if pro files get added
- // and removed
- m_proFilesForCodeModelUpdate.clear();
}
void Qt4Project::qtVersionsChanged()
@@ -654,8 +617,167 @@ QStringList Qt4Project::frameworkPaths(const QString &fileName) const
// */
void Qt4Project::update()
{
+ qDebug()<<"Doing sync update";
m_rootProjectNode->update();
- //updateCodeModel();
+ qDebug()<<"State is now Base";
+ m_asyncUpdateState = Base;
+}
+
+void Qt4Project::scheduleAsyncUpdate(Qt4ProFileNode *node)
+{
+ qDebug()<<"schduleAsyncUpdate (node)";
+ Q_ASSERT(m_asyncUpdateState != NoState);
+
+ if (m_cancelEvaluate) {
+ qDebug()<<" Already canceling, nothing to do";
+ // 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;
+ }
+
+ if (m_asyncUpdateState == AsyncFullUpdatePending) {
+ // Just postpone
+ qDebug()<<" full update pending, restarting timer";
+ m_asyncUpdateTimer.start();
+ } else if (m_asyncUpdateState == AsyncPartialUpdatePending
+ || m_asyncUpdateState == Base) {
+ qDebug()<<" adding node to async update list, setting state to AsyncPartialUpdatePending";
+ // Add the node
+ m_asyncUpdateState = AsyncPartialUpdatePending;
+
+ QList<Internal::Qt4ProFileNode *>::iterator it;
+ bool add = true;
+ qDebug()<<"scheduleAsyncUpdate();"<<m_partialEvaluate.size()<<"nodes";
+ int count = 0;
+ 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
+ add = false;
+ break;
+ } else if ((*it)->isParent(node)) { // The node is the parent of a child already in the list
+ it = m_partialEvaluate.erase(it);
+ } 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
+ qDebug()<<" Async update in progress, scheduling new one afterwards";
+ scheduleAsyncUpdate();
+ }
+}
+
+void Qt4Project::scheduleAsyncUpdate()
+{
+ qDebug()<<"scheduleAsyncUpdate";
+ Q_ASSERT(m_asyncUpdateState != NoState);
+ if (m_cancelEvaluate) { // we are in progress of canceling
+ // and will start the evaluation after that
+ qDebug()<<" canceling is in progress, doing nothing";
+ return;
+ }
+ if (m_asyncUpdateState == AsyncUpdateInProgress) {
+ qDebug()<<" update in progress, canceling and setting state to full update pending";
+ m_cancelEvaluate = true;
+ m_asyncUpdateState = AsyncFullUpdatePending;
+ return;
+ }
+
+ qDebug()<<" starting timer for full update, setting state to full update pending";
+ m_partialEvaluate.clear();
+ m_asyncUpdateState = AsyncFullUpdatePending;
+ m_asyncUpdateTimer.start();
+}
+
+
+void Qt4Project::incrementPendingEvaluateFutures()
+{
+ ++m_pendingEvaluateFuturesCount;
+ qDebug()<<"incrementPendingEvaluateFutures to"<<m_pendingEvaluateFuturesCount;
+
+ m_asyncUpdateFutureInterface->setProgressRange(m_asyncUpdateFutureInterface->progressMinimum(),
+ m_asyncUpdateFutureInterface->progressMaximum() + 1);
+}
+
+void Qt4Project::decrementPendingEvaluateFutures()
+{
+ --m_pendingEvaluateFuturesCount;
+
+ qDebug()<<"decrementPendingEvaluateFutures to"<<m_pendingEvaluateFuturesCount;
+
+ m_asyncUpdateFutureInterface->setProgressValue(m_asyncUpdateFutureInterface->progressValue() + 1);
+ if (m_pendingEvaluateFuturesCount == 0) {
+ qDebug()<<" WOHOO, no pending futures, cleaning up";
+ // We are done!
+ qDebug()<<" reporting finished";
+ m_asyncUpdateFutureInterface->reportFinished();
+ delete m_asyncUpdateFutureInterface;
+ m_asyncUpdateFutureInterface = 0;
+ m_cancelEvaluate = false;
+
+ // After beeing done, we need to call:
+ updateFileList();
+ updateCodeModel();
+ checkForNewApplicationProjects();
+ checkForDeletedApplicationProjects();
+
+ // TODO clear the profile cache ?
+ if (m_asyncUpdateState == AsyncFullUpdatePending || m_asyncUpdateState == AsyncPartialUpdatePending) {
+ qDebug()<<" Oh update is pending start the timer";
+ m_asyncUpdateTimer.start();
+ } else {
+ qDebug()<<" Setting state to Base";
+ m_asyncUpdateState = Base;
+ }
+ }
+}
+
+bool Qt4Project::wasEvaluateCanceled()
+{
+ return m_cancelEvaluate;
+}
+
+void Qt4Project::asyncUpdate()
+{
+ qDebug()<<"async update, timer expired, doing now";
+ Q_ASSERT(!m_asyncUpdateFutureInterface);
+ m_asyncUpdateFutureInterface = new QFutureInterface<void>();
+
+ Core::ProgressManager *progressManager = Core::ICore::instance()->progressManager();
+
+ progressManager->addTask(m_asyncUpdateFutureInterface->future(), tr("Evaluate"), Constants::PROFILE_EVALUATE);
+ qDebug()<<" adding task";
+
+ m_asyncUpdateFutureInterface->setProgressRange(0, 0);
+ m_asyncUpdateFutureInterface->reportStarted();
+
+ if (m_asyncUpdateState == AsyncFullUpdatePending) {
+ qDebug()<<" full update, starting with root node";
+ m_rootProjectNode->asyncUpdate();
+ } else {
+ qDebug()<<" partial update,"<<m_partialEvaluate.size()<<"nodes to update";
+ foreach(Qt4ProFileNode *node, m_partialEvaluate)
+ node->asyncUpdate();
+ }
+
+ m_partialEvaluate.clear();
+ qDebug()<<" Setting state to AsyncUpdateInProgress";
+ m_asyncUpdateState = AsyncUpdateInProgress;
}
/*!
@@ -666,11 +788,6 @@ bool Qt4Project::isApplication() const
return m_isApplication;
}
-ProjectExplorer::ProjectExplorerPlugin *Qt4Project::projectExplorer() const
-{
- return m_manager->projectExplorer();
-}
-
ProjectExplorer::IProjectManager *Qt4Project::projectManager() const
{
return m_manager;
@@ -773,6 +890,7 @@ ProFileReader *Qt4Project::createProFileReader(Qt4ProFileNode *qt4ProFileNode)
m_proFileOption->properties = version->versionInfo();
}
+ ProFileCacheManager::instance()->incRefCount();
m_proFileOption->cache = ProFileCacheManager::instance()->cache();
}
++m_proFileOptionRefCnt;
@@ -797,6 +915,7 @@ void Qt4Project::destroyProFileReader(ProFileReader *reader)
delete m_proFileOption;
m_proFileOption = 0;
+ ProFileCacheManager::instance()->decRefCount();
}
}
@@ -830,23 +949,12 @@ void Qt4Project::collectApplicationProFiles(QList<Qt4ProFileNode *> &list, Qt4Pr
}
}
-void Qt4Project::foldersAboutToBeAdded(FolderNode *, const QList<FolderNode*> &nodes)
-{
- QList<Qt4ProFileNode *> list;
- foreach (FolderNode *node, nodes) {
- Qt4ProFileNode *qt4ProFileNode = qobject_cast<Qt4ProFileNode *>(node);
- if (qt4ProFileNode)
- collectApplicationProFiles(list, qt4ProFileNode);
- }
- m_applicationProFileChange = list;
-}
-
void Qt4Project::checkForNewApplicationProjects()
{
// Check all new project nodes
// against all runConfigurations in all targets.
- foreach (Qt4ProFileNode *qt4proFile, m_applicationProFileChange) {
+ foreach (Qt4ProFileNode *qt4proFile, applicationProFiles()) {
foreach (Target *target, targets()) {
Qt4Target *qt4Target = static_cast<Qt4Target *>(target);
bool found = false;
@@ -879,7 +987,6 @@ void Qt4Project::checkForDeletedApplicationProjects()
if (Qt4RunConfiguration *qt4rc = qobject_cast<Qt4RunConfiguration *>(rc)) {
if (!paths.contains(qt4rc->proFilePath())) {
removeList.append(qt4rc);
- // qDebug()<<"Removing runConfiguration for "<<qt4rc->proFilePath();
}
}
}
@@ -922,31 +1029,12 @@ QStringList Qt4Project::applicationProFilePathes(const QString &prepend) const
return proFiles;
}
-void Qt4Project::projectTypeChanged(Qt4ProFileNode *node, const Qt4ProjectType oldType, const Qt4ProjectType newType)
-{
- if (oldType == Internal::ApplicationTemplate
- || oldType == Internal::ScriptTemplate) {
- // check whether we need to delete a Run Configuration
- checkForDeletedApplicationProjects();
- }
-
- if (newType == Internal::ApplicationTemplate
- || newType == Internal::ScriptTemplate) {
- // add a new Run Configuration
- m_applicationProFileChange.clear();
- m_applicationProFileChange.append(node);
- checkForNewApplicationProjects();
- }
-}
-
void Qt4Project::activeTargetWasChanged()
{
- emit targetInformationChanged();
-
if (!activeTarget())
return;
- update();
+ scheduleAsyncUpdate();
}
bool Qt4Project::hasSubNode(Qt4PriFileNode *root, const QString &path)
diff --git a/src/plugins/qt4projectmanager/qt4project.h b/src/plugins/qt4projectmanager/qt4project.h
index d3d2d5bb40..f4d9d48cea 100644
--- a/src/plugins/qt4projectmanager/qt4project.h
+++ b/src/plugins/qt4projectmanager/qt4project.h
@@ -51,6 +51,7 @@
#include <QtCore/QMap>
#include <QtGui/QDirModel>
#include <QtCore/QFutureInterface>
+#include <QtCore/QTimer>
QT_BEGIN_NAMESPACE
struct ProFileOption;
@@ -67,6 +68,7 @@ namespace Internal {
class GCCPreprocessor;
struct Qt4ProjectFiles;
class Qt4ProjectConfigWidget;
+ class Qt4Target;
class CodeModelInfo
{
@@ -152,47 +154,54 @@ public:
virtual QStringList includePaths(const QString &fileName) const;
virtual QStringList frameworkPaths(const QString &fileName) const;
+ /// \internal
Internal::ProFileReader *createProFileReader(Internal::Qt4ProFileNode *qt4ProFileNode);
+ /// \internal
void destroyProFileReader(Internal::ProFileReader *reader);
+ /// \internal
+ void scheduleAsyncUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *node);
+ /// \internal
+ void incrementPendingEvaluateFutures();
+ /// \internal
+ void decrementPendingEvaluateFutures();
+ /// \internal
+ bool wasEvaluateCanceled();
+
signals:
- /// convenience signal, emitted if either the active buildconfiguration emits
- /// targetInformationChanged() or if the active build configuration changes
- /// (which can happen by the active target changing, too).
- void targetInformationChanged();
+ /// emitted after parse
void proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *node);
void buildDirectoryInitialized();
public slots:
void proFileParseError(const QString &errorMessage);
void update();
- void changeTargetInformation();
+
+protected:
+ virtual bool fromMap(const QVariantMap &map);
private slots:
- void updateCodeModel();
- void scheduleUpdateCodeModel(Qt4ProjectManager::Internal::Qt4ProFileNode *);
+ void proFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4Target *target);
+
+ void asyncUpdate();
+
void qtVersionsChanged();
- void updateFileList();
void onAddedTarget(ProjectExplorer::Target *t);
+ void activeTargetWasChanged();
+
+private:
+ void scheduleAsyncUpdate();
- void foldersAboutToBeAdded(FolderNode *, const QList<FolderNode*> &);
void checkForNewApplicationProjects();
void checkForDeletedApplicationProjects();
- void projectTypeChanged(Qt4ProjectManager::Internal::Qt4ProFileNode *node,
- const Qt4ProjectManager::Internal::Qt4ProjectType oldType,
- const Qt4ProjectManager::Internal::Qt4ProjectType newType);
- void activeTargetWasChanged();
-
-protected:
- virtual bool fromMap(const QVariantMap &map);
+ void updateCodeModel();
+ void updateFileList();
-private:
static void collectApplicationProFiles(QList<Internal::Qt4ProFileNode *> &list, Internal::Qt4ProFileNode *node);
static void findProFile(const QString& fileName, Internal::Qt4ProFileNode *root, QList<Internal::Qt4ProFileNode *> &list);
static bool hasSubNode(Internal::Qt4PriFileNode *root, const QString &path);
- QList<Internal::Qt4ProFileNode *> m_applicationProFileChange;
- ProjectExplorer::ProjectExplorerPlugin *projectExplorer() const;
+ static bool equalFileList(const QStringList &a, const QStringList &b);
void addDefaultBuild();
@@ -213,17 +222,22 @@ private:
// cached lists of all of files
Internal::Qt4ProjectFiles *m_projectFiles;
- QTimer m_updateCodeModelTimer;
- QList<Qt4ProjectManager::Internal::Qt4ProFileNode *> m_proFilesForCodeModelUpdate;
+ // cached data during project rescan
+ ProFileOption *m_proFileOption;
+ int m_proFileOptionRefCnt;
+
+ QTimer m_asyncUpdateTimer;
+ QFutureInterface<void> *m_asyncUpdateFutureInterface;
+ int m_pendingEvaluateFuturesCount;
+ enum AsyncUpdateState { NoState, Base, AsyncFullUpdatePending, AsyncPartialUpdatePending, AsyncUpdateInProgress };
+ AsyncUpdateState m_asyncUpdateState;
+ bool m_cancelEvaluate;
+ QList<Internal::Qt4ProFileNode *> m_partialEvaluate;
QMap<QString, Internal::CodeModelInfo> m_codeModelInfo;
friend class Qt4ProjectFile;
friend class Internal::Qt4ProjectConfigWidget;
-
- // cached data during project rescan
- ProFileOption *m_proFileOption;
- int m_proFileOptionRefCnt;
};
} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp b/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp
index 0195ea63e5..8621407547 100644
--- a/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp
+++ b/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp
@@ -161,8 +161,6 @@ void Qt4ProjectConfigWidget::init(ProjectExplorer::BuildConfiguration *bc)
qDebug() << "Qt4ProjectConfigWidget::init() for"<<bc->displayName();
if (m_buildConfiguration) {
- disconnect(m_buildConfiguration, SIGNAL(buildDirectoryChanged()),
- this, SLOT(buildDirectoryChanged()));
disconnect(m_buildConfiguration, SIGNAL(qtVersionChanged()),
this, SLOT(qtVersionChanged()));
disconnect(m_buildConfiguration, SIGNAL(qmakeBuildConfigurationChanged()),
@@ -185,7 +183,7 @@ void Qt4ProjectConfigWidget::init(ProjectExplorer::BuildConfiguration *bc)
m_ui->shadowBuildCheckBox->setChecked(shadowBuild);
m_ui->shadowBuildDirEdit->setEnabled(shadowBuild);
m_browseButton->setEnabled(shadowBuild);
- m_ui->shadowBuildDirEdit->setPath(m_buildConfiguration->buildDirectory());
+ m_ui->shadowBuildDirEdit->setPath(m_buildConfiguration->shadowBuildDirectory());
updateImportLabel();
updateToolChainCombo();
updateDetails();
diff --git a/src/plugins/qt4projectmanager/qt4projectmanager.cpp b/src/plugins/qt4projectmanager/qt4projectmanager.cpp
index 48dcc2a74a..751ff411be 100644
--- a/src/plugins/qt4projectmanager/qt4projectmanager.cpp
+++ b/src/plugins/qt4projectmanager/qt4projectmanager.cpp
@@ -203,7 +203,6 @@ ProjectExplorer::Project* Qt4Manager::openProject(const QString &fileName)
}
Qt4Project *pro = new Qt4Project(this, canonicalFilePath);
- registerProject(pro);
return pro;
}
diff --git a/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h b/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h
index 00709dbbe1..6728889bdf 100644
--- a/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h
+++ b/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h
@@ -85,6 +85,9 @@ const char * const QT_APP_WIZARD_CATEGORY = "C.QtApplicationProjects";
const char * const QT_APP_WIZARD_TR_SCOPE = "Qt4ProjectManager";
const char * const QT_APP_WIZARD_TR_CATEGORY = QT_TRANSLATE_NOOP("Qt4ProjectManager", "Qt Application Project");
+// Tasks
+const char * const PROFILE_EVALUATE = "Qt4ProjectManager.ProFileEvaluate";
+
} // namespace Constants
} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt4runconfiguration.cpp b/src/plugins/qt4projectmanager/qt4runconfiguration.cpp
index 3ca4e5cccc..78a7cace61 100644
--- a/src/plugins/qt4projectmanager/qt4runconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt4runconfiguration.cpp
@@ -95,7 +95,6 @@ Qt4RunConfiguration::Qt4RunConfiguration(Qt4Target *parent, const QString &proFi
m_proFilePath(proFilePath),
m_runMode(Gui),
m_userSetName(false),
- m_cachedTargetInformationValid(false),
m_isUsingDyldImageSuffix(false),
m_userSetWokingDirectory(false),
m_baseEnvironmentBase(Qt4RunConfiguration::BuildEnvironmentBase)
@@ -109,7 +108,6 @@ Qt4RunConfiguration::Qt4RunConfiguration(Qt4Target *parent, Qt4RunConfiguration
m_proFilePath(source->m_proFilePath),
m_runMode(source->m_runMode),
m_userSetName(source->m_userSetName),
- m_cachedTargetInformationValid(false),
m_isUsingDyldImageSuffix(source->m_isUsingDyldImageSuffix),
m_userSetWokingDirectory(source->m_userSetWokingDirectory),
m_userWorkingDirectory(source->m_userWorkingDirectory),
@@ -156,15 +154,12 @@ bool Qt4RunConfiguration::isEnabled(ProjectExplorer::BuildConfiguration *configu
void Qt4RunConfiguration::proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro)
{
if (m_proFilePath == pro->path())
- invalidateCachedTargetInformation();
+ emit effectiveTargetInformationChanged();
}
void Qt4RunConfiguration::ctor()
{
setDefaultDisplayName();
- connect(qt4Target(), SIGNAL(targetInformationChanged()),
- this, SLOT(invalidateCachedTargetInformation()));
-
connect(qt4Target(), SIGNAL(environmentChanged()),
this, SIGNAL(baseEnvironmentChanged()));
@@ -475,7 +470,6 @@ bool Qt4RunConfiguration::fromMap(const QVariantMap &map)
m_userWorkingDirectory = map.value(QLatin1String(USER_WORKING_DIRECTORY_KEY)).toString();
if (!m_proFilePath.isEmpty()) {
- m_cachedTargetInformationValid = false;
if (!m_userSetName)
setDefaultDisplayName();
}
@@ -487,8 +481,11 @@ bool Qt4RunConfiguration::fromMap(const QVariantMap &map)
QString Qt4RunConfiguration::executable() const
{
- const_cast<Qt4RunConfiguration *>(this)->updateTarget();
- return m_executable;
+ Qt4Project *pro = qt4Target()->qt4Project();
+ TargetInformation ti = pro->rootProjectNode()->targetInformation(m_proFilePath);
+ if (!ti.valid)
+ return QString();
+ return ti.executable;
}
LocalApplicationRunConfiguration::RunMode Qt4RunConfiguration::runMode() const
@@ -514,8 +511,11 @@ QString Qt4RunConfiguration::workingDirectory() const
return m_userWorkingDirectory;
// else what the pro file reader tells us
- const_cast<Qt4RunConfiguration *>(this)->updateTarget();
- return m_workingDir;
+ Qt4Project *pro = qt4Target()->qt4Project();
+ TargetInformation ti = pro->rootProjectNode()->targetInformation(m_proFilePath);
+ if(!ti.valid)
+ return QString();
+ return ti.workingDir;
}
QStringList Qt4RunConfiguration::commandLineArguments() const
@@ -611,38 +611,6 @@ QString Qt4RunConfiguration::proFilePath() const
return m_proFilePath;
}
-void Qt4RunConfiguration::updateTarget()
-{
- if (m_cachedTargetInformationValid)
- return;
- Qt4TargetInformation info = qt4Target()->targetInformation(qt4Target()->activeBuildConfiguration(),
- m_proFilePath);
- if (info.error != Qt4TargetInformation::NoError) {
- if (info.error == Qt4TargetInformation::ProParserError) {
- Core::ICore::instance()->messageManager()->printToOutputPane(
- tr("Could not parse %1. The Qt4 run configuration %2 can not be started.")
- .arg(m_proFilePath).arg(displayName()));
- }
- m_workingDir.clear();
- m_executable.clear();
- m_cachedTargetInformationValid = true;
- emit effectiveTargetInformationChanged();
- return;
- }
- m_workingDir = info.workingDir;
- m_executable = info.executable;
-
- m_cachedTargetInformationValid = true;
-
- emit effectiveTargetInformationChanged();
-}
-
-void Qt4RunConfiguration::invalidateCachedTargetInformation()
-{
- m_cachedTargetInformationValid = false;
- emit effectiveTargetInformationChanged();
-}
-
QString Qt4RunConfiguration::dumperLibrary() const
{
QtVersion *version = qt4Target()->activeBuildConfiguration()->qtVersion();
diff --git a/src/plugins/qt4projectmanager/qt4runconfiguration.h b/src/plugins/qt4projectmanager/qt4runconfiguration.h
index 3243a3f26b..9f23e25298 100644
--- a/src/plugins/qt4projectmanager/qt4runconfiguration.h
+++ b/src/plugins/qt4projectmanager/qt4runconfiguration.h
@@ -91,12 +91,7 @@ public:
QVariantMap toMap() const;
public slots:
- // This function is called if:
- // X the pro file changes
- // X the active buildconfiguration changes
- // X the qmake parameters change
- // X the build directory changes
- void invalidateCachedTargetInformation();
+ void targetInformationChanged();
signals:
void commandLineArgumentsChanged(const QString&);
@@ -140,11 +135,8 @@ private:
QString m_proFilePath; // Full path to the Application Pro File
// Cached startup sub project information
- QString m_executable;
- QString m_workingDir;
ProjectExplorer::LocalApplicationRunConfiguration::RunMode m_runMode;
bool m_userSetName;
- bool m_cachedTargetInformationValid;
bool m_isUsingDyldImageSuffix;
bool m_userSetWokingDirectory;
QString m_userWorkingDirectory;
diff --git a/src/plugins/qt4projectmanager/qt4target.cpp b/src/plugins/qt4projectmanager/qt4target.cpp
index 9d4c088267..1ce701fa9b 100644
--- a/src/plugins/qt4projectmanager/qt4target.cpp
+++ b/src/plugins/qt4projectmanager/qt4target.cpp
@@ -202,8 +202,9 @@ Qt4Target::Qt4Target(Qt4Project *parent, const QString &id) :
{
connect(project(), SIGNAL(supportedTargetIdsChanged()),
this, SLOT(updateQtVersion()));
+
connect(this, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
- this, SIGNAL(targetInformationChanged()));
+ this, SLOT(emitProFileEvaluateNeeded()));
connect(this, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
this, SIGNAL(environmentChanged()));
connect(this, SIGNAL(addedRunConfiguration(ProjectExplorer::RunConfiguration*)),
@@ -231,89 +232,6 @@ Qt4Project *Qt4Target::qt4Project() const
return static_cast<Qt4Project *>(project());
}
-Qt4TargetInformation Qt4Target::targetInformation(Qt4BuildConfiguration *buildConfiguration,
- const QString &proFilePath)
-{
- Qt4TargetInformation info;
- Qt4ProFileNode *proFileNode = qt4Project()->rootProjectNode()->findProFileFor(proFilePath);
- if (!proFileNode) {
- info.error = Qt4TargetInformation::InvalidProjectError;
- return info;
- }
- ProFileReader *reader = qt4Project()->createProFileReader(proFileNode);
- reader->setCumulative(false);
-
- // Find out what flags we pass on to qmake
- QStringList addedUserConfigArguments;
- QStringList removedUserConfigArguments;
- buildConfiguration->getConfigCommandLineArguments(&addedUserConfigArguments, &removedUserConfigArguments);
- reader->setConfigCommandLineArguments(addedUserConfigArguments, removedUserConfigArguments);
-
- if (!reader->readProFile(proFilePath)) {
- qt4Project()->destroyProFileReader(reader);
- info.error = Qt4TargetInformation::ProParserError;
- return info;
- }
-
- // Extract data
- const QDir baseProjectDirectory = QFileInfo(project()->file()->fileName()).absoluteDir();
- const QString relSubDir = baseProjectDirectory.relativeFilePath(QFileInfo(proFilePath).path());
- const QDir baseBuildDirectory = buildConfiguration->buildDirectory();
- const QString baseDir = baseBuildDirectory.absoluteFilePath(relSubDir);
- //qDebug()<<relSubDir<<baseDir;
-
- // Working Directory
- if (reader->contains("DESTDIR")) {
- //qDebug() << "reader contains destdir:" << reader->value("DESTDIR");
- info.workingDir = reader->value("DESTDIR");
- if (QDir::isRelativePath(info.workingDir)) {
- info.workingDir = baseDir + QLatin1Char('/') + info.workingDir;
- //qDebug() << "was relative and expanded to" << info.workingDir;
- }
- } else {
- //qDebug() << "reader didn't contain DESTDIR, setting to " << baseDir;
- info.workingDir = baseDir;
- }
-
- info.target = reader->value("TARGET");
- if (info.target.isEmpty())
- info.target = QFileInfo(proFilePath).baseName();
-
-#if defined (Q_OS_MAC)
- if (reader->values("CONFIG").contains("app_bundle")) {
- info.workingDir += QLatin1Char('/')
- + info.target
- + QLatin1String(".app/Contents/MacOS");
- }
-#endif
-
- info.workingDir = QDir::cleanPath(info.workingDir);
-
- QString wd = info.workingDir;
- if (!reader->contains("DESTDIR")
- && reader->values("CONFIG").contains("debug_and_release")
- && reader->values("CONFIG").contains("debug_and_release_target")) {
- // If we don't have a destdir and debug and release is set
- // then the executable is in a debug/release folder
- //qDebug() << "reader has debug_and_release_target";
- QString qmakeBuildConfig = "release";
- if (buildConfiguration->qmakeBuildConfiguration() & QtVersion::DebugBuild)
- qmakeBuildConfig = "debug";
- wd += QLatin1Char('/') + qmakeBuildConfig;
- }
-
- info.executable = QDir::cleanPath(wd + QLatin1Char('/') + info.target);
- //qDebug() << "##### updateTarget sets:" << info.workingDir << info.executable;
-
-#if defined (Q_OS_WIN)
- info.executable += QLatin1String(".exe");
-#endif
-
- qt4Project()->destroyProFileReader(reader);
- info.error = Qt4TargetInformation::NoError;
- return info;
-}
-
Qt4BuildConfiguration *Qt4Target::addQt4BuildConfiguration(QString displayName, QtVersion *qtversion,
QtVersion::QmakeBuildConfigs qmakeBuildConfiguration,
QStringList additionalArguments)
@@ -429,8 +347,8 @@ void Qt4Target::onAddedBuildConfiguration(ProjectExplorer::BuildConfiguration *b
Q_ASSERT(qt4bc);
connect(qt4bc, SIGNAL(buildDirectoryInitialized()),
this, SIGNAL(buildDirectoryInitialized()));
- connect(qt4bc, SIGNAL(targetInformationChanged()),
- this, SLOT(changeTargetInformation()));
+ connect(qt4bc, SIGNAL(proFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4BuildConfiguration *)),
+ this, SLOT(onProFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4BuildConfiguration *)));
}
void Qt4Target::slotUpdateDeviceInformation()
@@ -441,11 +359,15 @@ void Qt4Target::slotUpdateDeviceInformation()
}
}
-void Qt4Target::changeTargetInformation()
+void Qt4Target::onProFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4BuildConfiguration *bc)
{
- Qt4BuildConfiguration * bc = qobject_cast<Qt4BuildConfiguration *>(sender());
if (bc && bc == activeBuildConfiguration())
- emit targetInformationChanged();
+ emit proFileEvaluateNeeded(this);
+}
+
+void Qt4Target::emitProFileEvaluateNeeded()
+{
+ emit proFileEvaluateNeeded(this);
}
void Qt4Target::updateToolTipAndIcon()
diff --git a/src/plugins/qt4projectmanager/qt4target.h b/src/plugins/qt4projectmanager/qt4target.h
index 724df41019..ebc105ca28 100644
--- a/src/plugins/qt4projectmanager/qt4target.h
+++ b/src/plugins/qt4projectmanager/qt4target.h
@@ -53,20 +53,6 @@ class ProFileReader;
class Qt4ProFileNode;
class Qt4TargetFactory;
-struct Qt4TargetInformation
-{
- enum ErrorCode {
- NoError,
- InvalidProjectError,
- ProParserError
- };
-
- ErrorCode error;
- QString workingDir;
- QString target;
- QString executable;
-};
-
class Qt4Target : public ProjectExplorer::Target
{
Q_OBJECT
@@ -79,9 +65,6 @@ public:
Qt4BuildConfiguration *activeBuildConfiguration() const;
Qt4ProjectManager::Qt4Project *qt4Project() const;
- Qt4TargetInformation targetInformation(Internal::Qt4BuildConfiguration *buildConfiguration,
- const QString &proFilePath);
-
Internal::Qt4BuildConfiguration *addQt4BuildConfiguration(QString displayName,
QtVersion *qtversion,
QtVersion::QmakeBuildConfigs qmakeBuildConfiguration,
@@ -94,11 +77,10 @@ public:
ProjectExplorer::ToolChain::ToolChainType preferredToolChainType(const QList<ProjectExplorer::ToolChain::ToolChainType> &candidates) const;
signals:
- /// convenience signal, emitted if either the active buildconfiguration emits
- /// targetInformationChanged() or if the active build configuration changes
- void targetInformationChanged();
-
void buildDirectoryInitialized();
+ /// emitted if the build configuration changed in a way that
+ /// should trigger a reevaluation of all .pro files
+ void proFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4Target *);
protected:
bool fromMap(const QVariantMap &map);
@@ -108,7 +90,8 @@ private slots:
void onAddedRunConfiguration(ProjectExplorer::RunConfiguration *rc);
void onAddedBuildConfiguration(ProjectExplorer::BuildConfiguration *bc);
void slotUpdateDeviceInformation();
- void changeTargetInformation();
+ void onProFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4BuildConfiguration *bc);
+ void emitProFileEvaluateNeeded();
void updateToolTipAndIcon();
private:
diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp
index cf7035cdc5..0e09628022 100644
--- a/src/plugins/qt4projectmanager/qtversionmanager.cpp
+++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp
@@ -1221,6 +1221,7 @@ void QtVersion::updateToolChainAndMkspec() const
ProFileOption option;
option.properties = versionInfo();
option.cache = ProFileCacheManager::instance()->cache();
+ ProFileCacheManager::instance()->incRefCount();
ProFileReader *reader = new ProFileReader(&option);
reader->setCumulative(false);
reader->setParsePreAndPostFiles(false);
@@ -1302,6 +1303,7 @@ void QtVersion::updateToolChainAndMkspec() const
}
delete reader;
+ ProFileCacheManager::instance()->decRefCount();
m_toolChainUpToDate = true;
}