1
0
mirror of https://github.com/juzzlin/Heimer.git synced 2025-05-09 21:01:39 +08:00

Introduce EdgeModel

This commit is contained in:
Jussi Lind 2022-11-08 22:33:30 +02:00
parent 094cf9dd90
commit c7c8f51ca8
14 changed files with 104 additions and 70 deletions

View File

@ -28,6 +28,7 @@ set(LIB_SRC
edge.cpp
edge_context_menu.cpp
edge_dot.cpp
edge_model.hpp
edge_point.hpp
edge_text_edit.cpp
editor_data.cpp

View File

@ -391,7 +391,7 @@ static EdgeU readEdge(const QDomElement & element, MindMapData & data)
// Initialize a new edge. QGraphicsScene will take the ownership eventually.
auto edge = std::make_unique<Edge>(data.graph().getNode(index0), data.graph().getNode(index1));
edge->setArrowMode(static_cast<Edge::ArrowMode>(arrowMode));
edge->setArrowMode(static_cast<EdgeModel::ArrowMode>(arrowMode));
edge->setDashedLine(dashedLine);
edge->setReversed(reversed);

View File

@ -76,9 +76,9 @@ void DefaultsTab::createEdgeWidgets(QVBoxLayout & mainLayout)
const auto edgeGroup = WidgetFactory::buildGroupBoxWithVLayout(tr("Edge Arrow Style"), mainLayout);
m_edgeArrowStyleRadioMap = {
{ Edge::ArrowMode::Hidden, new QRadioButton(tr("No arrow")) },
{ Edge::ArrowMode::Single, new QRadioButton(tr("Single arrow")) },
{ Edge::ArrowMode::Double, new QRadioButton(tr("Double arrow")) }
{ EdgeModel::ArrowMode::Hidden, new QRadioButton(tr("No arrow")) },
{ EdgeModel::ArrowMode::Single, new QRadioButton(tr("Single arrow")) },
{ EdgeModel::ArrowMode::Double, new QRadioButton(tr("Double arrow")) }
};
const auto edgeArrowRadioGroup = new QButtonGroup;

View File

@ -44,7 +44,7 @@ private:
void setActiveDefaults();
std::map<Edge::ArrowMode, QRadioButton *> m_edgeArrowStyleRadioMap;
std::map<EdgeModel::ArrowMode, QRadioButton *> m_edgeArrowStyleRadioMap;
QCheckBox * m_edgeDirectionCheckBox = nullptr;

View File

@ -42,10 +42,9 @@
#include <cmath>
Edge::Edge(NodeP sourceNode, NodeP targetNode, bool enableAnimations, bool enableLabel)
: m_sourceNode(sourceNode)
: m_edgeModel(std::make_unique<EdgeModel>(SettingsProxy::instance().reversedEdgeDirection(), SettingsProxy::instance().edgeArrowMode()))
, m_sourceNode(sourceNode)
, m_targetNode(targetNode)
, m_reversed(SettingsProxy::instance().reversedEdgeDirection())
, m_arrowMode(SettingsProxy::instance().edgeArrowMode())
, m_enableAnimations(enableAnimations)
, m_enableLabel(enableLabel)
, m_sourceDot(enableAnimations ? new EdgeDot(this) : nullptr)
@ -72,7 +71,7 @@ Edge::Edge(NodeP sourceNode, NodeP targetNode, bool enableAnimations, bool enabl
m_label->setBackgroundColor(Constants::Edge::LABEL_COLOR);
connect(m_label, &TextEdit::textChanged, this, [=](const QString & text) {
updateLabel();
m_text = text;
m_edgeModel->text = text;
});
connect(m_label, &TextEdit::undoPointRequested, this, &Edge::undoPointRequested);
@ -137,7 +136,7 @@ QPen Edge::buildPen(bool ignoreDashSetting) const
{
QPen pen { QBrush { QColor { m_color.red(), m_color.green(), m_color.blue() } }, m_edgeWidth };
pen.setCapStyle(Qt::PenCapStyle::RoundCap);
if (!ignoreDashSetting && m_dashedLine) {
if (!ignoreDashSetting && m_edgeModel->dashedLine) {
pen.setDashPattern(Constants::Edge::DASH_PATTERN);
}
return pen;
@ -145,11 +144,9 @@ QPen Edge::buildPen(bool ignoreDashSetting) const
void Edge::copyData(EdgeCR other)
{
m_arrowMode = other.m_arrowMode;
m_dashedLine = other.m_dashedLine;
m_reversed = other.m_reversed;
*m_edgeModel = *other.m_edgeModel;
setText(other.m_text); // Update text to the label component
setText(other.m_edgeModel->text); // Update text to the label component
}
void Edge::changeFont(const QFont & font)
@ -167,7 +164,7 @@ void Edge::changeFont(const QFont & font)
bool Edge::dashedLine() const
{
return m_dashedLine;
return m_edgeModel->dashedLine;
}
void Edge::initDots()
@ -254,9 +251,9 @@ void Edge::setEdgeWidth(double edgeWidth)
updateLine();
}
void Edge::setArrowMode(ArrowMode arrowMode)
void Edge::setArrowMode(EdgeModel::ArrowMode arrowMode)
{
m_arrowMode = arrowMode;
m_edgeModel->arrowMode = arrowMode;
if (!TestMode::enabled()) {
updateLine();
} else {
@ -280,7 +277,7 @@ void Edge::setColor(const QColor & color)
void Edge::setDashedLine(bool enable)
{
m_dashedLine = enable;
m_edgeModel->dashedLine = enable;
if (!TestMode::enabled()) {
updateLine();
} else {
@ -290,7 +287,7 @@ void Edge::setDashedLine(bool enable)
void Edge::setText(const QString & text)
{
m_text = text;
m_edgeModel->text = text;
if (!TestMode::enabled()) {
if (m_enableLabel) {
m_label->setText(text);
@ -311,7 +308,7 @@ void Edge::setTextSize(int textSize)
void Edge::setReversed(bool reversed)
{
m_reversed = reversed;
m_edgeModel->reversed = reversed;
updateArrowhead();
}
@ -349,18 +346,19 @@ void Edge::updateArrowhead()
{
setArrowHeadPen(buildPen(true));
const auto point0 = m_reversed ? this->line().p1() : this->line().p2();
const auto angle0 = m_reversed ? -this->line().angle() + 180 : -this->line().angle();
const auto point1 = m_reversed ? this->line().p2() : this->line().p1();
const auto angle1 = m_reversed ? -this->line().angle() : -this->line().angle() + 180;
const auto reversed = m_edgeModel->reversed;
const auto point0 = reversed ? this->line().p1() : this->line().p2();
const auto angle0 = reversed ? -this->line().angle() + 180 : -this->line().angle();
const auto point1 = reversed ? this->line().p2() : this->line().p1();
const auto angle1 = reversed ? -this->line().angle() : -this->line().angle() + 180;
QLineF lineL0;
QLineF lineR0;
QLineF lineL1;
QLineF lineR1;
switch (m_arrowMode) {
case ArrowMode::Single: {
switch (m_edgeModel->arrowMode) {
case EdgeModel::ArrowMode::Single: {
lineL0.setP1(point0);
const auto angleL = qDegreesToRadians(angle0 + Constants::Edge::ARROW_OPENING);
lineL0.setP2(point0 + QPointF(std::cos(angleL), std::sin(angleL)) * m_arrowSize);
@ -375,7 +373,7 @@ void Edge::updateArrowhead()
m_arrowheadR1->hide();
break;
}
case ArrowMode::Double: {
case EdgeModel::ArrowMode::Double: {
lineL0.setP1(point0);
const auto angleL0 = qDegreesToRadians(angle0 + Constants::Edge::ARROW_OPENING);
lineL0.setP2(point0 + QPointF(std::cos(angleL0), std::sin(angleL0)) * m_arrowSize);
@ -398,7 +396,7 @@ void Edge::updateArrowhead()
m_arrowheadR1->show();
break;
}
case ArrowMode::Hidden:
case EdgeModel::ArrowMode::Hidden:
m_arrowheadL0->hide();
m_arrowheadR0->hide();
m_arrowheadL1->hide();
@ -458,7 +456,7 @@ void Edge::setSourceNode(NodeR sourceNode)
bool Edge::reversed() const
{
return m_reversed;
return m_edgeModel->reversed;
}
void Edge::restoreLabelParent()
@ -468,14 +466,14 @@ void Edge::restoreLabelParent()
}
}
Edge::ArrowMode Edge::arrowMode() const
EdgeModel::ArrowMode Edge::arrowMode() const
{
return m_arrowMode;
return m_edgeModel->arrowMode;
}
QString Edge::text() const
{
return m_text;
return m_edgeModel->text;
}
void Edge::updateLine()

View File

@ -23,6 +23,7 @@
#include <memory>
#include "constants.hpp"
#include "edge_model.hpp"
#include "edge_point.hpp"
#include "edge_text_edit.hpp"
#include "types.hpp"
@ -33,6 +34,7 @@ class Node;
class QFont;
class QGraphicsEllipseItem;
class QPropertyAnimation;
struct ShadowEffectParams;
//! A graphic representation of a graph edge between nodes.
@ -41,12 +43,6 @@ class Edge : public QObject, public QGraphicsLineItem
Q_OBJECT
public:
enum class ArrowMode
{
Single = 0,
Double = 1,
Hidden = 2
};
//! Constructor.
//! Note!!: We are using raw pointers here because the edge only must only refer to the nodes.
@ -64,7 +60,7 @@ public:
virtual ~Edge() override;
ArrowMode arrowMode() const;
EdgeModel::ArrowMode arrowMode() const;
bool dashedLine() const;
@ -92,7 +88,7 @@ public slots:
void updateLine();
void setArrowMode(ArrowMode arrowMode);
void setArrowMode(EdgeModel::ArrowMode arrowMode);
void setArrowSize(double arrowSize);
@ -139,12 +135,12 @@ private:
void updateLabel(LabelUpdateReason lur = LabelUpdateReason::Default);
std::unique_ptr<EdgeModel> m_edgeModel;
NodeP m_sourceNode = nullptr;
NodeP m_targetNode = nullptr;
QString m_text;
double m_arrowSize = Constants::Edge::Defaults::ARROW_SIZE;
double m_edgeWidth = Constants::MindMap::Defaults::EDGE_WIDTH;
@ -153,14 +149,8 @@ private:
QColor m_color;
bool m_reversed;
bool m_selected = false;
ArrowMode m_arrowMode;
bool m_dashedLine = false;
bool m_enableAnimations;
bool m_enableLabel;

View File

@ -33,14 +33,14 @@ EdgeContextMenu::EdgeContextMenu(QWidget * parent, Mediator & mediator)
const auto showEdgeArrowAction(new QAction(tr("Show arrow"), this));
QObject::connect(showEdgeArrowAction, &QAction::triggered, this, [=] {
m_mediator.saveUndoPoint();
m_mediator.selectedEdge()->setArrowMode(showEdgeArrowAction->isChecked() ? Edge::ArrowMode::Single : Edge::ArrowMode::Hidden);
m_mediator.selectedEdge()->setArrowMode(showEdgeArrowAction->isChecked() ? EdgeModel::ArrowMode::Single : EdgeModel::ArrowMode::Hidden);
});
showEdgeArrowAction->setCheckable(true);
const auto doubleArrowAction(new QAction(tr("Double arrow"), this));
QObject::connect(doubleArrowAction, &QAction::triggered, this, [=] {
m_mediator.saveUndoPoint();
m_mediator.selectedEdge()->setArrowMode(doubleArrowAction->isChecked() ? Edge::ArrowMode::Double : Edge::ArrowMode::Single);
m_mediator.selectedEdge()->setArrowMode(doubleArrowAction->isChecked() ? EdgeModel::ArrowMode::Double : EdgeModel::ArrowMode::Single);
});
doubleArrowAction->setCheckable(true);
@ -76,10 +76,10 @@ EdgeContextMenu::EdgeContextMenu(QWidget * parent, Mediator & mediator)
connect(this, &QMenu::aboutToShow, this, [=] {
m_selectedEdge = m_mediator.selectedEdge();
assert(m_selectedEdge);
changeEdgeDirectionAction->setEnabled(m_selectedEdge->arrowMode() != Edge::ArrowMode::Double && m_selectedEdge->arrowMode() != Edge::ArrowMode::Hidden);
changeEdgeDirectionAction->setEnabled(m_selectedEdge->arrowMode() != EdgeModel::ArrowMode::Double && m_selectedEdge->arrowMode() != EdgeModel::ArrowMode::Hidden);
dashedLineAction->setChecked(m_selectedEdge->dashedLine());
doubleArrowAction->setChecked(m_selectedEdge->arrowMode() == Edge::ArrowMode::Double);
showEdgeArrowAction->setChecked(m_selectedEdge->arrowMode() != Edge::ArrowMode::Hidden);
doubleArrowAction->setChecked(m_selectedEdge->arrowMode() == EdgeModel::ArrowMode::Double);
showEdgeArrowAction->setChecked(m_selectedEdge->arrowMode() != EdgeModel::ArrowMode::Hidden);
});
// Always clear edge selection when the menu closes.

45
src/edge_model.hpp Normal file
View File

@ -0,0 +1,45 @@
// This file is part of Heimer.
// Copyright (C) 2022 Jussi Lind <jussi.lind@iki.fi>
//
// Heimer is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Heimer is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Heimer. If not, see <http://www.gnu.org/licenses/>.
#ifndef EDGE_MODEL_HPP
#define EDGE_MODEL_HPP
#include <QString>
struct EdgeModel
{
enum class ArrowMode
{
Single = 0,
Double = 1,
Hidden = 2
};
EdgeModel(bool reversed, ArrowMode arrowMode)
: arrowMode(arrowMode)
, reversed(reversed)
{
}
ArrowMode arrowMode;
bool dashedLine = false;
bool reversed;
QString text;
};
#endif // EDGE_MODEL_HPP

View File

@ -92,16 +92,16 @@ void saveAutoSnapState(int state)
settings.endGroup();
}
Edge::ArrowMode loadEdgeArrowMode(Edge::ArrowMode defaultMode)
EdgeModel::ArrowMode loadEdgeArrowMode(EdgeModel::ArrowMode defaultMode)
{
QSettings settings;
settings.beginGroup(Constants::MindMap::Defaults::SETTINGS_GROUP);
const auto mode = static_cast<Edge::ArrowMode>(settings.value(edgeArrowModeKey, static_cast<int>(defaultMode)).toInt());
const auto mode = static_cast<EdgeModel::ArrowMode>(settings.value(edgeArrowModeKey, static_cast<int>(defaultMode)).toInt());
settings.endGroup();
return mode;
}
void saveEdgeArrowMode(Edge::ArrowMode mode)
void saveEdgeArrowMode(EdgeModel::ArrowMode mode)
{
QSettings settings;
settings.beginGroup(Constants::MindMap::Defaults::SETTINGS_GROUP);

View File

@ -32,9 +32,9 @@ Qt::CheckState loadAutoSnapState();
void saveAutoSnapState(int state);
Edge::ArrowMode loadEdgeArrowMode(Edge::ArrowMode defaultMode);
EdgeModel::ArrowMode loadEdgeArrowMode(EdgeModel::ArrowMode defaultMode);
void saveEdgeArrowMode(Edge::ArrowMode mode);
void saveEdgeArrowMode(EdgeModel::ArrowMode mode);
bool loadReversedEdgeDirection(bool defaultDirection);

View File

@ -25,7 +25,7 @@ SettingsProxy::SettingsProxy()
, m_gridColor(Settings::V2::getColor(Constants::MindMap::Defaults::SETTINGS_GROUP, Constants::MindMap::Defaults::GRID_COLOR_SETTINGS_KEY, Constants::MindMap::Defaults::GRID_COLOR))
, m_nodeColor(Settings::V2::getColor(Constants::MindMap::Defaults::SETTINGS_GROUP, Constants::MindMap::Defaults::NODE_COLOR_SETTINGS_KEY, Constants::MindMap::Defaults::NODE_COLOR))
, m_nodeTextColor(Settings::V2::getColor(Constants::MindMap::Defaults::SETTINGS_GROUP, Constants::MindMap::Defaults::NODE_TEXT_COLOR_SETTINGS_KEY, Constants::MindMap::Defaults::NODE_TEXT_COLOR))
, m_edgeArrowMode(Settings::V1::loadEdgeArrowMode(Edge::ArrowMode::Single))
, m_edgeArrowMode(Settings::V1::loadEdgeArrowMode(EdgeModel::ArrowMode::Single))
, m_reversedEdgeDirection(Settings::V1::loadReversedEdgeDirection(false))
, m_selectNodeGroupByIntersection(Settings::V1::loadSelectNodeGroupByIntersection())
, m_shadowEffectParams(
@ -123,12 +123,12 @@ void SettingsProxy::setNodeTextColor(const QColor & nodeTextColor)
}
}
Edge::ArrowMode SettingsProxy::edgeArrowMode() const
EdgeModel::ArrowMode SettingsProxy::edgeArrowMode() const
{
return m_edgeArrowMode;
}
void SettingsProxy::setEdgeArrowMode(Edge::ArrowMode mode)
void SettingsProxy::setEdgeArrowMode(EdgeModel::ArrowMode mode)
{
if (m_edgeArrowMode != mode) {
m_edgeArrowMode = mode;

View File

@ -53,9 +53,9 @@ public:
void setNodeTextColor(const QColor & nodeTextColor);
Edge::ArrowMode edgeArrowMode() const;
EdgeModel::ArrowMode edgeArrowMode() const;
void setEdgeArrowMode(Edge::ArrowMode mode);
void setEdgeArrowMode(EdgeModel::ArrowMode mode);
bool reversedEdgeDirection() const;
@ -82,7 +82,7 @@ private:
QColor m_nodeTextColor;
Edge::ArrowMode m_edgeArrowMode;
EdgeModel::ArrowMode m_edgeArrowMode;
bool m_reversedEdgeDirection = false;

View File

@ -306,7 +306,7 @@ void AlzFileIOTest::testSingleEdge()
const auto edge = std::make_shared<Edge>(outNode0, outNode1);
const QString text = "Lorem ipsum";
edge->setArrowMode(Edge::ArrowMode::Double);
edge->setArrowMode(EdgeModel::ArrowMode::Double);
edge->setDashedLine(true);
edge->setReversed(true);
edge->setText(text);

View File

@ -357,21 +357,21 @@ void EditorDataTest::testUndoArrowMode()
const auto edge01 = std::make_shared<Edge>(node0, node1);
editorData.addEdge(edge01);
QCOMPARE(edge01->arrowMode(), Edge::ArrowMode::Single);
QCOMPARE(edge01->arrowMode(), EdgeModel::ArrowMode::Single);
edge01->setArrowMode(Edge::ArrowMode::Double);
edge01->setArrowMode(EdgeModel::ArrowMode::Double);
editorData.saveUndoPoint();
edge01->setArrowMode(Edge::ArrowMode::Hidden);
edge01->setArrowMode(EdgeModel::ArrowMode::Hidden);
editorData.undo();
QCOMPARE(editorData.mindMapData()->graph().getEdges().at(0)->arrowMode(), Edge::ArrowMode::Double);
QCOMPARE(editorData.mindMapData()->graph().getEdges().at(0)->arrowMode(), EdgeModel::ArrowMode::Double);
editorData.redo();
QCOMPARE(editorData.mindMapData()->graph().getEdges().at(0)->arrowMode(), Edge::ArrowMode::Hidden);
QCOMPARE(editorData.mindMapData()->graph().getEdges().at(0)->arrowMode(), EdgeModel::ArrowMode::Hidden);
}
void EditorDataTest::testUndoArrowSize()