mirror of
https://github.com/epasveer/seer.git
synced 2026-08-29 16:40:42 +08:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 62596d3234 | |||
| afa4d70072 | |||
| 5183339a2b | |||
| fe6fa48306 | |||
| 41f78b68da | |||
| 0c876d0c92 | |||
| 42bcc76aa4 | |||
| 93b569191c | |||
| aa74c16edf | |||
| 5d030042d5 | |||
| afc8c188c5 | |||
| ddc7245125 | |||
| bd04ef3199 | |||
| 23df8207d8 | |||
| d54df0b1b3 |
@@ -115,6 +115,7 @@ set(HEADER_FILES
|
|||||||
SeerParallelStacksVisualizerWidget.h
|
SeerParallelStacksVisualizerWidget.h
|
||||||
SeerParallelStacksGraphicsView.h
|
SeerParallelStacksGraphicsView.h
|
||||||
SeerParallelStacksCommon.h
|
SeerParallelStacksCommon.h
|
||||||
|
SeerParallelStacksSettingsDialog.h
|
||||||
SeerGdbMonitorWidget.h
|
SeerGdbMonitorWidget.h
|
||||||
SeerRegisterValuesBrowserWidget.h
|
SeerRegisterValuesBrowserWidget.h
|
||||||
SeerRegisterEditValueDialog.h
|
SeerRegisterEditValueDialog.h
|
||||||
@@ -233,6 +234,7 @@ set(SOURCE_FILES
|
|||||||
SeerParallelStacksVisualizerWidget.cpp
|
SeerParallelStacksVisualizerWidget.cpp
|
||||||
SeerParallelStacksGraphicsView.cpp
|
SeerParallelStacksGraphicsView.cpp
|
||||||
SeerParallelStacksCommon.cpp
|
SeerParallelStacksCommon.cpp
|
||||||
|
SeerParallelStacksSettingsDialog.cpp
|
||||||
SeerGdbMonitorWidget.cpp
|
SeerGdbMonitorWidget.cpp
|
||||||
SeerRegisterValuesBrowserWidget.cpp
|
SeerRegisterValuesBrowserWidget.cpp
|
||||||
SeerRegisterEditValueDialog.cpp
|
SeerRegisterEditValueDialog.cpp
|
||||||
|
|||||||
+31
-1
@@ -9,6 +9,7 @@
|
|||||||
#include <QtGui/QImageReader>
|
#include <QtGui/QImageReader>
|
||||||
#include <QtGui/QImageWriter>
|
#include <QtGui/QImageWriter>
|
||||||
#include <QtGui/QPainter>
|
#include <QtGui/QPainter>
|
||||||
|
#include <QtGui/QWheelEvent>
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QtPrintSupport/QPrintDialog>
|
#include <QtPrintSupport/QPrintDialog>
|
||||||
|
|
||||||
@@ -19,6 +20,8 @@
|
|||||||
|
|
||||||
QImageViewer::QImageViewer (QWidget* parent) : QWidget(parent) {
|
QImageViewer::QImageViewer (QWidget* parent) : QWidget(parent) {
|
||||||
|
|
||||||
|
setFocusPolicy(Qt::StrongFocus); // So the widget can take focus and receive the +/-/ESC zoom keys.
|
||||||
|
|
||||||
_zoomFactor = 1.0;
|
_zoomFactor = 1.0;
|
||||||
|
|
||||||
// Setup the widgets
|
// Setup the widgets
|
||||||
@@ -34,6 +37,10 @@ QImageViewer::QImageViewer (QWidget* parent) : QWidget(parent) {
|
|||||||
_scrollArea->setWidget(_imageLabel);
|
_scrollArea->setWidget(_imageLabel);
|
||||||
_scrollArea->setWidgetResizable(false);
|
_scrollArea->setWidgetResizable(false);
|
||||||
|
|
||||||
|
// The scroll area consumes wheel events for scrolling, so watch its
|
||||||
|
// viewport to catch Ctrl+wheel for zooming.
|
||||||
|
_scrollArea->viewport()->installEventFilter(this);
|
||||||
|
|
||||||
layout->addWidget(_scrollArea);
|
layout->addWidget(_scrollArea);
|
||||||
|
|
||||||
clearImage();
|
clearImage();
|
||||||
@@ -174,7 +181,30 @@ void QImageViewer::keyPressEvent (QKeyEvent* event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QImageViewer::enterEvent (QEvent* event) {
|
bool QImageViewer::eventFilter (QObject* object, QEvent* event) {
|
||||||
|
|
||||||
|
// Ctrl+wheel over the image zooms in or out. A plain wheel keeps
|
||||||
|
// scrolling the image as usual.
|
||||||
|
if (object == _scrollArea->viewport() && event->type() == QEvent::Wheel) {
|
||||||
|
|
||||||
|
QWheelEvent* wheelEvent = static_cast<QWheelEvent*>(event);
|
||||||
|
|
||||||
|
if (wheelEvent->modifiers() & Qt::ControlModifier) {
|
||||||
|
|
||||||
|
if (wheelEvent->angleDelta().y() > 0) {
|
||||||
|
zoomIn();
|
||||||
|
}else if (wheelEvent->angleDelta().y() < 0) {
|
||||||
|
zoomOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QWidget::eventFilter(object, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QImageViewer::enterEvent (QEnterEvent* event) {
|
||||||
|
|
||||||
Q_UNUSED(event);
|
Q_UNUSED(event);
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -38,8 +38,9 @@ class QImageViewer : public QWidget {
|
|||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void keyPressEvent (QKeyEvent* event);
|
void keyPressEvent (QKeyEvent* event);
|
||||||
void enterEvent (QEvent* event);
|
bool eventFilter (QObject* object, QEvent* event) override;
|
||||||
void leaveEvent (QEvent* event);
|
void enterEvent (QEnterEvent* event) override;
|
||||||
|
void leaveEvent (QEvent* event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QImage _image;
|
QImage _image;
|
||||||
|
|||||||
@@ -398,7 +398,10 @@ void SeerArrayVisualizerWidget::handleText (const QString& text) {
|
|||||||
|
|
||||||
//qDebug() << text;
|
//qDebug() << text;
|
||||||
|
|
||||||
if (text.contains(QRegularExpression("^([0-9]+)\\^done,value="))) {
|
static const QRegularExpression valueResponse = QRegularExpression("^([0-9]+)\\^done,value=");
|
||||||
|
static const QRegularExpression memoryResponse = QRegularExpression("^([0-9]+)\\^done,memory=");
|
||||||
|
static const QRegularExpression errorResponse = QRegularExpression("^([0-9]+)\\^error,msg=");
|
||||||
|
if (text.contains(valueResponse)) {
|
||||||
|
|
||||||
// 11^done,value="1"
|
// 11^done,value="1"
|
||||||
// 11^done,value="0x7fffffffd538"
|
// 11^done,value="0x7fffffffd538"
|
||||||
@@ -527,7 +530,7 @@ void SeerArrayVisualizerWidget::handleText (const QString& text) {
|
|||||||
handlebRefreshButton();
|
handlebRefreshButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
}else if (text.contains(QRegularExpression("^([0-9]+)\\^done,memory="))) {
|
}else if (text.contains(memoryResponse)) {
|
||||||
|
|
||||||
// 3^done,memory=[{begin="0x0000000000613e70",offset="0x0000000000000000",end="0x0000000000613e71",contents="00"}]
|
// 3^done,memory=[{begin="0x0000000000613e70",offset="0x0000000000000000",end="0x0000000000613e71",contents="00"}]
|
||||||
// 4^done,memory=[{begin="0x0000000000613e70",offset="0x0000000000000000",end="0x0000000000613ed4",contents="000000000000000000000000"}]
|
// 4^done,memory=[{begin="0x0000000000613e70",offset="0x0000000000000000",end="0x0000000000613ed4",contents="000000000000000000000000"}]
|
||||||
@@ -632,7 +635,7 @@ void SeerArrayVisualizerWidget::handleText (const QString& text) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}else if (text.contains(QRegularExpression("^([0-9]+)\\^error,msg="))) {
|
}else if (text.contains(errorResponse)) {
|
||||||
|
|
||||||
// 12^error,msg="No symbol \"return\" in current context."
|
// 12^error,msg="No symbol \"return\" in current context."
|
||||||
// 13^error,msg="No symbol \"cout\" in current context."
|
// 13^error,msg="No symbol \"cout\" in current context."
|
||||||
|
|||||||
@@ -439,7 +439,7 @@ int SeerEditorWidgetAssemblyArea::miniMapAreaWidth () {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 120;
|
return 80;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SeerEditorWidgetAssemblyArea::offsetAreaWidth () {
|
int SeerEditorWidgetAssemblyArea::offsetAreaWidth () {
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ int SeerEditorWidgetSourceArea::miniMapAreaWidth () {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 120;
|
return 80;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SeerEditorWidgetSourceArea::updateLineNumberArea (const QRect& rect, int dy) {
|
void SeerEditorWidgetSourceArea::updateLineNumberArea (const QRect& rect, int dy) {
|
||||||
|
|||||||
@@ -43,6 +43,15 @@ const QString& SeerParallelStacksFrame::function () const {
|
|||||||
return _function;
|
return _function;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString SeerParallelStacksFrame::functionOrAddr () const {
|
||||||
|
|
||||||
|
if (_function == "??") {
|
||||||
|
return _addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _function;
|
||||||
|
}
|
||||||
|
|
||||||
const QString& SeerParallelStacksFrame::arch () const {
|
const QString& SeerParallelStacksFrame::arch () const {
|
||||||
return _arch;
|
return _arch;
|
||||||
}
|
}
|
||||||
@@ -206,19 +215,26 @@ SeerParallelStacksStack SeerParallelStacksFillStack(const SeerParallelStacksNode
|
|||||||
stack.threadIds.append(t.id());
|
stack.threadIds.append(t.id());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.function.function().isEmpty() == false) {
|
|
||||||
stack.frames.append(node.function);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.children.size() == 1) {
|
if (node.children.size() == 1) {
|
||||||
// Merge single child into this stack (chain of frames).
|
// Merge single child into this stack (chain of frames).
|
||||||
// Keep the IDs from the leaf (most specific) node.
|
// Keep the IDs from the leaf (most specific) node.
|
||||||
|
// Children are deeper (more toward the top of the call stack) than
|
||||||
|
// this node, so their frames go first — the resulting list reads
|
||||||
|
// top of stack (innermost) to bottom of stack (outermost).
|
||||||
auto child = SeerParallelStacksFillStack(node.children[0]);
|
auto child = SeerParallelStacksFillStack(node.children[0]);
|
||||||
stack.frames += child.frames;
|
stack.frames = child.frames;
|
||||||
stack.stacks = child.stacks;
|
stack.stacks = child.stacks;
|
||||||
stack.threadCount = child.threadCount;
|
stack.threadCount = child.threadCount;
|
||||||
stack.threadIds = child.threadIds;
|
stack.threadIds = child.threadIds;
|
||||||
|
|
||||||
|
if (node.function.function().isEmpty() == false) {
|
||||||
|
stack.frames.append(node.function);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (node.function.function().isEmpty() == false) {
|
||||||
|
stack.frames.append(node.function);
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& childNode : node.children) {
|
for (const auto& childNode : node.children) {
|
||||||
stack.stacks.append(SeerParallelStacksFillStack(childNode));
|
stack.stacks.append(SeerParallelStacksFillStack(childNode));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ class SeerParallelStacksFrame {
|
|||||||
int level () const;
|
int level () const;
|
||||||
const QString& addr () const;
|
const QString& addr () const;
|
||||||
const QString& function () const;
|
const QString& function () const;
|
||||||
|
QString functionOrAddr () const;
|
||||||
const QString& arch () const;
|
const QString& arch () const;
|
||||||
const QString& from () const;
|
const QString& from () const;
|
||||||
const QString& file () const;
|
const QString& file () const;
|
||||||
|
|||||||
@@ -87,6 +87,12 @@ SeerParallelStacksStackBoxItem::SeerParallelStacksStackBoxItem(const SeerParalle
|
|||||||
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
|
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
|
||||||
setAcceptHoverEvents(true);
|
setAcceptHoverEvents(true);
|
||||||
|
|
||||||
|
_hoverTimer = new QTimer(this);
|
||||||
|
_hoverTimer->setSingleShot(true);
|
||||||
|
_hoverTimer->setInterval(_kHoverDelayMs);
|
||||||
|
|
||||||
|
QObject::connect(_hoverTimer, &QTimer::timeout, this, &SeerParallelStacksStackBoxItem::handleShowPopup);
|
||||||
|
|
||||||
_headerLeft = QString("%1 Thread%2") .arg(stack.threadCount) .arg(stack.threadCount == 1 ? "" : "s");
|
_headerLeft = QString("%1 Thread%2") .arg(stack.threadCount) .arg(stack.threadCount == 1 ? "" : "s");
|
||||||
|
|
||||||
_threadIds.resize(0);
|
_threadIds.resize(0);
|
||||||
@@ -118,15 +124,15 @@ SeerParallelStacksStackBoxItem::SeerParallelStacksStackBoxItem(const SeerParalle
|
|||||||
QFont normFont;
|
QFont normFont;
|
||||||
QFontMetrics normFm(normFont);
|
QFontMetrics normFm(normFont);
|
||||||
|
|
||||||
qreal headerW = boldFm.horizontalAdvance(_headerLeft) + boldFm.horizontalAdvance(_headerRight) + kHeaderGap;
|
qreal headerW = boldFm.horizontalAdvance(_headerLeft) + boldFm.horizontalAdvance(_headerRight) + _kHeaderGap;
|
||||||
qreal maxTextW = headerW;
|
qreal maxTextW = headerW;
|
||||||
|
|
||||||
for (const auto& frame : _stack.frames) {
|
for (const auto& frame : _stack.frames) {
|
||||||
maxTextW = std::max(maxTextW, (qreal)normFm.horizontalAdvance(frame.function()));
|
maxTextW = std::max(maxTextW, (qreal)normFm.horizontalAdvance(frame.functionOrAddr()));
|
||||||
}
|
}
|
||||||
|
|
||||||
_width = maxTextW + 2 * kPadX;
|
_width = maxTextW + 2 * _kPadX;
|
||||||
_height = kPadY + kRowH * (1 + (int)_stack.frames.size()) + kPadY;
|
_height = _kPadY + _kRowH * (1 + (int)_stack.frames.size()) + _kPadY;
|
||||||
|
|
||||||
qDebug() << _stack.stacks.size();
|
qDebug() << _stack.stacks.size();
|
||||||
}
|
}
|
||||||
@@ -163,19 +169,19 @@ void SeerParallelStacksStackBoxItem::paint(QPainter* painter, const QStyleOption
|
|||||||
|
|
||||||
QFont boldFont; boldFont.setBold(true);
|
QFont boldFont; boldFont.setBold(true);
|
||||||
QFont normFont;
|
QFont normFont;
|
||||||
const qreal innerW = _width - 2 * kPadX;
|
const qreal innerW = _width - 2 * _kPadX;
|
||||||
qreal y = kPadY;
|
qreal y = _kPadY;
|
||||||
|
|
||||||
painter->setFont(boldFont);
|
painter->setFont(boldFont);
|
||||||
painter->setPen(colors.headerText);
|
painter->setPen(colors.headerText);
|
||||||
painter->drawText(QRectF(kPadX, y, innerW, kRowH), Qt::AlignLeft | Qt::AlignVCenter, _headerLeft);
|
painter->drawText(QRectF(_kPadX, y, innerW, _kRowH), Qt::AlignLeft | Qt::AlignVCenter, _headerLeft);
|
||||||
|
|
||||||
if (!_headerRight.isEmpty()) {
|
if (!_headerRight.isEmpty()) {
|
||||||
painter->setPen(colors.threadIdsText);
|
painter->setPen(colors.threadIdsText);
|
||||||
painter->drawText(QRectF(kPadX, y, innerW, kRowH), Qt::AlignRight | Qt::AlignVCenter, _headerRight);
|
painter->drawText(QRectF(_kPadX, y, innerW, _kRowH), Qt::AlignRight | Qt::AlignVCenter, _headerRight);
|
||||||
}
|
}
|
||||||
|
|
||||||
y += kRowH;
|
y += _kRowH;
|
||||||
|
|
||||||
painter->setPen(QPen(colors.divider, 1));
|
painter->setPen(QPen(colors.divider, 1));
|
||||||
painter->drawLine(QPointF(0, y), QPointF(_width, y));
|
painter->drawLine(QPointF(0, y), QPointF(_width, y));
|
||||||
@@ -184,8 +190,8 @@ void SeerParallelStacksStackBoxItem::paint(QPainter* painter, const QStyleOption
|
|||||||
painter->setPen(colors.frameText);
|
painter->setPen(colors.frameText);
|
||||||
|
|
||||||
for (const auto& frame : _stack.frames) {
|
for (const auto& frame : _stack.frames) {
|
||||||
painter->drawText(QRectF(kPadX, y, innerW, kRowH), Qt::AlignLeft | Qt::AlignVCenter, frame.function());
|
painter->drawText(QRectF(_kPadX, y, innerW, _kRowH), Qt::AlignLeft | Qt::AlignVCenter, frame.functionOrAddr());
|
||||||
y += kRowH;
|
y += _kRowH;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_dragging) {
|
if (_dragging) {
|
||||||
@@ -269,37 +275,82 @@ void SeerParallelStacksStackBoxItem::hoverEnterEvent(QGraphicsSceneHoverEvent* e
|
|||||||
QGraphicsItem::hoverEnterEvent(event);
|
QGraphicsItem::hoverEnterEvent(event);
|
||||||
|
|
||||||
if (_popup == nullptr) {
|
if (_popup == nullptr) {
|
||||||
|
_hoverTimer->start();
|
||||||
QString frame;
|
|
||||||
|
|
||||||
if (_stack.frames.size() > 0) {
|
|
||||||
frame = _stack.frames[0].function();
|
|
||||||
}
|
|
||||||
|
|
||||||
_popup = new SeerParallelStacksPopupTableWidget();
|
|
||||||
|
|
||||||
for (const auto& id : _threadIds) {
|
|
||||||
_popup->addRow(id, frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
QGraphicsView* view = scene()->views().first(); // scene() is always valid here
|
|
||||||
|
|
||||||
// Position below the item, aligned to its left edge
|
|
||||||
QRectF sceneRect = mapToScene(boundingRect()).boundingRect();
|
|
||||||
QPoint viewportPt = view->mapFromScene(sceneRect.bottomLeft());
|
|
||||||
QPoint globalPt = view->viewport()->mapToGlobal(viewportPt);
|
|
||||||
_popup->move(globalPt);
|
|
||||||
|
|
||||||
_popup->show();
|
|
||||||
|
|
||||||
// Connect things.
|
|
||||||
QObject::connect(_popup, &SeerParallelStacksPopupTableWidget::mouseLeftPopup, this, &SeerParallelStacksStackBoxItem::handleDeletePopup);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SeerParallelStacksStackBoxItem::hoverLeaveEvent(QGraphicsSceneHoverEvent* event) {
|
void SeerParallelStacksStackBoxItem::hoverLeaveEvent(QGraphicsSceneHoverEvent* event) {
|
||||||
|
|
||||||
QGraphicsItem::hoverLeaveEvent(event);
|
QGraphicsItem::hoverLeaveEvent(event);
|
||||||
|
|
||||||
|
// Cancel a pending popup if the mouse left before the delay elapsed.
|
||||||
|
_hoverTimer->stop();
|
||||||
|
|
||||||
|
// A popup that's already showing stays up if the mouse just moved onto
|
||||||
|
// it — give handleMaybeClosePopup() a moment to check for that.
|
||||||
|
handleMaybeClosePopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect SeerParallelStacksStackBoxItem::globalRect() const {
|
||||||
|
|
||||||
|
QGraphicsView* view = scene()->views().first(); // scene() is always valid here
|
||||||
|
|
||||||
|
QRectF sceneRect = mapToScene(boundingRect()).boundingRect();
|
||||||
|
QPoint topLeft = view->viewport()->mapToGlobal(view->mapFromScene(sceneRect.topLeft()));
|
||||||
|
QPoint bottomRight = view->viewport()->mapToGlobal(view->mapFromScene(sceneRect.bottomRight()));
|
||||||
|
|
||||||
|
return QRect(topLeft, bottomRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SeerParallelStacksStackBoxItem::handleShowPopup() {
|
||||||
|
|
||||||
|
if (_popup != nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString frame;
|
||||||
|
|
||||||
|
if (_stack.frames.size() > 0) {
|
||||||
|
frame = _stack.frames[0].functionOrAddr();
|
||||||
|
}
|
||||||
|
|
||||||
|
_popup = new SeerParallelStacksPopupTableWidget();
|
||||||
|
|
||||||
|
for (const auto& id : _threadIds) {
|
||||||
|
_popup->addRow(id, frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Position below the item, aligned to its left edge
|
||||||
|
_popup->move(globalRect().bottomLeft());
|
||||||
|
|
||||||
|
_popup->show();
|
||||||
|
|
||||||
|
QObject::connect(_popup, &SeerParallelStacksPopupTableWidget::mouseLeftPopup, this, &SeerParallelStacksStackBoxItem::handleMaybeClosePopup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SeerParallelStacksStackBoxItem::handleMaybeClosePopup() {
|
||||||
|
|
||||||
|
if (_popup == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The mouse may have simply crossed from the node onto the popup (or
|
||||||
|
// vice versa) — give that a moment to register before deciding the
|
||||||
|
// mouse has truly left both, then re-check with the cursor's live
|
||||||
|
// position rather than relying on possibly-stale hover state.
|
||||||
|
QTimer::singleShot(_kCloseGraceMs, this, [this]() {
|
||||||
|
|
||||||
|
if (_popup == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool overNode = globalRect().contains(QCursor::pos());
|
||||||
|
bool overPopup = _popup->frameGeometry().contains(QCursor::pos());
|
||||||
|
|
||||||
|
if (overNode == false && overPopup == false) {
|
||||||
|
handleDeletePopup();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void SeerParallelStacksStackBoxItem::handleDeletePopup() {
|
void SeerParallelStacksStackBoxItem::handleDeletePopup() {
|
||||||
@@ -358,7 +409,7 @@ QRectF SeerParallelStacksLiveEdge::boundingRect() const {
|
|||||||
QPointF f = _from->sceneBottom();
|
QPointF f = _from->sceneBottom();
|
||||||
QPointF t = _to->sceneTop();
|
QPointF t = _to->sceneTop();
|
||||||
|
|
||||||
qreal pad = kArrow + kVCtrl + 4;
|
qreal pad = _kArrow + _kVCtrl + 4;
|
||||||
|
|
||||||
return QRectF(f, t).normalized().adjusted(-pad, -pad, pad, pad);
|
return QRectF(f, t).normalized().adjusted(-pad, -pad, pad, pad);
|
||||||
}
|
}
|
||||||
@@ -382,39 +433,8 @@ void SeerParallelStacksLiveEdge::paint(QPainter* painter, const QStyleOptionGrap
|
|||||||
QPointF from = _from->sceneBottom();
|
QPointF from = _from->sceneBottom();
|
||||||
QPointF to = _to->sceneTop();
|
QPointF to = _to->sceneTop();
|
||||||
|
|
||||||
/*
|
|
||||||
// Bezier: control points pull vertically toward each other
|
|
||||||
QPainterPath path;
|
|
||||||
path.moveTo(from);
|
|
||||||
path.cubicTo(from + QPointF(0, kVCtrl), to + QPointF(0, -kVCtrl), to);
|
|
||||||
|
|
||||||
painter->setPen(QPen(QColor(0x55, 0x55, 0x55), 1.5));
|
|
||||||
painter->setBrush(Qt::NoBrush);
|
|
||||||
painter->drawPath(path);
|
|
||||||
|
|
||||||
// Arrowhead at `to` pointing downward (into the parent box)
|
|
||||||
// The tangent direction at the end of the cubic is (to - cp2)
|
|
||||||
QPointF cp2 = to + QPointF(0, -kVCtrl);
|
|
||||||
QPointF dir = to - cp2;
|
|
||||||
double len = std::hypot(dir.x(), dir.y());
|
|
||||||
if (len < 1e-6) return;
|
|
||||||
dir /= len; // normalise
|
|
||||||
|
|
||||||
// Perpendicular
|
|
||||||
QPointF perp(-dir.y(), dir.x());
|
|
||||||
|
|
||||||
QPointF a1 = to - dir * kArrow + perp * (kArrow * 0.5);
|
|
||||||
QPointF a2 = to - dir * kArrow - perp * (kArrow * 0.5);
|
|
||||||
|
|
||||||
QPolygonF arrowHead;
|
|
||||||
arrowHead << to << a1 << a2;
|
|
||||||
painter->setPen(Qt::NoPen);
|
|
||||||
painter->setBrush(QColor(0x55, 0x55, 0x55));
|
|
||||||
painter->drawPolygon(arrowHead);
|
|
||||||
*/
|
|
||||||
|
|
||||||
// --- Arrowhead: tip touches the child box bottom (`from`),
|
// --- Arrowhead: tip touches the child box bottom (`from`),
|
||||||
// base is kArrow further along toward `to`.
|
// base is _kArrow further along toward `to`.
|
||||||
// The bezier starts at the base so the line never overlaps the head.
|
// The bezier starts at the base so the line never overlaps the head.
|
||||||
QPointF delta = to - from;
|
QPointF delta = to - from;
|
||||||
double len = std::hypot(delta.x(), delta.y());
|
double len = std::hypot(delta.x(), delta.y());
|
||||||
@@ -425,16 +445,16 @@ void SeerParallelStacksLiveEdge::paint(QPainter* painter, const QStyleOptionGrap
|
|||||||
QPointF perp(-dir.y(), dir.x()); // perpendicular
|
QPointF perp(-dir.y(), dir.x()); // perpendicular
|
||||||
|
|
||||||
QPointF tip = from; // touches child box
|
QPointF tip = from; // touches child box
|
||||||
QPointF base = from + dir * kArrow; // where the line begins
|
QPointF base = from + dir * _kArrow; // where the line begins
|
||||||
|
|
||||||
QPointF a1 = base + perp * (kArrow * 0.5);
|
QPointF a1 = base + perp * (_kArrow * 0.5);
|
||||||
QPointF a2 = base - perp * (kArrow * 0.5);
|
QPointF a2 = base - perp * (_kArrow * 0.5);
|
||||||
|
|
||||||
// Bezier runs from the arrowhead base to the parent box top.
|
// Bezier runs from the arrowhead base to the parent box top.
|
||||||
QPainterPath path;
|
QPainterPath path;
|
||||||
|
|
||||||
path.moveTo(base);
|
path.moveTo(base);
|
||||||
path.cubicTo(base + QPointF(0, kVCtrl), to + QPointF(0, -kVCtrl), to);
|
path.cubicTo(base + QPointF(0, _kVCtrl), to + QPointF(0, -_kVCtrl), to);
|
||||||
|
|
||||||
const QColor color = edgeColor();
|
const QColor color = edgeColor();
|
||||||
|
|
||||||
@@ -641,15 +661,6 @@ SeerParallelStacksPopupTableWidget::SeerParallelStacksPopupTableWidget(QWidget*
|
|||||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||||
layout->setContentsMargins(6, 6, 6, 6);
|
layout->setContentsMargins(6, 6, 6, 6);
|
||||||
layout->addWidget(_table);
|
layout->addWidget(_table);
|
||||||
|
|
||||||
_closeTimer = new QTimer(this);
|
|
||||||
_closeTimer->setSingleShot(true); // Ensures it only fires once
|
|
||||||
_closeTimer->setInterval(1500); // Delay
|
|
||||||
|
|
||||||
// Connect things.
|
|
||||||
QObject::connect(_closeTimer, &QTimer::timeout, this, &SeerParallelStacksPopupTableWidget::handleCloseTimer);
|
|
||||||
|
|
||||||
_closeTimer->start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SeerParallelStacksPopupTableWidget::addRow (int threadid, const QString& frame) {
|
void SeerParallelStacksPopupTableWidget::addRow (int threadid, const QString& frame) {
|
||||||
@@ -673,31 +684,13 @@ void SeerParallelStacksPopupTableWidget::addRow (int threadid, const QString& fr
|
|||||||
_table->resizeColumnToContents(1);
|
_table->resizeColumnToContents(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SeerParallelStacksPopupTableWidget::enterEvent(QEnterEvent* event) {
|
|
||||||
|
|
||||||
// If the user moves the cursor into the table, cancel the timer.
|
|
||||||
if (_closeTimer->isActive()) {
|
|
||||||
_closeTimer->stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
QFrame::enterEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SeerParallelStacksPopupTableWidget::leaveEvent(QEvent* event) {
|
void SeerParallelStacksPopupTableWidget::leaveEvent(QEvent* event) {
|
||||||
|
|
||||||
// If the user leaves the table, ask for the table to be closed.
|
|
||||||
QFrame::leaveEvent(event);
|
QFrame::leaveEvent(event);
|
||||||
|
|
||||||
emit mouseLeftPopup();
|
emit mouseLeftPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SeerParallelStacksPopupTableWidget::handleCloseTimer() {
|
|
||||||
|
|
||||||
// If the user doesn't move the cursor into the table in the default time,
|
|
||||||
// ask the table to be closed.
|
|
||||||
emit mouseLeftPopup();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ================================================================
|
// ================================================================
|
||||||
// SeerParallelStacksPopupTableWidget
|
// SeerParallelStacksPopupTableWidget
|
||||||
// ================================================================
|
// ================================================================
|
||||||
|
|||||||
@@ -52,26 +52,32 @@ class SeerParallelStacksStackBoxItem : public QObject, public QGraphicsItem {
|
|||||||
void hoverLeaveEvent (QGraphicsSceneHoverEvent* event) override;
|
void hoverLeaveEvent (QGraphicsSceneHoverEvent* event) override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleDeletePopup ();
|
void handleDeletePopup ();
|
||||||
|
void handleShowPopup ();
|
||||||
|
void handleMaybeClosePopup ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Global (screen) rect this box occupies, used to test whether the
|
||||||
|
// cursor is still over the node.
|
||||||
|
QRect globalRect () const;
|
||||||
|
|
||||||
|
QVector<SeerParallelStacksLiveEdge*> _edges; // non-owning
|
||||||
QVector<int> _threadIds;
|
QVector<int> _threadIds;
|
||||||
SeerParallelStacksStack _stack;
|
SeerParallelStacksStack _stack;
|
||||||
QString _headerLeft;
|
QString _headerLeft;
|
||||||
QString _headerRight;
|
QString _headerRight;
|
||||||
qreal _width = 0;
|
qreal _width = 0;
|
||||||
qreal _height = 0;
|
qreal _height = 0;
|
||||||
SeerParallelStacksPopupTableWidget* _popup = 0;
|
SeerParallelStacksPopupTableWidget* _popup = 0;
|
||||||
|
QTimer* _hoverTimer = 0;
|
||||||
bool _dragging = false;
|
static constexpr int _kHoverDelayMs = 1000;
|
||||||
|
static constexpr int _kCloseGraceMs = 150;
|
||||||
|
bool _dragging = false;
|
||||||
QPointF _dragOffset;
|
QPointF _dragOffset;
|
||||||
|
static constexpr qreal _kPadX = 12;
|
||||||
QVector<SeerParallelStacksLiveEdge*> _edges; // non-owning
|
static constexpr qreal _kPadY = 8;
|
||||||
|
static constexpr qreal _kRowH = 20;
|
||||||
static constexpr qreal kPadX = 12;
|
static constexpr qreal _kHeaderGap = 16;
|
||||||
static constexpr qreal kPadY = 8;
|
|
||||||
static constexpr qreal kRowH = 20;
|
|
||||||
static constexpr qreal kHeaderGap = 16;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
@@ -82,7 +88,7 @@ class SeerParallelStacksLiveEdge : public QGraphicsItem {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
SeerParallelStacksLiveEdge(SeerParallelStacksStackBoxItem* from, SeerParallelStacksStackBoxItem* to, QGraphicsItem* parent = nullptr);
|
SeerParallelStacksLiveEdge(SeerParallelStacksStackBoxItem* from, SeerParallelStacksStackBoxItem* to, QGraphicsItem* parent = nullptr);
|
||||||
~SeerParallelStacksLiveEdge() override;
|
~SeerParallelStacksLiveEdge() override;
|
||||||
|
|
||||||
QRectF boundingRect () const override;
|
QRectF boundingRect () const override;
|
||||||
QPainterPath shape () const override;
|
QPainterPath shape () const override;
|
||||||
@@ -95,11 +101,11 @@ class SeerParallelStacksLiveEdge : public QGraphicsItem {
|
|||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SeerParallelStacksStackBoxItem* _from; // child (bottom anchor)
|
SeerParallelStacksStackBoxItem* _from; // child (bottom anchor)
|
||||||
SeerParallelStacksStackBoxItem* _to; // parent (top anchor)
|
SeerParallelStacksStackBoxItem* _to; // parent (top anchor)
|
||||||
|
|
||||||
static constexpr qreal kArrow = 8.0;
|
static constexpr qreal _kArrow = 8.0;
|
||||||
static constexpr qreal kVCtrl = 60.0 * 0.4; // bezier control-point stretch
|
static constexpr qreal _kVCtrl = 60.0 * 0.4; // bezier control-point stretch
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -142,7 +148,8 @@ class SeerParallelStacksMiniMapWidget : public QWidget {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// A frameless popup window that wraps a QTableWidget inside a small
|
// A frameless popup window that wraps a QTableWidget inside a small
|
||||||
// bordered frame, and closes/deletes itself when the mouse leaves it.
|
// bordered frame. Its lifetime is owned by the SeerParallelStacksStackBoxItem
|
||||||
|
// that created it — it stays up for as long as the mouse is in that node.
|
||||||
class SeerParallelStacksPopupTableWidget : public QFrame {
|
class SeerParallelStacksPopupTableWidget : public QFrame {
|
||||||
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -153,18 +160,13 @@ class SeerParallelStacksPopupTableWidget : public QFrame {
|
|||||||
void addRow (int threadid, const QString& function);
|
void addRow (int threadid, const QString& function);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void enterEvent (QEnterEvent* event) override;
|
|
||||||
void leaveEvent (QEvent* event) override;
|
void leaveEvent (QEvent* event) override;
|
||||||
|
|
||||||
protected slots:
|
|
||||||
void handleCloseTimer ();
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void mouseLeftPopup ();
|
void mouseLeftPopup ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QTableWidget* _table;
|
QTableWidget* _table;
|
||||||
QTimer* _closeTimer;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SeerParallelStacksGraphicsView : public QGraphicsView {
|
class SeerParallelStacksGraphicsView : public QGraphicsView {
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2026 Ernie Pasveer <epasveer@att.net>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include "SeerParallelStacksSettingsDialog.h"
|
||||||
|
#include <QtWidgets/QMessageBox>
|
||||||
|
#include <QtCore/QSettings>
|
||||||
|
#include <QtCore/QDebug>
|
||||||
|
|
||||||
|
SeerParallelStacksSettingsDialog::SeerParallelStacksSettingsDialog (QWidget* parent) : QDialog(parent) {
|
||||||
|
|
||||||
|
// Set up the UI.
|
||||||
|
setupUi(this);
|
||||||
|
|
||||||
|
// Setup the widgets
|
||||||
|
|
||||||
|
// Connect things.
|
||||||
|
|
||||||
|
// Restore window settings.
|
||||||
|
readSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
SeerParallelStacksSettingsDialog::~SeerParallelStacksSettingsDialog () {
|
||||||
|
}
|
||||||
|
|
||||||
|
void SeerParallelStacksSettingsDialog::setShowMinimap (const QString& when) {
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SeerParallelStacksSettingsDialog::showMinimap () const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void SeerParallelStacksSettingsDialog::setShowFullFunctionName (bool flag) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SeerParallelStacksSettingsDialog::showFullFunctionName () const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void SeerParallelStacksSettingsDialog::setFunctionNameLenght (int length) {
|
||||||
|
}
|
||||||
|
|
||||||
|
int SeerParallelStacksSettingsDialog::functionNameLenght () const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void SeerParallelStacksSettingsDialog::setShowFullStackSize (bool flag) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SeerParallelStacksSettingsDialog::showFullStackSize () const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void SeerParallelStacksSettingsDialog::setStackSize (int size) {
|
||||||
|
}
|
||||||
|
|
||||||
|
int SeerParallelStacksSettingsDialog::stackSize () const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void SeerParallelStacksSettingsDialog::writeSettings() {
|
||||||
|
|
||||||
|
QSettings settings;
|
||||||
|
|
||||||
|
settings.beginGroup("parallelstackssettingsdialog"); {
|
||||||
|
settings.setValue("size", size());
|
||||||
|
}settings.endGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SeerParallelStacksSettingsDialog::readSettings() {
|
||||||
|
|
||||||
|
QSettings settings;
|
||||||
|
|
||||||
|
settings.beginGroup("parallelstackssettingsdialog"); {
|
||||||
|
if (settings.contains("size")) {
|
||||||
|
resize(settings.value("size", QSize(400, 225)).toSize());
|
||||||
|
}
|
||||||
|
} settings.endGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SeerParallelStacksSettingsDialog::resizeEvent (QResizeEvent* event) {
|
||||||
|
|
||||||
|
// Write window settings.
|
||||||
|
writeSettings();
|
||||||
|
|
||||||
|
QWidget::resizeEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2026 Ernie Pasveer <epasveer@att.net>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QtWidgets/QDialog>
|
||||||
|
#include <QtCore/QString>
|
||||||
|
#include <QtCore/QVector>
|
||||||
|
|
||||||
|
#include "ui_SeerParallelStacksSettingsDialog.h"
|
||||||
|
|
||||||
|
class SeerParallelStacksSettingsDialog : public QDialog, protected Ui::SeerParallelStacksSettingsDialogForm {
|
||||||
|
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SeerParallelStacksSettingsDialog (QWidget* parent = 0);
|
||||||
|
~SeerParallelStacksSettingsDialog ();
|
||||||
|
|
||||||
|
void setShowMinimap (const QString& when);
|
||||||
|
QString showMinimap () const;
|
||||||
|
|
||||||
|
void setShowFullFunctionName (bool flag);
|
||||||
|
bool showFullFunctionName () const;
|
||||||
|
void setFunctionNameLenght (int length);
|
||||||
|
int functionNameLenght () const;
|
||||||
|
|
||||||
|
void setShowFullStackSize (bool flag);
|
||||||
|
bool showFullStackSize () const;
|
||||||
|
void setStackSize (int size);
|
||||||
|
int stackSize () const;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void writeSettings ();
|
||||||
|
void readSettings ();
|
||||||
|
void resizeEvent (QResizeEvent* event);
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
@@ -0,0 +1,201 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>SeerParallelStacksSettingsDialogForm</class>
|
||||||
|
<widget class="QDialog" name="SeerParallelStacksSettingsDialogForm">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>373</width>
|
||||||
|
<height>200</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Seer - ParallelStacks Settings</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>ParallelStacks Settings</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="showMinimapLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Show Minimap</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QRadioButton" name="showMinimapWhenNeededRadioButton">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Only show the minimap if the contents exceeds the display area.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>When needed</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="buttonGroup">
|
||||||
|
<string notr="true">minimapbuttonGroup</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="2">
|
||||||
|
<widget class="QSpinBox" name="stackFrameSizeSpinBox">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Keep N frames of the stack. Omit the middle frames.</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>999</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="functionNameLengthLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Function Name Length</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QRadioButton" name="functionNameLengthAllRadioButton">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Keep the full length of function names.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Full</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QRadioButton" name="showMiniMapAlwaysRadioButton">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Always show the minimap.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Always</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="buttonGroup">
|
||||||
|
<string notr="true">minimapbuttonGroup</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QRadioButton" name="stackFrameSizeAllRadioButton">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Keep all frames of the stack.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>All</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="stackFrameSizeLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Stack Frame Size</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QSpinBox" name="functionNameLengthSpinBox">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Keep N characters of the function name. Omit the middle characters.</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>999</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>4</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
<zorder>groupBox</zorder>
|
||||||
|
<zorder>buttonBox</zorder>
|
||||||
|
<zorder>verticalSpacer</zorder>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>SeerParallelStacksSettingsDialogForm</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>227</x>
|
||||||
|
<y>179</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>199</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>SeerParallelStacksSettingsDialogForm</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>295</x>
|
||||||
|
<y>185</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>199</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
<buttongroups>
|
||||||
|
<buttongroup name="minimapbuttonGroup"/>
|
||||||
|
</buttongroups>
|
||||||
|
</ui>
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#include "SeerParallelStacksVisualizerWidget.h"
|
#include "SeerParallelStacksVisualizerWidget.h"
|
||||||
|
#include "SeerParallelStacksSettingsDialog.h"
|
||||||
#include "SeerParallelStacksCommon.h"
|
#include "SeerParallelStacksCommon.h"
|
||||||
#include "SeerHelpPageDialog.h"
|
#include "SeerHelpPageDialog.h"
|
||||||
#include "SeerUtl.h"
|
#include "SeerUtl.h"
|
||||||
@@ -40,6 +41,7 @@ SeerParallelStacksVisualizerWidget::SeerParallelStacksVisualizerWidget (QWidget*
|
|||||||
QObject::connect(helpToolButton, &QToolButton::clicked, this, &SeerParallelStacksVisualizerWidget::handleHelpButton);
|
QObject::connect(helpToolButton, &QToolButton::clicked, this, &SeerParallelStacksVisualizerWidget::handleHelpButton);
|
||||||
QObject::connect(printToolButton, &QToolButton::clicked, this, &SeerParallelStacksVisualizerWidget::handlePrintButton);
|
QObject::connect(printToolButton, &QToolButton::clicked, this, &SeerParallelStacksVisualizerWidget::handlePrintButton);
|
||||||
QObject::connect(saveToolButton, &QToolButton::clicked, this, &SeerParallelStacksVisualizerWidget::handleSaveButton);
|
QObject::connect(saveToolButton, &QToolButton::clicked, this, &SeerParallelStacksVisualizerWidget::handleSaveButton);
|
||||||
|
QObject::connect(settingsToolButton, &QToolButton::clicked, this, &SeerParallelStacksVisualizerWidget::handleSettingsButton);
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 3)
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 3)
|
||||||
QObject::connect(QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, this, &SeerParallelStacksVisualizerWidget::handleThemeChanged);
|
QObject::connect(QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, this, &SeerParallelStacksVisualizerWidget::handleThemeChanged);
|
||||||
#endif
|
#endif
|
||||||
@@ -238,6 +240,19 @@ void SeerParallelStacksVisualizerWidget::handleSaveButton () {
|
|||||||
QMessageBox::information(this, "Done", "Scene saved to:\n" + fileName);
|
QMessageBox::information(this, "Done", "Scene saved to:\n" + fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SeerParallelStacksVisualizerWidget::handleSettingsButton () {
|
||||||
|
|
||||||
|
// Bring up the settings dialog.
|
||||||
|
SeerParallelStacksSettingsDialog dlg(this);
|
||||||
|
|
||||||
|
// Set dialog things.
|
||||||
|
|
||||||
|
// Execute the dialog.
|
||||||
|
if (dlg.exec()) {
|
||||||
|
// Set things.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SeerParallelStacksVisualizerWidget::handleThemeChanged () {
|
void SeerParallelStacksVisualizerWidget::handleThemeChanged () {
|
||||||
|
|
||||||
// Colorize icons for theme.
|
// Colorize icons for theme.
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class SeerParallelStacksVisualizerWidget : public QWidget, protected Ui::SeerPar
|
|||||||
void handleHelpButton ();
|
void handleHelpButton ();
|
||||||
void handlePrintButton ();
|
void handlePrintButton ();
|
||||||
void handleSaveButton ();
|
void handleSaveButton ();
|
||||||
|
void handleSettingsButton ();
|
||||||
void handleThemeChanged ();
|
void handleThemeChanged ();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -68,6 +68,20 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="settingsToolButton">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Settings.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="resource.qrc">
|
||||||
|
<normaloff>:/seer/resources/RelaxLightIcons/application-menu.svg</normaloff>:/seer/resources/RelaxLightIcons/application-menu.svg</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QToolButton" name="refreshToolButton">
|
<widget class="QToolButton" name="refreshToolButton">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
|
|||||||
@@ -78,5 +78,6 @@ Available Quick keys while in the Image Visualizer:
|
|||||||
'+' zoom in
|
'+' zoom in
|
||||||
'-' zoom out
|
'-' zoom out
|
||||||
ESC reset to default zoom level.
|
ESC reset to default zoom level.
|
||||||
|
Ctrl+mouse wheel zoom in or out.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user