GUI Milestone 8b

This commit is contained in:
Joey Yakimowich-Payne 2026-01-30 08:07:21 -07:00
commit 4a248e5622
6 changed files with 682 additions and 37 deletions

View file

@ -13,9 +13,11 @@
#include <QContextMenuEvent>
#include <QDateTime>
#include <QDir>
#include <QFileDialog>
#include <QGraphicsItem>
#include <QGuiApplication>
#include <QInputDialog>
#include <QMouseEvent>
#include <QJsonArray>
#include <QJsonDocument>
#include <QMenu>
@ -188,7 +190,7 @@ GraphEditorWidget::GraphEditorWidget(warppipe::Client *client,
autoArrangeAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
connect(autoArrangeAction, &QAction::triggered, this, [this]() {
m_model->autoArrange();
m_model->saveLayout(m_layoutPath);
saveLayoutWithViewState();
});
m_view->addAction(autoArrangeAction);
@ -239,19 +241,26 @@ GraphEditorWidget::GraphEditorWidget(warppipe::Client *client,
connect(m_model, &WarpGraphModel::nodePositionUpdated, this,
&GraphEditorWidget::scheduleSaveLayout);
connect(m_model, &QtNodes::AbstractGraphModel::nodeCreated, this,
&GraphEditorWidget::scheduleSaveLayout);
connect(m_model, &QtNodes::AbstractGraphModel::nodeDeleted, this,
&GraphEditorWidget::scheduleSaveLayout);
connect(m_model, &QtNodes::AbstractGraphModel::nodeUpdated, this,
&GraphEditorWidget::scheduleSaveLayout);
m_saveTimer = new QTimer(this);
m_saveTimer->setSingleShot(true);
m_saveTimer->setInterval(1000);
connect(m_saveTimer, &QTimer::timeout, this, [this]() {
m_model->saveLayout(m_layoutPath);
});
connect(m_saveTimer, &QTimer::timeout, this,
&GraphEditorWidget::saveLayoutWithViewState);
m_model->refreshFromClient();
if (!hasLayout) {
m_model->autoArrange();
}
QTimer::singleShot(0, this, &GraphEditorWidget::restoreViewState);
if (m_model->allNodeIds().size() > 0) {
m_graphReady = true;
Q_EMIT graphReady();
@ -342,10 +351,18 @@ void GraphEditorWidget::captureDebugScreenshot(const QString &event) {
}
bool GraphEditorWidget::eventFilter(QObject *obj, QEvent *event) {
if (obj == m_view->viewport() &&
event->type() == QEvent::ContextMenu) {
if (obj != m_view->viewport()) {
return QWidget::eventFilter(obj, event);
}
if (event->type() == QEvent::ContextMenu) {
auto *cme = static_cast<QContextMenuEvent *>(event);
m_lastContextMenuScenePos = m_view->mapToScene(cme->pos());
} else if (event->type() == QEvent::MouseButtonPress) {
auto *me = static_cast<QMouseEvent *>(event);
if (me->button() == Qt::MiddleButton) {
m_view->centerOn(m_view->mapToScene(me->pos()));
return true;
}
}
return QWidget::eventFilter(obj, event);
}
@ -410,6 +427,9 @@ void GraphEditorWidget::showCanvasContextMenu(const QPoint &screenPos,
autoArrange->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_L));
QAction *refreshGraph = menu.addAction(QStringLiteral("Refresh Graph"));
refreshGraph->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_R));
menu.addSeparator();
QAction *saveLayoutAs = menu.addAction(QStringLiteral("Save Layout As..."));
QAction *resetLayout = menu.addAction(QStringLiteral("Reset Layout"));
QAction *chosen = menu.exec(screenPos);
if (chosen == createSink) {
@ -430,8 +450,22 @@ void GraphEditorWidget::showCanvasContextMenu(const QPoint &screenPos,
m_view->zoomFitSelected();
} else if (chosen == autoArrange) {
m_model->autoArrange();
saveLayoutWithViewState();
} else if (chosen == refreshGraph) {
m_model->refreshFromClient();
} else if (chosen == saveLayoutAs) {
QString path = QFileDialog::getSaveFileName(
this, QStringLiteral("Save Layout As"), QString(),
QStringLiteral("JSON files (*.json)"));
if (!path.isEmpty()) {
saveLayoutWithViewState();
m_model->saveLayout(path);
}
} else if (chosen == resetLayout) {
m_model->clearSavedPositions();
m_model->autoArrange();
m_view->zoomFitAll();
saveLayoutWithViewState();
}
}
@ -827,3 +861,23 @@ void GraphEditorWidget::tryResolvePendingLinks() {
m_pendingPasteLinks = remaining;
}
void GraphEditorWidget::saveLayoutWithViewState() {
WarpGraphModel::ViewState vs;
vs.scale = m_view->getScale();
QPointF center = m_view->mapToScene(m_view->viewport()->rect().center());
vs.centerX = center.x();
vs.centerY = center.y();
vs.valid = true;
m_model->saveLayout(m_layoutPath, vs);
}
void GraphEditorWidget::restoreViewState() {
auto vs = m_model->savedViewState();
if (vs.valid) {
m_view->setupScale(vs.scale);
m_view->centerOn(QPointF(vs.centerX, vs.centerY));
} else {
m_view->zoomFitAll();
}
}