Added ChangeListPane widget to snapshot diff window
This commit is contained in:
@@ -115,6 +115,8 @@ target_sources(
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialHexViewerWidget.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialHexViewerWidget.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsView.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsView.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsScene.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsScene.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/ChangeListPane/ChangeListPane.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/ChangeListPane/ChangeListItem.cpp
|
||||||
|
|
||||||
# Memory region manager window
|
# Memory region manager window
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/MemoryRegionManagerWindow.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/MemoryRegionManagerWindow.cpp
|
||||||
@@ -208,6 +210,7 @@ qt_add_resources(
|
|||||||
"./UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/Images/sync-hex-viewer-scroll.svg"
|
"./UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/Images/sync-hex-viewer-scroll.svg"
|
||||||
"./UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/Images/sync-hex-viewer-hover.svg"
|
"./UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/Images/sync-hex-viewer-hover.svg"
|
||||||
"./UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/Images/sync-hex-viewer-selection.svg"
|
"./UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/Images/sync-hex-viewer-selection.svg"
|
||||||
|
"./UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/Images/view-change-list-icon.svg"
|
||||||
|
|
||||||
# Memory region manager window
|
# Memory region manager window
|
||||||
"./UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/UiFiles/MemoryRegionManagerWindow.ui"
|
"./UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/UiFiles/MemoryRegionManagerWindow.ui"
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
#include "ChangeListItem.hpp"
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QLocale>
|
||||||
|
|
||||||
|
namespace Widgets
|
||||||
|
{
|
||||||
|
ChangeListItem::ChangeListItem(const Targets::TargetMemoryAddressRange& addressRange)
|
||||||
|
: addressRange(addressRange)
|
||||||
|
{
|
||||||
|
this->size = QSize(0, ChangeListItem::HEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChangeListItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
|
||||||
|
static constexpr auto margins = QMargins(7, 5, 7, 0);
|
||||||
|
|
||||||
|
static auto font = QFont("'Ubuntu', sans-serif");
|
||||||
|
font.setPixelSize(14);
|
||||||
|
static auto secondaryFont = QFont("'Ubuntu', sans-serif");
|
||||||
|
secondaryFont.setPixelSize(13);
|
||||||
|
|
||||||
|
static constexpr auto fontColor = QColor(0xAF, 0xB1, 0xB3);
|
||||||
|
static constexpr auto secondaryFontColor = QColor(0x8A, 0x8A, 0x8D);
|
||||||
|
|
||||||
|
if (this->selected) {
|
||||||
|
static constexpr auto selectedBackgroundColor = QColor(0x3C, 0x59, 0x5C);
|
||||||
|
|
||||||
|
painter->setBrush(selectedBackgroundColor);
|
||||||
|
painter->setPen(Qt::PenStyle::NoPen);
|
||||||
|
painter->drawRect(QRect(QPoint(0, 0), this->size));
|
||||||
|
}
|
||||||
|
|
||||||
|
painter->setFont(font);
|
||||||
|
painter->setPen(fontColor);
|
||||||
|
|
||||||
|
auto fontMetrics = painter->fontMetrics();
|
||||||
|
|
||||||
|
const auto byteCount = this->addressRange.endAddress - this->addressRange.startAddress + 1;
|
||||||
|
const auto byteCountText = QLocale(QLocale::English).toString(byteCount)
|
||||||
|
+ (byteCount == 1 ? " byte" : " bytes");
|
||||||
|
const auto byteCountTextSize = fontMetrics.size(Qt::TextSingleLine, byteCountText);
|
||||||
|
|
||||||
|
const auto byteCountTextRect = QRect(
|
||||||
|
margins.left(),
|
||||||
|
margins.top(),
|
||||||
|
byteCountTextSize.width(),
|
||||||
|
byteCountTextSize.height()
|
||||||
|
);
|
||||||
|
|
||||||
|
painter->drawText(byteCountTextRect, Qt::AlignLeft, byteCountText);
|
||||||
|
|
||||||
|
painter->setFont(secondaryFont);
|
||||||
|
fontMetrics = painter->fontMetrics();
|
||||||
|
|
||||||
|
if (!this->selected) {
|
||||||
|
painter->setPen(secondaryFontColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto addressRangeText = "0x" + QString::number(
|
||||||
|
this->addressRange.startAddress,
|
||||||
|
16
|
||||||
|
).rightJustified(8, '0').toUpper();
|
||||||
|
|
||||||
|
if (byteCount > 1) {
|
||||||
|
addressRangeText += " -> 0x" + QString::number(
|
||||||
|
this->addressRange.endAddress,
|
||||||
|
16
|
||||||
|
).rightJustified(8, '0').toUpper();
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto availableAddressRangeTextWidth = this->size.width() - margins.left() - margins.right();
|
||||||
|
|
||||||
|
addressRangeText = fontMetrics.elidedText(
|
||||||
|
addressRangeText,
|
||||||
|
Qt::TextElideMode::ElideRight,
|
||||||
|
availableAddressRangeTextWidth
|
||||||
|
);
|
||||||
|
|
||||||
|
const auto addressRangeTextSize = fontMetrics.size(Qt::TextSingleLine, addressRangeText);
|
||||||
|
const auto addressRangeTextRect = QRect(
|
||||||
|
margins.left(),
|
||||||
|
byteCountTextRect.bottom() + 5,
|
||||||
|
addressRangeTextSize.width(),
|
||||||
|
addressRangeTextSize.height()
|
||||||
|
);
|
||||||
|
|
||||||
|
painter->drawText(addressRangeTextRect, Qt::AlignLeft, addressRangeText);
|
||||||
|
|
||||||
|
static constexpr auto borderColor = QColor(0x41, 0x42, 0x3F);
|
||||||
|
|
||||||
|
painter->setPen(borderColor);
|
||||||
|
painter->drawLine(0, this->size.height() - 1, this->size.width(), this->size.height() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/ListView/ListItem.hpp"
|
||||||
|
|
||||||
|
#include "src/Targets/TargetMemory.hpp"
|
||||||
|
|
||||||
|
namespace Widgets
|
||||||
|
{
|
||||||
|
class ChangeListItem: public ListItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Targets::TargetMemoryAddressRange addressRange;
|
||||||
|
|
||||||
|
ChangeListItem(const Targets::TargetMemoryAddressRange& addressRange);
|
||||||
|
|
||||||
|
bool operator < (const ListItem& rhs) const override {
|
||||||
|
const auto& rhsSnapshotItem = dynamic_cast<const ChangeListItem&>(rhs);
|
||||||
|
return this->addressRange.startAddress < rhsSnapshotItem.addressRange.startAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr int HEIGHT = 50;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
#include "ChangeListPane.hpp"
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <QScrollBar>
|
||||||
|
|
||||||
|
#include "src/Insight/UserInterfaces/InsightWindow/UiLoader.hpp"
|
||||||
|
|
||||||
|
#include "src/Services/PathService.hpp"
|
||||||
|
#include "src/Exceptions/Exception.hpp"
|
||||||
|
|
||||||
|
namespace Widgets
|
||||||
|
{
|
||||||
|
using Exceptions::Exception;
|
||||||
|
|
||||||
|
ChangeListPane::ChangeListPane(
|
||||||
|
DifferentialHexViewerWidget* hexViewerWidgetA,
|
||||||
|
DifferentialHexViewerWidget* hexViewerWidgetB,
|
||||||
|
PaneState& state,
|
||||||
|
PanelWidget* parent
|
||||||
|
)
|
||||||
|
: PaneWidget(state, parent)
|
||||||
|
, hexViewerWidgetA(hexViewerWidgetA)
|
||||||
|
, hexViewerWidgetB(hexViewerWidgetB)
|
||||||
|
{
|
||||||
|
this->setObjectName("change-list-pane");
|
||||||
|
this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||||
|
|
||||||
|
auto widgetUiFile = QFile(
|
||||||
|
QString::fromStdString(Services::PathService::compiledResourcesPath()
|
||||||
|
+ "/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager"
|
||||||
|
+ "/SnapshotDiff/ChangeListPane/UiFiles/ChangeListPane.ui"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!widgetUiFile.open(QFile::ReadOnly)) {
|
||||||
|
throw Exception("Failed to open ChangeListPane UI file");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto uiLoader = UiLoader(this);
|
||||||
|
this->container = uiLoader.load(&widgetUiFile, this);
|
||||||
|
|
||||||
|
this->container->setFixedSize(this->size());
|
||||||
|
this->container->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
|
auto* containerLayout = this->container->findChild<QVBoxLayout*>();
|
||||||
|
|
||||||
|
this->changeListView = new ListView({}, this);
|
||||||
|
this->changeListView->viewport()->installEventFilter(parent);
|
||||||
|
this->changeListView->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded);
|
||||||
|
|
||||||
|
this->changeListScene = this->changeListView->listScene();
|
||||||
|
this->changeListScene->setSelectionLimit(1);
|
||||||
|
|
||||||
|
containerLayout->addWidget(this->changeListView);
|
||||||
|
|
||||||
|
QObject::connect(
|
||||||
|
this->changeListView->verticalScrollBar(),
|
||||||
|
&QScrollBar::rangeChanged,
|
||||||
|
this,
|
||||||
|
&ChangeListPane::refreshChangeListViewSize
|
||||||
|
);
|
||||||
|
|
||||||
|
QObject::connect(
|
||||||
|
this->changeListScene,
|
||||||
|
&ListScene::selectionChanged,
|
||||||
|
this,
|
||||||
|
&ChangeListPane::onItemSelectionChanged
|
||||||
|
);
|
||||||
|
|
||||||
|
this->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChangeListPane::setDiffRanges(const std::vector<Targets::TargetMemoryAddressRange>& diffRanges) {
|
||||||
|
this->changeListScene->clearListItems();
|
||||||
|
|
||||||
|
for (const auto& diffRange : diffRanges) {
|
||||||
|
this->changeListScene->addListItem(new ChangeListItem(diffRange));
|
||||||
|
}
|
||||||
|
|
||||||
|
this->changeListScene->refreshGeometry();
|
||||||
|
|
||||||
|
// Trigger a resize event
|
||||||
|
this->resize(this->size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChangeListPane::resizeEvent(QResizeEvent* event) {
|
||||||
|
const auto size = this->size();
|
||||||
|
this->container->setFixedSize(size.width() - 1, size.height());
|
||||||
|
|
||||||
|
this->refreshChangeListViewSize();
|
||||||
|
|
||||||
|
PaneWidget::resizeEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChangeListPane::showEvent(QShowEvent* event) {
|
||||||
|
this->refreshChangeListViewSize();
|
||||||
|
PaneWidget::showEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChangeListPane::onItemSelectionChanged(const std::list<ListItem*>& selectedItems) {
|
||||||
|
if (selectedItems.size() < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto* item = dynamic_cast<ChangeListItem*>(selectedItems.front());
|
||||||
|
|
||||||
|
this->hexViewerWidgetA->selectAndHighlightBytes({item->addressRange});
|
||||||
|
this->hexViewerWidgetA->centerOnByte(item->addressRange.startAddress);
|
||||||
|
|
||||||
|
this->hexViewerWidgetB->selectAndHighlightBytes({item->addressRange});
|
||||||
|
this->hexViewerWidgetB->centerOnByte(item->addressRange.startAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChangeListPane::refreshChangeListViewSize() {
|
||||||
|
this->changeListView->setFixedWidth(
|
||||||
|
this->container->width() - (
|
||||||
|
this->changeListView->verticalScrollBar()->isVisible() ? this->parentPanel->getHandleSize() : 0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QResizeEvent>
|
||||||
|
#include <QShowEvent>
|
||||||
|
|
||||||
|
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/PaneWidget.hpp"
|
||||||
|
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/ListView/ListView.hpp"
|
||||||
|
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialHexViewerWidget.hpp"
|
||||||
|
|
||||||
|
#include "src/Targets/TargetMemory.hpp"
|
||||||
|
|
||||||
|
#include "ChangeListItem.hpp"
|
||||||
|
|
||||||
|
namespace Widgets
|
||||||
|
{
|
||||||
|
class ChangeListPane: public PaneWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ChangeListPane(
|
||||||
|
DifferentialHexViewerWidget* hexViewerWidgetA,
|
||||||
|
DifferentialHexViewerWidget* hexViewerWidgetB,
|
||||||
|
PaneState& state,
|
||||||
|
PanelWidget* parent = nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
void setDiffRanges(const std::vector<Targets::TargetMemoryAddressRange>& diffRanges);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void resizeEvent(QResizeEvent* event) override;
|
||||||
|
void showEvent(QShowEvent* event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
DifferentialHexViewerWidget* hexViewerWidgetA;
|
||||||
|
DifferentialHexViewerWidget* hexViewerWidgetB;
|
||||||
|
|
||||||
|
QWidget* container = nullptr;
|
||||||
|
|
||||||
|
ListView* changeListView = nullptr;
|
||||||
|
ListScene* changeListScene = nullptr;
|
||||||
|
|
||||||
|
void onItemSelectionChanged(const std::list<ListItem*>& selectedItems);
|
||||||
|
void refreshChangeListViewSize();
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<widget class="QWidget" name="container">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"/>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="margin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="title-bar">
|
||||||
|
<property name="minimumHeight">
|
||||||
|
<number>28</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximumHeight">
|
||||||
|
<number>28</number>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"/>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<property name="margin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontal-spacer">
|
||||||
|
<property name="sizeHint">
|
||||||
|
<size>
|
||||||
|
<width>5</width>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Label" name="change-list-title-label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Differences</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item alignment="Qt::AlignLeft">
|
||||||
|
<spacer name="horizontal-spacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</ui>
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
width="22"
|
||||||
|
height="15"
|
||||||
|
viewBox="0 0 5.8208333 3.96875"
|
||||||
|
version="1.1"
|
||||||
|
id="svg974"
|
||||||
|
sodipodi:docname="view-change-list-icon.svg"
|
||||||
|
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
|
<defs
|
||||||
|
id="defs968" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#343532"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="27.557152"
|
||||||
|
inkscape:cx="8.4732995"
|
||||||
|
inkscape:cy="7.0399148"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
showgrid="false"
|
||||||
|
units="px"
|
||||||
|
inkscape:snap-page="true"
|
||||||
|
inkscape:window-width="3440"
|
||||||
|
inkscape:window-height="1353"
|
||||||
|
inkscape:window-x="2560"
|
||||||
|
inkscape:window-y="34"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:pagecheckerboard="0" />
|
||||||
|
<metadata
|
||||||
|
id="metadata971">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<path
|
||||||
|
sodipodi:type="star"
|
||||||
|
style="fill:#838382;fill-opacity:1;stroke:none;stroke-width:3.15673;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path954"
|
||||||
|
inkscape:flatsided="false"
|
||||||
|
sodipodi:sides="3"
|
||||||
|
sodipodi:cx="3.6919894"
|
||||||
|
sodipodi:cy="6.7028265"
|
||||||
|
sodipodi:r1="8.1449661"
|
||||||
|
sodipodi:r2="4.0724831"
|
||||||
|
sodipodi:arg1="0.52359878"
|
||||||
|
sodipodi:arg2="1.5707963"
|
||||||
|
inkscape:rounded="0"
|
||||||
|
inkscape:randomized="0"
|
||||||
|
d="m 10.745737,10.77531 -7.0537475,0 -7.0537477,0 3.52687378,-6.1087249 3.52687392,-6.1087247 3.5268737,6.1087245 z"
|
||||||
|
transform="matrix(0.22505767,0,0,0.23821803,2.0795061,0.87271031)"
|
||||||
|
inkscape:transform-center-y="-0.48506947" />
|
||||||
|
<path
|
||||||
|
sodipodi:type="star"
|
||||||
|
style="fill:#343532;fill-opacity:1;stroke:none;stroke-width:3.15673;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path954-6"
|
||||||
|
inkscape:flatsided="false"
|
||||||
|
sodipodi:sides="3"
|
||||||
|
sodipodi:cx="3.6919894"
|
||||||
|
sodipodi:cy="6.7028265"
|
||||||
|
sodipodi:r1="8.1449661"
|
||||||
|
sodipodi:r2="4.0724831"
|
||||||
|
sodipodi:arg1="0.52359878"
|
||||||
|
sodipodi:arg2="1.5707963"
|
||||||
|
inkscape:rounded="0"
|
||||||
|
inkscape:randomized="0"
|
||||||
|
transform="matrix(0.07501922,0,0,0.08662474,2.6334465,1.8447166)"
|
||||||
|
inkscape:transform-center-y="-0.17638902"
|
||||||
|
d="m 10.745737,10.77531 -7.0537475,0 -7.0537477,0 3.52687378,-6.1087249 3.52687392,-6.1087247 3.5268737,6.1087245 z" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.1 KiB |
@@ -128,7 +128,12 @@ namespace Widgets
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SnapshotDiff::resizeEvent(QResizeEvent* event) {
|
void SnapshotDiff::resizeEvent(QResizeEvent* event) {
|
||||||
this->container->setFixedSize(this->size());
|
const auto windowSize = this->size();
|
||||||
|
this->container->setFixedSize(windowSize);
|
||||||
|
|
||||||
|
const auto maxLeftPanelSize = static_cast<int>(windowSize.width() / 3);
|
||||||
|
this->leftPanel->setMaximumResize(maxLeftPanelSize);
|
||||||
|
this->leftPanel->setMinimumResize(std::min(this->leftPanel->getMinimumResize(), maxLeftPanelSize));
|
||||||
|
|
||||||
QWidget::resizeEvent(event);
|
QWidget::resizeEvent(event);
|
||||||
}
|
}
|
||||||
@@ -176,6 +181,19 @@ namespace Widgets
|
|||||||
this->syncHexViewerHoverButton = toolBar->findChild<SvgToolButton*>("sync-hover-btn");
|
this->syncHexViewerHoverButton = toolBar->findChild<SvgToolButton*>("sync-hover-btn");
|
||||||
this->syncHexViewerSelectionButton = toolBar->findChild<SvgToolButton*>("sync-selection-btn");
|
this->syncHexViewerSelectionButton = toolBar->findChild<SvgToolButton*>("sync-selection-btn");
|
||||||
|
|
||||||
|
this->viewChangeListButton = this->container->findChild<QToolButton*>("change-list-btn");
|
||||||
|
this->viewChangeListButton->layout()->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
|
auto* subContainerLayout = this->container->findChild<QWidget*>(
|
||||||
|
"sub-container"
|
||||||
|
)->findChild<QHBoxLayout*>("sub-layout");
|
||||||
|
|
||||||
|
this->leftPanel = new PanelWidget(PanelWidgetType::LEFT, this->leftPanelState, this);
|
||||||
|
this->leftPanel->setObjectName("left-panel");
|
||||||
|
this->leftPanel->setMinimumResize(200);
|
||||||
|
this->leftPanel->setHandleSize(6);
|
||||||
|
subContainerLayout->insertWidget(1, this->leftPanel, 0, Qt::AlignLeft);
|
||||||
|
|
||||||
this->dataAContainer = this->container->findChild<QWidget*>("data-a-container");
|
this->dataAContainer = this->container->findChild<QWidget*>("data-a-container");
|
||||||
this->dataBContainer = this->container->findChild<QWidget*>("data-b-container");
|
this->dataBContainer = this->container->findChild<QWidget*>("data-b-container");
|
||||||
|
|
||||||
@@ -220,6 +238,15 @@ namespace Widgets
|
|||||||
snapshotAContainerLayout->addWidget(this->hexViewerWidgetA);
|
snapshotAContainerLayout->addWidget(this->hexViewerWidgetA);
|
||||||
snapshotBContainerLayout->addWidget(this->hexViewerWidgetB);
|
snapshotBContainerLayout->addWidget(this->hexViewerWidgetB);
|
||||||
|
|
||||||
|
this->changeListPane = new ChangeListPane(
|
||||||
|
this->hexViewerWidgetA,
|
||||||
|
this->hexViewerWidgetB,
|
||||||
|
this->changeListPaneState,
|
||||||
|
this->leftPanel
|
||||||
|
);
|
||||||
|
this->leftPanel->layout()->addWidget(this->changeListPane);
|
||||||
|
this->viewChangeListButton->setChecked(this->changeListPane->state.activated);
|
||||||
|
|
||||||
this->bottomBar = this->container->findChild<QWidget*>("bottom-bar");
|
this->bottomBar = this->container->findChild<QWidget*>("bottom-bar");
|
||||||
this->bottomBarLayout = this->bottomBar->findChild<QHBoxLayout*>();
|
this->bottomBarLayout = this->bottomBar->findChild<QHBoxLayout*>();
|
||||||
|
|
||||||
@@ -240,6 +267,13 @@ namespace Widgets
|
|||||||
this->setSyncHexViewerHoverEnabled(this->settings.syncHexViewerHover);
|
this->setSyncHexViewerHoverEnabled(this->settings.syncHexViewerHover);
|
||||||
this->setSyncHexViewerSelectionEnabled(this->settings.syncHexViewerSelection);
|
this->setSyncHexViewerSelectionEnabled(this->settings.syncHexViewerSelection);
|
||||||
|
|
||||||
|
QObject::connect(
|
||||||
|
this->viewChangeListButton,
|
||||||
|
&QToolButton::clicked,
|
||||||
|
this,
|
||||||
|
&SnapshotDiff::toggleChangeListPane
|
||||||
|
);
|
||||||
|
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
this->syncHexViewerSettingsButton,
|
this->syncHexViewerSettingsButton,
|
||||||
&QToolButton::clicked,
|
&QToolButton::clicked,
|
||||||
@@ -308,10 +342,13 @@ namespace Widgets
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SnapshotDiff::refreshDifferences() {
|
void SnapshotDiff::refreshDifferences() {
|
||||||
|
using Targets::TargetMemoryAddressRange;
|
||||||
|
|
||||||
assert(this->hexViewerDataA.has_value());
|
assert(this->hexViewerDataA.has_value());
|
||||||
assert(this->hexViewerDataB.has_value());
|
assert(this->hexViewerDataB.has_value());
|
||||||
|
|
||||||
this->differentialHexViewerSharedState.differences.clear();
|
this->differentialHexViewerSharedState.differences.clear();
|
||||||
|
auto diffRanges = std::vector<TargetMemoryAddressRange>();
|
||||||
|
|
||||||
const auto& dataA = *(this->hexViewerDataA);
|
const auto& dataA = *(this->hexViewerDataA);
|
||||||
const auto& dataB = *(this->hexViewerDataB);
|
const auto& dataB = *(this->hexViewerDataB);
|
||||||
@@ -333,16 +370,32 @@ namespace Widgets
|
|||||||
};
|
};
|
||||||
|
|
||||||
const auto& memoryStartAddress = this->memoryDescriptor.addressRange.startAddress;
|
const auto& memoryStartAddress = this->memoryDescriptor.addressRange.startAddress;
|
||||||
|
auto lastDiffRange = std::optional<TargetMemoryAddressRange>();
|
||||||
|
|
||||||
for (Targets::TargetMemoryBuffer::size_type i = 0; i < dataA.size(); ++i) {
|
for (Targets::TargetMemoryBuffer::size_type i = 0; i < dataA.size(); ++i) {
|
||||||
const auto address = memoryStartAddress + static_cast<Targets::TargetMemoryAddress>(i);
|
const auto address = memoryStartAddress + static_cast<Targets::TargetMemoryAddress>(i);
|
||||||
|
|
||||||
if (dataA[i] != dataB[i] && !isAddressExcluded(address)) {
|
if (dataA[i] != dataB[i] && !isAddressExcluded(address)) {
|
||||||
this->differentialHexViewerSharedState.differences.insert(address);
|
this->differentialHexViewerSharedState.differences.insert(address);
|
||||||
|
|
||||||
|
if (lastDiffRange.has_value() && address > 0 && lastDiffRange->endAddress == (address - 1)) {
|
||||||
|
lastDiffRange->endAddress = address;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (lastDiffRange.has_value()) {
|
||||||
|
diffRanges.push_back(*lastDiffRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
lastDiffRange = TargetMemoryAddressRange(address, address);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto count = this->differentialHexViewerSharedState.differences.size();
|
if (lastDiffRange.has_value()) {
|
||||||
|
diffRanges.push_back(*lastDiffRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->changeListPane->setDiffRanges(diffRanges);
|
||||||
this->diffCountLabel->setText(
|
this->diffCountLabel->setText(
|
||||||
count == 0
|
count == 0
|
||||||
? "Contents are identical"
|
? "Contents are identical"
|
||||||
@@ -350,6 +403,17 @@ namespace Widgets
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SnapshotDiff::toggleChangeListPane() {
|
||||||
|
if (!this->changeListPane->state.activated) {
|
||||||
|
this->changeListPane->activate();
|
||||||
|
this->viewChangeListButton->setChecked(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->changeListPane->deactivate();
|
||||||
|
this->viewChangeListButton->setChecked(false);
|
||||||
|
}
|
||||||
|
|
||||||
void SnapshotDiff::setSyncHexViewerSettingsEnabled(bool enabled) {
|
void SnapshotDiff::setSyncHexViewerSettingsEnabled(bool enabled) {
|
||||||
this->settings.syncHexViewerSettings = enabled;
|
this->settings.syncHexViewerSettings = enabled;
|
||||||
this->syncHexViewerSettingsButton->setChecked(this->settings.syncHexViewerSettings);
|
this->syncHexViewerSettingsButton->setChecked(this->settings.syncHexViewerSettings);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "SnapshotDiffSettings.hpp"
|
#include "SnapshotDiffSettings.hpp"
|
||||||
|
|
||||||
|
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/PanelWidget.hpp"
|
||||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/SvgToolButton.hpp"
|
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/SvgToolButton.hpp"
|
||||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/Label.hpp"
|
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/Label.hpp"
|
||||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TaskProgressIndicator/TaskProgressIndicator.hpp"
|
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TaskProgressIndicator/TaskProgressIndicator.hpp"
|
||||||
@@ -17,6 +18,7 @@
|
|||||||
|
|
||||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemorySnapshot.hpp"
|
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemorySnapshot.hpp"
|
||||||
#include "DifferentialHexViewerWidget/DifferentialHexViewerWidget.hpp"
|
#include "DifferentialHexViewerWidget/DifferentialHexViewerWidget.hpp"
|
||||||
|
#include "ChangeListPane/ChangeListPane.hpp"
|
||||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ContextMenuAction.hpp"
|
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ContextMenuAction.hpp"
|
||||||
|
|
||||||
namespace Widgets
|
namespace Widgets
|
||||||
@@ -66,6 +68,14 @@ namespace Widgets
|
|||||||
SvgToolButton* syncHexViewerHoverButton = nullptr;
|
SvgToolButton* syncHexViewerHoverButton = nullptr;
|
||||||
SvgToolButton* syncHexViewerSelectionButton = nullptr;
|
SvgToolButton* syncHexViewerSelectionButton = nullptr;
|
||||||
|
|
||||||
|
QToolButton* viewChangeListButton = nullptr;
|
||||||
|
|
||||||
|
PanelWidget* leftPanel = nullptr;
|
||||||
|
PanelState leftPanelState = PanelState(300, true);
|
||||||
|
|
||||||
|
PaneState changeListPaneState = PaneState(true, true, std::nullopt);
|
||||||
|
ChangeListPane* changeListPane = nullptr;
|
||||||
|
|
||||||
QWidget* dataAContainer = nullptr;
|
QWidget* dataAContainer = nullptr;
|
||||||
QWidget* dataBContainer = nullptr;
|
QWidget* dataBContainer = nullptr;
|
||||||
|
|
||||||
@@ -108,6 +118,8 @@ namespace Widgets
|
|||||||
|
|
||||||
void refreshDifferences();
|
void refreshDifferences();
|
||||||
|
|
||||||
|
void toggleChangeListPane();
|
||||||
|
|
||||||
void setSyncHexViewerSettingsEnabled(bool enabled);
|
void setSyncHexViewerSettingsEnabled(bool enabled);
|
||||||
void setSyncHexViewerScrollEnabled(bool enabled);
|
void setSyncHexViewerScrollEnabled(bool enabled);
|
||||||
void setSyncHexViewerHoverEnabled(bool enabled);
|
void setSyncHexViewerHoverEnabled(bool enabled);
|
||||||
|
|||||||
@@ -41,6 +41,62 @@
|
|||||||
max-width: 1px;
|
max-width: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#snapshot-diff #lh-side-bar {
|
||||||
|
border-right: 1px solid #41423f;
|
||||||
|
}
|
||||||
|
|
||||||
|
#snapshot-diff #rh-side-bar {
|
||||||
|
border-left: 1px solid #41423f;
|
||||||
|
}
|
||||||
|
|
||||||
|
#snapshot-diff #lh-side-bar QToolButton,
|
||||||
|
#snapshot-diff #rh-side-bar QToolButton {
|
||||||
|
border: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#snapshot-diff #lh-side-bar #change-list-btn {
|
||||||
|
border: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#snapshot-diff #lh-side-bar #change-list-btn #label {
|
||||||
|
qproperty-bottomMargin: 1;
|
||||||
|
color: #999a9d;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#snapshot-diff #lh-side-bar #change-list-btn:hover {
|
||||||
|
background-color: #2F2F2D;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#snapshot-diff #lh-side-bar #change-list-btn:checked {
|
||||||
|
background-color: #2F2F2D;
|
||||||
|
}
|
||||||
|
|
||||||
|
#snapshot-diff #left-panel {
|
||||||
|
border-right: 1px solid #41423f;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ChangeListPane */
|
||||||
|
#change-list-pane #title-bar {
|
||||||
|
background-color: transparent;
|
||||||
|
border-bottom: 1px solid #41423f;
|
||||||
|
}
|
||||||
|
|
||||||
|
#change-list-pane #title-bar #change-list-title-label {
|
||||||
|
color: #8a8a8d;
|
||||||
|
}
|
||||||
|
|
||||||
|
#change-list-pane QScrollBar {
|
||||||
|
margin: 0;
|
||||||
|
padding: 1px 0 0 6px;
|
||||||
|
width: 14px;
|
||||||
|
border-left: 1px solid #41423f;
|
||||||
|
}
|
||||||
|
|
||||||
#snapshot-diff #data-details-container {
|
#snapshot-diff #data-details-container {
|
||||||
border-bottom: 1px solid #41423f;
|
border-bottom: 1px solid #41423f;
|
||||||
color: #8a8a8d;
|
color: #8a8a8d;
|
||||||
|
|||||||
@@ -134,6 +134,116 @@
|
|||||||
<property name="margin">
|
<property name="margin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
|
<item alignment="Qt::AlignLeft">
|
||||||
|
<widget class="QWidget" name="lh-side-bar">
|
||||||
|
<property name="minimumWidth">
|
||||||
|
<number>23</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximumWidth">
|
||||||
|
<number>23</number>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Expanding"/>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="lh-side-bar-layout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="margin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<spacer name="vertical-spacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item alignment="Qt::AlignLeft">
|
||||||
|
<widget class="QToolButton" name="change-list-btn">
|
||||||
|
<property name="minimumWidth">
|
||||||
|
<number>22</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximumWidth">
|
||||||
|
<number>22</number>
|
||||||
|
</property>
|
||||||
|
<property name="minimumHeight">
|
||||||
|
<number>108</number>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>View differences</string>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<layout class="QVBoxLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="margin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<spacer name="vertical-spacer">
|
||||||
|
<property name="sizeHint">
|
||||||
|
<size>
|
||||||
|
<height>10</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item alignment="Qt::AlignTop">
|
||||||
|
<widget class="RotatableLabel" name="label">
|
||||||
|
<property name="angle">
|
||||||
|
<number>270</number>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Differences</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="vertical-spacer">
|
||||||
|
<property name="sizeHint">
|
||||||
|
<size>
|
||||||
|
<height>2</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item alignment="Qt::AlignTop">
|
||||||
|
<widget class="SvgWidget" name="icon">
|
||||||
|
<property name="containerHeight">
|
||||||
|
<number>15</number>
|
||||||
|
</property>
|
||||||
|
<property name="containerWidth">
|
||||||
|
<number>22</number>
|
||||||
|
</property>
|
||||||
|
<property name="svgFilePath">
|
||||||
|
<string>:/compiled/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/Images/view-change-list-icon.svg</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="vertical-spacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QWidget" name="data-a-container">
|
<widget class="QWidget" name="data-a-container">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@@ -280,6 +390,35 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item alignment="Qt::AlignLeft">
|
||||||
|
<widget class="QWidget" name="rh-side-bar">
|
||||||
|
<property name="minimumWidth">
|
||||||
|
<number>23</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximumWidth">
|
||||||
|
<number>23</number>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Expanding"/>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="rh-side-bar-layout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="margin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<spacer name="vertical-spacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<!-- Button items here -->
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
Reference in New Issue
Block a user