diff options
| author | hjk <hjk@theqtcompany.com> | 2016-07-18 12:36:31 +0200 |
|---|---|---|
| committer | hjk <hjk@qt.io> | 2016-07-18 11:17:53 +0000 |
| commit | 2d79bdc29c242a04aad3519858ad64712be4de8e (patch) | |
| tree | a910e2daeaeca5ce943f33d569f2e88b8a477ad4 /src/plugins/debugger/moduleshandler.cpp | |
| parent | 84f1466b01e9098ae983c1f53e376e977921dad9 (diff) | |
| download | qt-creator-2d79bdc29c242a04aad3519858ad64712be4de8e.tar.gz | |
Debugger: Remove some uses of semi-global currentEngine()
Make use of recent TreeModel improvements in various
tool views, push more operations into the engine-
owned data models, specifically context menu creation.
Change-Id: I479c97102b9fb81611c6461c6df1cec59295179a
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Reviewed-by: hjk <hjk@qt.io>
Diffstat (limited to 'src/plugins/debugger/moduleshandler.cpp')
| -rw-r--r-- | src/plugins/debugger/moduleshandler.cpp | 226 |
1 files changed, 144 insertions, 82 deletions
diff --git a/src/plugins/debugger/moduleshandler.cpp b/src/plugins/debugger/moduleshandler.cpp index e90093f504..b388322ce3 100644 --- a/src/plugins/debugger/moduleshandler.cpp +++ b/src/plugins/debugger/moduleshandler.cpp @@ -25,30 +25,39 @@ #include "moduleshandler.h" +#include "debuggerconstants.h" +#include "debuggercore.h" +#include "debuggerengine.h" + +#include <utils/basetreeview.h> +#include <utils/hostosinfo.h> #include <utils/qtcassert.h> #include <utils/treemodel.h> #include <QCoreApplication> #include <QDebug> +#include <QMenu> #include <QSortFilterProxyModel> -using namespace Utils; +#include <functional> -////////////////////////////////////////////////////////////////// -// -// ModulesModel -// -////////////////////////////////////////////////////////////////// +using namespace Utils; namespace Debugger { namespace Internal { class ModuleItem : public TreeItem { + Q_DECLARE_TR_FUNCTIONS(Debuggger::Internal::ModulesHandler) + public: - QVariant data(int column, int role) const; + QVariant data(int column, int role) const override; + bool setData(int column, const QVariant &data, int role) override; + + bool contextMenuEvent(const ItemViewEvent &event); public: + DebuggerEngine *engine; Module module; bool updated; }; @@ -78,110 +87,158 @@ QVariant ModuleItem::data(int column, int role) const case 2: if (role == Qt::DisplayRole) switch (module.symbolsRead) { - case Module::UnknownReadState: return ModulesHandler::tr("Unknown"); - case Module::ReadFailed: return ModulesHandler::tr("No"); - case Module::ReadOk: return ModulesHandler::tr("Yes"); + case Module::UnknownReadState: return tr("Unknown"); + case Module::ReadFailed: return tr("No"); + case Module::ReadOk: return tr("Yes"); } break; case 3: if (role == Qt::DisplayRole) switch (module.elfData.symbolsType) { - case UnknownSymbols: - return ModulesHandler::tr("Unknown"); - case NoSymbols: - return ModulesHandler::tr("None"); - case PlainSymbols: - return ModulesHandler::tr("Plain"); - case FastSymbols: - return ModulesHandler::tr("Fast"); - case LinkedSymbols: - return ModulesHandler::tr("debuglnk"); - case BuildIdSymbols: - return ModulesHandler::tr("buildid"); + case UnknownSymbols: return tr("Unknown"); + case NoSymbols: return tr("None"); + case PlainSymbols: return tr("Plain"); + case FastSymbols: return tr("Fast"); + case LinkedSymbols: return tr("debuglnk"); + case BuildIdSymbols: return tr("buildid"); } else if (role == Qt::ToolTipRole) switch (module.elfData.symbolsType) { case UnknownSymbols: - return ModulesHandler::tr( - "It is unknown whether this module contains debug " - "information.\nUse \"Examine Symbols\" from the " - "context menu to initiate a check."); + return tr("It is unknown whether this module contains debug " + "information.\nUse \"Examine Symbols\" from the " + "context menu to initiate a check."); case NoSymbols: - return ModulesHandler::tr( - "This module neither contains nor references debug " - "information.\nStepping into the module or setting " - "breakpoints by file and line will not work."); + return tr("This module neither contains nor references debug " + "information.\nStepping into the module or setting " + "breakpoints by file and line will not work."); case PlainSymbols: - return ModulesHandler::tr( - "This module contains debug information.\nStepping " - "into the module or setting breakpoints by file and " - "line is expected to work."); + return tr("This module contains debug information.\nStepping " + "into the module or setting breakpoints by file and " + "line is expected to work."); case FastSymbols: - return ModulesHandler::tr( - "This module contains debug information.\nStepping " - "into the module or setting breakpoints by file and " - "line is expected to work."); + return tr("This module contains debug information.\nStepping " + "into the module or setting breakpoints by file and " + "line is expected to work."); case LinkedSymbols: case BuildIdSymbols: - return ModulesHandler::tr( - "This module does not contain debug information " - "itself, but contains a reference to external " - "debug information."); + return tr("This module does not contain debug information " + "itself, but contains a reference to external " + "debug information."); } break; case 4: if (role == Qt::DisplayRole) if (module.startAddress) - return QString(QLatin1String("0x") - + QString::number(module.startAddress, 16)); + return QString("0x" + QString::number(module.startAddress, 16)); break; case 5: if (role == Qt::DisplayRole) { if (module.endAddress) - return QString(QLatin1String("0x") - + QString::number(module.endAddress, 16)); + return QString("0x" + QString::number(module.endAddress, 16)); //: End address of loaded module - return ModulesHandler::tr("<unknown>", "address"); + return tr("<unknown>", "address"); } break; } return QVariant(); } +bool ModuleItem::setData(int, const QVariant &data, int role) +{ + if (role == BaseTreeView::ItemActivatedRole) { + engine->gotoLocation(module.modulePath); + return true; + } + + if (role == BaseTreeView::ItemViewEventRole) { + ItemViewEvent ev = data.value<ItemViewEvent>(); + if (ev.type() == QEvent::ContextMenu) + return contextMenuEvent(ev); + } + + return false; +} + +bool ModuleItem::contextMenuEvent(const ItemViewEvent &event) +{ + auto menu = new QMenu; + + const bool enabled = engine->debuggerActionsEnabled(); + const bool canReload = engine->hasCapability(ReloadModuleCapability); + const bool canLoadSymbols = engine->hasCapability(ReloadModuleSymbolsCapability); + const bool canShowSymbols = engine->hasCapability(ShowModuleSymbolsCapability); + const bool moduleNameValid = !module.moduleName.isEmpty(); + + addAction(menu, tr("Update Module List"), + enabled && canReload, + [this] { engine->reloadModules(); }); + + addAction(menu, tr("Show Source Files for Module \"%1\"").arg(module.moduleName), + enabled && canReload, + [this] { engine->loadSymbols(module.modulePath); }); + + // FIXME: Dependencies only available on Windows, when "depends" is installed. + addAction(menu, tr("Show Dependencies of \"%1\"").arg(module.moduleName), + tr("Show Dependencies"), + moduleNameValid && !module.modulePath.isEmpty() && HostOsInfo::isWindowsHost(), + [this] { QProcess::startDetached("depends", QStringList(module.modulePath)); }); + + addAction(menu, tr("Load Symbols for All Modules"), + enabled && canLoadSymbols, + [this] { engine->loadAllSymbols(); }); + + addAction(menu, tr("Examine All Modules"), + enabled && canLoadSymbols, + [this] { engine->examineModules(); }); + + addAction(menu, tr("Load Symbols for Module \"%1\"").arg(module.moduleName), + tr("Load Symbols for Module"), + canLoadSymbols, + [this] { engine->loadSymbols(module.modulePath); }); + + addAction(menu, tr("Edit File \"%1\"").arg(module.moduleName), + tr("Edit File"), + moduleNameValid, + [this] { engine->gotoLocation(module.modulePath); }); + + addAction(menu, tr("Show Symbols in File \"%1\"").arg(module.moduleName), + tr("Show Symbols"), + canShowSymbols && moduleNameValid, + [this] { engine->requestModuleSymbols(module.modulePath); }); + + addAction(menu, tr("Show Sections in File \"%1\"").arg(module.moduleName), + tr("Show Sections"), + canShowSymbols && moduleNameValid, + [this] { engine->requestModuleSections(module.modulePath); }); + + menu->popup(event.globalPos()); + return true; +} + ////////////////////////////////////////////////////////////////// // // ModulesHandler // ////////////////////////////////////////////////////////////////// -static ModuleItem *moduleFromPath(TreeItem *root, const QString &modulePath) -{ - // Recent modules are more likely to be unloaded first. - for (int i = root->childCount(); --i >= 0; ) { - auto item = static_cast<ModuleItem *>(root->childAt(i)); - if (item->module.modulePath == modulePath) - return item; - } - return 0; -} - ModulesHandler::ModulesHandler(DebuggerEngine *engine) { m_engine = engine; - QString pad = QLatin1String(" "); - m_model = new TreeModel(this); - m_model->setObjectName(QLatin1String("ModulesModel")); - m_model->setHeader(QStringList() - << ModulesHandler::tr("Module Name") + pad - << ModulesHandler::tr("Module Path") + pad - << ModulesHandler::tr("Symbols Read") + pad - << ModulesHandler::tr("Symbols Type") + pad - << ModulesHandler::tr("Start Address") + pad - << ModulesHandler::tr("End Address") + pad); + QString pad = " "; + m_model = new ModulesModel; + m_model->setObjectName("ModulesModel"); + m_model->setHeader(QStringList({ + tr("Module Name") + pad, + tr("Module Path") + pad, + tr("Symbols Read") + pad, + tr("Symbols Type") + pad, + tr("Start Address") + pad, + tr("End Address") + pad})); m_proxyModel = new QSortFilterProxyModel(this); - m_proxyModel->setObjectName(QLatin1String("ModulesProxyModel")); + m_proxyModel->setObjectName("ModulesProxyModel"); m_proxyModel->setSourceModel(m_model); } @@ -190,6 +247,14 @@ QAbstractItemModel *ModulesHandler::model() const return m_proxyModel; } +ModuleItem *ModulesHandler::moduleFromPath(const QString &modulePath) const +{ + // Recent modules are more likely to be unloaded first. + return m_model->findFirstLevelItem([modulePath](ModuleItem *item) { + return item->module.modulePath == modulePath; + }); +} + void ModulesHandler::removeAll() { m_model->clear(); @@ -198,15 +263,13 @@ void ModulesHandler::removeAll() Modules ModulesHandler::modules() const { Modules mods; - TreeItem *root = m_model->rootItem(); - for (int i = root->childCount(); --i >= 0; ) - mods.append(static_cast<ModuleItem *>(root->childAt(i))->module); + m_model->forFirstLevelItems([&mods](ModuleItem *item) { mods.append(item->module); }); return mods; } void ModulesHandler::removeModule(const QString &modulePath) { - if (ModuleItem *item = moduleFromPath(m_model->rootItem(), modulePath)) + if (ModuleItem *item = moduleFromPath(modulePath)) m_model->destroyItem(item); } @@ -216,12 +279,13 @@ void ModulesHandler::updateModule(const Module &module) if (path.isEmpty()) return; - ModuleItem *item = moduleFromPath(m_model->rootItem(), path); + ModuleItem *item = moduleFromPath(path); if (item) { item->module = module; } else { item = new ModuleItem; item->module = module; + item->engine = m_engine; m_model->rootItem()->appendChild(item); } @@ -238,19 +302,17 @@ void ModulesHandler::updateModule(const Module &module) void ModulesHandler::beginUpdateAll() { - TreeItem *root = m_model->rootItem(); - for (int i = root->childCount(); --i >= 0; ) - static_cast<ModuleItem *>(root->childAt(i))->updated = false; + m_model->forFirstLevelItems([](ModuleItem *item) { item->updated = false; }); } void ModulesHandler::endUpdateAll() { - TreeItem *root = m_model->rootItem(); - for (int i = root->childCount(); --i >= 0; ) { - auto item = static_cast<ModuleItem *>(root->childAt(i)); + QList<TreeItem *> toDestroy; + m_model->forFirstLevelItems([&toDestroy](ModuleItem *item) { if (!item->updated) - m_model->destroyItem(item); - } + toDestroy.append(item); + }); + qDeleteAll(toDestroy); } } // namespace Internal |
