mirror of https://github.com/mgba-emu/mgba.git
Qt: Add access log view to memory view
This commit is contained in:
parent
75dc290853
commit
159b0dc445
|
@ -262,6 +262,7 @@ if(ENABLE_DEBUGGERS)
|
|||
DebuggerConsole.cpp
|
||||
DebuggerConsoleController.cpp
|
||||
MemoryAccessLogController.cpp
|
||||
MemoryAccessLogModel.cpp
|
||||
MemoryAccessLogView.cpp)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -10,8 +10,14 @@
|
|||
#include "utils.h"
|
||||
#include "VFileDevice.h"
|
||||
|
||||
#include <mgba-util/math.h>
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
int MemoryAccessLogController::Flags::count() const {
|
||||
return popcount32(flags) + popcount32(flagsEx);
|
||||
}
|
||||
|
||||
MemoryAccessLogController::MemoryAccessLogController(CoreController* controller, QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_controller(controller)
|
||||
|
@ -39,6 +45,17 @@ bool MemoryAccessLogController::canExport() const {
|
|||
return m_regionMapping.contains("cart0");
|
||||
}
|
||||
|
||||
MemoryAccessLogController::Flags MemoryAccessLogController::flagsForAddress(uint32_t addresss, int segment) {
|
||||
uint32_t offset = cacheRegion(addresss, segment);
|
||||
if (!m_cachedRegion) {
|
||||
return { 0, 0 };
|
||||
}
|
||||
return {
|
||||
m_cachedRegion->blockEx ? m_cachedRegion->blockEx[offset] : mDebuggerAccessLogFlagsEx{},
|
||||
m_cachedRegion->block ? m_cachedRegion->block[offset] : mDebuggerAccessLogFlags{},
|
||||
};
|
||||
}
|
||||
|
||||
void MemoryAccessLogController::updateRegion(const QString& internalName, bool checked) {
|
||||
if (checked) {
|
||||
m_watchedRegions += internalName;
|
||||
|
@ -116,3 +133,27 @@ void MemoryAccessLogController::exportFile(const QString& filename) {
|
|||
mDebuggerAccessLoggerCreateShadowFile(&m_logger, m_regionMapping[QString("cart0")], vf, 0);
|
||||
vf->close(vf);
|
||||
}
|
||||
|
||||
uint32_t MemoryAccessLogController::cacheRegion(uint32_t address, int segment) {
|
||||
if (m_cachedRegion && (address < m_cachedRegion->start || address >= m_cachedRegion->end)) {
|
||||
m_cachedRegion = nullptr;
|
||||
}
|
||||
if (!m_cachedRegion) {
|
||||
m_cachedRegion = mDebuggerAccessLoggerGetRegion(&m_logger, address, segment, nullptr);
|
||||
}
|
||||
if (!m_cachedRegion) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t offset = address - m_cachedRegion->start;
|
||||
if (segment > 0) {
|
||||
uint32_t segmentSize = m_cachedRegion->end - m_cachedRegion->segmentStart;
|
||||
offset %= segmentSize;
|
||||
offset += segmentSize * segment;
|
||||
}
|
||||
if (offset >= m_cachedRegion->size) {
|
||||
m_cachedRegion = nullptr;
|
||||
return cacheRegion(address, segment);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "CoreController.h"
|
||||
|
||||
#include <mgba/debugger/debugger.h>
|
||||
#include <mgba/internal/debugger/access-logger.h>
|
||||
|
||||
namespace QGBA {
|
||||
|
@ -25,6 +26,16 @@ public:
|
|||
QString internalName;
|
||||
};
|
||||
|
||||
struct Flags {
|
||||
mDebuggerAccessLogFlagsEx flagsEx;
|
||||
mDebuggerAccessLogFlags flags;
|
||||
|
||||
int count() const;
|
||||
bool operator==(const Flags& other) const { return flags == other.flags && flagsEx == other.flagsEx; }
|
||||
bool operator!=(const Flags& other) const { return flags != other.flags || flagsEx != other.flagsEx; }
|
||||
operator bool() const { return flags || flagsEx; }
|
||||
};
|
||||
|
||||
MemoryAccessLogController(CoreController* controller, QObject* parent = nullptr);
|
||||
~MemoryAccessLogController();
|
||||
|
||||
|
@ -34,6 +45,8 @@ public:
|
|||
bool canExport() const;
|
||||
mPlatform platform() const { return m_controller->platform(); }
|
||||
|
||||
Flags flagsForAddress(uint32_t address, int segment = -1);
|
||||
|
||||
QString file() const { return m_path; }
|
||||
bool active() const { return m_active; }
|
||||
|
||||
|
@ -59,8 +72,10 @@ private:
|
|||
QVector<Region> m_regions;
|
||||
struct mDebuggerAccessLogger m_logger{};
|
||||
bool m_active = false;
|
||||
mDebuggerAccessLogRegion* m_cachedRegion = nullptr;
|
||||
|
||||
mDebuggerAccessLogRegionFlags activeFlags() const;
|
||||
uint32_t cacheRegion(uint32_t address, int segment);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,283 @@
|
|||
/* Copyright (c) 2013-2025 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "MemoryAccessLogModel.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
MemoryAccessLogModel::MemoryAccessLogModel(std::weak_ptr<MemoryAccessLogController> controller, mPlatform platform)
|
||||
: m_controller(controller)
|
||||
, m_platform(platform)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant MemoryAccessLogModel::data(const QModelIndex& index, int role) const {
|
||||
if (role != Qt::DisplayRole) {
|
||||
return {};
|
||||
}
|
||||
if (index.column() != 0) {
|
||||
return {};
|
||||
}
|
||||
int blockIndex = -1;
|
||||
int flagIndex = -1;
|
||||
QModelIndex parent = index.parent();
|
||||
if (!parent.isValid()) {
|
||||
blockIndex = index.row();
|
||||
} else {
|
||||
blockIndex = parent.row();
|
||||
flagIndex = index.row();
|
||||
}
|
||||
|
||||
if (blockIndex < 0 || blockIndex >= m_cachedBlocks.count()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const Block& block = m_cachedBlocks[blockIndex];
|
||||
|
||||
if (flagIndex < 0) {
|
||||
return QString("0x%1 – 0x%2")
|
||||
.arg(QString("%0").arg(block.region.first, 8, 16, QChar('0')).toUpper())
|
||||
.arg(QString("%0").arg(block.region.second, 8, 16, QChar('0')).toUpper());
|
||||
}
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
if (!(block.flags.flags & (1 << i))) {
|
||||
continue;
|
||||
}
|
||||
if (flagIndex == 0) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
return tr("Data read");
|
||||
case 1:
|
||||
return tr("Data written");
|
||||
case 2:
|
||||
return tr("Code executed");
|
||||
case 3:
|
||||
return tr("Code aborted");
|
||||
case 4:
|
||||
return tr("8-bit access");
|
||||
case 5:
|
||||
return tr("16-bit access");
|
||||
case 6:
|
||||
return tr("32-bit access");
|
||||
case 7:
|
||||
return tr("64-bit access");
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
--flagIndex;
|
||||
}
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
if (!(block.flags.flagsEx & (1 << i))) {
|
||||
continue;
|
||||
}
|
||||
if (flagIndex == 0) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
return tr("Accessed by instruction");
|
||||
case 1:
|
||||
return tr("Accessed by DMA");
|
||||
case 2:
|
||||
return tr("Accessed by BIOS");
|
||||
case 3:
|
||||
return tr("Compressed data");
|
||||
case 4:
|
||||
return tr("Accessed by memory copy");
|
||||
case 5:
|
||||
return tr("(Unknown extra bit 5)");
|
||||
case 6:
|
||||
return tr("(Unknown extra bit 6)");
|
||||
case 7:
|
||||
return tr("(Unknown extra bit 7)");
|
||||
case 8:
|
||||
return tr("Invalid instruction");
|
||||
case 9:
|
||||
return tr("Invalid read");
|
||||
case 10:
|
||||
return tr("Invalid write");
|
||||
case 11:
|
||||
return tr("Invalid executable address");
|
||||
case 12:
|
||||
return tr("(Private bit 0)");
|
||||
case 13:
|
||||
return tr("(Private bit 1)");
|
||||
case 14:
|
||||
switch (m_platform) {
|
||||
case mPLATFORM_GBA:
|
||||
return tr("ARM code");
|
||||
default:
|
||||
return tr("(Private bit 2)");
|
||||
}
|
||||
case 15:
|
||||
switch (m_platform) {
|
||||
case mPLATFORM_GBA:
|
||||
return tr("Thumb code");
|
||||
default:
|
||||
return tr("(Private bit 2)");
|
||||
}
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
--flagIndex;
|
||||
}
|
||||
return tr("(Unknown)");
|
||||
}
|
||||
|
||||
QModelIndex MemoryAccessLogModel::index(int row, int column, const QModelIndex& parent) const {
|
||||
if (column != 0) {
|
||||
return {};
|
||||
}
|
||||
if (parent.isValid()) {
|
||||
return createIndex(row, 0, parent.row());
|
||||
}
|
||||
return createIndex(row, 0, std::numeric_limits<quintptr>::max());
|
||||
}
|
||||
|
||||
QModelIndex MemoryAccessLogModel::parent(const QModelIndex& index) const {
|
||||
if (!index.isValid()) {
|
||||
return {};
|
||||
}
|
||||
quintptr row = index.internalId();
|
||||
if (row >= std::numeric_limits<uint32_t>::max()) {
|
||||
return {};
|
||||
}
|
||||
return createIndex(row, 0, std::numeric_limits<quintptr>::max());
|
||||
}
|
||||
|
||||
int MemoryAccessLogModel::rowCount(const QModelIndex& parent) const {
|
||||
int blockIndex = -1;
|
||||
if (!parent.isValid()) {
|
||||
return m_cachedBlocks.count();
|
||||
} else if (parent.column() != 0) {
|
||||
return 0;
|
||||
} else if (parent.parent().isValid()) {
|
||||
return 0;
|
||||
} else {
|
||||
blockIndex = parent.row();
|
||||
}
|
||||
|
||||
if (blockIndex < 0 || blockIndex >= m_cachedBlocks.count()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Block& block = m_cachedBlocks[blockIndex];
|
||||
return block.flags.count();
|
||||
}
|
||||
|
||||
void MemoryAccessLogModel::updateSelection(uint32_t start, uint32_t end) {
|
||||
std::shared_ptr<MemoryAccessLogController> controller = m_controller.lock();
|
||||
if (!controller) {
|
||||
return;
|
||||
}
|
||||
QVector<Block> newBlocks;
|
||||
uint32_t lastStart = start;
|
||||
auto lastFlags = controller->flagsForAddress(m_base + start, m_segment);
|
||||
|
||||
for (uint32_t address = start; address < end; ++address) {
|
||||
auto flags = controller->flagsForAddress(m_base + address, m_segment);
|
||||
if (flags == lastFlags) {
|
||||
continue;
|
||||
}
|
||||
if (lastFlags) {
|
||||
newBlocks.append({ lastFlags, qMakePair(lastStart, address) });
|
||||
}
|
||||
lastFlags = flags;
|
||||
lastStart = address;
|
||||
}
|
||||
if (lastFlags) {
|
||||
newBlocks.append({ lastFlags, qMakePair(lastStart, end) });
|
||||
}
|
||||
|
||||
if (m_cachedBlocks.count() == 0 || newBlocks.count() == 0) {
|
||||
beginResetModel();
|
||||
m_cachedBlocks = newBlocks;
|
||||
endResetModel();
|
||||
return;
|
||||
}
|
||||
|
||||
QPair<int, int> changed{ -1, -1 };
|
||||
for (int i = 0; i < m_cachedBlocks.count() && i < newBlocks.count(); ++i) {
|
||||
const Block& oldBlock = m_cachedBlocks.at(i);
|
||||
const Block& newBlock = newBlocks.at(i);
|
||||
|
||||
if (oldBlock != newBlock) {
|
||||
changed = qMakePair(i, m_cachedBlocks.count());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_cachedBlocks.count() > newBlocks.count()) {
|
||||
beginRemoveRows({}, newBlocks.count(), m_cachedBlocks.count());
|
||||
m_cachedBlocks.resize(newBlocks.count());
|
||||
endRemoveRows();
|
||||
changed.second = newBlocks.count();
|
||||
}
|
||||
|
||||
if (m_cachedBlocks.count() < newBlocks.count()) {
|
||||
beginInsertRows({}, m_cachedBlocks.count(), newBlocks.count());
|
||||
if (changed.first < 0) {
|
||||
// Only new rows
|
||||
m_cachedBlocks = newBlocks;
|
||||
endInsertRows();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed.first < 0) {
|
||||
// No changed rows, though some might have been removed
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_cachedBlocks.count() && i < newBlocks.count(); ++i) {
|
||||
const Block& oldBlock = m_cachedBlocks.at(i);
|
||||
const Block& newBlock = newBlocks.at(i);
|
||||
if (oldBlock.flags != newBlock.flags) {
|
||||
int oldFlags = oldBlock.flags.count();
|
||||
int newFlags = newBlock.flags.count();
|
||||
if (oldFlags > newFlags) {
|
||||
beginRemoveRows(createIndex(i, 0, std::numeric_limits<quintptr>::max()), newFlags, oldFlags);
|
||||
} else if (oldFlags < newFlags) {
|
||||
beginInsertRows(createIndex(i, 0, std::numeric_limits<quintptr>::max()), oldFlags, newFlags);
|
||||
}
|
||||
m_cachedBlocks[i] = newBlock;
|
||||
emit dataChanged(createIndex(0, 0, i), createIndex(std::min(oldFlags, newFlags), 0, i));
|
||||
if (oldFlags > newFlags) {
|
||||
endRemoveRows();
|
||||
} else if (oldFlags < newFlags) {
|
||||
endInsertRows();
|
||||
}
|
||||
}
|
||||
}
|
||||
emit dataChanged(createIndex(changed.first, 0, std::numeric_limits<quintptr>::max()),
|
||||
createIndex(changed.second, 0, std::numeric_limits<quintptr>::max()));
|
||||
|
||||
if (m_cachedBlocks.count() < newBlocks.count()) {
|
||||
m_cachedBlocks = newBlocks;
|
||||
endInsertRows();
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryAccessLogModel::setSegment(int segment) {
|
||||
if (m_segment == segment) {
|
||||
return;
|
||||
}
|
||||
beginResetModel();
|
||||
m_segment = segment;
|
||||
m_cachedBlocks.clear();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void MemoryAccessLogModel::setRegion(uint32_t base, uint32_t, bool useSegments) {
|
||||
if (m_base == base) {
|
||||
return;
|
||||
}
|
||||
beginResetModel();
|
||||
m_segment = useSegments ? 0 : -1;
|
||||
m_cachedBlocks.clear();
|
||||
endResetModel();
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/* Copyright (c) 2013-2025 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QVector>
|
||||
|
||||
#include "MemoryAccessLogController.h"
|
||||
|
||||
struct mCheatDevice;
|
||||
struct mCheatSet;
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class MemoryAccessLogModel : public QAbstractItemModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MemoryAccessLogModel(std::weak_ptr<MemoryAccessLogController> controller, mPlatform platform);
|
||||
|
||||
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
virtual QModelIndex index(int row, int column, const QModelIndex& parent) const override;
|
||||
virtual QModelIndex parent(const QModelIndex& index) const override;
|
||||
|
||||
virtual int columnCount(const QModelIndex& = QModelIndex()) const override { return 1; }
|
||||
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
|
||||
public slots:
|
||||
void updateSelection(uint32_t start, uint32_t end);
|
||||
void setSegment(int segment);
|
||||
void setRegion(uint32_t base, uint32_t segmentSize, bool useSegments);
|
||||
|
||||
private:
|
||||
struct Block {
|
||||
MemoryAccessLogController::Flags flags;
|
||||
QPair<uint32_t, uint32_t> region;
|
||||
|
||||
bool operator==(const Block& other) const { return flags == other.flags && region == other.region; }
|
||||
bool operator!=(const Block& other) const { return flags != other.flags || region != other.region; }
|
||||
};
|
||||
|
||||
int flagCount(int index) const;
|
||||
|
||||
std::weak_ptr<MemoryAccessLogController> m_controller;
|
||||
mPlatform m_platform;
|
||||
uint32_t m_base = 0;
|
||||
int m_segment = -1;
|
||||
QVector<Block> m_cachedBlocks;
|
||||
};
|
||||
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
#include "MemoryView.h"
|
||||
|
||||
#include "CoreController.h"
|
||||
#include "MemoryAccessLogView.h"
|
||||
#include "MemoryDump.h"
|
||||
|
||||
#include <mgba/core/core.h>
|
||||
|
@ -107,6 +108,9 @@ QValidator::State IntValidator::validate(QString& input, int&) const {
|
|||
MemoryView::MemoryView(std::shared_ptr<CoreController> controller, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_controller(controller)
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
, m_malModel(controller->memoryAccessLogController(), controller->platform())
|
||||
#endif
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
|
||||
|
@ -189,6 +193,22 @@ MemoryView::MemoryView(std::shared_ptr<CoreController> controller, QWidget* pare
|
|||
}
|
||||
update();
|
||||
});
|
||||
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
connect(m_ui.hexfield, &MemoryModel::selectionChanged, &m_malModel, &MemoryAccessLogModel::updateSelection);
|
||||
connect(m_ui.segments, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
|
||||
&m_malModel, &MemoryAccessLogModel::setSegment);
|
||||
connect(m_ui.accessLoggerButton, &QAbstractButton::clicked, this, [this]() {
|
||||
std::weak_ptr<MemoryAccessLogController> controller = m_controller->memoryAccessLogController();
|
||||
MemoryAccessLogView* view = new MemoryAccessLogView(controller);
|
||||
connect(m_controller.get(), &CoreController::stopping, view, &QWidget::close);
|
||||
view->setAttribute(Qt::WA_DeleteOnClose);
|
||||
view->show();
|
||||
});
|
||||
m_ui.accessLog->setModel(&m_malModel);
|
||||
#else
|
||||
m_ui.accessLog->hide();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MemoryView::setIndex(int index) {
|
||||
|
@ -206,6 +226,10 @@ void MemoryView::setIndex(int index) {
|
|||
m_ui.segmentColon->setVisible(info.maxSegment > 0);
|
||||
m_ui.segments->setMaximum(info.maxSegment);
|
||||
m_ui.hexfield->setRegion(info.start, info.end - info.start, info.shortName);
|
||||
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
m_malModel.setRegion(info.start, info.segmentStart - info.start, info.maxSegment > 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MemoryView::setSegment(int segment) {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <QValidator>
|
||||
|
||||
#include "MemoryModel.h"
|
||||
#include "MemoryAccessLogModel.h"
|
||||
|
||||
#include "ui_MemoryView.h"
|
||||
|
||||
|
@ -54,6 +55,10 @@ private:
|
|||
std::shared_ptr<CoreController> m_controller;
|
||||
QPair<uint32_t, uint32_t> m_region;
|
||||
QPair<uint32_t, uint32_t> m_selection;
|
||||
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
MemoryAccessLogModel m_malModel;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -31,14 +31,14 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<layout class="QVBoxLayout" name="sidebarLayout" stretch="0,0,0,1,0,1">
|
||||
<item>
|
||||
<widget class="QComboBox" name="regions"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<layout class="QHBoxLayout" name="addressLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<widget class="QLabel" name="address">
|
||||
<property name="text">
|
||||
<string>Address:</string>
|
||||
</property>
|
||||
|
@ -105,9 +105,9 @@
|
|||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<layout class="QHBoxLayout" name="alignmentLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<widget class="QLabel" name="alignmentLabel">
|
||||
<property name="text">
|
||||
<string>Alignment:</string>
|
||||
</property>
|
||||
|
@ -141,7 +141,7 @@
|
|||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<widget class="QGroupBox" name="data">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Ignored" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
|
@ -151,9 +151,9 @@
|
|||
<property name="title">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<layout class="QGridLayout" name="gridLayout_9">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<widget class="QLabel" name="sintLabel">
|
||||
<property name="text">
|
||||
<string>Signed:</string>
|
||||
</property>
|
||||
|
@ -173,7 +173,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<widget class="QLabel" name="uintLabel">
|
||||
<property name="text">
|
||||
<string>Unsigned:</string>
|
||||
</property>
|
||||
|
@ -193,7 +193,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<widget class="QLabel" name="stringLabel">
|
||||
<property name="text">
|
||||
<string>String:</string>
|
||||
</property>
|
||||
|
@ -232,7 +232,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<layout class="QGridLayout" name="buttons">
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="copy">
|
||||
<property name="text">
|
||||
|
@ -276,6 +276,44 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="verticalGroupBox_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Selected address accesses</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTreeView" name="accessLog">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="textElideMode">
|
||||
<enum>Qt::ElideNone</enum>
|
||||
</property>
|
||||
<attribute name="headerVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="accessLoggerButton">
|
||||
<property name="text">
|
||||
<string>Logging configuration</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
Loading…
Reference in New Issue