forked from qt-creator/qt-creator
Debugger: Use DebuggerTreeItem in DebuggerKitAspect
For sorting and icons. Task-number: QTCREATORBUG-31574 Change-Id: Ieefe3f2dfc0078439ca70db61b512394d9c35fdf Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -308,7 +308,7 @@ QDateTime DebuggerItem::lastModified() const
|
||||
|
||||
DebuggerItem::Problem DebuggerItem::problem() const
|
||||
{
|
||||
if (isGeneric())
|
||||
if (isGeneric() || !m_id.isValid()) // Id can only be invalid for the "none" item.
|
||||
return Problem::None;
|
||||
if (m_engineType == NoEngineType)
|
||||
return Problem::NoEngine;
|
||||
|
@@ -3,7 +3,6 @@
|
||||
|
||||
#include "debuggeritemmanager.h"
|
||||
|
||||
#include "debuggeritem.h"
|
||||
#include "debuggertr.h"
|
||||
|
||||
#include <coreplugin/dialogs/ioptionspage.h>
|
||||
@@ -26,7 +25,6 @@
|
||||
#include <utils/persistentsettings.h>
|
||||
#include <utils/qtcprocess.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/treemodel.h>
|
||||
#include <utils/winutils.h>
|
||||
|
||||
#include <nanotrace/nanotrace.h>
|
||||
@@ -102,50 +100,45 @@ private:
|
||||
// DebuggerTreeItem
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
class DebuggerTreeItem : public TreeItem
|
||||
QVariant DebuggerTreeItem::data(int column, int role) const
|
||||
{
|
||||
public:
|
||||
DebuggerTreeItem(const DebuggerItem &item, bool changed)
|
||||
: m_item(item), m_orig(item), m_added(changed), m_changed(changed)
|
||||
{}
|
||||
|
||||
QVariant data(int column, int role) const override
|
||||
{
|
||||
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();
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::FontRole: {
|
||||
QFont font;
|
||||
if (m_changed)
|
||||
font.setBold(true);
|
||||
if (m_removed)
|
||||
font.setStrikeOut(true);
|
||||
return font;
|
||||
}
|
||||
|
||||
case Qt::DecorationRole:
|
||||
if (column == 0)
|
||||
return m_item.decoration();
|
||||
break;
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
return m_item.validityMessage();
|
||||
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();
|
||||
}
|
||||
return QVariant();
|
||||
break;
|
||||
|
||||
case Qt::FontRole: {
|
||||
QFont font;
|
||||
if (m_changed)
|
||||
font.setBold(true);
|
||||
if (m_removed)
|
||||
font.setStrikeOut(true);
|
||||
return font;
|
||||
}
|
||||
|
||||
DebuggerItem m_item; // Displayed, possibly unapplied data.
|
||||
DebuggerItem m_orig; // Stored original data.
|
||||
bool m_added;
|
||||
bool m_changed;
|
||||
bool m_removed = false;
|
||||
};
|
||||
case Qt::DecorationRole:
|
||||
if (column == 0)
|
||||
return m_item.decoration();
|
||||
break;
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
return m_item.validityMessage();
|
||||
|
||||
case IdRole:
|
||||
return m_item.id();
|
||||
|
||||
case ProblemRole:
|
||||
return int(m_item.problem());
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// DebuggerItemModel
|
||||
|
@@ -5,15 +5,15 @@
|
||||
|
||||
#include "debugger_global.h"
|
||||
#include "debuggerconstants.h"
|
||||
#include "debuggeritem.h"
|
||||
|
||||
#include <utils/filepath.h>
|
||||
#include <utils/treemodel.h>
|
||||
|
||||
#include <QList>
|
||||
|
||||
namespace Debugger {
|
||||
|
||||
class DebuggerItem;
|
||||
|
||||
namespace DebuggerItemManager {
|
||||
|
||||
DEBUGGER_EXPORT void restoreDebuggers();
|
||||
@@ -34,4 +34,25 @@ DEBUGGER_EXPORT const DebuggerItem *findById(const QVariant &id);
|
||||
DEBUGGER_EXPORT const DebuggerItem *findByEngineType(DebuggerEngineType engineType);
|
||||
|
||||
} // DebuggerItemManager
|
||||
|
||||
namespace Internal {
|
||||
class DebuggerTreeItem : public Utils::TreeItem
|
||||
{
|
||||
public:
|
||||
DebuggerTreeItem(const DebuggerItem &item, bool changed)
|
||||
: m_item(item), m_orig(item), m_added(changed), m_changed(changed)
|
||||
{}
|
||||
|
||||
static const inline int IdRole = Qt::UserRole;
|
||||
static const inline int ProblemRole = Qt::UserRole + 1;
|
||||
QVariant data(int column, int role) const override;
|
||||
|
||||
DebuggerItem m_item; // Displayed, possibly unapplied data.
|
||||
DebuggerItem m_orig; // Stored original data.
|
||||
bool m_added;
|
||||
bool m_changed;
|
||||
bool m_removed = false;
|
||||
};
|
||||
|
||||
} // Internal
|
||||
} // Debugger
|
||||
|
@@ -22,7 +22,7 @@
|
||||
|
||||
#include <QComboBox>
|
||||
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
@@ -35,6 +35,98 @@ namespace Debugger {
|
||||
|
||||
namespace Internal {
|
||||
|
||||
class DebuggerItemListModel : public TreeModel<TreeItem, DebuggerTreeItem>
|
||||
{
|
||||
public:
|
||||
DebuggerItemListModel(const Kit &kit, QObject *parent)
|
||||
: TreeModel(parent)
|
||||
, m_kit(kit)
|
||||
{}
|
||||
|
||||
QModelIndex indexForId(const QVariant &id) const
|
||||
{
|
||||
// The "None" item always comes last
|
||||
const auto noneIndex = [this] { return index(rowCount() - 1, 0); };
|
||||
|
||||
if (id.isNull())
|
||||
return noneIndex();
|
||||
const TreeItem *const item = findItemAtLevel<1>(
|
||||
[id](TreeItem *item) { return item->data(0, DebuggerTreeItem::IdRole) == id; });
|
||||
return item ? indexForItem(item) : noneIndex();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
clear();
|
||||
|
||||
const IDeviceConstPtr device = BuildDeviceKitAspect::device(&m_kit);
|
||||
const Utils::FilePath rootPath = device->rootPath();
|
||||
const QList<DebuggerItem> debuggersForBuildDevice
|
||||
= Utils::filtered(DebuggerItemManager::debuggers(), [&](const DebuggerItem &item) {
|
||||
if (item.isGeneric())
|
||||
return device->id() != ProjectExplorer::Constants::DESKTOP_DEVICE_ID;
|
||||
return item.command().isSameDevice(rootPath);
|
||||
});
|
||||
for (const DebuggerItem &item : debuggersForBuildDevice)
|
||||
rootItem()->appendChild(new DebuggerTreeItem(item, false));
|
||||
DebuggerItem noneItem;
|
||||
noneItem.setUnexpandedDisplayName(Tr::tr("None"));
|
||||
rootItem()->appendChild(new DebuggerTreeItem(noneItem, false));
|
||||
}
|
||||
|
||||
private:
|
||||
const Kit &m_kit;
|
||||
};
|
||||
|
||||
class DebuggerItemSortModel : public SortModel
|
||||
{
|
||||
public:
|
||||
DebuggerItemSortModel(QObject *parent) : SortModel(parent) {}
|
||||
|
||||
QModelIndex indexForId(const QVariant &id) const
|
||||
{
|
||||
return mapFromSource(
|
||||
static_cast<DebuggerItemListModel *>(sourceModel())->indexForId(id));
|
||||
}
|
||||
|
||||
void reset() { static_cast<DebuggerItemListModel *>(sourceModel())->reset(); }
|
||||
|
||||
private:
|
||||
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override
|
||||
{
|
||||
const auto source = static_cast<DebuggerItemListModel *>(sourceModel());
|
||||
const auto item1 = static_cast<DebuggerTreeItem *>(source->itemForIndex(source_left));
|
||||
const auto item2 = static_cast<DebuggerTreeItem *>(source->itemForIndex(source_right));
|
||||
QTC_ASSERT(item1 && item2, return false);
|
||||
|
||||
// Criterion 1: "None" comes last
|
||||
if (!item1->data(0, DebuggerTreeItem::IdRole).isValid())
|
||||
return false;
|
||||
if (!item2->data(0, DebuggerTreeItem::IdRole).isValid())
|
||||
return true;
|
||||
|
||||
// Criterion 2: Invalid items come after valid ones with warnings, which come
|
||||
// after valid ones without warnings.
|
||||
if (const QVariant &p1 = item1->data(0, DebuggerTreeItem::ProblemRole),
|
||||
&p2 = item2->data(0, DebuggerTreeItem::ProblemRole);
|
||||
p1 != p2) {
|
||||
const auto problem1 = static_cast<DebuggerItem::Problem>(p1.toInt());
|
||||
const auto problem2 = static_cast<DebuggerItem::Problem>(p2.toInt());
|
||||
if (problem1 == DebuggerItem::Problem::None
|
||||
|| problem2 == DebuggerItem::Problem::NoEngine) {
|
||||
return true;
|
||||
}
|
||||
if (problem2 == DebuggerItem::Problem::None
|
||||
|| problem1 == DebuggerItem::Problem::NoEngine) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Criterion 3: Name.
|
||||
return SortModel::lessThan(source_left, source_right);
|
||||
}
|
||||
};
|
||||
|
||||
class DebuggerKitAspectImpl final : public KitAspect
|
||||
{
|
||||
public:
|
||||
@@ -46,16 +138,16 @@ public:
|
||||
m_comboBox = createSubWidget<QComboBox>();
|
||||
m_comboBox->setSizePolicy(QSizePolicy::Ignored, m_comboBox->sizePolicy().verticalPolicy());
|
||||
m_comboBox->setEnabled(true);
|
||||
const auto sortModel = new DebuggerItemSortModel(this);
|
||||
sortModel->setSourceModel(new DebuggerItemListModel(*workingCopy, this));
|
||||
m_comboBox->setModel(sortModel);
|
||||
|
||||
refresh();
|
||||
m_comboBox->setToolTip(factory->description());
|
||||
connect(m_comboBox, &QComboBox::currentIndexChanged, this, [this] {
|
||||
if (m_ignoreChanges.isLocked())
|
||||
return;
|
||||
|
||||
int currentIndex = m_comboBox->currentIndex();
|
||||
QVariant id = m_comboBox->itemData(currentIndex);
|
||||
m_kit->setValue(DebuggerKitAspect::id(), id);
|
||||
m_kit->setValue(DebuggerKitAspect::id(), currentId());
|
||||
});
|
||||
|
||||
}
|
||||
@@ -81,34 +173,16 @@ private:
|
||||
void refresh() override
|
||||
{
|
||||
const GuardLocker locker(m_ignoreChanges);
|
||||
m_comboBox->clear();
|
||||
m_comboBox->addItem(Tr::tr("None"), QString());
|
||||
|
||||
IDeviceConstPtr device = BuildDeviceKitAspect::device(kit());
|
||||
const Utils::FilePath path = device->rootPath();
|
||||
|
||||
const QList<DebuggerItem> debuggersForBuildDevice
|
||||
= Utils::filtered(DebuggerItemManager::debuggers(), [path](const DebuggerItem &item) {
|
||||
return item.command().isSameDevice(path);
|
||||
});
|
||||
for (const DebuggerItem &item : debuggersForBuildDevice)
|
||||
m_comboBox->addItem(item.displayName(), item.id());
|
||||
|
||||
const DebuggerItem *item = DebuggerKitAspect::debugger(m_kit);
|
||||
updateComboBox(item ? item->id() : QVariant());
|
||||
const auto sortModel = static_cast<DebuggerItemSortModel *>(m_comboBox->model());
|
||||
sortModel->reset();
|
||||
sortModel->sort(0);
|
||||
const DebuggerItem * const item = DebuggerKitAspect::debugger(m_kit);
|
||||
m_comboBox->setCurrentIndex(sortModel->indexForId(item ? item->id() : QVariant()).row());
|
||||
}
|
||||
|
||||
QVariant currentId() const { return m_comboBox->itemData(m_comboBox->currentIndex()); }
|
||||
|
||||
void updateComboBox(const QVariant &id)
|
||||
QVariant currentId() const
|
||||
{
|
||||
for (int i = 0; i < m_comboBox->count(); ++i) {
|
||||
if (id == m_comboBox->itemData(i)) {
|
||||
m_comboBox->setCurrentIndex(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_comboBox->setCurrentIndex(0);
|
||||
return m_comboBox->itemData(m_comboBox->currentIndex(), DebuggerTreeItem::IdRole);
|
||||
}
|
||||
|
||||
Guard m_ignoreChanges;
|
||||
|
Reference in New Issue
Block a user