diff options
Diffstat (limited to 'src/plugins/debugger/snapshothandler.cpp')
-rw-r--r-- | src/plugins/debugger/snapshothandler.cpp | 358 |
1 files changed, 247 insertions, 111 deletions
diff --git a/src/plugins/debugger/snapshothandler.cpp b/src/plugins/debugger/snapshothandler.cpp index 21dcaf9d1e..619a3f5fdd 100644 --- a/src/plugins/debugger/snapshothandler.cpp +++ b/src/plugins/debugger/snapshothandler.cpp @@ -25,15 +25,28 @@ #include "snapshothandler.h" +#include "analyzer/analyzermanager.h" +#include "debuggeractions.h" #include "debuggerinternalconstants.h" #include "debuggericons.h" #include "debuggercore.h" #include "debuggerruncontrol.h" +#include "stackhandler.h" +#include <coreplugin/icontext.h> +#include <coreplugin/icore.h> +#include <coreplugin/modemanager.h> + +#include <utils/basetreeview.h> +#include <utils/treemodel.h> #include <utils/qtcassert.h> #include <QDebug> -#include <QFile> +#include <QMenu> +#include <QTimer> + +using namespace Core; +using namespace Utils; namespace Debugger { namespace Internal { @@ -102,177 +115,300 @@ QDebug operator<<(QDebug d, const SnapshotData &f) } #endif +class EngineItem : public QObject, public TreeItem +{ +public: + QVariant data(int column, int role) const final; + bool setData(int row, const QVariant &data, int role) final; + + const bool m_isPreset = false; + QPointer<DebuggerEngine> m_engine; +}; + +class EngineManagerPrivate : public QObject +{ +public: + EngineManagerPrivate() + { + m_engineModel.setHeader({EngineManager::tr("Name"), EngineManager::tr("File")}); + m_engineModel.rootItem()->appendChild(new EngineItem); // The preset case. + + m_engineChooser = new QComboBox; + m_engineChooser->setVisible(false); + m_engineChooser->setModel(&m_engineModel); + connect(m_engineChooser, static_cast<void(QComboBox::*)(int)>(&QComboBox::activated), + this, &EngineManagerPrivate::activateEngineByIndex); + } + + ~EngineManagerPrivate() + { + delete m_engineChooser; + } + + EngineItem *findEngineItem(DebuggerEngine *engine); + void activateEngine(DebuggerEngine *engine); + void activateEngineItem(EngineItem *engineItem); + void activateEngineByIndex(int index); + void selectUiForCurrentEngine(); + void updateEngineChooserVisibility(); + + TreeModel<TypedTreeItem<EngineItem>, EngineItem> m_engineModel; + QPointer<EngineItem> m_currentItem; + Core::Id m_previousMode; + QPointer<QComboBox> m_engineChooser; +}; + //////////////////////////////////////////////////////////////////////// // -// SnapshotHandler +// EngineManager // //////////////////////////////////////////////////////////////////////// /*! - \class Debugger::Internal::SnapshotHandler - \brief The SnapshotHandler class provides a model to represent the - snapshots in a QTreeView. - - A snapshot represents a debugging session. + \class Debugger::Internal::EngineManager + \brief The EngineManager manages running debugger engines. */ -SnapshotHandler::SnapshotHandler() = default; +static EngineManager *theEngineManager = nullptr; +static EngineManagerPrivate *d = nullptr; -SnapshotHandler::~SnapshotHandler() +EngineManager::EngineManager() { - for (int i = m_snapshots.size(); --i >= 0; ) { - if (DebuggerRunTool *runTool = at(i)) { - const DebuggerRunParameters &rp = runTool->runParameters(); - if (rp.isSnapshot && !rp.coreFile.isEmpty()) - QFile::remove(rp.coreFile); - } - } + theEngineManager = this; + d = new EngineManagerPrivate; } -int SnapshotHandler::rowCount(const QModelIndex &parent) const +QWidget *EngineManager::engineChooser() { - // Since the stack is not a tree, row count is 0 for any valid parent - return parent.isValid() ? 0 : m_snapshots.size(); + return d->m_engineChooser; } -int SnapshotHandler::columnCount(const QModelIndex &parent) const +EngineManager::~EngineManager() { - return parent.isValid() ? 0 : 2; + theEngineManager = nullptr; + delete d; } -QVariant SnapshotHandler::data(const QModelIndex &index, int role) const +EngineManager *EngineManager::instance() { - if (!index.isValid() || index.row() >= m_snapshots.size()) - return QVariant(); + return theEngineManager; +} - const DebuggerRunTool *runTool = at(index.row()); +QAbstractItemModel *EngineManager::model() +{ + return &d->m_engineModel; +} - if (role == SnapshotCapabilityRole) - return runTool && runTool->activeEngine()->hasCapability(SnapshotCapability); +void EngineManager::activateEngine(DebuggerEngine *engine) +{ + d->activateEngine(engine); +} - if (!runTool) - return QLatin1String("<finished>"); +QVariant EngineItem::data(int column, int role) const +{ + if (m_engine) { + if (role == SnapshotCapabilityRole) + return m_engine->hasCapability(SnapshotCapability); + + const DebuggerRunParameters &rp = m_engine->runParameters(); + + switch (role) { + case Qt::DisplayRole: + switch (column) { + case 0: + return m_engine->displayName(); + case 1: + return rp.coreFile.isEmpty() ? rp.inferior.executable : rp.coreFile; + } + return QVariant(); + + case Qt::ToolTipRole: + return QVariant(); + + case Qt::DecorationRole: + // Return icon that indicates whether this is the active engine + if (column == 0) + return d->m_currentItem == this ? Icons::LOCATION.icon() : Icons::EMPTY.icon(); + + default: + break; + } + } else { + switch (role) { + case Qt::DisplayRole: + return EngineManager::tr("Debugger Preset"); + default: + break; + } + } + return QVariant(); +} - const DebuggerRunParameters &rp = runTool->runParameters(); +bool EngineItem::setData(int row, const QVariant &value, int role) +{ + Q_UNUSED(row); + if (!m_engine) + return false; + + if (role == BaseTreeView::ItemActivatedRole) { + EngineItem *engineItem = d->findEngineItem(m_engine); + d->activateEngineItem(engineItem); + return true; + } - switch (role) { - case Qt::DisplayRole: - switch (index.column()) { - case 0: - return rp.displayName; - case 1: - return rp.coreFile.isEmpty() ? rp.inferior.executable : rp.coreFile; - } - return QVariant(); + if (role == BaseTreeView::ItemViewEventRole) { + ItemViewEvent ev = value.value<ItemViewEvent>(); + + if (auto cmev = ev.as<QContextMenuEvent>()) { - case Qt::ToolTipRole: - return QVariant(); + auto menu = new QMenu(ev.view()); - case Qt::DecorationRole: - // Return icon that indicates whether this is the active stack frame. - if (index.column() == 0) - return (index.row() == m_currentIndex) ? Icons::LOCATION.icon() : Icons::EMPTY.icon(); + QAction *actCreate = menu->addAction(tr("Create Snapshot")); + actCreate->setEnabled(m_engine->hasCapability(SnapshotCapabilityRole)); + menu->addSeparator(); - default: - break; + QAction *actRemove = menu->addAction(tr("Abort Debugger")); + actRemove->setEnabled(true); + + QAction *act = menu->exec(cmev->globalPos()); + + if (act == actCreate && m_engine) + m_engine->createSnapshot(); + else if (act == actRemove && m_engine) + m_engine->quitDebugger(); + + return true; + } + + if (auto kev = ev.as<QKeyEvent>(QEvent::KeyPress)) { + if (kev->key() == Qt::Key_Delete && m_engine) { + m_engine->quitDebugger(); + } else if (kev->key() == Qt::Key_Return || kev->key() == Qt::Key_Enter) { + d->activateEngineByIndex(row); + } + return true; + } } - return QVariant(); + + return false; } -QVariant SnapshotHandler::headerData(int section, Qt::Orientation orientation, int role) const +void EngineManagerPrivate::activateEngineByIndex(int index) { - if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { - switch (section) { - case 0: return tr("Name"); - case 1: return tr("File"); - }; + activateEngineItem(m_engineModel.rootItem()->childAt(index)); +} + +void EngineManagerPrivate::activateEngineItem(EngineItem *engineItem) +{ + if (m_currentItem) { + if (DebuggerEngine *engine = m_currentItem->m_engine) { + const Context context = engine->languageContext(); + ICore::removeAdditionalContext(context); + } } - return QVariant(); + + m_currentItem = engineItem; + + if (m_currentItem) { + if (DebuggerEngine *engine = m_currentItem->m_engine) { + const Context context = engine->languageContext(); + ICore::addAdditionalContext(context); + engine->gotoCurrentLocation(); + } + } + + selectUiForCurrentEngine(); } -Qt::ItemFlags SnapshotHandler::flags(const QModelIndex &index) const +void EngineManagerPrivate::selectUiForCurrentEngine() { - if (index.row() >= m_snapshots.size()) - return nullptr; - if (index.row() == m_snapshots.size()) - return QAbstractTableModel::flags(index); - return true ? QAbstractTableModel::flags(index) : Qt::ItemFlags({}); + Perspective *perspective = nullptr; + int row = 0; + + if (m_currentItem && m_currentItem->m_engine) { + perspective = m_currentItem->m_engine->perspective(); + row = m_engineModel.rootItem()->indexOf(m_currentItem); + } + + m_engineChooser->setCurrentIndex(row); + + if (perspective) + perspective->select(); + else + selectPerspective(Debugger::Constants::PRESET_PERSPRECTIVE_ID); + + m_engineModel.rootItem()->forFirstLevelChildren([this](EngineItem *engineItem) { + if (engineItem && engineItem->m_engine) + engineItem->m_engine->updateMarkers(); + }); + + emit theEngineManager->currentEngineChanged(); } -void SnapshotHandler::activateSnapshot(int index) +void EngineManager::selectUiForCurrentEngine() { - beginResetModel(); - m_currentIndex = index; - //qDebug() << "ACTIVATING INDEX: " << m_currentIndex << " OF " << size(); - Internal::displayDebugger(at(index)); - endResetModel(); + d->selectUiForCurrentEngine(); } -void SnapshotHandler::createSnapshot(int index) +EngineItem *EngineManagerPrivate::findEngineItem(DebuggerEngine *engine) { - DebuggerRunTool *runTool = at(index); - QTC_ASSERT(runTool, return); - runTool->engine()->createSnapshot(); + return m_engineModel.rootItem()->findFirstLevelChild([engine](EngineItem *engineItem) { + return engineItem->m_engine == engine; + }); } -void SnapshotHandler::removeSnapshot(int index) +void EngineManagerPrivate::activateEngine(DebuggerEngine *engine) { - DebuggerRunTool *runTool = at(index); - //qDebug() << "REMOVING " << runTool; - QTC_ASSERT(runTool, return); -#if 0 - // See http://sourceware.org/bugzilla/show_bug.cgi?id=11241. - setState(EngineSetupRequested); - postCommand("set stack-cache off"); -#endif - //QString fileName = runTool->startParameters().coreFile; - //if (!fileName.isEmpty()) - // QFile::remove(fileName); - beginResetModel(); - m_snapshots.removeAt(index); - if (index == m_currentIndex) - m_currentIndex = -1; - else if (index < m_currentIndex) - --m_currentIndex; - //runTool->quitDebugger(); - endResetModel(); + EngineItem *engineItem = findEngineItem(engine); + activateEngineItem(engineItem); } +void EngineManagerPrivate::updateEngineChooserVisibility() +{ + // Show it if there's more than one option (i.e. not the the preset engine only) + const int count = m_engineModel.rootItem()->childCount(); + m_engineChooser->setVisible(count >= 2); +} -void SnapshotHandler::removeAll() +void EngineManager::registerEngine(DebuggerEngine *engine) { - beginResetModel(); - m_snapshots.clear(); - m_currentIndex = -1; - endResetModel(); + auto engineItem = new EngineItem; + engineItem->m_engine = engine; + d->m_engineModel.rootItem()->appendChild(engineItem); + d->updateEngineChooserVisibility(); } -void SnapshotHandler::appendSnapshot(DebuggerRunTool *runTool) +void EngineManager::activateDebugMode() { - beginResetModel(); - m_snapshots.append(runTool); - m_currentIndex = size() - 1; - endResetModel(); + if (ModeManager::currentModeId() != Constants::MODE_DEBUG) { + d->m_previousMode = ModeManager::currentModeId(); + ModeManager::activateMode(Constants::MODE_DEBUG); + } } -void SnapshotHandler::removeSnapshot(DebuggerRunTool *runTool) +void EngineManager::unregisterEngine(DebuggerEngine *engine) { // Could be that the run controls died before it was appended. - int index = m_snapshots.indexOf(runTool); - if (index != -1) - removeSnapshot(index); + if (auto engineItem = d->findEngineItem(engine)) + d->m_engineModel.destroyItem(engineItem); + + d->updateEngineChooserVisibility(); + emit theEngineManager->currentEngineChanged(); } -void SnapshotHandler::setCurrentIndex(int index) +QList<QPointer<DebuggerEngine>> EngineManager::engines() { - beginResetModel(); - m_currentIndex = index; - endResetModel(); + QList<QPointer<DebuggerEngine>> result; + d->m_engineModel.forItemsAtLevel<1>([&result](EngineItem *engineItem) { + if (DebuggerEngine *engine = engineItem->m_engine) + result.append(engine); + }); + return result; } -DebuggerRunTool *SnapshotHandler::at(int i) const +QPointer<DebuggerEngine> EngineManager::currentEngine() { - return m_snapshots.at(i).data(); + return d->m_currentItem ? d->m_currentItem->m_engine : nullptr; } } // namespace Internal |