summaryrefslogtreecommitdiff
path: root/tikzit
diff options
context:
space:
mode:
authorAleks Kissinger <aleks0@gmail.com>2017-02-28 14:46:39 +0100
committerAleks Kissinger <aleks0@gmail.com>2017-02-28 14:46:39 +0100
commitcb322a3acee9debf40c48ad1e3fb4458b0f51b7f (patch)
tree2cd3dc1060885152f0c706e0cf52bff0d8181d1e /tikzit
parente1756ba69dd626073e22fd0a4f4c5fda42c88829 (diff)
generic nodes
Diffstat (limited to 'tikzit')
-rw-r--r--tikzit/src/data/edge.cpp211
-rw-r--r--tikzit/src/data/edge.h35
-rw-r--r--tikzit/src/data/node.cpp25
-rw-r--r--tikzit/src/data/node.h9
-rw-r--r--tikzit/src/data/nodestyle.cpp30
-rw-r--r--tikzit/src/data/nodestyle.h26
-rw-r--r--tikzit/src/gui/edgeitem.cpp89
-rw-r--r--tikzit/src/gui/edgeitem.h28
-rw-r--r--tikzit/src/gui/mainwindow.cpp57
-rw-r--r--tikzit/src/gui/mainwindow.h11
-rw-r--r--tikzit/src/gui/mainwindow.ui55
-rw-r--r--tikzit/src/gui/nodeitem.cpp82
-rw-r--r--tikzit/src/gui/nodeitem.h9
-rw-r--r--tikzit/src/gui/propertypalette.cpp1
-rw-r--r--tikzit/src/gui/tikzscene.cpp64
-rw-r--r--tikzit/src/gui/tikzscene.h10
-rw-r--r--tikzit/src/gui/tikzview.cpp65
-rw-r--r--tikzit/src/gui/tikzview.h5
-rw-r--r--tikzit/src/gui/toolpalette.cpp1
-rw-r--r--tikzit/src/main.cpp19
-rw-r--r--tikzit/src/test/testparser.cpp31
-rw-r--r--tikzit/src/test/testparser.h1
-rw-r--r--tikzit/src/tikzit.cpp132
-rw-r--r--tikzit/src/tikzit.h73
-rw-r--r--tikzit/tikzit.pro16
-rw-r--r--tikzit/tikzit.pro.user2
26 files changed, 938 insertions, 149 deletions
diff --git a/tikzit/src/data/edge.cpp b/tikzit/src/data/edge.cpp
index 9068a1c..b999f8a 100644
--- a/tikzit/src/data/edge.cpp
+++ b/tikzit/src/data/edge.cpp
@@ -1,12 +1,22 @@
#include "edge.h"
+#include "tikzit.h"
#include <QDebug>
+#include <QPointF>
+#include <cmath>
Edge::Edge(Node *s, Node *t, QObject *parent) :
QObject(parent), _source(s), _target(t)
{
_data = new GraphElementData();
_edgeNode = 0;
+ _dirty = true;
+ _basicBendMode = true;
+ _bend = 0;
+ _inAngle = 0;
+ _outAngle = 0;
+ _weight = 0.4f;
+ updateControls();
}
Edge::~Edge()
@@ -25,6 +35,16 @@ Node *Edge::target() const
return _target;
}
+bool Edge::isSelfLoop()
+{
+ return (_source == _target);
+}
+
+bool Edge::isStraight()
+{
+ return (_basicBendMode && _bend == 0);
+}
+
GraphElementData *Edge::data() const
{
return _data;
@@ -34,6 +54,7 @@ void Edge::setData(GraphElementData *data)
{
delete _data;
_data = data;
+ setAttributesFromData();
}
QString Edge::sourceAnchor() const
@@ -72,4 +93,194 @@ bool Edge::hasEdgeNode()
return _edgeNode != 0;
}
+void Edge::updateControls() {
+ //if (_dirty) {
+ QPointF src = _source->point();
+ QPointF targ = _target->point();
+
+ float dx = (targ.x() - src.x());
+ float dy = (targ.y() - src.y());
+
+ float outAngleR = 0.0f;
+ float inAngleR = 0.0f;
+
+ if (_basicBendMode) {
+ float angle = std::atan2(dy, dx);
+ float bnd = (float)_bend * (M_PI / 180.0f);
+ outAngleR = angle - bnd;
+ inAngleR = M_PI + angle + bnd;
+ _outAngle = outAngleR * (180.f / M_PI);
+ _inAngle = inAngleR * (180.f / M_PI);
+ } else {
+ outAngleR = (float)_outAngle * (M_PI / 180.0f);
+ inAngleR = (float)_inAngle * (M_PI / 180.0f);
+ }
+
+ // TODO: calculate head and tail properly, not just for circles
+ if (_source->style().isNone()) {
+ _tail = src;
+ } else {
+ _tail = QPointF(src.x() + std::cos(outAngleR) * 0.1,
+ src.y() + std::sin(outAngleR) * 0.1);
+ }
+
+ if (_target->style().isNone()) {
+ _head = targ;
+ } else {
+ _head = QPointF(targ.x() + std::cos(inAngleR) * 0.1,
+ targ.y() + std::sin(inAngleR) * 0.1);
+ }
+
+ // give a default distance for self-loops
+ _cpDist = (dx==0.0f && dy==0.0f) ? _weight : std::sqrt(dx*dx + dy*dy) * _weight;
+
+ _cp1 = QPointF(src.x() + (_cpDist * std::cos(outAngleR)),
+ src.y() + (_cpDist * std::sin(outAngleR)));
+
+ _cp2 = QPointF(targ.x() + (_cpDist * std::cos(inAngleR)),
+ targ.y() + (_cpDist * std::sin(inAngleR)));
+
+ _mid = bezierInterpolateFull (0.5f, _tail, _cp1, _cp2, _head);
+// midTan = [self _findTanFor:mid usingSpanFrom:0.4f to:0.6f];
+
+// tailTan = [self _findTanFor:tail usingSpanFrom:0.0f to:0.1f];
+// headTan = [self _findTanFor:head usingSpanFrom:1.0f to:0.9f];
+ //_dirty = false;
+ //}
+}
+
+void Edge::setAttributesFromData()
+{
+ _basicBendMode = true;
+ bool ok = true;
+
+ if (_data->atom("bend left")) {
+ _bend = -30;
+ } else if (_data->atom("bend right")) {
+ _bend = 30;
+ } else if (_data->property("bend left") != 0) {
+ _bend = -_data->property("bend left").toInt(&ok);
+ if (!ok) _bend = -30;
+ } else if (_data->property("bend right") != 0) {
+ _bend = _data->property("bend right").toInt(&ok);
+ if (!ok) _bend = 30;
+ } else {
+ _bend = 0;
+
+ if (_data->property("in") != 0 && _data->property("out") != 0) {
+ _basicBendMode = false;
+ _inAngle = _data->property("in").toInt(&ok);
+ if (!ok) _inAngle = 0;
+ _outAngle = _data->property("out").toInt(&ok);
+ if (!ok) _outAngle = 180;
+ }
+ }
+
+ if (_data->property("looseness") != 0) {
+ _weight = _data->property("looseness").toFloat(&ok) / 2.5f;
+ if (!ok) _weight = 0.4f;
+ } else {
+ _weight = (isSelfLoop()) ? 1.0f : 0.4f;
+ }
+
+ //qDebug() << "bend: " << _bend << " in: " << _inAngle << " out: " << _outAngle;
+ _dirty = true;
+}
+
+void Edge::updateData()
+{
+ _data->unsetAtom("loop");
+ _data->unsetProperty("in");
+ _data->unsetProperty("out");
+ _data->unsetAtom("bend left");
+ _data->unsetAtom("bend right");
+ _data->unsetProperty("bend left");
+ _data->unsetProperty("bend right");
+ _data->unsetProperty("looseness");
+
+ // TODO: style handling?
+
+ if (_basicBendMode && _bend != 0) {
+ QString bendKey;
+ int b;
+ if (_bend < 0) {
+ bendKey = "bend left";
+ b = -_bend;
+ } else {
+ bendKey = "bend right";
+ b = _bend;
+ }
+
+ if (b == 30) {
+ _data->setAtom(bendKey);
+ } else {
+ _data->setProperty(bendKey, QString::number(b));
+ }
+ } else {
+ _data->setProperty("in", QString::number(_inAngle));
+ _data->setProperty("out", QString::number(_outAngle));
+ }
+
+ if (_source == _target) _data->setAtom("loop");
+ if (!isSelfLoop() && !isStraight() && _weight != 0.4f)
+ _data->setProperty("looseness", QString::number(_weight*2.5f, 'f', 2));
+
+}
+
+
+QPointF Edge::head() const
+{
+ return _head;
+}
+
+QPointF Edge::tail() const
+{
+ return _tail;
+}
+
+QPointF Edge::cp1() const
+{
+ return _cp1;
+}
+
+QPointF Edge::cp2() const
+{
+ return _cp2;
+}
+
+int Edge::bend() const
+{
+ return _bend;
+}
+
+int Edge::inAngle() const
+{
+ return _inAngle;
+}
+
+int Edge::outAngle() const
+{
+ return _outAngle;
+}
+
+float Edge::weight() const
+{
+ return _weight;
+}
+
+bool Edge::basicBendMode() const
+{
+ return _basicBendMode;
+}
+
+float Edge::cpDist() const
+{
+ return _cpDist;
+}
+
+QPointF Edge::mid() const
+{
+ return _mid;
+}
+
diff --git a/tikzit/src/data/edge.h b/tikzit/src/data/edge.h
index 9655e98..e392c56 100644
--- a/tikzit/src/data/edge.h
+++ b/tikzit/src/data/edge.h
@@ -5,6 +5,7 @@
#include "node.h"
#include <QObject>
+#include <QPointF>
class Edge : public QObject
{
@@ -16,6 +17,9 @@ public:
Node *source() const;
Node *target() const;
+ bool isSelfLoop();
+ bool isStraight();
+
GraphElementData *data() const;
void setData(GraphElementData *data);
@@ -29,6 +33,23 @@ public:
void setEdgeNode(Node *edgeNode);
bool hasEdgeNode();
+ void updateControls();
+ void setAttributesFromData();
+ void updateData();
+
+ QPointF head() const;
+ QPointF tail() const;
+ QPointF cp1() const;
+ QPointF cp2() const;
+ QPointF mid() const;
+
+ int bend() const;
+ int inAngle() const;
+ int outAngle() const;
+ float weight() const;
+ bool basicBendMode() const;
+ float cpDist() const;
+
signals:
public slots:
@@ -44,6 +65,20 @@ private:
// referenced
Node *_source;
Node *_target;
+
+ bool _dirty;
+ bool _basicBendMode;
+ int _bend;
+ int _inAngle;
+ int _outAngle;
+ float _weight;
+ float _cpDist;
+
+ QPointF _head;
+ QPointF _tail;
+ QPointF _cp1;
+ QPointF _cp2;
+ QPointF _mid;
};
#endif // EDGE_H
diff --git a/tikzit/src/data/node.cpp b/tikzit/src/data/node.cpp
index b3b2155..1b8ccf8 100644
--- a/tikzit/src/data/node.cpp
+++ b/tikzit/src/data/node.cpp
@@ -1,10 +1,13 @@
#include "node.h"
+#include "tikzit.h"
#include <QDebug>
Node::Node(QObject *parent) : QObject(parent)
{
_data = new GraphElementData();
+ _style = NodeStyle();
+ _styleName = "none";
}
Node::~Node()
@@ -51,5 +54,27 @@ void Node::setData(GraphElementData *data)
{
delete _data;
_data = data;
+ if (_data->property("style") != 0) _styleName = _data->property("style");
+}
+
+QString Node::styleName() const
+{
+ return _styleName;
+}
+
+void Node::setStyleName(const QString &styleName)
+{
+ _styleName = styleName;
+}
+
+void Node::attachStyle()
+{
+ if (_styleName == "none") _style = NodeStyle();
+ else _style = tikzit->nodeStyle(_styleName);
+}
+
+NodeStyle Node::style() const
+{
+ return _style;
}
diff --git a/tikzit/src/data/node.h b/tikzit/src/data/node.h
index e72e9a7..91b1725 100644
--- a/tikzit/src/data/node.h
+++ b/tikzit/src/data/node.h
@@ -2,6 +2,7 @@
#define NODE_H
#include "graphelementdata.h"
+#include "nodestyle.h"
#include <QObject>
#include <QPointF>
@@ -26,6 +27,12 @@ public:
GraphElementData *data() const;
void setData(GraphElementData *data);
+ QString styleName() const;
+ void setStyleName(const QString &styleName);
+
+ void attachStyle();
+ NodeStyle style() const;
+
signals:
public slots:
@@ -34,6 +41,8 @@ private:
QPointF _point;
QString _name;
QString _label;
+ QString _styleName;
+ NodeStyle _style;
GraphElementData *_data;
};
diff --git a/tikzit/src/data/nodestyle.cpp b/tikzit/src/data/nodestyle.cpp
new file mode 100644
index 0000000..109e2af
--- /dev/null
+++ b/tikzit/src/data/nodestyle.cpp
@@ -0,0 +1,30 @@
+#include "nodestyle.h"
+
+NodeStyle::NodeStyle()
+{
+ name = "none";
+ shape = NodeShape::Circle;
+ fillColor = Qt::white;
+ strokeColor = Qt::black;
+ strokeThickness = 1;
+}
+
+NodeStyle::NodeStyle(QString nm, NodeShape sh, QColor fillCol)
+{
+ name = nm;
+ shape = sh;
+ fillColor = fillCol;
+ strokeColor = Qt::black;
+ strokeThickness = 1;
+}
+
+NodeStyle::NodeStyle(QString nm, NodeShape sh, QColor fillCol, QColor strokeCol, int strokeThick)
+{
+ name = nm;
+ shape = sh;
+ fillColor = fillCol;
+ strokeColor = strokeCol;
+ strokeThickness = strokeThick;
+}
+
+bool NodeStyle::isNone() { return name == "none"; }
diff --git a/tikzit/src/data/nodestyle.h b/tikzit/src/data/nodestyle.h
new file mode 100644
index 0000000..baf967c
--- /dev/null
+++ b/tikzit/src/data/nodestyle.h
@@ -0,0 +1,26 @@
+#ifndef NODESTYLE_H
+#define NODESTYLE_H
+
+#include <QColor>
+
+enum NodeShape {
+ Square, UpTriangle, DownTriangle, Circle
+};
+
+class NodeStyle
+{
+public:
+ NodeStyle();
+ NodeStyle(QString nm, NodeShape sh, QColor fillCol);
+ NodeStyle(QString nm, NodeShape sh, QColor fillCol, QColor strokeCol, int strokeThick);
+ bool isNone();
+ QString name;
+ NodeShape shape;
+ QColor fillColor;
+ QColor strokeColor;
+ int strokeThickness;
+};
+
+extern NodeStyle noneStyle;
+
+#endif // NODESTYLE_H
diff --git a/tikzit/src/gui/edgeitem.cpp b/tikzit/src/gui/edgeitem.cpp
new file mode 100644
index 0000000..f45493d
--- /dev/null
+++ b/tikzit/src/gui/edgeitem.cpp
@@ -0,0 +1,89 @@
+#include "tikzit.h"
+#include "edgeitem.h"
+
+#include <QPainterPath>
+#include <QPen>
+
+EdgeItem::EdgeItem(Edge *edge)
+{
+ _edge = edge;
+ setFlag(QGraphicsItem::ItemIsSelectable);
+
+ QPen pen(Qt::black);
+ pen.setWidth(2);
+ setPen(pen);
+ _cp1Item = new QGraphicsEllipseItem(this);
+ _cp1Item->setParentItem(this);
+ _cp2Item = new QGraphicsEllipseItem(this);
+ _cp2Item->setParentItem(this);
+ syncPos();
+}
+
+void EdgeItem::syncPos()
+{
+ _edge->setAttributesFromData();
+ _edge->updateControls();
+ QPainterPath path;
+
+ path.moveTo (toScreen(_edge->tail()));
+ path.cubicTo(toScreen(_edge->cp1()),
+ toScreen(_edge->cp2()),
+ toScreen(_edge->head()));
+ setPath(path);
+
+ float r = GLOBAL_SCALEF * 0.05;
+ //painter->drawEllipse(toScreen(_edge->cp1()), r, r);
+ //painter->drawEllipse(toScreen(_edge->cp2()), r, r);
+}
+
+void EdgeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ //QGraphicsPathItem::paint(painter, option, widget);
+ painter->setPen(pen());
+ painter->setBrush(Qt::NoBrush);
+ painter->drawPath(path());
+
+
+
+ if (isSelected()) {
+ QColor draw;
+ QColor draw1;
+ QColor fill;
+
+ if (_edge->basicBendMode()) {
+ draw = Qt::blue;
+ draw1 = QColor(100,100,255,100);
+ fill = QColor(200,200,255,50);
+ } else {
+ draw = Qt::darkGreen;
+ draw1 = QColor(0, 150, 0, 50);
+ fill = QColor(200,255,200,150);
+ }
+
+ painter->setPen(QPen(draw1));
+
+ float r = GLOBAL_SCALEF * _edge->cpDist();
+ painter->drawEllipse(toScreen(_edge->source()->point()), r, r);
+ painter->drawEllipse(toScreen(_edge->target()->point()), r, r);
+
+ painter->setPen(QPen(draw));
+ painter->setBrush(QBrush(fill));
+
+ painter->drawLine(toScreen(_edge->tail()), toScreen(_edge->cp1()));
+ painter->drawLine(toScreen(_edge->head()), toScreen(_edge->cp2()));
+
+ r = GLOBAL_SCALEF * 0.05;
+ painter->drawEllipse(toScreen(_edge->cp1()), r, r);
+ painter->drawEllipse(toScreen(_edge->cp2()), r, r);
+
+ painter->setPen(QPen(Qt::black));
+ painter->setBrush(QBrush(QColor(255,255,255,200)));
+ painter->drawEllipse(toScreen(_edge->mid()), r, r);
+ }
+}
+
+QRectF EdgeItem::boundingRect() const
+{
+ float r = GLOBAL_SCALEF * (_edge->cpDist() + 0.2);
+ return QGraphicsPathItem::boundingRect().adjusted(-r,-r,r,r);
+}
diff --git a/tikzit/src/gui/edgeitem.h b/tikzit/src/gui/edgeitem.h
new file mode 100644
index 0000000..935138b
--- /dev/null
+++ b/tikzit/src/gui/edgeitem.h
@@ -0,0 +1,28 @@
+#ifndef EDGEITEM_H
+#define EDGEITEM_H
+
+#include "edge.h"
+
+#include <QObject>
+#include <QGraphicsPathItem>
+#include <QPainter>
+#include <QStyleOptionGraphicsItem>
+#include <QWidget>
+#include <QGraphicsEllipseItem>
+
+class EdgeItem : public QGraphicsPathItem
+{
+public:
+ EdgeItem(Edge *edge);
+ void syncPos();
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
+ QWidget *widget);
+ QRectF boundingRect() const;
+
+private:
+ Edge *_edge;
+ QGraphicsEllipseItem *_cp1Item;
+ QGraphicsEllipseItem *_cp2Item;
+};
+
+#endif // EDGEITEM_H
diff --git a/tikzit/src/gui/mainwindow.cpp b/tikzit/src/gui/mainwindow.cpp
index f7357ec..7d7ab04 100644
--- a/tikzit/src/gui/mainwindow.cpp
+++ b/tikzit/src/gui/mainwindow.cpp
@@ -1,6 +1,8 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "tikzgraphassembler.h"
+#include "toolpalette.h"
+#include "tikzit.h"
#include <QDebug>
#include <QFile>
@@ -15,12 +17,13 @@ MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
+ _windowId = _numWindows;
_numWindows++;
ui->setupUi(this);
- setAttribute(Qt::WA_DeleteOnClose);
+ setAttribute(Qt::WA_DeleteOnClose, true);
_graph = new Graph(this);
- tikzScene = new TikzScene(_graph, this);
- ui->tikzView->setScene(tikzScene);
+ _tikzScene = new TikzScene(_graph, this);
+ ui->tikzView->setScene(_tikzScene);
_fileName = "";
_pristine = true;
@@ -33,7 +36,7 @@ MainWindow::MainWindow(QWidget *parent) :
MainWindow::~MainWindow()
{
- //qDebug() << "~MainWindow";
+ tikzit->removeWindow(this);
}
void MainWindow::open(QString fileName)
@@ -45,6 +48,8 @@ void MainWindow::open(QString fileName)
QSettings settings("tikzit", "tikzit");
settings.setValue("previous-file-path", fi.absolutePath());
+ setWindowTitle("TiKZiT - " + fi.fileName());
+
if (!file.open(QIODevice::ReadOnly)) {
QMessageBox::critical(this, tr("Error"),
tr("Could not open file"));
@@ -61,9 +66,11 @@ void MainWindow::open(QString fileName)
TikzGraphAssembler ass(newGraph);
if (ass.parse(tikz)) {
statusBar()->showMessage("TiKZ parsed successfully", 2000);
- tikzScene->setGraph(newGraph);
delete _graph;
_graph = newGraph;
+ foreach (Node *n, _graph->nodes()) n->attachStyle();
+ foreach (Edge *e, _graph->edges()) e->updateControls();
+ _tikzScene->setGraph(_graph);
} else {
statusBar()->showMessage("Cannot read TiKZ source");
delete newGraph;
@@ -77,24 +84,32 @@ void MainWindow::closeEvent(QCloseEvent *event)
QMainWindow::closeEvent(event);
}
-void MainWindow::on_actionOpen_triggered()
+void MainWindow::changeEvent(QEvent *event)
{
- QSettings settings("tikzit", "tikzit");
- QString fileName = QFileDialog::getOpenFileName(
- this,
- tr("Open File"),
- settings.value("previous-file-path").toString(),
- tr("TiKZ Files (*.tikz)"));
-
- if (!fileName.isEmpty()) {
- if (_pristine) {
- open(fileName);
- } else {
- MainWindow *w = new MainWindow();
- w->show();
- w->open(fileName);
- }
+ if (event->type() == QEvent::ActivationChange && isActiveWindow()) {
+ tikzit->setActiveWindow(this);
}
+ QMainWindow::changeEvent(event);
+}
+
+TikzScene *MainWindow::tikzScene() const
+{
+ return _tikzScene;
+}
+
+int MainWindow::windowId() const
+{
+ return _windowId;
+}
+
+TikzView *MainWindow::tikzView() const
+{
+ return ui->tikzView;
+}
+
+bool MainWindow::pristine() const
+{
+ return _pristine;
}
diff --git a/tikzit/src/gui/mainwindow.h b/tikzit/src/gui/mainwindow.h
index f48fd64..2e52cd5 100644
--- a/tikzit/src/gui/mainwindow.h
+++ b/tikzit/src/gui/mainwindow.h
@@ -2,6 +2,7 @@
#define MAINWINDOW_H
#include "tikzscene.h"
+#include "tikzview.h"
#include "graph.h"
#include <QMainWindow>
@@ -20,18 +21,22 @@ public:
~MainWindow();
void open(QString fileName);
+ bool pristine() const;
+ int windowId() const;
+ TikzView *tikzView() const;
+ TikzScene *tikzScene() const;
protected:
void closeEvent(QCloseEvent *event);
+ void changeEvent(QEvent *event);
private:
- TikzScene *tikzScene;
+ TikzScene *_tikzScene;
Ui::MainWindow *ui;
Graph *_graph;
QString _fileName;
bool _pristine;
+ int _windowId;
static int _numWindows;
-public slots:
- void on_actionOpen_triggered();
};
#endif // MAINWINDOW_H
diff --git a/tikzit/src/gui/mainwindow.ui b/tikzit/src/gui/mainwindow.ui
index a2655e6..8c7e8ae 100644
--- a/tikzit/src/gui/mainwindow.ui
+++ b/tikzit/src/gui/mainwindow.ui
@@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
- <string>TikZiT</string>
+ <string>TikZiT - untitled</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout">
@@ -58,59 +58,6 @@ p, li { white-space: pre-wrap; }
</item>
</layout>
</widget>
- <widget class="QMenuBar" name="menuBar">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>476</width>
- <height>22</height>
- </rect>
- </property>
- <widget class="QMenu" name="menuFile">
- <property name="title">
- <string>File</string>
- </property>
- <addaction name="actionNew"/>
- <addaction name="actionOpen"/>
- <addaction name="separator"/>
- <addaction name="actionClose"/>
- <addaction name="actionSave"/>
- <addaction name="actionSave_As"/>
- </widget>
- <widget class="QMenu" name="menuEdit">
- <property name="title">
- <string>Edit</string>
- </property>
- <addaction name="actionUndo"/>
- <addaction name="actionRedo"/>
- <addaction name="separator"/>
- <addaction name="actionCut"/>
- <addaction name="actionCopy"/>
- <addaction name="actionPase"/>
- <addaction name="actionDelete"/>
- <addaction name="separator"/>
- <addaction name="actionSelect_All"/>
- <addaction name="actionDeselect_All"/>
- </widget>
- <widget class="QMenu" name="menuTikz">
- <property name="title">
- <string>Tikz</string>
- </property>
- <addaction name="actionParse"/>
- </widget>
- <widget class="QMenu" name="menuView">
- <property name="title">
- <string>View</string>
- </property>
- <addaction name="actionZoom_In"/>
- <addaction name="actionZoom_Out"/>
- </widget>
- <addaction name="menuFile"/>
- <addaction name="menuEdit"/>
- <addaction name="menuView"/>
- <addaction name="menuTikz"/>
- </widget>
<widget class="QStatusBar" name="statusBar"/>
<action name="actionNew">
<property name="text">
diff --git a/tikzit/src/gui/nodeitem.cpp b/tikzit/src/gui/nodeitem.cpp
index e817d98..d91bfd6 100644
--- a/tikzit/src/gui/nodeitem.cpp
+++ b/tikzit/src/gui/nodeitem.cpp
@@ -1,17 +1,93 @@
+#include "tikzit.h"
#include "nodeitem.h"
#include <QPen>
#include <QBrush>
+#include <QDebug>
+#include <QFont>
+#include <QFontMetrics>
+#include <QPainterPathStroker>
NodeItem::NodeItem(Node *node)
{
_node = node;
- setPen(QPen(Qt::black));
- setBrush(QBrush(Qt::white));
+ setFlag(QGraphicsItem::ItemIsSelectable);
+ setFlag(QGraphicsItem::ItemIsMovable);
syncPos();
}
void NodeItem::syncPos()
{
- setRect(80*_node->point().x() - 8, -80*_node->point().y() - 8, 16, 16);
+ setPos(toScreen(_node->point()));
+}
+
+
+void NodeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ if (_node->style().isNone()) {
+ QColor c(180,180,200);
+ painter->setPen(QPen(c));
+ painter->setBrush(QBrush(c));
+ painter->drawEllipse(QPointF(0,0), 1,1);
+
+ QPen pen(QColor(180,180,220));
+ QVector<qreal> p;
+ p << 2.0 << 2.0;
+ pen.setDashPattern(p);
+ painter->setPen(pen);
+ painter->setBrush(Qt::NoBrush);
+ painter->drawPath(shape());
+ } else {
+ QPen pen(_node->style().strokeColor);
+ pen.setWidth(_node->style().strokeThickness);
+ painter->setPen(pen);
+ painter->setBrush(QBrush(_node->style().fillColor));
+ painter->drawPath(shape());
+ }
+
+ if (_node->label() != "") {
+ QString label = _node->label();
+ QFont f("Monaco", 9);
+ QFontMetrics fm(f);
+ int w = fm.width(label) + 4;
+ int h = fm.height() + 2;
+
+ QRectF rect = fm.boundingRect(label);
+ rect.adjust(-2,-2,2,2);
+ rect.moveCenter(QPointF(0,0));
+ QPen pen(QColor(200,0,0,120));
+ QVector<qreal> d;
+ d << 2.0 << 2.0;
+ pen.setDashPattern(d);
+ painter->setPen(pen);
+ painter->setBrush(QBrush(QColor(255,255,100,120)));
+ painter->drawRect(rect);
+
+ painter->setPen(QPen(Qt::black));
+ painter->setFont(f);
+ painter->drawText(rect, Qt::AlignCenter, _node->label());
+ }
+
+ if (isSelected()) {
+ QPainterPath sh = shape();
+ QPainterPathStroker stroker;
+ stroker.setWidth(4);
+ QPainterPath outline = (stroker.createStroke(sh) + sh).simplified();
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(QBrush(QColor(150,200,255,100)));
+ painter->drawPath(outline);
+ }
+
+}
+
+QPainterPath NodeItem::shape() const
+{
+ QPainterPath path;
+ path.addEllipse(QPointF(0,0), GLOBAL_SCALEF * 0.1, GLOBAL_SCALEF * 0.1);
+ return path;
+}
+
+QRectF NodeItem::boundingRect() const
+{
+ return shape().boundingRect().adjusted(-4,-4,4,4);
}
diff --git a/tikzit/src/gui/nodeitem.h b/tikzit/src/gui/nodeitem.h
index 60b2c05..867d8a3 100644
--- a/tikzit/src/gui/nodeitem.h
+++ b/tikzit/src/gui/nodeitem.h
@@ -4,13 +4,18 @@
#include "node.h"
#include <QObject>
-#include <QGraphicsEllipseItem>
+#include <QGraphicsItem>
+#include <QPainterPath>
+#include <QRectF>
-class NodeItem : public QGraphicsEllipseItem
+class NodeItem : public QGraphicsItem
{
public:
NodeItem(Node *node);
void syncPos();
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+ QPainterPath shape() const;
+ QRectF boundingRect() const;
private:
Node *_node;
};
diff --git a/tikzit/src/gui/propertypalette.cpp b/tikzit/src/gui/propertypalette.cpp
index ea0e90e..ea906a7 100644
--- a/tikzit/src/gui/propertypalette.cpp
+++ b/tikzit/src/gui/propertypalette.cpp
@@ -23,7 +23,6 @@ PropertyPalette::PropertyPalette(QWidget *parent) :
d->setProperty("key 2", "value 2");
QModelIndex i = d->index(0,0);
- qDebug() << "data: " << i.data();
ui->treeView->setModel(d);
QSettings settings("tikzit", "tikzit");
diff --git a/tikzit/src/gui/tikzscene.cpp b/tikzit/src/gui/tikzscene.cpp
index 11d5a72..cf7cde5 100644
--- a/tikzit/src/gui/tikzscene.cpp
+++ b/tikzit/src/gui/tikzscene.cpp
@@ -1,7 +1,10 @@
+#include "tikzit.h"
#include "tikzscene.h"
#include <QPen>
#include <QBrush>
+#include <QDebug>
+
TikzScene::TikzScene(Graph *graph, QObject *parent) :
QGraphicsScene(parent), _graph(graph)
@@ -28,8 +31,17 @@ void TikzScene::graphReplaced()
}
nodeItems.clear();
- QPen blackPen(Qt::black);
- QBrush redBrush(Qt::red);
+ foreach (EdgeItem *ei, edgeItems) {
+ removeItem(ei);
+ delete ei;
+ }
+ edgeItems.clear();
+
+ foreach (Edge *e, _graph->edges()) {
+ EdgeItem *ei = new EdgeItem(e);
+ edgeItems << ei;
+ addItem(ei);
+ }
foreach (Node *n, _graph->nodes()) {
NodeItem *ni = new NodeItem(n);
@@ -38,45 +50,19 @@ void TikzScene::graphReplaced()
}
}
-void TikzScene::drawBackground(QPainter *painter, const QRectF &rect)
+void TikzScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
- // draw the grid
- int step = 10;
+ // TODO: check if we grabbed a control point
- QPen pen;
- pen.setWidth(2);
- pen.setCosmetic(true);
- pen.setColor(QColor(245,245,255));
-
- painter->setPen(pen);
- for (int x = step; x < rect.right(); x += step) {
- if (x % (step * 8) != 0) {
- painter->drawLine(x, rect.top(), x, rect.bottom());
- painter->drawLine(-x, rect.top(), -x, rect.bottom());
- }
- }
-
- for (int y = step; y < rect.bottom(); y += step) {
- if (y % (step * 8) != 0) {
- painter->drawLine(rect.left(), y, rect.right(), y);
- painter->drawLine(rect.left(), -y, rect.right(), -y);
- }
- }
-
- pen.setColor(QColor(240,240,245));
- painter->setPen(pen);
- for (int x = step*8; x < rect.right(); x += step*8) {
- painter->drawLine(x, rect.top(), x, rect.bottom());
- painter->drawLine(-x, rect.top(), -x, rect.bottom());
- }
+ QGraphicsScene::mousePressEvent(event);
+}
- for (int y = step*8; y < rect.bottom(); y += step*8) {
- painter->drawLine(rect.left(), y, rect.right(), y);
- painter->drawLine(rect.left(), -y, rect.right(), -y);
- }
+void TikzScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ QGraphicsScene::mouseMoveEvent(event);
+}
- pen.setColor(QColor(230,230,240));
- painter->setPen(pen);
- painter->drawLine(rect.left(), 0, rect.right(), 0);
- painter->drawLine(0, rect.top(), 0, rect.bottom());
+void TikzScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ QGraphicsScene::mouseReleaseEvent(event);
}
diff --git a/tikzit/src/gui/tikzscene.h b/tikzit/src/gui/tikzscene.h
index c7039e6..2c77389 100644
--- a/tikzit/src/gui/tikzscene.h
+++ b/tikzit/src/gui/tikzscene.h
@@ -3,6 +3,7 @@
#include "graph.h"
#include "nodeitem.h"
+#include "edgeitem.h"
#include <QWidget>
#include <QGraphicsScene>
@@ -10,6 +11,7 @@
#include <QRectF>
#include <QVector>
#include <QGraphicsEllipseItem>
+#include <QGraphicsSceneMouseEvent>
class TikzScene : public QGraphicsScene
{
@@ -20,13 +22,15 @@ public:
void setGraph(Graph *graph);
public slots:
void graphReplaced();
-
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
private:
Graph *_graph;
QVector<NodeItem*> nodeItems;
+ QVector<EdgeItem*> edgeItems;
-protected:
- void drawBackground(QPainter *painter, const QRectF &rect);
};
#endif // TIKZSCENE_H
diff --git a/tikzit/src/gui/tikzview.cpp b/tikzit/src/gui/tikzview.cpp
index d2a769c..a83c9ec 100644
--- a/tikzit/src/gui/tikzview.cpp
+++ b/tikzit/src/gui/tikzview.cpp
@@ -1,20 +1,83 @@
#include "tikzview.h"
+#include "tikzit.h"
#include <QDebug>
TikzView::TikzView(QWidget *parent) : QGraphicsView(parent)
{
setRenderHint(QPainter::Antialiasing);
- qDebug() << "TikzView()";
+ setDragMode(QGraphicsView::RubberBandDrag);
+ _scale = 1.0f;
}
void TikzView::zoomIn()
{
+ _scale *= 1.6f;
scale(1.6,1.6);
}
void TikzView::zoomOut()
{
+ _scale *= 0.625f;
scale(0.625,0.625);
}
+void TikzView::drawBackground(QPainter *painter, const QRectF &rect)
+{
+ // draw the grid
+ int step = GLOBAL_SCALE / 8;
+
+ QPen pen1;
+ pen1.setWidth(1);
+ pen1.setCosmetic(true);
+ pen1.setColor(QColor(230,230,230));
+
+ QPen pen2 = pen1;
+ pen2.setColor(QColor(200,200,200));
+
+ QPen pen3 = pen1;
+ pen3.setColor(QColor(160,160,160));
+
+ painter->setPen(pen1);
+
+ if (_scale > 0.2f) {
+ for (int x = -step; x > rect.left(); x -= step) {
+ if (x % (step * 8) != 0) painter->drawLine(x, rect.top(), x, rect.bottom());
+ }
+
+ for (int x = step; x < rect.right(); x += step) {
+ if (x % (step * 8) != 0) painter->drawLine(x, rect.top(), x, rect.bottom());
+ }
+
+ for (int y = -step; y > rect.top(); y -= step) {
+ if (y % (step * 8) != 0) painter->drawLine(rect.left(), y, rect.right(), y);
+ }
+
+ for (int y = step; y < rect.bottom(); y += step) {
+ if (y % (step * 8) != 0) painter->drawLine(rect.left(), y, rect.right(), y);
+ }
+ }
+
+ painter->setPen(pen2);
+
+ for (int x = -step*8; x > rect.left(); x -= step*8) {
+ painter->drawLine(x, rect.top(), x, rect.bottom());
+ }
+
+ for (int x = step*8; x < rect.right(); x += step*8) {
+ painter->drawLine(x, rect.top(), x, rect.bottom());
+ }
+
+ for (int y = -step*8; y > rect.top(); y -= step*8) {
+ painter->drawLine(rect.left(), y, rect.right(), y);
+ }
+
+ for (int y = step*8; y < rect.bottom(); y += step*8) {
+ painter->drawLine(rect.left(), y, rect.right(), y);
+ }
+
+ painter->setPen(pen3);
+ painter->drawLine(rect.left(), 0, rect.right(), 0);
+ painter->drawLine(0, rect.top(), 0, rect.bottom());
+}
+
diff --git a/tikzit/src/gui/tikzview.h b/tikzit/src/gui/tikzview.h
index 032b9c4..b16e0df 100644
--- a/tikzit/src/gui/tikzview.h
+++ b/tikzit/src/gui/tikzview.h
@@ -8,6 +8,7 @@
#include <QGraphicsItem>
#include <QStyleOptionGraphicsItem>
#include <QRectF>
+#include <QMouseEvent>
class TikzView : public QGraphicsView
{
@@ -17,6 +18,10 @@ public:
public slots:
void zoomIn();
void zoomOut();
+protected:
+ void drawBackground(QPainter *painter, const QRectF &rect);
+private:
+ float _scale;
};
#endif // TIKZVIEW_H
diff --git a/tikzit/src/gui/toolpalette.cpp b/tikzit/src/gui/toolpalette.cpp
index 61b6cbf..3ee2106 100644
--- a/tikzit/src/gui/toolpalette.cpp
+++ b/tikzit/src/gui/toolpalette.cpp
@@ -9,7 +9,6 @@ ToolPalette::ToolPalette(QWidget *parent) :
QToolBar(parent)
{
setWindowFlags(Qt::Window
- | Qt::WindowStaysOnTopHint
| Qt::CustomizeWindowHint
| Qt::WindowDoesNotAcceptFocus);
setOrientation(Qt::Vertical);
diff --git a/tikzit/src/main.cpp b/tikzit/src/main.cpp
index e004529..b676211 100644
--- a/tikzit/src/main.cpp
+++ b/tikzit/src/main.cpp
@@ -1,25 +1,14 @@
-
-#include "mainwindow.h"
-#include "toolpalette.h"
-#include "propertypalette.h"
-#include "graph.h"
+#include "tikzit.h"
#include <QApplication>
+#include <QMenuBar>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
-
- ToolPalette *tp = new ToolPalette(new QMainWindow());
- tp->show();
- //w->addToolBar(Qt::LeftToolBarArea, tp);
-
- PropertyPalette *pp = new PropertyPalette;
- pp->show();
-
- MainWindow *w = new MainWindow();
- w->show();
+ a.setQuitOnLastWindowClosed(false);
+ tikzit = new Tikzit();
return a.exec();
}
diff --git a/tikzit/src/test/testparser.cpp b/tikzit/src/test/testparser.cpp
index bbc90cf..e220e2e 100644
--- a/tikzit/src/test/testparser.cpp
+++ b/tikzit/src/test/testparser.cpp
@@ -103,6 +103,36 @@ void TestParser::parseEdgeNode()
delete g;
}
+void TestParser::parseEdgeBends()
+{
+ Graph *g = new Graph();
+ TikzGraphAssembler ga(g);
+ bool res = ga.parse(
+ "\\begin{tikzpicture}\n"
+ " \\begin{pgfonlayer}{nodelayer}\n"
+ " \\node [style=white] (0) at (-1, 0) {};\n"
+ " \\node [style=black] (1) at (1, 0) {};\n"
+ " \\end{pgfonlayer}\n"
+ " \\begin{pgfonlayer}{edgelayer}\n"
+ " \\draw [style=diredge,bend left] (0) to (1);\n"
+ " \\draw [style=diredge,bend right] (0) to (1);\n"
+ " \\draw [style=diredge,bend left=20] (0) to (1);\n"
+ " \\draw [style=diredge,bend right=80] (0) to (1);\n"
+ " \\draw [style=diredge,in=10,out=150,looseness=2] (0) to (1);\n"
+ " \\end{pgfonlayer}\n"
+ "\\end{tikzpicture}\n");
+ QVERIFY(res);
+ QVERIFY(g->nodes().size() == 2);
+ QVERIFY(g->edges().size() == 5);
+ QVERIFY(g->edges()[0]->bend() == -30);
+ QVERIFY(g->edges()[1]->bend() == 30);
+ QVERIFY(g->edges()[2]->bend() == -20);
+ QVERIFY(g->edges()[3]->bend() == 80);
+ QVERIFY(g->edges()[4]->inAngle() == 10);
+ QVERIFY(g->edges()[4]->outAngle() == 150);
+ QVERIFY(g->edges()[4]->weight() == 2.0f/2.5f);
+}
+
void TestParser::parseBbox()
{
Graph *g = new Graph();
@@ -121,6 +151,7 @@ void TestParser::parseBbox()
" \\draw [style=diredge] (0) to (1);\n"
" \\end{pgfonlayer}\n"
"\\end{tikzpicture}\n");
+ QVERIFY(res);
QVERIFY(g->nodes().size() == 3);
QVERIFY(g->edges().size() == 3);
QVERIFY(g->hasBbox());
diff --git a/tikzit/src/test/testparser.h b/tikzit/src/test/testparser.h
index 69dc965..a40a58f 100644
--- a/tikzit/src/test/testparser.h
+++ b/tikzit/src/test/testparser.h
@@ -11,6 +11,7 @@ private slots:
void parseNodeGraph();
void parseEdgeGraph();
void parseEdgeNode();
+ void parseEdgeBends();
void parseBbox();
};
diff --git a/tikzit/src/tikzit.cpp b/tikzit/src/tikzit.cpp
new file mode 100644
index 0000000..9abf33e
--- /dev/null
+++ b/tikzit/src/tikzit.cpp
@@ -0,0 +1,132 @@
+#include "tikzit.h"
+
+#include <QFileDialog>
+#include <QSettings>
+
+// application-level instance of Tikzit
+Tikzit *tikzit;
+
+Tikzit::Tikzit()
+{
+ _activeWindow = 0;
+ QMainWindow *dummy = new QMainWindow();
+
+ _toolPalette = new ToolPalette(dummy);
+ _propertyPalette = new PropertyPalette(dummy);
+
+ createMenu();
+ loadStyles();
+
+ _toolPalette->show();
+ _propertyPalette->show();
+
+ _windows << new MainWindow();
+ _windows[0]->show();
+}
+
+QMenuBar *Tikzit::mainMenu() const
+{
+ return _mainMenu;
+}
+
+ToolPalette *Tikzit::toolPalette() const
+{
+ return _toolPalette;
+}
+
+PropertyPalette *Tikzit::propertyPalette() const
+{
+ return _propertyPalette;
+}
+
+void Tikzit::createMenu()
+{
+ _mainMenu = new QMenuBar(0);
+ QMenu *file = _mainMenu->addMenu(tr("&File"));
+ QAction *aNew = file->addAction(tr("&New"));
+ aNew->setShortcut(QKeySequence::New);
+ QAction *aOpen = file->addAction(tr("&Open"));
+ aOpen->setShortcut(QKeySequence::Open);
+
+ QMenu *view = _mainMenu->addMenu(tr("&View"));
+ QAction *aZoomIn = view->addAction(tr("Zoom &In"));
+ aZoomIn->setShortcut(QKeySequence::ZoomIn);
+ QAction *aZoomOut = view->addAction(tr("Zoom &Out"));
+ aZoomOut->setShortcut(QKeySequence::ZoomOut);
+
+ connect(aNew, SIGNAL(triggered()), this, SLOT(newDoc()));
+ connect(aOpen, SIGNAL(triggered()), this, SLOT(open()));
+ connect(aZoomIn, SIGNAL(triggered()), this, SLOT(zoomIn()));
+ connect(aZoomOut, SIGNAL(triggered()), this, SLOT(zoomOut()));
+}
+
+void Tikzit::loadStyles()
+{
+ _nodeStyles << NodeStyle("black dot", NodeShape::Circle, Qt::black, Qt::black, 1);
+ _nodeStyles << NodeStyle("white dot", NodeShape::Circle, Qt::white, Qt::black, 1);
+ _nodeStyles << NodeStyle("gray dot", NodeShape::Circle, Qt::gray, Qt::black, 1);
+}
+
+void Tikzit::newDoc()
+{
+ MainWindow *w = new MainWindow();
+ w->show();
+ _windows << w;
+}
+
+MainWindow *Tikzit::activeWindow() const
+{
+ return _activeWindow;
+}
+
+void Tikzit::setActiveWindow(MainWindow *activeWindow)
+{
+ _activeWindow = activeWindow;
+}
+
+void Tikzit::removeWindow(MainWindow *w)
+{
+ _windows.removeAll(w);
+ if (_activeWindow == w) {
+ if (_windows.isEmpty()) _activeWindow = 0;
+ else _activeWindow = _windows[0];
+ }
+}
+
+NodeStyle Tikzit::nodeStyle(QString name)
+{
+ foreach (NodeStyle s , _nodeStyles)
+ if (s.name == name) return s;
+ return NodeStyle(name, NodeShape::Circle, Qt::white);
+}
+
+void Tikzit::open()
+{
+ QSettings settings("tikzit", "tikzit");
+ QString fileName = QFileDialog::getOpenFileName(0,
+ tr("Open File"),
+ settings.value("previous-file-path").toString(),
+ tr("TiKZ Files (*.tikz)"));
+
+ if (!fileName.isEmpty()) {
+ if (_windows.size() == 1 && _windows[0]->pristine()) {
+ _windows[0]->open(fileName);
+ _windows[0]->show();
+ } else {
+ MainWindow *w = new MainWindow();
+ w->show();
+ w->open(fileName);
+ _windows << w;
+ }
+ }
+}
+
+void Tikzit::zoomIn()
+{
+ if (_activeWindow != 0) _activeWindow->tikzView()->zoomIn();
+}
+
+void Tikzit::zoomOut()
+{
+ if (_activeWindow != 0) _activeWindow->tikzView()->zoomOut();
+}
diff --git a/tikzit/src/tikzit.h b/tikzit/src/tikzit.h
new file mode 100644
index 0000000..74a7ea6
--- /dev/null
+++ b/tikzit/src/tikzit.h
@@ -0,0 +1,73 @@
+#ifndef TIKZIT_H
+#define TIKZIT_H
+
+#include "mainwindow.h"
+#include "toolpalette.h"
+#include "propertypalette.h"
+#include "nodestyle.h"
+
+#include <QObject>
+#include <QVector>
+#include <QPointF>
+#include <QMenuBar>
+#include <QMainWindow>
+
+// Number of pixels between (0,0) and (1,0) at 100% zoom level. This should be
+// divisible by 8 to avoid rounding errors with e.g. grid-snapping.
+#define GLOBAL_SCALE 80
+#define GLOBAL_SCALEF 80.0f
+
+inline QPointF toScreen(QPointF src)
+{ src.setY(-src.y()); src *= GLOBAL_SCALEF; return src; }
+
+inline QPointF fromScreen(QPointF src)
+{ src.setY(-src.y()); src /= GLOBAL_SCALEF; return src; }
+
+// interpolate on a cubic bezier curve
+inline float bezierInterpolate(float dist, float c0, float c1, float c2, float c3) {
+ float distp = 1 - dist;
+ return (distp*distp*distp) * c0 +
+ 3 * (distp*distp) * dist * c1 +
+ 3 * (dist*dist) * distp * c2 +
+ (dist*dist*dist) * c3;
+}
+
+inline QPointF bezierInterpolateFull (float dist, QPointF c0, QPointF c1, QPointF c2, QPointF c3) {
+ return QPointF(bezierInterpolate (dist, c0.x(), c1.x(), c2.x(), c3.x()),
+ bezierInterpolate (dist, c0.y(), c1.y(), c2.y(), c3.y()));
+}
+
+class Tikzit : public QObject {
+ Q_OBJECT
+public:
+ Tikzit();
+ QMenuBar *mainMenu() const;
+ ToolPalette *toolPalette() const;
+ PropertyPalette *propertyPalette() const;
+
+ MainWindow *activeWindow() const;
+ void setActiveWindow(MainWindow *activeWindow);
+ void removeWindow(MainWindow *w);
+ NodeStyle nodeStyle(QString name);
+
+private:
+ void createMenu();
+ void loadStyles();
+
+ QMenuBar *_mainMenu;
+ ToolPalette *_toolPalette;
+ PropertyPalette *_propertyPalette;
+ QVector<MainWindow*> _windows;
+ MainWindow *_activeWindow;
+ QVector<NodeStyle> _nodeStyles;
+
+public slots:
+ void newDoc();
+ void open();
+ void zoomIn();
+ void zoomOut();
+};
+
+extern Tikzit *tikzit;
+
+#endif // TIKZIT_H
diff --git a/tikzit/tikzit.pro b/tikzit/tikzit.pro
index 41bc6a3..cf0756f 100644
--- a/tikzit/tikzit.pro
+++ b/tikzit/tikzit.pro
@@ -40,7 +40,10 @@ SOURCES += src/gui/mainwindow.cpp \
src/data/graphelementproperty.cpp \
src/gui/propertypalette.cpp \
src/gui/tikzview.cpp \
- src/gui/nodeitem.cpp
+ src/gui/nodeitem.cpp \
+ src/gui/edgeitem.cpp \
+ src/tikzit.cpp \
+ src/data/nodestyle.cpp
HEADERS += src/gui/mainwindow.h \
src/gui/toolpalette.h \
@@ -54,17 +57,20 @@ HEADERS += src/gui/mainwindow.h \
src/gui/propertypalette.h \
src/data/tikzparserdefs.h \
src/gui/tikzview.h \
- src/gui/nodeitem.h
+ src/gui/nodeitem.h \
+ src/tikzit.h \
+ src/gui/edgeitem.h \
+ src/data/nodestyle.h
FORMS += src/gui/mainwindow.ui \
- src/gui/propertypalette.ui
+ src/gui/propertypalette.ui \
+ src/gui/mainmenu.ui
INCLUDEPATH += src src/gui src/data
DISTFILES +=
-RESOURCES += \
- tikzit.qrc
+RESOURCES += tikzit.qrc
test {
QT += testlib
diff --git a/tikzit/tikzit.pro.user b/tikzit/tikzit.pro.user
index 6d72c88..aca5fe8 100644
--- a/tikzit/tikzit.pro.user
+++ b/tikzit/tikzit.pro.user
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
-<!-- Written by QtCreator 4.2.0, 2017-02-02T17:06:07. -->
+<!-- Written by QtCreator 4.2.0, 2017-02-27T21:48:49. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>