summaryrefslogtreecommitdiff
path: root/src/plugins/debugger/debuggeroptionspage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/debugger/debuggeroptionspage.cpp')
-rw-r--r--src/plugins/debugger/debuggeroptionspage.cpp459
1 files changed, 287 insertions, 172 deletions
diff --git a/src/plugins/debugger/debuggeroptionspage.cpp b/src/plugins/debugger/debuggeroptionspage.cpp
index d0b04a9b32..0484757ca8 100644
--- a/src/plugins/debugger/debuggeroptionspage.cpp
+++ b/src/plugins/debugger/debuggeroptionspage.cpp
@@ -29,15 +29,14 @@
****************************************************************************/
#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 <utils/treemodel.h>
#include <utils/winutils.h>
#include <QFileInfo>
@@ -55,19 +54,176 @@ using namespace Utils;
namespace Debugger {
namespace Internal {
-static const char debuggingToolsWikiLinkC[] = "http://qt-project.org/wiki/Qt_Creator_Windows_Debugging";
+const char debuggingToolsWikiLinkC[] = "http://qt-project.org/wiki/Qt_Creator_Windows_Debugging";
+
+// --------------------------------------------------------------------------
+// DebuggerTreeItem
+// --------------------------------------------------------------------------
+
+class DebuggerTreeItem : public TreeItem
+{
+public:
+ DebuggerTreeItem(const DebuggerItem &item, bool changed) : m_item(item), m_changed(changed) {}
+
+ QVariant data(int column, int role) const
+ {
+ switch (role) {
+ case Qt::DisplayRole:
+ switch (column) {
+ case 0: return m_item.displayName();
+ case 1: return m_item.command().toUserOutput();
+ case 2: return m_item.engineTypeName();
+ }
+
+ case Qt::FontRole: {
+ QFont font;
+ font.setBold(m_changed);
+ return font;
+ }
+ }
+ return QVariant();
+ }
+
+ DebuggerItem m_item;
+ bool m_changed;
+};
+
+// --------------------------------------------------------------------------
+// DebuggerItemModel
+// --------------------------------------------------------------------------
+
+class DebuggerItemModel : public TreeModel
+{
+ Q_DECLARE_TR_FUNCTIONS(Debugger::DebuggerOptionsPage)
+
+public:
+ DebuggerItemModel();
+
+ QModelIndex lastIndex() const;
+ void setCurrentIndex(const QModelIndex &index);
+ DebuggerItem *currentDebugger() const;
+ void addDebugger(const DebuggerItem &item, bool changed);
+ void updateDebugger(const DebuggerItem &item);
+ void removeCurrentDebugger();
+ void apply();
+
+private:
+ DebuggerTreeItem *m_currentTreeItem;
+ QStringList removed;
+
+ QList<QVariant> m_removedItems;
+};
+
+DebuggerItemModel::DebuggerItemModel()
+ : m_currentTreeItem(0)
+{
+ setHeader(QStringList() << tr("Name") << tr("Location") << tr("Type"));
+ rootItem()->appendChild(new TreeItem(QStringList() << tr("Auto-detected") << QString() << QString()));
+ rootItem()->appendChild(new TreeItem(QStringList() << tr("Manual") << QString() << QString()));
+
+ foreach (const DebuggerItem &item, DebuggerItemManager::debuggers())
+ addDebugger(item, false);
+}
+
+void DebuggerItemModel::addDebugger(const DebuggerItem &item, bool changed)
+{
+ int group = item.isAutoDetected() ? 0 : 1;
+ rootItem()->child(group)->appendChild(new DebuggerTreeItem(item, changed));
+}
+
+void DebuggerItemModel::updateDebugger(const DebuggerItem &item)
+{
+ auto matcher = [item](DebuggerTreeItem *n) { return n->m_item.m_id == item.id(); };
+ DebuggerTreeItem *treeItem = findItemAtLevel<DebuggerTreeItem *>(2, matcher);
+ QTC_ASSERT(treeItem, return);
+
+ TreeItem *parent = treeItem->parent();
+ QTC_ASSERT(parent, return);
+
+ const DebuggerItem *orig = DebuggerItemManager::findById(item.id());
+ treeItem->m_changed = !orig || *orig != item;
+ treeItem->m_item = item;
+ treeItem->update(); // Notify views.
+}
+
+QModelIndex DebuggerItemModel::lastIndex() const
+{
+ TreeItem *manualGroup = rootItem()->lastChild();
+ TreeItem *lastItem = manualGroup->lastChild();
+ return lastItem ? indexFromItem(lastItem) : QModelIndex();
+}
+
+DebuggerItem *DebuggerItemModel::currentDebugger() const
+{
+ return m_currentTreeItem ? &m_currentTreeItem->m_item : 0;
+}
+
+void DebuggerItemModel::removeCurrentDebugger()
+{
+ QTC_ASSERT(m_currentTreeItem, return);
+ QVariant id = m_currentTreeItem->m_item.id();
+ DebuggerTreeItem *treeItem = m_currentTreeItem;
+ m_currentTreeItem = 0;
+ removeItem(treeItem);
+ delete treeItem;
+ m_removedItems.append(id);
+}
+
+void DebuggerItemModel::apply()
+{
+ foreach (const QVariant &id, m_removedItems)
+ DebuggerItemManager::deregisterDebugger(id);
+
+ foreach (auto item, treeLevelItems<DebuggerTreeItem *>(2)) {
+ item->m_changed = false;
+ DebuggerItemManager::updateOrAddDebugger(item->m_item);
+ }
+}
+
+void DebuggerItemModel::setCurrentIndex(const QModelIndex &index)
+{
+ TreeItem *treeItem = itemFromIndex(index);
+ m_currentTreeItem = treeItem && treeItem->level() == 2 ? static_cast<DebuggerTreeItem *>(treeItem) : 0;
+}
// -----------------------------------------------------------------------
// DebuggerItemConfigWidget
// -----------------------------------------------------------------------
-DebuggerItemConfigWidget::DebuggerItemConfigWidget(DebuggerItemModel *model) :
- m_model(model)
+class DebuggerItemConfigWidget : public QWidget
+{
+ Q_DECLARE_TR_FUNCTIONS(Debugger::DebuggerOptionsPage)
+
+public:
+ explicit DebuggerItemConfigWidget(DebuggerItemModel *model);
+ void load(const DebuggerItem *item);
+ void store() const;
+
+private:
+ void binaryPathHasChanged();
+ DebuggerItem item() const;
+ void setAbis(const QStringList &abiNames);
+
+ DebuggerItemModel *m_model;
+ QLineEdit *m_displayNameLineEdit;
+ QLineEdit *m_typeLineEdit;
+ QLabel *m_cdbLabel;
+ QLineEdit *m_versionLabel;
+ PathChooser *m_binaryChooser;
+ QLineEdit *m_abis;
+ bool m_autodetected;
+ DebuggerEngineType m_engineType;
+ QVariant m_id;
+};
+
+DebuggerItemConfigWidget::DebuggerItemConfigWidget(DebuggerItemModel *model)
+ : m_model(model)
{
- QTC_CHECK(model);
-
m_displayNameLineEdit = new QLineEdit(this);
+ m_typeLineEdit = new QLineEdit(this);
+ m_typeLineEdit->setEnabled(false);
+
m_binaryChooser = new PathChooser(this);
m_binaryChooser->setExpectedKind(PathChooser::ExistingCommand);
m_binaryChooser->setMinimumWidth(400);
@@ -87,21 +243,21 @@ DebuggerItemConfigWidget::DebuggerItemConfigWidget(DebuggerItemModel *model) :
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("Type:")), m_typeLineEdit);
formLayout->addRow(new QLabel(tr("ABIs:")), m_abis);
formLayout->addRow(new QLabel(tr("Version:")), m_versionLabel);
- connect(m_binaryChooser, SIGNAL(changed(QString)), this, SLOT(binaryPathHasChanged()));
+ connect(m_binaryChooser, &PathChooser::changed,
+ this, &DebuggerItemConfigWidget::binaryPathHasChanged);
+ connect(m_displayNameLineEdit, &QLineEdit::textChanged,
+ this, &DebuggerItemConfigWidget::store);
}
DebuggerItem DebuggerItemConfigWidget::item() const
{
DebuggerItem item(m_id);
- if (m_id.isNull())
- return item;
-
item.setDisplayName(m_displayNameLineEdit->text());
item.setCommand(m_binaryChooser->fileName());
item.setAutoDetected(m_autodetected);
@@ -117,12 +273,10 @@ DebuggerItem DebuggerItemConfigWidget::item() const
return item;
}
-
void DebuggerItemConfigWidget::store() const
{
- DebuggerItem i = item();
- if (i.isValid())
- m_model->updateDebugger(i);
+ if (!m_id.isNull())
+ m_model->updateDebugger(item());
}
void DebuggerItemConfigWidget::setAbis(const QStringList &abiNames)
@@ -130,50 +284,26 @@ void DebuggerItemConfigWidget::setAbis(const QStringList &abiNames)
m_abis->setText(abiNames.join(QLatin1String(", ")));
}
-void DebuggerItemConfigWidget::handleCommandChange()
+void DebuggerItemConfigWidget::load(const DebuggerItem *item)
{
- // Use DebuggerItemManager as a cache:
- const DebuggerItem *existing
- = DebuggerItemManager::findByCommand(m_binaryChooser->fileName());
- if (existing) {
- setAbis(existing->abiNames());
- m_versionLabel->setText(existing->version());
- m_engineType = existing->engineType();
- } else {
- QFileInfo fi = QFileInfo(m_binaryChooser->path());
- if (fi.isExecutable()) {
- DebuggerItem tmp = item();
- tmp.reinitializeFromFile();
- setAbis(tmp.abiNames());
- m_versionLabel->setText(tmp.version());
- m_engineType = tmp.engineType();
- } else {
- setAbis(QStringList());
- m_versionLabel->setText(QString());
- m_engineType = NoEngineType;
- }
- }
- m_model->updateDebugger(item());
-}
-
-void DebuggerItemConfigWidget::setItem(const DebuggerItem &item)
-{
- store(); // store away the (changed) settings for future use
-
m_id = QVariant(); // reset Id to avoid intermediate signal handling
+ if (!item)
+ return;
// Set values:
- m_autodetected = item.isAutoDetected();
+ m_autodetected = item->isAutoDetected();
- m_displayNameLineEdit->setEnabled(!item.isAutoDetected());
- m_displayNameLineEdit->setText(item.displayName());
+ m_displayNameLineEdit->setEnabled(!item->isAutoDetected());
+ m_displayNameLineEdit->setText(item->displayName());
- m_binaryChooser->setReadOnly(item.isAutoDetected());
- m_binaryChooser->setFileName(item.command());
+ m_typeLineEdit->setText(item->engineTypeName());
+
+ m_binaryChooser->setReadOnly(item->isAutoDetected());
+ m_binaryChooser->setFileName(item->command());
QString text;
QString versionCommand;
- if (item.engineType() == CdbEngineType) {
+ if (item->engineType() == CdbEngineType) {
const bool is64bit = is64BitWindowsSystem();
const QString versionString = is64bit ? tr("64-bit version") : tr("32-bit version");
//: Label text for path configuration. %2 is "x-bit version".
@@ -189,20 +319,10 @@ void DebuggerItemConfigWidget::setItem(const DebuggerItem &item)
m_cdbLabel->setText(text);
m_cdbLabel->setVisible(!text.isEmpty());
m_binaryChooser->setCommandVersionArguments(QStringList(versionCommand));
- m_versionLabel->setText(item.version());
- setAbis(item.abiNames());
- m_engineType = item.engineType();
- m_id = item.id();
-}
-
-void DebuggerItemConfigWidget::apply()
-{
- DebuggerItem current = m_model->currentDebugger();
- if (!current.isValid())
- return; // Nothing was selected here.
-
- store();
- setItem(item());
+ m_versionLabel->setText(item->version());
+ setAbis(item->abiNames());
+ m_engineType = item->engineType();
+ m_id = item->id();
}
void DebuggerItemConfigWidget::binaryPathHasChanged()
@@ -211,58 +331,57 @@ void DebuggerItemConfigWidget::binaryPathHasChanged()
if (!m_id.isValid())
return;
- handleCommandChange();
+ DebuggerItem tmp;
+ QFileInfo fi = QFileInfo(m_binaryChooser->path());
+ if (fi.isExecutable()) {
+ tmp = item();
+ tmp.reinitializeFromFile();
+ }
+
+ setAbis(tmp.abiNames());
+ m_versionLabel->setText(tmp.version());
+ m_engineType = tmp.engineType();
+ m_typeLineEdit->setText(tmp.engineTypeName());
+
+ store();
}
// --------------------------------------------------------------------------
-// DebuggerOptionsPage
+// DebuggerConfigWidget
// --------------------------------------------------------------------------
-DebuggerOptionsPage::DebuggerOptionsPage()
+class DebuggerConfigWidget : public QWidget
{
- m_model = 0;
- m_debuggerView = 0;
- m_container = 0;
- m_addButton = 0;
- m_cloneButton = 0;
- m_delButton = 0;
+public:
+ DebuggerConfigWidget()
+ {
+ m_addButton = new QPushButton(tr("Add"), this);
- 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::widget()
-{
- if (!m_configWidget) {
- m_configWidget = new QWidget;
+ m_cloneButton = new QPushButton(tr("Clone"), this);
+ m_cloneButton->setEnabled(false);
- 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_delButton = new QPushButton(tr("Remove"), this);
+ m_delButton->setEnabled(false);
- m_container = new DetailsWidget(m_configWidget);
+ m_container = new DetailsWidget(this);
m_container->setState(DetailsWidget::NoSummary);
m_container->setVisible(false);
- m_debuggerView = new QTreeView(m_configWidget);
- m_model = new DebuggerItemModel(m_debuggerView);
- m_debuggerView->setModel(m_model);
+ m_debuggerView = new QTreeView(this);
+ m_debuggerView->setModel(&m_model);
m_debuggerView->setUniformRowHeights(true);
+ m_debuggerView->setRootIsDecorated(false);
m_debuggerView->setSelectionMode(QAbstractItemView::SingleSelection);
m_debuggerView->setSelectionBehavior(QAbstractItemView::SelectRows);
m_debuggerView->expandAll();
- QHeaderView *header = m_debuggerView->header();
+ auto header = m_debuggerView->header();
header->setStretchLastSection(false);
header->setSectionResizeMode(0, QHeaderView::ResizeToContents);
header->setSectionResizeMode(1, QHeaderView::ResizeToContents);
header->setSectionResizeMode(2, QHeaderView::Stretch);
- QVBoxLayout *buttonLayout = new QVBoxLayout();
+ auto buttonLayout = new QVBoxLayout();
buttonLayout->setSpacing(6);
buttonLayout->setContentsMargins(0, 0, 0, 0);
buttonLayout->addWidget(m_addButton);
@@ -270,54 +389,62 @@ QWidget *DebuggerOptionsPage::widget()
buttonLayout->addWidget(m_delButton);
buttonLayout->addItem(new QSpacerItem(10, 40, QSizePolicy::Minimum, QSizePolicy::Expanding));
- QVBoxLayout *verticalLayout = new QVBoxLayout();
+ auto verticalLayout = new QVBoxLayout();
verticalLayout->addWidget(m_debuggerView);
verticalLayout->addWidget(m_container);
- QHBoxLayout *horizontalLayout = new QHBoxLayout(m_configWidget);
+ auto horizontalLayout = new QHBoxLayout(this);
horizontalLayout->addLayout(verticalLayout);
horizontalLayout->addLayout(buttonLayout);
- connect(m_debuggerView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
- this, SLOT(debuggerSelectionChanged()));
+ connect(m_debuggerView->selectionModel(), &QItemSelectionModel::currentChanged,
+ this, &DebuggerConfigWidget::currentDebuggerChanged, Qt::QueuedConnection);
- 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);
+ connect(m_addButton, &QAbstractButton::clicked,
+ this, &DebuggerConfigWidget::addDebugger, Qt::QueuedConnection);
+ connect(m_cloneButton, &QAbstractButton::clicked,
+ this, &DebuggerConfigWidget::cloneDebugger, Qt::QueuedConnection);
+ connect(m_delButton, &QAbstractButton::clicked,
+ this, &DebuggerConfigWidget::removeDebugger, Qt::QueuedConnection);
- m_itemConfigWidget = new DebuggerItemConfigWidget(m_model);
+ m_itemConfigWidget = new DebuggerItemConfigWidget(&m_model);
m_container->setWidget(m_itemConfigWidget);
-
- updateState();
}
- return m_configWidget;
-}
-void DebuggerOptionsPage::apply()
+ void cloneDebugger();
+ void addDebugger();
+ void removeDebugger();
+ void currentDebuggerChanged(const QModelIndex &newCurrent);
+ void updateState();
+
+ DebuggerItemModel m_model;
+ QTreeView *m_debuggerView;
+ QPushButton *m_addButton;
+ QPushButton *m_cloneButton;
+ QPushButton *m_delButton;
+ DetailsWidget *m_container;
+ DebuggerItemConfigWidget *m_itemConfigWidget;
+};
+
+void DebuggerConfigWidget::cloneDebugger()
{
- m_itemConfigWidget->apply();
- m_model->apply();
-}
-
-void DebuggerOptionsPage::cloneDebugger()
-{
- DebuggerItem item = m_model->currentDebugger();
- if (!item.isValid())
+ DebuggerItem *item = m_model.currentDebugger();
+ if (!item)
return;
DebuggerItem newItem;
newItem.createId();
newItem.setAutoDetected(false);
- newItem.setCommand(item.command());
- newItem.setEngineType(item.engineType());
- newItem.setAbis(item.abis());
- newItem.setDisplayName(DebuggerItemManager::uniqueDisplayName(tr("Clone of %1").arg(item.displayName())));
+ 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);
- m_model->addDebugger(newItem);
- m_debuggerView->setCurrentIndex(m_model->lastIndex());
+ m_model.addDebugger(newItem, true);
+ m_debuggerView->setCurrentIndex(m_model.lastIndex());
}
-void DebuggerOptionsPage::addDebugger()
+void DebuggerConfigWidget::addDebugger()
{
DebuggerItem item;
item.createId();
@@ -325,72 +452,60 @@ void DebuggerOptionsPage::addDebugger()
item.setEngineType(NoEngineType);
item.setDisplayName(DebuggerItemManager::uniqueDisplayName(tr("New Debugger")));
item.setAutoDetected(false);
- m_model->addDebugger(item);
- m_debuggerView->setCurrentIndex(m_model->lastIndex());
+ m_model.addDebugger(item, true);
+ m_debuggerView->setCurrentIndex(m_model.lastIndex());
}
-void DebuggerOptionsPage::removeDebugger()
+void DebuggerConfigWidget::removeDebugger()
{
- QVariant id = m_model->currentDebuggerId();
- m_model->removeDebugger(id);
- m_debuggerView->setCurrentIndex(m_model->lastIndex());
+ m_model.removeCurrentDebugger();
+ m_debuggerView->setCurrentIndex(m_model.lastIndex());
}
-void DebuggerOptionsPage::finish()
+void DebuggerConfigWidget::currentDebuggerChanged(const QModelIndex &newCurrent)
{
- delete m_configWidget;
-
- // Children of m_configWidget.
- m_model = 0;
- m_container = 0;
- m_debuggerView = 0;
- m_addButton = 0;
- m_cloneButton = 0;
- m_delButton = 0;
-}
+ m_model.setCurrentIndex(newCurrent);
-void DebuggerOptionsPage::debuggerSelectionChanged()
-{
- QTC_ASSERT(m_container, return);
+ DebuggerItem *item = m_model.currentDebugger();
- QModelIndex mi = m_debuggerView->currentIndex();
- mi = mi.sibling(mi.row(), 0);
- m_model->setCurrentIndex(mi);
+ m_itemConfigWidget->load(item);
+ m_container->setVisible(item);
+ m_cloneButton->setEnabled(item && item->isValid() && item->canClone());
+ m_delButton->setEnabled(item && !item->isAutoDetected());
+}
- DebuggerItem item = m_model->currentDebugger();
+// --------------------------------------------------------------------------
+// DebuggerOptionsPage
+// --------------------------------------------------------------------------
- m_itemConfigWidget->setItem(item);
- m_container->setVisible(item.isValid());
- updateState();
+DebuggerOptionsPage::DebuggerOptionsPage()
+{
+ 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));
}
-void DebuggerOptionsPage::debuggerModelChanged()
+QWidget *DebuggerOptionsPage::widget()
{
- QTC_ASSERT(m_container, return);
-
- QVariant id = m_model->currentDebuggerId();
- const DebuggerItem *item = DebuggerItemManager::findById(id);
- if (!item)
- return;
-
- m_itemConfigWidget->setItem(*item);
- m_container->setVisible(m_model->currentDebuggerId().isValid());
- m_debuggerView->setCurrentIndex(m_model->currentIndex());
- updateState();
+ if (!m_configWidget)
+ m_configWidget = new DebuggerConfigWidget;
+ return m_configWidget;
}
-void DebuggerOptionsPage::updateState()
+void DebuggerOptionsPage::apply()
{
- if (!m_cloneButton)
- return;
-
- DebuggerItem item = m_model->currentDebugger();
-
- bool canCopy = item.isValid() && item.canClone();
- bool canDelete = m_model->currentIndex().parent().isValid() && !item.isAutoDetected();
+ QTC_ASSERT(m_configWidget, return);
+ m_configWidget->m_itemConfigWidget->store();
+ m_configWidget->m_model.apply();
+}
- m_cloneButton->setEnabled(canCopy);
- m_delButton->setEnabled(canDelete);
+void DebuggerOptionsPage::finish()
+{
+ delete m_configWidget;
+ m_configWidget = 0;
}
} // namespace Internal