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;
|
||||
value.fromString(reply->reply);
|
||||
if (value.type() == GdbMi::List) {
|
||||
Modules modules;
|
||||
modules.reserve(value.childCount());
|
||||
ModulesHandler *handler = modulesHandler();
|
||||
handler->beginUpdateAll();
|
||||
foreach (const GdbMi &gdbmiModule, value.children()) {
|
||||
Module module;
|
||||
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);
|
||||
if (gdbmiModule["deferred"].type() == GdbMi::Invalid)
|
||||
module.symbolsRead = Module::ReadOk;
|
||||
modules.push_back(module);
|
||||
handler->updateModule(module);
|
||||
}
|
||||
modulesHandler()->setModules(modules);
|
||||
handler->endUpdateAll();
|
||||
} else {
|
||||
showMessage(QString::fromLatin1("Parse error in modules response."), LogError);
|
||||
qWarning("Parse error in modules response:\n%s", reply->reply.constData());
|
||||
|
@@ -771,7 +771,8 @@ void LldbEngine::reloadModules()
|
||||
|
||||
void LldbEngine::refreshModules(const GdbMi &modules)
|
||||
{
|
||||
Modules mods;
|
||||
ModulesHandler *handler = modulesHandler();
|
||||
handler->beginUpdateAll();
|
||||
foreach (const GdbMi &item, modules.children()) {
|
||||
Module module;
|
||||
module.modulePath = item["file"].toUtf8();
|
||||
@@ -779,9 +780,9 @@ void LldbEngine::refreshModules(const GdbMi &modules)
|
||||
module.symbolsRead = Module::UnknownReadState;
|
||||
module.startAddress = item["loaded_addr"].toAddress();
|
||||
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)
|
||||
|
@@ -31,7 +31,9 @@
|
||||
#include "moduleshandler.h"
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/treemodel.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
@@ -46,60 +48,19 @@ using namespace Utils;
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class ModulesModel : public QAbstractItemModel
|
||||
class ModuleItem : public TreeItem
|
||||
{
|
||||
public:
|
||||
explicit ModulesModel(QObject *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
{}
|
||||
QVariant data(int column, int role) const;
|
||||
|
||||
int columnCount(const QModelIndex &parent) const
|
||||
{ return parent.isValid() ? 0 : 5; }
|
||||
int rowCount(const QModelIndex &parent) const
|
||||
{ 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;
|
||||
public:
|
||||
Module module;
|
||||
bool updated;
|
||||
};
|
||||
|
||||
|
||||
QVariant ModulesModel::headerData(int section,
|
||||
Qt::Orientation orientation, int role) const
|
||||
QVariant ModuleItem::data(int column, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
||||
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()) {
|
||||
switch (column) {
|
||||
case 0:
|
||||
if (role == Qt::DisplayRole)
|
||||
return module.moduleName;
|
||||
@@ -192,78 +153,39 @@ QVariant ModulesModel::data(const QModelIndex &index, int role) const
|
||||
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
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
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)
|
||||
{
|
||||
m_engine = engine;
|
||||
m_model = new ModulesModel(this);
|
||||
|
||||
QString pad = QLatin1String(" ");
|
||||
m_model = new TreeModel(this);
|
||||
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->setObjectName(QLatin1String("ModulesProxyModel"));
|
||||
m_proxyModel->setSourceModel(m_model);
|
||||
@@ -276,27 +198,65 @@ QAbstractItemModel *ModulesHandler::model() const
|
||||
|
||||
void ModulesHandler::removeAll()
|
||||
{
|
||||
m_model->clearModel();
|
||||
}
|
||||
|
||||
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);
|
||||
m_model->removeAllSubItems(m_model->rootItem());
|
||||
}
|
||||
|
||||
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
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#define DEBUGGER_MODULESHANDLER_H
|
||||
|
||||
#include <utils/elfreader.h>
|
||||
#include <utils/treemodel.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QAbstractItemModel;
|
||||
@@ -42,7 +43,6 @@ namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class DebuggerEngine;
|
||||
class ModulesModel;
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -109,7 +109,6 @@ public:
|
||||
|
||||
typedef QVector<Module> Modules;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ModulesHandler
|
||||
@@ -125,16 +124,18 @@ public:
|
||||
|
||||
QAbstractItemModel *model() const;
|
||||
|
||||
void setModules(const Modules &modules);
|
||||
void removeModule(const QString &modulePath);
|
||||
void updateModule(const Module &module);
|
||||
|
||||
Modules modules() const;
|
||||
void beginUpdateAll();
|
||||
void endUpdateAll();
|
||||
|
||||
void removeAll();
|
||||
Modules modules() const;
|
||||
|
||||
private:
|
||||
DebuggerEngine *m_engine;
|
||||
ModulesModel *m_model;
|
||||
Utils::TreeModel *m_model;
|
||||
QSortFilterProxyModel *m_proxyModel;
|
||||
};
|
||||
|
||||
|
@@ -402,7 +402,8 @@ void PdbEngine::handleListModules(const PdbResponse &response)
|
||||
{
|
||||
GdbMi out;
|
||||
out.fromString(response.data.trimmed());
|
||||
Modules modules;
|
||||
ModulesHandler *handler = modulesHandler();
|
||||
handler->beginUpdateAll();
|
||||
foreach (const GdbMi &item, out.children()) {
|
||||
Module module;
|
||||
module.moduleName = _(item["name"].data());
|
||||
@@ -417,9 +418,9 @@ void PdbEngine::handleListModules(const PdbResponse &response)
|
||||
path = _("(builtin)");
|
||||
}
|
||||
module.modulePath = path;
|
||||
modules.append(module);
|
||||
handler->updateModule(module);
|
||||
}
|
||||
modulesHandler()->setModules(modules);
|
||||
handler->endUpdateAll();
|
||||
}
|
||||
|
||||
void PdbEngine::requestModuleSymbols(const QString &moduleName)
|
||||
|
Reference in New Issue
Block a user