From eac7dee2d8ba86001afbc61c4e9d7baae7341cb8 Mon Sep 17 00:00:00 2001 From: Aleks Kissinger Date: Tue, 10 Apr 2018 16:07:44 +0200 Subject: added edgestyles, but cant apply to nodes yet --- src/data/edgestyle.cpp | 109 ++++++++++++++++++++++++++++++++++ src/data/edgestyle.h | 38 ++++++++++++ src/data/nodestyle.cpp | 80 +++++-------------------- src/data/nodestyle.h | 21 ++----- src/data/style.cpp | 60 +++++++++++++++++++ src/data/style.h | 36 ++++++++++++ src/data/tikzlexer.l | 9 +-- src/data/tikzstyles.cpp | 27 +++++++-- src/data/tikzstyles.h | 4 ++ src/gui/stylepalette.cpp | 149 +++++++++++++++++++++++++++++++++++++++++++++++ src/gui/stylepalette.h | 42 +++++++++++++ src/gui/stylepalette.ui | 120 ++++++++++++++++++++++++++++++++++++++ src/gui/tikzscene.cpp | 2 +- src/gui/tikzview.cpp | 2 +- 14 files changed, 609 insertions(+), 90 deletions(-) create mode 100644 src/data/edgestyle.cpp create mode 100644 src/data/edgestyle.h create mode 100644 src/data/style.cpp create mode 100644 src/data/style.h create mode 100644 src/gui/stylepalette.cpp create mode 100644 src/gui/stylepalette.h create mode 100644 src/gui/stylepalette.ui (limited to 'src') diff --git a/src/data/edgestyle.cpp b/src/data/edgestyle.cpp new file mode 100644 index 0000000..d366946 --- /dev/null +++ b/src/data/edgestyle.cpp @@ -0,0 +1,109 @@ +#include "edgestyle.h" + +#include +#include + +EdgeStyle *noneEdgeStyle = new EdgeStyle(); + +EdgeStyle::EdgeStyle() : Style() +{ +} + +EdgeStyle::EdgeStyle(QString name, GraphElementData *data) : Style(name, data) +{ +} + +EdgeStyle::ArrowTipStyle EdgeStyle::arrowHead() const +{ + if (_data == 0) return NoTip; + + if (_data->atom("->") || _data->atom("<->") || _data->atom("|->")) return Pointer; + if (_data->atom("-|") || _data->atom("<-|") || _data->atom("|-|")) return Flat; + return NoTip; +} + +EdgeStyle::ArrowTipStyle EdgeStyle::arrowTail() const +{ + if (_data == 0) return NoTip; + if (_data->atom("<-") || _data->atom("<->") || _data->atom("<-|")) return Pointer; + if (_data->atom("|-") || _data->atom("|->") || _data->atom("|-|")) return Flat; + return NoTip; +} + +EdgeStyle::DrawStyle EdgeStyle::drawStyle() const +{ + if (_data == 0) return Solid; + if (_data->atom("dashed")) return Dashed; + if (_data->atom("dotted")) return Dotted; + return Solid; +} + +QPen EdgeStyle::pen() const +{ + QPen p(strokeColor()); + p.setWidthF((float)strokeThickness() * 3.0f); + + QVector pat; + switch (drawStyle()) { + case Dashed: + pat << 3.0 << 3.0; + p.setDashPattern(pat); + break; + case Dotted: + pat << 1.0 << 1.0; + p.setDashPattern(pat); + break; + } + + return p; +} + +QPainterPath EdgeStyle::path() const +{ + return QPainterPath(); +} + +QPainterPath EdgeStyle::palettePath() const +{ + return QPainterPath(); +} + +QIcon EdgeStyle::icon() const +{ + // draw an icon matching the style + QPixmap px(100,100); + px.fill(Qt::transparent); + QPainter painter(&px); + + if (_data == 0) { + QPen pen(Qt::black); + pen.setWidth(3); + } else { + painter.setPen(pen()); + } + + painter.drawLine(10, 50, 90, 50); + + switch (arrowHead()) { + case Pointer: + painter.drawLine(90,50,80,40); + painter.drawLine(90,50,80,60); + break; + case Flat: + painter.drawLine(90,40,90,60); + break; + } + + switch (arrowTail()) { + case Pointer: + painter.drawLine(10,50,20,40); + painter.drawLine(10,50,20,60); + break; + case Flat: + painter.drawLine(10,40,10,60); + break; + } + + + return QIcon(px); +} diff --git a/src/data/edgestyle.h b/src/data/edgestyle.h new file mode 100644 index 0000000..6b0c3bb --- /dev/null +++ b/src/data/edgestyle.h @@ -0,0 +1,38 @@ +#ifndef EDGESTYLE_H +#define EDGESTYLE_H + +#include "style.h" + +#include +#include +#include +#include +#include + +class EdgeStyle : public Style +{ +public: + EdgeStyle(); + EdgeStyle(QString name, GraphElementData *data); + + enum ArrowTipStyle { + Flat, Pointer, NoTip + }; + + enum DrawStyle { + Solid, Dotted, Dashed + }; + + ArrowTipStyle arrowHead() const; + ArrowTipStyle arrowTail() const; + DrawStyle drawStyle() const; + + QPen pen() const; + QPainterPath path() const override; + QPainterPath palettePath() const override; + QIcon icon() const override; +}; + +extern EdgeStyle *noneEdgeStyle; + +#endif // EDGESTYLE_H diff --git a/src/data/nodestyle.cpp b/src/data/nodestyle.cpp index b3d72fb..3f2c921 100644 --- a/src/data/nodestyle.cpp +++ b/src/data/nodestyle.cpp @@ -3,91 +3,43 @@ NodeStyle *noneStyle = new NodeStyle(); -NodeStyle::NodeStyle() : _name("none"), _data(0) +NodeStyle::NodeStyle() : Style() { } -NodeStyle::NodeStyle(QString name, GraphElementData *data): _name(name), _data(data) +NodeStyle::NodeStyle(QString name, GraphElementData *data): Style(name, data) { } -bool NodeStyle::isNone() { return _data == 0; } - -GraphElementData *NodeStyle::data() const -{ - return _data; -} - -QString NodeStyle::name() const -{ - return _name; -} - -NodeStyle::Shape NodeStyle::shape() const -{ - if (_data == 0) return NodeStyle::Circle; - - QString sh = _data->property("shape"); - if (sh.isNull()) return NodeStyle::Circle; - else if (sh == "circle") return NodeStyle::Circle; - else if (sh == "rectangle") return NodeStyle::Rectangle; - else return NodeStyle::Circle; -} - QColor NodeStyle::fillColor() const { if (_data == 0) return Qt::white; - QString col = _data->property("fill"); - - if (col.isNull()) { - return QColor(Qt::white); - } else { - QColor namedColor(col); - if (namedColor.isValid()) { - return namedColor; - } else { - // TODO: read RGB colors - return QColor(Qt::white); - } - } -} - -QColor NodeStyle::strokeColor() const -{ - if (_data == 0) return Qt::black; + QString col = propertyWithDefault("fill", "white"); - QString col = _data->property("draw"); - - if (col.isNull()) { - return QColor(Qt::black); + QColor namedColor(col); + if (namedColor.isValid()) { + return namedColor; } else { - QColor namedColor(col); - if (namedColor.isValid()) { - return namedColor; - } else { - // TODO: read RGB colors - return QColor(Qt::white); - } + // TODO: read RGB colors + return QColor(Qt::white); } } -int NodeStyle::strokeThickness() const +QBrush NodeStyle::brush() const { - return 1; + return QBrush(fillColor()); } -QPen NodeStyle::pen() const +NodeStyle::Shape NodeStyle::shape() const { - QPen p(strokeColor()); - p.setWidthF((float)strokeThickness() * 3.0f); - return p; -} + if (_data == 0) return NodeStyle::Circle; -QBrush NodeStyle::brush() const -{ - return QBrush(fillColor()); + QString sh = propertyWithDefault("shape", "circle"); + if (sh == "circle") return NodeStyle::Circle; + else if (sh == "rectangle") return NodeStyle::Rectangle; + else return NodeStyle::Circle; } QPainterPath NodeStyle::path() const diff --git a/src/data/nodestyle.h b/src/data/nodestyle.h index 0b9f282..4b48bb3 100644 --- a/src/data/nodestyle.h +++ b/src/data/nodestyle.h @@ -1,7 +1,7 @@ #ifndef NODESTYLE_H #define NODESTYLE_H -#include "graphelementdata.h" +#include "style.h" #include #include @@ -9,7 +9,7 @@ #include #include -class NodeStyle +class NodeStyle : public Style { public: enum Shape { @@ -18,23 +18,14 @@ public: NodeStyle(); NodeStyle(QString name, GraphElementData *data); - bool isNone(); - GraphElementData *data() const; - QString name() const; - Shape shape() const; QColor fillColor() const; - QColor strokeColor() const; - int strokeThickness() const; - - QPen pen() const; QBrush brush() const; QPainterPath path() const; - QPainterPath palettePath() const; - QIcon icon() const; -private: - QString _name; - GraphElementData *_data; + Shape shape() const; + + QPainterPath palettePath() const override; + QIcon icon() const override; }; extern NodeStyle *noneStyle; diff --git a/src/data/style.cpp b/src/data/style.cpp new file mode 100644 index 0000000..927271c --- /dev/null +++ b/src/data/style.cpp @@ -0,0 +1,60 @@ +#include "style.h" + +Style::Style() : _name("none"), _data(0) +{ +} + +Style::Style(QString name, GraphElementData *data) : _name(name), _data(data) +{ +} + +bool Style::isNone() +{ + return _data == 0; +} + +GraphElementData *Style::data() const +{ + return _data; +} + +QString Style::name() const +{ + return _name; +} + +QColor Style::strokeColor() const +{ + if (_data == 0) return Qt::black; + + QString col = propertyWithDefault("draw", "black"); + + QColor namedColor(col); + if (namedColor.isValid()) { + return namedColor; + } else { + // TODO: read RGB colors + return QColor(Qt::black); + } +} + +// TODO +int Style::strokeThickness() const +{ + return 1; +} + +QPen Style::pen() const +{ + QPen p(strokeColor()); + p.setWidthF((float)strokeThickness() * 3.0f); + return p; +} + +QString Style::propertyWithDefault(QString prop, QString def) const +{ + QString val = _data->property("tikzit " + prop); + if (val.isNull()) val = _data->property(prop); + if (val.isNull()) val = def; + return val; +} diff --git a/src/data/style.h b/src/data/style.h new file mode 100644 index 0000000..9d58ebe --- /dev/null +++ b/src/data/style.h @@ -0,0 +1,36 @@ +#ifndef STYLE_H +#define STYLE_H + + +#include "graphelementdata.h" + +#include +#include +#include +#include +#include + +class Style +{ +public: + Style(); + Style(QString name, GraphElementData *data); + bool isNone(); + + // properties that both edges and nodes have + GraphElementData *data() const; + QString name() const; + QColor strokeColor() const; + int strokeThickness() const; + + // methods that are implemented differently for edges and nodes + virtual QPen pen() const; + virtual QPainterPath path() const = 0; + virtual QPainterPath palettePath() const = 0; + virtual QIcon icon() const = 0; +protected: + QString propertyWithDefault(QString prop, QString def) const; + QString _name; + GraphElementData *_data; +}; +#endif // STYLE_H diff --git a/src/data/tikzlexer.l b/src/data/tikzlexer.l index d90ad4b..45494d2 100644 --- a/src/data/tikzlexer.l +++ b/src/data/tikzlexer.l @@ -65,6 +65,7 @@ FLOAT \-?[0-9]*(\.[0-9]+)? yylloc->first_column = yylloc->last_column = 0; } [\t ]+ { } +%.*$ { } \\begin\{tikzpicture\} { return BEGIN_TIKZPICTURE_CMD; } \\end\{tikzpicture\} { return END_TIKZPICTURE_CMD; } @@ -74,12 +75,12 @@ FLOAT \-?[0-9]*(\.[0-9]+)? \\draw { return DRAW_CMD; } \\node { return NODE_CMD; } \\path { return PATH_CMD; } -rectangle { return RECTANGLE; } -node { return NODE; } -at { return AT; } -to { return TO; } ; { return SEMICOLON; } = { return EQUALS; } +rectangle { return RECTANGLE; } +node { return NODE; } +at { return AT; } +to { return TO; } \([ ]*{FLOAT}[ ]*,[ ]*{FLOAT}[ ]*\) { yylloc->last_column = yylloc->first_column + 1; diff --git a/src/data/tikzstyles.cpp b/src/data/tikzstyles.cpp index 186e19b..c198412 100644 --- a/src/data/tikzstyles.cpp +++ b/src/data/tikzstyles.cpp @@ -12,7 +12,14 @@ NodeStyle *TikzStyles::nodeStyle(QString name) const { foreach (NodeStyle *s , _nodeStyles) if (s->name() == name) return s; - return noneStyle; //NodeStyle(name, NodeShape::Circle, Qt::white); + return noneStyle; +} + +EdgeStyle *TikzStyles::edgeStyle(QString name) const +{ + foreach (EdgeStyle *s , _edgeStyles) + if (s->name() == name) return s; + return noneEdgeStyle; } QVector TikzStyles::nodeStyles() const @@ -23,14 +30,24 @@ QVector TikzStyles::nodeStyles() const void TikzStyles::clear() { _nodeStyles.clear(); + _edgeStyles.clear(); +} + +QVector TikzStyles::edgeStyles() const +{ + return _edgeStyles; } void TikzStyles::addStyle(QString name, GraphElementData *data) { - //qDebug() << "got style {" << name << "} = [" << data << "]"; - if (!data->property("fill").isNull()) { // node style + if (data->atom("-") || data->atom("->") || data->atom("-|") || + data->atom("<-") || data->atom("<->") || data->atom("<-|") || + data->atom("|-") || data->atom("|->") || data->atom("|-|")) + { // edge style + qDebug() << "got edge style" << name; + _edgeStyles << new EdgeStyle(name, data); + } else { // node style + qDebug() << "got node style" << name; _nodeStyles << new NodeStyle(name, data); - } else { // edge style - // TODO: edge styles } } diff --git a/src/data/tikzstyles.h b/src/data/tikzstyles.h index eaf7e64..4cd7d6e 100644 --- a/src/data/tikzstyles.h +++ b/src/data/tikzstyles.h @@ -3,6 +3,7 @@ #include "graphelementdata.h" #include "nodestyle.h" +#include "edgestyle.h" #include #include @@ -15,7 +16,9 @@ public: void addStyle(QString name, GraphElementData *data); NodeStyle *nodeStyle(QString name) const; + EdgeStyle *edgeStyle(QString name) const; QVector nodeStyles() const; + QVector edgeStyles() const; void clear(); signals: @@ -24,6 +27,7 @@ public slots: private: QVector _nodeStyles; + QVector _edgeStyles; }; #endif // PROJECT_H diff --git a/src/gui/stylepalette.cpp b/src/gui/stylepalette.cpp new file mode 100644 index 0000000..f7c17c0 --- /dev/null +++ b/src/gui/stylepalette.cpp @@ -0,0 +1,149 @@ +#include "stylepalette.h" +#include "ui_stylepalette.h" +#include "tikzit.h" + +#include +#include +#include +#include +#include +#include +#include + +StylePalette::StylePalette(QWidget *parent) : + QDockWidget(parent), + ui(new Ui::StylePalette) +{ + ui->setupUi(this); + +// QSettings settings("tikzit", "tikzit"); +// QVariant geom = settings.value("style-palette-geometry"); +// if (geom != QVariant()) { +// restoreGeometry(geom.toByteArray()); +// } + + _nodeModel = new QStandardItemModel(this); + _edgeModel = new QStandardItemModel(this); + + ui->styleListView->setModel(_nodeModel); + ui->styleListView->setViewMode(QListView::IconMode); + ui->styleListView->setMovement(QListView::Static); + ui->styleListView->setGridSize(QSize(70,40)); + + ui->edgeStyleListView->setModel(_edgeModel); + ui->edgeStyleListView->setViewMode(QListView::IconMode); + ui->edgeStyleListView->setMovement(QListView::Static); + ui->edgeStyleListView->setGridSize(QSize(70,40)); + + reloadStyles(); + + connect(ui->styleListView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT( nodeStyleDoubleClicked(const QModelIndex&)) ); +} + +StylePalette::~StylePalette() +{ + delete ui; +} + +void StylePalette::reloadStyles() +{ + _nodeModel->clear(); + _edgeModel->clear(); + QString f = tikzit->styleFile(); + ui->styleFile->setText(f); + + QStandardItem *it; + + it = new QStandardItem(noneStyle->icon(), noneStyle->name()); + it->setEditable(false); + it->setData(noneStyle->name()); + _nodeModel->appendRow(it); + + foreach(NodeStyle *ns, tikzit->styles()->nodeStyles()) { + it = new QStandardItem(ns->icon(), ns->name()); + it->setEditable(false); + it->setData(ns->name()); + _nodeModel->appendRow(it); + } + + it = new QStandardItem(noneEdgeStyle->icon(), noneEdgeStyle->name()); + it->setEditable(false); + it->setData(noneEdgeStyle->name()); + _edgeModel->appendRow(it); + + foreach(EdgeStyle *es, tikzit->styles()->edgeStyles()) { + it = new QStandardItem(es->icon(), es->name()); + it->setEditable(false); + it->setData(es->name()); + _edgeModel->appendRow(it); + } +} + +void StylePalette::changeNodeStyle(int increment) +{ + QModelIndexList i = ui->styleListView->selectionModel()->selectedIndexes(); + int row = 0; + if (!i.isEmpty()) { + int row = (i[0].row()+increment)%_nodeModel->rowCount(); + if (row < 0) row += _nodeModel->rowCount(); + } + + QModelIndex i1 = ui->styleListView->rootIndex().child(row, 0); + ui->styleListView->selectionModel()->select(i1, QItemSelectionModel::ClearAndSelect); + ui->styleListView->scrollTo(i1); +} + +void StylePalette::nextNodeStyle() +{ + changeNodeStyle(1); +} + +void StylePalette::previousNodeStyle() +{ + changeNodeStyle(-1); +} + +QString StylePalette::activeNodeStyleName() +{ + const QModelIndexList i = ui->styleListView->selectionModel()->selectedIndexes(); + + if (i.isEmpty()) { + return "none"; + } else { + return i[0].data().toString(); + } +} + +void StylePalette::nodeStyleDoubleClicked(const QModelIndex &index) +{ + tikzit->activeWindow()->tikzScene()->applyActiveStyleToNodes(); +} + +void StylePalette::edgeStyleDoubleClicked(const QModelIndex &index) +{ + // TODO +} + +void StylePalette::on_buttonOpenTikzstyles_clicked() +{ + tikzit->openTikzStyles(); +} + +void StylePalette::on_buttonRefreshTikzstyles_clicked() +{ + QSettings settings("tikzit", "tikzit"); + QString path = settings.value("previous-tikzstyles-file").toString(); + if (!path.isEmpty()) tikzit->loadStyles(path); +} + +//void StylePalette::on_buttonApplyNodeStyle_clicked() +//{ +// if (tikzit->activeWindow() != 0) tikzit->activeWindow()->tikzScene()->applyActiveStyleToNodes(); +//} + +void StylePalette::closeEvent(QCloseEvent *event) +{ + QSettings settings("tikzit", "tikzit"); + settings.setValue("style-palette-geometry", saveGeometry()); + QDockWidget::closeEvent(event); +} diff --git a/src/gui/stylepalette.h b/src/gui/stylepalette.h new file mode 100644 index 0000000..8663cc4 --- /dev/null +++ b/src/gui/stylepalette.h @@ -0,0 +1,42 @@ +#ifndef STYLEPALETTE_H +#define STYLEPALETTE_H + +#include +#include + +namespace Ui { +class StylePalette; +} + +class StylePalette : public QDockWidget +{ + Q_OBJECT + +public: + explicit StylePalette(QWidget *parent = 0); + ~StylePalette(); + void reloadStyles(); + void nextNodeStyle(); + void previousNodeStyle(); + QString activeNodeStyleName(); + + +public slots: + void nodeStyleDoubleClicked(const QModelIndex &index); + void edgeStyleDoubleClicked(const QModelIndex &index); + void on_buttonOpenTikzstyles_clicked(); + void on_buttonRefreshTikzstyles_clicked(); + //void on_buttonApplyNodeStyle_clicked(); + +private: + void changeNodeStyle(int increment); + + Ui::StylePalette *ui; + QStandardItemModel *_nodeModel; + QStandardItemModel *_edgeModel; + +protected: + void closeEvent(QCloseEvent *event) override; +}; + +#endif // STYLEPALETTE_H diff --git a/src/gui/stylepalette.ui b/src/gui/stylepalette.ui new file mode 100644 index 0000000..4f5b58d --- /dev/null +++ b/src/gui/stylepalette.ui @@ -0,0 +1,120 @@ + + + StylePalette + + + + 0 + 0 + 88 + 518 + + + + + 0 + 0 + + + + + 88 + 191 + + + + + 88 + 524287 + + + + false + + + + + + + + + + 2 + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + New Project + + + + + + + :/images/document-open.svg:/images/document-open.svg + + + + + + + + + + + :/images/refresh.svg:/images/refresh.svg + + + + + + + + + + 0 + 0 + + + + [default] + + + + + + + + 8 + true + + + + + + + + + + + + + + + diff --git a/src/gui/tikzscene.cpp b/src/gui/tikzscene.cpp index 2a9b2fb..9b6c2d6 100644 --- a/src/gui/tikzscene.cpp +++ b/src/gui/tikzscene.cpp @@ -463,7 +463,7 @@ void TikzScene::keyPressEvent(QKeyEvent *event) if (event->key() == Qt::Key_QuoteLeft) { capture = true; - _styles->nextStyle(); + _styles->nextNodeStyle(); } if (event->modifiers() & Qt::ControlModifier) { diff --git a/src/gui/tikzview.cpp b/src/gui/tikzview.cpp index 047ef50..9997106 100644 --- a/src/gui/tikzview.cpp +++ b/src/gui/tikzview.cpp @@ -6,7 +6,7 @@ TikzView::TikzView(QWidget *parent) : QGraphicsView(parent) { - //setRenderHint(QPainter::Antialiasing); + setRenderHint(QPainter::Antialiasing); //setDragMode(QGraphicsView::RubberBandDrag); _scale = 1.0f; -- cgit v1.2.3