Nodes working
This commit is contained in:
parent
87e5aca9d8
commit
bba5d432f5
3 changed files with 78 additions and 13 deletions
|
|
@ -140,6 +140,10 @@ GraphEditorWidget::GraphEditorWidget(Potato::PipeWireController *controller, QWi
|
||||||
m_view->addAction(resetLayoutAction);
|
m_view->addAction(resetLayoutAction);
|
||||||
|
|
||||||
syncGraph();
|
syncGraph();
|
||||||
|
if (m_model->hasOverlaps()) {
|
||||||
|
m_model->autoArrange();
|
||||||
|
m_model->saveLayout();
|
||||||
|
}
|
||||||
double viewScale = 1.0;
|
double viewScale = 1.0;
|
||||||
QPointF viewCenter;
|
QPointF viewCenter;
|
||||||
if (m_model->viewState(viewScale, viewCenter)) {
|
if (m_model->viewState(viewScale, viewCenter)) {
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@
|
||||||
#include <QtCore/QStandardPaths>
|
#include <QtCore/QStandardPaths>
|
||||||
#include <QtGui/QFont>
|
#include <QtGui/QFont>
|
||||||
#include <QtGui/QFontMetrics>
|
#include <QtGui/QFontMetrics>
|
||||||
|
#include <QtCore/QRectF>
|
||||||
|
#include <QtCore/QSizeF>
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
|
@ -36,9 +38,9 @@ int nodeWidthFor(const Potato::NodeInfo &info)
|
||||||
maxTextWidth = std::max(maxTextWidth, portMetrics.horizontalAdvance(port.name));
|
maxTextWidth = std::max(maxTextWidth, portMetrics.horizontalAdvance(port.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
const int widthPadding = 140;
|
const int widthPadding = 180;
|
||||||
const int minWidth = 300;
|
const int minWidth = 320;
|
||||||
const int maxWidth = 520;
|
const int maxWidth = 700;
|
||||||
const int width = maxTextWidth + widthPadding;
|
const int width = maxTextWidth + widthPadding;
|
||||||
return std::max(minWidth, std::min(maxWidth, width));
|
return std::max(minWidth, std::min(maxWidth, width));
|
||||||
}
|
}
|
||||||
|
|
@ -194,8 +196,9 @@ QVariant PipeWireGraphModel::nodeData(QtNodes::NodeId nodeId, QtNodes::NodeRole
|
||||||
{
|
{
|
||||||
QFont captionFont;
|
QFont captionFont;
|
||||||
captionFont.setBold(true);
|
captionFont.setBold(true);
|
||||||
const int width = nodeWidthFor(info) - 40;
|
const int width = nodeWidthFor(info) - 50;
|
||||||
return elideLabel(info.name, width, captionFont);
|
const QString title = info.description.isEmpty() ? info.name : info.description;
|
||||||
|
return elideLabel(title, width, captionFont);
|
||||||
}
|
}
|
||||||
case QtNodes::NodeRole::CaptionVisible:
|
case QtNodes::NodeRole::CaptionVisible:
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -271,13 +274,13 @@ QVariant PipeWireGraphModel::portData(QtNodes::NodeId nodeId,
|
||||||
if (portType == QtNodes::PortType::In) {
|
if (portType == QtNodes::PortType::In) {
|
||||||
if (portIndex < static_cast<QtNodes::PortIndex>(info.inputPorts.size())) {
|
if (portIndex < static_cast<QtNodes::PortIndex>(info.inputPorts.size())) {
|
||||||
QFont font;
|
QFont font;
|
||||||
const int width = nodeWidthFor(info) - 80;
|
const int width = nodeWidthFor(info) - 100;
|
||||||
return elideLabel(info.inputPorts.at(portIndex).name, width, font);
|
return elideLabel(info.inputPorts.at(portIndex).name, width, font);
|
||||||
}
|
}
|
||||||
} else if (portType == QtNodes::PortType::Out) {
|
} else if (portType == QtNodes::PortType::Out) {
|
||||||
if (portIndex < static_cast<QtNodes::PortIndex>(info.outputPorts.size())) {
|
if (portIndex < static_cast<QtNodes::PortIndex>(info.outputPorts.size())) {
|
||||||
QFont font;
|
QFont font;
|
||||||
const int width = nodeWidthFor(info) - 80;
|
const int width = nodeWidthFor(info) - 100;
|
||||||
return elideLabel(info.outputPorts.at(portIndex).name, width, font);
|
return elideLabel(info.outputPorts.at(portIndex).name, width, font);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -473,9 +476,19 @@ void PipeWireGraphModel::autoArrange()
|
||||||
return left < right;
|
return left < right;
|
||||||
});
|
});
|
||||||
|
|
||||||
const int columns = 4;
|
int maxWidth = 0;
|
||||||
const qreal spacingX = 260.0;
|
int maxHeight = 0;
|
||||||
const qreal spacingY = 160.0;
|
for (const auto &entry : m_nodes) {
|
||||||
|
const Potato::NodeInfo &info = entry.second;
|
||||||
|
maxWidth = std::max(maxWidth, nodeWidthFor(info));
|
||||||
|
const int ports = std::max(info.inputPorts.size(), info.outputPorts.size());
|
||||||
|
const int height = std::max(110, 70 + (ports * 28));
|
||||||
|
maxHeight = std::max(maxHeight, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
const int columns = 3;
|
||||||
|
const qreal spacingX = static_cast<qreal>(maxWidth + 160);
|
||||||
|
const qreal spacingY = static_cast<qreal>(maxHeight + 120);
|
||||||
|
|
||||||
for (int i = 0; i < static_cast<int>(ids.size()); ++i) {
|
for (int i = 0; i < static_cast<int>(ids.size()); ++i) {
|
||||||
const int row = i / columns;
|
const int row = i / columns;
|
||||||
|
|
@ -621,14 +634,61 @@ QString PipeWireGraphModel::portLabel(const Potato::PortInfo &port) const
|
||||||
QPointF PipeWireGraphModel::nextPosition() const
|
QPointF PipeWireGraphModel::nextPosition() const
|
||||||
{
|
{
|
||||||
const int index = static_cast<int>(m_positions.size());
|
const int index = static_cast<int>(m_positions.size());
|
||||||
const int columns = 4;
|
int maxWidth = 0;
|
||||||
const qreal spacingX = 260.0;
|
int maxHeight = 0;
|
||||||
const qreal spacingY = 160.0;
|
for (const auto &entry : m_nodes) {
|
||||||
|
const Potato::NodeInfo &info = entry.second;
|
||||||
|
maxWidth = std::max(maxWidth, nodeWidthFor(info));
|
||||||
|
const int ports = std::max(info.inputPorts.size(), info.outputPorts.size());
|
||||||
|
const int height = std::max(110, 70 + (ports * 28));
|
||||||
|
maxHeight = std::max(maxHeight, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
const int columns = 3;
|
||||||
|
const qreal spacingX = static_cast<qreal>(maxWidth + 160);
|
||||||
|
const qreal spacingY = static_cast<qreal>(maxHeight + 120);
|
||||||
const int row = index / columns;
|
const int row = index / columns;
|
||||||
const int col = index % columns;
|
const int col = index % columns;
|
||||||
return QPointF(col * spacingX, row * spacingY);
|
return QPointF(col * spacingX, row * spacingY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PipeWireGraphModel::hasOverlaps() const
|
||||||
|
{
|
||||||
|
struct NodeBox {
|
||||||
|
QtNodes::NodeId id;
|
||||||
|
QRectF rect;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<NodeBox> boxes;
|
||||||
|
boxes.reserve(m_nodes.size());
|
||||||
|
|
||||||
|
for (const auto &entry : m_nodes) {
|
||||||
|
const QtNodes::NodeId nodeId = entry.first;
|
||||||
|
const auto posIt = m_positions.find(nodeId);
|
||||||
|
if (posIt == m_positions.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Potato::NodeInfo &info = entry.second;
|
||||||
|
const int width = nodeWidthFor(info);
|
||||||
|
const int ports = std::max(info.inputPorts.size(), info.outputPorts.size());
|
||||||
|
const int height = std::max(110, 70 + (ports * 28));
|
||||||
|
|
||||||
|
QRectF rect(posIt->second, QSizeF(width, height));
|
||||||
|
boxes.push_back({nodeId, rect});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < boxes.size(); ++i) {
|
||||||
|
for (size_t j = i + 1; j < boxes.size(); ++j) {
|
||||||
|
if (boxes[i].rect.intersects(boxes[j].rect)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
QString PipeWireGraphModel::layoutFilePath() const
|
QString PipeWireGraphModel::layoutFilePath() const
|
||||||
{
|
{
|
||||||
const QString baseDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
const QString baseDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ public:
|
||||||
const Potato::NodeInfo *nodeInfo(QtNodes::NodeId nodeId) const;
|
const Potato::NodeInfo *nodeInfo(QtNodes::NodeId nodeId) const;
|
||||||
bool connectionIdForLink(const Potato::LinkInfo &link, QtNodes::ConnectionId &connectionId) const;
|
bool connectionIdForLink(const Potato::LinkInfo &link, QtNodes::ConnectionId &connectionId) const;
|
||||||
bool updatePipeWireNode(const Potato::NodeInfo &node);
|
bool updatePipeWireNode(const Potato::NodeInfo &node);
|
||||||
|
bool hasOverlaps() const;
|
||||||
void reset();
|
void reset();
|
||||||
void loadLayout();
|
void loadLayout();
|
||||||
void saveLayout() const;
|
void saveLayout() const;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue