forked from qt-creator/qt-creator
Debugger: Use TreeModel for ModulesHandler
Change-Id: I831f71e7441330e2a6a7f3ddcf89a29517b3b91b Reviewed-by: hjk <hjk@theqtcompany.com>
This commit is contained in:
@@ -1858,8 +1858,8 @@ void CdbEngine::handleModules(const CdbExtensionCommandPtr &reply)
|
|||||||
GdbMi value;
|
GdbMi value;
|
||||||
value.fromString(reply->reply);
|
value.fromString(reply->reply);
|
||||||
if (value.type() == GdbMi::List) {
|
if (value.type() == GdbMi::List) {
|
||||||
Modules modules;
|
ModulesHandler *handler = modulesHandler();
|
||||||
modules.reserve(value.childCount());
|
handler->beginUpdateAll();
|
||||||
foreach (const GdbMi &gdbmiModule, value.children()) {
|
foreach (const GdbMi &gdbmiModule, value.children()) {
|
||||||
Module module;
|
Module module;
|
||||||
module.moduleName = QString::fromLatin1(gdbmiModule["name"].data());
|
module.moduleName = QString::fromLatin1(gdbmiModule["name"].data());
|
||||||
@@ -1868,9 +1868,9 @@ void CdbEngine::handleModules(const CdbExtensionCommandPtr &reply)
|
|||||||
module.endAddress = gdbmiModule["end"].data().toULongLong(0, 0);
|
module.endAddress = gdbmiModule["end"].data().toULongLong(0, 0);
|
||||||
if (gdbmiModule["deferred"].type() == GdbMi::Invalid)
|
if (gdbmiModule["deferred"].type() == GdbMi::Invalid)
|
||||||
module.symbolsRead = Module::ReadOk;
|
module.symbolsRead = Module::ReadOk;
|
||||||
modules.push_back(module);
|
handler->updateModule(module);
|
||||||
}
|
}
|
||||||
modulesHandler()->setModules(modules);
|
handler->endUpdateAll();
|
||||||
} else {
|
} else {
|
||||||
showMessage(QString::fromLatin1("Parse error in modules response."), LogError);
|
showMessage(QString::fromLatin1("Parse error in modules response."), LogError);
|
||||||
qWarning("Parse error in modules response:\n%s", reply->reply.constData());
|
qWarning("Parse error in modules response:\n%s", reply->reply.constData());
|
||||||
|
@@ -771,7 +771,8 @@ void LldbEngine::reloadModules()
|
|||||||
|
|
||||||
void LldbEngine::refreshModules(const GdbMi &modules)
|
void LldbEngine::refreshModules(const GdbMi &modules)
|
||||||
{
|
{
|
||||||
Modules mods;
|
ModulesHandler *handler = modulesHandler();
|
||||||
|
handler->beginUpdateAll();
|
||||||
foreach (const GdbMi &item, modules.children()) {
|
foreach (const GdbMi &item, modules.children()) {
|
||||||
Module module;
|
Module module;
|
||||||
module.modulePath = item["file"].toUtf8();
|
module.modulePath = item["file"].toUtf8();
|
||||||
@@ -779,9 +780,9 @@ void LldbEngine::refreshModules(const GdbMi &modules)
|
|||||||
module.symbolsRead = Module::UnknownReadState;
|
module.symbolsRead = Module::UnknownReadState;
|
||||||
module.startAddress = item["loaded_addr"].toAddress();
|
module.startAddress = item["loaded_addr"].toAddress();
|
||||||
module.endAddress = 0; // FIXME: End address not easily available.
|
module.endAddress = 0; // FIXME: End address not easily available.
|
||||||
mods.append(module);
|
handler->updateModule(module);
|
||||||
}
|
}
|
||||||
modulesHandler()->setModules(mods);
|
handler->endUpdateAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LldbEngine::requestModuleSymbols(const QString &moduleName)
|
void LldbEngine::requestModuleSymbols(const QString &moduleName)
|
||||||
|
@@ -31,7 +31,9 @@
|
|||||||
#include "moduleshandler.h"
|
#include "moduleshandler.h"
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/treemodel.h>
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
@@ -46,60 +48,19 @@ using namespace Utils;
|
|||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class ModulesModel : public QAbstractItemModel
|
class ModuleItem : public TreeItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ModulesModel(QObject *parent)
|
QVariant data(int column, int role) const;
|
||||||
: QAbstractItemModel(parent)
|
|
||||||
{}
|
|
||||||
|
|
||||||
int columnCount(const QModelIndex &parent) const
|
public:
|
||||||
{ return parent.isValid() ? 0 : 5; }
|
Module module;
|
||||||
int rowCount(const QModelIndex &parent) const
|
bool updated;
|
||||||
{ return parent.isValid() ? 0 : m_modules.size(); }
|
|
||||||
QModelIndex parent(const QModelIndex &) const { return QModelIndex(); }
|
|
||||||
QModelIndex index(int row, int column, const QModelIndex &) const
|
|
||||||
{ return createIndex(row, column); }
|
|
||||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
|
||||||
QVariant data(const QModelIndex &index, int role) const;
|
|
||||||
|
|
||||||
void clearModel();
|
|
||||||
void removeModule(const QString &modulePath);
|
|
||||||
void setModules(const Modules &modules);
|
|
||||||
void updateModule(const Module &module);
|
|
||||||
|
|
||||||
int indexOfModule(const QString &modulePath) const;
|
|
||||||
|
|
||||||
Modules m_modules;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QVariant ModuleItem::data(int column, int role) const
|
||||||
QVariant ModulesModel::headerData(int section,
|
|
||||||
Qt::Orientation orientation, int role) const
|
|
||||||
{
|
{
|
||||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
switch (column) {
|
||||||
static QString headers[] = {
|
|
||||||
ModulesHandler::tr("Module Name") + QLatin1String(" "),
|
|
||||||
ModulesHandler::tr("Module Path") + QLatin1String(" "),
|
|
||||||
ModulesHandler::tr("Symbols Read") + QLatin1String(" "),
|
|
||||||
ModulesHandler::tr("Symbols Type") + QLatin1String(" "),
|
|
||||||
ModulesHandler::tr("Start Address") + QLatin1String(" "),
|
|
||||||
ModulesHandler::tr("End Address") + QLatin1String(" ")
|
|
||||||
};
|
|
||||||
return headers[section];
|
|
||||||
}
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant ModulesModel::data(const QModelIndex &index, int role) const
|
|
||||||
{
|
|
||||||
int row = index.row();
|
|
||||||
if (row < 0 || row >= m_modules.size())
|
|
||||||
return QVariant();
|
|
||||||
|
|
||||||
const Module &module = m_modules.at(row);
|
|
||||||
|
|
||||||
switch (index.column()) {
|
|
||||||
case 0:
|
case 0:
|
||||||
if (role == Qt::DisplayRole)
|
if (role == Qt::DisplayRole)
|
||||||
return module.moduleName;
|
return module.moduleName;
|
||||||
@@ -192,78 +153,39 @@ QVariant ModulesModel::data(const QModelIndex &index, int role) const
|
|||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModulesModel::setModules(const Modules &m)
|
|
||||||
{
|
|
||||||
beginResetModel();
|
|
||||||
m_modules = m;
|
|
||||||
endResetModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModulesModel::clearModel()
|
|
||||||
{
|
|
||||||
if (!m_modules.isEmpty()) {
|
|
||||||
beginResetModel();
|
|
||||||
m_modules.clear();
|
|
||||||
endResetModel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int ModulesModel::indexOfModule(const QString &modulePath) const
|
|
||||||
{
|
|
||||||
// Recent modules are more likely to be unloaded first.
|
|
||||||
for (int i = m_modules.size() - 1; i >= 0; i--)
|
|
||||||
if (m_modules.at(i).modulePath == modulePath)
|
|
||||||
return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModulesModel::removeModule(const QString &modulePath)
|
|
||||||
{
|
|
||||||
const int row = indexOfModule(modulePath);
|
|
||||||
QTC_ASSERT(row != -1, return);
|
|
||||||
beginRemoveRows(QModelIndex(), row, row);
|
|
||||||
m_modules.remove(row);
|
|
||||||
endRemoveRows();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModulesModel::updateModule(const Module &module)
|
|
||||||
{
|
|
||||||
const int row = indexOfModule(module.modulePath);
|
|
||||||
const QString path = module.modulePath;
|
|
||||||
if (path.isEmpty())
|
|
||||||
return;
|
|
||||||
try { // MinGW occasionallly throws std::bad_alloc.
|
|
||||||
ElfReader reader(path);
|
|
||||||
ElfData elfData = reader.readHeaders();
|
|
||||||
|
|
||||||
if (row == -1) {
|
|
||||||
const int n = m_modules.size();
|
|
||||||
beginInsertRows(QModelIndex(), n, n);
|
|
||||||
m_modules.push_back(module);
|
|
||||||
m_modules.back().elfData = elfData;
|
|
||||||
endInsertRows();
|
|
||||||
} else {
|
|
||||||
m_modules[row] = module;
|
|
||||||
m_modules[row].elfData = elfData;
|
|
||||||
dataChanged(index(row, 0, QModelIndex()), index(row, 4, QModelIndex()));
|
|
||||||
}
|
|
||||||
} catch(...) {
|
|
||||||
qWarning("%s: An exception occurred while reading module '%s'",
|
|
||||||
Q_FUNC_INFO, qPrintable(module.modulePath));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// ModulesHandler
|
// ModulesHandler
|
||||||
//
|
//
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static ModuleItem *moduleFromPath(TreeItem *root, const QString &modulePath)
|
||||||
|
{
|
||||||
|
// Recent modules are more likely to be unloaded first.
|
||||||
|
for (int i = root->rowCount(); --i >= 0; ) {
|
||||||
|
auto item = static_cast<ModuleItem *>(root->child(i));
|
||||||
|
if (item->module.modulePath == modulePath)
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
ModulesHandler::ModulesHandler(DebuggerEngine *engine)
|
ModulesHandler::ModulesHandler(DebuggerEngine *engine)
|
||||||
{
|
{
|
||||||
m_engine = engine;
|
m_engine = engine;
|
||||||
m_model = new ModulesModel(this);
|
|
||||||
|
QString pad = QLatin1String(" ");
|
||||||
|
m_model = new TreeModel(this);
|
||||||
m_model->setObjectName(QLatin1String("ModulesModel"));
|
m_model->setObjectName(QLatin1String("ModulesModel"));
|
||||||
|
auto root = new TreeItem(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);
|
||||||
|
m_model->setRootItem(root);
|
||||||
|
|
||||||
m_proxyModel = new QSortFilterProxyModel(this);
|
m_proxyModel = new QSortFilterProxyModel(this);
|
||||||
m_proxyModel->setObjectName(QLatin1String("ModulesProxyModel"));
|
m_proxyModel->setObjectName(QLatin1String("ModulesProxyModel"));
|
||||||
m_proxyModel->setSourceModel(m_model);
|
m_proxyModel->setSourceModel(m_model);
|
||||||
@@ -276,27 +198,65 @@ QAbstractItemModel *ModulesHandler::model() const
|
|||||||
|
|
||||||
void ModulesHandler::removeAll()
|
void ModulesHandler::removeAll()
|
||||||
{
|
{
|
||||||
m_model->clearModel();
|
m_model->removeAllSubItems(m_model->rootItem());
|
||||||
}
|
|
||||||
|
|
||||||
void ModulesHandler::removeModule(const QString &modulePath)
|
|
||||||
{
|
|
||||||
m_model->removeModule(modulePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModulesHandler::updateModule(const Module &module)
|
|
||||||
{
|
|
||||||
m_model->updateModule(module);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModulesHandler::setModules(const Modules &modules)
|
|
||||||
{
|
|
||||||
m_model->setModules(modules);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Modules ModulesHandler::modules() const
|
Modules ModulesHandler::modules() const
|
||||||
{
|
{
|
||||||
return m_model->m_modules;
|
Modules mods;
|
||||||
|
TreeItem *root = m_model->rootItem();
|
||||||
|
for (int i = root->rowCount(); --i >= 0; )
|
||||||
|
mods.append(static_cast<ModuleItem *>(root->child(i))->module);
|
||||||
|
return mods;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModulesHandler::removeModule(const QString &modulePath)
|
||||||
|
{
|
||||||
|
if (ModuleItem *item = moduleFromPath(m_model->rootItem(), modulePath))
|
||||||
|
m_model->removeItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModulesHandler::updateModule(const Module &module)
|
||||||
|
{
|
||||||
|
const QString path = module.modulePath;
|
||||||
|
if (path.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ModuleItem *item = moduleFromPath(m_model->rootItem(), path);
|
||||||
|
if (item) {
|
||||||
|
item->module = module;
|
||||||
|
} else {
|
||||||
|
item = new ModuleItem;
|
||||||
|
item->module = module;
|
||||||
|
m_model->appendItem(m_model->rootItem(), item);
|
||||||
|
}
|
||||||
|
|
||||||
|
try { // MinGW occasionallly throws std::bad_alloc.
|
||||||
|
ElfReader reader(path);
|
||||||
|
item->module.elfData = reader.readHeaders();
|
||||||
|
m_model->updateItem(item);
|
||||||
|
} catch(...) {
|
||||||
|
qWarning("%s: An exception occurred while reading module '%s'",
|
||||||
|
Q_FUNC_INFO, qPrintable(module.modulePath));
|
||||||
|
}
|
||||||
|
item->updated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModulesHandler::beginUpdateAll()
|
||||||
|
{
|
||||||
|
TreeItem *root = m_model->rootItem();
|
||||||
|
for (int i = root->rowCount(); --i >= 0; )
|
||||||
|
static_cast<ModuleItem *>(root->child(i))->updated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModulesHandler::endUpdateAll()
|
||||||
|
{
|
||||||
|
TreeItem *root = m_model->rootItem();
|
||||||
|
for (int i = root->rowCount(); --i >= 0; ) {
|
||||||
|
auto item = static_cast<ModuleItem *>(root->child(i));
|
||||||
|
if (!item->updated)
|
||||||
|
m_model->removeItem(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -32,6 +32,7 @@
|
|||||||
#define DEBUGGER_MODULESHANDLER_H
|
#define DEBUGGER_MODULESHANDLER_H
|
||||||
|
|
||||||
#include <utils/elfreader.h>
|
#include <utils/elfreader.h>
|
||||||
|
#include <utils/treemodel.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QAbstractItemModel;
|
class QAbstractItemModel;
|
||||||
@@ -42,7 +43,6 @@ namespace Debugger {
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class DebuggerEngine;
|
class DebuggerEngine;
|
||||||
class ModulesModel;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
@@ -109,7 +109,6 @@ public:
|
|||||||
|
|
||||||
typedef QVector<Module> Modules;
|
typedef QVector<Module> Modules;
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// ModulesHandler
|
// ModulesHandler
|
||||||
@@ -125,16 +124,18 @@ public:
|
|||||||
|
|
||||||
QAbstractItemModel *model() const;
|
QAbstractItemModel *model() const;
|
||||||
|
|
||||||
void setModules(const Modules &modules);
|
|
||||||
void removeModule(const QString &modulePath);
|
void removeModule(const QString &modulePath);
|
||||||
void updateModule(const Module &module);
|
void updateModule(const Module &module);
|
||||||
|
|
||||||
Modules modules() const;
|
void beginUpdateAll();
|
||||||
|
void endUpdateAll();
|
||||||
|
|
||||||
void removeAll();
|
void removeAll();
|
||||||
|
Modules modules() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DebuggerEngine *m_engine;
|
DebuggerEngine *m_engine;
|
||||||
ModulesModel *m_model;
|
Utils::TreeModel *m_model;
|
||||||
QSortFilterProxyModel *m_proxyModel;
|
QSortFilterProxyModel *m_proxyModel;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -402,7 +402,8 @@ void PdbEngine::handleListModules(const PdbResponse &response)
|
|||||||
{
|
{
|
||||||
GdbMi out;
|
GdbMi out;
|
||||||
out.fromString(response.data.trimmed());
|
out.fromString(response.data.trimmed());
|
||||||
Modules modules;
|
ModulesHandler *handler = modulesHandler();
|
||||||
|
handler->beginUpdateAll();
|
||||||
foreach (const GdbMi &item, out.children()) {
|
foreach (const GdbMi &item, out.children()) {
|
||||||
Module module;
|
Module module;
|
||||||
module.moduleName = _(item["name"].data());
|
module.moduleName = _(item["name"].data());
|
||||||
@@ -417,9 +418,9 @@ void PdbEngine::handleListModules(const PdbResponse &response)
|
|||||||
path = _("(builtin)");
|
path = _("(builtin)");
|
||||||
}
|
}
|
||||||
module.modulePath = path;
|
module.modulePath = path;
|
||||||
modules.append(module);
|
handler->updateModule(module);
|
||||||
}
|
}
|
||||||
modulesHandler()->setModules(modules);
|
handler->endUpdateAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PdbEngine::requestModuleSymbols(const QString &moduleName)
|
void PdbEngine::requestModuleSymbols(const QString &moduleName)
|
||||||
|
Reference in New Issue
Block a user