From a60d55bdadf2278dfddc1b30f4133a40600a18b4 Mon Sep 17 00:00:00 2001
From: dt <qtc-committer@nokia.com>
Date: Thu, 29 Apr 2010 16:52:31 +0200
Subject: [PATCH] Sort build & run configurations in the ui

Implement a BuildConfigurationModel which does the sorting.
Extend the RunConfigurationModel to do sorting.

Make the mini target selector and project page use both of those models.

Task-Nr: QTCREATORBUG-1235
---
 .../buildconfigurationmodel.cpp               | 180 ++++++++++++++++++
 .../projectexplorer/buildconfigurationmodel.h |  69 +++++++
 .../buildsettingspropertiespage.cpp           |  58 +-----
 .../buildsettingspropertiespage.h             |   3 -
 .../miniprojecttargetselector.cpp             |  72 +++----
 .../miniprojecttargetselector.h               |   1 -
 .../projectexplorer/projectexplorer.pro       |   8 +-
 .../projectexplorer/runconfigurationmodel.cpp | 180 ++++++++++++++++++
 .../projectexplorer/runconfigurationmodel.h   |  67 +++++++
 .../runsettingspropertiespage.cpp             | 103 +---------
 .../runsettingspropertiespage.h               |  29 +--
 11 files changed, 544 insertions(+), 226 deletions(-)
 create mode 100644 src/plugins/projectexplorer/buildconfigurationmodel.cpp
 create mode 100644 src/plugins/projectexplorer/buildconfigurationmodel.h
 create mode 100644 src/plugins/projectexplorer/runconfigurationmodel.cpp
 create mode 100644 src/plugins/projectexplorer/runconfigurationmodel.h

diff --git a/src/plugins/projectexplorer/buildconfigurationmodel.cpp b/src/plugins/projectexplorer/buildconfigurationmodel.cpp
new file mode 100644
index 00000000000..a9f93b675ce
--- /dev/null
+++ b/src/plugins/projectexplorer/buildconfigurationmodel.cpp
@@ -0,0 +1,180 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "buildconfigurationmodel.h"
+#include "target.h"
+#include "buildconfiguration.h"
+
+using namespace ProjectExplorer;
+
+///
+/// RunConfigurationsModel
+///
+
+class BuildConfigurationComparer
+{
+public:
+    bool operator()(BuildConfiguration *a, BuildConfiguration *b)
+    {
+        return a->displayName() < b->displayName();
+    }
+};
+
+BuildConfigurationModel::BuildConfigurationModel(Target *target, QObject *parent)
+    : QAbstractListModel(parent),
+      m_target(target)
+{
+    m_buildConfigurations = m_target->buildConfigurations();
+    qSort(m_buildConfigurations.begin(), m_buildConfigurations.end(), BuildConfigurationComparer());
+
+    connect(target, SIGNAL(addedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
+            this, SLOT(addedBuildConfiguration(ProjectExplorer::BuildConfiguration*)));
+    connect(target, SIGNAL(removedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
+            this, SLOT(removedBuildConfiguration(ProjectExplorer::BuildConfiguration*)));
+
+    foreach (BuildConfiguration *bc, m_buildConfigurations)
+        connect(bc, SIGNAL(displayNameChanged()),
+                this, SLOT(displayNameChanged()));
+}
+
+int BuildConfigurationModel::rowCount(const QModelIndex &parent) const
+{
+    return parent.isValid() ? 0 : m_buildConfigurations.size();
+}
+
+int BuildConfigurationModel::columnCount(const QModelIndex &parent) const
+{
+    return parent.isValid() ? 0 : 1;
+}
+
+void BuildConfigurationModel::displayNameChanged()
+{
+    BuildConfiguration *rc = qobject_cast<BuildConfiguration *>(sender());
+    if (!rc)
+        return;
+
+    BuildConfigurationComparer compare;
+    // Find the old position
+    int oldPos = m_buildConfigurations.indexOf(rc);
+
+    if (oldPos >= 1 && compare(m_buildConfigurations.at(oldPos), m_buildConfigurations.at(oldPos - 1))) {
+        // We need to move up
+        int newPos = oldPos - 1;
+        while (newPos >= 0 && compare(m_buildConfigurations.at(oldPos), m_buildConfigurations.at(newPos))) {
+            --newPos;
+        }
+        ++newPos;
+
+        beginMoveRows(QModelIndex(), oldPos, oldPos, QModelIndex(), newPos);
+        m_buildConfigurations.insert(newPos, rc);
+        m_buildConfigurations.removeAt(oldPos + 1);
+        endMoveRows();
+        // Not only did we move, we also changed...
+        emit dataChanged(index(newPos, 0), index(newPos,0));
+    } else if  (oldPos < m_buildConfigurations.size() - 1
+                && compare(m_buildConfigurations.at(oldPos + 1), m_buildConfigurations.at(oldPos))) {
+        // We need to move down
+        int newPos = oldPos + 1;
+        while (newPos < m_buildConfigurations.size()
+            && compare(m_buildConfigurations.at(newPos), m_buildConfigurations.at(oldPos))) {
+            ++newPos;
+        }
+        beginMoveRows(QModelIndex(), oldPos, oldPos, QModelIndex(), newPos);
+        m_buildConfigurations.insert(newPos, rc);
+        m_buildConfigurations.removeAt(oldPos);
+        endMoveRows();
+
+        // We need to subtract one since removing at the old place moves the newIndex down
+        emit dataChanged(index(newPos - 1, 0), index(newPos - 1, 0));
+    } else {
+        emit dataChanged(index(oldPos, 0), index(oldPos, 0));
+    }
+}
+
+QVariant BuildConfigurationModel::data(const QModelIndex &index, int role) const
+{
+    if (role == Qt::DisplayRole) {
+        const int row = index.row();
+        if (row < m_buildConfigurations.size()) {
+            return m_buildConfigurations.at(row)->displayName();
+        }
+    }
+
+    return QVariant();
+}
+
+BuildConfiguration *BuildConfigurationModel::buildConfigurationAt(int i)
+{
+    if (i > m_buildConfigurations.size() || i < 0)
+        return 0;
+    return m_buildConfigurations.at(i);
+}
+
+BuildConfiguration *BuildConfigurationModel::buildConfigurationFor(const QModelIndex &idx)
+{
+    if (idx.row() > m_buildConfigurations.size() || idx.row() < 0)
+        return 0;
+    return m_buildConfigurations.at(idx.row());
+}
+
+QModelIndex BuildConfigurationModel::indexFor(BuildConfiguration *rc)
+{
+    int idx = m_buildConfigurations.indexOf(rc);
+    if (idx == -1)
+        return QModelIndex();
+    return index(idx, 0);
+}
+
+void BuildConfigurationModel::addedBuildConfiguration(ProjectExplorer::BuildConfiguration *bc)
+{
+    // Find the right place to insert
+    BuildConfigurationComparer compare;
+    int i = 0;
+    for (; i < m_buildConfigurations.size(); ++i) {
+        if (compare(bc, m_buildConfigurations.at(i))) {
+            break;
+        }
+    }
+
+    beginInsertRows(QModelIndex(), i, i);
+    m_buildConfigurations.insert(i, bc);
+    endInsertRows();
+
+
+    connect(bc, SIGNAL(displayNameChanged()),
+            this, SLOT(displayNameChanged()));
+}
+
+void BuildConfigurationModel::removedBuildConfiguration(ProjectExplorer::BuildConfiguration *bc)
+{
+    int i = m_buildConfigurations.indexOf(bc);
+    beginRemoveRows(QModelIndex(), i, i);
+    m_buildConfigurations.removeAt(i);
+    endRemoveRows();
+}
diff --git a/src/plugins/projectexplorer/buildconfigurationmodel.h b/src/plugins/projectexplorer/buildconfigurationmodel.h
new file mode 100644
index 00000000000..5f14552ca69
--- /dev/null
+++ b/src/plugins/projectexplorer/buildconfigurationmodel.h
@@ -0,0 +1,69 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef BUILDCONFIGURATIONMODEL_H
+#define BUILDCONFIGURATIONMODEL_H
+
+#include <QtCore/QAbstractItemModel>
+
+namespace ProjectExplorer {
+class Target;
+class BuildConfiguration;
+
+/*! A model to represent the build configurations of a target.
+    To be used in for the drop down of comboboxes
+    Does automatically adjust itself to added and removed BuildConfigurations
+    Very similar to the Run Configuration Model
+    TOOD might it possible to share code without making the code a complete mess
+*/
+class BuildConfigurationModel : public QAbstractListModel
+{
+    Q_OBJECT
+public:
+    BuildConfigurationModel(Target *target, QObject *parent = 0);
+
+    int rowCount(const QModelIndex &parent = QModelIndex()) const;
+    int columnCount(const QModelIndex &parent = QModelIndex()) const;
+    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+    BuildConfiguration *buildConfigurationAt(int i);
+    BuildConfiguration *buildConfigurationFor(const QModelIndex &idx);
+    QModelIndex indexFor(BuildConfiguration *rc);
+private slots:
+    void addedBuildConfiguration(ProjectExplorer::BuildConfiguration*);
+    void removedBuildConfiguration(ProjectExplorer::BuildConfiguration*);
+    void displayNameChanged();
+private:
+    Target *m_target;
+    QList<BuildConfiguration *> m_buildConfigurations;
+};
+
+}
+
+#endif // RUNCONFIGURATIONMODEL_H
diff --git a/src/plugins/projectexplorer/buildsettingspropertiespage.cpp b/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
index 5356f3a2a15..9fc730de216 100644
--- a/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
+++ b/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
@@ -33,6 +33,7 @@
 #include "project.h"
 #include "target.h"
 #include "buildconfiguration.h"
+#include "buildconfigurationmodel.h"
 
 #include <coreplugin/coreconstants.h>
 #include <extensionsystem/pluginmanager.h>
@@ -148,6 +149,7 @@ void BuildSettingsWidget::setupUi()
         hbox->addWidget(new QLabel(tr("Edit Build Configuration:"), this));
         m_buildConfigurationComboBox = new QComboBox(this);
         m_buildConfigurationComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
+        m_buildConfigurationComboBox->setModel(new BuildConfigurationModel(m_target, this));
         hbox->addWidget(m_buildConfigurationComboBox);
 
         m_addButton = new QPushButton(this);
@@ -167,6 +169,8 @@ void BuildSettingsWidget::setupUi()
     }
 
     m_buildConfiguration = m_target->activeBuildConfiguration();
+    BuildConfigurationModel *model = static_cast<BuildConfigurationModel *>(m_buildConfigurationComboBox->model());
+    m_buildConfigurationComboBox->setCurrentIndex(model->indexFor(m_buildConfiguration).row());
 
     updateAddButtonMenu();
     updateBuildSettings();
@@ -180,42 +184,11 @@ void BuildSettingsWidget::setupUi()
     connect(m_target, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
             this, SLOT(updateActiveConfiguration()));
 
-    connect(m_target, SIGNAL(addedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
-            this, SLOT(addedBuildConfiguration(ProjectExplorer::BuildConfiguration*)));
-
-    connect(m_target, SIGNAL(removedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
-            this, SLOT(removedBuildConfiguration(ProjectExplorer::BuildConfiguration*)));
-
-    foreach (BuildConfiguration *bc, m_target->buildConfigurations()) {
-        connect(bc, SIGNAL(displayNameChanged()),
-                this, SLOT(buildConfigurationDisplayNameChanged()));
-    }
-
     if (m_target->buildConfigurationFactory())
         connect(m_target->buildConfigurationFactory(), SIGNAL(availableCreationIdsChanged()),
                 SLOT(updateAddButtonMenu()));
 }
 
-void BuildSettingsWidget::addedBuildConfiguration(BuildConfiguration *bc)
-{
-    connect(bc, SIGNAL(displayNameChanged()),
-            this, SLOT(buildConfigurationDisplayNameChanged()));
-}
-
-void BuildSettingsWidget::removedBuildConfiguration(BuildConfiguration *bc)
-{
-    disconnect(bc, SIGNAL(displayNameChanged()),
-               this, SLOT(buildConfigurationDisplayNameChanged()));
-}
-
-void BuildSettingsWidget::buildConfigurationDisplayNameChanged()
-{
-    for (int i = 0; i < m_buildConfigurationComboBox->count(); ++i) {
-        BuildConfiguration *bc = m_buildConfigurationComboBox->itemData(i).value<BuildConfiguration *>();
-        m_buildConfigurationComboBox->setItemText(i, bc->displayName());
-    }
-}
-
 void BuildSettingsWidget::addSubWidget(const QString &name, BuildConfigWidget *widget)
 {
     widget->setContentsMargins(m_leftMargin, 10, 0, 0);
@@ -268,9 +241,6 @@ void BuildSettingsWidget::updateAddButtonMenu()
 
 void BuildSettingsWidget::updateBuildSettings()
 {
-    // Delete old tree items
-    bool blocked = m_buildConfigurationComboBox->blockSignals(true);
-    m_buildConfigurationComboBox->clear();
     clear();
 
     // update buttons
@@ -287,22 +257,14 @@ void BuildSettingsWidget::updateBuildSettings()
     foreach (BuildConfigWidget *subConfigWidget, subConfigWidgets)
         addSubWidget(subConfigWidget->displayName(), subConfigWidget);
 
-    // Add tree items
-    foreach (BuildConfiguration *bc, m_target->buildConfigurations()) {
-        m_buildConfigurationComboBox->addItem(bc->displayName(), QVariant::fromValue<BuildConfiguration *>(bc));
-        if (bc == m_buildConfiguration)
-            m_buildConfigurationComboBox->setCurrentIndex(m_buildConfigurationComboBox->count() - 1);
-    }
-
     foreach (BuildConfigWidget *widget, subWidgets())
         widget->init(m_buildConfiguration);
-
-    m_buildConfigurationComboBox->blockSignals(blocked);
 }
 
 void BuildSettingsWidget::currentIndexChanged(int index)
 {
-    BuildConfiguration *buildConfiguration = m_buildConfigurationComboBox->itemData(index).value<BuildConfiguration *>();
+    BuildConfigurationModel *model = static_cast<BuildConfigurationModel *>(m_buildConfigurationComboBox->model());
+    BuildConfiguration *buildConfiguration = model->buildConfigurationAt(index);
     m_target->setActiveBuildConfiguration(buildConfiguration);
 }
 
@@ -313,12 +275,8 @@ void BuildSettingsWidget::updateActiveConfiguration()
 
     m_buildConfiguration = m_target->activeBuildConfiguration();
 
-    for (int i = 0; i < m_buildConfigurationComboBox->count(); ++i) {
-        if (m_buildConfigurationComboBox->itemData(i).value<BuildConfiguration *>() == m_buildConfiguration) {
-            m_buildConfigurationComboBox->setCurrentIndex(i);
-            break;
-        }
-    }
+    BuildConfigurationModel *model = static_cast<BuildConfigurationModel *>(m_buildConfigurationComboBox->model());
+    m_buildConfigurationComboBox->setCurrentIndex(model->indexFor(m_buildConfiguration).row());
 
     foreach (QWidget *widget, subWidgets()) {
         if (BuildConfigWidget *buildStepWidget = qobject_cast<BuildConfigWidget*>(widget)) {
diff --git a/src/plugins/projectexplorer/buildsettingspropertiespage.h b/src/plugins/projectexplorer/buildsettingspropertiespage.h
index 5a38dba6279..e93f849c90c 100644
--- a/src/plugins/projectexplorer/buildsettingspropertiespage.h
+++ b/src/plugins/projectexplorer/buildsettingspropertiespage.h
@@ -102,9 +102,6 @@ private slots:
     void deleteConfiguration();
     void updateAddButtonMenu();
 
-    void addedBuildConfiguration(ProjectExplorer::BuildConfiguration *bc);
-    void removedBuildConfiguration(ProjectExplorer::BuildConfiguration *bc);
-    void buildConfigurationDisplayNameChanged();
     void updateActiveConfiguration();
 
 private:
diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.cpp b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
index b71e78f07f5..66e50df2df4 100644
--- a/src/plugins/projectexplorer/miniprojecttargetselector.cpp
+++ b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
@@ -28,6 +28,8 @@
 **************************************************************************/
 
 #include "miniprojecttargetselector.h"
+#include "buildconfigurationmodel.h"
+#include "runconfigurationmodel.h"
 
 #include <utils/qtcassert.h>
 #include <utils/styledbar.h>
@@ -186,6 +188,7 @@ MiniTargetWidget::MiniTargetWidget(Target *target, QWidget *parent) :
         m_buildComboBox->setProperty("hideborder", true);
         m_buildComboBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
         m_buildComboBox->setToolTip(tr("Select active build configuration"));
+        m_buildComboBox->setModel(new BuildConfigurationModel(m_target, this));
     } else {
         m_buildComboBox = 0;
     }
@@ -195,6 +198,8 @@ MiniTargetWidget::MiniTargetWidget(Target *target, QWidget *parent) :
     m_runComboBox ->setProperty("hideborder", true);
     m_runComboBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
     m_runComboBox->setToolTip(tr("Select active run configuration"));
+    RunConfigurationModel *model = new RunConfigurationModel(m_target, this);
+    m_runComboBox->setModel(model);
     int fontSize = font().pointSize();
     setStyleSheet(QString::fromLatin1("QLabel { font-size: %2pt; color: white; } "
                                       "#target { font: bold %1pt;} "
@@ -212,6 +217,9 @@ MiniTargetWidget::MiniTargetWidget(Target *target, QWidget *parent) :
         Q_FOREACH(BuildConfiguration* bc, m_target->buildConfigurations())
                 addBuildConfiguration(bc);
 
+        BuildConfigurationModel *model = static_cast<BuildConfigurationModel *>(m_buildComboBox->model());
+        m_buildComboBox->setCurrentIndex(model->indexFor(m_target->activeBuildConfiguration()).row());
+
         connect(m_target, SIGNAL(addedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
                 SLOT(addBuildConfiguration(ProjectExplorer::BuildConfiguration*)));
         connect(m_target, SIGNAL(removedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
@@ -222,8 +230,8 @@ MiniTargetWidget::MiniTargetWidget(Target *target, QWidget *parent) :
         connect(m_buildComboBox, SIGNAL(currentIndexChanged(int)), SLOT(setActiveBuildConfiguration(int)));
     }
 
-    Q_FOREACH(RunConfiguration* rc, m_target->runConfigurations())
-            addRunConfiguration(rc);
+    m_runComboBox->setEnabled(m_target->runConfigurations().count() > 1);
+    m_runComboBox->setCurrentIndex(model->indexFor(m_target->activeRunConfiguration()).row());
 
     connect(m_target, SIGNAL(addedRunConfiguration(ProjectExplorer::RunConfiguration*)),
             SLOT(addRunConfiguration(ProjectExplorer::RunConfiguration*)));
@@ -280,79 +288,57 @@ ProjectExplorer::Target *MiniTargetWidget::target() const
 
 void MiniTargetWidget::setActiveBuildConfiguration(int index)
 {
-    ProjectExplorer::BuildConfiguration* bc =
-            m_buildComboBox->itemData(index).value<ProjectExplorer::BuildConfiguration*>();
-    m_target->setActiveBuildConfiguration(bc);
+    BuildConfigurationModel *model = static_cast<BuildConfigurationModel *>(m_buildComboBox->model());
+    m_target->setActiveBuildConfiguration(model->buildConfigurationAt(index));
     emit changed();
 }
 
 void MiniTargetWidget::setActiveRunConfiguration(int index)
 {
-    m_target->setActiveRunConfiguration(
-            m_runComboBox->itemData(index).value<ProjectExplorer::RunConfiguration*>());
+    RunConfigurationModel *model = static_cast<RunConfigurationModel *>(m_runComboBox->model());
+    m_target->setActiveRunConfiguration(model->runConfigurationAt(index));
     updateIcon();
     emit changed();
 }
+
 void MiniTargetWidget::setActiveBuildConfiguration()
 {
-    QTC_ASSERT(m_buildComboBox, return)
-    m_buildComboBox->setCurrentIndex(m_buildComboBox->findData(
-            QVariant::fromValue(m_target->activeBuildConfiguration())));
+    QTC_ASSERT(m_buildComboBox, return);
+    BuildConfigurationModel *model = static_cast<BuildConfigurationModel *>(m_buildComboBox->model());
+    m_buildComboBox->setCurrentIndex(model->indexFor(m_target->activeBuildConfiguration()).row());
 }
 
 void MiniTargetWidget::setActiveRunConfiguration()
 {
-    m_runComboBox->setCurrentIndex(m_runComboBox->findData(
-            QVariant::fromValue(m_target->activeRunConfiguration())));
+    RunConfigurationModel *model = static_cast<RunConfigurationModel *>(m_runComboBox->model());
+    m_runComboBox->setCurrentIndex(model->indexFor(m_target->activeRunConfiguration()).row());
 }
 
 void MiniTargetWidget::addRunConfiguration(ProjectExplorer::RunConfiguration* rc)
 {
-    connect(rc, SIGNAL(displayNameChanged()), SLOT(updateDisplayName()));
-    m_runComboBox->addItem(rc->displayName(), QVariant::fromValue(rc));
-    if (m_target->activeRunConfiguration() == rc)
-        m_runComboBox->setCurrentIndex(m_runComboBox->count()-1);
-
-    m_runComboBox->setEnabled(m_runComboBox->count()>1);
+    Q_UNUSED(rc);
+    m_runComboBox->setEnabled(m_target->runConfigurations().count()>1);
 }
 
 void MiniTargetWidget::removeRunConfiguration(ProjectExplorer::RunConfiguration* rc)
 {
-    m_runComboBox->removeItem(m_runComboBox->findData(QVariant::fromValue(rc)));
-    m_runComboBox->setEnabled(m_runComboBox->count()>1);
+    Q_UNUSED(rc);
+    m_runComboBox->setEnabled(m_target->runConfigurations().count()>1);
 }
 
 void MiniTargetWidget::addBuildConfiguration(ProjectExplorer::BuildConfiguration* bc)
 {
+    Q_UNUSED(bc);
     QTC_ASSERT(m_buildComboBox, return);
-    connect(bc, SIGNAL(displayNameChanged()), SLOT(updateDisplayName()));
-    m_buildComboBox->addItem(bc->displayName(), QVariant::fromValue(bc));
-    if (m_target->activeBuildConfiguration() == bc)
-        m_buildComboBox->setCurrentIndex(m_buildComboBox->count()-1);
-
-    m_buildComboBox->setEnabled(m_buildComboBox->count() > 1);
+    connect(bc, SIGNAL(displayNameChanged()), SIGNAL(changed()), Qt::UniqueConnection);
+    m_buildComboBox->setEnabled(m_target->buildConfigurations().count() > 1);
 }
 
 void MiniTargetWidget::removeBuildConfiguration(ProjectExplorer::BuildConfiguration* bc)
 {
+    Q_UNUSED(bc);
     QTC_ASSERT(m_buildComboBox, return);
-    m_buildComboBox->removeItem(m_buildComboBox->findData(QVariant::fromValue(bc)));
-    m_buildComboBox->setEnabled(m_buildComboBox->count() > 1);
-}
-
-void MiniTargetWidget::updateDisplayName()
-{
-    QObject *obj = sender();
-    RunConfiguration *rc = qobject_cast<RunConfiguration*>(obj);
-    BuildConfiguration *bc = qobject_cast<BuildConfiguration*>(obj);
-    if (rc) {
-        m_runComboBox->setItemText(m_runComboBox->findData(QVariant::fromValue(rc)),
-                                   rc->displayName());
-    } else if (bc) {
-        m_buildComboBox->setItemText(m_buildComboBox->findData(QVariant::fromValue(bc)),
-                                     bc->displayName());
-    }
-    emit changed();
+    m_buildComboBox->setEnabled(m_target->buildConfigurations().count() > 1);
 }
 
 bool MiniTargetWidget::hasBuildConfiguration() const
diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.h b/src/plugins/projectexplorer/miniprojecttargetselector.h
index a9c114f5a3f..adaff962f7b 100644
--- a/src/plugins/projectexplorer/miniprojecttargetselector.h
+++ b/src/plugins/projectexplorer/miniprojecttargetselector.h
@@ -90,7 +90,6 @@ private slots:
     void setActiveBuildConfiguration();
     void setActiveRunConfiguration();
 
-    void updateDisplayName();
     void updateIcon();
 
 signals:
diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro
index 822a7b92830..a3ff46b692e 100644
--- a/src/plugins/projectexplorer/projectexplorer.pro
+++ b/src/plugins/projectexplorer/projectexplorer.pro
@@ -80,7 +80,9 @@ HEADERS += projectexplorer.h \
     buildconfigdialog.h \
     ldparser.h \
     linuxiccparser.h \
-    outputformatter.h
+    outputformatter.h \
+    runconfigurationmodel.h \
+    buildconfigurationmodel.h
 SOURCES += projectexplorer.cpp \
     projectwindow.cpp \
     buildmanager.cpp \
@@ -147,7 +149,9 @@ SOURCES += projectexplorer.cpp \
     buildconfigdialog.cpp \
     ldparser.cpp \
     linuxiccparser.cpp \
-    outputformatter.cpp
+    outputformatter.cpp \
+    runconfigurationmodel.cpp \
+    buildconfigurationmodel.cpp
 FORMS += processstep.ui \
     editorsettingspropertiespage.ui \
     runsettingspropertiespage.ui \
diff --git a/src/plugins/projectexplorer/runconfigurationmodel.cpp b/src/plugins/projectexplorer/runconfigurationmodel.cpp
new file mode 100644
index 00000000000..f5fa9697294
--- /dev/null
+++ b/src/plugins/projectexplorer/runconfigurationmodel.cpp
@@ -0,0 +1,180 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "runconfigurationmodel.h"
+#include "target.h"
+#include "runconfiguration.h"
+
+using namespace ProjectExplorer;
+
+///
+/// RunConfigurationsModel
+///
+
+class RunConfigurationComparer
+{
+public:
+    bool operator()(RunConfiguration *a, RunConfiguration *b)
+    {
+        return a->displayName() < b->displayName();
+    }
+};
+
+RunConfigurationModel::RunConfigurationModel(Target *target, QObject *parent)
+    : QAbstractListModel(parent),
+      m_target(target)
+{
+    m_runConfigurations = m_target->runConfigurations();
+    qSort(m_runConfigurations.begin(), m_runConfigurations.end(), RunConfigurationComparer());
+
+    connect(target, SIGNAL(addedRunConfiguration(ProjectExplorer::RunConfiguration*)),
+            this, SLOT(addedRunConfiguration(ProjectExplorer::RunConfiguration*)));
+    connect(target, SIGNAL(removedRunConfiguration(ProjectExplorer::RunConfiguration*)),
+            this, SLOT(removedRunConfiguration(ProjectExplorer::RunConfiguration*)));
+
+    foreach (RunConfiguration *rc, m_runConfigurations)
+        connect(rc, SIGNAL(displayNameChanged()),
+                this, SLOT(displayNameChanged()));
+}
+
+int RunConfigurationModel::rowCount(const QModelIndex &parent) const
+{
+    return parent.isValid() ? 0 : m_runConfigurations.size();
+}
+
+int RunConfigurationModel::columnCount(const QModelIndex &parent) const
+{
+    return parent.isValid() ? 0 : 1;
+}
+
+void RunConfigurationModel::displayNameChanged()
+{
+    RunConfiguration *rc = qobject_cast<RunConfiguration *>(sender());
+    if (!rc)
+        return;
+
+    RunConfigurationComparer compare;
+    // Find the old position
+    int oldPos = m_runConfigurations.indexOf(rc);
+
+    if (oldPos >= 1 && compare(m_runConfigurations.at(oldPos), m_runConfigurations.at(oldPos - 1))) {
+        // We need to move up
+        int newPos = oldPos - 1;
+        while (newPos >= 0 && compare(m_runConfigurations.at(oldPos), m_runConfigurations.at(newPos))) {
+            --newPos;
+        }
+        ++newPos;
+
+        beginMoveRows(QModelIndex(), oldPos, oldPos, QModelIndex(), newPos);
+        m_runConfigurations.insert(newPos, rc);
+        m_runConfigurations.removeAt(oldPos + 1);
+        endMoveRows();
+        // Not only did we move, we also changed...
+        emit dataChanged(index(newPos, 0), index(newPos,0));
+    } else if  (oldPos < m_runConfigurations.size() - 1
+                && compare(m_runConfigurations.at(oldPos + 1), m_runConfigurations.at(oldPos))) {
+        // We need to move down
+        int newPos = oldPos + 1;
+        while (newPos < m_runConfigurations.size()
+            && compare(m_runConfigurations.at(newPos), m_runConfigurations.at(oldPos))) {
+            ++newPos;
+        }
+        beginMoveRows(QModelIndex(), oldPos, oldPos, QModelIndex(), newPos);
+        m_runConfigurations.insert(newPos, rc);
+        m_runConfigurations.removeAt(oldPos);
+        endMoveRows();
+
+        // We need to subtract one since removing at the old place moves the newIndex down
+        emit dataChanged(index(newPos - 1, 0), index(newPos - 1, 0));
+    } else {
+        emit dataChanged(index(oldPos, 0), index(oldPos, 0));
+    }
+}
+
+QVariant RunConfigurationModel::data(const QModelIndex &index, int role) const
+{
+    if (role == Qt::DisplayRole) {
+        const int row = index.row();
+        if (row < m_runConfigurations.size()) {
+            return m_runConfigurations.at(row)->displayName();
+        }
+    }
+
+    return QVariant();
+}
+
+RunConfiguration *RunConfigurationModel::runConfigurationAt(int i)
+{
+    if (i > m_runConfigurations.size() || i < 0)
+        return 0;
+    return m_runConfigurations.at(i);
+}
+
+RunConfiguration *RunConfigurationModel::runConfigurationFor(const QModelIndex &idx)
+{
+    if (idx.row() > m_runConfigurations.size() || idx.row() < 0)
+        return 0;
+    return m_runConfigurations.at(idx.row());
+}
+
+QModelIndex RunConfigurationModel::indexFor(RunConfiguration *rc)
+{
+    int idx = m_runConfigurations.indexOf(rc);
+    if (idx == -1)
+        return QModelIndex();
+    return index(idx, 0);
+}
+
+void RunConfigurationModel::addedRunConfiguration(ProjectExplorer::RunConfiguration *rc)
+{
+    // Find the right place to insert
+    RunConfigurationComparer compare;
+    int i = 0;
+    for (; i < m_runConfigurations.size(); ++i) {
+        if (compare(rc, m_runConfigurations.at(i))) {
+            break;
+        }
+    }
+
+    beginInsertRows(QModelIndex(), i, i);
+    m_runConfigurations.insert(i, rc);
+    endInsertRows();
+
+
+    connect(rc, SIGNAL(displayNameChanged()),
+            this, SLOT(displayNameChanged()));
+}
+
+void RunConfigurationModel::removedRunConfiguration(ProjectExplorer::RunConfiguration *rc)
+{
+    int i = m_runConfigurations.indexOf(rc);
+    beginRemoveRows(QModelIndex(), i, i);
+    m_runConfigurations.removeAt(i);
+    endRemoveRows();
+}
diff --git a/src/plugins/projectexplorer/runconfigurationmodel.h b/src/plugins/projectexplorer/runconfigurationmodel.h
new file mode 100644
index 00000000000..243916769ad
--- /dev/null
+++ b/src/plugins/projectexplorer/runconfigurationmodel.h
@@ -0,0 +1,67 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef RUNCONFIGURATIONMODEL_H
+#define RUNCONFIGURATIONMODEL_H
+
+#include <QtCore/QAbstractItemModel>
+
+namespace ProjectExplorer {
+class Target;
+class RunConfiguration;
+
+/*! A model to represent the run configurations of a target.
+    To be used in for the drop down of comboboxes
+    Does automatically adjust itself to added and removed RunConfigurations
+*/
+class RunConfigurationModel : public QAbstractListModel
+{
+    Q_OBJECT
+public:
+    RunConfigurationModel(Target *target, QObject *parent = 0);
+
+    int rowCount(const QModelIndex &parent = QModelIndex()) const;
+    int columnCount(const QModelIndex &parent = QModelIndex()) const;
+    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+    RunConfiguration *runConfigurationAt(int i);
+    RunConfiguration *runConfigurationFor(const QModelIndex &idx);
+    QModelIndex indexFor(RunConfiguration *rc);
+private slots:
+    void addedRunConfiguration(ProjectExplorer::RunConfiguration*);
+    void removedRunConfiguration(ProjectExplorer::RunConfiguration*);
+    void displayNameChanged();
+private:
+    Target *m_target;
+    QList<RunConfiguration *> m_runConfigurations;
+};
+
+}
+
+#endif // RUNCONFIGURATIONMODEL_H
diff --git a/src/plugins/projectexplorer/runsettingspropertiespage.cpp b/src/plugins/projectexplorer/runsettingspropertiespage.cpp
index 1c56ccbdd8f..624b623ed5d 100644
--- a/src/plugins/projectexplorer/runsettingspropertiespage.cpp
+++ b/src/plugins/projectexplorer/runsettingspropertiespage.cpp
@@ -28,6 +28,7 @@
 **************************************************************************/
 
 #include "runsettingspropertiespage.h"
+#include "runconfigurationmodel.h"
 #include "runconfiguration.h"
 #include "target.h"
 #include "project.h"
@@ -115,111 +116,13 @@ QIcon RunSettingsPanel::icon() const
     return m_icon;
 }
 
-///
-/// RunConfigurationsModel
-///
-
-RunConfigurationsModel::RunConfigurationsModel(Target *target, QObject *parent)
-    : QAbstractListModel(parent),
-      m_target(target)
-{
-    m_runConfigurations = m_target->runConfigurations();
-    connect(target, SIGNAL(addedRunConfiguration(ProjectExplorer::RunConfiguration*)),
-            this, SLOT(addedRunConfiguration(ProjectExplorer::RunConfiguration*)));
-    connect(target, SIGNAL(removedRunConfiguration(ProjectExplorer::RunConfiguration*)),
-            this, SLOT(removedRunConfiguration(ProjectExplorer::RunConfiguration*)));
-
-    foreach (RunConfiguration *rc, m_runConfigurations)
-        connect(rc, SIGNAL(displayNameChanged()),
-                this, SLOT(displayNameChanged()));
-}
-
-int RunConfigurationsModel::rowCount(const QModelIndex &parent) const
-{
-    return parent.isValid() ? 0 : m_runConfigurations.size();
-}
-
-int RunConfigurationsModel::columnCount(const QModelIndex &parent) const
-{
-    return parent.isValid() ? 0 : 1;
-}
-
-void RunConfigurationsModel::displayNameChanged()
-{
-    RunConfiguration *rc = qobject_cast<RunConfiguration *>(sender());
-    QTC_ASSERT(rc, return);
-    for (int i = 0; i < m_runConfigurations.size(); ++i) {
-        if (m_runConfigurations.at(i) == rc) {
-            emit dataChanged(index(i, 0), index(i,0));
-            break;
-        }
-    }
-}
-
-QVariant RunConfigurationsModel::data(const QModelIndex &index, int role) const
-{
-    if (role == Qt::DisplayRole) {
-        const int row = index.row();
-        if (row < m_runConfigurations.size()) {
-            return m_runConfigurations.at(row)->displayName();
-        }
-    }
-
-    return QVariant();
-}
-
-RunConfiguration *RunConfigurationsModel::runConfigurationAt(int i)
-{
-    if (i > m_runConfigurations.size() || i < 0)
-        return 0;
-    return m_runConfigurations.at(i);
-}
-
-RunConfiguration *RunConfigurationsModel::runConfigurationFor(const QModelIndex &idx)
-{
-    if (idx.row() > m_runConfigurations.size() || idx.row() < 0)
-        return 0;
-    return m_runConfigurations.at(idx.row());
-}
-
-QModelIndex RunConfigurationsModel::indexFor(RunConfiguration *rc)
-{
-    int idx = m_runConfigurations.indexOf(rc);
-    if (idx == -1)
-        return QModelIndex();
-    return index(idx, 0);
-}
-
-void RunConfigurationsModel::addedRunConfiguration(ProjectExplorer::RunConfiguration *rc)
-{
-    int i = m_target->runConfigurations().indexOf(rc);
-    QTC_ASSERT(i > 0, return);
-    beginInsertRows(QModelIndex(), i, i);
-    m_runConfigurations.insert(i, rc);
-    endInsertRows();
-    QTC_ASSERT(m_runConfigurations == m_target->runConfigurations(), return);
-    connect(rc, SIGNAL(displayNameChanged()),
-            this, SLOT(displayNameChanged()));
-}
-
-void RunConfigurationsModel::removedRunConfiguration(ProjectExplorer::RunConfiguration *rc)
-{
-    int i = m_runConfigurations.indexOf(rc);
-    QTC_ASSERT(i >= 0, return);
-    beginRemoveRows(QModelIndex(), i, i);
-    m_runConfigurations.removeAt(i);
-    endRemoveRows();
-    QTC_ASSERT(m_runConfigurations == m_target->runConfigurations(), return);
-}
-
-
 ///
 /// RunSettingsWidget
 ///
 
 RunSettingsWidget::RunSettingsWidget(Target *target)
     : m_target(target),
-      m_runConfigurationsModel(new RunConfigurationsModel(target, this)),
+      m_runConfigurationsModel(new RunConfigurationModel(target, this)),
       m_runConfigurationWidget(0),
       m_ignoreChange(false)
 {
@@ -233,7 +136,7 @@ RunSettingsWidget::RunSettingsWidget(Target *target)
     m_ui->removeToolButton->setText(tr("Remove"));
     m_ui->runConfigurationCombo->setModel(m_runConfigurationsModel);
     m_ui->runConfigurationCombo->setCurrentIndex(
-            m_target->runConfigurations().indexOf(m_target->activeRunConfiguration()));
+            m_runConfigurationsModel->indexFor(m_target->activeRunConfiguration()).row());
 
     m_ui->removeToolButton->setEnabled(m_target->runConfigurations().size() > 1);
 
diff --git a/src/plugins/projectexplorer/runsettingspropertiespage.h b/src/plugins/projectexplorer/runsettingspropertiespage.h
index 9393437a5a5..29eeb04b2e0 100644
--- a/src/plugins/projectexplorer/runsettingspropertiespage.h
+++ b/src/plugins/projectexplorer/runsettingspropertiespage.h
@@ -43,6 +43,7 @@ QT_END_NAMESPACE
 namespace ProjectExplorer {
 
 class RunConfiguration;
+class RunConfigurationModel;
 
 namespace Internal {
 
@@ -52,7 +53,6 @@ namespace Ui {
 class RunSettingsPropertiesPage;
 }
 
-class RunConfigurationsModel;
 class RunSettingsWidget;
 
 class RunSettingsPanelFactory : public ITargetPanelFactory
@@ -94,38 +94,13 @@ private slots:
     void activeRunConfigurationChanged();
 private:
     Target *m_target;
-    RunConfigurationsModel *m_runConfigurationsModel;
+    RunConfigurationModel *m_runConfigurationsModel;
     Ui::RunSettingsPropertiesPage *m_ui;
     QWidget *m_runConfigurationWidget;
     QMenu *m_addMenu;
     bool m_ignoreChange;
 };
 
-/*! A model to represent the run configurations of a target. */
-class RunConfigurationsModel : public QAbstractListModel
-{
-    Q_OBJECT
-public:
-    RunConfigurationsModel(Target *target, QObject *parent = 0);
-
-    int rowCount(const QModelIndex &parent = QModelIndex()) const;
-    int columnCount(const QModelIndex &parent = QModelIndex()) const;
-    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
-
-    RunConfiguration *runConfigurationAt(int i);
-    RunConfiguration *runConfigurationFor(const QModelIndex &idx);
-    QModelIndex indexFor(RunConfiguration *rc);
-private slots:
-    void addedRunConfiguration(ProjectExplorer::RunConfiguration*);
-    void removedRunConfiguration(ProjectExplorer::RunConfiguration*);
-    void displayNameChanged();
-private:
-    Target *m_target;
-    QList<RunConfiguration *> m_runConfigurations;
-};
-
-
-
 } // namespace Internal
 } // namespace ProjectExplorer
 
-- 
GitLab