Fix perf issues and some visual bugs
This commit is contained in:
parent
00e997a204
commit
d389161f4a
5 changed files with 300 additions and 11 deletions
|
|
@ -4,6 +4,7 @@
|
||||||
#include "SquareConnectionPainter.h"
|
#include "SquareConnectionPainter.h"
|
||||||
#include "VolumeWidgets.h"
|
#include "VolumeWidgets.h"
|
||||||
#include "WarpGraphModel.h"
|
#include "WarpGraphModel.h"
|
||||||
|
#include "ZoomGraphicsView.h"
|
||||||
|
|
||||||
#include <QtNodes/BasicGraphicsScene>
|
#include <QtNodes/BasicGraphicsScene>
|
||||||
#include <QtNodes/ConnectionStyle>
|
#include <QtNodes/ConnectionStyle>
|
||||||
|
|
@ -178,6 +179,7 @@ GraphEditorWidget::GraphEditorWidget(warppipe::Client *client,
|
||||||
bool hasLayout = m_model->loadLayout(m_layoutPath);
|
bool hasLayout = m_model->loadLayout(m_layoutPath);
|
||||||
|
|
||||||
m_scene = new QtNodes::BasicGraphicsScene(*m_model, this);
|
m_scene = new QtNodes::BasicGraphicsScene(*m_model, this);
|
||||||
|
m_scene->setItemIndexMethod(QGraphicsScene::BspTreeIndex);
|
||||||
|
|
||||||
QtNodes::ConnectionStyle::setConnectionStyle(
|
QtNodes::ConnectionStyle::setConnectionStyle(
|
||||||
R"({"ConnectionStyle": {
|
R"({"ConnectionStyle": {
|
||||||
|
|
@ -192,10 +194,12 @@ GraphEditorWidget::GraphEditorWidget(warppipe::Client *client,
|
||||||
"UseDataDefinedColors": false
|
"UseDataDefinedColors": false
|
||||||
}})");
|
}})");
|
||||||
|
|
||||||
m_view = new QtNodes::GraphicsView(m_scene);
|
m_view = new ZoomGraphicsView(m_scene);
|
||||||
m_view->setFocusPolicy(Qt::StrongFocus);
|
m_view->setFocusPolicy(Qt::StrongFocus);
|
||||||
m_view->viewport()->setFocusPolicy(Qt::StrongFocus);
|
m_view->viewport()->setFocusPolicy(Qt::StrongFocus);
|
||||||
m_view->viewport()->installEventFilter(this);
|
m_view->viewport()->installEventFilter(this);
|
||||||
|
connect(m_view, &ZoomGraphicsView::scaleChanged, m_view,
|
||||||
|
[this]() { m_view->updateProxyCacheMode(); });
|
||||||
|
|
||||||
m_presetDir =
|
m_presetDir =
|
||||||
QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) +
|
QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) +
|
||||||
|
|
@ -233,6 +237,108 @@ GraphEditorWidget::GraphEditorWidget(warppipe::Client *client,
|
||||||
|
|
||||||
presetsLayout->addWidget(savePresetBtn);
|
presetsLayout->addWidget(savePresetBtn);
|
||||||
presetsLayout->addWidget(loadPresetBtn);
|
presetsLayout->addWidget(loadPresetBtn);
|
||||||
|
|
||||||
|
presetsLayout->addSpacing(16);
|
||||||
|
|
||||||
|
auto *zoomSensLabel = new QLabel(QStringLiteral("ZOOM SENSITIVITY"));
|
||||||
|
zoomSensLabel->setStyleSheet(QStringLiteral(
|
||||||
|
"QLabel { color: #a0a8b6; font-size: 11px; font-weight: bold;"
|
||||||
|
" background: transparent; }"));
|
||||||
|
presetsLayout->addWidget(zoomSensLabel);
|
||||||
|
|
||||||
|
m_zoomSensSlider = new QSlider(Qt::Horizontal);
|
||||||
|
m_zoomSensSlider->setRange(5, 50);
|
||||||
|
m_zoomSensSlider->setValue(20);
|
||||||
|
m_zoomSensSlider->setStyleSheet(QStringLiteral(
|
||||||
|
"QSlider::groove:horizontal {"
|
||||||
|
" background: #1a1a1e; border-radius: 3px; height: 6px; }"
|
||||||
|
"QSlider::handle:horizontal {"
|
||||||
|
" background: #ecf0f6; border-radius: 5px;"
|
||||||
|
" width: 10px; margin: -4px 0; }"
|
||||||
|
"QSlider::sub-page:horizontal {"
|
||||||
|
" background: #4caf50; border-radius: 3px; }"));
|
||||||
|
|
||||||
|
m_zoomSensValue = new QLabel(QStringLiteral("1.20x"));
|
||||||
|
m_zoomSensValue->setStyleSheet(QStringLiteral(
|
||||||
|
"QLabel { color: #ecf0f6; font-size: 11px; background: transparent; }"));
|
||||||
|
m_zoomSensValue->setAlignment(Qt::AlignCenter);
|
||||||
|
|
||||||
|
connect(m_zoomSensSlider, &QSlider::valueChanged, this,
|
||||||
|
[this](int value) {
|
||||||
|
double sensitivity = 1.0 + value / 100.0;
|
||||||
|
m_view->setZoomSensitivity(sensitivity);
|
||||||
|
m_zoomSensValue->setText(
|
||||||
|
QString::number(sensitivity, 'f', 2) + QStringLiteral("x"));
|
||||||
|
scheduleSaveLayout();
|
||||||
|
});
|
||||||
|
|
||||||
|
presetsLayout->addWidget(m_zoomSensSlider);
|
||||||
|
presetsLayout->addWidget(m_zoomSensValue);
|
||||||
|
|
||||||
|
auto sliderStyle = m_zoomSensSlider->styleSheet();
|
||||||
|
auto valueLabelStyle = m_zoomSensValue->styleSheet();
|
||||||
|
|
||||||
|
presetsLayout->addSpacing(12);
|
||||||
|
|
||||||
|
auto *zoomMinLabel = new QLabel(QStringLiteral("MIN ZOOM"));
|
||||||
|
zoomMinLabel->setStyleSheet(zoomSensLabel->styleSheet());
|
||||||
|
presetsLayout->addWidget(zoomMinLabel);
|
||||||
|
|
||||||
|
m_zoomMinSlider = new QSlider(Qt::Horizontal);
|
||||||
|
m_zoomMinSlider->setRange(5, 90);
|
||||||
|
m_zoomMinSlider->setValue(30);
|
||||||
|
m_zoomMinSlider->setStyleSheet(sliderStyle);
|
||||||
|
|
||||||
|
m_zoomMinValue = new QLabel(QStringLiteral("0.30x"));
|
||||||
|
m_zoomMinValue->setStyleSheet(valueLabelStyle);
|
||||||
|
m_zoomMinValue->setAlignment(Qt::AlignCenter);
|
||||||
|
|
||||||
|
connect(m_zoomMinSlider, &QSlider::valueChanged, this,
|
||||||
|
[this](int value) {
|
||||||
|
double minZoom = value / 100.0;
|
||||||
|
if (m_zoomMaxSlider->value() <= value) {
|
||||||
|
m_zoomMaxSlider->setValue(value + 5);
|
||||||
|
}
|
||||||
|
m_view->setScaleRange(minZoom,
|
||||||
|
m_zoomMaxSlider->value() / 100.0);
|
||||||
|
m_zoomMinValue->setText(
|
||||||
|
QString::number(minZoom, 'f', 2) + QStringLiteral("x"));
|
||||||
|
scheduleSaveLayout();
|
||||||
|
});
|
||||||
|
|
||||||
|
presetsLayout->addWidget(m_zoomMinSlider);
|
||||||
|
presetsLayout->addWidget(m_zoomMinValue);
|
||||||
|
|
||||||
|
presetsLayout->addSpacing(12);
|
||||||
|
|
||||||
|
auto *zoomMaxLabel = new QLabel(QStringLiteral("MAX ZOOM"));
|
||||||
|
zoomMaxLabel->setStyleSheet(zoomSensLabel->styleSheet());
|
||||||
|
presetsLayout->addWidget(zoomMaxLabel);
|
||||||
|
|
||||||
|
m_zoomMaxSlider = new QSlider(Qt::Horizontal);
|
||||||
|
m_zoomMaxSlider->setRange(10, 500);
|
||||||
|
m_zoomMaxSlider->setValue(200);
|
||||||
|
m_zoomMaxSlider->setStyleSheet(sliderStyle);
|
||||||
|
|
||||||
|
m_zoomMaxValue = new QLabel(QStringLiteral("2.00x"));
|
||||||
|
m_zoomMaxValue->setStyleSheet(valueLabelStyle);
|
||||||
|
m_zoomMaxValue->setAlignment(Qt::AlignCenter);
|
||||||
|
|
||||||
|
connect(m_zoomMaxSlider, &QSlider::valueChanged, this,
|
||||||
|
[this](int value) {
|
||||||
|
double maxZoom = value / 100.0;
|
||||||
|
if (m_zoomMinSlider->value() >= value) {
|
||||||
|
m_zoomMinSlider->setValue(value - 5);
|
||||||
|
}
|
||||||
|
m_view->setScaleRange(m_zoomMinSlider->value() / 100.0,
|
||||||
|
maxZoom);
|
||||||
|
m_zoomMaxValue->setText(
|
||||||
|
QString::number(maxZoom, 'f', 2) + QStringLiteral("x"));
|
||||||
|
scheduleSaveLayout();
|
||||||
|
});
|
||||||
|
|
||||||
|
presetsLayout->addWidget(m_zoomMaxSlider);
|
||||||
|
presetsLayout->addWidget(m_zoomMaxValue);
|
||||||
presetsLayout->addStretch();
|
presetsLayout->addStretch();
|
||||||
|
|
||||||
auto *metersTab = new QWidget();
|
auto *metersTab = new QWidget();
|
||||||
|
|
@ -504,9 +610,7 @@ void GraphEditorWidget::onRefreshTimer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphEditorWidget::scheduleSaveLayout() {
|
void GraphEditorWidget::scheduleSaveLayout() {
|
||||||
if (!m_saveTimer->isActive()) {
|
m_saveTimer->start();
|
||||||
m_saveTimer->start();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphEditorWidget::~GraphEditorWidget() {
|
GraphEditorWidget::~GraphEditorWidget() {
|
||||||
|
|
@ -1130,6 +1234,9 @@ void GraphEditorWidget::saveLayoutWithViewState() {
|
||||||
vs.splitterGraph = sizes.value(0, 1200);
|
vs.splitterGraph = sizes.value(0, 1200);
|
||||||
vs.splitterSidebar = sizes.value(1, 320);
|
vs.splitterSidebar = sizes.value(1, 320);
|
||||||
vs.connectionStyle = static_cast<int>(m_connectionStyle);
|
vs.connectionStyle = static_cast<int>(m_connectionStyle);
|
||||||
|
vs.zoomSensitivity = m_view->zoomSensitivity();
|
||||||
|
vs.zoomMin = m_zoomMinSlider->value() / 100.0;
|
||||||
|
vs.zoomMax = m_zoomMaxSlider->value() / 100.0;
|
||||||
vs.valid = true;
|
vs.valid = true;
|
||||||
m_model->saveLayout(m_layoutPath, vs);
|
m_model->saveLayout(m_layoutPath, vs);
|
||||||
}
|
}
|
||||||
|
|
@ -1145,6 +1252,17 @@ void GraphEditorWidget::restoreViewState() {
|
||||||
if (vs.connectionStyle == static_cast<int>(ConnectionStyleType::kSquare)) {
|
if (vs.connectionStyle == static_cast<int>(ConnectionStyleType::kSquare)) {
|
||||||
setConnectionStyle(ConnectionStyleType::kSquare);
|
setConnectionStyle(ConnectionStyleType::kSquare);
|
||||||
}
|
}
|
||||||
|
if (vs.zoomSensitivity > 0.0) {
|
||||||
|
m_view->setZoomSensitivity(vs.zoomSensitivity);
|
||||||
|
int sliderVal = static_cast<int>((vs.zoomSensitivity - 1.0) * 100.0);
|
||||||
|
m_zoomSensSlider->setValue(sliderVal);
|
||||||
|
}
|
||||||
|
if (vs.zoomMin > 0.0) {
|
||||||
|
m_zoomMinSlider->setValue(static_cast<int>(vs.zoomMin * 100.0));
|
||||||
|
}
|
||||||
|
if (vs.zoomMax > 0.0) {
|
||||||
|
m_zoomMaxSlider->setValue(static_cast<int>(vs.zoomMax * 100.0));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
m_view->zoomFitAll();
|
m_view->zoomFitAll();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,10 @@
|
||||||
namespace QtNodes {
|
namespace QtNodes {
|
||||||
using NodeId = unsigned int;
|
using NodeId = unsigned int;
|
||||||
class BasicGraphicsScene;
|
class BasicGraphicsScene;
|
||||||
class GraphicsView;
|
|
||||||
} // namespace QtNodes
|
} // namespace QtNodes
|
||||||
|
|
||||||
|
class ZoomGraphicsView;
|
||||||
|
|
||||||
class AudioLevelMeter;
|
class AudioLevelMeter;
|
||||||
class WarpGraphModel;
|
class WarpGraphModel;
|
||||||
class NodeVolumeWidget;
|
class NodeVolumeWidget;
|
||||||
|
|
@ -24,6 +25,7 @@ class QLabel;
|
||||||
class QScrollArea;
|
class QScrollArea;
|
||||||
class QSplitter;
|
class QSplitter;
|
||||||
class QTabWidget;
|
class QTabWidget;
|
||||||
|
class QSlider;
|
||||||
class QTimer;
|
class QTimer;
|
||||||
class DeleteVirtualNodeCommand;
|
class DeleteVirtualNodeCommand;
|
||||||
|
|
||||||
|
|
@ -96,7 +98,7 @@ private:
|
||||||
warppipe::Client *m_client = nullptr;
|
warppipe::Client *m_client = nullptr;
|
||||||
WarpGraphModel *m_model = nullptr;
|
WarpGraphModel *m_model = nullptr;
|
||||||
QtNodes::BasicGraphicsScene *m_scene = nullptr;
|
QtNodes::BasicGraphicsScene *m_scene = nullptr;
|
||||||
QtNodes::GraphicsView *m_view = nullptr;
|
ZoomGraphicsView *m_view = nullptr;
|
||||||
QSplitter *m_splitter = nullptr;
|
QSplitter *m_splitter = nullptr;
|
||||||
QTabWidget *m_sidebar = nullptr;
|
QTabWidget *m_sidebar = nullptr;
|
||||||
QTimer *m_refreshTimer = nullptr;
|
QTimer *m_refreshTimer = nullptr;
|
||||||
|
|
@ -129,4 +131,11 @@ private:
|
||||||
QScrollArea *m_rulesScroll = nullptr;
|
QScrollArea *m_rulesScroll = nullptr;
|
||||||
|
|
||||||
ConnectionStyleType m_connectionStyle = ConnectionStyleType::kBezier;
|
ConnectionStyleType m_connectionStyle = ConnectionStyleType::kBezier;
|
||||||
|
|
||||||
|
QSlider *m_zoomSensSlider = nullptr;
|
||||||
|
QLabel *m_zoomSensValue = nullptr;
|
||||||
|
QSlider *m_zoomMinSlider = nullptr;
|
||||||
|
QLabel *m_zoomMinValue = nullptr;
|
||||||
|
QSlider *m_zoomMaxSlider = nullptr;
|
||||||
|
QLabel *m_zoomMaxValue = nullptr;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@ WarpGraphModel::WarpGraphModel(warppipe::Client *client, QObject *parent)
|
||||||
if (parent) {
|
if (parent) {
|
||||||
setParent(parent);
|
setParent(parent);
|
||||||
}
|
}
|
||||||
|
connect(this, &WarpGraphModel::nodeUpdated, this,
|
||||||
|
[this](QtNodes::NodeId nodeId) { m_styleCache.erase(nodeId); });
|
||||||
}
|
}
|
||||||
|
|
||||||
QtNodes::NodeId WarpGraphModel::newNodeId() { return m_nextNodeId++; }
|
QtNodes::NodeId WarpGraphModel::newNodeId() { return m_nextNodeId++; }
|
||||||
|
|
@ -195,9 +197,14 @@ QVariant WarpGraphModel::nodeData(QtNodes::NodeId nodeId,
|
||||||
case QtNodes::NodeRole::Type:
|
case QtNodes::NodeRole::Type:
|
||||||
return QString("PipeWire");
|
return QString("PipeWire");
|
||||||
case QtNodes::NodeRole::Style: {
|
case QtNodes::NodeRole::Style: {
|
||||||
|
auto cacheIt = m_styleCache.find(nodeId);
|
||||||
|
if (cacheIt != m_styleCache.end())
|
||||||
|
return cacheIt->second;
|
||||||
bool ghost = m_ghostNodes.find(nodeId) != m_ghostNodes.end();
|
bool ghost = m_ghostNodes.find(nodeId) != m_ghostNodes.end();
|
||||||
WarpNodeType type = classifyNode(data.info);
|
WarpNodeType type = classifyNode(data.info);
|
||||||
return styleForNode(type, ghost);
|
QVariant result = styleForNode(type, ghost);
|
||||||
|
m_styleCache[nodeId] = result;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
case QtNodes::NodeRole::Widget: {
|
case QtNodes::NodeRole::Widget: {
|
||||||
auto wIt = m_volumeWidgets.find(nodeId);
|
auto wIt = m_volumeWidgets.find(nodeId);
|
||||||
|
|
@ -321,6 +328,7 @@ bool WarpGraphModel::deleteNode(QtNodes::NodeId const nodeId) {
|
||||||
m_positions.erase(nodeId);
|
m_positions.erase(nodeId);
|
||||||
m_sizes.erase(nodeId);
|
m_sizes.erase(nodeId);
|
||||||
m_volumeStates.erase(nodeId);
|
m_volumeStates.erase(nodeId);
|
||||||
|
m_styleCache.erase(nodeId);
|
||||||
auto vwIt = m_volumeWidgets.find(nodeId);
|
auto vwIt = m_volumeWidgets.find(nodeId);
|
||||||
if (vwIt != m_volumeWidgets.end()) {
|
if (vwIt != m_volumeWidgets.end()) {
|
||||||
delete vwIt->second;
|
delete vwIt->second;
|
||||||
|
|
@ -593,7 +601,8 @@ void WarpGraphModel::refreshFromClient() {
|
||||||
|
|
||||||
if (outIsGhost || inIsGhost) {
|
if (outIsGhost || inIsGhost) {
|
||||||
m_ghostConnections.insert(connId);
|
m_ghostConnections.insert(connId);
|
||||||
} else {
|
}
|
||||||
|
{
|
||||||
auto connIt = m_connections.find(connId);
|
auto connIt = m_connections.find(connId);
|
||||||
if (connIt != m_connections.end()) {
|
if (connIt != m_connections.end()) {
|
||||||
m_connections.erase(connIt);
|
m_connections.erase(connIt);
|
||||||
|
|
@ -643,10 +652,8 @@ void WarpGraphModel::refreshFromClient() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QtNodes::ConnectionId connId{outQtId, outIdx, inQtId, inIdx};
|
QtNodes::ConnectionId connId{outQtId, outIdx, inQtId, inIdx};
|
||||||
if (m_connections.find(connId) == m_connections.end()) {
|
if (m_ghostConnections.find(connId) == m_ghostConnections.end()) {
|
||||||
m_connections.insert(connId);
|
|
||||||
m_ghostConnections.insert(connId);
|
m_ghostConnections.insert(connId);
|
||||||
Q_EMIT connectionCreated(connId);
|
|
||||||
}
|
}
|
||||||
it = m_pendingGhostConnections.erase(it);
|
it = m_pendingGhostConnections.erase(it);
|
||||||
}
|
}
|
||||||
|
|
@ -969,6 +976,12 @@ void WarpGraphModel::saveLayout(const QString &path,
|
||||||
viewObj["splitter_sidebar"] = viewState.splitterSidebar;
|
viewObj["splitter_sidebar"] = viewState.splitterSidebar;
|
||||||
}
|
}
|
||||||
viewObj["connection_style"] = viewState.connectionStyle;
|
viewObj["connection_style"] = viewState.connectionStyle;
|
||||||
|
if (viewState.zoomSensitivity > 0.0)
|
||||||
|
viewObj["zoom_sensitivity"] = viewState.zoomSensitivity;
|
||||||
|
if (viewState.zoomMin > 0.0)
|
||||||
|
viewObj["zoom_min"] = viewState.zoomMin;
|
||||||
|
if (viewState.zoomMax > 0.0)
|
||||||
|
viewObj["zoom_max"] = viewState.zoomMax;
|
||||||
root["view"] = viewObj;
|
root["view"] = viewObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1029,6 +1042,9 @@ bool WarpGraphModel::loadLayout(const QString &path) {
|
||||||
m_savedViewState.splitterGraph = viewObj["splitter_graph"].toInt(0);
|
m_savedViewState.splitterGraph = viewObj["splitter_graph"].toInt(0);
|
||||||
m_savedViewState.splitterSidebar = viewObj["splitter_sidebar"].toInt(0);
|
m_savedViewState.splitterSidebar = viewObj["splitter_sidebar"].toInt(0);
|
||||||
m_savedViewState.connectionStyle = viewObj["connection_style"].toInt(0);
|
m_savedViewState.connectionStyle = viewObj["connection_style"].toInt(0);
|
||||||
|
m_savedViewState.zoomSensitivity = viewObj["zoom_sensitivity"].toDouble(0.0);
|
||||||
|
m_savedViewState.zoomMin = viewObj["zoom_min"].toDouble(0.0);
|
||||||
|
m_savedViewState.zoomMax = viewObj["zoom_max"].toDouble(0.0);
|
||||||
m_savedViewState.valid = true;
|
m_savedViewState.valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,9 @@ public:
|
||||||
double scale;
|
double scale;
|
||||||
double centerX;
|
double centerX;
|
||||||
double centerY;
|
double centerY;
|
||||||
|
double zoomSensitivity;
|
||||||
|
double zoomMin;
|
||||||
|
double zoomMax;
|
||||||
int splitterGraph;
|
int splitterGraph;
|
||||||
int splitterSidebar;
|
int splitterSidebar;
|
||||||
int connectionStyle;
|
int connectionStyle;
|
||||||
|
|
@ -156,4 +159,5 @@ private:
|
||||||
|
|
||||||
std::unordered_map<QtNodes::NodeId, NodeVolumeState> m_volumeStates;
|
std::unordered_map<QtNodes::NodeId, NodeVolumeState> m_volumeStates;
|
||||||
std::unordered_map<QtNodes::NodeId, QWidget *> m_volumeWidgets;
|
std::unordered_map<QtNodes::NodeId, QWidget *> m_volumeWidgets;
|
||||||
|
mutable std::unordered_map<QtNodes::NodeId, QVariant> m_styleCache;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
142
gui/ZoomGraphicsView.h
Normal file
142
gui/ZoomGraphicsView.h
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QtNodes/GraphicsView>
|
||||||
|
#include <QtNodes/StyleCollection>
|
||||||
|
|
||||||
|
#include <QGraphicsProxyWidget>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QScrollBar>
|
||||||
|
#include <QWheelEvent>
|
||||||
|
|
||||||
|
#include <QtNodes/internal/ConnectionGraphicsObject.hpp>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
class ZoomGraphicsView : public QtNodes::GraphicsView {
|
||||||
|
public:
|
||||||
|
explicit ZoomGraphicsView(QtNodes::BasicGraphicsScene *scene,
|
||||||
|
QWidget *parent = nullptr)
|
||||||
|
: QtNodes::GraphicsView(scene, parent) {
|
||||||
|
setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
|
||||||
|
setCacheMode(QGraphicsView::CacheNone);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setZoomSensitivity(double sensitivity) {
|
||||||
|
m_sensitivity = sensitivity;
|
||||||
|
}
|
||||||
|
double zoomSensitivity() const { return m_sensitivity; }
|
||||||
|
|
||||||
|
void updateProxyCacheMode() {
|
||||||
|
if (!scene())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const double zoom = transform().m11();
|
||||||
|
const bool highZoom = zoom > 1.4;
|
||||||
|
|
||||||
|
if (highZoom == m_proxiesCached)
|
||||||
|
return;
|
||||||
|
m_proxiesCached = highZoom;
|
||||||
|
|
||||||
|
auto cacheMode = highZoom ? QGraphicsItem::DeviceCoordinateCache
|
||||||
|
: QGraphicsItem::NoCache;
|
||||||
|
for (QGraphicsItem *item : scene()->items()) {
|
||||||
|
if (item->type() == QGraphicsProxyWidget::Type ||
|
||||||
|
item->type() == QtNodes::ConnectionGraphicsObject::Type)
|
||||||
|
item->setCacheMode(cacheMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void wheelEvent(QWheelEvent *event) override {
|
||||||
|
const double dy = event->angleDelta().y();
|
||||||
|
if (dy == 0.0) {
|
||||||
|
event->ignore();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr double kTickUnits = 120.0;
|
||||||
|
const double exponent = dy / kTickUnits;
|
||||||
|
const double factor = std::pow(m_sensitivity, exponent);
|
||||||
|
const double proposed = transform().m11() * factor;
|
||||||
|
setupScale(proposed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mousePressEvent(QMouseEvent *event) override {
|
||||||
|
if (event->button() == Qt::LeftButton) {
|
||||||
|
m_panActive = true;
|
||||||
|
m_panStart = event->pos();
|
||||||
|
}
|
||||||
|
QGraphicsView::mousePressEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouseMoveEvent(QMouseEvent *event) override {
|
||||||
|
if (m_panActive && (event->buttons() & Qt::LeftButton) &&
|
||||||
|
!(event->modifiers() & Qt::ShiftModifier) &&
|
||||||
|
!scene()->mouseGrabberItem()) {
|
||||||
|
QPoint delta = event->pos() - m_panStart;
|
||||||
|
m_panStart = event->pos();
|
||||||
|
horizontalScrollBar()->setValue(horizontalScrollBar()->value() - delta.x());
|
||||||
|
verticalScrollBar()->setValue(verticalScrollBar()->value() - delta.y());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QGraphicsView::mouseMoveEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouseReleaseEvent(QMouseEvent *event) override {
|
||||||
|
if (event->button() == Qt::LeftButton)
|
||||||
|
m_panActive = false;
|
||||||
|
QGraphicsView::mouseReleaseEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawBackground(QPainter *painter, const QRectF &r) override {
|
||||||
|
QGraphicsView::drawBackground(painter, r);
|
||||||
|
|
||||||
|
const double zoom = transform().m11();
|
||||||
|
auto const &style =
|
||||||
|
QtNodes::StyleCollection::flowViewStyle();
|
||||||
|
|
||||||
|
static constexpr double kBaseFine = 15.0;
|
||||||
|
static constexpr double kBaseCoarse = 150.0;
|
||||||
|
static constexpr double kMinPixelSpacing = 10.0;
|
||||||
|
|
||||||
|
double fineStep = kBaseFine;
|
||||||
|
while (fineStep * zoom < kMinPixelSpacing)
|
||||||
|
fineStep *= 2.0;
|
||||||
|
|
||||||
|
double coarseStep = kBaseCoarse;
|
||||||
|
while (coarseStep * zoom < kMinPixelSpacing * 5.0)
|
||||||
|
coarseStep *= 2.0;
|
||||||
|
|
||||||
|
auto drawGrid = [&](double gridStep) {
|
||||||
|
QRect windowRect = rect();
|
||||||
|
QPointF tl = mapToScene(windowRect.topLeft());
|
||||||
|
QPointF br = mapToScene(windowRect.bottomRight());
|
||||||
|
|
||||||
|
double left = std::floor(tl.x() / gridStep - 0.5);
|
||||||
|
double right = std::floor(br.x() / gridStep + 1.0);
|
||||||
|
double bottom = std::floor(tl.y() / gridStep - 0.5);
|
||||||
|
double top = std::floor(br.y() / gridStep + 1.0);
|
||||||
|
|
||||||
|
for (int xi = int(left); xi <= int(right); ++xi)
|
||||||
|
painter->drawLine(QLineF(xi * gridStep, bottom * gridStep,
|
||||||
|
xi * gridStep, top * gridStep));
|
||||||
|
|
||||||
|
for (int yi = int(bottom); yi <= int(top); ++yi)
|
||||||
|
painter->drawLine(QLineF(left * gridStep, yi * gridStep,
|
||||||
|
right * gridStep, yi * gridStep));
|
||||||
|
};
|
||||||
|
|
||||||
|
painter->setPen(QPen(style.FineGridColor, 1.0));
|
||||||
|
drawGrid(fineStep);
|
||||||
|
|
||||||
|
painter->setPen(QPen(style.CoarseGridColor, 1.0));
|
||||||
|
drawGrid(coarseStep);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
double m_sensitivity = 1.2;
|
||||||
|
bool m_proxiesCached = false;
|
||||||
|
bool m_panActive = false;
|
||||||
|
QPoint m_panStart;
|
||||||
|
};
|
||||||
Loading…
Add table
Add a link
Reference in a new issue