diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp
index 80d1c9451abeba2219668c027d29305eaa636fc0..ee39135f5d679cd55e0e6a6c457790ce17712ae9 100644
--- a/src/plugins/android/androidconfigurations.cpp
+++ b/src/plugins/android/androidconfigurations.cpp
@@ -44,6 +44,7 @@
 #include <projectexplorer/devicesupport/devicemanager.h>
 #include <projectexplorer/toolchainmanager.h>
 #include <projectexplorer/session.h>
+#include <debugger/debuggeritemmanager.h>
 #include <debugger/debuggerkitinformation.h>
 #include <qtsupport/baseqtversion.h>
 #include <qtsupport/qtkitinformation.h>
diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro
index ce31216535bf8cb7874ebe24d0ead8b1705c241c..7798cf0bfe11c4db75300f6d628af96c1de64d3f 100644
--- a/src/plugins/debugger/debugger.pro
+++ b/src/plugins/debugger/debugger.pro
@@ -24,9 +24,13 @@ HEADERS += \
     debuggercore.h \
     debuggerconstants.h \
     debuggerinternalconstants.h \
+    debuggeritem.h \
+    debuggeritemmanager.h \
+    debuggeritemmodel.h \
     debuggerdialogs.h \
     debuggerengine.h \
     debuggermainwindow.h \
+    debuggeroptionspage.h \
     debuggerplugin.h \
     debuggerprotocol.h \
     debuggerrunconfigurationaspect.h \
@@ -80,12 +84,16 @@ SOURCES += \
     debuggeractions.cpp \
     debuggerdialogs.cpp \
     debuggerengine.cpp \
+    debuggeritem.cpp \
+    debuggeritemmanager.cpp \
+    debuggeritemmodel.cpp \
     debuggermainwindow.cpp \
     debuggerplugin.cpp \
     debuggerprotocol.cpp \
     debuggerrunconfigurationaspect.cpp \
     debuggerrunner.cpp \
     debuggerstreamops.cpp \
+    debuggeroptionspage.cpp \
     debuggerkitconfigwidget.cpp \
     debuggerkitinformation.cpp \
     disassembleragent.cpp \
diff --git a/src/plugins/debugger/debugger.qbs b/src/plugins/debugger/debugger.qbs
index 9032e8466084655a1cf96f209747c49fa444c7ac..709dc128c3c2f373ed96fa883d2e1526de3f115f 100644
--- a/src/plugins/debugger/debugger.qbs
+++ b/src/plugins/debugger/debugger.qbs
@@ -40,9 +40,13 @@ QtcPlugin {
             "debuggerdialogs.cpp", "debuggerdialogs.h",
             "debuggerengine.cpp", "debuggerengine.h",
             "debuggerinternalconstants.h",
+            "debuggeritem.cpp", "debuggeritem.h",
+            "debuggeritemmanager.cpp", "debuggeritemmanager.h",
+            "debuggeritemmodel.cpp", "debuggeritemmodel.h",
             "debuggerkitconfigwidget.cpp", "debuggerkitconfigwidget.h",
             "debuggerkitinformation.cpp", "debuggerkitinformation.h",
             "debuggermainwindow.cpp", "debuggermainwindow.h",
+            "debuggeroptionspage.cpp", "debuggeroptionspage.h",
             "debuggerplugin.cpp", "debuggerplugin.h",
             "debuggerprotocol.cpp", "debuggerprotocol.h",
             "debuggerruncontrolfactory.h",
diff --git a/src/plugins/debugger/debuggeritem.cpp b/src/plugins/debugger/debuggeritem.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9ac30bbb7d4a060e4de5ba3c5fa10651ebf6d7c0
--- /dev/null
+++ b/src/plugins/debugger/debuggeritem.cpp
@@ -0,0 +1,337 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "debuggerkitinformation.h"
+#include "debuggerkitconfigwidget.h"
+#include "debuggeroptionspage.h"
+
+#include <projectexplorer/abi.h>
+#include <utils/fileutils.h>
+
+#include <QProcess>
+#include <QUuid>
+
+using namespace Debugger::Internal;
+using namespace ProjectExplorer;
+using namespace Utils;
+
+static const char DEBUGGER_INFORMATION_COMMAND[] = "Binary";
+static const char DEBUGGER_INFORMATION_DISPLAYNAME[] = "DisplayName";
+static const char DEBUGGER_INFORMATION_ID[] = "Id";
+static const char DEBUGGER_INFORMATION_ENGINETYPE[] = "EngineType";
+static const char DEBUGGER_INFORMATION_AUTODETECTED[] = "AutoDetected";
+static const char DEBUGGER_INFORMATION_ABIS[] = "Abis";
+
+namespace Debugger {
+
+// --------------------------------------------------------------------------
+// DebuggerItem
+// --------------------------------------------------------------------------
+
+DebuggerItem::DebuggerItem()
+{
+    m_id = QUuid::createUuid().toString();
+    m_engineType = NoEngineType;
+    m_isAutoDetected = false;
+}
+
+DebuggerItem::DebuggerItem(const QVariantMap &data)
+{
+    m_command = FileName::fromUserInput(data.value(QLatin1String(DEBUGGER_INFORMATION_COMMAND)).toString());
+    m_id = data.value(QLatin1String(DEBUGGER_INFORMATION_ID)).toString();
+    m_displayName = data.value(QLatin1String(DEBUGGER_INFORMATION_DISPLAYNAME)).toString();
+    m_isAutoDetected = data.value(QLatin1String(DEBUGGER_INFORMATION_AUTODETECTED), false).toBool();
+    m_engineType = DebuggerEngineType(data.value(QLatin1String(DEBUGGER_INFORMATION_ENGINETYPE),
+                                                 static_cast<int>(NoEngineType)).toInt());
+
+    foreach (const QString &a, data.value(QLatin1String(DEBUGGER_INFORMATION_ABIS)).toStringList()) {
+        Abi abi(a);
+        if (abi.isValid())
+            m_abis.append(abi);
+    }
+}
+
+void DebuggerItem::reinitializeFromFile()
+{
+    QProcess proc;
+    proc.start(m_command.toString(), QStringList() << QLatin1String("--version"));
+    proc.waitForStarted();
+    proc.waitForFinished();
+    QByteArray ba = proc.readAll();
+    if (ba.contains("gdb")) {
+        m_engineType = GdbEngineType;
+        const char needle[] = "This GDB was configured as \"";
+        // E.g.  "--host=i686-pc-linux-gnu --target=arm-unknown-nto-qnx6.5.0".
+        // or "i686-linux-gnu"
+        int pos1 = ba.indexOf(needle);
+        if (pos1 != -1) {
+            pos1 += int(sizeof(needle));
+            int pos2 = ba.indexOf('"', pos1 + 1);
+            QByteArray target = ba.mid(pos1, pos2 - pos1);
+            int pos3 = target.indexOf("--target=");
+            if (pos3 >= 0)
+                target = target.mid(pos3 + 9);
+            m_abis.append(Abi::abiFromTargetTriplet(QString::fromLatin1(target)));
+        } else {
+            // Fallback.
+            m_abis = Abi::abisOfBinary(m_command); // FIXME: Wrong.
+        }
+        return;
+    }
+    if (ba.contains("lldb") || ba.startsWith("LLDB")) {
+        m_engineType = LldbEngineType;
+        m_abis = Abi::abisOfBinary(m_command);
+        return;
+    }
+    if (ba.startsWith("Python")) {
+        m_engineType = PdbEngineType;
+        return;
+    }
+    m_engineType = NoEngineType;
+}
+
+QString DebuggerItem::engineTypeName() const
+{
+    switch (m_engineType) {
+    case Debugger::NoEngineType:
+        return DebuggerOptionsPage::tr("Not recognized");
+    case Debugger::GdbEngineType:
+        return QLatin1String("GDB");
+    case Debugger::CdbEngineType:
+        return QLatin1String("CDB");
+    case Debugger::LldbEngineType:
+        return QLatin1String("LLDB");
+    default:
+        return QString();
+    }
+}
+
+QStringList DebuggerItem::abiNames() const
+{
+    QStringList list;
+    foreach (const Abi &abi, m_abis)
+        list.append(abi.toString());
+    return list;
+}
+
+QVariantMap DebuggerItem::toMap() const
+{
+    QVariantMap data;
+    data.insert(QLatin1String(DEBUGGER_INFORMATION_DISPLAYNAME), m_displayName);
+    data.insert(QLatin1String(DEBUGGER_INFORMATION_ID), m_id);
+    data.insert(QLatin1String(DEBUGGER_INFORMATION_COMMAND), m_command.toUserOutput());
+    data.insert(QLatin1String(DEBUGGER_INFORMATION_ENGINETYPE), int(m_engineType));
+    data.insert(QLatin1String(DEBUGGER_INFORMATION_AUTODETECTED), m_isAutoDetected);
+    data.insert(QLatin1String(DEBUGGER_INFORMATION_ABIS), abiNames());
+    return data;
+}
+
+void DebuggerItem::setDisplayName(const QString &displayName)
+{
+    m_displayName = displayName;
+}
+
+void DebuggerItem::setEngineType(const DebuggerEngineType &engineType)
+{
+    m_engineType = engineType;
+}
+
+void DebuggerItem::setCommand(const Utils::FileName &command)
+{
+    m_command = command;
+}
+
+void DebuggerItem::setAutoDetected(bool isAutoDetected)
+{
+    m_isAutoDetected = isAutoDetected;
+}
+
+void DebuggerItem::setAbis(const QList<ProjectExplorer::Abi> &abis)
+{
+    m_abis = abis;
+}
+
+void DebuggerItem::setAbi(const Abi &abi)
+{
+    m_abis.clear();
+    m_abis.append(abi);
+}
+
+static DebuggerItem::MatchLevel matchSingle(const Abi &debuggerAbi, const Abi &targetAbi)
+{
+    if (debuggerAbi.architecture() != Abi::UnknownArchitecture
+            && debuggerAbi.architecture() != targetAbi.architecture())
+        return DebuggerItem::DoesNotMatch;
+
+    if (debuggerAbi.os() != Abi::UnknownOS
+            && debuggerAbi.os() != targetAbi.os())
+        return DebuggerItem::DoesNotMatch;
+
+    if (debuggerAbi.binaryFormat() != Abi::UnknownFormat
+            && debuggerAbi.binaryFormat() != targetAbi.binaryFormat())
+        return DebuggerItem::DoesNotMatch;
+
+    if (debuggerAbi.os() == Abi::WindowsOS) {
+        if (debuggerAbi.osFlavor() == Abi::WindowsMSysFlavor && targetAbi.osFlavor() != Abi::WindowsMSysFlavor)
+            return DebuggerItem::DoesNotMatch;
+        if (debuggerAbi.osFlavor() != Abi::WindowsMSysFlavor && targetAbi.osFlavor() == Abi::WindowsMSysFlavor)
+            return DebuggerItem::DoesNotMatch;
+    }
+
+    if (debuggerAbi.wordWidth() == 64 && targetAbi.wordWidth() == 32)
+        return DebuggerItem::MatchesSomewhat;
+    if (debuggerAbi.wordWidth() != 0 && debuggerAbi.wordWidth() != targetAbi.wordWidth())
+        return DebuggerItem::DoesNotMatch;
+
+    return DebuggerItem::MatchesPerfectly;
+}
+
+DebuggerItem::MatchLevel DebuggerItem::matchTarget(const Abi &targetAbi) const
+{
+    MatchLevel bestMatch = DoesNotMatch;
+    foreach (const Abi &debuggerAbi, m_abis) {
+        MatchLevel currentMatch = matchSingle(debuggerAbi, targetAbi);
+        if (currentMatch > bestMatch)
+            bestMatch = currentMatch;
+    }
+    return bestMatch;
+}
+
+bool Debugger::DebuggerItem::isValid() const
+{
+    return m_engineType != NoEngineType;
+}
+
+} // namespace Debugger;
+
+#ifdef WITH_TESTS
+
+#    include <QTest>
+#    include "debuggerplugin.h"
+
+void Debugger::DebuggerPlugin::testDebuggerMatching_data()
+{
+    QTest::addColumn<QStringList>("debugger");
+    QTest::addColumn<QString>("target");
+    QTest::addColumn<int>("result");
+
+    QTest::newRow("Invalid data")
+            << QStringList()
+            << QString()
+            << int(DebuggerItem::DoesNotMatch);
+    QTest::newRow("Invalid debugger")
+            << QStringList()
+            << QString::fromLatin1("x86-linux-generic-elf-32bit")
+            << int(DebuggerItem::DoesNotMatch);
+    QTest::newRow("Invalid target")
+            << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
+            << QString()
+            << int(DebuggerItem::DoesNotMatch);
+
+    QTest::newRow("Fuzzy match 1")
+            << (QStringList() << QLatin1String("unknown-unknown-unknown-unknown-0bit"))
+            << QString::fromLatin1("x86-linux-generic-elf-32bit")
+            << int(DebuggerItem::MatchesPerfectly); // Is this the expected behavior?
+    QTest::newRow("Fuzzy match 2")
+            << (QStringList() << QLatin1String("unknown-unknown-unknown-unknown-0bit"))
+            << QString::fromLatin1("arm-windows-msys-pe-64bit")
+            << int(DebuggerItem::MatchesPerfectly); // Is this the expected behavior?
+
+    QTest::newRow("Architecture mismatch")
+            << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
+            << QString::fromLatin1("arm-linux-generic-elf-32bit")
+            << int(DebuggerItem::DoesNotMatch);
+    QTest::newRow("OS mismatch")
+            << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
+            << QString::fromLatin1("x86-macosx-generic-elf-32bit")
+            << int(DebuggerItem::DoesNotMatch);
+    QTest::newRow("Format mismatch")
+            << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
+            << QString::fromLatin1("x86-linux-generic-pe-32bit")
+            << int(DebuggerItem::DoesNotMatch);
+
+    QTest::newRow("Linux perfect match")
+            << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
+            << QString::fromLatin1("x86-linux-generic-elf-32bit")
+            << int(DebuggerItem::MatchesPerfectly);
+    QTest::newRow("Linux match")
+            << (QStringList() << QLatin1String("x86-linux-generic-elf-64bit"))
+            << QString::fromLatin1("x86-linux-generic-elf-32bit")
+            << int(DebuggerItem::MatchesSomewhat);
+
+    QTest::newRow("Windows perfect match 1")
+            << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit"))
+            << QString::fromLatin1("x86-windows-msvc2013-pe-64bit")
+            << int(DebuggerItem::MatchesPerfectly);
+    QTest::newRow("Windows perfect match 2")
+            << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit"))
+            << QString::fromLatin1("x86-windows-msvc2012-pe-64bit")
+            << int(DebuggerItem::MatchesPerfectly);
+    QTest::newRow("Windows match 1")
+            << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit"))
+            << QString::fromLatin1("x86-windows-msvc2013-pe-32bit")
+            << int(DebuggerItem::MatchesSomewhat);
+    QTest::newRow("Windows match 2")
+            << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit"))
+            << QString::fromLatin1("x86-windows-msvc2012-pe-32bit")
+            << int(DebuggerItem::MatchesSomewhat);
+    QTest::newRow("Windows mismatch on word size")
+            << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-32bit"))
+            << QString::fromLatin1("x86-windows-msvc2013-pe-64bit")
+            << int(DebuggerItem::DoesNotMatch);
+    QTest::newRow("Windows mismatch on osflavor 1")
+            << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-32bit"))
+            << QString::fromLatin1("x86-windows-msys-pe-64bit")
+            << int(DebuggerItem::DoesNotMatch);
+    QTest::newRow("Windows mismatch on osflavor 2")
+            << (QStringList() << QLatin1String("x86-windows-msys-pe-32bit"))
+            << QString::fromLatin1("x86-windows-msvc2010-pe-64bit")
+            << int(DebuggerItem::DoesNotMatch);
+}
+
+void Debugger::DebuggerPlugin::testDebuggerMatching()
+{
+    QFETCH(QStringList, debugger);
+    QFETCH(QString, target);
+    QFETCH(int, result);
+
+    DebuggerItem::MatchLevel expectedLevel = static_cast<DebuggerItem::MatchLevel>(result);
+
+    QList<Abi> debuggerAbis;
+    foreach (const QString &abi, debugger)
+        debuggerAbis << Abi(abi);
+
+    DebuggerItem item;
+    item.setAbis(debuggerAbis);
+
+    DebuggerItem::MatchLevel level = item.matchTarget(Abi(target));
+
+    QCOMPARE(expectedLevel, level);
+}
+#endif
diff --git a/src/plugins/debugger/debuggeritem.h b/src/plugins/debugger/debuggeritem.h
new file mode 100644
index 0000000000000000000000000000000000000000..9809da22c7b01214f3e795dafda545c92d89e8fc
--- /dev/null
+++ b/src/plugins/debugger/debuggeritem.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef DEBUGGER_DEBUGGERITEM_H
+#define DEBUGGER_DEBUGGERITEM_H
+
+#include "debugger_global.h"
+#include "debuggerconstants.h"
+
+#include <projectexplorer/abi.h>
+
+#include <utils/fileutils.h>
+
+#include <QList>
+#include <QVariant>
+
+namespace Debugger {
+
+// -----------------------------------------------------------------------
+// DebuggerItem
+// -----------------------------------------------------------------------
+
+class DEBUGGER_EXPORT DebuggerItem
+{
+public:
+    DebuggerItem();
+    DebuggerItem(const QVariantMap &data);
+
+    bool canClone() const { return true; }
+    bool isValid() const;
+    QString engineTypeName() const;
+
+    QVariantMap toMap() const;
+    void reinitializeFromFile();
+
+    QVariant id() const { return m_id; }
+
+    QString displayName() const { return m_displayName; }
+    void setDisplayName(const QString &displayName);
+
+    DebuggerEngineType engineType() const { return m_engineType; }
+    void setEngineType(const DebuggerEngineType &engineType);
+
+    Utils::FileName command() const { return m_command; }
+    void setCommand(const Utils::FileName &command);
+
+    bool isAutoDetected() const { return m_isAutoDetected; }
+    void setAutoDetected(bool isAutoDetected);
+
+    QList<ProjectExplorer::Abi> abis() const { return m_abis; }
+    void setAbis(const QList<ProjectExplorer::Abi> &abis);
+    void setAbi(const ProjectExplorer::Abi &abi);
+
+    enum MatchLevel { DoesNotMatch, MatchesSomewhat, MatchesPerfectly };
+    MatchLevel matchTarget(const ProjectExplorer::Abi &targetAbi) const;
+
+    QStringList abiNames() const;
+
+private:
+    QVariant m_id;
+    QString m_displayName;
+    DebuggerEngineType m_engineType;
+    Utils::FileName m_command;
+    bool m_isAutoDetected;
+    QList<ProjectExplorer::Abi> m_abis;
+};
+
+} // namespace Debugger
+
+#endif // DEBUGGER_DEBUGGERITEM_H
diff --git a/src/plugins/debugger/debuggeritemmanager.cpp b/src/plugins/debugger/debuggeritemmanager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e9df26be1ef11be23af4de0ae35df0508565294a
--- /dev/null
+++ b/src/plugins/debugger/debuggeritemmanager.cpp
@@ -0,0 +1,408 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "debuggeritemmanager.h"
+
+#include "debuggeritemmodel.h"
+#include "debuggerkitinformation.h"
+
+#include <coreplugin/icore.h>
+
+#include <utils/environment.h>
+#include <utils/fileutils.h>
+#include <utils/persistentsettings.h>
+#include <utils/qtcassert.h>
+
+#include <QDebug>
+#include <QDir>
+#include <QFileInfo>
+
+using namespace ProjectExplorer;
+using namespace Utils;
+
+namespace Debugger {
+
+static const char DEBUGGER_COUNT_KEY[] = "DebuggerItem.Count";
+static const char DEBUGGER_DATA_KEY[] = "DebuggerItem.";
+static const char DEBUGGER_LEGACY_FILENAME[] = "/qtcreator/profiles.xml";
+static const char DEBUGGER_FILE_VERSION_KEY[] = "Version";
+static const char DEBUGGER_FILENAME[] = "/qtcreator/debuggers.xml";
+
+// --------------------------------------------------------------------------
+// DebuggerItemManager
+// --------------------------------------------------------------------------
+
+static DebuggerItemManager *m_instance = 0;
+
+static FileName userSettingsFileName()
+{
+    QFileInfo settingsLocation(Core::ICore::settings()->fileName());
+    return FileName::fromString(settingsLocation.absolutePath() + QLatin1String(DEBUGGER_FILENAME));
+}
+
+static void readDebuggers(const FileName &fileName, bool isSystem)
+{
+    PersistentSettingsReader reader;
+    if (!reader.load(fileName))
+        return;
+    QVariantMap data = reader.restoreValues();
+
+    // Check version
+    int version = data.value(QLatin1String(DEBUGGER_FILE_VERSION_KEY), 0).toInt();
+    if (version < 1)
+        return;
+
+    int count = data.value(QLatin1String(DEBUGGER_COUNT_KEY), 0).toInt();
+    for (int i = 0; i < count; ++i) {
+        const QString key = QString::fromLatin1(DEBUGGER_DATA_KEY) + QString::number(i);
+        if (!data.contains(key))
+            continue;
+        const QVariantMap dbMap = data.value(key).toMap();
+        DebuggerItem item(dbMap);
+        if (isSystem) {
+            item.setAutoDetected(true);
+            // SDK debuggers are always considered to be up-to-date, so no need to recheck them.
+        } else {
+            // User settings.
+            if (item.isAutoDetected() && !item.isValid()) {
+                qWarning() << QString::fromLatin1("DebuggerItem \"%1\" (%2) dropped since it is not valid")
+                              .arg(item.command().toString()).arg(item.id().toString());
+                continue;
+            }
+        }
+        DebuggerItemManager::registerDebugger(item);
+    }
+}
+
+QList<DebuggerItem> DebuggerItemManager::m_debuggers;
+Internal::DebuggerItemModel* DebuggerItemManager::m_model = 0;
+PersistentSettingsWriter * DebuggerItemManager::m_writer = 0;
+
+DebuggerItemManager::DebuggerItemManager(QObject *parent)
+    : QObject(parent)
+{
+    m_instance = this;
+    m_writer = new PersistentSettingsWriter(userSettingsFileName(), QLatin1String("QtCreatorDebugger"));
+    m_model = new Debugger::Internal::DebuggerItemModel(this);
+    connect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()),
+            this, SLOT(saveDebuggers()));
+}
+
+QObject *DebuggerItemManager::instance()
+{
+    return m_instance;
+}
+
+DebuggerItemManager::~DebuggerItemManager()
+{
+    disconnect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()),
+            this, SLOT(saveDebuggers()));
+    delete m_writer;
+}
+
+QList<DebuggerItem> DebuggerItemManager::debuggers()
+{
+    return m_debuggers;
+}
+
+Internal::DebuggerItemModel *DebuggerItemManager::model()
+{
+    return m_model;
+}
+
+void DebuggerItemManager::autoDetectCdbDebuggers()
+{
+    QList<FileName> cdbs;
+
+    QStringList programDirs;
+    programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramFiles")));
+    programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramFiles(x86)")));
+    programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramW6432")));
+
+    foreach (const QString &dirName, programDirs) {
+        if (dirName.isEmpty())
+            continue;
+        QDir dir(dirName);
+        // Windows SDK's starting from version 8 live in
+        // "ProgramDir\Windows Kits\<version>"
+        const QString windowsKitsFolderName = QLatin1String("Windows Kits");
+        if (dir.exists(windowsKitsFolderName)) {
+            QDir windowKitsFolder = dir;
+            if (windowKitsFolder.cd(windowsKitsFolderName)) {
+                // Check in reverse order (latest first)
+                const QFileInfoList kitFolders =
+                    windowKitsFolder.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot,
+                                                   QDir::Time | QDir::Reversed);
+                foreach (const QFileInfo &kitFolderFi, kitFolders) {
+                    const QString path = kitFolderFi.absoluteFilePath();
+                    const QFileInfo cdb32(path + QLatin1String("/Debuggers/x86/cdb.exe"));
+                    if (cdb32.isExecutable())
+                        cdbs.append(FileName::fromString(cdb32.absoluteFilePath()));
+                    const QFileInfo cdb64(path + QLatin1String("/Debuggers/x64/cdb.exe"));
+                    if (cdb64.isExecutable())
+                        cdbs.append(FileName::fromString(cdb64.absoluteFilePath()));
+                }
+            }
+        }
+
+        // Pre Windows SDK 8: Check 'Debugging Tools for Windows'
+        foreach (const QFileInfo &fi, dir.entryInfoList(QStringList(QLatin1String("Debugging Tools for Windows*")),
+                                                        QDir::Dirs | QDir::NoDotAndDotDot)) {
+            FileName filePath(fi);
+            filePath.appendPath(QLatin1String("cdb.exe"));
+            if (!cdbs.contains(filePath))
+                cdbs.append(filePath);
+        }
+    }
+
+    foreach (const FileName &cdb, cdbs) {
+        if (findByCommand(cdb))
+            continue;
+        DebuggerItem item;
+        item.setAutoDetected(true);
+        item.setAbis(Abi::abisOfBinary(cdb));
+        item.setCommand(cdb);
+        item.setEngineType(CdbEngineType);
+        item.setDisplayName(uniqueDisplayName(tr("Auto-detected CDB at %1").arg(cdb.toUserOutput())));
+        addDebugger(item);
+    }
+}
+
+void DebuggerItemManager::autoDetectGdbOrLldbDebuggers()
+{
+    QStringList filters;
+    filters.append(QLatin1String("gdb-i686-pc-mingw32"));
+    filters.append(QLatin1String("gdb"));
+    filters.append(QLatin1String("lldb"));
+    filters.append(QLatin1String("lldb-*"));
+
+//    DebuggerItem result;
+//    result.setAutoDetected(true);
+//    result.setDisplayName(tr("Auto-detected for Tool Chain %1").arg(tc->displayName()));
+    /*
+    // Check suggestions from the SDK.
+    Environment env = Environment::systemEnvironment();
+    if (tc) {
+        tc->addToEnvironment(env); // Find MinGW gdb in toolchain environment.
+        QString path = tc->suggestedDebugger().toString();
+        if (!path.isEmpty()) {
+            const QFileInfo fi(path);
+            if (!fi.isAbsolute())
+                path = env.searchInPath(path);
+            result.command = FileName::fromString(path);
+            result.engineType = engineTypeFromBinary(path);
+            return maybeAddDebugger(result, false);
+        }
+    }
+    */
+
+    QFileInfoList suspects;
+
+    QStringList path = Environment::systemEnvironment().path();
+    foreach (const QString &base, path) {
+        QDir dir(base);
+        dir.setNameFilters(filters);
+        suspects += dir.entryInfoList();
+    }
+
+    foreach (const QFileInfo &fi, suspects) {
+        if (fi.exists()) {
+            FileName command = FileName::fromString(fi.absoluteFilePath());
+            if (findByCommand(command))
+                continue;
+            DebuggerItem item;
+            item.setCommand(command);
+            item.reinitializeFromFile();
+            //: %1: Debugger engine type (GDB, LLDB, CDB...), %2: Path
+            item.setDisplayName(tr("System %1 at %2")
+                .arg(item.engineTypeName()).arg(QDir::toNativeSeparators(fi.absoluteFilePath())));
+            item.setAutoDetected(true);
+            addDebugger(item);
+        }
+    }
+}
+
+void DebuggerItemManager::readLegacyDebuggers()
+{
+    QFileInfo settingsLocation(Core::ICore::settings()->fileName());
+    FileName legacyKits = FileName::fromString(settingsLocation.absolutePath() + QLatin1String(DEBUGGER_LEGACY_FILENAME));
+
+    PersistentSettingsReader reader;
+    if (!reader.load(legacyKits))
+        return;
+
+    foreach (const QVariant &v, reader.restoreValues()) {
+        QVariantMap data1 = v.toMap();
+        QString kitName = data1.value(QLatin1String("PE.Profile.Name")).toString();
+        QVariantMap data2 = data1.value(QLatin1String("PE.Profile.Data")).toMap();
+        QVariant v3 = data2.value(DebuggerKitInformation::id().toString());
+        QString fn;
+        if (v3.type() == QVariant::String)
+            fn = v3.toString();
+        else
+            fn = v3.toMap().value(QLatin1String("Binary")).toString();
+        if (fn.isEmpty())
+            continue;
+        if (fn.startsWith(QLatin1Char('{')))
+            continue;
+        if (fn == QLatin1String("auto"))
+            continue;
+        FileName command = FileName::fromUserInput(fn);
+        if (findByCommand(command))
+            continue;
+        DebuggerItem item;
+        item.setCommand(command);
+        item.setAutoDetected(true);
+        item.reinitializeFromFile();
+        item.setDisplayName(tr("Extracted from Kit %1").arg(kitName));
+        addDebugger(item);
+    }
+}
+
+const DebuggerItem *DebuggerItemManager::findByCommand(const FileName &command)
+{
+    foreach (const DebuggerItem &item, m_debuggers)
+        if (item.command() == command)
+            return &item;
+
+    return 0;
+}
+
+const DebuggerItem *DebuggerItemManager::findById(const QVariant &id)
+{
+    foreach (const DebuggerItem &item, m_debuggers)
+        if (item.id() == id)
+            return &item;
+
+    return 0;
+}
+
+void DebuggerItemManager::restoreDebuggers()
+{
+    // Read debuggers from SDK
+    QFileInfo systemSettingsFile(Core::ICore::settings(QSettings::SystemScope)->fileName());
+    readDebuggers(FileName::fromString(systemSettingsFile.absolutePath() + QLatin1String(DEBUGGER_FILENAME)), true);
+
+    // Read all debuggers from user file.
+    readDebuggers(userSettingsFileName(), false);
+
+    // Auto detect current.
+    autoDetectCdbDebuggers();
+    autoDetectGdbOrLldbDebuggers();
+
+    // Add debuggers from pre-3.x profiles.xml
+    readLegacyDebuggers();
+}
+
+void DebuggerItemManager::saveDebuggers()
+{
+    QTC_ASSERT(m_writer, return);
+    QVariantMap data;
+    data.insert(QLatin1String(DEBUGGER_FILE_VERSION_KEY), 1);
+
+    int count = 0;
+    foreach (const DebuggerItem &item, m_debuggers) {
+        if (item.isValid()) {
+            QVariantMap tmp = item.toMap();
+            if (tmp.isEmpty())
+                continue;
+            data.insert(QString::fromLatin1(DEBUGGER_DATA_KEY) + QString::number(count), tmp);
+            ++count;
+        }
+    }
+    data.insert(QLatin1String(DEBUGGER_COUNT_KEY), count);
+    m_writer->save(data, Core::ICore::mainWindow());
+
+    // Do not save default debuggers as they are set by the SDK.
+}
+
+QVariant DebuggerItemManager::registerDebugger(const DebuggerItem &item)
+{
+    if (findByCommand(item.command()))
+        return item.id();
+
+    return addDebugger(item);
+}
+
+void DebuggerItemManager::deregisterDebugger(const DebuggerItem &item)
+{
+    if (findByCommand(item.command()))
+        removeDebugger(item.id());
+}
+
+QVariant DebuggerItemManager::addDebugger(const DebuggerItem &item)
+{
+    QTC_ASSERT(!item.command().isEmpty(), return QVariant());
+    QTC_ASSERT(!item.displayName().isEmpty(), return QVariant());
+    QTC_ASSERT(item.engineType() != NoEngineType, return QVariant());
+    QTC_ASSERT(item.id().isValid(), return QVariant());
+    m_debuggers.append(item);
+    m_model->addDebugger(item);
+    return item.id();
+}
+
+void DebuggerItemManager::removeDebugger(const QVariant &id)
+{
+    bool ok = false;
+    for (int i = 0, n = m_debuggers.size(); i != n; ++i) {
+        if (m_debuggers.at(i).id() == id) {
+            m_debuggers.removeAt(i);
+            ok = true;
+            break;
+        }
+    }
+
+    QTC_ASSERT(ok, return);
+    m_model->removeDebugger(id);
+}
+
+QString DebuggerItemManager::uniqueDisplayName(const QString &base)
+{
+    foreach (const DebuggerItem &item, m_debuggers)
+        if (item.displayName() == base)
+            return uniqueDisplayName(base + QLatin1String(" (1)"));
+
+    return base;
+}
+
+void DebuggerItemManager::setItemData(const QVariant &id, const QString &displayName, const FileName &fileName)
+{
+    for (int i = 0, n = m_debuggers.size(); i != n; ++i) {
+        DebuggerItem &item = m_debuggers[i];
+        if (item.id() == id) {
+            item.setDisplayName(displayName);
+            item.setCommand(fileName);
+            item.reinitializeFromFile();
+            emit m_model->updateDebugger(item.id());
+            break;
+        }
+    }
+}
+
+} // namespace Debugger;
diff --git a/src/plugins/debugger/debuggeritemmanager.h b/src/plugins/debugger/debuggeritemmanager.h
new file mode 100644
index 0000000000000000000000000000000000000000..057cfd58b12d05938a825d01dd8be48e54470679
--- /dev/null
+++ b/src/plugins/debugger/debuggeritemmanager.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef DEBUGGER_DEBUGGERITEMMANAGER_H
+#define DEBUGGER_DEBUGGERITEMMANAGER_H
+
+#include "debugger_global.h"
+#include "debuggeritem.h"
+#include "debuggeritemmodel.h"
+
+#include <QList>
+#include <QObject>
+#include <QString>
+
+namespace Utils { class PersistentSettingsWriter; }
+
+namespace Debugger {
+
+// -----------------------------------------------------------------------
+// DebuggerItemManager
+// -----------------------------------------------------------------------
+
+class DEBUGGER_EXPORT DebuggerItemManager : public QObject
+{
+    Q_OBJECT
+
+public:
+    static QObject *instance();
+    ~DebuggerItemManager();
+
+    static QList<DebuggerItem> debuggers();
+    static Debugger::Internal::DebuggerItemModel *model();
+
+    static QVariant registerDebugger(const DebuggerItem &item);
+    static void deregisterDebugger(const DebuggerItem &item);
+
+    static const DebuggerItem *findByCommand(const Utils::FileName &command);
+    static const DebuggerItem *findById(const QVariant &id);
+
+    static void restoreDebuggers();
+    static QString uniqueDisplayName(const QString &base);
+    static void setItemData(const QVariant &id, const QString& displayName, const Utils::FileName &fileName);
+
+    static void removeDebugger(const QVariant &id);
+    static QVariant addDebugger(const DebuggerItem &item);
+
+public slots:
+    void saveDebuggers();
+
+private:
+    explicit DebuggerItemManager(QObject *parent = 0);
+    static void autoDetectGdbOrLldbDebuggers();
+    static void autoDetectCdbDebuggers();
+    static void readLegacyDebuggers();
+
+    static Utils::PersistentSettingsWriter *m_writer;
+    static QList<DebuggerItem> m_debuggers;
+    static Debugger::Internal::DebuggerItemModel *m_model;
+
+    friend class Internal::DebuggerItemModel;
+    friend class DebuggerPlugin; // Enable constrcutor for DebuggerPlugin
+};
+
+} // namespace Debugger
+
+#endif // DEBUGGER_DEBUGGERITEMMANAGER_H
diff --git a/src/plugins/debugger/debuggeritemmodel.cpp b/src/plugins/debugger/debuggeritemmodel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..635404684fbc233c04e42ce8ea03ba976b506575
--- /dev/null
+++ b/src/plugins/debugger/debuggeritemmodel.cpp
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "debuggeritemmodel.h"
+
+#include "debuggeritem.h"
+#include "debuggeritemmanager.h"
+
+#include <utils/qtcassert.h>
+
+namespace Debugger {
+namespace Internal {
+
+static QList<QStandardItem *> describeItem(const DebuggerItem &item)
+{
+    QList<QStandardItem *> row;
+    row.append(new QStandardItem(item.displayName()));
+    row.append(new QStandardItem(item.command().toUserOutput()));
+    row.append(new QStandardItem(item.engineTypeName()));
+    row.at(0)->setData(item.id());
+    row.at(0)->setEditable(false);
+    row.at(1)->setEditable(false);
+    row.at(2)->setEditable(false);
+    row.at(0)->setSelectable(true);
+    row.at(1)->setSelectable(true);
+    row.at(2)->setSelectable(true);
+    return row;
+}
+
+static QList<QStandardItem *> createRow(const QString &display)
+{
+    QList<QStandardItem *> row;
+    row.append(new QStandardItem(display));
+    row.append(new QStandardItem());
+    row.append(new QStandardItem());
+    row.at(0)->setEditable(false);
+    row.at(1)->setEditable(false);
+    row.at(2)->setEditable(false);
+    row.at(0)->setSelectable(false);
+    row.at(1)->setSelectable(false);
+    row.at(2)->setSelectable(false);
+    return row;
+}
+
+// --------------------------------------------------------------------------
+// DebuggerItemModel
+// --------------------------------------------------------------------------
+
+DebuggerItemModel::DebuggerItemModel(QObject *parent)
+    : QStandardItemModel(parent)
+{
+    setColumnCount(3);
+
+    QList<QStandardItem *> row = createRow(tr("Auto-detected"));
+    m_autoRoot = row.at(0);
+    appendRow(row);
+
+    row = createRow(tr("Manual"));
+    m_manualRoot = row.at(0);
+    appendRow(row);
+}
+
+QVariant DebuggerItemModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+    if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
+        switch (section) {
+        case 0:
+            return tr("Name");
+        case 1:
+            return tr("Path");
+        case 2:
+            return tr("Type");
+        }
+    }
+    return QVariant();
+}
+
+QStandardItem *DebuggerItemModel::currentStandardItem() const
+{
+    return findStandardItemById(m_currentDebugger);
+}
+
+QStandardItem *DebuggerItemModel::findStandardItemById(const QVariant &id) const
+{
+    for (int i = 0, n = m_autoRoot->rowCount(); i != n; ++i) {
+        QStandardItem *sitem = m_autoRoot->child(i);
+        if (sitem->data() == id)
+            return sitem;
+    }
+    for (int i = 0, n = m_manualRoot->rowCount(); i != n; ++i) {
+        QStandardItem *sitem = m_manualRoot->child(i);
+        if (sitem->data() == id)
+            return sitem;
+    }
+    return 0;
+}
+
+QModelIndex DebuggerItemModel::currentIndex() const
+{
+    QStandardItem *current = currentStandardItem();
+    return current ? current->index() : QModelIndex();
+}
+
+QModelIndex DebuggerItemModel::lastIndex() const
+{
+    int n = m_manualRoot->rowCount();
+    QStandardItem *current = m_manualRoot->child(n - 1);
+    return current ? current->index() : QModelIndex();
+}
+
+void DebuggerItemModel::markCurrentDirty()
+{
+    QStandardItem *sitem = currentStandardItem();
+    QTC_ASSERT(sitem, return);
+    QFont font = sitem->font();
+    font.setBold(true);
+    sitem->setFont(font);
+}
+
+void DebuggerItemModel::addDebugger(const DebuggerItem &item)
+{
+    QTC_ASSERT(item.id().isValid(), return);
+    QList<QStandardItem *> row = describeItem(item);
+    (item.isAutoDetected() ? m_autoRoot : m_manualRoot)->appendRow(row);
+    emit debuggerAdded(item.id(), item.displayName());
+}
+
+void DebuggerItemModel::removeDebugger(const QVariant &id)
+{
+    QStandardItem *sitem = findStandardItemById(id);
+    QTC_ASSERT(sitem, return);
+    QStandardItem *parent = sitem->parent();
+    QTC_ASSERT(parent, return);
+    // This will trigger a change of m_currentDebugger via changing the
+    // view selection.
+    parent->removeRow(sitem->row());
+    emit debuggerRemoved(id);
+}
+
+void DebuggerItemModel::updateDebugger(const QVariant &id)
+{
+    QList<DebuggerItem> debuggers = DebuggerItemManager::debuggers();
+    for (int i = 0, n = debuggers.size(); i != n; ++i) {
+        DebuggerItem &item = debuggers[i];
+        if (item.id() == id) {
+            QStandardItem *sitem = findStandardItemById(id);
+            QTC_ASSERT(sitem, return);
+            QStandardItem *parent = sitem->parent();
+            QTC_ASSERT(parent, return);
+            int row = sitem->row();
+            QFont font = sitem->font();
+            font.setBold(false);
+            parent->child(row, 0)->setData(item.displayName(), Qt::DisplayRole);
+            parent->child(row, 0)->setFont(font);
+            parent->child(row, 1)->setData(item.command().toUserOutput(), Qt::DisplayRole);
+            parent->child(row, 1)->setFont(font);
+            parent->child(row, 2)->setData(item.engineTypeName(), Qt::DisplayRole);
+            parent->child(row, 2)->setFont(font);
+            emit debuggerUpdated(id, item.displayName());
+            return;
+        }
+    }
+}
+
+void DebuggerItemModel::setCurrentIndex(const QModelIndex &index)
+{
+    QStandardItem *sit = itemFromIndex(index);
+    m_currentDebugger = sit ? sit->data() : QVariant();
+}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/debuggeritemmodel.h b/src/plugins/debugger/debuggeritemmodel.h
new file mode 100644
index 0000000000000000000000000000000000000000..bb53c708ab139966ed88981e3e1a1379e964429b
--- /dev/null
+++ b/src/plugins/debugger/debuggeritemmodel.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef DEBUGGER_DEBUGGERITEMMODEL_H
+#define DEBUGGER_DEBUGGERITEMMODEL_H
+
+#include "debuggeritem.h"
+
+#include <QStandardItemModel>
+#include <QVariant>
+
+namespace Debugger {
+namespace Internal {
+
+// -----------------------------------------------------------------------
+// DebuggerItemModel
+//------------------------------------------------------------------------
+
+class DebuggerItemModel : public QStandardItemModel
+{
+    Q_OBJECT
+
+public:
+    DebuggerItemModel(QObject *parent);
+
+    QModelIndex currentIndex() const;
+    QModelIndex lastIndex() const;
+    void setCurrentIndex(const QModelIndex &index);
+    QVariant currentDebugger() const { return m_currentDebugger; }
+    void addDebugger(const DebuggerItem &item);
+    void removeDebugger(const QVariant &id);
+    void updateDebugger(const QVariant &id);
+
+public slots:
+    void markCurrentDirty();
+
+signals:
+    void debuggerAdded(const QVariant &id, const QString &display);
+    void debuggerUpdated(const QVariant &id, const QString &display);
+    void debuggerRemoved(const QVariant &id);
+
+private:
+    // <debug>
+    // friend class Debugger::DebuggerKitInformation;
+    // friend class DebuggerKitConfigWidget;
+    // friend class DebuggerItemConfigWidget;
+    // friend class DebuggerOptionsPage;
+    // </debug>
+
+    QStandardItem *currentStandardItem() const;
+    QStandardItem *findStandardItemById(const QVariant &id) const;
+    QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+
+    QVariant m_currentDebugger;
+
+    QStandardItem *m_autoRoot;
+    QStandardItem *m_manualRoot;
+    QStringList removed;
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // DEBUGGER_DEBUGGERITEMMODEL_H
diff --git a/src/plugins/debugger/debuggerkitconfigwidget.cpp b/src/plugins/debugger/debuggerkitconfigwidget.cpp
index a3e0b611d311bb094e7971f1f0109ba9aaf91cd0..85f4ded64183743c95c8b9405ab0f13191effe11 100644
--- a/src/plugins/debugger/debuggerkitconfigwidget.cpp
+++ b/src/plugins/debugger/debuggerkitconfigwidget.cpp
@@ -29,6 +29,9 @@
 
 #include "debuggerkitconfigwidget.h"
 
+#include "debuggeritemmanager.h"
+#include "debuggeritemmodel.h"
+
 #include <coreplugin/icore.h>
 
 #include <projectexplorer/abi.h>
@@ -64,811 +67,10 @@ using namespace Utils;
 using namespace Debugger::Internal;
 
 namespace Debugger {
-
-static const char debuggingToolsWikiLinkC[] = "http://qt-project.org/wiki/Qt_Creator_Windows_Debugging";
-
-static const char DEBUGGER_DATA_KEY[] = "DebuggerItem.";
-static const char DEBUGGER_COUNT_KEY[] = "DebuggerItem.Count";
-static const char DEBUGGER_FILE_VERSION_KEY[] = "Version";
-static const char DEBUGGER_FILENAME[] = "/qtcreator/debuggers.xml";
-static const char DEBUGGER_LEGACY_FILENAME[] = "/qtcreator/profiles.xml";
-
-// --------------------------------------------------------------------------
-// DebuggerKitInformation
-// --------------------------------------------------------------------------
-
-DebuggerKitInformation::DebuggerKitInformation()
-{
-    setObjectName(QLatin1String("DebuggerKitInformation"));
-    setId(DebuggerKitInformation::id());
-    setPriority(28000);
-}
-
-QVariant DebuggerKitInformation::defaultValue(Kit *k) const
-{
-    ToolChain *tc = ToolChainKitInformation::toolChain(k);
-    QTC_ASSERT(tc, return QVariant());
-
-    const Abi toolChainAbi = tc->targetAbi();
-    foreach (const DebuggerItem &item, DebuggerItemManager::debuggers())
-        foreach (const Abi targetAbi, item.abis())
-            if (targetAbi.isCompatibleWith(toolChainAbi))
-                return item.id();
-
-    return QVariant();
-}
-
-void DebuggerKitInformation::setup(Kit *k)
-{
-    // Get one of the available debugger matching the kit's toolchain.
-    const ToolChain *tc = ToolChainKitInformation::toolChain(k);
-    const Abi toolChainAbi = tc ? tc->targetAbi() : Abi::hostAbi();
-
-    // This can be anything (Id, binary path, "auto")
-    const QVariant rawId = k->value(DebuggerKitInformation::id());
-
-    enum {
-        NotDetected, DetectedAutomatically, DetectedByFile, DetectedById
-    } detection = NotDetected;
-    DebuggerEngineType autoEngine = NoEngineType;
-    FileName fileName;
-
-    // With 3.0 we have:
-    // <value type="QString" key="Debugger.Information">{75ecf347-f221-44c3-b613-ea1d29929cd4}</value>
-    // Before we had:
-    // <valuemap type="QVariantMap" key="Debugger.Information">
-    //    <value type="QString" key="Binary">/data/dev/debugger/gdb-git/gdb/gdb</value>
-    //    <value type="int" key="EngineType">1</value>
-    //  </valuemap>
-    // Or for force auto-detected CDB
-    // <valuemap type="QVariantMap" key="Debugger.Information">
-    //    <value type="QString" key="Binary">auto</value>
-    //    <value type="int" key="EngineType">4</value>
-    //  </valuemap>
-
-    if (rawId.isNull()) {
-        // Initial setup of a kit
-        detection = NotDetected;
-    } else if (rawId.type() == QVariant::String) {
-        detection = DetectedById;
-    } else {
-        QMap<QString, QVariant> map = rawId.toMap();
-        QString binary = map.value(QLatin1String("Binary")).toString();
-        if (binary == QLatin1String("auto")) {
-            detection = DetectedAutomatically;
-            autoEngine = DebuggerEngineType(map.value(QLatin1String("EngineType")).toInt());
-        } else {
-            detection  = DetectedByFile;
-            fileName = FileName::fromUserInput(binary);
-        }
-    }
-
-    const DebuggerItem *bestItem = 0;
-    DebuggerItem::MatchLevel bestLevel = DebuggerItem::DoesNotMatch;
-    foreach (const DebuggerItem &item, DebuggerItemManager::debuggers()) {
-        const DebuggerItem *goodItem = 0;
-        if (detection == DetectedById && item.id() == rawId)
-            goodItem = &item;
-        if (detection == DetectedByFile && item.command() == fileName)
-            goodItem = &item;
-        if (detection == DetectedAutomatically && item.engineType() == autoEngine)
-            goodItem = &item;
-
-        if (goodItem) {
-            DebuggerItem::MatchLevel level = goodItem->matchTarget(toolChainAbi);
-            if (level > bestLevel) {
-                bestLevel = level;
-                bestItem = goodItem;
-            }
-        }
-    }
-
-    // If we have an existing debugger with matching id _and_
-    // matching target ABI we are fine.
-    if (bestItem) {
-        k->setValue(DebuggerKitInformation::id(), bestItem->id());
-        return;
-    }
-
-    // We didn't find an existing debugger that matched by whatever
-    // data we found in the kit (i.e. no id, filename, "auto")
-    // (or what we found did not match ABI-wise)
-    // Let's try to pick one with matching ABI.
-    QVariant bestId;
-    bestLevel = DebuggerItem::DoesNotMatch;
-    foreach (const DebuggerItem &item, DebuggerItemManager::debuggers()) {
-        DebuggerItem::MatchLevel level = item.matchTarget(toolChainAbi);
-        if (level > bestLevel) {
-            bestLevel = level;
-            bestId = item.id();
-        }
-    }
-
-    k->setValue(DebuggerKitInformation::id(), bestId);
-}
-
-
-// This handles the upgrade path from 2.8 to 3.0
-void DebuggerKitInformation::fix(Kit *k)
-{
-    // This can be Id, binary path, but not "auto" anymore.
-    const QVariant rawId = k->value(DebuggerKitInformation::id());
-
-    if (rawId.isNull()) // No debugger set, that is fine.
-        return;
-
-    if (rawId.type() == QVariant::String) {
-        if (!DebuggerItemManager::findById(rawId)) {
-            qWarning("Unknown debugger id %s in kit %s",
-                     qPrintable(rawId.toString()), qPrintable(k->displayName()));
-            k->setValue(DebuggerKitInformation::id(), QVariant());
-        }
-        return; // All fine (now).
-    }
-
-    QMap<QString, QVariant> map = rawId.toMap();
-    QString binary = map.value(QLatin1String("Binary")).toString();
-    if (binary == QLatin1String("auto")) {
-        // This should not happen as "auto" is handled by setup() already.
-        QTC_CHECK(false);
-        k->setValue(DebuggerKitInformation::id(), QVariant());
-        return;
-    }
-
-    FileName fileName = FileName::fromUserInput(binary);
-    const DebuggerItem *item = DebuggerItemManager::findByCommand(fileName);
-    if (!item) {
-        qWarning("Debugger command %s invalid in kit %s",
-                 qPrintable(binary), qPrintable(k->displayName()));
-        k->setValue(DebuggerKitInformation::id(), QVariant());
-        return;
-    }
-
-    k->setValue(DebuggerKitInformation::id(), item->id());
-}
-
-// Check the configuration errors and return a flag mask. Provide a quick check and
-// a verbose one with a list of errors.
-
-enum DebuggerConfigurationErrors {
-    NoDebugger = 0x1,
-    DebuggerNotFound = 0x2,
-    DebuggerNotExecutable = 0x4,
-    DebuggerNeedsAbsolutePath = 0x8
-};
-
-static unsigned debuggerConfigurationErrors(const Kit *k)
-{
-    QTC_ASSERT(k, return NoDebugger);
-
-    const DebuggerItem *item = DebuggerKitInformation::debugger(k);
-    if (!item)
-        return NoDebugger;
-
-    if (item->command().isEmpty())
-        return NoDebugger;
-
-    unsigned result = 0;
-    const QFileInfo fi = item->command().toFileInfo();
-    if (!fi.exists() || fi.isDir())
-        result |= DebuggerNotFound;
-    else if (!fi.isExecutable())
-        result |= DebuggerNotExecutable;
-
-    if (!fi.exists() || fi.isDir()) {
-        if (item->engineType() == NoEngineType)
-            return NoDebugger;
-
-        // We need an absolute path to be able to locate Python on Windows.
-        if (item->engineType() == GdbEngineType)
-            if (const ToolChain *tc = ToolChainKitInformation::toolChain(k))
-                if (tc->targetAbi().os() == Abi::WindowsOS && !fi.isAbsolute())
-                    result |= DebuggerNeedsAbsolutePath;
-    }
-    return result;
-}
-
-const DebuggerItem *DebuggerKitInformation::debugger(const Kit *kit)
-{
-    QTC_ASSERT(kit, return 0);
-    const QVariant id = kit->value(DebuggerKitInformation::id());
-    return DebuggerItemManager::findById(id);
-}
-
-bool DebuggerKitInformation::isValidDebugger(const Kit *k)
-{
-    return debuggerConfigurationErrors(k) == 0;
-}
-
-QList<Task> DebuggerKitInformation::validateDebugger(const Kit *k)
-{
-    QList<Task> result;
-
-    const unsigned errors = debuggerConfigurationErrors(k);
-    if (!errors)
-        return result;
-
-    QString path;
-    if (const DebuggerItem *item = debugger(k))
-        path = item->command().toUserOutput();
-
-    const Core::Id id = ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM;
-    if (errors & NoDebugger)
-        result << Task(Task::Warning, tr("No debugger set up."), FileName(), -1, id);
-
-    if (errors & DebuggerNotFound)
-        result << Task(Task::Error, tr("Debugger '%1' not found.").arg(path),
-                       FileName(), -1, id);
-    if (errors & DebuggerNotExecutable)
-        result << Task(Task::Error, tr("Debugger '%1' not executable.").arg(path), FileName(), -1, id);
-
-    if (errors & DebuggerNeedsAbsolutePath) {
-        const QString message =
-                tr("The debugger location must be given as an "
-                   "absolute path (%1).").arg(path);
-        result << Task(Task::Error, message, FileName(), -1, id);
-    }
-    return result;
-}
-
-KitConfigWidget *DebuggerKitInformation::createConfigWidget(Kit *k) const
-{
-    return new Internal::DebuggerKitConfigWidget(k, this);
-}
-
-KitInformation::ItemList DebuggerKitInformation::toUserOutput(const Kit *k) const
-{
-    return ItemList() << qMakePair(tr("Debugger"), displayString(k));
-}
-
-FileName DebuggerKitInformation::debuggerCommand(const ProjectExplorer::Kit *k)
-{
-    const DebuggerItem *item = debugger(k);
-    QTC_ASSERT(item, return FileName());
-    return item->command();
-}
-
-DebuggerEngineType DebuggerKitInformation::engineType(const ProjectExplorer::Kit *k)
-{
-    const DebuggerItem *item = debugger(k);
-    QTC_ASSERT(item, return NoEngineType);
-    return item->engineType();
-}
-
-QString DebuggerKitInformation::displayString(const Kit *k)
-{
-    const DebuggerItem *item = debugger(k);
-    if (!item)
-        return tr("No Debugger");
-    QString binary = item->command().toUserOutput();
-    QString name = tr("%1 Engine").arg(item->engineTypeName());
-    return binary.isEmpty() ? tr("%1 <None>").arg(name) : tr("%1 using \"%2\"").arg(name, binary);
-}
-
-void DebuggerKitInformation::setDebugger(Kit *k, const QVariant &id)
-{
-    // Only register reasonably complete debuggers.
-    QTC_ASSERT(DebuggerItemManager::findById(id), return);
-    k->setValue(DebuggerKitInformation::id(), id);
-}
-
-Core::Id DebuggerKitInformation::id()
-{
-    return "Debugger.Information";
-}
-
-// --------------------------------------------------------------------------
-// DebuggerItemManager
-// --------------------------------------------------------------------------
-
-static DebuggerItemManager *m_instance = 0;
-
-static FileName userSettingsFileName()
-{
-    QFileInfo settingsLocation(Core::ICore::settings()->fileName());
-    return FileName::fromString(settingsLocation.absolutePath() + QLatin1String(DEBUGGER_FILENAME));
-}
-
-static void readDebuggers(const FileName &fileName, bool isSystem)
-{
-    PersistentSettingsReader reader;
-    if (!reader.load(fileName))
-        return;
-    QVariantMap data = reader.restoreValues();
-
-    // Check version
-    int version = data.value(QLatin1String(DEBUGGER_FILE_VERSION_KEY), 0).toInt();
-    if (version < 1)
-        return;
-
-    int count = data.value(QLatin1String(DEBUGGER_COUNT_KEY), 0).toInt();
-    for (int i = 0; i < count; ++i) {
-        const QString key = QString::fromLatin1(DEBUGGER_DATA_KEY) + QString::number(i);
-        if (!data.contains(key))
-            continue;
-        const QVariantMap dbMap = data.value(key).toMap();
-        DebuggerItem item(dbMap);
-        if (isSystem) {
-            item.setAutoDetected(true);
-            // SDK debuggers are always considered to be up-to-date, so no need to recheck them.
-        } else {
-            // User settings.
-            if (item.isAutoDetected() && !item.isValid()) {
-                qWarning() << QString::fromLatin1("DebuggerItem \"%1\" (%2) dropped since it is not valid")
-                              .arg(item.command().toString()).arg(item.id().toString());
-                continue;
-            }
-        }
-        DebuggerItemManager::registerDebugger(item);
-    }
-}
-
-QList<DebuggerItem> DebuggerItemManager::m_debuggers;
-DebuggerItemModel* DebuggerItemManager::m_model = 0;
-PersistentSettingsWriter * DebuggerItemManager::m_writer = 0;
-
-DebuggerItemManager::DebuggerItemManager(QObject *parent)
-    : QObject(parent)
-{
-    m_instance = this;
-    m_writer = new PersistentSettingsWriter(userSettingsFileName(), QLatin1String("QtCreatorDebugger"));
-    m_model = new Debugger::Internal::DebuggerItemModel(this);
-    connect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()),
-            this, SLOT(saveDebuggers()));
-}
-
-QObject *DebuggerItemManager::instance()
-{
-    return m_instance;
-}
-
-DebuggerItemManager::~DebuggerItemManager()
-{
-    disconnect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()),
-            this, SLOT(saveDebuggers()));
-    delete m_writer;
-}
-
-QList<DebuggerItem> DebuggerItemManager::debuggers()
-{
-    return m_debuggers;
-}
-
-DebuggerItemModel *DebuggerItemManager::model()
-{
-    return m_model;
-}
-
-void DebuggerItemManager::autoDetectCdbDebuggers()
-{
-    QList<FileName> cdbs;
-
-    QStringList programDirs;
-    programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramFiles")));
-    programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramFiles(x86)")));
-    programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramW6432")));
-
-    foreach (const QString &dirName, programDirs) {
-        if (dirName.isEmpty())
-            continue;
-        QDir dir(dirName);
-        // Windows SDK's starting from version 8 live in
-        // "ProgramDir\Windows Kits\<version>"
-        const QString windowsKitsFolderName = QLatin1String("Windows Kits");
-        if (dir.exists(windowsKitsFolderName)) {
-            QDir windowKitsFolder = dir;
-            if (windowKitsFolder.cd(windowsKitsFolderName)) {
-                // Check in reverse order (latest first)
-                const QFileInfoList kitFolders =
-                    windowKitsFolder.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot,
-                                                   QDir::Time | QDir::Reversed);
-                foreach (const QFileInfo &kitFolderFi, kitFolders) {
-                    const QString path = kitFolderFi.absoluteFilePath();
-                    const QFileInfo cdb32(path + QLatin1String("/Debuggers/x86/cdb.exe"));
-                    if (cdb32.isExecutable())
-                        cdbs.append(FileName::fromString(cdb32.absoluteFilePath()));
-                    const QFileInfo cdb64(path + QLatin1String("/Debuggers/x64/cdb.exe"));
-                    if (cdb64.isExecutable())
-                        cdbs.append(FileName::fromString(cdb64.absoluteFilePath()));
-                }
-            }
-        }
-
-        // Pre Windows SDK 8: Check 'Debugging Tools for Windows'
-        foreach (const QFileInfo &fi, dir.entryInfoList(QStringList(QLatin1String("Debugging Tools for Windows*")),
-                                                        QDir::Dirs | QDir::NoDotAndDotDot)) {
-            FileName filePath(fi);
-            filePath.appendPath(QLatin1String("cdb.exe"));
-            if (!cdbs.contains(filePath))
-                cdbs.append(filePath);
-        }
-    }
-
-    foreach (const FileName &cdb, cdbs) {
-        if (findByCommand(cdb))
-            continue;
-        DebuggerItem item;
-        item.setAutoDetected(true);
-        item.setAbis(Abi::abisOfBinary(cdb));
-        item.setCommand(cdb);
-        item.setEngineType(CdbEngineType);
-        item.setDisplayName(uniqueDisplayName(tr("Auto-detected CDB at %1").arg(cdb.toUserOutput())));
-        addDebugger(item);
-    }
-}
-
-void DebuggerItemManager::autoDetectGdbOrLldbDebuggers()
-{
-    QStringList filters;
-    filters.append(QLatin1String("gdb-i686-pc-mingw32"));
-    filters.append(QLatin1String("gdb"));
-    filters.append(QLatin1String("lldb"));
-    filters.append(QLatin1String("lldb-*"));
-
-//    DebuggerItem result;
-//    result.setAutoDetected(true);
-//    result.setDisplayName(tr("Auto-detected for Tool Chain %1").arg(tc->displayName()));
-    /*
-    // Check suggestions from the SDK.
-    Environment env = Environment::systemEnvironment();
-    if (tc) {
-        tc->addToEnvironment(env); // Find MinGW gdb in toolchain environment.
-        QString path = tc->suggestedDebugger().toString();
-        if (!path.isEmpty()) {
-            const QFileInfo fi(path);
-            if (!fi.isAbsolute())
-                path = env.searchInPath(path);
-            result.command = FileName::fromString(path);
-            result.engineType = engineTypeFromBinary(path);
-            return maybeAddDebugger(result, false);
-        }
-    }
-    */
-
-    QFileInfoList suspects;
-
-    QStringList path = Environment::systemEnvironment().path();
-    foreach (const QString &base, path) {
-        QDir dir(base);
-        dir.setNameFilters(filters);
-        suspects += dir.entryInfoList();
-    }
-
-    foreach (const QFileInfo &fi, suspects) {
-        if (fi.exists()) {
-            FileName command = FileName::fromString(fi.absoluteFilePath());
-            if (findByCommand(command))
-                continue;
-            DebuggerItem item;
-            item.setCommand(command);
-            item.reinitializeFromFile();
-            //: %1: Debugger engine type (GDB, LLDB, CDB...), %2: Path
-            item.setDisplayName(tr("System %1 at %2")
-                .arg(item.engineTypeName()).arg(QDir::toNativeSeparators(fi.absoluteFilePath())));
-            item.setAutoDetected(true);
-            addDebugger(item);
-        }
-    }
-}
-
-void DebuggerItemManager::readLegacyDebuggers()
-{
-    QFileInfo settingsLocation(Core::ICore::settings()->fileName());
-    FileName legacyKits = FileName::fromString(settingsLocation.absolutePath() + QLatin1String(DEBUGGER_LEGACY_FILENAME));
-
-    PersistentSettingsReader reader;
-    if (!reader.load(legacyKits))
-        return;
-
-    foreach (const QVariant &v, reader.restoreValues()) {
-        QVariantMap data1 = v.toMap();
-        QString kitName = data1.value(QLatin1String("PE.Profile.Name")).toString();
-        QVariantMap data2 = data1.value(QLatin1String("PE.Profile.Data")).toMap();
-        QVariant v3 = data2.value(DebuggerKitInformation::id().toString());
-        QString fn;
-        if (v3.type() == QVariant::String)
-            fn = v3.toString();
-        else
-            fn = v3.toMap().value(QLatin1String("Binary")).toString();
-        if (fn.isEmpty())
-            continue;
-        if (fn.startsWith(QLatin1Char('{')))
-            continue;
-        if (fn == QLatin1String("auto"))
-            continue;
-        FileName command = FileName::fromUserInput(fn);
-        if (findByCommand(command))
-            continue;
-        DebuggerItem item;
-        item.setCommand(command);
-        item.setAutoDetected(true);
-        item.reinitializeFromFile();
-        item.setDisplayName(tr("Extracted from Kit %1").arg(kitName));
-        addDebugger(item);
-    }
-}
-
-const DebuggerItem *DebuggerItemManager::findByCommand(const FileName &command)
-{
-    foreach (const DebuggerItem &item, m_debuggers)
-        if (item.command() == command)
-            return &item;
-
-    return 0;
-}
-
-const DebuggerItem *DebuggerItemManager::findById(const QVariant &id)
-{
-    foreach (const DebuggerItem &item, m_debuggers)
-        if (item.id() == id)
-            return &item;
-
-    return 0;
-}
-
-void DebuggerItemManager::restoreDebuggers()
-{
-    // Read debuggers from SDK
-    QFileInfo systemSettingsFile(Core::ICore::settings(QSettings::SystemScope)->fileName());
-    readDebuggers(FileName::fromString(systemSettingsFile.absolutePath() + QLatin1String(DEBUGGER_FILENAME)), true);
-
-    // Read all debuggers from user file.
-    readDebuggers(userSettingsFileName(), false);
-
-    // Auto detect current.
-    autoDetectCdbDebuggers();
-    autoDetectGdbOrLldbDebuggers();
-
-    // Add debuggers from pre-3.x profiles.xml
-    readLegacyDebuggers();
-}
-
-void DebuggerItemManager::saveDebuggers()
-{
-    QTC_ASSERT(m_writer, return);
-    QVariantMap data;
-    data.insert(QLatin1String(DEBUGGER_FILE_VERSION_KEY), 1);
-
-    int count = 0;
-    foreach (const DebuggerItem &item, m_debuggers) {
-        if (item.isValid()) {
-            QVariantMap tmp = item.toMap();
-            if (tmp.isEmpty())
-                continue;
-            data.insert(QString::fromLatin1(DEBUGGER_DATA_KEY) + QString::number(count), tmp);
-            ++count;
-        }
-    }
-    data.insert(QLatin1String(DEBUGGER_COUNT_KEY), count);
-    m_writer->save(data, Core::ICore::mainWindow());
-
-    // Do not save default debuggers as they are set by the SDK.
-}
-
-QVariant DebuggerItemManager::registerDebugger(const DebuggerItem &item)
-{
-    QTC_ASSERT(!item.command().isEmpty(), return QVariant());
-    QTC_ASSERT(!item.displayName().isEmpty(), return QVariant());
-    QTC_ASSERT(item.engineType() != NoEngineType, return QVariant());
-    if (findByCommand(item.command()))
-        return item.id();
-
-    return addDebugger(item);
-}
-
-void DebuggerItemManager::deregisterDebugger(const DebuggerItem &item)
-{
-    if (findByCommand(item.command()))
-        removeDebugger(item.id());
-}
-
-QVariant DebuggerItemManager::addDebugger(const DebuggerItem &item)
-{
-    QTC_ASSERT(item.id().isValid(), return QVariant());
-    m_debuggers.append(item);
-    m_model->addDebugger(item);
-    return item.id();
-}
-
-void DebuggerItemManager::removeDebugger(const QVariant &id)
-{
-    bool ok = false;
-    for (int i = 0, n = m_debuggers.size(); i != n; ++i) {
-        if (m_debuggers.at(i).id() == id) {
-            m_debuggers.removeAt(i);
-            ok = true;
-            break;
-        }
-    }
-
-    QTC_ASSERT(ok, return);
-    m_model->removeDebugger(id);
-}
-
-QString DebuggerItemManager::uniqueDisplayName(const QString &base)
-{
-    foreach (const DebuggerItem &item, m_debuggers)
-        if (item.displayName() == base)
-            return uniqueDisplayName(base + QLatin1String(" (1)"));
-
-    return base;
-}
-
-void DebuggerItemManager::setItemData(const QVariant &id, const QString &displayName, const FileName &fileName)
-{
-    for (int i = 0, n = m_debuggers.size(); i != n; ++i) {
-        DebuggerItem &item = m_debuggers[i];
-        if (item.id() == id) {
-            item.setDisplayName(displayName);
-            item.setCommand(fileName);
-            item.reinitializeFromFile();
-            emit m_model->updateDebugger(item.id());
-            break;
-        }
-    }
-}
-
 namespace Internal {
 
-static QList<QStandardItem *> describeItem(const DebuggerItem &item)
-{
-    QList<QStandardItem *> row;
-    row.append(new QStandardItem(item.displayName()));
-    row.append(new QStandardItem(item.command().toUserOutput()));
-    row.append(new QStandardItem(item.engineTypeName()));
-    row.at(0)->setData(item.id());
-    row.at(0)->setEditable(false);
-    row.at(1)->setEditable(false);
-    row.at(2)->setEditable(false);
-    row.at(0)->setSelectable(true);
-    row.at(1)->setSelectable(true);
-    row.at(2)->setSelectable(true);
-    return row;
-}
-
-static QList<QStandardItem *> createRow(const QString &display)
-{
-    QList<QStandardItem *> row;
-    row.append(new QStandardItem(display));
-    row.append(new QStandardItem());
-    row.append(new QStandardItem());
-    row.at(0)->setEditable(false);
-    row.at(1)->setEditable(false);
-    row.at(2)->setEditable(false);
-    row.at(0)->setSelectable(false);
-    row.at(1)->setSelectable(false);
-    row.at(2)->setSelectable(false);
-    return row;
-}
-
 class DebuggerItemConfigWidget;
 
-// --------------------------------------------------------------------------
-// DebuggerItemModel
-// --------------------------------------------------------------------------
-
-DebuggerItemModel::DebuggerItemModel(QObject *parent)
-    : QStandardItemModel(parent)
-{
-    setColumnCount(3);
-
-    QList<QStandardItem *> row = createRow(tr("Auto-detected"));
-    m_autoRoot = row.at(0);
-    appendRow(row);
-
-    row = createRow(tr("Manual"));
-    m_manualRoot = row.at(0);
-    appendRow(row);
-}
-
-QVariant DebuggerItemModel::headerData(int section, Qt::Orientation orientation, int role) const
-{
-    if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
-        switch (section) {
-        case 0:
-            return tr("Name");
-        case 1:
-            return tr("Path");
-        case 2:
-            return tr("Type");
-        }
-    }
-    return QVariant();
-}
-
-QStandardItem *DebuggerItemModel::currentStandardItem() const
-{
-    return findStandardItemById(m_currentDebugger);
-}
-
-QStandardItem *DebuggerItemModel::findStandardItemById(const QVariant &id) const
-{
-    for (int i = 0, n = m_autoRoot->rowCount(); i != n; ++i) {
-        QStandardItem *sitem = m_autoRoot->child(i);
-        if (sitem->data() == id)
-            return sitem;
-    }
-    for (int i = 0, n = m_manualRoot->rowCount(); i != n; ++i) {
-        QStandardItem *sitem = m_manualRoot->child(i);
-        if (sitem->data() == id)
-            return sitem;
-    }
-    return 0;
-}
-
-QModelIndex DebuggerItemModel::currentIndex() const
-{
-    QStandardItem *current = currentStandardItem();
-    return current ? current->index() : QModelIndex();
-}
-
-QModelIndex DebuggerItemModel::lastIndex() const
-{
-    int n = m_manualRoot->rowCount();
-    QStandardItem *current = m_manualRoot->child(n - 1);
-    return current ? current->index() : QModelIndex();
-}
-
-void DebuggerItemModel::markCurrentDirty()
-{
-    QStandardItem *sitem = currentStandardItem();
-    QTC_ASSERT(sitem, return);
-    QFont font = sitem->font();
-    font.setBold(true);
-    sitem->setFont(font);
-}
-
-void DebuggerItemModel::addDebugger(const DebuggerItem &item)
-{
-    QTC_ASSERT(item.id().isValid(), return);
-    QList<QStandardItem *> row = describeItem(item);
-    (item.isAutoDetected() ? m_autoRoot : m_manualRoot)->appendRow(row);
-    emit debuggerAdded(item.id(), item.displayName());
-}
-
-void DebuggerItemModel::removeDebugger(const QVariant &id)
-{
-    QStandardItem *sitem = findStandardItemById(id);
-    QTC_ASSERT(sitem, return);
-    QStandardItem *parent = sitem->parent();
-    QTC_ASSERT(parent, return);
-    // This will trigger a change of m_currentDebugger via changing the
-    // view selection.
-    parent->removeRow(sitem->row());
-    emit debuggerRemoved(id);
-}
-
-void DebuggerItemModel::updateDebugger(const QVariant &id)
-{
-    QList<DebuggerItem> debuggers = DebuggerItemManager::debuggers();
-    for (int i = 0, n = debuggers.size(); i != n; ++i) {
-        DebuggerItem &item = debuggers[i];
-        if (item.id() == id) {
-            QStandardItem *sitem = findStandardItemById(id);
-            QTC_ASSERT(sitem, return);
-            QStandardItem *parent = sitem->parent();
-            QTC_ASSERT(parent, return);
-            int row = sitem->row();
-            QFont font = sitem->font();
-            font.setBold(false);
-            parent->child(row, 0)->setData(item.displayName(), Qt::DisplayRole);
-            parent->child(row, 0)->setFont(font);
-            parent->child(row, 1)->setData(item.command().toUserOutput(), Qt::DisplayRole);
-            parent->child(row, 1)->setFont(font);
-            parent->child(row, 2)->setData(item.engineTypeName(), Qt::DisplayRole);
-            parent->child(row, 2)->setFont(font);
-            emit debuggerUpdated(id, item.displayName());
-            return;
-        }
-    }
-}
-
-void DebuggerItemModel::setCurrentIndex(const QModelIndex &index)
-{
-    QStandardItem *sit = itemFromIndex(index);
-    m_currentDebugger = sit ? sit->data() : QVariant();
-}
-
 // -----------------------------------------------------------------------
 // DebuggerKitConfigWidget
 // -----------------------------------------------------------------------
@@ -1002,296 +204,5 @@ void DebuggerKitConfigWidget::updateComboBox(const QVariant &id)
     m_comboBox->setCurrentIndex(0);
 }
 
-// -----------------------------------------------------------------------
-// DebuggerItemConfigWidget
-// -----------------------------------------------------------------------
-
-class DebuggerItemConfigWidget : public QWidget
-{
-    Q_DECLARE_TR_FUNCTIONS(Debugger::Internal::DebuggerItemConfigWidget)
-public:
-    explicit DebuggerItemConfigWidget();
-    void loadItem();
-    void saveItem();
-    void connectDirty();
-    void disconnectDirty();
-
-private:
-    QLineEdit *m_displayNameLineEdit;
-    QLabel *m_cdbLabel;
-    PathChooser *m_binaryChooser;
-    QLineEdit *m_abis;
-};
-
-DebuggerItemConfigWidget::DebuggerItemConfigWidget()
-{
-    m_displayNameLineEdit = new QLineEdit(this);
-
-    m_binaryChooser = new PathChooser(this);
-    m_binaryChooser->setExpectedKind(PathChooser::ExistingCommand);
-    m_binaryChooser->setMinimumWidth(400);
-
-    m_cdbLabel = new QLabel(this);
-    m_cdbLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
-    m_cdbLabel->setOpenExternalLinks(true);
-
-    m_abis = new QLineEdit(this);
-    m_abis->setEnabled(false);
-
-    QFormLayout *formLayout = new QFormLayout(this);
-    formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
-    formLayout->addRow(new QLabel(tr("Name:")), m_displayNameLineEdit);
-//    formLayout->addRow(new QLabel(tr("Type:")), m_engineTypeComboBox);
-    formLayout->addRow(m_cdbLabel);
-    formLayout->addRow(new QLabel(tr("Path:")), m_binaryChooser);
-    formLayout->addRow(new QLabel(tr("ABIs:")), m_abis);
-
-    connectDirty();
-}
-
-void DebuggerItemConfigWidget::connectDirty()
-{
-    DebuggerItemModel *model = DebuggerItemManager::model();
-    connect(m_displayNameLineEdit, SIGNAL(textChanged(QString)),
-            model, SLOT(markCurrentDirty()));
-    connect(m_binaryChooser, SIGNAL(changed(QString)),
-            model, SLOT(markCurrentDirty()));
-}
-
-void DebuggerItemConfigWidget::disconnectDirty()
-{
-    DebuggerItemModel *model = DebuggerItemManager::model();
-    disconnect(m_displayNameLineEdit, SIGNAL(textChanged(QString)),
-            model, SLOT(markCurrentDirty()));
-    disconnect(m_binaryChooser, SIGNAL(changed(QString)),
-            model, SLOT(markCurrentDirty()));
-}
-
-void DebuggerItemConfigWidget::loadItem()
-{
-    DebuggerItemModel *model = DebuggerItemManager::model();
-    const DebuggerItem *item = DebuggerItemManager::findById(model->m_currentDebugger);
-    if (!item)
-        return;
-
-    disconnectDirty();
-    m_displayNameLineEdit->setEnabled(!item->isAutoDetected());
-    m_displayNameLineEdit->setText(item->displayName());
-
-    m_binaryChooser->setEnabled(!item->isAutoDetected());
-    m_binaryChooser->setFileName(item->command());
-    connectDirty();
-
-    QString text;
-    QString versionCommand;
-    if (item->engineType() == CdbEngineType) {
-#ifdef Q_OS_WIN
-        const bool is64bit = winIs64BitSystem();
-#else
-        const bool is64bit = false;
-#endif
-        const QString versionString = is64bit ? tr("64-bit version") : tr("32-bit version");
-        //: Label text for path configuration. %2 is "x-bit version".
-        text = tr("<html><body><p>Specify the path to the "
-                  "<a href=\"%1\">Windows Console Debugger executable</a>"
-                  " (%2) here.</p>""</body></html>").
-                arg(QLatin1String(debuggingToolsWikiLinkC), versionString);
-        versionCommand = QLatin1String("-version");
-    } else {
-        versionCommand = QLatin1String("--version");
-    }
-
-    m_cdbLabel->setText(text);
-    m_cdbLabel->setVisible(!text.isEmpty());
-    m_binaryChooser->setCommandVersionArguments(QStringList(versionCommand));
-
-    m_abis->setText(item->abiNames().join(QLatin1String(", ")));
-}
-
-void DebuggerItemConfigWidget::saveItem()
-{
-    DebuggerItemModel *model = DebuggerItemManager::model();
-    const DebuggerItem *item = DebuggerItemManager::findById(model->m_currentDebugger);
-    QTC_ASSERT(item, return);
-    DebuggerItemManager::setItemData(item->id(), m_displayNameLineEdit->text(),
-                                                             m_binaryChooser->fileName());
-}
-
-// --------------------------------------------------------------------------
-// DebuggerOptionsPage
-// --------------------------------------------------------------------------
-
-DebuggerOptionsPage::DebuggerOptionsPage()
-{
-    m_model = 0;
-    m_debuggerView = 0;
-    m_container = 0;
-    m_addButton = 0;
-    m_cloneButton = 0;
-    m_delButton = 0;
-
-    setId(ProjectExplorer::Constants::DEBUGGER_SETTINGS_PAGE_ID);
-    setDisplayName(tr("Debuggers"));
-    setCategory(ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_CATEGORY);
-    setDisplayCategory(QCoreApplication::translate("ProjectExplorer",
-        ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_TR_CATEGORY));
-    setCategoryIcon(QLatin1String(ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_CATEGORY_ICON));
-}
-
-QWidget *DebuggerOptionsPage::createPage(QWidget *parent)
-{
-    m_configWidget = new QWidget(parent);
-
-    m_addButton = new QPushButton(tr("Add"), m_configWidget);
-    m_cloneButton = new QPushButton(tr("Clone"), m_configWidget);
-    m_delButton = new QPushButton(tr("Remove"), m_configWidget);
-
-    m_container = new DetailsWidget(m_configWidget);
-    m_container->setState(DetailsWidget::NoSummary);
-    m_container->setVisible(false);
-
-    m_model = DebuggerItemManager::model();
-
-    m_debuggerView = new QTreeView(m_configWidget);
-    m_debuggerView->setModel(m_model);
-    m_debuggerView->setUniformRowHeights(true);
-    m_debuggerView->setSelectionMode(QAbstractItemView::SingleSelection);
-    m_debuggerView->setSelectionBehavior(QAbstractItemView::SelectRows);
-    m_debuggerView->expandAll();
-
-    QHeaderView *header = m_debuggerView->header();
-    header->setStretchLastSection(false);
-    header->setResizeMode(0, QHeaderView::ResizeToContents);
-    header->setResizeMode(1, QHeaderView::ResizeToContents);
-    header->setResizeMode(2, QHeaderView::Stretch);
-
-    QVBoxLayout *buttonLayout = new QVBoxLayout();
-    buttonLayout->setSpacing(6);
-    buttonLayout->setContentsMargins(0, 0, 0, 0);
-    buttonLayout->addWidget(m_addButton);
-    buttonLayout->addWidget(m_cloneButton);
-    buttonLayout->addWidget(m_delButton);
-    buttonLayout->addItem(new QSpacerItem(10, 40, QSizePolicy::Minimum, QSizePolicy::Expanding));
-
-    QVBoxLayout *verticalLayout = new QVBoxLayout();
-    verticalLayout->addWidget(m_debuggerView);
-    verticalLayout->addWidget(m_container);
-
-    QHBoxLayout *horizontalLayout = new QHBoxLayout(m_configWidget);
-    horizontalLayout->addLayout(verticalLayout);
-    horizontalLayout->addLayout(buttonLayout);
-
-    connect(m_debuggerView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
-            this, SLOT(debuggerSelectionChanged()));
-
-    connect(m_addButton, SIGNAL(clicked()), this, SLOT(addDebugger()), Qt::QueuedConnection);
-    connect(m_cloneButton, SIGNAL(clicked()), this, SLOT(cloneDebugger()), Qt::QueuedConnection);
-    connect(m_delButton, SIGNAL(clicked()), this, SLOT(removeDebugger()), Qt::QueuedConnection);
-
-    m_searchKeywords = tr("Debuggers");
-
-    m_itemConfigWidget = new DebuggerItemConfigWidget;
-    m_container->setWidget(m_itemConfigWidget);
-
-    updateState();
-
-    return m_configWidget;
-}
-
-void DebuggerOptionsPage::apply()
-{
-    m_itemConfigWidget->saveItem();
-    debuggerModelChanged();
-}
-
-void DebuggerOptionsPage::cloneDebugger()
-{
-    const DebuggerItem *item = DebuggerItemManager::findById(m_model->currentDebugger());
-    QTC_ASSERT(item, return);
-    DebuggerItem newItem;
-    newItem.setCommand(item->command());
-    newItem.setEngineType(item->engineType());
-    newItem.setAbis(item->abis());
-    newItem.setDisplayName(DebuggerItemManager::uniqueDisplayName(tr("Clone of %1").arg(item->displayName())));
-    newItem.setAutoDetected(false);
-    DebuggerItemManager::addDebugger(newItem);
-    m_debuggerView->setCurrentIndex(m_model->lastIndex());
-}
-
-void DebuggerOptionsPage::addDebugger()
-{
-    DebuggerItem item;
-    item.setEngineType(NoEngineType);
-    item.setDisplayName(DebuggerItemManager::uniqueDisplayName(tr("New Debugger")));
-    item.setAutoDetected(false);
-    DebuggerItemManager::addDebugger(item);
-    m_debuggerView->setCurrentIndex(m_model->lastIndex());
-}
-
-void DebuggerOptionsPage::removeDebugger()
-{
-    QVariant id = m_model->currentDebugger();
-    DebuggerItemManager::removeDebugger(id);
-    m_debuggerView->setCurrentIndex(m_model->lastIndex());
-}
-
-void DebuggerOptionsPage::finish()
-{
-    // Deleted by settingsdialog.
-    m_configWidget = 0;
-
-    // Children of m_configWidget.
-    m_container = 0;
-    m_debuggerView = 0;
-    m_addButton = 0;
-    m_cloneButton = 0;
-    m_delButton = 0;
-}
-
-bool DebuggerOptionsPage::matches(const QString &s) const
-{
-    return m_searchKeywords.contains(s, Qt::CaseInsensitive);
-}
-
-void DebuggerOptionsPage::debuggerSelectionChanged()
-{
-    QTC_ASSERT(m_container, return);
-
-    QModelIndex mi = m_debuggerView->currentIndex();
-    mi = mi.sibling(mi.row(), 0);
-    m_model->setCurrentIndex(mi);
-
-    m_itemConfigWidget->loadItem();
-    m_container->setVisible(m_model->m_currentDebugger.isValid());
-    updateState();
-}
-
-void DebuggerOptionsPage::debuggerModelChanged()
-{
-    QTC_ASSERT(m_container, return);
-
-    m_itemConfigWidget->loadItem();
-    m_container->setVisible(m_model->m_currentDebugger.isValid());
-    m_debuggerView->setCurrentIndex(m_model->currentIndex());
-    updateState();
-}
-
-void DebuggerOptionsPage::updateState()
-{
-    if (!m_cloneButton)
-        return;
-
-    bool canCopy = false;
-    bool canDelete = false;
-
-    if (const DebuggerItem *item = DebuggerItemManager::findById(m_model->m_currentDebugger)) {
-        canCopy = item->isValid() && item->canClone();
-        canDelete = !item->isAutoDetected();
-        canDelete = true; // Do we want to remove auto-detected items?
-    }
-    m_cloneButton->setEnabled(canCopy);
-    m_delButton->setEnabled(canDelete);
-}
-
 } // namespace Internal
 } // namespace Debugger
diff --git a/src/plugins/debugger/debuggerkitconfigwidget.h b/src/plugins/debugger/debuggerkitconfigwidget.h
index f2ab06695f5eab8d7940f745bdec3bc103c1e585..c6a543321806820875dfeb9ba8c3f0eaa601ae93 100644
--- a/src/plugins/debugger/debuggerkitconfigwidget.h
+++ b/src/plugins/debugger/debuggerkitconfigwidget.h
@@ -52,52 +52,6 @@ QT_END_NAMESPACE
 namespace Debugger {
 namespace Internal {
 
-class DebuggerItemConfigWidget;
-class DebuggerKitConfigWidget;
-
-// -----------------------------------------------------------------------
-// DebuggerItemModel
-//------------------------------------------------------------------------
-class DebuggerItemModel : public QStandardItemModel
-{
-    Q_OBJECT
-
-public:
-    DebuggerItemModel(QObject *parent);
-
-    QModelIndex currentIndex() const;
-    QModelIndex lastIndex() const;
-    void setCurrentIndex(const QModelIndex &index);
-    QVariant currentDebugger() const { return m_currentDebugger; }
-    void addDebugger(const DebuggerItem &item);
-    void removeDebugger(const QVariant &id);
-    void updateDebugger(const QVariant &id);
-
-public slots:
-    void markCurrentDirty();
-
-signals:
-    void debuggerAdded(const QVariant &id, const QString &display);
-    void debuggerUpdated(const QVariant &id, const QString &display);
-    void debuggerRemoved(const QVariant &id);
-
-private:
-    friend class Debugger::DebuggerKitInformation;
-    friend class DebuggerKitConfigWidget;
-    friend class DebuggerItemConfigWidget;
-    friend class DebuggerOptionsPage;
-
-    QStandardItem *currentStandardItem() const;
-    QStandardItem *findStandardItemById(const QVariant &id) const;
-    QVariant headerData(int section, Qt::Orientation orientation, int role) const;
-
-    QVariant m_currentDebugger;
-
-    QStandardItem *m_autoRoot;
-    QStandardItem *m_manualRoot;
-    QStringList removed;
-};
-
 // -----------------------------------------------------------------------
 // DebuggerKitConfigWidget
 // -----------------------------------------------------------------------
@@ -135,44 +89,7 @@ private:
     QPushButton *m_manageButton;
 };
 
-// --------------------------------------------------------------------------
-// DebuggerOptionsPage
-// --------------------------------------------------------------------------
-
-class DebuggerOptionsPage : public Core::IOptionsPage
-{
-    Q_OBJECT
-
-public:
-    DebuggerOptionsPage();
-
-    QWidget *createPage(QWidget *parent);
-    void apply();
-    void finish();
-    bool matches(const QString &) const;
-
-private slots:
-    void debuggerSelectionChanged();
-    void debuggerModelChanged();
-    void updateState();
-    void cloneDebugger();
-    void addDebugger();
-    void removeDebugger();
-
-private:
-    QWidget *m_configWidget;
-    QString m_searchKeywords;
-
-    DebuggerItemModel *m_model;
-    DebuggerItemConfigWidget *m_itemConfigWidget;
-    QTreeView *m_debuggerView;
-    Utils::DetailsWidget *m_container;
-    QPushButton *m_addButton;
-    QPushButton *m_cloneButton;
-    QPushButton *m_delButton;
-};
-
 } // namespace Internal
 } // namespace Debugger
 
-#endif // DEBUGGER_DEBUGGERKITINFORMATION_H
+#endif // DEBUGGER_DEBUGGERKITCONFIGWIDGET_H
diff --git a/src/plugins/debugger/debuggerkitinformation.cpp b/src/plugins/debugger/debuggerkitinformation.cpp
index 5436206bcba08c7633262d5e6fa516750ac40555..7ee98c619db1376f2fcda0676dfeea87857465d4 100644
--- a/src/plugins/debugger/debuggerkitinformation.cpp
+++ b/src/plugins/debugger/debuggerkitinformation.cpp
@@ -28,309 +28,305 @@
 ****************************************************************************/
 
 #include "debuggerkitinformation.h"
+
+#include "debuggeritemmanager.h"
 #include "debuggerkitconfigwidget.h"
 
-#include <projectexplorer/abi.h>
+#include "projectexplorer/toolchain.h"
+#include "projectexplorer/projectexplorerconstants.h"
+
 #include <utils/fileutils.h>
+#include <utils/qtcassert.h>
 
-#include <QProcess>
-#include <QUuid>
+#include <QFileInfo>
 
-using namespace Debugger::Internal;
 using namespace ProjectExplorer;
 using namespace Utils;
 
-static const char DEBUGGER_INFORMATION_COMMAND[] = "Binary";
-static const char DEBUGGER_INFORMATION_DISPLAYNAME[] = "DisplayName";
-static const char DEBUGGER_INFORMATION_ID[] = "Id";
-static const char DEBUGGER_INFORMATION_ENGINETYPE[] = "EngineType";
-static const char DEBUGGER_INFORMATION_AUTODETECTED[] = "AutoDetected";
-static const char DEBUGGER_INFORMATION_ABIS[] = "Abis";
-
 namespace Debugger {
 
 // --------------------------------------------------------------------------
-// DebuggerItem
+// DebuggerKitInformation
 // --------------------------------------------------------------------------
 
-DebuggerItem::DebuggerItem()
+DebuggerKitInformation::DebuggerKitInformation()
 {
-    m_id = QUuid::createUuid().toString();
-    m_engineType = NoEngineType;
-    m_isAutoDetected = false;
+    setObjectName(QLatin1String("DebuggerKitInformation"));
+    setId(DebuggerKitInformation::id());
+    setPriority(28000);
 }
 
-DebuggerItem::DebuggerItem(const QVariantMap &data)
+QVariant DebuggerKitInformation::defaultValue(Kit *k) const
 {
-    m_command = FileName::fromUserInput(data.value(QLatin1String(DEBUGGER_INFORMATION_COMMAND)).toString());
-    m_id = data.value(QLatin1String(DEBUGGER_INFORMATION_ID)).toString();
-    m_displayName = data.value(QLatin1String(DEBUGGER_INFORMATION_DISPLAYNAME)).toString();
-    m_isAutoDetected = data.value(QLatin1String(DEBUGGER_INFORMATION_AUTODETECTED), false).toBool();
-    m_engineType = DebuggerEngineType(data.value(QLatin1String(DEBUGGER_INFORMATION_ENGINETYPE),
-                                                 static_cast<int>(NoEngineType)).toInt());
-
-    foreach (const QString &a, data.value(QLatin1String(DEBUGGER_INFORMATION_ABIS)).toStringList()) {
-        Abi abi(a);
-        if (abi.isValid())
-            m_abis.append(abi);
-    }
+    ToolChain *tc = ToolChainKitInformation::toolChain(k);
+    QTC_ASSERT(tc, return QVariant());
+
+    const Abi toolChainAbi = tc->targetAbi();
+    foreach (const DebuggerItem &item, DebuggerItemManager::debuggers())
+        foreach (const Abi targetAbi, item.abis())
+            if (targetAbi.isCompatibleWith(toolChainAbi))
+                return item.id();
+
+    return QVariant();
 }
 
-void DebuggerItem::reinitializeFromFile()
+void DebuggerKitInformation::setup(Kit *k)
 {
-    QProcess proc;
-    proc.start(m_command.toString(), QStringList() << QLatin1String("--version"));
-    proc.waitForStarted();
-    proc.waitForFinished();
-    QByteArray ba = proc.readAll();
-    if (ba.contains("gdb")) {
-        m_engineType = GdbEngineType;
-        const char needle[] = "This GDB was configured as \"";
-        // E.g.  "--host=i686-pc-linux-gnu --target=arm-unknown-nto-qnx6.5.0".
-        // or "i686-linux-gnu"
-        int pos1 = ba.indexOf(needle);
-        if (pos1 != -1) {
-            pos1 += int(sizeof(needle));
-            int pos2 = ba.indexOf('"', pos1 + 1);
-            QByteArray target = ba.mid(pos1, pos2 - pos1);
-            int pos3 = target.indexOf("--target=");
-            if (pos3 >= 0)
-                target = target.mid(pos3 + 9);
-            m_abis.append(Abi::abiFromTargetTriplet(QString::fromLatin1(target)));
+    // Get one of the available debugger matching the kit's toolchain.
+    const ToolChain *tc = ToolChainKitInformation::toolChain(k);
+    const Abi toolChainAbi = tc ? tc->targetAbi() : Abi::hostAbi();
+
+    // This can be anything (Id, binary path, "auto")
+    const QVariant rawId = k->value(DebuggerKitInformation::id());
+
+    enum {
+        NotDetected, DetectedAutomatically, DetectedByFile, DetectedById
+    } detection = NotDetected;
+    DebuggerEngineType autoEngine = NoEngineType;
+    FileName fileName;
+
+    // With 3.0 we have:
+    // <value type="QString" key="Debugger.Information">{75ecf347-f221-44c3-b613-ea1d29929cd4}</value>
+    // Before we had:
+    // <valuemap type="QVariantMap" key="Debugger.Information">
+    //    <value type="QString" key="Binary">/data/dev/debugger/gdb-git/gdb/gdb</value>
+    //    <value type="int" key="EngineType">1</value>
+    //  </valuemap>
+    // Or for force auto-detected CDB
+    // <valuemap type="QVariantMap" key="Debugger.Information">
+    //    <value type="QString" key="Binary">auto</value>
+    //    <value type="int" key="EngineType">4</value>
+    //  </valuemap>
+
+    if (rawId.isNull()) {
+        // Initial setup of a kit
+        detection = NotDetected;
+    } else if (rawId.type() == QVariant::String) {
+        detection = DetectedById;
+    } else {
+        QMap<QString, QVariant> map = rawId.toMap();
+        QString binary = map.value(QLatin1String("Binary")).toString();
+        if (binary == QLatin1String("auto")) {
+            detection = DetectedAutomatically;
+            autoEngine = DebuggerEngineType(map.value(QLatin1String("EngineType")).toInt());
         } else {
-            // Fallback.
-            m_abis = Abi::abisOfBinary(m_command); // FIXME: Wrong.
+            detection  = DetectedByFile;
+            fileName = FileName::fromUserInput(binary);
         }
-        return;
     }
-    if (ba.contains("lldb") || ba.startsWith("LLDB")) {
-        m_engineType = LldbEngineType;
-        m_abis = Abi::abisOfBinary(m_command);
-        return;
+
+    const DebuggerItem *bestItem = 0;
+    DebuggerItem::MatchLevel bestLevel = DebuggerItem::DoesNotMatch;
+    foreach (const DebuggerItem &item, DebuggerItemManager::debuggers()) {
+        const DebuggerItem *goodItem = 0;
+        if (detection == DetectedById && item.id() == rawId)
+            goodItem = &item;
+        if (detection == DetectedByFile && item.command() == fileName)
+            goodItem = &item;
+        if (detection == DetectedAutomatically && item.engineType() == autoEngine)
+            goodItem = &item;
+
+        if (goodItem) {
+            DebuggerItem::MatchLevel level = goodItem->matchTarget(toolChainAbi);
+            if (level > bestLevel) {
+                bestLevel = level;
+                bestItem = goodItem;
+            }
+        }
     }
-    if (ba.startsWith("Python")) {
-        m_engineType = PdbEngineType;
+
+    // If we have an existing debugger with matching id _and_
+    // matching target ABI we are fine.
+    if (bestItem) {
+        k->setValue(DebuggerKitInformation::id(), bestItem->id());
         return;
     }
-    m_engineType = NoEngineType;
-}
 
-QString DebuggerItem::engineTypeName() const
-{
-    switch (m_engineType) {
-    case Debugger::NoEngineType:
-        return DebuggerOptionsPage::tr("Not recognized");
-    case Debugger::GdbEngineType:
-        return QLatin1String("GDB");
-    case Debugger::CdbEngineType:
-        return QLatin1String("CDB");
-    case Debugger::LldbEngineType:
-        return QLatin1String("LLDB");
-    default:
-        return QString();
+    // We didn't find an existing debugger that matched by whatever
+    // data we found in the kit (i.e. no id, filename, "auto")
+    // (or what we found did not match ABI-wise)
+    // Let's try to pick one with matching ABI.
+    QVariant bestId;
+    bestLevel = DebuggerItem::DoesNotMatch;
+    foreach (const DebuggerItem &item, DebuggerItemManager::debuggers()) {
+        DebuggerItem::MatchLevel level = item.matchTarget(toolChainAbi);
+        if (level > bestLevel) {
+            bestLevel = level;
+            bestId = item.id();
+        }
     }
-}
 
-QStringList DebuggerItem::abiNames() const
-{
-    QStringList list;
-    foreach (const Abi &abi, m_abis)
-        list.append(abi.toString());
-    return list;
+    k->setValue(DebuggerKitInformation::id(), bestId);
 }
 
-QVariantMap DebuggerItem::toMap() const
+
+// This handles the upgrade path from 2.8 to 3.0
+void DebuggerKitInformation::fix(Kit *k)
 {
-    QVariantMap data;
-    data.insert(QLatin1String(DEBUGGER_INFORMATION_DISPLAYNAME), m_displayName);
-    data.insert(QLatin1String(DEBUGGER_INFORMATION_ID), m_id);
-    data.insert(QLatin1String(DEBUGGER_INFORMATION_COMMAND), m_command.toUserOutput());
-    data.insert(QLatin1String(DEBUGGER_INFORMATION_ENGINETYPE), int(m_engineType));
-    data.insert(QLatin1String(DEBUGGER_INFORMATION_AUTODETECTED), m_isAutoDetected);
-    data.insert(QLatin1String(DEBUGGER_INFORMATION_ABIS), abiNames());
-    return data;
+    // This can be Id, binary path, but not "auto" anymore.
+    const QVariant rawId = k->value(DebuggerKitInformation::id());
+
+    if (rawId.isNull()) // No debugger set, that is fine.
+        return;
+
+    if (rawId.type() == QVariant::String) {
+        if (!DebuggerItemManager::findById(rawId)) {
+            qWarning("Unknown debugger id %s in kit %s",
+                     qPrintable(rawId.toString()), qPrintable(k->displayName()));
+            k->setValue(DebuggerKitInformation::id(), QVariant());
+        }
+        return; // All fine (now).
+    }
+
+    QMap<QString, QVariant> map = rawId.toMap();
+    QString binary = map.value(QLatin1String("Binary")).toString();
+    if (binary == QLatin1String("auto")) {
+        // This should not happen as "auto" is handled by setup() already.
+        QTC_CHECK(false);
+        k->setValue(DebuggerKitInformation::id(), QVariant());
+        return;
+    }
+
+    FileName fileName = FileName::fromUserInput(binary);
+    const DebuggerItem *item = DebuggerItemManager::findByCommand(fileName);
+    if (!item) {
+        qWarning("Debugger command %s invalid in kit %s",
+                 qPrintable(binary), qPrintable(k->displayName()));
+        k->setValue(DebuggerKitInformation::id(), QVariant());
+        return;
+    }
+
+    k->setValue(DebuggerKitInformation::id(), item->id());
 }
 
-void DebuggerItem::setDisplayName(const QString &displayName)
+// Check the configuration errors and return a flag mask. Provide a quick check and
+// a verbose one with a list of errors.
+
+enum DebuggerConfigurationErrors {
+    NoDebugger = 0x1,
+    DebuggerNotFound = 0x2,
+    DebuggerNotExecutable = 0x4,
+    DebuggerNeedsAbsolutePath = 0x8
+};
+
+static unsigned debuggerConfigurationErrors(const Kit *k)
 {
-    m_displayName = displayName;
+    QTC_ASSERT(k, return NoDebugger);
+
+    const DebuggerItem *item = DebuggerKitInformation::debugger(k);
+    if (!item)
+        return NoDebugger;
+
+    if (item->command().isEmpty())
+        return NoDebugger;
+
+    unsigned result = 0;
+    const QFileInfo fi = item->command().toFileInfo();
+    if (!fi.exists() || fi.isDir())
+        result |= DebuggerNotFound;
+    else if (!fi.isExecutable())
+        result |= DebuggerNotExecutable;
+
+    if (!fi.exists() || fi.isDir()) {
+        if (item->engineType() == NoEngineType)
+            return NoDebugger;
+
+        // We need an absolute path to be able to locate Python on Windows.
+        if (item->engineType() == GdbEngineType)
+            if (const ToolChain *tc = ToolChainKitInformation::toolChain(k))
+                if (tc->targetAbi().os() == Abi::WindowsOS && !fi.isAbsolute())
+                    result |= DebuggerNeedsAbsolutePath;
+    }
+    return result;
 }
 
-void DebuggerItem::setEngineType(const DebuggerEngineType &engineType)
+const DebuggerItem *DebuggerKitInformation::debugger(const Kit *kit)
 {
-    m_engineType = engineType;
+    QTC_ASSERT(kit, return 0);
+    const QVariant id = kit->value(DebuggerKitInformation::id());
+    return DebuggerItemManager::findById(id);
 }
 
-void DebuggerItem::setCommand(const Utils::FileName &command)
+bool DebuggerKitInformation::isValidDebugger(const Kit *k)
 {
-    m_command = command;
+    return debuggerConfigurationErrors(k) == 0;
 }
 
-void DebuggerItem::setAutoDetected(bool isAutoDetected)
+QList<Task> DebuggerKitInformation::validateDebugger(const Kit *k)
 {
-    m_isAutoDetected = isAutoDetected;
+    QList<Task> result;
+
+    const unsigned errors = debuggerConfigurationErrors(k);
+    if (!errors)
+        return result;
+
+    QString path;
+    if (const DebuggerItem *item = debugger(k))
+        path = item->command().toUserOutput();
+
+    const Core::Id id = ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM;
+    if (errors & NoDebugger)
+        result << Task(Task::Warning, tr("No debugger set up."), FileName(), -1, id);
+
+    if (errors & DebuggerNotFound)
+        result << Task(Task::Error, tr("Debugger '%1' not found.").arg(path),
+                       FileName(), -1, id);
+    if (errors & DebuggerNotExecutable)
+        result << Task(Task::Error, tr("Debugger '%1' not executable.").arg(path), FileName(), -1, id);
+
+    if (errors & DebuggerNeedsAbsolutePath) {
+        const QString message =
+                tr("The debugger location must be given as an "
+                   "absolute path (%1).").arg(path);
+        result << Task(Task::Error, message, FileName(), -1, id);
+    }
+    return result;
 }
 
-void DebuggerItem::setAbis(const QList<ProjectExplorer::Abi> &abis)
+KitConfigWidget *DebuggerKitInformation::createConfigWidget(Kit *k) const
 {
-    m_abis = abis;
+    return new Internal::DebuggerKitConfigWidget(k, this);
 }
 
-void DebuggerItem::setAbi(const Abi &abi)
+KitInformation::ItemList DebuggerKitInformation::toUserOutput(const Kit *k) const
 {
-    m_abis.clear();
-    m_abis.append(abi);
+    return ItemList() << qMakePair(tr("Debugger"), displayString(k));
 }
 
-static DebuggerItem::MatchLevel matchSingle(const Abi &debuggerAbi, const Abi &targetAbi)
+FileName DebuggerKitInformation::debuggerCommand(const ProjectExplorer::Kit *k)
 {
-    if (debuggerAbi.architecture() != Abi::UnknownArchitecture
-            && debuggerAbi.architecture() != targetAbi.architecture())
-        return DebuggerItem::DoesNotMatch;
-
-    if (debuggerAbi.os() != Abi::UnknownOS
-            && debuggerAbi.os() != targetAbi.os())
-        return DebuggerItem::DoesNotMatch;
-
-    if (debuggerAbi.binaryFormat() != Abi::UnknownFormat
-            && debuggerAbi.binaryFormat() != targetAbi.binaryFormat())
-        return DebuggerItem::DoesNotMatch;
-
-    if (debuggerAbi.os() == Abi::WindowsOS) {
-        if (debuggerAbi.osFlavor() == Abi::WindowsMSysFlavor && targetAbi.osFlavor() != Abi::WindowsMSysFlavor)
-            return DebuggerItem::DoesNotMatch;
-        if (debuggerAbi.osFlavor() != Abi::WindowsMSysFlavor && targetAbi.osFlavor() == Abi::WindowsMSysFlavor)
-            return DebuggerItem::DoesNotMatch;
-    }
-
-    if (debuggerAbi.wordWidth() == 64 && targetAbi.wordWidth() == 32)
-        return DebuggerItem::MatchesSomewhat;
-    if (debuggerAbi.wordWidth() != 0 && debuggerAbi.wordWidth() != targetAbi.wordWidth())
-        return DebuggerItem::DoesNotMatch;
-
-    return DebuggerItem::MatchesPerfectly;
+    const DebuggerItem *item = debugger(k);
+    QTC_ASSERT(item, return FileName());
+    return item->command();
 }
 
-DebuggerItem::MatchLevel DebuggerItem::matchTarget(const Abi &targetAbi) const
+DebuggerEngineType DebuggerKitInformation::engineType(const ProjectExplorer::Kit *k)
 {
-    MatchLevel bestMatch = DoesNotMatch;
-    foreach (const Abi &debuggerAbi, m_abis) {
-        MatchLevel currentMatch = matchSingle(debuggerAbi, targetAbi);
-        if (currentMatch > bestMatch)
-            bestMatch = currentMatch;
-    }
-    return bestMatch;
+    const DebuggerItem *item = debugger(k);
+    QTC_ASSERT(item, return NoEngineType);
+    return item->engineType();
 }
 
-bool Debugger::DebuggerItem::isValid() const
+QString DebuggerKitInformation::displayString(const Kit *k)
 {
-    return m_engineType != NoEngineType;
+    const DebuggerItem *item = debugger(k);
+    if (!item)
+        return tr("No Debugger");
+    QString binary = item->command().toUserOutput();
+    QString name = tr("%1 Engine").arg(item->engineTypeName());
+    return binary.isEmpty() ? tr("%1 <None>").arg(name) : tr("%1 using \"%2\"").arg(name, binary);
 }
 
-} // namespace Debugger;
-
-#ifdef WITH_TESTS
-
-#    include <QTest>
-#    include "debuggerplugin.h"
-
-void Debugger::DebuggerPlugin::testDebuggerMatching_data()
+void DebuggerKitInformation::setDebugger(Kit *k, const QVariant &id)
 {
-    QTest::addColumn<QStringList>("debugger");
-    QTest::addColumn<QString>("target");
-    QTest::addColumn<int>("result");
-
-    QTest::newRow("Invalid data")
-            << QStringList()
-            << QString()
-            << int(DebuggerItem::DoesNotMatch);
-    QTest::newRow("Invalid debugger")
-            << QStringList()
-            << QString::fromLatin1("x86-linux-generic-elf-32bit")
-            << int(DebuggerItem::DoesNotMatch);
-    QTest::newRow("Invalid target")
-            << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
-            << QString()
-            << int(DebuggerItem::DoesNotMatch);
-
-    QTest::newRow("Fuzzy match 1")
-            << (QStringList() << QLatin1String("unknown-unknown-unknown-unknown-0bit"))
-            << QString::fromLatin1("x86-linux-generic-elf-32bit")
-            << int(DebuggerItem::MatchesPerfectly); // Is this the expected behavior?
-    QTest::newRow("Fuzzy match 2")
-            << (QStringList() << QLatin1String("unknown-unknown-unknown-unknown-0bit"))
-            << QString::fromLatin1("arm-windows-msys-pe-64bit")
-            << int(DebuggerItem::MatchesPerfectly); // Is this the expected behavior?
-
-    QTest::newRow("Architecture mismatch")
-            << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
-            << QString::fromLatin1("arm-linux-generic-elf-32bit")
-            << int(DebuggerItem::DoesNotMatch);
-    QTest::newRow("OS mismatch")
-            << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
-            << QString::fromLatin1("x86-macosx-generic-elf-32bit")
-            << int(DebuggerItem::DoesNotMatch);
-    QTest::newRow("Format mismatch")
-            << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
-            << QString::fromLatin1("x86-linux-generic-pe-32bit")
-            << int(DebuggerItem::DoesNotMatch);
-
-    QTest::newRow("Linux perfect match")
-            << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
-            << QString::fromLatin1("x86-linux-generic-elf-32bit")
-            << int(DebuggerItem::MatchesPerfectly);
-    QTest::newRow("Linux match")
-            << (QStringList() << QLatin1String("x86-linux-generic-elf-64bit"))
-            << QString::fromLatin1("x86-linux-generic-elf-32bit")
-            << int(DebuggerItem::MatchesSomewhat);
-
-    QTest::newRow("Windows perfect match 1")
-            << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit"))
-            << QString::fromLatin1("x86-windows-msvc2013-pe-64bit")
-            << int(DebuggerItem::MatchesPerfectly);
-    QTest::newRow("Windows perfect match 2")
-            << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit"))
-            << QString::fromLatin1("x86-windows-msvc2012-pe-64bit")
-            << int(DebuggerItem::MatchesPerfectly);
-    QTest::newRow("Windows match 1")
-            << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit"))
-            << QString::fromLatin1("x86-windows-msvc2013-pe-32bit")
-            << int(DebuggerItem::MatchesSomewhat);
-    QTest::newRow("Windows match 2")
-            << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit"))
-            << QString::fromLatin1("x86-windows-msvc2012-pe-32bit")
-            << int(DebuggerItem::MatchesSomewhat);
-    QTest::newRow("Windows mismatch on word size")
-            << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-32bit"))
-            << QString::fromLatin1("x86-windows-msvc2013-pe-64bit")
-            << int(DebuggerItem::DoesNotMatch);
-    QTest::newRow("Windows mismatch on osflavor 1")
-            << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-32bit"))
-            << QString::fromLatin1("x86-windows-msys-pe-64bit")
-            << int(DebuggerItem::DoesNotMatch);
-    QTest::newRow("Windows mismatch on osflavor 2")
-            << (QStringList() << QLatin1String("x86-windows-msys-pe-32bit"))
-            << QString::fromLatin1("x86-windows-msvc2010-pe-64bit")
-            << int(DebuggerItem::DoesNotMatch);
+    // Only register reasonably complete debuggers.
+    QTC_ASSERT(DebuggerItemManager::findById(id), return);
+    k->setValue(DebuggerKitInformation::id(), id);
 }
 
-void Debugger::DebuggerPlugin::testDebuggerMatching()
+Core::Id DebuggerKitInformation::id()
 {
-    QFETCH(QStringList, debugger);
-    QFETCH(QString, target);
-    QFETCH(int, result);
-
-    DebuggerItem::MatchLevel expectedLevel = static_cast<DebuggerItem::MatchLevel>(result);
-
-    QList<Abi> debuggerAbis;
-    foreach (const QString &abi, debugger)
-        debuggerAbis << Abi(abi);
-
-    DebuggerItem item;
-    item.setAbis(debuggerAbis);
-
-    DebuggerItem::MatchLevel level = item.matchTarget(Abi(target));
-
-    QCOMPARE(expectedLevel, level);
+    return "Debugger.Information";
 }
-#endif
+
+} // namespace Debugger
diff --git a/src/plugins/debugger/debuggerkitinformation.h b/src/plugins/debugger/debuggerkitinformation.h
index 4a185d79e3d769885050c081d592778f20de7abe..3e03e19d2e722a056e134a3b36d405798d03a9ca 100644
--- a/src/plugins/debugger/debuggerkitinformation.h
+++ b/src/plugins/debugger/debuggerkitinformation.h
@@ -32,6 +32,7 @@
 
 #include "debugger_global.h"
 #include "debuggerconstants.h"
+#include "debuggeritem.h"
 
 #include <projectexplorer/abi.h>
 #include <projectexplorer/kitinformation.h>
@@ -40,102 +41,6 @@
 
 namespace Debugger {
 
-namespace Internal { class DebuggerItemModel; }
-
-// -----------------------------------------------------------------------
-// DebuggerItem
-// -----------------------------------------------------------------------
-
-class DEBUGGER_EXPORT DebuggerItem
-{
-public:
-    DebuggerItem();
-    DebuggerItem(const QVariantMap &data);
-
-    bool canClone() const { return true; }
-    bool isValid() const;
-    QString engineTypeName() const;
-
-    QVariantMap toMap() const;
-    void reinitializeFromFile();
-
-    QVariant id() const { return m_id; }
-
-    QString displayName() const { return m_displayName; }
-    void setDisplayName(const QString &displayName);
-
-    DebuggerEngineType engineType() const { return m_engineType; }
-    void setEngineType(const DebuggerEngineType &engineType);
-
-    Utils::FileName command() const { return m_command; }
-    void setCommand(const Utils::FileName &command);
-
-    bool isAutoDetected() const { return m_isAutoDetected; }
-    void setAutoDetected(bool isAutoDetected);
-
-    QList<ProjectExplorer::Abi> abis() const { return m_abis; }
-    void setAbis(const QList<ProjectExplorer::Abi> &abis);
-    void setAbi(const ProjectExplorer::Abi &abi);
-
-    enum MatchLevel { DoesNotMatch, MatchesSomewhat, MatchesPerfectly };
-    MatchLevel matchTarget(const ProjectExplorer::Abi &targetAbi) const;
-
-    QStringList abiNames() const;
-
-private:
-    QVariant m_id;
-    QString m_displayName;
-    DebuggerEngineType m_engineType;
-    Utils::FileName m_command;
-    bool m_isAutoDetected;
-    QList<ProjectExplorer::Abi> m_abis;
-};
-
-// -----------------------------------------------------------------------
-// DebuggerItemManager
-// -----------------------------------------------------------------------
-
-class DEBUGGER_EXPORT DebuggerItemManager : public QObject
-{
-    Q_OBJECT
-
-public:
-    static QObject *instance();
-    ~DebuggerItemManager();
-
-    static QList<DebuggerItem> debuggers();
-    static Debugger::Internal::DebuggerItemModel *model();
-
-    static QVariant registerDebugger(const DebuggerItem &item);
-    static void deregisterDebugger(const DebuggerItem &item);
-
-    static const DebuggerItem *findByCommand(const Utils::FileName &command);
-    static const DebuggerItem *findById(const QVariant &id);
-
-    static void restoreDebuggers();
-    static QString uniqueDisplayName(const QString &base);
-    static void setItemData(const QVariant &id, const QString& displayName, const Utils::FileName &fileName);
-
-    static void removeDebugger(const QVariant &id);
-    static QVariant addDebugger(const DebuggerItem &item);
-
-public slots:
-    void saveDebuggers();
-
-private:
-    explicit DebuggerItemManager(QObject *parent = 0);
-    static void autoDetectGdbOrLldbDebuggers();
-    static void autoDetectCdbDebuggers();
-    static void readLegacyDebuggers();
-
-    static Utils::PersistentSettingsWriter *m_writer;
-    static QList<DebuggerItem> m_debuggers;
-    static Debugger::Internal::DebuggerItemModel *m_model;
-
-    friend class Internal::DebuggerItemModel;
-    friend class DebuggerPlugin; // Enable constrcutor for DebuggerPlugin
-};
-
 class DEBUGGER_EXPORT DebuggerKitInformation : public ProjectExplorer::KitInformation
 {
     Q_OBJECT
diff --git a/src/plugins/debugger/debuggeroptionspage.cpp b/src/plugins/debugger/debuggeroptionspage.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..893b28582b09b3b50ca1f6a056a22860fa3a22e0
--- /dev/null
+++ b/src/plugins/debugger/debuggeroptionspage.cpp
@@ -0,0 +1,350 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "debuggeroptionspage.h"
+
+#include "debuggeritemmanager.h"
+#include "debuggeritemmodel.h"
+
+#include <projectexplorer/projectexplorerconstants.h>
+
+#include <utils/detailswidget.h>
+#include <utils/pathchooser.h>
+#include <utils/qtcassert.h>
+
+#include <QFormLayout>
+#include <QHeaderView>
+#include <QLabel>
+#include <QLineEdit>
+#include <QObject>
+#include <QPushButton>
+#include <QTreeView>
+#include <QWidget>
+
+using namespace Utils;
+
+namespace Debugger {
+namespace Internal {
+
+static const char debuggingToolsWikiLinkC[] = "http://qt-project.org/wiki/Qt_Creator_Windows_Debugging";
+
+// -----------------------------------------------------------------------
+// DebuggerItemConfigWidget
+// -----------------------------------------------------------------------
+
+class DebuggerItemConfigWidget : public QWidget
+{
+    Q_DECLARE_TR_FUNCTIONS(Debugger::Internal::DebuggerItemConfigWidget)
+
+public:
+    explicit DebuggerItemConfigWidget();
+    void loadItem();
+    void saveItem();
+    void connectDirty();
+    void disconnectDirty();
+
+private:
+    QLineEdit *m_displayNameLineEdit;
+    QLabel *m_cdbLabel;
+    PathChooser *m_binaryChooser;
+    QLineEdit *m_abis;
+};
+
+DebuggerItemConfigWidget::DebuggerItemConfigWidget()
+{
+    m_displayNameLineEdit = new QLineEdit(this);
+
+    m_binaryChooser = new PathChooser(this);
+    m_binaryChooser->setExpectedKind(PathChooser::ExistingCommand);
+    m_binaryChooser->setMinimumWidth(400);
+
+    m_cdbLabel = new QLabel(this);
+    m_cdbLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
+    m_cdbLabel->setOpenExternalLinks(true);
+
+    m_abis = new QLineEdit(this);
+    m_abis->setEnabled(false);
+
+    QFormLayout *formLayout = new QFormLayout(this);
+    formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
+    formLayout->addRow(new QLabel(tr("Name:")), m_displayNameLineEdit);
+//    formLayout->addRow(new QLabel(tr("Type:")), m_engineTypeComboBox);
+    formLayout->addRow(m_cdbLabel);
+    formLayout->addRow(new QLabel(tr("Path:")), m_binaryChooser);
+    formLayout->addRow(new QLabel(tr("ABIs:")), m_abis);
+
+    connectDirty();
+}
+
+void DebuggerItemConfigWidget::connectDirty()
+{
+    DebuggerItemModel *model = DebuggerItemManager::model();
+    connect(m_displayNameLineEdit, SIGNAL(textChanged(QString)),
+            model, SLOT(markCurrentDirty()));
+    connect(m_binaryChooser, SIGNAL(changed(QString)),
+            model, SLOT(markCurrentDirty()));
+}
+
+void DebuggerItemConfigWidget::disconnectDirty()
+{
+    DebuggerItemModel *model = DebuggerItemManager::model();
+    disconnect(m_displayNameLineEdit, SIGNAL(textChanged(QString)),
+            model, SLOT(markCurrentDirty()));
+    disconnect(m_binaryChooser, SIGNAL(changed(QString)),
+            model, SLOT(markCurrentDirty()));
+}
+
+void DebuggerItemConfigWidget::loadItem()
+{
+    DebuggerItemModel *model = DebuggerItemManager::model();
+    const DebuggerItem *item = DebuggerItemManager::findById(model->currentDebugger());
+    if (!item)
+        return;
+
+    disconnectDirty();
+    m_displayNameLineEdit->setEnabled(!item->isAutoDetected());
+    m_displayNameLineEdit->setText(item->displayName());
+
+    m_binaryChooser->setEnabled(!item->isAutoDetected());
+    m_binaryChooser->setFileName(item->command());
+    connectDirty();
+
+    QString text;
+    QString versionCommand;
+    if (item->engineType() == CdbEngineType) {
+#ifdef Q_OS_WIN
+        const bool is64bit = winIs64BitSystem();
+#else
+        const bool is64bit = false;
+#endif
+        const QString versionString = is64bit ? tr("64-bit version") : tr("32-bit version");
+        //: Label text for path configuration. %2 is "x-bit version".
+        text = tr("<html><body><p>Specify the path to the "
+                  "<a href=\"%1\">Windows Console Debugger executable</a>"
+                  " (%2) here.</p>""</body></html>").
+                arg(QLatin1String(debuggingToolsWikiLinkC), versionString);
+        versionCommand = QLatin1String("-version");
+    } else {
+        versionCommand = QLatin1String("--version");
+    }
+
+    m_cdbLabel->setText(text);
+    m_cdbLabel->setVisible(!text.isEmpty());
+    m_binaryChooser->setCommandVersionArguments(QStringList(versionCommand));
+
+    m_abis->setText(item->abiNames().join(QLatin1String(", ")));
+}
+
+void DebuggerItemConfigWidget::saveItem()
+{
+    DebuggerItemModel *model = DebuggerItemManager::model();
+    const DebuggerItem *item = DebuggerItemManager::findById(model->currentDebugger());
+    QTC_ASSERT(item, return);
+    DebuggerItemManager::setItemData(item->id(), m_displayNameLineEdit->text(),
+                                                             m_binaryChooser->fileName());
+}
+
+// --------------------------------------------------------------------------
+// DebuggerOptionsPage
+// --------------------------------------------------------------------------
+
+DebuggerOptionsPage::DebuggerOptionsPage()
+{
+    m_model = 0;
+    m_debuggerView = 0;
+    m_container = 0;
+    m_addButton = 0;
+    m_cloneButton = 0;
+    m_delButton = 0;
+
+    setId(ProjectExplorer::Constants::DEBUGGER_SETTINGS_PAGE_ID);
+    setDisplayName(tr("Debuggers"));
+    setCategory(ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_CATEGORY);
+    setDisplayCategory(QCoreApplication::translate("ProjectExplorer",
+        ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_TR_CATEGORY));
+    setCategoryIcon(QLatin1String(ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_CATEGORY_ICON));
+}
+
+QWidget *DebuggerOptionsPage::createPage(QWidget *parent)
+{
+    m_configWidget = new QWidget(parent);
+
+    m_addButton = new QPushButton(tr("Add"), m_configWidget);
+    m_cloneButton = new QPushButton(tr("Clone"), m_configWidget);
+    m_delButton = new QPushButton(tr("Remove"), m_configWidget);
+
+    m_container = new DetailsWidget(m_configWidget);
+    m_container->setState(DetailsWidget::NoSummary);
+    m_container->setVisible(false);
+
+    m_model = DebuggerItemManager::model();
+
+    m_debuggerView = new QTreeView(m_configWidget);
+    m_debuggerView->setModel(m_model);
+    m_debuggerView->setUniformRowHeights(true);
+    m_debuggerView->setSelectionMode(QAbstractItemView::SingleSelection);
+    m_debuggerView->setSelectionBehavior(QAbstractItemView::SelectRows);
+    m_debuggerView->expandAll();
+
+    QHeaderView *header = m_debuggerView->header();
+    header->setStretchLastSection(false);
+    header->setResizeMode(0, QHeaderView::ResizeToContents);
+    header->setResizeMode(1, QHeaderView::ResizeToContents);
+    header->setResizeMode(2, QHeaderView::Stretch);
+
+    QVBoxLayout *buttonLayout = new QVBoxLayout();
+    buttonLayout->setSpacing(6);
+    buttonLayout->setContentsMargins(0, 0, 0, 0);
+    buttonLayout->addWidget(m_addButton);
+    buttonLayout->addWidget(m_cloneButton);
+    buttonLayout->addWidget(m_delButton);
+    buttonLayout->addItem(new QSpacerItem(10, 40, QSizePolicy::Minimum, QSizePolicy::Expanding));
+
+    QVBoxLayout *verticalLayout = new QVBoxLayout();
+    verticalLayout->addWidget(m_debuggerView);
+    verticalLayout->addWidget(m_container);
+
+    QHBoxLayout *horizontalLayout = new QHBoxLayout(m_configWidget);
+    horizontalLayout->addLayout(verticalLayout);
+    horizontalLayout->addLayout(buttonLayout);
+
+    connect(m_debuggerView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
+            this, SLOT(debuggerSelectionChanged()));
+
+    connect(m_addButton, SIGNAL(clicked()), this, SLOT(addDebugger()), Qt::QueuedConnection);
+    connect(m_cloneButton, SIGNAL(clicked()), this, SLOT(cloneDebugger()), Qt::QueuedConnection);
+    connect(m_delButton, SIGNAL(clicked()), this, SLOT(removeDebugger()), Qt::QueuedConnection);
+
+    m_searchKeywords = tr("Debuggers");
+
+    m_itemConfigWidget = new DebuggerItemConfigWidget;
+    m_container->setWidget(m_itemConfigWidget);
+
+    updateState();
+
+    return m_configWidget;
+}
+
+void DebuggerOptionsPage::apply()
+{
+    m_itemConfigWidget->saveItem();
+    debuggerModelChanged();
+}
+
+void DebuggerOptionsPage::cloneDebugger()
+{
+    const DebuggerItem *item = DebuggerItemManager::findById(m_model->currentDebugger());
+    QTC_ASSERT(item, return);
+    DebuggerItem newItem;
+    newItem.setCommand(item->command());
+    newItem.setEngineType(item->engineType());
+    newItem.setAbis(item->abis());
+    newItem.setDisplayName(DebuggerItemManager::uniqueDisplayName(tr("Clone of %1").arg(item->displayName())));
+    newItem.setAutoDetected(false);
+    DebuggerItemManager::addDebugger(newItem);
+    m_debuggerView->setCurrentIndex(m_model->lastIndex());
+}
+
+void DebuggerOptionsPage::addDebugger()
+{
+    DebuggerItem item;
+    item.setEngineType(NoEngineType);
+    item.setDisplayName(DebuggerItemManager::uniqueDisplayName(tr("New Debugger")));
+    item.setAutoDetected(false);
+    DebuggerItemManager::addDebugger(item);
+    m_debuggerView->setCurrentIndex(m_model->lastIndex());
+}
+
+void DebuggerOptionsPage::removeDebugger()
+{
+    QVariant id = m_model->currentDebugger();
+    DebuggerItemManager::removeDebugger(id);
+    m_debuggerView->setCurrentIndex(m_model->lastIndex());
+}
+
+void DebuggerOptionsPage::finish()
+{
+    // Deleted by settingsdialog.
+    m_configWidget = 0;
+
+    // Children of m_configWidget.
+    m_container = 0;
+    m_debuggerView = 0;
+    m_addButton = 0;
+    m_cloneButton = 0;
+    m_delButton = 0;
+}
+
+bool DebuggerOptionsPage::matches(const QString &s) const
+{
+    return m_searchKeywords.contains(s, Qt::CaseInsensitive);
+}
+
+void DebuggerOptionsPage::debuggerSelectionChanged()
+{
+    QTC_ASSERT(m_container, return);
+
+    QModelIndex mi = m_debuggerView->currentIndex();
+    mi = mi.sibling(mi.row(), 0);
+    m_model->setCurrentIndex(mi);
+
+    m_itemConfigWidget->loadItem();
+    m_container->setVisible(m_model->currentDebugger().isValid());
+    updateState();
+}
+
+void DebuggerOptionsPage::debuggerModelChanged()
+{
+    QTC_ASSERT(m_container, return);
+
+    m_itemConfigWidget->loadItem();
+    m_container->setVisible(m_model->currentDebugger().isValid());
+    m_debuggerView->setCurrentIndex(m_model->currentIndex());
+    updateState();
+}
+
+void DebuggerOptionsPage::updateState()
+{
+    if (!m_cloneButton)
+        return;
+
+    bool canCopy = false;
+    bool canDelete = false;
+
+    if (const DebuggerItem *item = DebuggerItemManager::findById(m_model->currentDebugger())) {
+        canCopy = item->isValid() && item->canClone();
+        canDelete = !item->isAutoDetected();
+        canDelete = true; // Do we want to remove auto-detected items?
+    }
+    m_cloneButton->setEnabled(canCopy);
+    m_delButton->setEnabled(canDelete);
+}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/debuggeroptionspage.h b/src/plugins/debugger/debuggeroptionspage.h
new file mode 100644
index 0000000000000000000000000000000000000000..fd1782f4b47d5a2a6a1b5f1d973f6bd86199dbac
--- /dev/null
+++ b/src/plugins/debugger/debuggeroptionspage.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef DEBUGGER_DEBUGGEROPTIONSPAGE_H
+#define DEBUGGER_DEBUGGEROPTIONSPAGE_H
+
+#include <coreplugin/dialogs/ioptionspage.h>
+
+QT_BEGIN_NAMESPACE
+class QPushButton;
+class QTreeView;
+class QWidget;
+QT_END_NAMESPACE
+
+namespace Utils { class DetailsWidget; }
+
+namespace Debugger {
+namespace Internal {
+
+class DebuggerItemModel;
+class DebuggerItemConfigWidget;
+class DebuggerKitConfigWidget;
+
+// --------------------------------------------------------------------------
+// DebuggerOptionsPage
+// --------------------------------------------------------------------------
+
+class DebuggerOptionsPage : public Core::IOptionsPage
+{
+    Q_OBJECT
+
+public:
+    DebuggerOptionsPage();
+
+    QWidget *createPage(QWidget *parent);
+    void apply();
+    void finish();
+    bool matches(const QString &) const;
+
+private slots:
+    void debuggerSelectionChanged();
+    void debuggerModelChanged();
+    void updateState();
+    void cloneDebugger();
+    void addDebugger();
+    void removeDebugger();
+
+private:
+    QWidget *m_configWidget;
+    QString m_searchKeywords;
+
+    DebuggerItemModel *m_model;
+    DebuggerItemConfigWidget *m_itemConfigWidget;
+    QTreeView *m_debuggerView;
+    Utils::DetailsWidget *m_container;
+    QPushButton *m_addButton;
+    QPushButton *m_cloneButton;
+    QPushButton *m_delButton;
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // DEBUGGER_DEBUGGEROPTIONSPAGE_H
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index a01bdc9b63667095a193369afbae2198c06b64b4..67953afcfca6a6d9c01a07c16f320e6940134869 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -36,11 +36,13 @@
 #include "debuggerkitconfigwidget.h"
 #include "debuggerdialogs.h"
 #include "debuggerengine.h"
+#include "debuggeritemmanager.h"
 #include "debuggermainwindow.h"
 #include "debuggerrunner.h"
 #include "debuggerrunconfigurationaspect.h"
 #include "debuggerruncontrolfactory.h"
 #include "debuggerstringutils.h"
+#include "debuggeroptionspage.h"
 #include "debuggerkitinformation.h"
 #include "memoryagent.h"
 #include "breakhandler.h"
diff --git a/src/plugins/ios/iosconfigurations.cpp b/src/plugins/ios/iosconfigurations.cpp
index ebfca0293fcc2a532c29a01583bcf7070fbba2f0..1eaa690bc994cc7cea56cd3aa7e212cfc1753f50 100644
--- a/src/plugins/ios/iosconfigurations.cpp
+++ b/src/plugins/ios/iosconfigurations.cpp
@@ -42,6 +42,7 @@
 #include <projectexplorer/toolchain.h>
 #include <projectexplorer/gcctoolchain.h>
 #include <projectexplorer/projectexplorerconstants.h>
+#include <debugger/debuggeritemmanager.h>
 #include <debugger/debuggerkitinformation.h>
 #include <qtsupport/baseqtversion.h>
 #include <qtsupport/qtkitinformation.h>
diff --git a/src/plugins/qnx/blackberryconfiguration.cpp b/src/plugins/qnx/blackberryconfiguration.cpp
index 78b01a30d88c34ab4fc4ddc5f918d08d71bbce7d..cc45468e53969b57ee98f23fda953a6194f3f1a4 100644
--- a/src/plugins/qnx/blackberryconfiguration.cpp
+++ b/src/plugins/qnx/blackberryconfiguration.cpp
@@ -45,6 +45,7 @@
 
 #include <qt4projectmanager/qmakekitinformation.h>
 
+#include <debugger/debuggeritemmanager.h>
 #include <debugger/debuggerkitinformation.h>
 
 #include <QFileInfo>