From b3ec859c80bd0656cfc48cfe6514ec4f631b8206 Mon Sep 17 00:00:00 2001
From: dt <qtc-committer@nokia.com>
Date: Thu, 19 Mar 2009 15:04:43 +0100
Subject: [PATCH] Fixes:    Handle debug and release scopes for TARGET and
 DESTDIR

Task:     247606
Details:  Remove all the magic which build on top of the cumalative
parser. Instead trust the exact parsing to get those variables correct.
This required a bug fix in the profile evaluator, done with ossi.
Hopefully this doesn't break windows/mac. Will check.
---
 src/plugins/qt4projectmanager/qmakestep.cpp   |   2 +
 .../qt4buildconfigwidget.cpp                  |  20 +-
 .../qt4projectmanager/qt4buildconfigwidget.h  |   1 +
 src/plugins/qt4projectmanager/qt4project.cpp  |  42 ++-
 src/plugins/qt4projectmanager/qt4project.h    |   5 +
 .../qt4projectmanager/qt4runconfiguration.cpp | 241 ++++++------------
 .../qt4projectmanager/qt4runconfiguration.h   |  28 +-
 src/shared/proparser/profileevaluator.cpp     |  23 +-
 src/shared/proparser/profileevaluator.h       |   1 +
 9 files changed, 185 insertions(+), 178 deletions(-)

diff --git a/src/plugins/qt4projectmanager/qmakestep.cpp b/src/plugins/qt4projectmanager/qmakestep.cpp
index 10190302624..b448f98e41d 100644
--- a/src/plugins/qt4projectmanager/qmakestep.cpp
+++ b/src/plugins/qt4projectmanager/qmakestep.cpp
@@ -234,6 +234,7 @@ void QMakeStepConfigWidget::qmakeArgumentsLineEditTextEdited()
     Q_ASSERT(!m_buildConfiguration.isNull());
     m_step->setValue(m_buildConfiguration, "qmakeArgs", ProjectExplorer::Environment::parseCombinedArgString(m_ui.qmakeAdditonalArgumentsLineEdit->text()));
     m_ui.qmakeArgumentsEdit->setPlainText(ProjectExplorer::Environment::joinArgumentList(m_step->arguments(m_buildConfiguration)));
+    static_cast<Qt4Project *>(m_step->project())->invalidateCachedTargetInformation();
 }
 
 void QMakeStepConfigWidget::buildConfigurationChanged()
@@ -247,6 +248,7 @@ void QMakeStepConfigWidget::buildConfigurationChanged()
     }
     m_step->setValue(m_buildConfiguration, "buildConfiguration", int(buildConfiguration));
     m_ui.qmakeArgumentsEdit->setPlainText(ProjectExplorer::Environment::joinArgumentList(m_step->arguments(m_buildConfiguration)));
+    static_cast<Qt4Project *>(m_step->project())->invalidateCachedTargetInformation();
 }
 
 QString QMakeStepConfigWidget::displayName() const
diff --git a/src/plugins/qt4projectmanager/qt4buildconfigwidget.cpp b/src/plugins/qt4projectmanager/qt4buildconfigwidget.cpp
index c63861bc1fb..75fa4ee25c2 100644
--- a/src/plugins/qt4projectmanager/qt4buildconfigwidget.cpp
+++ b/src/plugins/qt4projectmanager/qt4buildconfigwidget.cpp
@@ -115,7 +115,7 @@ void Qt4BuildConfigWidget::init(const QString &buildConfiguration)
     m_ui->shadowBuildCheckBox->setChecked(shadowBuild);
     m_ui->shadowBuildDirEdit->setEnabled(shadowBuild);
     m_ui->shadowBuildDirEdit->setPath(m_pro->buildDirectory(buildConfiguration));
-    shadowBuildLineEditTextChanged(); // Update the import label
+    updateImportLabel();
 }
 
 void Qt4BuildConfigWidget::changeConfigName(const QString &newName)
@@ -173,12 +173,8 @@ void Qt4BuildConfigWidget::shadowBuildCheckBoxClicked(bool checked)
         m_pro->setValue(m_buildConfiguration, "buildDirectory", QVariant(QString::null));
 }
 
-void Qt4BuildConfigWidget::shadowBuildLineEditTextChanged()
+void Qt4BuildConfigWidget::updateImportLabel()
 {
-    m_pro->setValue(m_buildConfiguration, "buildDirectory", m_ui->shadowBuildDirEdit->path());
-    // if the directory already exists
-    // check if we have a build in there and
-    // offer to import it
     m_ui->importLabel->setVisible(false);
     if (m_ui->shadowBuildCheckBox->isChecked()) {
         QString qtPath = m_pro->qt4ProjectManager()->versionManager()->findQtVersionFromMakefile(m_ui->shadowBuildDirEdit->path());
@@ -186,6 +182,18 @@ void Qt4BuildConfigWidget::shadowBuildLineEditTextChanged()
             m_ui->importLabel->setVisible(true);
         }
     }
+}
+
+void Qt4BuildConfigWidget::shadowBuildLineEditTextChanged()
+{
+    if (m_pro->value(m_buildConfiguration, "buildDirectory").toString() == m_ui->shadowBuildDirEdit->path())
+    m_pro->setValue(m_buildConfiguration, "buildDirectory", m_ui->shadowBuildDirEdit->path());
+    // if the directory already exists
+    // check if we have a build in there and
+    // offer to import it
+    updateImportLabel();
+
+    m_pro->invalidateCachedTargetInformation();
 
 //    QFileInfo fi(m_ui->shadowBuildDirEdit->path());
 //    if (fi.exists()) {
diff --git a/src/plugins/qt4projectmanager/qt4buildconfigwidget.h b/src/plugins/qt4projectmanager/qt4buildconfigwidget.h
index edd74aa9f9e..0dffeed5104 100644
--- a/src/plugins/qt4projectmanager/qt4buildconfigwidget.h
+++ b/src/plugins/qt4projectmanager/qt4buildconfigwidget.h
@@ -63,6 +63,7 @@ private slots:
     void manageQtVersions();
 
 private:
+    void updateImportLabel();
     Ui::Qt4BuildConfigWidget *m_ui;
     Qt4Project *m_pro;
     QString m_buildConfiguration;
diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp
index a95c1284161..cf496f991bb 100644
--- a/src/plugins/qt4projectmanager/qt4project.cpp
+++ b/src/plugins/qt4projectmanager/qt4project.cpp
@@ -952,7 +952,7 @@ void Qt4Project::proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *nod
     foreach (QSharedPointer<RunConfiguration> rc, runConfigurations()) {
         if (QSharedPointer<Qt4RunConfiguration> qt4rc = rc.dynamicCast<Qt4RunConfiguration>()) {
             if (qt4rc->proFilePath() == node->path()) {
-                qt4rc->updateCachedValues();
+                qt4rc->invalidateCachedTargetInformation();
             }
         }
     }
@@ -1011,3 +1011,43 @@ void Qt4Project::notifyChanged(const QString &name)
             node->update();
     }
 }
+
+void Qt4Project::invalidateCachedTargetInformation()
+{
+    foreach(QSharedPointer<RunConfiguration> rc, runConfigurations()) {
+        QSharedPointer<Qt4RunConfiguration> qt4rc = rc.dynamicCast<Qt4RunConfiguration>();
+        if (qt4rc) {
+            qt4rc->invalidateCachedTargetInformation();
+        }
+    }
+}
+
+
+/*!
+  Handle special case were a subproject of the qt directory is opened, and
+  qt was configured to be built as a shadow build -> also build in the sub-
+  project in the correct shadow build directory.
+  */
+
+// TODO this function should be called on project first load
+// and it should check against all configured qt versions ?
+//void Qt4Project::detectQtShadowBuild(const QString &buildConfiguration) const
+//{
+//    if (project()->activeBuildConfiguration() == buildConfiguration)
+//        return;
+//
+//    const QString currentQtDir = static_cast<Qt4Project *>(project())->qtDir(buildConfiguration);
+//    const QString qtSourceDir = static_cast<Qt4Project *>(project())->qtVersion(buildConfiguration)->sourcePath();
+//
+//    // if the project is a sub-project of Qt and Qt was shadow-built then automatically
+//    // adjust the build directory of the sub-project.
+//    if (project()->file()->fileName().startsWith(qtSourceDir) && qtSourceDir != currentQtDir) {
+//        project()->setValue(buildConfiguration, "useShadowBuild", true);
+//        QString buildDir = QFileInfo(project()->file()->fileName()).absolutePath();
+//        buildDir.replace(qtSourceDir, currentQtDir);
+//        project()->setValue(buildConfiguration, "buildDirectory", buildDir);
+//        project()->setValue(buildConfiguration, "autoShadowBuild", true);
+//    }
+//}
+
+
diff --git a/src/plugins/qt4projectmanager/qt4project.h b/src/plugins/qt4projectmanager/qt4project.h
index 2b032c73c75..df23a18ba36 100644
--- a/src/plugins/qt4projectmanager/qt4project.h
+++ b/src/plugins/qt4projectmanager/qt4project.h
@@ -183,6 +183,11 @@ public:
 
     QString makeCommand(const QString &buildConfiguration) const;
 
+    // Is called by qmakestep qt4configurationwidget if the settings change
+    // Informs all Qt4RunConfigurations that their cached values are now invalid
+    // the Qt4RunConfigurations will update as soon as asked
+    void invalidateCachedTargetInformation();
+
 public slots:
     void update();
     void proFileParseError(const QString &errorMessage);
diff --git a/src/plugins/qt4projectmanager/qt4runconfiguration.cpp b/src/plugins/qt4projectmanager/qt4runconfiguration.cpp
index 433630e54c1..33d12957feb 100644
--- a/src/plugins/qt4projectmanager/qt4runconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt4runconfiguration.cpp
@@ -58,17 +58,16 @@ Qt4RunConfiguration::Qt4RunConfiguration(Qt4Project *pro, QString proFilePath)
       m_userSetName(false),
       m_configWidget(0),
       m_executableLabel(0),
-      m_workingDirectoryLabel(0)
+      m_workingDirectoryLabel(0),
+      m_cachedTargetInformationValid(false)
 {
     setName(tr("Qt4RunConfiguration"));
     if (!m_proFilePath.isEmpty()) {
-        updateCachedValues();
         setName(QFileInfo(m_proFilePath).baseName());
     }
+
     connect(pro, SIGNAL(activeBuildConfigurationChanged()),
-            this, SIGNAL(effectiveExecutableChanged()));
-    connect(pro, SIGNAL(activeBuildConfigurationChanged()),
-            this, SIGNAL(effectiveWorkingDirectoryChanged()));
+            this, SLOT(invalidateCachedTargetInformation()));
 }
 
 Qt4RunConfiguration::~Qt4RunConfiguration()
@@ -87,7 +86,7 @@ QString Qt4RunConfiguration::type() const
 /////
 
 Qt4RunConfigurationWidget::Qt4RunConfigurationWidget(Qt4RunConfiguration *qt4RunConfiguration, QWidget *parent)
-    : QWidget(parent), m_qt4RunConfiguration(qt4RunConfiguration), m_ignoreChange(false)
+    : QWidget(parent), m_qt4RunConfiguration(qt4RunConfiguration), m_ignoreChange(false), m_isShown(false)
 {
     QFormLayout *toplayout = new QFormLayout(this);
     toplayout->setMargin(0);
@@ -128,11 +127,8 @@ Qt4RunConfigurationWidget::Qt4RunConfigurationWidget(Qt4RunConfiguration *qt4Run
     connect(qt4RunConfiguration, SIGNAL(runModeChanged(ProjectExplorer::ApplicationRunConfiguration::RunMode)),
             this, SLOT(runModeChanged(ProjectExplorer::ApplicationRunConfiguration::RunMode)));
 
-    connect(qt4RunConfiguration, SIGNAL(effectiveExecutableChanged()),
-            this, SLOT(effectiveExecutableChanged()));
-    connect(qt4RunConfiguration, SIGNAL(effectiveWorkingDirectoryChanged()),
-            this, SLOT(effectiveWorkingDirectoryChanged()));
-
+    connect(qt4RunConfiguration, SIGNAL(effectiveTargetInformationChanged()),
+            this, SLOT(effectiveTargetInformationChanged()), Qt::QueuedConnection);
 }
 
 void Qt4RunConfigurationWidget::setCommandLineArguments(const QString &args)
@@ -175,18 +171,28 @@ void Qt4RunConfigurationWidget::runModeChanged(ApplicationRunConfiguration::RunM
         m_useTerminalCheck->setChecked(runMode == ApplicationRunConfiguration::Console);
 }
 
-void Qt4RunConfigurationWidget::effectiveExecutableChanged()
+void Qt4RunConfigurationWidget::effectiveTargetInformationChanged()
 {
-    m_executableLabel->setText(m_qt4RunConfiguration->executable());
+    if (m_isShown) {
+        m_executableLabel->setText(m_qt4RunConfiguration->executable());
+        m_workingDirectoryLabel->setText(m_qt4RunConfiguration->workingDirectory());
+    }
 }
 
-void Qt4RunConfigurationWidget::effectiveWorkingDirectoryChanged()
+void Qt4RunConfigurationWidget::showEvent(QShowEvent *event)
 {
-    m_workingDirectoryLabel->setText(m_qt4RunConfiguration->workingDirectory());
+    m_isShown = true;
+    effectiveTargetInformationChanged();
+    QWidget::showEvent(event);
 }
 
-////// TODO c&p above
+void Qt4RunConfigurationWidget::hideEvent(QHideEvent *event)
+{
+    m_isShown = false;
+    QWidget::hideEvent(event);
+}
 
+////// TODO c&p above
 QWidget *Qt4RunConfiguration::configurationWidget()
 {
     return new Qt4RunConfigurationWidget(this, 0);
@@ -209,7 +215,7 @@ void Qt4RunConfiguration::restore(const PersistentSettingsReader &reader)
     m_userSetName = reader.restoreValue("UserSetName").toBool();
     m_runMode = reader.restoreValue("UseTerminal").toBool() ? Console : Gui;
     if (!m_proFilePath.isEmpty()) {
-        updateCachedValues();
+        m_cachedTargetInformationValid = false;
         if (!m_userSetName)
             setName(QFileInfo(m_proFilePath).baseName());
     }
@@ -217,7 +223,8 @@ void Qt4RunConfiguration::restore(const PersistentSettingsReader &reader)
 
 QString Qt4RunConfiguration::executable() const
 {
-    return resolveVariables(project()->activeBuildConfiguration(), m_executable);
+    const_cast<Qt4RunConfiguration *>(this)->updateTarget();
+    return m_executable;
 }
 
 ApplicationRunConfiguration::RunMode Qt4RunConfiguration::runMode() const
@@ -227,7 +234,8 @@ ApplicationRunConfiguration::RunMode Qt4RunConfiguration::runMode() const
 
 QString Qt4RunConfiguration::workingDirectory() const
 {
-    return resolveVariables(project()->activeBuildConfiguration(), m_workingDir);
+    const_cast<Qt4RunConfiguration *>(this)->updateTarget();
+    return m_workingDir;
 }
 
 QStringList Qt4RunConfiguration::commandLineArguments() const
@@ -271,180 +279,99 @@ QString Qt4RunConfiguration::proFilePath() const
     return m_proFilePath;
 }
 
-// and needs to be reloaded.
-// Check wheter it is
-void Qt4RunConfiguration::updateCachedValues()
+void Qt4RunConfiguration::updateTarget()
 {
-    ProFileReader *reader = static_cast<Qt4Project *>(project())->createProFileReader();
+    if (m_cachedTargetInformationValid)
+        return;
+    //qDebug()<<"updateTarget";
+    Qt4Project *pro = static_cast<Qt4Project *>(project());
+    ProFileReader *reader = pro->createProFileReader();
     reader->setCumulative(false);
+    reader->setQtVersion(pro->qtVersion(pro->activeBuildConfiguration()));
+
+    // Find out what flags we pass on to qmake, this code is duplicated in the qmake step
+    QtVersion::QmakeBuildConfig defaultBuildConfiguration = pro->qtVersion(pro->activeBuildConfiguration())->defaultBuildConfig();
+    QtVersion::QmakeBuildConfig projectBuildConfiguration = QtVersion::QmakeBuildConfig(pro->qmakeStep()->value(pro->activeBuildConfiguration(), "buildConfiguration").toInt());
+    QStringList addedUserConfigArguments;
+    QStringList removedUserConfigArguments;
+    if ((defaultBuildConfiguration & QtVersion::BuildAll) && !(projectBuildConfiguration & QtVersion::BuildAll))
+        removedUserConfigArguments << "debug_and_release";
+    if (!(defaultBuildConfiguration & QtVersion::BuildAll) && (projectBuildConfiguration & QtVersion::BuildAll))
+        addedUserConfigArguments << "debug_and_release";
+    if ((defaultBuildConfiguration & QtVersion::DebugBuild) && !(projectBuildConfiguration & QtVersion::DebugBuild))
+        addedUserConfigArguments << "release";
+    if (!(defaultBuildConfiguration & QtVersion::DebugBuild) && (projectBuildConfiguration & QtVersion::DebugBuild))
+        addedUserConfigArguments << "debug";
+
+    reader->setUserConfigCmdArgs(addedUserConfigArguments, removedUserConfigArguments);
+
+    QHash<QString, QStringList>::const_iterator it;
+
     if (!reader->readProFile(m_proFilePath)) {
         delete reader;
         Core::ICore::instance()->messageManager()->printToOutputPane(QString("Could not parse %1. The Qt4 run configuration %2 can not be started.").arg(m_proFilePath).arg(name()));
         return;
     }
 
-    QString destDir;
+    // Extract data
+    QString relSubDir = QFileInfo(project()->file()->fileName()).absoluteDir().relativeFilePath(QFileInfo(m_proFilePath).path());
+    QString baseDir = QDir(project()->buildDirectory(project()->activeBuildConfiguration())).absoluteFilePath(relSubDir);
+
+    //qDebug()<<relSubDir<<baseDir;
 
+    // Working Directory
     if (reader->contains("DESTDIR")) {
-        // TODO Can return different destdirs for different scopes!
-        destDir = reader->value("DESTDIR");
-        if (QDir::isRelativePath(destDir)) {
-            destDir = "${BASEDIR}" + QLatin1Char('/') + destDir;
+        //qDebug()<<"reader contains destdir:"<<reader->value("DESTDIR");
+        m_workingDir = reader->value("DESTDIR");
+        if (QDir::isRelativePath(m_workingDir)) {
+            m_workingDir = baseDir + QLatin1Char('/') + m_workingDir;
+            //qDebug()<<"was relative and expanded to"<<m_workingDir;
         }
     } else {
-        destDir = "${BASEDIR}";
+        //qDebug()<<"reader didn't contain DESTDIR, setting to "<<baseDir;
+        m_workingDir = baseDir;
+
 #if defined(Q_OS_WIN)
+        QString qmakeBuildConfig = "release";
+        if (projectBuildConfiguration & QtVersion::DebugBuild)
+            qmakeBuildConfig = "debug";
         if (!reader->contains("DESTDIR"))
-            destDir += QLatin1Char('/') + "${QMAKE_BUILDCONFIG}";
+            destDir += QLatin1Char('/') + qmakeBuildConfig;
 #endif
     }
 
 #if defined (Q_OS_MAC)
     if (reader->values("CONFIG").contains("app_bundle")) {
+        QString qmakeBuildConfig = "release";
+        if (projectBuildConfiguration & QtVersion::DebugBuild)
+            qmakeBuildConfig = "debug";
         destDir += QLatin1Char('/')
-                   + "${QMAKE_TARGET}"
+                   + qmakeBuildConfig
                    + QLatin1String(".app/Contents/MacOS");
     }
 #endif
-    m_workingDir = destDir;
-    m_executable = destDir + QLatin1Char('/') + "${QMAKE_TARGET}";
+
+    m_workingDir = QDir::cleanPath(m_workingDir);
+    m_executable = QDir::cleanPath(m_workingDir + QLatin1Char('/') + reader->value("TARGET"));
+    //qDebug()<<"##### updateTarget sets:"<<m_workingDir<<m_executable;
 
 #if defined (Q_OS_WIN)
     m_executable += QLatin1String(".exe");
 #endif
 
-    m_targets = reader->values(QLatin1String("TARGET"));
-
-    m_srcDir = QFileInfo(m_proFilePath).path();
-
     delete reader;
 
-    emit effectiveExecutableChanged();
-    emit effectiveWorkingDirectoryChanged();
-}
-
-QString Qt4RunConfiguration::resolveVariables(const QString &buildConfiguration, const QString& in) const
-{
-    detectQtShadowBuild(buildConfiguration);
-    
-    QString relSubDir = QFileInfo(project()->file()->fileName()).absoluteDir().relativeFilePath(m_srcDir);
-    QString baseDir = QDir(project()->buildDirectory(buildConfiguration)).absoluteFilePath(relSubDir);
-
-    Core::VariableManager *vm = Core::ICore::instance()->variableManager();
-    if (!vm)
-        return QString();
-    QString dest;
-    bool found = false;
-    vm->insert("QMAKE_BUILDCONFIG", qmakeBuildConfigFromBuildConfiguration(buildConfiguration));
-    vm->insert("BASEDIR", baseDir);
-
-
-    /*
-      TODO This is a hack to detect correct target (there might be different targets in
-      different scopes)
-    */
-
-    // This code also works for workingDirectory,
-    // since directories are executable.
-    foreach (const QString &target, m_targets) {
-        dest = in;
-        vm->insert("QMAKE_TARGET", target);
-        dest = QDir::cleanPath(vm->resolve(dest));
-        vm->remove("QMAKE_TARGET");
-        QFileInfo fi(dest);
-        if (fi.exists() && (fi.isExecutable() || dest.endsWith(".js"))) {
-            found = true;
-            break;
-        }
-    }
-    vm->remove("BASEDIR");
-    vm->remove("QMAKE_BUILDCONFIG");
-    if (found)
-        return dest;
-    else
-        return QString();
-}
-
-/* This function tries to find out wheter qmake/make will put the binary in "/debug/" or in "/release/"
-   That is this function is strictly only for windows.
-   We look wheter make gets an explicit parameter "debug" or "release"
-   That works because if we have either debug or release there then it is surely a
-   debug_and_release buildconfiguration and thus we are put in a subdirectory.
-
-   Now if there is no explicit debug or release parameter, then we need to look at what qmake's CONFIG
-   value is, if it is not debug_and_release, we don't care and return ""
-   otherwise we look at wheter the default is debug or not
-
-   Note: When fixing this function consider those cases
-       qmake CONFIG+=debug_and_release CONFIG+=debug
-       make release
-    => we should return release
-
-        qmake CONFIG+=debug_and_release CONFIG+=debug
-        make
-    => we should return debug
-
-        qmake CONFIG-=debug_and_release CONFIG+=debug
-        make
-    => we should return "", since the executable is not put in a subdirectory
-
-   Not a function to be proud of
-*/
-QString Qt4RunConfiguration::qmakeBuildConfigFromBuildConfiguration(const QString &buildConfigurationName) const
-{
-    MakeStep *ms = qobject_cast<Qt4Project *>(project())->makeStep();
-    QStringList makeargs = ms->value(buildConfigurationName, "makeargs").toStringList();
-    if (makeargs.contains("debug"))
-        return "debug";
-    else if (makeargs.contains("release"))
-        return "release";
-
-    // Oh we don't have an explicit make argument
-    QMakeStep *qs = qobject_cast<Qt4Project *>(project())->qmakeStep();
-    QVariant qmakeBuildConfiguration = qs->value(buildConfigurationName, "buildConfiguration");
-    if (qmakeBuildConfiguration.isValid()) {
-        QtVersion::QmakeBuildConfig projectBuildConfiguration = QtVersion::QmakeBuildConfig(qmakeBuildConfiguration.toInt());
-        if (projectBuildConfiguration & QtVersion::DebugBuild)
-            return "debug";
-        else
-            return "release";
-    } else {
-        // Old style always CONFIG+=debug_and_release
-        if (qobject_cast<Qt4Project *>(project())->qtVersion(buildConfigurationName)->defaultBuildConfig() & QtVersion::DebugBuild)
-            return "debug";
-        else
-            return "release";
-    }
+    m_cachedTargetInformationValid = true;
 
-    // enable us to infer the right string
-    return "";
+    emit effectiveTargetInformationChanged();
 }
 
-/*!
-  Handle special case were a subproject of the qt directory is opened, and
-  qt was configured to be built as a shadow build -> also build in the sub-
-  project in the correct shadow build directory.
-  */
-void Qt4RunConfiguration::detectQtShadowBuild(const QString &buildConfiguration) const
+void Qt4RunConfiguration::invalidateCachedTargetInformation()
 {
-    if (project()->activeBuildConfiguration() == buildConfiguration)
-        return;
-
-    const QString currentQtDir = static_cast<Qt4Project *>(project())->qtDir(buildConfiguration);
-    const QString qtSourceDir = static_cast<Qt4Project *>(project())->qtVersion(buildConfiguration)->sourcePath();
-
-    // if the project is a sub-project of Qt and Qt was shadow-built then automatically
-    // adjust the build directory of the sub-project.
-    if (project()->file()->fileName().startsWith(qtSourceDir) && qtSourceDir != currentQtDir) {
-        project()->setValue(buildConfiguration, "useShadowBuild", true);
-        QString buildDir = QFileInfo(project()->file()->fileName()).absolutePath();
-        buildDir.replace(qtSourceDir, currentQtDir);
-        project()->setValue(buildConfiguration, "buildDirectory", buildDir);
-        project()->setValue(buildConfiguration, "autoShadowBuild", true);
-    }
+    m_cachedTargetInformationValid = false;
+    emit effectiveTargetInformationChanged();
 }
 
-
 ///
 /// Qt4RunConfigurationFactory
 /// This class is used to restore run settings (saved in .user files)
diff --git a/src/plugins/qt4projectmanager/qt4runconfiguration.h b/src/plugins/qt4projectmanager/qt4runconfiguration.h
index d848531d013..7828270a5c7 100644
--- a/src/plugins/qt4projectmanager/qt4runconfiguration.h
+++ b/src/plugins/qt4projectmanager/qt4runconfiguration.h
@@ -73,8 +73,15 @@ public:
 
     QString proFilePath() const;
 
-    // Should just be called from qt4project, since that knows that the file changed on disc
-    void updateCachedValues();
+    // TODO detectQtShadowBuild() ? how did this work ?
+
+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();
 
 signals:
     void nameChanged(const QString&);
@@ -82,8 +89,7 @@ signals:
     void runModeChanged(ProjectExplorer::ApplicationRunConfiguration::RunMode runMode);
 
     // note those signals might not emited for every change
-    void effectiveExecutableChanged();
-    void effectiveWorkingDirectoryChanged();
+    void effectiveTargetInformationChanged();
 
 private slots:
     void setCommandLineArguments(const QString &argumentsString);
@@ -91,10 +97,7 @@ private slots:
     void setRunMode(RunMode runMode);
 
 private:
-    void detectQtShadowBuild(const QString &buildConfig) const;
-    QString resolveVariables(const QString &buildConfiguration, const QString& in) const;
-    QString qmakeBuildConfigFromBuildConfiguration(const QString &buildConfigurationName) const;
-
+    void updateTarget();
     QStringList m_commandLineArguments;
     Qt4ProFileNode *m_proFileNode;
     QString m_proFilePath; // Full path to the Application Pro File
@@ -102,13 +105,13 @@ private:
     // Cached startup sub project information
     QStringList m_targets;
     QString m_executable;
-    QString m_srcDir;
     QString m_workingDir;
     ProjectExplorer::ApplicationRunConfiguration::RunMode m_runMode;
     bool m_userSetName;
     QWidget *m_configWidget;
     QLabel *m_executableLabel;
     QLabel *m_workingDirectoryLabel;
+    bool m_cachedTargetInformationValid;
 };
 
 class Qt4RunConfigurationWidget : public QWidget
@@ -116,6 +119,9 @@ class Qt4RunConfigurationWidget : public QWidget
     Q_OBJECT
 public:
     Qt4RunConfigurationWidget(Qt4RunConfiguration *qt4runconfigration, QWidget *parent);
+protected:
+    void showEvent(QShowEvent *event);
+    void hideEvent(QHideEvent *event);
 private slots:
     void setCommandLineArguments(const QString &arguments);
     void nameEdited(const QString &name);
@@ -123,8 +129,7 @@ private slots:
     void commandLineArgumentsChanged(const QString &args);
     void nameChanged(const QString &name);
     void runModeChanged(ProjectExplorer::ApplicationRunConfiguration::RunMode runMode);
-    void effectiveExecutableChanged();
-    void effectiveWorkingDirectoryChanged();
+    void effectiveTargetInformationChanged();
     void termToggled(bool);
 private:
     Qt4RunConfiguration *m_qt4RunConfiguration;
@@ -134,6 +139,7 @@ private:
     QLineEdit *m_nameLineEdit;
     QLineEdit *m_argumentsLineEdit;
     QCheckBox *m_useTerminalCheck;
+    bool m_isShown;
 };
 
 class Qt4RunConfigurationFactory : public ProjectExplorer::IRunConfigurationFactory
diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp
index 64a75c0256a..bbfeba7dd7e 100644
--- a/src/shared/proparser/profileevaluator.cpp
+++ b/src/shared/proparser/profileevaluator.cpp
@@ -217,6 +217,8 @@ public:
 
     int m_prevLineNo;                               // Checking whether we're assigning the same TARGET
     ProFile *m_prevProFile;                         // See m_prevLineNo
+    QStringList m_addUserConfigCmdArgs;
+    QStringList m_removeUserConfigCmdArgs;
 };
 
 ProFileEvaluator::Private::Private(ProFileEvaluator *q_)
@@ -628,6 +630,12 @@ bool ProFileEvaluator::Private::visitBeginProFile(ProFile * pro)
             // But this also creates a lot of problems
             evaluateFile(mkspecDirectory + QLatin1String("/default/qmake.conf"), &ok);
             evaluateFile(mkspecDirectory + QLatin1String("/features/default_pre.prf"), &ok);
+
+            QStringList tmp = m_valuemap.value("CONFIG");
+            tmp.append(m_addUserConfigCmdArgs);
+            foreach(const QString &remove, m_removeUserConfigCmdArgs)
+                tmp.removeAll(remove);
+            m_valuemap.insert("CONFIG", tmp);
             m_cumulative = cumulative;
         }
 
@@ -822,6 +830,7 @@ bool ProFileEvaluator::Private::visitProValue(ProValue *value)
                     // but this will break just as much as it fixes, so leave it as is.
                     replaceInList(&m_tempValuemap[varName], regexp, replace, global);
                     replaceInList(&m_tempFilevaluemap[currentProFile()][varName], regexp, replace, global);
+
                 }
             }
             break;
@@ -1679,14 +1688,16 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct
             }
             const QStringList mutuals = args[1].split(QLatin1Char('|'));
             const QStringList &configs = valuesDirect(QLatin1String("CONFIG"));
+
             for (int i = configs.size() - 1; i >= 0; i--) {
                 for (int mut = 0; mut < mutuals.count(); mut++) {
                     if (configs[i] == mutuals[mut].trimmed()) {
                         cond = (configs[i] == args[0]);
-                        break;
+                        goto done_T_CONFIG;
                     }
                 }
             }
+          done_T_CONFIG:
             break;
         }
         case T_CONTAINS: {
@@ -1713,12 +1724,12 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct
                     for (int mut = 0; mut < mutuals.count(); mut++) {
                         if (val == mutuals[mut].trimmed()) {
                             cond = (regx.exactMatch(val) || val == args[1]);
-                            break;
+                            goto done_T_CONTAINS;
                         }
                     }
                 }
             }
-
+          done_T_CONTAINS:
             break;
         }
         case T_COUNT: {
@@ -2284,6 +2295,12 @@ void ProFileEvaluator::setOutputDir(const QString &dir)
     d->m_outputDir = dir;
 }
 
+void ProFileEvaluator::setUserConfigCmdArgs(const QStringList &addUserConfigCmdArgs, const QStringList &removeUserConfigCmdArgs)
+{
+    d->m_addUserConfigCmdArgs = addUserConfigCmdArgs;
+    d->m_removeUserConfigCmdArgs = removeUserConfigCmdArgs;
+}
+
 void evaluateProFile(const ProFileEvaluator &visitor, QHash<QByteArray, QStringList> *varMap)
 {
     QStringList sourceFiles;
diff --git a/src/shared/proparser/profileevaluator.h b/src/shared/proparser/profileevaluator.h
index 452b2ceceb3..b6df287b7d7 100644
--- a/src/shared/proparser/profileevaluator.h
+++ b/src/shared/proparser/profileevaluator.h
@@ -65,6 +65,7 @@ public:
     void setVerbose(bool on); // Default is false
     void setCumulative(bool on); // Default is true!
     void setOutputDir(const QString &dir); // Default is empty
+    void setUserConfigCmdArgs(const QStringList &addUserConfigCmdArgs, const QStringList &removeUserConfigCmdArgs);
 
     bool queryProFile(ProFile *pro);
     bool accept(ProFile *pro);
-- 
GitLab