diff options
Diffstat (limited to 'src/plugins/debugger/debuggeroptionspage.cpp')
-rw-r--r-- | src/plugins/debugger/debuggeroptionspage.cpp | 459 |
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 |