Compare commits
No commits in common. "978c8c10e30af3185e1877037da612e648db3e1f" and "fb176a40b0ddd256590713c38b525a46ca91cbeb" have entirely different histories.
978c8c10e3
...
fb176a40b0
7 changed files with 5 additions and 256 deletions
|
|
@ -85,7 +85,6 @@ if(WARPPIPE_BUILD_GUI)
|
|||
gui/PresetManager.cpp
|
||||
gui/VolumeWidgets.cpp
|
||||
gui/AudioLevelMeter.cpp
|
||||
gui/SquareConnectionPainter.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(warppipe-gui PRIVATE
|
||||
|
|
@ -103,7 +102,6 @@ if(WARPPIPE_BUILD_GUI)
|
|||
gui/PresetManager.cpp
|
||||
gui/VolumeWidgets.cpp
|
||||
gui/AudioLevelMeter.cpp
|
||||
gui/SquareConnectionPainter.cpp
|
||||
)
|
||||
|
||||
target_compile_definitions(warppipe-gui-tests PRIVATE WARPPIPE_TESTING)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,12 @@
|
|||
#include "AudioLevelMeter.h"
|
||||
#include "GraphEditorWidget.h"
|
||||
#include "PresetManager.h"
|
||||
#include "SquareConnectionPainter.h"
|
||||
#include "VolumeWidgets.h"
|
||||
#include "WarpGraphModel.h"
|
||||
|
||||
#include <QtNodes/BasicGraphicsScene>
|
||||
#include <QtNodes/ConnectionStyle>
|
||||
#include <QtNodes/GraphicsView>
|
||||
#include <QtNodes/internal/DefaultConnectionPainter.hpp>
|
||||
#include <QtNodes/internal/NodeGraphicsObject.hpp>
|
||||
#include <QtNodes/internal/ConnectionGraphicsObject.hpp>
|
||||
#include <QtNodes/internal/UndoCommands.hpp>
|
||||
|
|
@ -643,15 +641,6 @@ 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();
|
||||
auto *connStyleMenu = menu.addMenu(QStringLiteral("Connection Style"));
|
||||
auto *styleBezier = connStyleMenu->addAction(QStringLiteral("Bezier Curves"));
|
||||
styleBezier->setCheckable(true);
|
||||
styleBezier->setChecked(m_connectionStyle == ConnectionStyleType::kBezier);
|
||||
auto *styleSquare = connStyleMenu->addAction(QStringLiteral("Square Routing"));
|
||||
styleSquare->setCheckable(true);
|
||||
styleSquare->setChecked(m_connectionStyle == ConnectionStyleType::kSquare);
|
||||
|
||||
menu.addSeparator();
|
||||
QAction *saveLayoutAs = menu.addAction(QStringLiteral("Save Layout As..."));
|
||||
QAction *resetLayout = menu.addAction(QStringLiteral("Reset Layout"));
|
||||
|
|
@ -694,10 +683,6 @@ void GraphEditorWidget::showCanvasContextMenu(const QPoint &screenPos,
|
|||
m_model->autoArrange();
|
||||
m_view->zoomFitAll();
|
||||
saveLayoutWithViewState();
|
||||
} else if (chosen == styleBezier) {
|
||||
setConnectionStyle(ConnectionStyleType::kBezier);
|
||||
} else if (chosen == styleSquare) {
|
||||
setConnectionStyle(ConnectionStyleType::kSquare);
|
||||
} else if (chosen == savePresetAction) {
|
||||
savePreset();
|
||||
} else if (chosen == loadPresetAction) {
|
||||
|
|
@ -1118,7 +1103,6 @@ void GraphEditorWidget::saveLayoutWithViewState() {
|
|||
QList<int> sizes = m_splitter->sizes();
|
||||
vs.splitterGraph = sizes.value(0, 1200);
|
||||
vs.splitterSidebar = sizes.value(1, 320);
|
||||
vs.connectionStyle = static_cast<int>(m_connectionStyle);
|
||||
vs.valid = true;
|
||||
m_model->saveLayout(m_layoutPath, vs);
|
||||
}
|
||||
|
|
@ -1131,9 +1115,6 @@ void GraphEditorWidget::restoreViewState() {
|
|||
if (vs.splitterGraph > 0 || vs.splitterSidebar > 0) {
|
||||
m_splitter->setSizes({vs.splitterGraph, vs.splitterSidebar});
|
||||
}
|
||||
if (vs.connectionStyle == static_cast<int>(ConnectionStyleType::kSquare)) {
|
||||
setConnectionStyle(ConnectionStyleType::kSquare);
|
||||
}
|
||||
} else {
|
||||
m_view->zoomFitAll();
|
||||
}
|
||||
|
|
@ -1467,10 +1448,6 @@ void GraphEditorWidget::rebuildRulesList() {
|
|||
" border-radius: 4px; padding: 6px 12px; }"
|
||||
"QPushButton:hover { background: #3a3a44; }"
|
||||
"QPushButton:pressed { background: #44444e; }");
|
||||
const QString editBtnStyle = QStringLiteral(
|
||||
"QPushButton { background: transparent; color: #5070a0; border: none;"
|
||||
" font-size: 14px; font-weight: bold; padding: 2px 6px; }"
|
||||
"QPushButton:hover { color: #70a0e0; }");
|
||||
const QString delBtnStyle = QStringLiteral(
|
||||
"QPushButton { background: transparent; color: #a05050; border: none;"
|
||||
" font-size: 14px; font-weight: bold; padding: 2px 6px; }"
|
||||
|
|
@ -1523,23 +1500,10 @@ void GraphEditorWidget::rebuildRulesList() {
|
|||
|
||||
cardLayout->addLayout(infoLayout, 1);
|
||||
|
||||
auto *editBtn = new QPushButton(QString(QChar(0x270E)));
|
||||
editBtn->setFixedSize(24, 24);
|
||||
editBtn->setStyleSheet(editBtnStyle);
|
||||
warppipe::RuleId ruleId = rule.id;
|
||||
std::string ruleApp = rule.match.application_name;
|
||||
std::string ruleBin = rule.match.process_binary;
|
||||
std::string ruleRole = rule.match.media_role;
|
||||
std::string ruleTarget = rule.target_node;
|
||||
connect(editBtn, &QPushButton::clicked, this,
|
||||
[this, ruleApp, ruleBin, ruleRole, ruleTarget, ruleId]() {
|
||||
showAddRuleDialog(ruleApp, ruleBin, ruleRole, ruleTarget, ruleId);
|
||||
});
|
||||
cardLayout->addWidget(editBtn);
|
||||
|
||||
auto *delBtn = new QPushButton(QString(QChar(0x2715)));
|
||||
delBtn->setFixedSize(24, 24);
|
||||
delBtn->setStyleSheet(delBtnStyle);
|
||||
warppipe::RuleId ruleId = rule.id;
|
||||
connect(delBtn, &QPushButton::clicked, this, [this, ruleId]() {
|
||||
m_client->RemoveRouteRule(ruleId);
|
||||
rebuildRulesList();
|
||||
|
|
@ -1559,38 +1523,14 @@ void GraphEditorWidget::rebuildRulesList() {
|
|||
static_cast<QVBoxLayout *>(layout)->addStretch();
|
||||
}
|
||||
|
||||
void GraphEditorWidget::setConnectionStyle(ConnectionStyleType style) {
|
||||
if (style == m_connectionStyle)
|
||||
return;
|
||||
m_connectionStyle = style;
|
||||
|
||||
if (style == ConnectionStyleType::kSquare) {
|
||||
m_scene->setConnectionPainter(std::make_unique<SquareConnectionPainter>());
|
||||
} else {
|
||||
m_scene->setConnectionPainter(
|
||||
std::make_unique<QtNodes::DefaultConnectionPainter>());
|
||||
}
|
||||
|
||||
for (auto *item : m_scene->items()) {
|
||||
item->update();
|
||||
}
|
||||
|
||||
scheduleSaveLayout();
|
||||
}
|
||||
|
||||
void GraphEditorWidget::showAddRuleDialog(const std::string &prefillApp,
|
||||
const std::string &prefillBin,
|
||||
const std::string &prefillRole,
|
||||
const std::string &prefillTarget,
|
||||
warppipe::RuleId editRuleId) {
|
||||
const std::string &prefillRole) {
|
||||
if (!m_client)
|
||||
return;
|
||||
|
||||
bool editing = editRuleId.value != 0;
|
||||
|
||||
QDialog dlg(this);
|
||||
dlg.setWindowTitle(editing ? QStringLiteral("Edit Routing Rule")
|
||||
: QStringLiteral("Add Routing Rule"));
|
||||
dlg.setWindowTitle(QStringLiteral("Add Routing Rule"));
|
||||
dlg.setStyleSheet(QStringLiteral(
|
||||
"QDialog { background: #1e1e22; }"
|
||||
"QLabel { color: #ecf0f6; }"
|
||||
|
|
@ -1635,11 +1575,6 @@ void GraphEditorWidget::showAddRuleDialog(const std::string &prefillApp,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!prefillTarget.empty()) {
|
||||
int idx = targetCombo->findData(QString::fromStdString(prefillTarget));
|
||||
if (idx >= 0)
|
||||
targetCombo->setCurrentIndex(idx);
|
||||
}
|
||||
form->addRow(QStringLiteral("Target Node:"), targetCombo);
|
||||
|
||||
auto *buttons = new QDialogButtonBox(
|
||||
|
|
@ -1671,10 +1606,6 @@ void GraphEditorWidget::showAddRuleDialog(const std::string &prefillApp,
|
|||
return;
|
||||
}
|
||||
|
||||
if (editing) {
|
||||
m_client->RemoveRouteRule(editRuleId);
|
||||
}
|
||||
|
||||
warppipe::RouteRule rule;
|
||||
rule.match.application_name = appName;
|
||||
rule.match.process_binary = procBin;
|
||||
|
|
|
|||
|
|
@ -27,11 +27,6 @@ class QTabWidget;
|
|||
class QTimer;
|
||||
class DeleteVirtualNodeCommand;
|
||||
|
||||
enum class ConnectionStyleType : uint8_t {
|
||||
kBezier = 0,
|
||||
kSquare,
|
||||
};
|
||||
|
||||
class GraphEditorWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
|
|
@ -81,10 +76,7 @@ private:
|
|||
void rebuildRulesList();
|
||||
void showAddRuleDialog(const std::string &prefillApp = {},
|
||||
const std::string &prefillBin = {},
|
||||
const std::string &prefillRole = {},
|
||||
const std::string &prefillTarget = {},
|
||||
warppipe::RuleId editRuleId = {});
|
||||
void setConnectionStyle(ConnectionStyleType style);
|
||||
const std::string &prefillRole = {});
|
||||
|
||||
struct PendingPasteLink {
|
||||
std::string outNodeName;
|
||||
|
|
@ -127,6 +119,4 @@ private:
|
|||
|
||||
QWidget *m_rulesContainer = nullptr;
|
||||
QScrollArea *m_rulesScroll = nullptr;
|
||||
|
||||
ConnectionStyleType m_connectionStyle = ConnectionStyleType::kBezier;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,116 +0,0 @@
|
|||
#include "SquareConnectionPainter.h"
|
||||
|
||||
#include <QtNodes/internal/ConnectionGraphicsObject.hpp>
|
||||
#include <QtNodes/internal/ConnectionState.hpp>
|
||||
#include <QtNodes/internal/Definitions.hpp>
|
||||
#include <QtNodes/StyleCollection>
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QPainterPathStroker>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
QPainterPath SquareConnectionPainter::orthogonalPath(
|
||||
QtNodes::ConnectionGraphicsObject const &cgo) const {
|
||||
QPointF out = cgo.endPoint(QtNodes::PortType::Out);
|
||||
QPointF in = cgo.endPoint(QtNodes::PortType::In);
|
||||
|
||||
constexpr double kRadius = 5.0;
|
||||
constexpr double kSpacing = 8.0;
|
||||
constexpr double kMinStub = 20.0;
|
||||
|
||||
auto cId = cgo.connectionId();
|
||||
double spread = static_cast<double>(cId.outPortIndex) * kSpacing;
|
||||
|
||||
double dy = in.y() - out.y();
|
||||
|
||||
if (std::abs(dy) < 0.5 && in.x() > out.x()) {
|
||||
QPainterPath path(out);
|
||||
path.lineTo(in);
|
||||
return path;
|
||||
}
|
||||
|
||||
double midX = (out.x() + in.x()) / 2.0 + spread;
|
||||
midX = std::max(midX, out.x() + kMinStub);
|
||||
if (in.x() > out.x())
|
||||
midX = std::min(midX, in.x() - kMinStub);
|
||||
|
||||
double r = std::min({kRadius, std::abs(dy) / 2.0,
|
||||
std::abs(midX - out.x()),
|
||||
std::abs(in.x() - midX)});
|
||||
r = std::max(r, 0.0);
|
||||
|
||||
double sy = (dy > 0) ? 1.0 : -1.0;
|
||||
double hDir = (in.x() >= midX) ? 1.0 : -1.0;
|
||||
|
||||
QPainterPath path(out);
|
||||
|
||||
if (r > 0.5) {
|
||||
path.lineTo(midX - r, out.y());
|
||||
path.quadTo(QPointF(midX, out.y()), QPointF(midX, out.y() + sy * r));
|
||||
path.lineTo(midX, in.y() - sy * r);
|
||||
path.quadTo(QPointF(midX, in.y()), QPointF(midX + hDir * r, in.y()));
|
||||
} else {
|
||||
path.lineTo(midX, out.y());
|
||||
path.lineTo(midX, in.y());
|
||||
}
|
||||
|
||||
path.lineTo(in);
|
||||
return path;
|
||||
}
|
||||
|
||||
void SquareConnectionPainter::paint(
|
||||
QPainter *painter,
|
||||
QtNodes::ConnectionGraphicsObject const &cgo) const {
|
||||
auto const &style = QtNodes::StyleCollection::connectionStyle();
|
||||
|
||||
bool const hovered = cgo.connectionState().hovered();
|
||||
bool const selected = cgo.isSelected();
|
||||
bool const sketch = cgo.connectionState().requiresPort();
|
||||
|
||||
auto path = orthogonalPath(cgo);
|
||||
|
||||
if (hovered || selected) {
|
||||
QPen pen;
|
||||
pen.setWidth(static_cast<int>(2 * style.lineWidth()));
|
||||
pen.setColor(selected ? style.selectedHaloColor() : style.hoveredColor());
|
||||
painter->setPen(pen);
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->drawPath(path);
|
||||
}
|
||||
|
||||
if (sketch) {
|
||||
QPen pen;
|
||||
pen.setWidth(static_cast<int>(style.constructionLineWidth()));
|
||||
pen.setColor(style.constructionColor());
|
||||
pen.setStyle(Qt::DashLine);
|
||||
painter->setPen(pen);
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->drawPath(path);
|
||||
} else {
|
||||
QPen pen;
|
||||
pen.setWidth(style.lineWidth());
|
||||
pen.setColor(selected ? style.selectedColor() : style.normalColor());
|
||||
painter->setPen(pen);
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->drawPath(path);
|
||||
}
|
||||
|
||||
double const pointRadius = style.pointDiameter() / 2.0;
|
||||
painter->setPen(style.constructionColor());
|
||||
painter->setBrush(style.constructionColor());
|
||||
painter->drawEllipse(cgo.out(), pointRadius, pointRadius);
|
||||
painter->drawEllipse(cgo.in(), pointRadius, pointRadius);
|
||||
}
|
||||
|
||||
QPainterPath SquareConnectionPainter::getPainterStroke(
|
||||
QtNodes::ConnectionGraphicsObject const &cgo) const {
|
||||
auto path = orthogonalPath(cgo);
|
||||
|
||||
QPainterPathStroker stroker;
|
||||
stroker.setWidth(10.0);
|
||||
|
||||
return stroker.createStroke(path);
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <QtNodes/internal/AbstractConnectionPainter.hpp>
|
||||
|
||||
class SquareConnectionPainter : public QtNodes::AbstractConnectionPainter {
|
||||
public:
|
||||
void paint(QPainter *painter,
|
||||
QtNodes::ConnectionGraphicsObject const &cgo) const override;
|
||||
QPainterPath
|
||||
getPainterStroke(QtNodes::ConnectionGraphicsObject const &cgo) const override;
|
||||
|
||||
private:
|
||||
QPainterPath
|
||||
orthogonalPath(QtNodes::ConnectionGraphicsObject const &cgo) const;
|
||||
};
|
||||
|
|
@ -466,8 +466,7 @@ void WarpGraphModel::refreshFromClient() {
|
|||
if (savedIt != m_savedPositions.end()) {
|
||||
m_positions.emplace(qtId, savedIt->second);
|
||||
} else {
|
||||
QPointF candidate = nextPosition(nodeIt->second);
|
||||
m_positions.emplace(qtId, findNonOverlappingPosition(candidate, nodeIt->second));
|
||||
m_positions.emplace(qtId, nextPosition(nodeIt->second));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -699,40 +698,6 @@ QPointF WarpGraphModel::nextPosition(const WarpNodeData &data) {
|
|||
return pos;
|
||||
}
|
||||
|
||||
QPointF WarpGraphModel::findNonOverlappingPosition(QPointF candidate,
|
||||
const WarpNodeData &data) const {
|
||||
QSizeF newSize(estimateNodeSize(data));
|
||||
constexpr int kMaxAttempts = 50;
|
||||
|
||||
for (int attempt = 0; attempt < kMaxAttempts; ++attempt) {
|
||||
QRectF newRect(candidate, newSize);
|
||||
bool overlaps = false;
|
||||
for (const auto &[existingId, existingPos] : m_positions) {
|
||||
auto nodeIt = m_nodes.find(existingId);
|
||||
if (nodeIt == m_nodes.end())
|
||||
continue;
|
||||
QSizeF existingSize;
|
||||
auto sizeIt = m_sizes.find(existingId);
|
||||
if (sizeIt != m_sizes.end()) {
|
||||
existingSize = QSizeF(sizeIt->second);
|
||||
} else {
|
||||
existingSize = QSizeF(estimateNodeSize(nodeIt->second));
|
||||
}
|
||||
QRectF existingRect(existingPos, existingSize);
|
||||
QRectF padded = existingRect.adjusted(-kHorizontalGap / 2, -kVerticalGap / 2,
|
||||
kHorizontalGap / 2, kVerticalGap / 2);
|
||||
if (newRect.intersects(padded)) {
|
||||
candidate.setY(existingRect.bottom() + kVerticalGap);
|
||||
overlaps = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!overlaps)
|
||||
break;
|
||||
}
|
||||
return candidate;
|
||||
}
|
||||
|
||||
bool WarpGraphModel::isGhost(QtNodes::NodeId nodeId) const {
|
||||
return m_ghostNodes.find(nodeId) != m_ghostNodes.end();
|
||||
}
|
||||
|
|
@ -905,7 +870,6 @@ void WarpGraphModel::saveLayout(const QString &path,
|
|||
viewObj["splitter_graph"] = viewState.splitterGraph;
|
||||
viewObj["splitter_sidebar"] = viewState.splitterSidebar;
|
||||
}
|
||||
viewObj["connection_style"] = viewState.connectionStyle;
|
||||
root["view"] = viewObj;
|
||||
}
|
||||
|
||||
|
|
@ -965,7 +929,6 @@ bool WarpGraphModel::loadLayout(const QString &path) {
|
|||
m_savedViewState.centerY = viewObj["center_y"].toDouble();
|
||||
m_savedViewState.splitterGraph = viewObj["splitter_graph"].toInt(0);
|
||||
m_savedViewState.splitterSidebar = viewObj["splitter_sidebar"].toInt(0);
|
||||
m_savedViewState.connectionStyle = viewObj["connection_style"].toInt(0);
|
||||
m_savedViewState.valid = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -88,7 +88,6 @@ public:
|
|||
double centerY;
|
||||
int splitterGraph;
|
||||
int splitterSidebar;
|
||||
int connectionStyle;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
|
|
@ -103,7 +102,6 @@ private:
|
|||
static QString captionForNode(const warppipe::NodeInfo &info);
|
||||
static QVariant styleForNode(WarpNodeType type, bool ghost);
|
||||
QPointF nextPosition(const WarpNodeData &data);
|
||||
QPointF findNonOverlappingPosition(QPointF candidate, const WarpNodeData &data) const;
|
||||
static QSize estimateNodeSize(const WarpNodeData &data);
|
||||
|
||||
warppipe::Client *m_client = nullptr;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue