From c7f79b3a9878dafc4088f170964264dff839f502 Mon Sep 17 00:00:00 2001 From: Aleks Kissinger Date: Fri, 20 Jul 2018 11:13:42 +0200 Subject: ... --- src/gui/commands.h | 8 +- src/gui/edgeitem.cpp | 442 ++++++------ src/gui/edgeitem.h | 124 ++-- src/gui/mainmenu.cpp | 302 ++++----- src/gui/mainmenu.h | 128 ++-- src/gui/mainmenu.ui | 418 ++++++------ src/gui/mainwindow.cpp | 320 ++++----- src/gui/mainwindow.h | 120 ++-- src/gui/mainwindow.ui | 410 ++++++------ src/gui/nodeitem.cpp | 318 ++++----- src/gui/nodeitem.h | 102 +-- src/gui/propertypalette.cpp | 122 ++-- src/gui/propertypalette.h | 92 +-- src/gui/propertypalette.ui | 66 +- src/gui/stylepalette.cpp | 358 +++++----- src/gui/stylepalette.h | 122 ++-- src/gui/stylepalette.ui | 240 +++---- src/gui/tikzscene.cpp | 1560 +++++++++++++++++++++---------------------- src/gui/tikzscene.h | 214 +++--- src/gui/tikzview.cpp | 256 +++---- src/gui/tikzview.h | 104 +-- src/gui/toolpalette.cpp | 172 ++--- src/gui/toolpalette.h | 106 +-- src/gui/undocommands.cpp | 856 ++++++++++++------------ src/gui/undocommands.h | 388 +++++------ 25 files changed, 3674 insertions(+), 3674 deletions(-) (limited to 'src') diff --git a/src/gui/commands.h b/src/gui/commands.h index 9942ba8..73bfaa7 100644 --- a/src/gui/commands.h +++ b/src/gui/commands.h @@ -1,4 +1,4 @@ -#ifndef COMMANDS_H -#define COMMANDS_H - -#endif // COMMANDS_H +#ifndef COMMANDS_H +#define COMMANDS_H + +#endif // COMMANDS_H diff --git a/src/gui/edgeitem.cpp b/src/gui/edgeitem.cpp index 9cf14c8..f469506 100644 --- a/src/gui/edgeitem.cpp +++ b/src/gui/edgeitem.cpp @@ -1,221 +1,221 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - This program 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. - - This program 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 this program. If not, see . -*/ - -#include "tikzit.h" -#include "edgeitem.h" - -#include -#include - -EdgeItem::EdgeItem(Edge *edge) -{ - _edge = edge; - setFlag(QGraphicsItem::ItemIsSelectable); - - _cp1Item = new QGraphicsEllipseItem(this); - _cp1Item->setParentItem(this); - _cp1Item->setRect(GLOBAL_SCALEF * (-0.1), GLOBAL_SCALEF * (-0.1), - GLOBAL_SCALEF * 0.2, GLOBAL_SCALEF * 0.2); - _cp1Item->setVisible(false); - - _cp2Item = new QGraphicsEllipseItem(this); - _cp2Item->setParentItem(this); - _cp2Item->setRect(GLOBAL_SCALEF * (-0.1), GLOBAL_SCALEF * (-0.1), - GLOBAL_SCALEF * 0.2, GLOBAL_SCALEF * 0.2); - _cp2Item->setVisible(false); - - readPos(); -} - -void EdgeItem::readPos() -{ - //_edge->setAttributesFromData(); - _edge->updateControls(); - QPainterPath path; - - path.moveTo (toScreen(_edge->tail())); - - if (_edge->bend() != 0 || !_edge->basicBendMode()) { - path.cubicTo(toScreen(_edge->cp1()), - toScreen(_edge->cp2()), - toScreen(_edge->head())); - } - else { - path.lineTo(toScreen(_edge->head())); - } - - setPath(path); - - _cp1Item->setPos(toScreen(_edge->cp1())); - _cp2Item->setPos(toScreen(_edge->cp2())); -} - -void EdgeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) -{ - //QGraphicsPathItem::paint(painter, option, widget); - QPen pen = _edge->style()->pen(); - painter->setPen(pen); - painter->setBrush(Qt::NoBrush); - painter->drawPath(path()); - - QPointF ht = _edge->headTangent(); - QPointF hLeft(-ht.y(), ht.x()); - QPointF hRight(ht.y(), -ht.x()); - QPointF tt = _edge->tailTangent(); - QPointF tLeft(-ht.y(), ht.x()); - QPointF tRight(ht.y(), -ht.x()); - - pen.setStyle(Qt::SolidLine); - painter->setPen(pen); - - - - switch (_edge->style()->arrowHead()) { - case EdgeStyle::Flat: - { - painter->drawLine( - toScreen(_edge->head() + hLeft), - toScreen(_edge->head() + hRight)); - break; - } - case EdgeStyle::Pointer: - { - QPainterPath pth; - pth.moveTo(toScreen(_edge->head() + ht + hLeft)); - pth.lineTo(toScreen(_edge->head())); - pth.lineTo(toScreen(_edge->head() + ht + hRight)); - painter->drawPath(pth); - break; - } - } - - switch (_edge->style()->arrowTail()) { - case EdgeStyle::Flat: - { - painter->drawLine( - toScreen(_edge->tail() + tLeft), - toScreen(_edge->tail() + tRight)); - break; - } - case EdgeStyle::Pointer: - { - QPainterPath pth; - pth.moveTo(toScreen(_edge->tail() + tt + tLeft)); - pth.lineTo(toScreen(_edge->tail())); - pth.lineTo(toScreen(_edge->tail() + tt + tRight)); - painter->drawPath(pth); - break; - } - } - - 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())); - - //painter->drawEllipse(toScreen(_edge->cp1()), r, r); - //painter->drawEllipse(toScreen(_edge->cp2()), r, r); - - _cp1Item->setPen(QPen(draw)); - _cp1Item->setBrush(QBrush(fill)); - _cp1Item->setVisible(true); - - _cp2Item->setPen(QPen(draw)); - _cp2Item->setBrush(QBrush(fill)); - _cp2Item->setVisible(true); - - r = GLOBAL_SCALEF * 0.05; - painter->setPen(QPen(Qt::black)); - painter->setBrush(QBrush(QColor(255,255,255,200))); - painter->drawEllipse(toScreen(_edge->mid()), r, r); - } else { - _cp1Item->setVisible(false); - _cp2Item->setVisible(false); - } -} - -QRectF EdgeItem::boundingRect() const -{ - return _boundingRect; -} - -QPainterPath EdgeItem::shape() const -{ - return _expPath; -} - -Edge *EdgeItem::edge() const -{ - return _edge; -} - -QGraphicsEllipseItem *EdgeItem::cp1Item() const -{ - return _cp1Item; -} - -QGraphicsEllipseItem *EdgeItem::cp2Item() const -{ - return _cp2Item; -} - -QPainterPath EdgeItem::path() const -{ - return _path; -} - -void EdgeItem::setPath(const QPainterPath &path) -{ - prepareGeometryChange(); - - _path = path; - - // get the shape of the edge, and expand a bit to make selection easier - QPainterPathStroker stroker; - stroker.setWidth(5); - stroker.setJoinStyle(Qt::MiterJoin); - _expPath = (stroker.createStroke(_path) + _path).simplified(); - - float r = GLOBAL_SCALEF * (_edge->cpDist() + 0.2); - _boundingRect = _path.boundingRect().adjusted(-r,-r,r,r); - - update(); -} - +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program 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. + + This program 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 this program. If not, see . +*/ + +#include "tikzit.h" +#include "edgeitem.h" + +#include +#include + +EdgeItem::EdgeItem(Edge *edge) +{ + _edge = edge; + setFlag(QGraphicsItem::ItemIsSelectable); + + _cp1Item = new QGraphicsEllipseItem(this); + _cp1Item->setParentItem(this); + _cp1Item->setRect(GLOBAL_SCALEF * (-0.1), GLOBAL_SCALEF * (-0.1), + GLOBAL_SCALEF * 0.2, GLOBAL_SCALEF * 0.2); + _cp1Item->setVisible(false); + + _cp2Item = new QGraphicsEllipseItem(this); + _cp2Item->setParentItem(this); + _cp2Item->setRect(GLOBAL_SCALEF * (-0.1), GLOBAL_SCALEF * (-0.1), + GLOBAL_SCALEF * 0.2, GLOBAL_SCALEF * 0.2); + _cp2Item->setVisible(false); + + readPos(); +} + +void EdgeItem::readPos() +{ + //_edge->setAttributesFromData(); + _edge->updateControls(); + QPainterPath path; + + path.moveTo (toScreen(_edge->tail())); + + if (_edge->bend() != 0 || !_edge->basicBendMode()) { + path.cubicTo(toScreen(_edge->cp1()), + toScreen(_edge->cp2()), + toScreen(_edge->head())); + } + else { + path.lineTo(toScreen(_edge->head())); + } + + setPath(path); + + _cp1Item->setPos(toScreen(_edge->cp1())); + _cp2Item->setPos(toScreen(_edge->cp2())); +} + +void EdgeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + //QGraphicsPathItem::paint(painter, option, widget); + QPen pen = _edge->style()->pen(); + painter->setPen(pen); + painter->setBrush(Qt::NoBrush); + painter->drawPath(path()); + + QPointF ht = _edge->headTangent(); + QPointF hLeft(-ht.y(), ht.x()); + QPointF hRight(ht.y(), -ht.x()); + QPointF tt = _edge->tailTangent(); + QPointF tLeft(-ht.y(), ht.x()); + QPointF tRight(ht.y(), -ht.x()); + + pen.setStyle(Qt::SolidLine); + painter->setPen(pen); + + + + switch (_edge->style()->arrowHead()) { + case EdgeStyle::Flat: + { + painter->drawLine( + toScreen(_edge->head() + hLeft), + toScreen(_edge->head() + hRight)); + break; + } + case EdgeStyle::Pointer: + { + QPainterPath pth; + pth.moveTo(toScreen(_edge->head() + ht + hLeft)); + pth.lineTo(toScreen(_edge->head())); + pth.lineTo(toScreen(_edge->head() + ht + hRight)); + painter->drawPath(pth); + break; + } + } + + switch (_edge->style()->arrowTail()) { + case EdgeStyle::Flat: + { + painter->drawLine( + toScreen(_edge->tail() + tLeft), + toScreen(_edge->tail() + tRight)); + break; + } + case EdgeStyle::Pointer: + { + QPainterPath pth; + pth.moveTo(toScreen(_edge->tail() + tt + tLeft)); + pth.lineTo(toScreen(_edge->tail())); + pth.lineTo(toScreen(_edge->tail() + tt + tRight)); + painter->drawPath(pth); + break; + } + } + + 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())); + + //painter->drawEllipse(toScreen(_edge->cp1()), r, r); + //painter->drawEllipse(toScreen(_edge->cp2()), r, r); + + _cp1Item->setPen(QPen(draw)); + _cp1Item->setBrush(QBrush(fill)); + _cp1Item->setVisible(true); + + _cp2Item->setPen(QPen(draw)); + _cp2Item->setBrush(QBrush(fill)); + _cp2Item->setVisible(true); + + r = GLOBAL_SCALEF * 0.05; + painter->setPen(QPen(Qt::black)); + painter->setBrush(QBrush(QColor(255,255,255,200))); + painter->drawEllipse(toScreen(_edge->mid()), r, r); + } else { + _cp1Item->setVisible(false); + _cp2Item->setVisible(false); + } +} + +QRectF EdgeItem::boundingRect() const +{ + return _boundingRect; +} + +QPainterPath EdgeItem::shape() const +{ + return _expPath; +} + +Edge *EdgeItem::edge() const +{ + return _edge; +} + +QGraphicsEllipseItem *EdgeItem::cp1Item() const +{ + return _cp1Item; +} + +QGraphicsEllipseItem *EdgeItem::cp2Item() const +{ + return _cp2Item; +} + +QPainterPath EdgeItem::path() const +{ + return _path; +} + +void EdgeItem::setPath(const QPainterPath &path) +{ + prepareGeometryChange(); + + _path = path; + + // get the shape of the edge, and expand a bit to make selection easier + QPainterPathStroker stroker; + stroker.setWidth(5); + stroker.setJoinStyle(Qt::MiterJoin); + _expPath = (stroker.createStroke(_path) + _path).simplified(); + + float r = GLOBAL_SCALEF * (_edge->cpDist() + 0.2); + _boundingRect = _path.boundingRect().adjusted(-r,-r,r,r); + + update(); +} + diff --git a/src/gui/edgeitem.h b/src/gui/edgeitem.h index 060de13..3d4758a 100644 --- a/src/gui/edgeitem.h +++ b/src/gui/edgeitem.h @@ -1,62 +1,62 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - This program 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. - - This program 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 this program. If not, see . -*/ - -/*! - * A QGraphicsItem that handles drawing a single edge. - */ - -#ifndef EDGEITEM_H -#define EDGEITEM_H - -#include "edge.h" - -#include -#include -#include -#include -#include -#include -#include - -class EdgeItem : public QGraphicsItem -{ -public: - EdgeItem(Edge *edge); - void readPos(); - void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *); - QRectF boundingRect() const; - QPainterPath shape() const; - Edge *edge() const; - QGraphicsEllipseItem *cp1Item() const; - QGraphicsEllipseItem *cp2Item() const; - - - QPainterPath path() const; - void setPath(const QPainterPath &path); - - -private: - Edge *_edge; - QPainterPath _path; - QPainterPath _expPath; - QRectF _boundingRect; - QGraphicsEllipseItem *_cp1Item; - QGraphicsEllipseItem *_cp2Item; -}; - -#endif // EDGEITEM_H +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program 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. + + This program 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 this program. If not, see . +*/ + +/*! + * A QGraphicsItem that handles drawing a single edge. + */ + +#ifndef EDGEITEM_H +#define EDGEITEM_H + +#include "edge.h" + +#include +#include +#include +#include +#include +#include +#include + +class EdgeItem : public QGraphicsItem +{ +public: + EdgeItem(Edge *edge); + void readPos(); + void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *); + QRectF boundingRect() const; + QPainterPath shape() const; + Edge *edge() const; + QGraphicsEllipseItem *cp1Item() const; + QGraphicsEllipseItem *cp2Item() const; + + + QPainterPath path() const; + void setPath(const QPainterPath &path); + + +private: + Edge *_edge; + QPainterPath _path; + QPainterPath _expPath; + QRectF _boundingRect; + QGraphicsEllipseItem *_cp1Item; + QGraphicsEllipseItem *_cp2Item; +}; + +#endif // EDGEITEM_H diff --git a/src/gui/mainmenu.cpp b/src/gui/mainmenu.cpp index 69159d2..3625338 100644 --- a/src/gui/mainmenu.cpp +++ b/src/gui/mainmenu.cpp @@ -1,151 +1,151 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - This program 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. - - This program 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 this program. If not, see . -*/ - -#include "mainmenu.h" -#include "tikzit.h" - -#include - -MainMenu::MainMenu() -{ - ui.setupUi(this); -} - -// File -void MainMenu::on_actionNew_triggered() -{ - tikzit->newDoc(); -} - -void MainMenu::on_actionOpen_triggered() -{ - tikzit->open(); -} - -void MainMenu::on_actionClose_triggered() -{ - if (tikzit->activeWindow() != 0) - tikzit->activeWindow()->close(); -} - -void MainMenu::on_actionSave_triggered() -{ - if (tikzit->activeWindow() != 0) - tikzit->activeWindow()->tikzDocument()->save(); -} - -void MainMenu::on_actionSave_As_triggered() -{ - if (tikzit->activeWindow() != 0) - tikzit->activeWindow()->tikzDocument()->saveAs(); -} - -void MainMenu::on_actionExit_triggered() -{ - tikzit->quit(); -} - - -// Edit -void MainMenu::on_actionUndo_triggered() -{ - if (tikzit->activeWindow() != 0) - tikzit->activeWindow()->tikzDocument()->undoStack()->undo(); -} - -void MainMenu::on_actionRedo_triggered() -{ - if (tikzit->activeWindow() != 0) - tikzit->activeWindow()->tikzDocument()->undoStack()->redo(); -} - -void MainMenu::on_actionCut_triggered() -{ - if (tikzit->activeWindow() != 0) - tikzit->activeWindow()->tikzScene()->cutToClipboard(); -} - -void MainMenu::on_actionCopy_triggered() -{ - if (tikzit->activeWindow() != 0) - tikzit->activeWindow()->tikzScene()->copyToClipboard(); -} - -void MainMenu::on_actionPaste_triggered() -{ - if (tikzit->activeWindow() != 0) - tikzit->activeWindow()->tikzScene()->pasteFromClipboard(); -} - -void MainMenu::on_actionDelete_triggered() -{ - if (tikzit->activeWindow() != 0) - tikzit->activeWindow()->tikzScene()->deleteSelectedItems(); -} - -void MainMenu::on_actionSelect_All_triggered() -{ - if (tikzit->activeWindow() != 0) - tikzit->activeWindow()->tikzScene()->selectAllNodes(); -} - -void MainMenu::on_actionDeselect_All_triggered() -{ - if (tikzit->activeWindow() != 0) - tikzit->activeWindow()->tikzScene()->deselectAll(); -} - - -// Tikz -void MainMenu::on_actionParse_triggered() -{ - MainWindow *win = tikzit->activeWindow(); - if (win != 0) { - win->tikzScene()->parseTikz(win->tikzSource()); - } -} - -void MainMenu::on_actionRevert_triggered() -{ - MainWindow *win = tikzit->activeWindow(); - if (win != 0) { - win->tikzDocument()->refreshTikz(); - win->tikzScene()->setEnabled(true); - } -} - -void MainMenu::on_actionJump_to_Selection_triggered() -{ - MainWindow *win = tikzit->activeWindow(); - if (win != 0) { - qDebug() << "jump to selection on line:" << win->tikzScene()->lineNumberForSelection(); - win->setSourceLine(win->tikzScene()->lineNumberForSelection()); - } -} - - -// View -void MainMenu::on_actionZoom_In_triggered() -{ - if (tikzit->activeWindow() != 0) tikzit->activeWindow()->tikzView()->zoomIn(); -} - -void MainMenu::on_actionZoom_Out_triggered() -{ - if (tikzit->activeWindow() != 0) tikzit->activeWindow()->tikzView()->zoomOut(); -} +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program 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. + + This program 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 this program. If not, see . +*/ + +#include "mainmenu.h" +#include "tikzit.h" + +#include + +MainMenu::MainMenu() +{ + ui.setupUi(this); +} + +// File +void MainMenu::on_actionNew_triggered() +{ + tikzit->newDoc(); +} + +void MainMenu::on_actionOpen_triggered() +{ + tikzit->open(); +} + +void MainMenu::on_actionClose_triggered() +{ + if (tikzit->activeWindow() != 0) + tikzit->activeWindow()->close(); +} + +void MainMenu::on_actionSave_triggered() +{ + if (tikzit->activeWindow() != 0) + tikzit->activeWindow()->tikzDocument()->save(); +} + +void MainMenu::on_actionSave_As_triggered() +{ + if (tikzit->activeWindow() != 0) + tikzit->activeWindow()->tikzDocument()->saveAs(); +} + +void MainMenu::on_actionExit_triggered() +{ + tikzit->quit(); +} + + +// Edit +void MainMenu::on_actionUndo_triggered() +{ + if (tikzit->activeWindow() != 0) + tikzit->activeWindow()->tikzDocument()->undoStack()->undo(); +} + +void MainMenu::on_actionRedo_triggered() +{ + if (tikzit->activeWindow() != 0) + tikzit->activeWindow()->tikzDocument()->undoStack()->redo(); +} + +void MainMenu::on_actionCut_triggered() +{ + if (tikzit->activeWindow() != 0) + tikzit->activeWindow()->tikzScene()->cutToClipboard(); +} + +void MainMenu::on_actionCopy_triggered() +{ + if (tikzit->activeWindow() != 0) + tikzit->activeWindow()->tikzScene()->copyToClipboard(); +} + +void MainMenu::on_actionPaste_triggered() +{ + if (tikzit->activeWindow() != 0) + tikzit->activeWindow()->tikzScene()->pasteFromClipboard(); +} + +void MainMenu::on_actionDelete_triggered() +{ + if (tikzit->activeWindow() != 0) + tikzit->activeWindow()->tikzScene()->deleteSelectedItems(); +} + +void MainMenu::on_actionSelect_All_triggered() +{ + if (tikzit->activeWindow() != 0) + tikzit->activeWindow()->tikzScene()->selectAllNodes(); +} + +void MainMenu::on_actionDeselect_All_triggered() +{ + if (tikzit->activeWindow() != 0) + tikzit->activeWindow()->tikzScene()->deselectAll(); +} + + +// Tikz +void MainMenu::on_actionParse_triggered() +{ + MainWindow *win = tikzit->activeWindow(); + if (win != 0) { + win->tikzScene()->parseTikz(win->tikzSource()); + } +} + +void MainMenu::on_actionRevert_triggered() +{ + MainWindow *win = tikzit->activeWindow(); + if (win != 0) { + win->tikzDocument()->refreshTikz(); + win->tikzScene()->setEnabled(true); + } +} + +void MainMenu::on_actionJump_to_Selection_triggered() +{ + MainWindow *win = tikzit->activeWindow(); + if (win != 0) { + qDebug() << "jump to selection on line:" << win->tikzScene()->lineNumberForSelection(); + win->setSourceLine(win->tikzScene()->lineNumberForSelection()); + } +} + + +// View +void MainMenu::on_actionZoom_In_triggered() +{ + if (tikzit->activeWindow() != 0) tikzit->activeWindow()->tikzView()->zoomIn(); +} + +void MainMenu::on_actionZoom_Out_triggered() +{ + if (tikzit->activeWindow() != 0) tikzit->activeWindow()->tikzView()->zoomOut(); +} diff --git a/src/gui/mainmenu.h b/src/gui/mainmenu.h index 8cb7a3a..aa5c727 100644 --- a/src/gui/mainmenu.h +++ b/src/gui/mainmenu.h @@ -1,64 +1,64 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - This program 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. - - This program 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 this program. If not, see . -*/ - -#ifndef MAINMENU_H -#define MAINMENU_H - -#include "ui_mainmenu.h" - -#include - -class MainMenu : public QMenuBar -{ - Q_OBJECT -public: - MainMenu(); - -private: - Ui::MainMenu ui; - -public slots: - // File - void on_actionNew_triggered(); - void on_actionOpen_triggered(); - void on_actionClose_triggered(); - void on_actionSave_triggered(); - void on_actionSave_As_triggered(); - void on_actionExit_triggered(); - - // Edit - void on_actionUndo_triggered(); - void on_actionRedo_triggered(); - void on_actionCut_triggered(); - void on_actionCopy_triggered(); - void on_actionPaste_triggered(); - void on_actionDelete_triggered(); - void on_actionSelect_All_triggered(); - void on_actionDeselect_All_triggered(); - - // Tikz - void on_actionParse_triggered(); - void on_actionRevert_triggered(); - void on_actionJump_to_Selection_triggered(); - - // View - void on_actionZoom_In_triggered(); - void on_actionZoom_Out_triggered(); -}; - -#endif // MAINMENU_H +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program 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. + + This program 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 this program. If not, see . +*/ + +#ifndef MAINMENU_H +#define MAINMENU_H + +#include "ui_mainmenu.h" + +#include + +class MainMenu : public QMenuBar +{ + Q_OBJECT +public: + MainMenu(); + +private: + Ui::MainMenu ui; + +public slots: + // File + void on_actionNew_triggered(); + void on_actionOpen_triggered(); + void on_actionClose_triggered(); + void on_actionSave_triggered(); + void on_actionSave_As_triggered(); + void on_actionExit_triggered(); + + // Edit + void on_actionUndo_triggered(); + void on_actionRedo_triggered(); + void on_actionCut_triggered(); + void on_actionCopy_triggered(); + void on_actionPaste_triggered(); + void on_actionDelete_triggered(); + void on_actionSelect_All_triggered(); + void on_actionDeselect_All_triggered(); + + // Tikz + void on_actionParse_triggered(); + void on_actionRevert_triggered(); + void on_actionJump_to_Selection_triggered(); + + // View + void on_actionZoom_In_triggered(); + void on_actionZoom_Out_triggered(); +}; + +#endif // MAINMENU_H diff --git a/src/gui/mainmenu.ui b/src/gui/mainmenu.ui index ce7d41d..6a2511e 100644 --- a/src/gui/mainmenu.ui +++ b/src/gui/mainmenu.ui @@ -1,209 +1,209 @@ - - - MainMenu - - - - 0 - 0 - 476 - 22 - - - - - File - - - - - - - - - - - - - Edit - - - - - - - - - - - - - - - Tikz - - - - - - - - View - - - - - - - New... - - - Ctrl+N - - - - - Open... - - - Ctrl+O - - - - - Close - - - Ctrl+W - - - - - Save - - - Ctrl+S - - - - - Save As... - - - Ctrl+Shift+S - - - - - Undo - - - Ctrl+Z - - - - - Redo - - - Ctrl+Shift+Z - - - - - Cut - - - Ctrl+X - - - - - Copy - - - Ctrl+C - - - - - Paste - - - Ctrl+V - - - - - Delete - - - Backspace - - - - - Select All - - - Ctrl+A - - - - - Deselect All - - - Ctrl+D - - - - - Parse Tikz - - - Ctrl+T - - - - - Zoom In - - - Ctrl+= - - - - - Zoom Out - - - Ctrl+- - - - - - Exit - - - - - Revert Tikz - - - - - Jump to Selection - - - Ctrl+J - - - - - - - - - - + + + MainMenu + + + + 0 + 0 + 476 + 22 + + + + + File + + + + + + + + + + + + + Edit + + + + + + + + + + + + + + + Tikz + + + + + + + + View + + + + + + + New... + + + Ctrl+N + + + + + Open... + + + Ctrl+O + + + + + Close + + + Ctrl+W + + + + + Save + + + Ctrl+S + + + + + Save As... + + + Ctrl+Shift+S + + + + + Undo + + + Ctrl+Z + + + + + Redo + + + Ctrl+Shift+Z + + + + + Cut + + + Ctrl+X + + + + + Copy + + + Ctrl+C + + + + + Paste + + + Ctrl+V + + + + + Delete + + + Backspace + + + + + Select All + + + Ctrl+A + + + + + Deselect All + + + Ctrl+D + + + + + Parse Tikz + + + Ctrl+T + + + + + Zoom In + + + Ctrl+= + + + + + Zoom Out + + + Ctrl+- + + + + + Exit + + + + + Revert Tikz + + + + + Jump to Selection + + + Ctrl+J + + + + + + + + + + diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 953889e..15b6943 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -1,160 +1,160 @@ -#include "mainwindow.h" -#include "ui_mainwindow.h" - -#include "mainmenu.h" -#include "tikzassembler.h" -#include "toolpalette.h" -#include "tikzit.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -int MainWindow::_numWindows = 0; - -MainWindow::MainWindow(QWidget *parent) : - QMainWindow(parent), - ui(new Ui::MainWindow) -{ - _windowId = _numWindows; - _numWindows++; - ui->setupUi(this); - setAttribute(Qt::WA_DeleteOnClose, true); - _tikzDocument = new TikzDocument(this); - - _toolPalette = new ToolPalette(this); - addToolBar(_toolPalette); - - _stylePalette = new StylePalette(this); - addDockWidget(Qt::RightDockWidgetArea, _stylePalette); - - _tikzScene = new TikzScene(_tikzDocument, _toolPalette, _stylePalette, this); - ui->tikzView->setScene(_tikzScene); - - // TODO: check if each window should have a menu - _menu = new MainMenu(); - _menu->setParent(this); - - setMenuBar(_menu); - - // initially, the source view should be collapsed - QList sz = ui->splitter->sizes(); - sz[0] = sz[0] + sz[1]; - sz[1] = 0; - ui->splitter->setSizes(sz); - - _tikzDocument->refreshTikz(); - - connect(_tikzDocument->undoStack(), SIGNAL(cleanChanged(bool)), this, SLOT(updateFileName())); -} - -MainWindow::~MainWindow() -{ - tikzit->removeWindow(this); - delete ui; -} - -void MainWindow::open(QString fileName) -{ - _tikzDocument->open(fileName); - - //ui->tikzSource->setText(_tikzDocument->tikz()); - - - if (_tikzDocument->parseSuccess()) { - statusBar()->showMessage("TiKZ parsed successfully", 2000); - //setWindowTitle("TiKZiT - " + _tikzDocument->shortName()); - _tikzScene->setTikzDocument(_tikzDocument); - updateFileName(); - } else { - statusBar()->showMessage("Cannot read TiKZ source"); - } - -} - -void MainWindow::closeEvent(QCloseEvent *event) -{ - qDebug() << "got close event"; - QMainWindow::closeEvent(event); -} - -void MainWindow::changeEvent(QEvent *event) -{ - if (event->type() == QEvent::ActivationChange && isActiveWindow()) { - tikzit->setActiveWindow(this); - //tikzit->stylePalette()->raise(); - } - QMainWindow::changeEvent(event); -} - -StylePalette *MainWindow::stylePalette() const -{ - return _stylePalette; -} - -QString MainWindow::tikzSource() -{ - return ui->tikzSource->toPlainText(); -} - -void MainWindow::setSourceLine(int line) -{ - QTextCursor cursor(ui->tikzSource->document()->findBlockByLineNumber(line)); - cursor.movePosition(QTextCursor::EndOfLine); - //ui->tikzSource->moveCursor(QTextCursor::End); - ui->tikzSource->setTextCursor(cursor); - ui->tikzSource->setFocus(); -} - -void MainWindow::updateFileName() -{ - QString nm = _tikzDocument->shortName(); - if (nm.isEmpty()) nm = "untitled"; - if (!_tikzDocument->isClean()) nm += "*"; - setWindowTitle("TiKZiT - " + nm); -} - -void MainWindow::refreshTikz() -{ - // don't emit textChanged() when we update the tikz - ui->tikzSource->blockSignals(true); - ui->tikzSource->setText(_tikzDocument->tikz()); - ui->tikzSource->blockSignals(false); -} - -ToolPalette *MainWindow::toolPalette() const -{ - return _toolPalette; -} - -TikzDocument *MainWindow::tikzDocument() const -{ - return _tikzDocument; -} - -TikzScene *MainWindow::tikzScene() const -{ - return _tikzScene; -} - -int MainWindow::windowId() const -{ - return _windowId; -} - -TikzView *MainWindow::tikzView() const -{ - return ui->tikzView; -} - -void MainWindow::on_tikzSource_textChanged() -{ - if (_tikzScene->enabled()) _tikzScene->setEnabled(false); -} - - +#include "mainwindow.h" +#include "ui_mainwindow.h" + +#include "mainmenu.h" +#include "tikzassembler.h" +#include "toolpalette.h" +#include "tikzit.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +int MainWindow::_numWindows = 0; + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + _windowId = _numWindows; + _numWindows++; + ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose, true); + _tikzDocument = new TikzDocument(this); + + _toolPalette = new ToolPalette(this); + addToolBar(_toolPalette); + + _stylePalette = new StylePalette(this); + addDockWidget(Qt::RightDockWidgetArea, _stylePalette); + + _tikzScene = new TikzScene(_tikzDocument, _toolPalette, _stylePalette, this); + ui->tikzView->setScene(_tikzScene); + + // TODO: check if each window should have a menu + _menu = new MainMenu(); + _menu->setParent(this); + + setMenuBar(_menu); + + // initially, the source view should be collapsed + QList sz = ui->splitter->sizes(); + sz[0] = sz[0] + sz[1]; + sz[1] = 0; + ui->splitter->setSizes(sz); + + _tikzDocument->refreshTikz(); + + connect(_tikzDocument->undoStack(), SIGNAL(cleanChanged(bool)), this, SLOT(updateFileName())); +} + +MainWindow::~MainWindow() +{ + tikzit->removeWindow(this); + delete ui; +} + +void MainWindow::open(QString fileName) +{ + _tikzDocument->open(fileName); + + //ui->tikzSource->setText(_tikzDocument->tikz()); + + + if (_tikzDocument->parseSuccess()) { + statusBar()->showMessage("TiKZ parsed successfully", 2000); + //setWindowTitle("TiKZiT - " + _tikzDocument->shortName()); + _tikzScene->setTikzDocument(_tikzDocument); + updateFileName(); + } else { + statusBar()->showMessage("Cannot read TiKZ source"); + } + +} + +void MainWindow::closeEvent(QCloseEvent *event) +{ + qDebug() << "got close event"; + QMainWindow::closeEvent(event); +} + +void MainWindow::changeEvent(QEvent *event) +{ + if (event->type() == QEvent::ActivationChange && isActiveWindow()) { + tikzit->setActiveWindow(this); + //tikzit->stylePalette()->raise(); + } + QMainWindow::changeEvent(event); +} + +StylePalette *MainWindow::stylePalette() const +{ + return _stylePalette; +} + +QString MainWindow::tikzSource() +{ + return ui->tikzSource->toPlainText(); +} + +void MainWindow::setSourceLine(int line) +{ + QTextCursor cursor(ui->tikzSource->document()->findBlockByLineNumber(line)); + cursor.movePosition(QTextCursor::EndOfLine); + //ui->tikzSource->moveCursor(QTextCursor::End); + ui->tikzSource->setTextCursor(cursor); + ui->tikzSource->setFocus(); +} + +void MainWindow::updateFileName() +{ + QString nm = _tikzDocument->shortName(); + if (nm.isEmpty()) nm = "untitled"; + if (!_tikzDocument->isClean()) nm += "*"; + setWindowTitle("TiKZiT - " + nm); +} + +void MainWindow::refreshTikz() +{ + // don't emit textChanged() when we update the tikz + ui->tikzSource->blockSignals(true); + ui->tikzSource->setText(_tikzDocument->tikz()); + ui->tikzSource->blockSignals(false); +} + +ToolPalette *MainWindow::toolPalette() const +{ + return _toolPalette; +} + +TikzDocument *MainWindow::tikzDocument() const +{ + return _tikzDocument; +} + +TikzScene *MainWindow::tikzScene() const +{ + return _tikzScene; +} + +int MainWindow::windowId() const +{ + return _windowId; +} + +TikzView *MainWindow::tikzView() const +{ + return ui->tikzView; +} + +void MainWindow::on_tikzSource_textChanged() +{ + if (_tikzScene->enabled()) _tikzScene->setEnabled(false); +} + + diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h index 3ab641c..1e05239 100644 --- a/src/gui/mainwindow.h +++ b/src/gui/mainwindow.h @@ -1,60 +1,60 @@ -/*! - * A top-level window, which contains a single TikzDocument. - */ - -#ifndef MAINWINDOW_H -#define MAINWINDOW_H - -#include "tikzscene.h" -#include "tikzview.h" -#include "graph.h" -#include "tikzdocument.h" -#include "mainmenu.h" -#include "toolpalette.h" -#include "stylepalette.h" - -#include -#include - -namespace Ui { -class MainWindow; -} - -class MainWindow : public QMainWindow -{ - Q_OBJECT - -public: - explicit MainWindow(QWidget *parent = 0); - ~MainWindow(); - - void open(QString fileName); - int windowId() const; - TikzView *tikzView() const; - TikzScene *tikzScene() const; - TikzDocument *tikzDocument() const; - ToolPalette *toolPalette() const; - StylePalette *stylePalette() const; - QString tikzSource(); - void setSourceLine(int line); - -public slots: - void on_tikzSource_textChanged(); - void updateFileName(); - void refreshTikz(); -protected: - void closeEvent(QCloseEvent *event); - void changeEvent(QEvent *event); - -private: - TikzScene *_tikzScene; - TikzDocument *_tikzDocument; - MainMenu *_menu; - ToolPalette *_toolPalette; - StylePalette *_stylePalette; - Ui::MainWindow *ui; - int _windowId; - static int _numWindows; -}; - -#endif // MAINWINDOW_H +/*! + * A top-level window, which contains a single TikzDocument. + */ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include "tikzscene.h" +#include "tikzview.h" +#include "graph.h" +#include "tikzdocument.h" +#include "mainmenu.h" +#include "toolpalette.h" +#include "stylepalette.h" + +#include +#include + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + + void open(QString fileName); + int windowId() const; + TikzView *tikzView() const; + TikzScene *tikzScene() const; + TikzDocument *tikzDocument() const; + ToolPalette *toolPalette() const; + StylePalette *stylePalette() const; + QString tikzSource(); + void setSourceLine(int line); + +public slots: + void on_tikzSource_textChanged(); + void updateFileName(); + void refreshTikz(); +protected: + void closeEvent(QCloseEvent *event); + void changeEvent(QEvent *event); + +private: + TikzScene *_tikzScene; + TikzDocument *_tikzDocument; + MainMenu *_menu; + ToolPalette *_toolPalette; + StylePalette *_stylePalette; + Ui::MainWindow *ui; + int _windowId; + static int _numWindows; +}; + +#endif // MAINWINDOW_H diff --git a/src/gui/mainwindow.ui b/src/gui/mainwindow.ui index 3df579f..137d6cf 100644 --- a/src/gui/mainwindow.ui +++ b/src/gui/mainwindow.ui @@ -1,205 +1,205 @@ - - - MainWindow - - - - 0 - 0 - 640 - 580 - - - - TikZiT - untitled - - - - - 0 - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Qt::Vertical - - - - - - Courier New - 10 - - - - QTextEdit::NoWrap - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Courier New'; font-size:10pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'.SF NS Text'; font-size:13pt;"><br /></p></body></html> - - - 20 - - - - - - - - - - New... - - - - - Open... - - - - - Close - - - - - Save - - - - - Save As... - - - - - Undo - - - - - Redo - - - - - Cut - - - - - Copy - - - - - Paste - - - - - Delete - - - - - Select All - - - - - Deselect All - - - - - Parse - - - Ctrl+T - - - - - Zoom In - - - Ctrl+= - - - - - Zoom Out - - - Ctrl+- - - - - - - - TikzView - QGraphicsView -
tikzview.h
- - zoomIn() - zoomOut() - -
-
- - - - actionZoom_In - triggered() - tikzView - zoomIn() - - - -1 - -1 - - - 237 - 103 - - - - - actionZoom_Out - triggered() - tikzView - zoomOut() - - - -1 - -1 - - - 237 - 103 - - - - -
+ + + MainWindow + + + + 0 + 0 + 640 + 580 + + + + TikZiT - untitled + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Vertical + + + + + + Courier New + 10 + + + + QTextEdit::NoWrap + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Courier New'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'.SF NS Text'; font-size:13pt;"><br /></p></body></html> + + + 20 + + + + + + + + + + New... + + + + + Open... + + + + + Close + + + + + Save + + + + + Save As... + + + + + Undo + + + + + Redo + + + + + Cut + + + + + Copy + + + + + Paste + + + + + Delete + + + + + Select All + + + + + Deselect All + + + + + Parse + + + Ctrl+T + + + + + Zoom In + + + Ctrl+= + + + + + Zoom Out + + + Ctrl+- + + + + + + + TikzView + QGraphicsView +
tikzview.h
+ + zoomIn() + zoomOut() + +
+
+ + + + actionZoom_In + triggered() + tikzView + zoomIn() + + + -1 + -1 + + + 237 + 103 + + + + + actionZoom_Out + triggered() + tikzView + zoomOut() + + + -1 + -1 + + + 237 + 103 + + + + +
diff --git a/src/gui/nodeitem.cpp b/src/gui/nodeitem.cpp index d308dd2..b452848 100644 --- a/src/gui/nodeitem.cpp +++ b/src/gui/nodeitem.cpp @@ -1,159 +1,159 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - This program 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. - - This program 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 this program. If not, see . -*/ - -#include "tikzit.h" -#include "nodeitem.h" -#include "tikzscene.h" -#include - -#include -#include -#include -#include -#include -#include -#include - -NodeItem::NodeItem(Node *node) -{ - _node = node; - setFlag(QGraphicsItem::ItemIsSelectable); - //setFlag(QGraphicsItem::ItemIsMovable); - //setFlag(QGraphicsItem::ItemSendsGeometryChanges); - readPos(); - updateBounds(); -} - -void NodeItem::readPos() -{ - setPos(toScreen(_node->point())); -} - -void NodeItem::writePos() -{ - _node->setPoint(fromScreen(pos())); -} - -QRectF NodeItem::labelRect() const { - QString label = _node->label(); - //QFont f("Courier", 9); - QFontMetrics fm(Tikzit::LABEL_FONT); - - QRectF rect = fm.boundingRect(label); - //rect.adjust(-2,-2,2,2); - rect.moveCenter(QPointF(0,0)); - return rect; -} - -void NodeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) -{ - 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 p; - p << 1.0 << 2.0; - pen.setDashPattern(p); - pen.setWidthF(2.0f); - 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() != "") { - QRectF rect = labelRect(); - QPen pen(QColor(200,0,0,120)); - QVector 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(Tikzit::LABEL_FONT); - 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.2, GLOBAL_SCALEF * 0.2); - return path; -} - -// TODO: nodeitem should sync boundingRect()-relevant stuff (label etc) explicitly, -// to allow prepareGeometryChange() -QRectF NodeItem::boundingRect() const -{ - return _boundingRect; -} - -void NodeItem::updateBounds() -{ - prepareGeometryChange(); - QString label = _node->label(); - if (label != "") { - QFontMetrics fm(Tikzit::LABEL_FONT); - QRectF labelRect = fm.boundingRect(label); - labelRect.moveCenter(QPointF(0, 0)); - _boundingRect = labelRect.united(shape().boundingRect()).adjusted(-4, -4, 4, 4); - } else { - _boundingRect = shape().boundingRect().adjusted(-4, -4, 4, 4); - } -} - -Node *NodeItem::node() const -{ - return _node; -} - -//QVariant NodeItem::itemChange(GraphicsItemChange change, const QVariant &value) -//{ -// if (change == ItemPositionChange) { -// QPointF newPos = value.toPointF(); -// int gridSize = GLOBAL_SCALE / 8; -// QPointF gridPos(round(newPos.x()/gridSize)*gridSize, round(newPos.y()/gridSize)*gridSize); -// _node->setPoint(fromScreen(gridPos)); -// -// return gridPos; -// } else { -// return QGraphicsItem::itemChange(change, value); -// } -//} +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program 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. + + This program 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 this program. If not, see . +*/ + +#include "tikzit.h" +#include "nodeitem.h" +#include "tikzscene.h" +#include + +#include +#include +#include +#include +#include +#include +#include + +NodeItem::NodeItem(Node *node) +{ + _node = node; + setFlag(QGraphicsItem::ItemIsSelectable); + //setFlag(QGraphicsItem::ItemIsMovable); + //setFlag(QGraphicsItem::ItemSendsGeometryChanges); + readPos(); + updateBounds(); +} + +void NodeItem::readPos() +{ + setPos(toScreen(_node->point())); +} + +void NodeItem::writePos() +{ + _node->setPoint(fromScreen(pos())); +} + +QRectF NodeItem::labelRect() const { + QString label = _node->label(); + //QFont f("Courier", 9); + QFontMetrics fm(Tikzit::LABEL_FONT); + + QRectF rect = fm.boundingRect(label); + //rect.adjust(-2,-2,2,2); + rect.moveCenter(QPointF(0,0)); + return rect; +} + +void NodeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + 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 p; + p << 1.0 << 2.0; + pen.setDashPattern(p); + pen.setWidthF(2.0f); + 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() != "") { + QRectF rect = labelRect(); + QPen pen(QColor(200,0,0,120)); + QVector 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(Tikzit::LABEL_FONT); + 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.2, GLOBAL_SCALEF * 0.2); + return path; +} + +// TODO: nodeitem should sync boundingRect()-relevant stuff (label etc) explicitly, +// to allow prepareGeometryChange() +QRectF NodeItem::boundingRect() const +{ + return _boundingRect; +} + +void NodeItem::updateBounds() +{ + prepareGeometryChange(); + QString label = _node->label(); + if (label != "") { + QFontMetrics fm(Tikzit::LABEL_FONT); + QRectF labelRect = fm.boundingRect(label); + labelRect.moveCenter(QPointF(0, 0)); + _boundingRect = labelRect.united(shape().boundingRect()).adjusted(-4, -4, 4, 4); + } else { + _boundingRect = shape().boundingRect().adjusted(-4, -4, 4, 4); + } +} + +Node *NodeItem::node() const +{ + return _node; +} + +//QVariant NodeItem::itemChange(GraphicsItemChange change, const QVariant &value) +//{ +// if (change == ItemPositionChange) { +// QPointF newPos = value.toPointF(); +// int gridSize = GLOBAL_SCALE / 8; +// QPointF gridPos(round(newPos.x()/gridSize)*gridSize, round(newPos.y()/gridSize)*gridSize); +// _node->setPoint(fromScreen(gridPos)); +// +// return gridPos; +// } else { +// return QGraphicsItem::itemChange(change, value); +// } +//} diff --git a/src/gui/nodeitem.h b/src/gui/nodeitem.h index efd32f1..678a7e8 100644 --- a/src/gui/nodeitem.h +++ b/src/gui/nodeitem.h @@ -1,51 +1,51 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - This program 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. - - This program 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 this program. If not, see . -*/ - -/*! - * A QGraphicsItem that handles drawing a single node. - */ - -#ifndef NODEITEM_H -#define NODEITEM_H - -#include "node.h" - -#include -#include -#include -#include - -class NodeItem : public QGraphicsItem -{ -public: - NodeItem(Node *node); - void readPos(); - void writePos(); - void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *); - QPainterPath shape() const override; - QRectF boundingRect() const override; - void updateBounds(); - Node *node() const; - -private: - Node *_node; - QRectF labelRect() const; - QRectF _boundingRect; -}; - -#endif // NODEITEM_H +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program 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. + + This program 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 this program. If not, see . +*/ + +/*! + * A QGraphicsItem that handles drawing a single node. + */ + +#ifndef NODEITEM_H +#define NODEITEM_H + +#include "node.h" + +#include +#include +#include +#include + +class NodeItem : public QGraphicsItem +{ +public: + NodeItem(Node *node); + void readPos(); + void writePos(); + void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *); + QPainterPath shape() const override; + QRectF boundingRect() const override; + void updateBounds(); + Node *node() const; + +private: + Node *_node; + QRectF labelRect() const; + QRectF _boundingRect; +}; + +#endif // NODEITEM_H diff --git a/src/gui/propertypalette.cpp b/src/gui/propertypalette.cpp index e2b8b8d..c27b8b2 100644 --- a/src/gui/propertypalette.cpp +++ b/src/gui/propertypalette.cpp @@ -1,61 +1,61 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - This program 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. - - This program 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 this program. If not, see . -*/ - -#include "propertypalette.h" -#include "graphelementdata.h" -#include "ui_propertypalette.h" - -#include -#include -#include -#include - -PropertyPalette::PropertyPalette(QWidget *parent) : - QDockWidget(parent), - ui(new Ui::PropertyPalette) -{ - setWindowFlags(Qt::Window - | Qt::CustomizeWindowHint - | Qt::WindowTitleHint); - //setFocusPolicy(Qt::NoFocus); - ui->setupUi(this); - GraphElementData *d = new GraphElementData(); - d->setProperty("key 1", "value 1"); - d->setAtom("atom 1"); - d->setProperty("key 2", "value 2"); - - //QModelIndex i = d->index(0,0); - //ui->treeView->setModel(d); - - QSettings settings("tikzit", "tikzit"); - QVariant geom = settings.value("property-palette-geometry"); - if (geom != QVariant()) { - restoreGeometry(geom.toByteArray()); - } -} - -PropertyPalette::~PropertyPalette() -{ - delete ui; -} - -void PropertyPalette::closeEvent(QCloseEvent *event) { - QSettings settings("tikzit", "tikzit"); - settings.setValue("property-palette-geometry", saveGeometry()); - QDockWidget::closeEvent(event); -} +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program 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. + + This program 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 this program. If not, see . +*/ + +#include "propertypalette.h" +#include "graphelementdata.h" +#include "ui_propertypalette.h" + +#include +#include +#include +#include + +PropertyPalette::PropertyPalette(QWidget *parent) : + QDockWidget(parent), + ui(new Ui::PropertyPalette) +{ + setWindowFlags(Qt::Window + | Qt::CustomizeWindowHint + | Qt::WindowTitleHint); + //setFocusPolicy(Qt::NoFocus); + ui->setupUi(this); + GraphElementData *d = new GraphElementData(); + d->setProperty("key 1", "value 1"); + d->setAtom("atom 1"); + d->setProperty("key 2", "value 2"); + + //QModelIndex i = d->index(0,0); + //ui->treeView->setModel(d); + + QSettings settings("tikzit", "tikzit"); + QVariant geom = settings.value("property-palette-geometry"); + if (geom != QVariant()) { + restoreGeometry(geom.toByteArray()); + } +} + +PropertyPalette::~PropertyPalette() +{ + delete ui; +} + +void PropertyPalette::closeEvent(QCloseEvent *event) { + QSettings settings("tikzit", "tikzit"); + settings.setValue("property-palette-geometry", saveGeometry()); + QDockWidget::closeEvent(event); +} diff --git a/src/gui/propertypalette.h b/src/gui/propertypalette.h index 1241123..29fb0af 100644 --- a/src/gui/propertypalette.h +++ b/src/gui/propertypalette.h @@ -1,46 +1,46 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - This program 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. - - This program 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 this program. If not, see . -*/ - -/*! - * Enables the user to edit properties of the graph, as well as the selected node/edge. - */ - -#ifndef PROPERTYPALETTE_H -#define PROPERTYPALETTE_H - -#include - -namespace Ui { -class PropertyPalette; -} - -class PropertyPalette : public QDockWidget -{ - Q_OBJECT - -public: - explicit PropertyPalette(QWidget *parent = 0); - ~PropertyPalette(); - -protected: - void closeEvent(QCloseEvent *event); -private: - Ui::PropertyPalette *ui; -}; - -#endif // PROPERTYPALETTE_H +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program 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. + + This program 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 this program. If not, see . +*/ + +/*! + * Enables the user to edit properties of the graph, as well as the selected node/edge. + */ + +#ifndef PROPERTYPALETTE_H +#define PROPERTYPALETTE_H + +#include + +namespace Ui { +class PropertyPalette; +} + +class PropertyPalette : public QDockWidget +{ + Q_OBJECT + +public: + explicit PropertyPalette(QWidget *parent = 0); + ~PropertyPalette(); + +protected: + void closeEvent(QCloseEvent *event); +private: + Ui::PropertyPalette *ui; +}; + +#endif // PROPERTYPALETTE_H diff --git a/src/gui/propertypalette.ui b/src/gui/propertypalette.ui index f5ccebd..a8ba5d2 100644 --- a/src/gui/propertypalette.ui +++ b/src/gui/propertypalette.ui @@ -1,33 +1,33 @@ - - - PropertyPalette - - - - 0 - 0 - 194 - 341 - - - - false - - - Properties - - - - - - - 0 - - - - - - - - - + + + PropertyPalette + + + + 0 + 0 + 194 + 341 + + + + false + + + Properties + + + + + + + 0 + + + + + + + + + diff --git a/src/gui/stylepalette.cpp b/src/gui/stylepalette.cpp index 42d440e..e3fea0b 100644 --- a/src/gui/stylepalette.cpp +++ b/src/gui/stylepalette.cpp @@ -1,179 +1,179 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - This program 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. - - This program 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 this program. If not, see . -*/ - -#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(48,48)); - - - ui->edgeStyleListView->setModel(_edgeModel); - ui->edgeStyleListView->setViewMode(QListView::IconMode); - ui->edgeStyleListView->setMovement(QListView::Static); - ui->edgeStyleListView->setGridSize(QSize(48,48)); - - 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(); - } -} - -QString StylePalette::activeEdgeStyleName() -{ - const QModelIndexList i = ui->edgeStyleListView->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); -} +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program 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. + + This program 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 this program. If not, see . +*/ + +#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(48,48)); + + + ui->edgeStyleListView->setModel(_edgeModel); + ui->edgeStyleListView->setViewMode(QListView::IconMode); + ui->edgeStyleListView->setMovement(QListView::Static); + ui->edgeStyleListView->setGridSize(QSize(48,48)); + + 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(); + } +} + +QString StylePalette::activeEdgeStyleName() +{ + const QModelIndexList i = ui->edgeStyleListView->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 index 01daa90..45dc8da 100644 --- a/src/gui/stylepalette.h +++ b/src/gui/stylepalette.h @@ -1,61 +1,61 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - This program 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. - - This program 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 this program. If not, see . -*/ - -#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(); - QString activeEdgeStyleName(); - - -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 +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program 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. + + This program 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 this program. If not, see . +*/ + +#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(); + QString activeEdgeStyleName(); + + +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 index be8263e..4f5b58d 100644 --- a/src/gui/stylepalette.ui +++ b/src/gui/stylepalette.ui @@ -1,120 +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 - - - - - - - - - - - - - - - + + + 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 6f2994b..47464fe 100644 --- a/src/gui/tikzscene.cpp +++ b/src/gui/tikzscene.cpp @@ -1,780 +1,780 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - This program 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. - - This program 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 this program. If not, see . -*/ - -#include "tikzit.h" -#include "util.h" -#include "tikzscene.h" -#include "undocommands.h" -#include "tikzassembler.h" - -#include -#include -#include -#include -#include -#include - - -TikzScene::TikzScene(TikzDocument *tikzDocument, ToolPalette *tools, - StylePalette *styles, QObject *parent) : - QGraphicsScene(parent), _tikzDocument(tikzDocument), _tools(tools), _styles(styles) -{ - _modifyEdgeItem = 0; - _edgeStartNodeItem = 0; - _drawEdgeItem = new QGraphicsLineItem(); - _rubberBandItem = new QGraphicsRectItem(); - _enabled = true; - //setSceneRect(-310,-230,620,450); - setSceneRect(-1000,-1000,2000,2000); - - QPen pen; - pen.setColor(QColor::fromRgbF(0.5f, 0.0f, 0.5f)); - //pen.setWidth(3.0f); - pen.setCosmetic(true); - _drawEdgeItem->setPen(pen); - _drawEdgeItem->setLine(0,0,0,0); - _drawEdgeItem->setVisible(false); - addItem(_drawEdgeItem); - - pen.setColor(QColor::fromRgbF(0.6f, 0.6f, 0.8f)); - //pen.setWidth(3.0f); - //QVector dash; - //dash << 4.0 << 4.0; - pen.setStyle(Qt::DashLine); - //pen.setDashPattern(dash); - _rubberBandItem->setPen(pen); - - QBrush brush(QColor::fromRgbF(0.6,0.6,0.8,0.2)); - _rubberBandItem->setBrush(brush); - - _rubberBandItem->setVisible(false); - addItem(_rubberBandItem); -} - -TikzScene::~TikzScene() { -} - -Graph *TikzScene::graph() -{ - return _tikzDocument->graph(); -} - -void TikzScene::graphReplaced() -{ - - foreach (NodeItem *ni, _nodeItems) { - removeItem(ni); - delete ni; - } - _nodeItems.clear(); - - foreach (EdgeItem *ei, _edgeItems) { - removeItem(ei); - delete ei; - } - _edgeItems.clear(); - - foreach (Edge *e, graph()->edges()) { - e->attachStyle(); - EdgeItem *ei = new EdgeItem(e); - _edgeItems.insert(e, ei); - addItem(ei); - } - - foreach (Node *n, graph()->nodes()) { - n->attachStyle(); - NodeItem *ni = new NodeItem(n); - _nodeItems.insert(n, ni); - addItem(ni); - } -} - -void TikzScene::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - if (!_enabled) return; - - // current mouse position, in scene coordinates - _mouseDownPos = event->scenePos(); - - _draggingNodes = false; - - // disable rubber band drag, which will clear the selection. Only re-enable it - // for the SELECT tool, and when no control point has been clicked. - //views()[0]->setDragMode(QGraphicsView::NoDrag); - - // radius of a control point for bezier edges, in scene coordinates - qreal cpR = GLOBAL_SCALEF * (0.1); - qreal cpR2 = cpR * cpR; - - switch (_tools->currentTool()) { - case ToolPalette::SELECT: - // check if we grabbed a control point of an edge - foreach (QGraphicsItem *gi, selectedItems()) { - if (EdgeItem *ei = dynamic_cast(gi)) { - qreal dx, dy; - - dx = ei->cp1Item()->pos().x() - _mouseDownPos.x(); - dy = ei->cp1Item()->pos().y() - _mouseDownPos.y(); - - if (dx*dx + dy*dy <= cpR2) { - _modifyEdgeItem = ei; - _firstControlPoint = true; - break; - } - - dx = ei->cp2Item()->pos().x() - _mouseDownPos.x(); - dy = ei->cp2Item()->pos().y() - _mouseDownPos.y(); - - if (dx*dx + dy*dy <= cpR2) { - _modifyEdgeItem = ei; - _firstControlPoint = false; - break; - } - } - } - - if (_modifyEdgeItem != 0) { - // store for undo purposes - Edge *e = _modifyEdgeItem->edge(); - _oldBend = e->bend(); - _oldInAngle = e->inAngle(); - _oldOutAngle = e->outAngle(); - _oldWeight = e->weight(); - } else { - // since we are not dragging a control point, process the click normally - //views()[0]->setDragMode(QGraphicsView::RubberBandDrag); - QGraphicsScene::mousePressEvent(event); - - if (items(_mouseDownPos).isEmpty()) { - _rubberBandItem->setRect(QRectF(_mouseDownPos,_mouseDownPos)); - _rubberBandItem->setVisible(true); - qDebug() << "starting rubber band drag"; - } - -// foreach (QGraphicsItem *gi, items()) { -// if (EdgeItem *ei = dynamic_cast(gi)) { -// //qDebug() << "got an edge item: " << ei; -// ei->setFlag(QGraphicsItem::ItemIsSelectable, false); -// //ei->setSelected(true); -// } -// } - - // save current node positions for undo support - _oldNodePositions.clear(); - foreach (QGraphicsItem *gi, selectedItems()) { - if (NodeItem *ni = dynamic_cast(gi)) { - _oldNodePositions.insert(ni->node(), ni->node()->point()); - } - } - - auto its = items(_mouseDownPos); - if (!its.isEmpty() && dynamic_cast(its[0])) - _draggingNodes = true; - } - - break; - case ToolPalette::VERTEX: - break; - case ToolPalette::EDGE: - foreach (QGraphicsItem *gi, items(_mouseDownPos)) { - if (NodeItem *ni = dynamic_cast(gi)){ - _edgeStartNodeItem = ni; - _edgeEndNodeItem = ni; - QLineF line(toScreen(ni->node()->point()), _mouseDownPos); - _drawEdgeItem->setLine(line); - _drawEdgeItem->setVisible(true); - break; - } - } - break; - case ToolPalette::CROP: - break; - } -} - -void TikzScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) -{ - if (!_enabled) return; - - // current mouse position, in scene coordinates - QPointF mousePos = event->scenePos(); - //QRectF rb = views()[0]->rubberBandRect(); - //invalidate(-800,-800,1600,1600); - //invalidate(QRectF(), QGraphicsScene::BackgroundLayer); - - switch (_tools->currentTool()) { - case ToolPalette::SELECT: - if (_modifyEdgeItem != 0) { - Edge *e = _modifyEdgeItem->edge(); - - // dragging a control point - QPointF src = toScreen(e->source()->point()); - QPointF targ = toScreen(e->target()->point()); - float dx1 = targ.x() - src.x(); - float dy1 = targ.y() - src.y(); - float dx2, dy2; - if (_firstControlPoint) { - dx2 = mousePos.x() - src.x(); - dy2 = mousePos.y() - src.y(); - } else { - dx2 = mousePos.x() - targ.x(); - dy2 = mousePos.y() - targ.y(); - } - - float baseDist = sqrt(dx1*dx1 + dy1*dy1); - float handleDist = sqrt(dx2*dx2 + dy2*dy2); - float wcoarseness = 0.1f; - - if (!e->isSelfLoop()) { - if (baseDist != 0) { - e->setWeight(roundToNearest(wcoarseness, handleDist/baseDist)); - } else { - e->setWeight(roundToNearest(wcoarseness, handleDist/GLOBAL_SCALEF)); - } - } - - float control_angle = atan2(-dy2, dx2); - - int bcoarseness = 15; - - if(e->basicBendMode()) { - float bnd; - float base_angle = atan2(-dy1, dx1); - if (_firstControlPoint) { - bnd = base_angle - control_angle; - } else { - bnd = control_angle - base_angle + M_PI; - if (bnd > M_PI) bnd -= 2*M_PI; - } - - e->setBend(round(bnd * (180.0f / M_PI) * (1.0f / (float)bcoarseness)) * bcoarseness); - - } else { - int bnd = round(control_angle * (180.0f / M_PI) * - (1.0f / (float)bcoarseness)) * - bcoarseness; - if (_firstControlPoint) { - // TODO: enable moving both control points -// if ([theEvent modifierFlags] & NSAlternateKeyMask) { -// if ([modifyEdge isSelfLoop]) { -// [modifyEdge setInAngle:[modifyEdge inAngle] + -// (bnd - [modifyEdge outAngle])]; -// } else { -// [modifyEdge setInAngle:[modifyEdge inAngle] - -// (bnd - [modifyEdge outAngle])]; -// } -// } - - e->setOutAngle(bnd); - } else { -// if (theEvent.modifierFlags & NSAlternateKeyMask) { -// if ([modifyEdge isSelfLoop]) { -// [modifyEdge setOutAngle:[modifyEdge outAngle] + -// (bnd - [modifyEdge inAngle])]; -// } else { -// [modifyEdge setOutAngle:[modifyEdge outAngle] - -// (bnd - [modifyEdge inAngle])]; -// } -// } - - e->setInAngle(bnd); - } - } - - _modifyEdgeItem->readPos(); - - } else if (_draggingNodes) { // nodes being dragged - QGraphicsScene::mouseMoveEvent(event); - - // apply the same offset to all nodes, otherwise we get odd rounding behaviour with - // multiple selection. - QPointF shift = mousePos - _mouseDownPos; - shift = QPointF(round(shift.x()/GRID_SEP)*GRID_SEP, round(shift.y()/GRID_SEP)*GRID_SEP); - - foreach (Node *n, _oldNodePositions.keys()) { - NodeItem *ni = _nodeItems[n]; - - // in (rare) cases, the graph can change while we are dragging - if (ni != 0) { - ni->setPos(toScreen(_oldNodePositions[n]) + shift); - ni->writePos(); - } - } - - refreshAdjacentEdges(_oldNodePositions.keys()); - } else { - // otherwise, process mouse move normally - QGraphicsScene::mouseMoveEvent(event); - - if (_rubberBandItem->isVisible()) { - qreal left = std::min(_mouseDownPos.x(), mousePos.x()); - qreal top = std::min(_mouseDownPos.y(), mousePos.y()); - qreal w = std::abs(_mouseDownPos.x() - mousePos.x()); - qreal h = std::abs(_mouseDownPos.y() - mousePos.y()); - - _rubberBandItem->setRect(QRectF(left, top, w, h)); - } - } - - break; - case ToolPalette::VERTEX: - break; - case ToolPalette::EDGE: - if (_drawEdgeItem->isVisible()) { - _edgeEndNodeItem = 0; - foreach (QGraphicsItem *gi, items(mousePos)) { - if (NodeItem *ni = dynamic_cast(gi)){ - _edgeEndNodeItem = ni; - break; - } - } - QPointF p1 = _drawEdgeItem->line().p1(); - QPointF p2 = (_edgeEndNodeItem != 0) ? toScreen(_edgeEndNodeItem->node()->point()) : mousePos; - QLineF line(p1, p2); - - _drawEdgeItem->setLine(line); - } - break; - case ToolPalette::CROP: - break; - } -} - -void TikzScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) -{ - if (!_enabled) return; - - // current mouse position, in scene coordinates - QPointF mousePos = event->scenePos(); - - switch (_tools->currentTool()) { - case ToolPalette::SELECT: - if (_modifyEdgeItem != 0) { - // finished dragging a control point - Edge *e = _modifyEdgeItem->edge(); - - if (_oldWeight != e->weight() || - _oldBend != e->bend() || - _oldInAngle != e->inAngle() || - _oldOutAngle != e->outAngle()) - { - EdgeBendCommand *cmd = new EdgeBendCommand(this, e, _oldWeight, _oldBend, _oldInAngle, _oldOutAngle); - _tikzDocument->undoStack()->push(cmd); - } - - _modifyEdgeItem = 0; - } else { - // otherwise, process mouse move normally - QGraphicsScene::mouseReleaseEvent(event); - - if (_rubberBandItem->isVisible()) { - QPainterPath sel; - sel.addRect(_rubberBandItem->rect()); - foreach (QGraphicsItem *gi, items()) { - if (NodeItem *ni = dynamic_cast(gi)) { - if (sel.contains(toScreen(ni->node()->point()))) ni->setSelected(true); - } - } - //setSelectionArea(sel); - } - - _rubberBandItem->setVisible(false); - - if (!_oldNodePositions.empty()) { - QPointF shift = mousePos - _mouseDownPos; - shift = QPointF(round(shift.x()/GRID_SEP)*GRID_SEP, round(shift.y()/GRID_SEP)*GRID_SEP); - - if (shift.x() != 0 || shift.y() != 0) { - QMap newNodePositions; - - foreach (QGraphicsItem *gi, selectedItems()) { - if (NodeItem *ni = dynamic_cast(gi)) { - ni->writePos(); - newNodePositions.insert(ni->node(), ni->node()->point()); - } - } - - //qDebug() << _oldNodePositions; - //qDebug() << newNodePositions; - - _tikzDocument->undoStack()->push(new MoveCommand(this, _oldNodePositions, newNodePositions)); - } - - _oldNodePositions.clear(); - } - } - - break; - case ToolPalette::VERTEX: - { - QPointF gridPos(round(mousePos.x()/GRID_SEP)*GRID_SEP, round(mousePos.y()/GRID_SEP)*GRID_SEP); - Node *n = new Node(_tikzDocument); - n->setName(graph()->freshNodeName()); - n->setPoint(fromScreen(gridPos)); - n->setStyleName(_styles->activeNodeStyleName()); - - QRectF grow(gridPos.x() - GLOBAL_SCALEF, gridPos.y() - GLOBAL_SCALEF, 2 * GLOBAL_SCALEF, 2 * GLOBAL_SCALEF); - QRectF newBounds = sceneRect().united(grow); - //qDebug() << grow; - //qDebug() << newBounds; - - AddNodeCommand *cmd = new AddNodeCommand(this, n, newBounds); - _tikzDocument->undoStack()->push(cmd); - } - break; - case ToolPalette::EDGE: - if (_edgeStartNodeItem != 0 && _edgeEndNodeItem != 0) { - Edge *e = new Edge(_edgeStartNodeItem->node(), _edgeEndNodeItem->node(), _tikzDocument); - e->setStyleName(_styles->activeEdgeStyleName()); - AddEdgeCommand *cmd = new AddEdgeCommand(this, e); - _tikzDocument->undoStack()->push(cmd); - } - _edgeStartNodeItem = 0; - _edgeEndNodeItem = 0; - _drawEdgeItem->setVisible(false); - break; - case ToolPalette::CROP: - break; - } - - // clear artefacts from rubber band selection - invalidate(QRect(), QGraphicsScene::BackgroundLayer); -} - - - -void TikzScene::keyReleaseEvent(QKeyEvent *event) -{ - if (!_enabled) return; - - if (event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete) { - deleteSelectedItems(); - } else if (event->modifiers() == Qt::NoModifier) { - switch(event->key()) { - case Qt::Key_S: - tikzit->activeWindow()->toolPalette()->setCurrentTool(ToolPalette::SELECT); - break; - case Qt::Key_V: - case Qt::Key_N: - tikzit->activeWindow()->toolPalette()->setCurrentTool(ToolPalette::VERTEX); - break; - case Qt::Key_E: - tikzit->activeWindow()->toolPalette()->setCurrentTool(ToolPalette::EDGE); - break; - case Qt::Key_B: - tikzit->activeWindow()->toolPalette()->setCurrentTool(ToolPalette::CROP); - break; - } - } -} - -void TikzScene::keyPressEvent(QKeyEvent *event) -{ - bool capture = false; - - if (event->key() == Qt::Key_QuoteLeft) { - capture = true; - _styles->nextNodeStyle(); - } - - if (event->modifiers() & Qt::ControlModifier) { - QPointF delta(0,0); - float shift = (event->modifiers() & Qt::ShiftModifier) ? 1.0f : 10.0f; - switch(event->key()) { - case Qt::Key_Left: - delta.setX(-0.025f * shift); - break; - case Qt::Key_Right: - delta.setX(0.025f * shift); - break; - case Qt::Key_Up: - delta.setY(0.025f * shift); - break; - case Qt::Key_Down: - delta.setY(-0.025f * shift); - break; - } - - if (!delta.isNull()) { - capture = true; - QMap oldNodePositions; - QMap newNodePositions; - QPointF pos; - - foreach (QGraphicsItem *gi, selectedItems()) { - if (NodeItem *ni = dynamic_cast(gi)) { - pos = ni->node()->point(); - oldNodePositions.insert(ni->node(), pos); - newNodePositions.insert(ni->node(), pos + delta); - } - } - - MoveCommand *cmd = new MoveCommand(this, oldNodePositions, newNodePositions); - _tikzDocument->undoStack()->push(cmd); - } - } - - if (!capture) QGraphicsScene::keyPressEvent(event); -} - -void TikzScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) -{ - if (!_enabled) return; - - QPointF mousePos = event->scenePos(); - - foreach (QGraphicsItem *it, items(mousePos)) { - if (EdgeItem *ei = dynamic_cast(it)) { - ChangeEdgeModeCommand *cmd = new ChangeEdgeModeCommand(this, ei->edge()); - _tikzDocument->undoStack()->push(cmd); - break; - } else if (NodeItem *ni = dynamic_cast(it)) { - bool ok; - QString newLabel = QInputDialog::getText(views()[0], tr("Node label"), - tr("Label:"), QLineEdit::Normal, - ni->node()->label(), &ok); - if (ok && !newLabel.isEmpty()) { - QMap oldLabels; - oldLabels.insert(ni->node(), ni->node()->label()); - ChangeLabelCommand *cmd = new ChangeLabelCommand(this, graph(), oldLabels, newLabel); - _tikzDocument->undoStack()->push(cmd); - } - break; - } - } -} - -bool TikzScene::enabled() const -{ - return _enabled; -} - -void TikzScene::setEnabled(bool enabled) -{ - _enabled = enabled; - update(); -} - -int TikzScene::lineNumberForSelection() -{ - foreach (QGraphicsItem *gi, selectedItems()) { - if (NodeItem *ni = dynamic_cast(gi)) return ni->node()->tikzLine(); - if (EdgeItem *ei = dynamic_cast(gi)) return ei->edge()->tikzLine(); - } - return 0; -} - - -void TikzScene::applyActiveStyleToNodes() { - ApplyStyleToNodesCommand *cmd = new ApplyStyleToNodesCommand(this, _styles->activeNodeStyleName()); - _tikzDocument->undoStack()->push(cmd); -} - -void TikzScene::deleteSelectedItems() -{ - QSet selNodes; - QSet selEdges; - getSelection(selNodes, selEdges); - - QMap deleteNodes; - QMap deleteEdges; - - for (int i = 0; i < _tikzDocument->graph()->nodes().length(); ++i) { - Node *n = _tikzDocument->graph()->nodes()[i]; - if (selNodes.contains(n)) deleteNodes.insert(i, n); - } - - for (int i = 0; i < _tikzDocument->graph()->edges().length(); ++i) { - Edge *e = _tikzDocument->graph()->edges()[i]; - if (selEdges.contains(e) || - selNodes.contains(e->source()) || - selNodes.contains(e->target())) deleteEdges.insert(i, e); - } - - //qDebug() << "nodes:" << deleteNodes; - //qDebug() << "edges:" << deleteEdges; - DeleteCommand *cmd = new DeleteCommand(this, deleteNodes, deleteEdges, selEdges); - _tikzDocument->undoStack()->push(cmd); -} - -void TikzScene::copyToClipboard() -{ - Graph *g = graph()->copyOfSubgraphWithNodes(getSelectedNodes()); - QGuiApplication::clipboard()->setText(g->tikz()); - delete g; -} - -void TikzScene::cutToClipboard() -{ - copyToClipboard(); - deleteSelectedItems(); -} - - -void TikzScene::pasteFromClipboard() -{ - QString tikz = QGuiApplication::clipboard()->text(); - Graph *g = new Graph(); - TikzAssembler ass(g); - - // attempt to parse whatever's on the clipboard, if we get a - // non-empty tikz graph, insert it. - if (ass.parse(tikz) && !g->nodes().isEmpty()) { - // make sure names in the new subgraph are fresh - g->renameApart(graph()); - - QRectF srcRect = g->realBbox(); - QRectF tgtRect = graph()->realBbox(); - QPointF shift(tgtRect.right() - srcRect.left(), 0.0f); - - if (shift.x() > 0) { - foreach (Node *n, g->nodes()) { - n->setPoint(n->point() + shift); - } - } - - PasteCommand *cmd = new PasteCommand(this, g); - _tikzDocument->undoStack()->push(cmd); - } -} - -void TikzScene::selectAllNodes() -{ - foreach (NodeItem *ni, _nodeItems.values()) { - ni->setSelected(true); - } -} - -void TikzScene::deselectAll() -{ - selectedItems().clear(); -} - -void TikzScene::parseTikz(QString tikz) -{ - Graph *newGraph = new Graph(this); - TikzAssembler ass(newGraph); - if (ass.parse(tikz)) { - ReplaceGraphCommand *cmd = new ReplaceGraphCommand(this, graph(), newGraph); - tikzDocument()->undoStack()->push(cmd); - setEnabled(true); - } -} - -void TikzScene::getSelection(QSet &selNodes, QSet &selEdges) -{ - foreach (QGraphicsItem *gi, selectedItems()) { - if (NodeItem *ni = dynamic_cast(gi)) selNodes << ni->node(); - if (EdgeItem *ei = dynamic_cast(gi)) selEdges << ei->edge(); - } -} - -QSet TikzScene::getSelectedNodes() -{ - QSet selNodes; - foreach (QGraphicsItem *gi, selectedItems()) { - if (NodeItem *ni = dynamic_cast(gi)) selNodes << ni->node(); - } - return selNodes; -} - - -TikzDocument *TikzScene::tikzDocument() const -{ - return _tikzDocument; -} - -void TikzScene::setTikzDocument(TikzDocument *tikzDocument) -{ - _tikzDocument = tikzDocument; - graphReplaced(); -} - -void TikzScene::reloadStyles() -{ - _styles->reloadStyles(); - foreach(EdgeItem *ei, _edgeItems) { - ei->edge()->attachStyle(); - ei->readPos(); // trigger a repaint - } - - foreach (NodeItem *ni, _nodeItems) { - ni->node()->attachStyle(); - ni->readPos(); // trigger a repaint - } -} - -// void TikzScene::refreshSceneBounds() -// { -// // if (!views().empty()) { -// // QGraphicsView *v = views().first(); -// // QRectF viewB = v->mapToScene(v->viewport()->rect()).boundingRect(); -// // //QPointF tl = v->mapToScene(viewB.topLeft()); -// // //viewB.setTopLeft(tl); -// -// // QRectF bounds = viewB.united(rectToScreen(graph()->realBbox().adjusted(-1.0f, -1.0f, 1.0f, 1.0f))); -// // //qDebug() << viewB; -// -// // if (bounds != sceneRect()) { -// // QPointF c = viewB.center(); -// // setSceneRect(bounds); -// // v->centerOn(c); -// // } -// // } -// //setBounds(graphB); -// } - -void TikzScene::refreshAdjacentEdges(QList nodes) -{ - if (nodes.empty()) return; - foreach (Edge *e, _edgeItems.keys()) { - EdgeItem *ei = _edgeItems[e]; - - // the list "nodes" can be out of date, e.g. if the graph changes while dragging - if (ei != 0) { - if (nodes.contains(ei->edge()->source()) || nodes.contains(ei->edge()->target())) { - ei->edge()->updateControls(); - ei->readPos(); - } - } - } -} - -//void TikzScene::setBounds(QRectF bounds) -//{ -// if (bounds != sceneRect()) { -// if (!views().empty()) { -// QGraphicsView *v = views().first(); -// QPointF c = v->mapToScene(v->viewport()->rect().center()); -// setSceneRect(bounds); -// v->centerOn(c); -// } else { -// setSceneRect(bounds); -// } -// } -//} - -QMap &TikzScene::nodeItems() -{ - return _nodeItems; -} - -QMap &TikzScene::edgeItems() -{ - return _edgeItems; -} +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program 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. + + This program 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 this program. If not, see . +*/ + +#include "tikzit.h" +#include "util.h" +#include "tikzscene.h" +#include "undocommands.h" +#include "tikzassembler.h" + +#include +#include +#include +#include +#include +#include + + +TikzScene::TikzScene(TikzDocument *tikzDocument, ToolPalette *tools, + StylePalette *styles, QObject *parent) : + QGraphicsScene(parent), _tikzDocument(tikzDocument), _tools(tools), _styles(styles) +{ + _modifyEdgeItem = 0; + _edgeStartNodeItem = 0; + _drawEdgeItem = new QGraphicsLineItem(); + _rubberBandItem = new QGraphicsRectItem(); + _enabled = true; + //setSceneRect(-310,-230,620,450); + setSceneRect(-1000,-1000,2000,2000); + + QPen pen; + pen.setColor(QColor::fromRgbF(0.5f, 0.0f, 0.5f)); + //pen.setWidth(3.0f); + pen.setCosmetic(true); + _drawEdgeItem->setPen(pen); + _drawEdgeItem->setLine(0,0,0,0); + _drawEdgeItem->setVisible(false); + addItem(_drawEdgeItem); + + pen.setColor(QColor::fromRgbF(0.6f, 0.6f, 0.8f)); + //pen.setWidth(3.0f); + //QVector dash; + //dash << 4.0 << 4.0; + pen.setStyle(Qt::DashLine); + //pen.setDashPattern(dash); + _rubberBandItem->setPen(pen); + + QBrush brush(QColor::fromRgbF(0.6,0.6,0.8,0.2)); + _rubberBandItem->setBrush(brush); + + _rubberBandItem->setVisible(false); + addItem(_rubberBandItem); +} + +TikzScene::~TikzScene() { +} + +Graph *TikzScene::graph() +{ + return _tikzDocument->graph(); +} + +void TikzScene::graphReplaced() +{ + + foreach (NodeItem *ni, _nodeItems) { + removeItem(ni); + delete ni; + } + _nodeItems.clear(); + + foreach (EdgeItem *ei, _edgeItems) { + removeItem(ei); + delete ei; + } + _edgeItems.clear(); + + foreach (Edge *e, graph()->edges()) { + e->attachStyle(); + EdgeItem *ei = new EdgeItem(e); + _edgeItems.insert(e, ei); + addItem(ei); + } + + foreach (Node *n, graph()->nodes()) { + n->attachStyle(); + NodeItem *ni = new NodeItem(n); + _nodeItems.insert(n, ni); + addItem(ni); + } +} + +void TikzScene::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + if (!_enabled) return; + + // current mouse position, in scene coordinates + _mouseDownPos = event->scenePos(); + + _draggingNodes = false; + + // disable rubber band drag, which will clear the selection. Only re-enable it + // for the SELECT tool, and when no control point has been clicked. + //views()[0]->setDragMode(QGraphicsView::NoDrag); + + // radius of a control point for bezier edges, in scene coordinates + qreal cpR = GLOBAL_SCALEF * (0.1); + qreal cpR2 = cpR * cpR; + + switch (_tools->currentTool()) { + case ToolPalette::SELECT: + // check if we grabbed a control point of an edge + foreach (QGraphicsItem *gi, selectedItems()) { + if (EdgeItem *ei = dynamic_cast(gi)) { + qreal dx, dy; + + dx = ei->cp1Item()->pos().x() - _mouseDownPos.x(); + dy = ei->cp1Item()->pos().y() - _mouseDownPos.y(); + + if (dx*dx + dy*dy <= cpR2) { + _modifyEdgeItem = ei; + _firstControlPoint = true; + break; + } + + dx = ei->cp2Item()->pos().x() - _mouseDownPos.x(); + dy = ei->cp2Item()->pos().y() - _mouseDownPos.y(); + + if (dx*dx + dy*dy <= cpR2) { + _modifyEdgeItem = ei; + _firstControlPoint = false; + break; + } + } + } + + if (_modifyEdgeItem != 0) { + // store for undo purposes + Edge *e = _modifyEdgeItem->edge(); + _oldBend = e->bend(); + _oldInAngle = e->inAngle(); + _oldOutAngle = e->outAngle(); + _oldWeight = e->weight(); + } else { + // since we are not dragging a control point, process the click normally + //views()[0]->setDragMode(QGraphicsView::RubberBandDrag); + QGraphicsScene::mousePressEvent(event); + + if (items(_mouseDownPos).isEmpty()) { + _rubberBandItem->setRect(QRectF(_mouseDownPos,_mouseDownPos)); + _rubberBandItem->setVisible(true); + qDebug() << "starting rubber band drag"; + } + +// foreach (QGraphicsItem *gi, items()) { +// if (EdgeItem *ei = dynamic_cast(gi)) { +// //qDebug() << "got an edge item: " << ei; +// ei->setFlag(QGraphicsItem::ItemIsSelectable, false); +// //ei->setSelected(true); +// } +// } + + // save current node positions for undo support + _oldNodePositions.clear(); + foreach (QGraphicsItem *gi, selectedItems()) { + if (NodeItem *ni = dynamic_cast(gi)) { + _oldNodePositions.insert(ni->node(), ni->node()->point()); + } + } + + auto its = items(_mouseDownPos); + if (!its.isEmpty() && dynamic_cast(its[0])) + _draggingNodes = true; + } + + break; + case ToolPalette::VERTEX: + break; + case ToolPalette::EDGE: + foreach (QGraphicsItem *gi, items(_mouseDownPos)) { + if (NodeItem *ni = dynamic_cast(gi)){ + _edgeStartNodeItem = ni; + _edgeEndNodeItem = ni; + QLineF line(toScreen(ni->node()->point()), _mouseDownPos); + _drawEdgeItem->setLine(line); + _drawEdgeItem->setVisible(true); + break; + } + } + break; + case ToolPalette::CROP: + break; + } +} + +void TikzScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + if (!_enabled) return; + + // current mouse position, in scene coordinates + QPointF mousePos = event->scenePos(); + //QRectF rb = views()[0]->rubberBandRect(); + //invalidate(-800,-800,1600,1600); + //invalidate(QRectF(), QGraphicsScene::BackgroundLayer); + + switch (_tools->currentTool()) { + case ToolPalette::SELECT: + if (_modifyEdgeItem != 0) { + Edge *e = _modifyEdgeItem->edge(); + + // dragging a control point + QPointF src = toScreen(e->source()->point()); + QPointF targ = toScreen(e->target()->point()); + float dx1 = targ.x() - src.x(); + float dy1 = targ.y() - src.y(); + float dx2, dy2; + if (_firstControlPoint) { + dx2 = mousePos.x() - src.x(); + dy2 = mousePos.y() - src.y(); + } else { + dx2 = mousePos.x() - targ.x(); + dy2 = mousePos.y() - targ.y(); + } + + float baseDist = sqrt(dx1*dx1 + dy1*dy1); + float handleDist = sqrt(dx2*dx2 + dy2*dy2); + float wcoarseness = 0.1f; + + if (!e->isSelfLoop()) { + if (baseDist != 0) { + e->setWeight(roundToNearest(wcoarseness, handleDist/baseDist)); + } else { + e->setWeight(roundToNearest(wcoarseness, handleDist/GLOBAL_SCALEF)); + } + } + + float control_angle = atan2(-dy2, dx2); + + int bcoarseness = 15; + + if(e->basicBendMode()) { + float bnd; + float base_angle = atan2(-dy1, dx1); + if (_firstControlPoint) { + bnd = base_angle - control_angle; + } else { + bnd = control_angle - base_angle + M_PI; + if (bnd > M_PI) bnd -= 2*M_PI; + } + + e->setBend(round(bnd * (180.0f / M_PI) * (1.0f / (float)bcoarseness)) * bcoarseness); + + } else { + int bnd = round(control_angle * (180.0f / M_PI) * + (1.0f / (float)bcoarseness)) * + bcoarseness; + if (_firstControlPoint) { + // TODO: enable moving both control points +// if ([theEvent modifierFlags] & NSAlternateKeyMask) { +// if ([modifyEdge isSelfLoop]) { +// [modifyEdge setInAngle:[modifyEdge inAngle] + +// (bnd - [modifyEdge outAngle])]; +// } else { +// [modifyEdge setInAngle:[modifyEdge inAngle] - +// (bnd - [modifyEdge outAngle])]; +// } +// } + + e->setOutAngle(bnd); + } else { +// if (theEvent.modifierFlags & NSAlternateKeyMask) { +// if ([modifyEdge isSelfLoop]) { +// [modifyEdge setOutAngle:[modifyEdge outAngle] + +// (bnd - [modifyEdge inAngle])]; +// } else { +// [modifyEdge setOutAngle:[modifyEdge outAngle] - +// (bnd - [modifyEdge inAngle])]; +// } +// } + + e->setInAngle(bnd); + } + } + + _modifyEdgeItem->readPos(); + + } else if (_draggingNodes) { // nodes being dragged + QGraphicsScene::mouseMoveEvent(event); + + // apply the same offset to all nodes, otherwise we get odd rounding behaviour with + // multiple selection. + QPointF shift = mousePos - _mouseDownPos; + shift = QPointF(round(shift.x()/GRID_SEP)*GRID_SEP, round(shift.y()/GRID_SEP)*GRID_SEP); + + foreach (Node *n, _oldNodePositions.keys()) { + NodeItem *ni = _nodeItems[n]; + + // in (rare) cases, the graph can change while we are dragging + if (ni != 0) { + ni->setPos(toScreen(_oldNodePositions[n]) + shift); + ni->writePos(); + } + } + + refreshAdjacentEdges(_oldNodePositions.keys()); + } else { + // otherwise, process mouse move normally + QGraphicsScene::mouseMoveEvent(event); + + if (_rubberBandItem->isVisible()) { + qreal left = std::min(_mouseDownPos.x(), mousePos.x()); + qreal top = std::min(_mouseDownPos.y(), mousePos.y()); + qreal w = std::abs(_mouseDownPos.x() - mousePos.x()); + qreal h = std::abs(_mouseDownPos.y() - mousePos.y()); + + _rubberBandItem->setRect(QRectF(left, top, w, h)); + } + } + + break; + case ToolPalette::VERTEX: + break; + case ToolPalette::EDGE: + if (_drawEdgeItem->isVisible()) { + _edgeEndNodeItem = 0; + foreach (QGraphicsItem *gi, items(mousePos)) { + if (NodeItem *ni = dynamic_cast(gi)){ + _edgeEndNodeItem = ni; + break; + } + } + QPointF p1 = _drawEdgeItem->line().p1(); + QPointF p2 = (_edgeEndNodeItem != 0) ? toScreen(_edgeEndNodeItem->node()->point()) : mousePos; + QLineF line(p1, p2); + + _drawEdgeItem->setLine(line); + } + break; + case ToolPalette::CROP: + break; + } +} + +void TikzScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + if (!_enabled) return; + + // current mouse position, in scene coordinates + QPointF mousePos = event->scenePos(); + + switch (_tools->currentTool()) { + case ToolPalette::SELECT: + if (_modifyEdgeItem != 0) { + // finished dragging a control point + Edge *e = _modifyEdgeItem->edge(); + + if (_oldWeight != e->weight() || + _oldBend != e->bend() || + _oldInAngle != e->inAngle() || + _oldOutAngle != e->outAngle()) + { + EdgeBendCommand *cmd = new EdgeBendCommand(this, e, _oldWeight, _oldBend, _oldInAngle, _oldOutAngle); + _tikzDocument->undoStack()->push(cmd); + } + + _modifyEdgeItem = 0; + } else { + // otherwise, process mouse move normally + QGraphicsScene::mouseReleaseEvent(event); + + if (_rubberBandItem->isVisible()) { + QPainterPath sel; + sel.addRect(_rubberBandItem->rect()); + foreach (QGraphicsItem *gi, items()) { + if (NodeItem *ni = dynamic_cast(gi)) { + if (sel.contains(toScreen(ni->node()->point()))) ni->setSelected(true); + } + } + //setSelectionArea(sel); + } + + _rubberBandItem->setVisible(false); + + if (!_oldNodePositions.empty()) { + QPointF shift = mousePos - _mouseDownPos; + shift = QPointF(round(shift.x()/GRID_SEP)*GRID_SEP, round(shift.y()/GRID_SEP)*GRID_SEP); + + if (shift.x() != 0 || shift.y() != 0) { + QMap newNodePositions; + + foreach (QGraphicsItem *gi, selectedItems()) { + if (NodeItem *ni = dynamic_cast(gi)) { + ni->writePos(); + newNodePositions.insert(ni->node(), ni->node()->point()); + } + } + + //qDebug() << _oldNodePositions; + //qDebug() << newNodePositions; + + _tikzDocument->undoStack()->push(new MoveCommand(this, _oldNodePositions, newNodePositions)); + } + + _oldNodePositions.clear(); + } + } + + break; + case ToolPalette::VERTEX: + { + QPointF gridPos(round(mousePos.x()/GRID_SEP)*GRID_SEP, round(mousePos.y()/GRID_SEP)*GRID_SEP); + Node *n = new Node(_tikzDocument); + n->setName(graph()->freshNodeName()); + n->setPoint(fromScreen(gridPos)); + n->setStyleName(_styles->activeNodeStyleName()); + + QRectF grow(gridPos.x() - GLOBAL_SCALEF, gridPos.y() - GLOBAL_SCALEF, 2 * GLOBAL_SCALEF, 2 * GLOBAL_SCALEF); + QRectF newBounds = sceneRect().united(grow); + //qDebug() << grow; + //qDebug() << newBounds; + + AddNodeCommand *cmd = new AddNodeCommand(this, n, newBounds); + _tikzDocument->undoStack()->push(cmd); + } + break; + case ToolPalette::EDGE: + if (_edgeStartNodeItem != 0 && _edgeEndNodeItem != 0) { + Edge *e = new Edge(_edgeStartNodeItem->node(), _edgeEndNodeItem->node(), _tikzDocument); + e->setStyleName(_styles->activeEdgeStyleName()); + AddEdgeCommand *cmd = new AddEdgeCommand(this, e); + _tikzDocument->undoStack()->push(cmd); + } + _edgeStartNodeItem = 0; + _edgeEndNodeItem = 0; + _drawEdgeItem->setVisible(false); + break; + case ToolPalette::CROP: + break; + } + + // clear artefacts from rubber band selection + invalidate(QRect(), QGraphicsScene::BackgroundLayer); +} + + + +void TikzScene::keyReleaseEvent(QKeyEvent *event) +{ + if (!_enabled) return; + + if (event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete) { + deleteSelectedItems(); + } else if (event->modifiers() == Qt::NoModifier) { + switch(event->key()) { + case Qt::Key_S: + tikzit->activeWindow()->toolPalette()->setCurrentTool(ToolPalette::SELECT); + break; + case Qt::Key_V: + case Qt::Key_N: + tikzit->activeWindow()->toolPalette()->setCurrentTool(ToolPalette::VERTEX); + break; + case Qt::Key_E: + tikzit->activeWindow()->toolPalette()->setCurrentTool(ToolPalette::EDGE); + break; + case Qt::Key_B: + tikzit->activeWindow()->toolPalette()->setCurrentTool(ToolPalette::CROP); + break; + } + } +} + +void TikzScene::keyPressEvent(QKeyEvent *event) +{ + bool capture = false; + + if (event->key() == Qt::Key_QuoteLeft) { + capture = true; + _styles->nextNodeStyle(); + } + + if (event->modifiers() & Qt::ControlModifier) { + QPointF delta(0,0); + float shift = (event->modifiers() & Qt::ShiftModifier) ? 1.0f : 10.0f; + switch(event->key()) { + case Qt::Key_Left: + delta.setX(-0.025f * shift); + break; + case Qt::Key_Right: + delta.setX(0.025f * shift); + break; + case Qt::Key_Up: + delta.setY(0.025f * shift); + break; + case Qt::Key_Down: + delta.setY(-0.025f * shift); + break; + } + + if (!delta.isNull()) { + capture = true; + QMap oldNodePositions; + QMap newNodePositions; + QPointF pos; + + foreach (QGraphicsItem *gi, selectedItems()) { + if (NodeItem *ni = dynamic_cast(gi)) { + pos = ni->node()->point(); + oldNodePositions.insert(ni->node(), pos); + newNodePositions.insert(ni->node(), pos + delta); + } + } + + MoveCommand *cmd = new MoveCommand(this, oldNodePositions, newNodePositions); + _tikzDocument->undoStack()->push(cmd); + } + } + + if (!capture) QGraphicsScene::keyPressEvent(event); +} + +void TikzScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) +{ + if (!_enabled) return; + + QPointF mousePos = event->scenePos(); + + foreach (QGraphicsItem *it, items(mousePos)) { + if (EdgeItem *ei = dynamic_cast(it)) { + ChangeEdgeModeCommand *cmd = new ChangeEdgeModeCommand(this, ei->edge()); + _tikzDocument->undoStack()->push(cmd); + break; + } else if (NodeItem *ni = dynamic_cast(it)) { + bool ok; + QString newLabel = QInputDialog::getText(views()[0], tr("Node label"), + tr("Label:"), QLineEdit::Normal, + ni->node()->label(), &ok); + if (ok && !newLabel.isEmpty()) { + QMap oldLabels; + oldLabels.insert(ni->node(), ni->node()->label()); + ChangeLabelCommand *cmd = new ChangeLabelCommand(this, graph(), oldLabels, newLabel); + _tikzDocument->undoStack()->push(cmd); + } + break; + } + } +} + +bool TikzScene::enabled() const +{ + return _enabled; +} + +void TikzScene::setEnabled(bool enabled) +{ + _enabled = enabled; + update(); +} + +int TikzScene::lineNumberForSelection() +{ + foreach (QGraphicsItem *gi, selectedItems()) { + if (NodeItem *ni = dynamic_cast(gi)) return ni->node()->tikzLine(); + if (EdgeItem *ei = dynamic_cast(gi)) return ei->edge()->tikzLine(); + } + return 0; +} + + +void TikzScene::applyActiveStyleToNodes() { + ApplyStyleToNodesCommand *cmd = new ApplyStyleToNodesCommand(this, _styles->activeNodeStyleName()); + _tikzDocument->undoStack()->push(cmd); +} + +void TikzScene::deleteSelectedItems() +{ + QSet selNodes; + QSet selEdges; + getSelection(selNodes, selEdges); + + QMap deleteNodes; + QMap deleteEdges; + + for (int i = 0; i < _tikzDocument->graph()->nodes().length(); ++i) { + Node *n = _tikzDocument->graph()->nodes()[i]; + if (selNodes.contains(n)) deleteNodes.insert(i, n); + } + + for (int i = 0; i < _tikzDocument->graph()->edges().length(); ++i) { + Edge *e = _tikzDocument->graph()->edges()[i]; + if (selEdges.contains(e) || + selNodes.contains(e->source()) || + selNodes.contains(e->target())) deleteEdges.insert(i, e); + } + + //qDebug() << "nodes:" << deleteNodes; + //qDebug() << "edges:" << deleteEdges; + DeleteCommand *cmd = new DeleteCommand(this, deleteNodes, deleteEdges, selEdges); + _tikzDocument->undoStack()->push(cmd); +} + +void TikzScene::copyToClipboard() +{ + Graph *g = graph()->copyOfSubgraphWithNodes(getSelectedNodes()); + QGuiApplication::clipboard()->setText(g->tikz()); + delete g; +} + +void TikzScene::cutToClipboard() +{ + copyToClipboard(); + deleteSelectedItems(); +} + + +void TikzScene::pasteFromClipboard() +{ + QString tikz = QGuiApplication::clipboard()->text(); + Graph *g = new Graph(); + TikzAssembler ass(g); + + // attempt to parse whatever's on the clipboard, if we get a + // non-empty tikz graph, insert it. + if (ass.parse(tikz) && !g->nodes().isEmpty()) { + // make sure names in the new subgraph are fresh + g->renameApart(graph()); + + QRectF srcRect = g->realBbox(); + QRectF tgtRect = graph()->realBbox(); + QPointF shift(tgtRect.right() - srcRect.left(), 0.0f); + + if (shift.x() > 0) { + foreach (Node *n, g->nodes()) { + n->setPoint(n->point() + shift); + } + } + + PasteCommand *cmd = new PasteCommand(this, g); + _tikzDocument->undoStack()->push(cmd); + } +} + +void TikzScene::selectAllNodes() +{ + foreach (NodeItem *ni, _nodeItems.values()) { + ni->setSelected(true); + } +} + +void TikzScene::deselectAll() +{ + selectedItems().clear(); +} + +void TikzScene::parseTikz(QString tikz) +{ + Graph *newGraph = new Graph(this); + TikzAssembler ass(newGraph); + if (ass.parse(tikz)) { + ReplaceGraphCommand *cmd = new ReplaceGraphCommand(this, graph(), newGraph); + tikzDocument()->undoStack()->push(cmd); + setEnabled(true); + } +} + +void TikzScene::getSelection(QSet &selNodes, QSet &selEdges) +{ + foreach (QGraphicsItem *gi, selectedItems()) { + if (NodeItem *ni = dynamic_cast(gi)) selNodes << ni->node(); + if (EdgeItem *ei = dynamic_cast(gi)) selEdges << ei->edge(); + } +} + +QSet TikzScene::getSelectedNodes() +{ + QSet selNodes; + foreach (QGraphicsItem *gi, selectedItems()) { + if (NodeItem *ni = dynamic_cast(gi)) selNodes << ni->node(); + } + return selNodes; +} + + +TikzDocument *TikzScene::tikzDocument() const +{ + return _tikzDocument; +} + +void TikzScene::setTikzDocument(TikzDocument *tikzDocument) +{ + _tikzDocument = tikzDocument; + graphReplaced(); +} + +void TikzScene::reloadStyles() +{ + _styles->reloadStyles(); + foreach(EdgeItem *ei, _edgeItems) { + ei->edge()->attachStyle(); + ei->readPos(); // trigger a repaint + } + + foreach (NodeItem *ni, _nodeItems) { + ni->node()->attachStyle(); + ni->readPos(); // trigger a repaint + } +} + +// void TikzScene::refreshSceneBounds() +// { +// // if (!views().empty()) { +// // QGraphicsView *v = views().first(); +// // QRectF viewB = v->mapToScene(v->viewport()->rect()).boundingRect(); +// // //QPointF tl = v->mapToScene(viewB.topLeft()); +// // //viewB.setTopLeft(tl); +// +// // QRectF bounds = viewB.united(rectToScreen(graph()->realBbox().adjusted(-1.0f, -1.0f, 1.0f, 1.0f))); +// // //qDebug() << viewB; +// +// // if (bounds != sceneRect()) { +// // QPointF c = viewB.center(); +// // setSceneRect(bounds); +// // v->centerOn(c); +// // } +// // } +// //setBounds(graphB); +// } + +void TikzScene::refreshAdjacentEdges(QList nodes) +{ + if (nodes.empty()) return; + foreach (Edge *e, _edgeItems.keys()) { + EdgeItem *ei = _edgeItems[e]; + + // the list "nodes" can be out of date, e.g. if the graph changes while dragging + if (ei != 0) { + if (nodes.contains(ei->edge()->source()) || nodes.contains(ei->edge()->target())) { + ei->edge()->updateControls(); + ei->readPos(); + } + } + } +} + +//void TikzScene::setBounds(QRectF bounds) +//{ +// if (bounds != sceneRect()) { +// if (!views().empty()) { +// QGraphicsView *v = views().first(); +// QPointF c = v->mapToScene(v->viewport()->rect().center()); +// setSceneRect(bounds); +// v->centerOn(c); +// } else { +// setSceneRect(bounds); +// } +// } +//} + +QMap &TikzScene::nodeItems() +{ + return _nodeItems; +} + +QMap &TikzScene::edgeItems() +{ + return _edgeItems; +} diff --git a/src/gui/tikzscene.h b/src/gui/tikzscene.h index 8aafe28..4ac56c7 100644 --- a/src/gui/tikzscene.h +++ b/src/gui/tikzscene.h @@ -1,107 +1,107 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - This program 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. - - This program 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 this program. If not, see . -*/ - -/*! - * Manage the scene, which contains a single Graph, and respond to user input. This serves as - * the controller for the MVC (TikzDocument, TikzView, TikzScene). - */ - -#ifndef TIKZSCENE_H -#define TIKZSCENE_H - -#include "graph.h" -#include "nodeitem.h" -#include "edgeitem.h" -#include "tikzdocument.h" -#include "toolpalette.h" -#include "stylepalette.h" - -#include -#include -#include -#include -#include -#include -#include - -class TikzScene : public QGraphicsScene -{ - Q_OBJECT -public: - TikzScene(TikzDocument *tikzDocument, ToolPalette *tools, StylePalette *styles, QObject *parent); - ~TikzScene(); - Graph *graph(); - QMap &nodeItems(); - QMap &edgeItems(); - void refreshAdjacentEdges(QList nodes); -// void setBounds(QRectF bounds); - - TikzDocument *tikzDocument() const; - void setTikzDocument(TikzDocument *tikzDocument); - void reloadStyles(); - //void refreshSceneBounds(); - void applyActiveStyleToNodes(); - void deleteSelectedItems(); - void copyToClipboard(); - void cutToClipboard(); - void pasteFromClipboard(); - void selectAllNodes(); - void deselectAll(); - void parseTikz(QString tikz); - bool enabled() const; - void setEnabled(bool enabled); - int lineNumberForSelection(); - - - void getSelection(QSet &selNodes, QSet &selEdges); - QSet getSelectedNodes(); - -public slots: - void graphReplaced(); - -protected: - void mousePressEvent(QGraphicsSceneMouseEvent *event) override; - void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; - void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; - void keyReleaseEvent(QKeyEvent *event) override; - void keyPressEvent(QKeyEvent *event) override; - void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override; -private: - TikzDocument *_tikzDocument; - ToolPalette *_tools; - StylePalette *_styles; - QMap _nodeItems; - QMap _edgeItems; - QGraphicsLineItem *_drawEdgeItem; - QGraphicsRectItem *_rubberBandItem; - EdgeItem *_modifyEdgeItem; - NodeItem *_edgeStartNodeItem; - NodeItem *_edgeEndNodeItem; - bool _firstControlPoint; - QPointF _mouseDownPos; - bool _draggingNodes; - - QMap _oldNodePositions; - float _oldWeight; - int _oldBend; - int _oldInAngle; - int _oldOutAngle; - bool _enabled; -}; - -#endif // TIKZSCENE_H +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program 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. + + This program 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 this program. If not, see . +*/ + +/*! + * Manage the scene, which contains a single Graph, and respond to user input. This serves as + * the controller for the MVC (TikzDocument, TikzView, TikzScene). + */ + +#ifndef TIKZSCENE_H +#define TIKZSCENE_H + +#include "graph.h" +#include "nodeitem.h" +#include "edgeitem.h" +#include "tikzdocument.h" +#include "toolpalette.h" +#include "stylepalette.h" + +#include +#include +#include +#include +#include +#include +#include + +class TikzScene : public QGraphicsScene +{ + Q_OBJECT +public: + TikzScene(TikzDocument *tikzDocument, ToolPalette *tools, StylePalette *styles, QObject *parent); + ~TikzScene(); + Graph *graph(); + QMap &nodeItems(); + QMap &edgeItems(); + void refreshAdjacentEdges(QList nodes); +// void setBounds(QRectF bounds); + + TikzDocument *tikzDocument() const; + void setTikzDocument(TikzDocument *tikzDocument); + void reloadStyles(); + //void refreshSceneBounds(); + void applyActiveStyleToNodes(); + void deleteSelectedItems(); + void copyToClipboard(); + void cutToClipboard(); + void pasteFromClipboard(); + void selectAllNodes(); + void deselectAll(); + void parseTikz(QString tikz); + bool enabled() const; + void setEnabled(bool enabled); + int lineNumberForSelection(); + + + void getSelection(QSet &selNodes, QSet &selEdges); + QSet getSelectedNodes(); + +public slots: + void graphReplaced(); + +protected: + void mousePressEvent(QGraphicsSceneMouseEvent *event) override; + void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; + void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; + void keyReleaseEvent(QKeyEvent *event) override; + void keyPressEvent(QKeyEvent *event) override; + void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override; +private: + TikzDocument *_tikzDocument; + ToolPalette *_tools; + StylePalette *_styles; + QMap _nodeItems; + QMap _edgeItems; + QGraphicsLineItem *_drawEdgeItem; + QGraphicsRectItem *_rubberBandItem; + EdgeItem *_modifyEdgeItem; + NodeItem *_edgeStartNodeItem; + NodeItem *_edgeEndNodeItem; + bool _firstControlPoint; + QPointF _mouseDownPos; + bool _draggingNodes; + + QMap _oldNodePositions; + float _oldWeight; + int _oldBend; + int _oldInAngle; + int _oldOutAngle; + bool _enabled; +}; + +#endif // TIKZSCENE_H diff --git a/src/gui/tikzview.cpp b/src/gui/tikzview.cpp index f0084fb..6cdb17c 100644 --- a/src/gui/tikzview.cpp +++ b/src/gui/tikzview.cpp @@ -1,128 +1,128 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - This program 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. - - This program 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 this program. If not, see . -*/ - -#include "tikzview.h" -#include "tikzit.h" - -#include -#include - -TikzView::TikzView(QWidget *parent) : QGraphicsView(parent) -{ - setRenderHint(QPainter::Antialiasing); - //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::setScene(QGraphicsScene *scene) -{ - QGraphicsView::setScene(scene); - centerOn(QPointF(0.0f,-230.0f)); -} - -void TikzView::drawBackground(QPainter *painter, const QRectF &rect) -{ - // draw a gray background if disabled - TikzScene *sc = static_cast(scene()); - if (!sc->enabled()) painter->fillRect(rect, QBrush(QColor(240,240,240))); - - // draw the grid - - QPen pen1; - //pen1.setWidthF(0.5); - pen1.setCosmetic(true); - pen1.setColor(QColor(250,250,255)); - - QPen pen2 = pen1; - pen2.setColor(QColor(240,240,250)); - - QPen pen3 = pen1; - pen3.setColor(QColor(220,220,240)); - - painter->setPen(pen1); - - if (_scale > 0.2f) { - for (int x = -GRID_SEP; x > rect.left(); x -= GRID_SEP) { - if (x % (GRID_SEP * GRID_N) != 0) { - qreal xf = (qreal)x; - painter->drawLine(xf, rect.top(), xf, rect.bottom()); - } - } - - for (int x = GRID_SEP; x < rect.right(); x += GRID_SEP) { - if (x % (GRID_SEP * GRID_N) != 0) { - qreal xf = (qreal)x; - painter->drawLine(xf, rect.top(), xf, rect.bottom()); - } - } - - for (int y = -GRID_SEP; y > rect.top(); y -= GRID_SEP) { - if (y % (GRID_SEP * GRID_N) != 0) { - qreal yf = (qreal)y; - painter->drawLine(rect.left(), yf, rect.right(), yf); - } - } - - for (int y = GRID_SEP; y < rect.bottom(); y += GRID_SEP) { - if (y % (GRID_SEP * GRID_N) != 0) { - qreal yf = (qreal)y; - painter->drawLine(rect.left(), yf, rect.right(), yf); - } - } - } - - painter->setPen(pen2); - - for (int x = -GRID_SEP*GRID_N; x > rect.left(); x -= GRID_SEP*GRID_N) { - qreal xf = (qreal)x; - painter->drawLine(xf, rect.top(), xf, rect.bottom()); - } - - for (int x = GRID_SEP*GRID_N; x < rect.right(); x += GRID_SEP*GRID_N) { - qreal xf = (qreal)x; - painter->drawLine(xf, rect.top(), xf, rect.bottom()); - } - - for (int y = -GRID_SEP*GRID_N; y > rect.top(); y -= GRID_SEP*GRID_N) { - qreal yf = (qreal)y; - painter->drawLine(rect.left(), yf, rect.right(), yf); - } - - for (int y = GRID_SEP*GRID_N; y < rect.bottom(); y += GRID_SEP*GRID_N) { - qreal yf = (qreal)y; - painter->drawLine(rect.left(), yf, rect.right(), yf); - } - - painter->setPen(pen3); - painter->drawLine(rect.left(), 0, rect.right(), 0); - painter->drawLine(0, rect.top(), 0, rect.bottom()); -} - +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program 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. + + This program 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 this program. If not, see . +*/ + +#include "tikzview.h" +#include "tikzit.h" + +#include +#include + +TikzView::TikzView(QWidget *parent) : QGraphicsView(parent) +{ + setRenderHint(QPainter::Antialiasing); + //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::setScene(QGraphicsScene *scene) +{ + QGraphicsView::setScene(scene); + centerOn(QPointF(0.0f,-230.0f)); +} + +void TikzView::drawBackground(QPainter *painter, const QRectF &rect) +{ + // draw a gray background if disabled + TikzScene *sc = static_cast(scene()); + if (!sc->enabled()) painter->fillRect(rect, QBrush(QColor(240,240,240))); + + // draw the grid + + QPen pen1; + //pen1.setWidthF(0.5); + pen1.setCosmetic(true); + pen1.setColor(QColor(250,250,255)); + + QPen pen2 = pen1; + pen2.setColor(QColor(240,240,250)); + + QPen pen3 = pen1; + pen3.setColor(QColor(220,220,240)); + + painter->setPen(pen1); + + if (_scale > 0.2f) { + for (int x = -GRID_SEP; x > rect.left(); x -= GRID_SEP) { + if (x % (GRID_SEP * GRID_N) != 0) { + qreal xf = (qreal)x; + painter->drawLine(xf, rect.top(), xf, rect.bottom()); + } + } + + for (int x = GRID_SEP; x < rect.right(); x += GRID_SEP) { + if (x % (GRID_SEP * GRID_N) != 0) { + qreal xf = (qreal)x; + painter->drawLine(xf, rect.top(), xf, rect.bottom()); + } + } + + for (int y = -GRID_SEP; y > rect.top(); y -= GRID_SEP) { + if (y % (GRID_SEP * GRID_N) != 0) { + qreal yf = (qreal)y; + painter->drawLine(rect.left(), yf, rect.right(), yf); + } + } + + for (int y = GRID_SEP; y < rect.bottom(); y += GRID_SEP) { + if (y % (GRID_SEP * GRID_N) != 0) { + qreal yf = (qreal)y; + painter->drawLine(rect.left(), yf, rect.right(), yf); + } + } + } + + painter->setPen(pen2); + + for (int x = -GRID_SEP*GRID_N; x > rect.left(); x -= GRID_SEP*GRID_N) { + qreal xf = (qreal)x; + painter->drawLine(xf, rect.top(), xf, rect.bottom()); + } + + for (int x = GRID_SEP*GRID_N; x < rect.right(); x += GRID_SEP*GRID_N) { + qreal xf = (qreal)x; + painter->drawLine(xf, rect.top(), xf, rect.bottom()); + } + + for (int y = -GRID_SEP*GRID_N; y > rect.top(); y -= GRID_SEP*GRID_N) { + qreal yf = (qreal)y; + painter->drawLine(rect.left(), yf, rect.right(), yf); + } + + for (int y = GRID_SEP*GRID_N; y < rect.bottom(); y += GRID_SEP*GRID_N) { + qreal yf = (qreal)y; + painter->drawLine(rect.left(), yf, rect.right(), yf); + } + + painter->setPen(pen3); + painter->drawLine(rect.left(), 0, rect.right(), 0); + painter->drawLine(0, rect.top(), 0, rect.bottom()); +} + diff --git a/src/gui/tikzview.h b/src/gui/tikzview.h index bfa7ace..4ec9f3d 100644 --- a/src/gui/tikzview.h +++ b/src/gui/tikzview.h @@ -1,52 +1,52 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - This program 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. - - This program 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 this program. If not, see . -*/ - -/*! - * Display a Graph, and manage any user input that purely changes the view (e.g. Zoom). This - * serves as the view in the MVC (TikzDocument, TikzView, TikzScene). - */ - -#ifndef TIKZVIEW_H -#define TIKZVIEW_H - -#include -#include -#include -#include -#include -#include -#include -#include - -class TikzView : public QGraphicsView -{ - Q_OBJECT -public: - explicit TikzView(QWidget *parent = 0); - -public slots: - void zoomIn(); - void zoomOut(); - void setScene(QGraphicsScene *scene); -protected: - void drawBackground(QPainter *painter, const QRectF &rect); -private: - float _scale; -}; - -#endif // TIKZVIEW_H +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program 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. + + This program 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 this program. If not, see . +*/ + +/*! + * Display a Graph, and manage any user input that purely changes the view (e.g. Zoom). This + * serves as the view in the MVC (TikzDocument, TikzView, TikzScene). + */ + +#ifndef TIKZVIEW_H +#define TIKZVIEW_H + +#include +#include +#include +#include +#include +#include +#include +#include + +class TikzView : public QGraphicsView +{ + Q_OBJECT +public: + explicit TikzView(QWidget *parent = 0); + +public slots: + void zoomIn(); + void zoomOut(); + void setScene(QGraphicsScene *scene); +protected: + void drawBackground(QPainter *painter, const QRectF &rect); +private: + float _scale; +}; + +#endif // TIKZVIEW_H diff --git a/src/gui/toolpalette.cpp b/src/gui/toolpalette.cpp index 2931f82..43a4a49 100644 --- a/src/gui/toolpalette.cpp +++ b/src/gui/toolpalette.cpp @@ -1,86 +1,86 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - This program 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. - - This program 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 this program. If not, see . -*/ - -#include "toolpalette.h" - -#include -#include -#include -#include - -ToolPalette::ToolPalette(QWidget *parent) : - QToolBar(parent) -{ - setWindowFlags(Qt::Window - | Qt::CustomizeWindowHint - | Qt::WindowDoesNotAcceptFocus); - setOrientation(Qt::Vertical); - setFocusPolicy(Qt::NoFocus); - //setGeometry(100,200,30,195); - - tools = new QActionGroup(this); - - select = new QAction(QIcon(":/images/Inkscape_icons_edit_select_all.svg"), "Select"); - vertex = new QAction(QIcon(":/images/Inkscape_icons_draw_ellipse.svg"), "Add Vertex"); - edge = new QAction(QIcon(":/images/Inkscape_icons_draw_path.svg"), "Add Edge"); - crop = new QAction(QIcon(":/images/crop.svg"), "Bounding Box"); - - tools->addAction(select); - tools->addAction(vertex); - tools->addAction(edge); - tools->addAction(crop); - - select->setCheckable(true); - vertex->setCheckable(true); - edge->setCheckable(true); - crop->setCheckable(true); - select->setChecked(true); - - addAction(select); - addAction(vertex); - addAction(edge); - addAction(crop); -} - -ToolPalette::Tool ToolPalette::currentTool() const -{ - QAction *a = tools->checkedAction(); - if (a == vertex) return VERTEX; - else if (a == edge) return EDGE; - else if (a == crop) return CROP; - else return SELECT; -} - -void ToolPalette::setCurrentTool(ToolPalette::Tool tool) -{ - switch(tool) { - case SELECT: - select->setChecked(true); - break; - case VERTEX: - vertex->setChecked(true); - break; - case EDGE: - edge->setChecked(true); - break; - case CROP: - crop->setChecked(true); - break; - } -} - +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program 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. + + This program 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 this program. If not, see . +*/ + +#include "toolpalette.h" + +#include +#include +#include +#include + +ToolPalette::ToolPalette(QWidget *parent) : + QToolBar(parent) +{ + setWindowFlags(Qt::Window + | Qt::CustomizeWindowHint + | Qt::WindowDoesNotAcceptFocus); + setOrientation(Qt::Vertical); + setFocusPolicy(Qt::NoFocus); + //setGeometry(100,200,30,195); + + tools = new QActionGroup(this); + + select = new QAction(QIcon(":/images/Inkscape_icons_edit_select_all.svg"), "Select"); + vertex = new QAction(QIcon(":/images/Inkscape_icons_draw_ellipse.svg"), "Add Vertex"); + edge = new QAction(QIcon(":/images/Inkscape_icons_draw_path.svg"), "Add Edge"); + crop = new QAction(QIcon(":/images/crop.svg"), "Bounding Box"); + + tools->addAction(select); + tools->addAction(vertex); + tools->addAction(edge); + tools->addAction(crop); + + select->setCheckable(true); + vertex->setCheckable(true); + edge->setCheckable(true); + crop->setCheckable(true); + select->setChecked(true); + + addAction(select); + addAction(vertex); + addAction(edge); + addAction(crop); +} + +ToolPalette::Tool ToolPalette::currentTool() const +{ + QAction *a = tools->checkedAction(); + if (a == vertex) return VERTEX; + else if (a == edge) return EDGE; + else if (a == crop) return CROP; + else return SELECT; +} + +void ToolPalette::setCurrentTool(ToolPalette::Tool tool) +{ + switch(tool) { + case SELECT: + select->setChecked(true); + break; + case VERTEX: + vertex->setChecked(true); + break; + case EDGE: + edge->setChecked(true); + break; + case CROP: + crop->setChecked(true); + break; + } +} + diff --git a/src/gui/toolpalette.h b/src/gui/toolpalette.h index d095d93..a001055 100644 --- a/src/gui/toolpalette.h +++ b/src/gui/toolpalette.h @@ -1,53 +1,53 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - This program 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. - - This program 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 this program. If not, see . -*/ - -/*! - * A small window that lets the user select the current editing tool. - */ - -#ifndef TOOLPALETTE_H -#define TOOLPALETTE_H - -#include -#include -#include -#include - -class ToolPalette : public QToolBar -{ - Q_OBJECT -public: - ToolPalette(QWidget *parent = 0); - enum Tool { - SELECT, - VERTEX, - EDGE, - CROP - }; - - Tool currentTool() const; - void setCurrentTool(Tool tool); -private: - QActionGroup *tools; - QAction *select; - QAction *vertex; - QAction *edge; - QAction *crop; -}; - -#endif // TOOLPALETTE_H +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program 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. + + This program 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 this program. If not, see . +*/ + +/*! + * A small window that lets the user select the current editing tool. + */ + +#ifndef TOOLPALETTE_H +#define TOOLPALETTE_H + +#include +#include +#include +#include + +class ToolPalette : public QToolBar +{ + Q_OBJECT +public: + ToolPalette(QWidget *parent = 0); + enum Tool { + SELECT, + VERTEX, + EDGE, + CROP + }; + + Tool currentTool() const; + void setCurrentTool(Tool tool); +private: + QActionGroup *tools; + QAction *select; + QAction *vertex; + QAction *edge; + QAction *crop; +}; + +#endif // TOOLPALETTE_H diff --git a/src/gui/undocommands.cpp b/src/gui/undocommands.cpp index dc7a797..5525cb7 100644 --- a/src/gui/undocommands.cpp +++ b/src/gui/undocommands.cpp @@ -1,428 +1,428 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - This program 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. - - This program 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 this program. If not, see . -*/ - -#include "undocommands.h" -#include "nodeitem.h" -#include "edgeitem.h" - -#include - -GraphUpdateCommand::GraphUpdateCommand(TikzScene *scene, QUndoCommand *parent) : QUndoCommand(parent), _scene(scene) -{ -} - -void GraphUpdateCommand::undo() -{ - _scene->tikzDocument()->refreshTikz(); - //refreshSceneBounds does nothing - //_scene->refreshSceneBounds(); - _scene->invalidate(); -} - -void GraphUpdateCommand::redo() -{ - _scene->tikzDocument()->refreshTikz(); - //refreshSceneBounds does nothing - //_scene->refreshSceneBounds(); - _scene->invalidate(); -} - - -MoveCommand::MoveCommand(TikzScene *scene, - QMap oldNodePositions, - QMap newNodePositions, - QUndoCommand *parent) : - GraphUpdateCommand(scene, parent), - _oldNodePositions(oldNodePositions), - _newNodePositions(newNodePositions) -{} - - -void MoveCommand::undo() -{ - foreach (NodeItem *ni, _scene->nodeItems()) { - if (_oldNodePositions.contains(ni->node())) { - ni->node()->setPoint(_oldNodePositions.value(ni->node())); - ni->readPos(); - } - } - - _scene->refreshAdjacentEdges(_oldNodePositions.keys()); - GraphUpdateCommand::undo(); -} - -void MoveCommand::redo() -{ - foreach (NodeItem *ni, _scene->nodeItems()) { - if (_newNodePositions.contains(ni->node())) { - ni->node()->setPoint(_newNodePositions.value(ni->node())); - ni->readPos(); - } - } - - _scene->refreshAdjacentEdges(_newNodePositions.keys()); - GraphUpdateCommand::redo(); -} - -EdgeBendCommand::EdgeBendCommand(TikzScene *scene, Edge *edge, - float oldWeight, int oldBend, - int oldInAngle, int oldOutAngle, QUndoCommand *parent) : - GraphUpdateCommand(scene, parent), - _edge(edge), - _oldWeight(oldWeight), _oldBend(oldBend), - _oldInAngle(oldInAngle), _oldOutAngle(oldOutAngle) -{ - _newWeight = edge->weight(); - _newBend = edge->bend(); - _newInAngle = edge->inAngle(); - _newOutAngle = edge->outAngle(); -} - -void EdgeBendCommand::undo() -{ - _edge->setWeight(_oldWeight); - _edge->setBend(_oldBend); - _edge->setInAngle(_oldInAngle); - _edge->setOutAngle(_oldOutAngle); - - foreach(EdgeItem *ei, _scene->edgeItems()) { - if (ei->edge() == _edge) { - ei->readPos(); - break; - } - } - GraphUpdateCommand::undo(); -} - -void EdgeBendCommand::redo() -{ - _edge->setWeight(_newWeight); - _edge->setBend(_newBend); - _edge->setInAngle(_newInAngle); - _edge->setOutAngle(_newOutAngle); - - foreach(EdgeItem *ei, _scene->edgeItems()) { - if (ei->edge() == _edge) { - ei->readPos(); - break; - } - } - - GraphUpdateCommand::redo(); -} - -DeleteCommand::DeleteCommand(TikzScene *scene, - QMap deleteNodes, - QMap deleteEdges, - QSet selEdges, QUndoCommand *parent) : - GraphUpdateCommand(scene, parent), - _deleteNodes(deleteNodes), _deleteEdges(deleteEdges), _selEdges(selEdges) -{} - -void DeleteCommand::undo() -{ - for (auto it = _deleteNodes.begin(); it != _deleteNodes.end(); ++it) { - Node *n = it.value(); - n->attachStyle(); // in case styles have changed - _scene->graph()->addNode(n, it.key()); - NodeItem *ni = new NodeItem(n); - _scene->nodeItems().insert(n, ni); - _scene->addItem(ni); - ni->setSelected(true); - } - - for (auto it = _deleteEdges.begin(); it != _deleteEdges.end(); ++it) { - Edge *e = it.value(); - e->attachStyle(); - _scene->graph()->addEdge(e, it.key()); - EdgeItem *ei = new EdgeItem(e); - _scene->edgeItems().insert(e, ei); - _scene->addItem(ei); - - if (_selEdges.contains(e)) ei->setSelected(true); - } - - GraphUpdateCommand::undo(); -} - -void DeleteCommand::redo() -{ - foreach (Edge *e, _deleteEdges.values()) { - EdgeItem *ei = _scene->edgeItems()[e]; - _scene->edgeItems().remove(e); - _scene->removeItem(ei); - delete ei; - - _scene->graph()->removeEdge(e); - } - - foreach (Node *n, _deleteNodes.values()) { - NodeItem *ni = _scene->nodeItems()[n]; - _scene->nodeItems().remove(n); - _scene->removeItem(ni); - delete ni; - - _scene->graph()->removeNode(n); - } - - GraphUpdateCommand::redo(); -} - -AddNodeCommand::AddNodeCommand(TikzScene *scene, Node *node, QRectF newBounds, QUndoCommand *parent) : - GraphUpdateCommand(scene, parent), _node(node), _oldBounds(_scene->sceneRect()), _newBounds(newBounds) -{ -} - -void AddNodeCommand::undo() -{ - NodeItem *ni = _scene->nodeItems()[_node]; - _scene->removeItem(ni); - _scene->nodeItems().remove(_node); - delete ni; - - _scene->graph()->removeNode(_node); - - //_scene->setBounds(_oldBounds); - - GraphUpdateCommand::undo(); -} - -void AddNodeCommand::redo() -{ - _node->attachStyle(); // do for every redo, in case styles have changed - _scene->graph()->addNode(_node); - NodeItem *ni = new NodeItem(_node); - _scene->nodeItems().insert(_node, ni); - _scene->addItem(ni); - - //_scene->setBounds(_newBounds); - - GraphUpdateCommand::redo(); -} - -AddEdgeCommand::AddEdgeCommand(TikzScene *scene, Edge *edge, QUndoCommand *parent) : - GraphUpdateCommand(scene, parent), _edge(edge) -{ -} - -void AddEdgeCommand::undo() -{ - EdgeItem *ei = _scene->edgeItems()[_edge]; - _scene->removeItem(ei); - _scene->edgeItems().remove(_edge); - delete ei; - - _scene->graph()->removeEdge(_edge); - GraphUpdateCommand::undo(); -} - -void AddEdgeCommand::redo() -{ - _edge->attachStyle(); // do for every redo, in case styles have changed - _scene->graph()->addEdge(_edge); - EdgeItem *ei = new EdgeItem(_edge); - _scene->edgeItems().insert(_edge, ei); - _scene->addItem(ei); - - // TODO: deal consistently with stacking order - // edges should always be stacked below nodes - if (!_scene->graph()->nodes().isEmpty()) { - ei->stackBefore(_scene->nodeItems()[_scene->graph()->nodes().first()]); - } - - GraphUpdateCommand::redo(); -} - -ChangeEdgeModeCommand::ChangeEdgeModeCommand(TikzScene *scene, Edge *edge, QUndoCommand *parent) : - GraphUpdateCommand(scene, parent), _edge(edge) -{ -} - -void ChangeEdgeModeCommand::undo() -{ - // FIXME: this act strangely sometimes - _edge->setBasicBendMode(!_edge->basicBendMode()); - _scene->edgeItems()[_edge]->readPos(); - GraphUpdateCommand::undo(); -} - -void ChangeEdgeModeCommand::redo() -{ - _edge->setBasicBendMode(!_edge->basicBendMode()); - _scene->edgeItems()[_edge]->readPos(); - GraphUpdateCommand::redo(); -} - -ApplyStyleToNodesCommand::ApplyStyleToNodesCommand(TikzScene *scene, QString style, QUndoCommand *parent) : - GraphUpdateCommand(scene, parent), _style(style), _oldStyles() -{ - foreach (QGraphicsItem *it, scene->selectedItems()) { - if (NodeItem *ni = dynamic_cast(it)) { - _oldStyles.insert(ni->node(), ni->node()->styleName()); - } - } -} - -void ApplyStyleToNodesCommand::undo() -{ - foreach (Node *n, _oldStyles.keys()) { - n->setStyleName(_oldStyles[n]); - n->attachStyle(); - } - - GraphUpdateCommand::undo(); -} - -void ApplyStyleToNodesCommand::redo() -{ - foreach (Node *n, _oldStyles.keys()) { - n->setStyleName(_style); - n->attachStyle(); - } - GraphUpdateCommand::redo(); -} - -ApplyStyleToEdgesCommand::ApplyStyleToEdgesCommand(TikzScene *scene, QString style, QUndoCommand *parent) : - GraphUpdateCommand(scene, parent), _style(style), _oldStyles() -{ - foreach(QGraphicsItem *it, scene->selectedItems()) { - if (EdgeItem *ei = dynamic_cast(it)) { - _oldStyles.insert(ei->edge(), ei->edge()->styleName()); - } - } -} - -void ApplyStyleToEdgesCommand::undo() -{ - foreach(Edge *e, _oldStyles.keys()) { - e->setStyleName(_oldStyles[e]); - e->attachStyle(); - } - - GraphUpdateCommand::undo(); -} - -void ApplyStyleToEdgesCommand::redo() -{ - foreach(Edge *e, _oldStyles.keys()) { - e->setStyleName(_style); - e->attachStyle(); - } - GraphUpdateCommand::redo(); -} - -PasteCommand::PasteCommand(TikzScene *scene, Graph *graph, QUndoCommand *parent) : - GraphUpdateCommand(scene, parent), _graph(graph) -{ - scene->getSelection(_oldSelectedNodes, _oldSelectedEdges); -} - -void PasteCommand::undo() -{ - _scene->clearSelection(); - - foreach (Edge *e, _graph->edges()) { - EdgeItem *ei = _scene->edgeItems()[e]; - _scene->edgeItems().remove(e); - _scene->removeItem(ei); - delete ei; - - _scene->graph()->removeEdge(e); - } - - foreach (Node *n, _graph->nodes()) { - NodeItem *ni = _scene->nodeItems()[n]; - _scene->nodeItems().remove(n); - _scene->removeItem(ni); - delete ni; - - _scene->graph()->removeNode(n); - } - - foreach(Node *n, _oldSelectedNodes) _scene->nodeItems()[n]->setSelected(true); - foreach(Edge *e, _oldSelectedEdges) _scene->edgeItems()[e]->setSelected(true); - - GraphUpdateCommand::undo(); -} - -void PasteCommand::redo() -{ - _scene->clearSelection(); - _scene->graph()->insertGraph(_graph); - - foreach (Edge *e, _graph->edges()) { - e->attachStyle(); // in case styles have changed - EdgeItem *ei = new EdgeItem(e); - _scene->edgeItems().insert(e, ei); - _scene->addItem(ei); - } - - foreach (Node *n, _graph->nodes()) { - n->attachStyle(); // in case styles have changed - NodeItem *ni = new NodeItem(n); - _scene->nodeItems().insert(n, ni); - _scene->addItem(ni); - ni->setSelected(true); - } - - GraphUpdateCommand::redo(); -} - -ChangeLabelCommand::ChangeLabelCommand(TikzScene *scene, Graph *graph, QMap oldLabels, QString newLabel, QUndoCommand *parent) : - GraphUpdateCommand(scene, parent), _oldLabels(oldLabels), _newLabel(newLabel) -{ -} - -void ChangeLabelCommand::undo() -{ - foreach (Node *n, _oldLabels.keys()) { - n->setLabel(_oldLabels[n]); - NodeItem *ni = _scene->nodeItems()[n]; - if (ni != 0) ni->updateBounds(); - } - - GraphUpdateCommand::undo(); -} - -void ChangeLabelCommand::redo() -{ - foreach (Node *n, _oldLabels.keys()) { - n->setLabel(_newLabel); - NodeItem *ni = _scene->nodeItems()[n]; - if (ni != 0) ni->updateBounds(); - } - - GraphUpdateCommand::redo(); -} - -ReplaceGraphCommand::ReplaceGraphCommand(TikzScene *scene, Graph *oldGraph, Graph *newGraph, QUndoCommand *parent) : - GraphUpdateCommand(scene, parent), _oldGraph(oldGraph), _newGraph(newGraph) -{ -} - -void ReplaceGraphCommand::undo() -{ - _scene->tikzDocument()->setGraph(_oldGraph); - _scene->graphReplaced(); -} - -void ReplaceGraphCommand::redo() -{ - _scene->tikzDocument()->setGraph(_newGraph); - _scene->graphReplaced(); -} +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program 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. + + This program 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 this program. If not, see . +*/ + +#include "undocommands.h" +#include "nodeitem.h" +#include "edgeitem.h" + +#include + +GraphUpdateCommand::GraphUpdateCommand(TikzScene *scene, QUndoCommand *parent) : QUndoCommand(parent), _scene(scene) +{ +} + +void GraphUpdateCommand::undo() +{ + _scene->tikzDocument()->refreshTikz(); + //refreshSceneBounds does nothing + //_scene->refreshSceneBounds(); + _scene->invalidate(); +} + +void GraphUpdateCommand::redo() +{ + _scene->tikzDocument()->refreshTikz(); + //refreshSceneBounds does nothing + //_scene->refreshSceneBounds(); + _scene->invalidate(); +} + + +MoveCommand::MoveCommand(TikzScene *scene, + QMap oldNodePositions, + QMap newNodePositions, + QUndoCommand *parent) : + GraphUpdateCommand(scene, parent), + _oldNodePositions(oldNodePositions), + _newNodePositions(newNodePositions) +{} + + +void MoveCommand::undo() +{ + foreach (NodeItem *ni, _scene->nodeItems()) { + if (_oldNodePositions.contains(ni->node())) { + ni->node()->setPoint(_oldNodePositions.value(ni->node())); + ni->readPos(); + } + } + + _scene->refreshAdjacentEdges(_oldNodePositions.keys()); + GraphUpdateCommand::undo(); +} + +void MoveCommand::redo() +{ + foreach (NodeItem *ni, _scene->nodeItems()) { + if (_newNodePositions.contains(ni->node())) { + ni->node()->setPoint(_newNodePositions.value(ni->node())); + ni->readPos(); + } + } + + _scene->refreshAdjacentEdges(_newNodePositions.keys()); + GraphUpdateCommand::redo(); +} + +EdgeBendCommand::EdgeBendCommand(TikzScene *scene, Edge *edge, + float oldWeight, int oldBend, + int oldInAngle, int oldOutAngle, QUndoCommand *parent) : + GraphUpdateCommand(scene, parent), + _edge(edge), + _oldWeight(oldWeight), _oldBend(oldBend), + _oldInAngle(oldInAngle), _oldOutAngle(oldOutAngle) +{ + _newWeight = edge->weight(); + _newBend = edge->bend(); + _newInAngle = edge->inAngle(); + _newOutAngle = edge->outAngle(); +} + +void EdgeBendCommand::undo() +{ + _edge->setWeight(_oldWeight); + _edge->setBend(_oldBend); + _edge->setInAngle(_oldInAngle); + _edge->setOutAngle(_oldOutAngle); + + foreach(EdgeItem *ei, _scene->edgeItems()) { + if (ei->edge() == _edge) { + ei->readPos(); + break; + } + } + GraphUpdateCommand::undo(); +} + +void EdgeBendCommand::redo() +{ + _edge->setWeight(_newWeight); + _edge->setBend(_newBend); + _edge->setInAngle(_newInAngle); + _edge->setOutAngle(_newOutAngle); + + foreach(EdgeItem *ei, _scene->edgeItems()) { + if (ei->edge() == _edge) { + ei->readPos(); + break; + } + } + + GraphUpdateCommand::redo(); +} + +DeleteCommand::DeleteCommand(TikzScene *scene, + QMap deleteNodes, + QMap deleteEdges, + QSet selEdges, QUndoCommand *parent) : + GraphUpdateCommand(scene, parent), + _deleteNodes(deleteNodes), _deleteEdges(deleteEdges), _selEdges(selEdges) +{} + +void DeleteCommand::undo() +{ + for (auto it = _deleteNodes.begin(); it != _deleteNodes.end(); ++it) { + Node *n = it.value(); + n->attachStyle(); // in case styles have changed + _scene->graph()->addNode(n, it.key()); + NodeItem *ni = new NodeItem(n); + _scene->nodeItems().insert(n, ni); + _scene->addItem(ni); + ni->setSelected(true); + } + + for (auto it = _deleteEdges.begin(); it != _deleteEdges.end(); ++it) { + Edge *e = it.value(); + e->attachStyle(); + _scene->graph()->addEdge(e, it.key()); + EdgeItem *ei = new EdgeItem(e); + _scene->edgeItems().insert(e, ei); + _scene->addItem(ei); + + if (_selEdges.contains(e)) ei->setSelected(true); + } + + GraphUpdateCommand::undo(); +} + +void DeleteCommand::redo() +{ + foreach (Edge *e, _deleteEdges.values()) { + EdgeItem *ei = _scene->edgeItems()[e]; + _scene->edgeItems().remove(e); + _scene->removeItem(ei); + delete ei; + + _scene->graph()->removeEdge(e); + } + + foreach (Node *n, _deleteNodes.values()) { + NodeItem *ni = _scene->nodeItems()[n]; + _scene->nodeItems().remove(n); + _scene->removeItem(ni); + delete ni; + + _scene->graph()->removeNode(n); + } + + GraphUpdateCommand::redo(); +} + +AddNodeCommand::AddNodeCommand(TikzScene *scene, Node *node, QRectF newBounds, QUndoCommand *parent) : + GraphUpdateCommand(scene, parent), _node(node), _oldBounds(_scene->sceneRect()), _newBounds(newBounds) +{ +} + +void AddNodeCommand::undo() +{ + NodeItem *ni = _scene->nodeItems()[_node]; + _scene->removeItem(ni); + _scene->nodeItems().remove(_node); + delete ni; + + _scene->graph()->removeNode(_node); + + //_scene->setBounds(_oldBounds); + + GraphUpdateCommand::undo(); +} + +void AddNodeCommand::redo() +{ + _node->attachStyle(); // do for every redo, in case styles have changed + _scene->graph()->addNode(_node); + NodeItem *ni = new NodeItem(_node); + _scene->nodeItems().insert(_node, ni); + _scene->addItem(ni); + + //_scene->setBounds(_newBounds); + + GraphUpdateCommand::redo(); +} + +AddEdgeCommand::AddEdgeCommand(TikzScene *scene, Edge *edge, QUndoCommand *parent) : + GraphUpdateCommand(scene, parent), _edge(edge) +{ +} + +void AddEdgeCommand::undo() +{ + EdgeItem *ei = _scene->edgeItems()[_edge]; + _scene->removeItem(ei); + _scene->edgeItems().remove(_edge); + delete ei; + + _scene->graph()->removeEdge(_edge); + GraphUpdateCommand::undo(); +} + +void AddEdgeCommand::redo() +{ + _edge->attachStyle(); // do for every redo, in case styles have changed + _scene->graph()->addEdge(_edge); + EdgeItem *ei = new EdgeItem(_edge); + _scene->edgeItems().insert(_edge, ei); + _scene->addItem(ei); + + // TODO: deal consistently with stacking order + // edges should always be stacked below nodes + if (!_scene->graph()->nodes().isEmpty()) { + ei->stackBefore(_scene->nodeItems()[_scene->graph()->nodes().first()]); + } + + GraphUpdateCommand::redo(); +} + +ChangeEdgeModeCommand::ChangeEdgeModeCommand(TikzScene *scene, Edge *edge, QUndoCommand *parent) : + GraphUpdateCommand(scene, parent), _edge(edge) +{ +} + +void ChangeEdgeModeCommand::undo() +{ + // FIXME: this act strangely sometimes + _edge->setBasicBendMode(!_edge->basicBendMode()); + _scene->edgeItems()[_edge]->readPos(); + GraphUpdateCommand::undo(); +} + +void ChangeEdgeModeCommand::redo() +{ + _edge->setBasicBendMode(!_edge->basicBendMode()); + _scene->edgeItems()[_edge]->readPos(); + GraphUpdateCommand::redo(); +} + +ApplyStyleToNodesCommand::ApplyStyleToNodesCommand(TikzScene *scene, QString style, QUndoCommand *parent) : + GraphUpdateCommand(scene, parent), _style(style), _oldStyles() +{ + foreach (QGraphicsItem *it, scene->selectedItems()) { + if (NodeItem *ni = dynamic_cast(it)) { + _oldStyles.insert(ni->node(), ni->node()->styleName()); + } + } +} + +void ApplyStyleToNodesCommand::undo() +{ + foreach (Node *n, _oldStyles.keys()) { + n->setStyleName(_oldStyles[n]); + n->attachStyle(); + } + + GraphUpdateCommand::undo(); +} + +void ApplyStyleToNodesCommand::redo() +{ + foreach (Node *n, _oldStyles.keys()) { + n->setStyleName(_style); + n->attachStyle(); + } + GraphUpdateCommand::redo(); +} + +ApplyStyleToEdgesCommand::ApplyStyleToEdgesCommand(TikzScene *scene, QString style, QUndoCommand *parent) : + GraphUpdateCommand(scene, parent), _style(style), _oldStyles() +{ + foreach(QGraphicsItem *it, scene->selectedItems()) { + if (EdgeItem *ei = dynamic_cast(it)) { + _oldStyles.insert(ei->edge(), ei->edge()->styleName()); + } + } +} + +void ApplyStyleToEdgesCommand::undo() +{ + foreach(Edge *e, _oldStyles.keys()) { + e->setStyleName(_oldStyles[e]); + e->attachStyle(); + } + + GraphUpdateCommand::undo(); +} + +void ApplyStyleToEdgesCommand::redo() +{ + foreach(Edge *e, _oldStyles.keys()) { + e->setStyleName(_style); + e->attachStyle(); + } + GraphUpdateCommand::redo(); +} + +PasteCommand::PasteCommand(TikzScene *scene, Graph *graph, QUndoCommand *parent) : + GraphUpdateCommand(scene, parent), _graph(graph) +{ + scene->getSelection(_oldSelectedNodes, _oldSelectedEdges); +} + +void PasteCommand::undo() +{ + _scene->clearSelection(); + + foreach (Edge *e, _graph->edges()) { + EdgeItem *ei = _scene->edgeItems()[e]; + _scene->edgeItems().remove(e); + _scene->removeItem(ei); + delete ei; + + _scene->graph()->removeEdge(e); + } + + foreach (Node *n, _graph->nodes()) { + NodeItem *ni = _scene->nodeItems()[n]; + _scene->nodeItems().remove(n); + _scene->removeItem(ni); + delete ni; + + _scene->graph()->removeNode(n); + } + + foreach(Node *n, _oldSelectedNodes) _scene->nodeItems()[n]->setSelected(true); + foreach(Edge *e, _oldSelectedEdges) _scene->edgeItems()[e]->setSelected(true); + + GraphUpdateCommand::undo(); +} + +void PasteCommand::redo() +{ + _scene->clearSelection(); + _scene->graph()->insertGraph(_graph); + + foreach (Edge *e, _graph->edges()) { + e->attachStyle(); // in case styles have changed + EdgeItem *ei = new EdgeItem(e); + _scene->edgeItems().insert(e, ei); + _scene->addItem(ei); + } + + foreach (Node *n, _graph->nodes()) { + n->attachStyle(); // in case styles have changed + NodeItem *ni = new NodeItem(n); + _scene->nodeItems().insert(n, ni); + _scene->addItem(ni); + ni->setSelected(true); + } + + GraphUpdateCommand::redo(); +} + +ChangeLabelCommand::ChangeLabelCommand(TikzScene *scene, Graph *graph, QMap oldLabels, QString newLabel, QUndoCommand *parent) : + GraphUpdateCommand(scene, parent), _oldLabels(oldLabels), _newLabel(newLabel) +{ +} + +void ChangeLabelCommand::undo() +{ + foreach (Node *n, _oldLabels.keys()) { + n->setLabel(_oldLabels[n]); + NodeItem *ni = _scene->nodeItems()[n]; + if (ni != 0) ni->updateBounds(); + } + + GraphUpdateCommand::undo(); +} + +void ChangeLabelCommand::redo() +{ + foreach (Node *n, _oldLabels.keys()) { + n->setLabel(_newLabel); + NodeItem *ni = _scene->nodeItems()[n]; + if (ni != 0) ni->updateBounds(); + } + + GraphUpdateCommand::redo(); +} + +ReplaceGraphCommand::ReplaceGraphCommand(TikzScene *scene, Graph *oldGraph, Graph *newGraph, QUndoCommand *parent) : + GraphUpdateCommand(scene, parent), _oldGraph(oldGraph), _newGraph(newGraph) +{ +} + +void ReplaceGraphCommand::undo() +{ + _scene->tikzDocument()->setGraph(_oldGraph); + _scene->graphReplaced(); +} + +void ReplaceGraphCommand::redo() +{ + _scene->tikzDocument()->setGraph(_newGraph); + _scene->graphReplaced(); +} diff --git a/src/gui/undocommands.h b/src/gui/undocommands.h index 9164f01..292632e 100644 --- a/src/gui/undocommands.h +++ b/src/gui/undocommands.h @@ -1,194 +1,194 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - This program 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. - - This program 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 this program. If not, see . -*/ - -/*! - * \file undocommands.h - * - * All changes to a TikzDocument are done via subclasses of QUndoCommand. When a controller - * (e.g. TikzScene) gets input from the user to change the document, it will push one of - * these commands onto the TikzDocument's undo stack, which automatically calls the redo() - * method of the command. - */ - -#ifndef UNDOCOMMANDS_H -#define UNDOCOMMANDS_H - -#include "tikzscene.h" - -#include -#include - -class GraphUpdateCommand : public QUndoCommand { -public: - explicit GraphUpdateCommand(TikzScene *scene, - QUndoCommand *parent = 0); - void undo() override; - void redo() override; -protected: - TikzScene *_scene; -}; - -class MoveCommand : public GraphUpdateCommand -{ -public: - explicit MoveCommand(TikzScene *scene, - QMap oldNodePositions, - QMap newNodePositions, - QUndoCommand *parent = 0); - void undo() override; - void redo() override; -private: - QMap _oldNodePositions; - QMap _newNodePositions; -}; - -class EdgeBendCommand : public GraphUpdateCommand -{ -public: - explicit EdgeBendCommand(TikzScene *scene, Edge *edge, - float oldWeight, int oldBend, - int oldInAngle, int oldOutAngle, - QUndoCommand *parent = 0); - void undo() override; - void redo() override; -private: - Edge *_edge; - float _oldWeight; - int _oldBend; - int _oldInAngle; - int _oldOutAngle; - float _newWeight; - int _newBend; - int _newInAngle; - int _newOutAngle; -}; - -class DeleteCommand : public GraphUpdateCommand -{ -public: - explicit DeleteCommand(TikzScene *scene, - QMap deleteNodes, - QMap deleteEdges, - QSet selEdges, - QUndoCommand *parent = 0); - void undo() override; - void redo() override; -private: - QMap _deleteNodes; - QMap _deleteEdges; - QSet _selEdges; -}; - -class AddNodeCommand : public GraphUpdateCommand -{ -public: - explicit AddNodeCommand(TikzScene *scene, Node *node, QRectF newBounds, - QUndoCommand *parent = 0); - void undo() override; - void redo() override; -private: - Node *_node; - QRectF _oldBounds; - QRectF _newBounds; -}; - -class AddEdgeCommand : public GraphUpdateCommand -{ -public: - explicit AddEdgeCommand(TikzScene *scene, Edge *edge, QUndoCommand *parent = 0); - void undo() override; - void redo() override; -private: - Edge *_edge; -}; - -class ChangeEdgeModeCommand : public GraphUpdateCommand -{ -public: - explicit ChangeEdgeModeCommand(TikzScene *scene, Edge *edge, QUndoCommand *parent = 0); - void undo() override; - void redo() override; -private: - Edge *_edge; -}; - -class ApplyStyleToNodesCommand : public GraphUpdateCommand -{ -public: - explicit ApplyStyleToNodesCommand(TikzScene *scene, QString style, QUndoCommand *parent = 0); - void undo() override; - void redo() override; -private: - QString _style; - QMap _oldStyles; -}; - -class ApplyStyleToEdgesCommand : public GraphUpdateCommand -{ -public: - explicit ApplyStyleToEdgesCommand(TikzScene *scene, QString style, QUndoCommand *parent = 0); - void undo() override; - void redo() override; -private: - QString _style; - QMap _oldStyles; -}; - -class PasteCommand : public GraphUpdateCommand -{ -public: - explicit PasteCommand(TikzScene *scene, Graph *graph, QUndoCommand *parent = 0); - void undo() override; - void redo() override; -private: - Graph *_graph; - QSet _oldSelectedNodes; - QSet _oldSelectedEdges; -}; - -class ChangeLabelCommand : public GraphUpdateCommand -{ -public: - explicit ChangeLabelCommand(TikzScene *scene, - Graph *graph, - QMap oldLabels, - QString newLabel, - QUndoCommand *parent = 0); - void undo() override; - void redo() override; -private: - Graph *_graph; - QMap _oldLabels; - QString _newLabel; -}; - -class ReplaceGraphCommand : public GraphUpdateCommand -{ -public: - explicit ReplaceGraphCommand(TikzScene *scene, - Graph *oldGraph, - Graph *newGraph, - QUndoCommand *parent = 0); - void undo() override; - void redo() override; -private: - Graph *_oldGraph; - Graph *_newGraph; -}; - -#endif // UNDOCOMMANDS_H +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program 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. + + This program 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 this program. If not, see . +*/ + +/*! + * \file undocommands.h + * + * All changes to a TikzDocument are done via subclasses of QUndoCommand. When a controller + * (e.g. TikzScene) gets input from the user to change the document, it will push one of + * these commands onto the TikzDocument's undo stack, which automatically calls the redo() + * method of the command. + */ + +#ifndef UNDOCOMMANDS_H +#define UNDOCOMMANDS_H + +#include "tikzscene.h" + +#include +#include + +class GraphUpdateCommand : public QUndoCommand { +public: + explicit GraphUpdateCommand(TikzScene *scene, + QUndoCommand *parent = 0); + void undo() override; + void redo() override; +protected: + TikzScene *_scene; +}; + +class MoveCommand : public GraphUpdateCommand +{ +public: + explicit MoveCommand(TikzScene *scene, + QMap oldNodePositions, + QMap newNodePositions, + QUndoCommand *parent = 0); + void undo() override; + void redo() override; +private: + QMap _oldNodePositions; + QMap _newNodePositions; +}; + +class EdgeBendCommand : public GraphUpdateCommand +{ +public: + explicit EdgeBendCommand(TikzScene *scene, Edge *edge, + float oldWeight, int oldBend, + int oldInAngle, int oldOutAngle, + QUndoCommand *parent = 0); + void undo() override; + void redo() override; +private: + Edge *_edge; + float _oldWeight; + int _oldBend; + int _oldInAngle; + int _oldOutAngle; + float _newWeight; + int _newBend; + int _newInAngle; + int _newOutAngle; +}; + +class DeleteCommand : public GraphUpdateCommand +{ +public: + explicit DeleteCommand(TikzScene *scene, + QMap deleteNodes, + QMap deleteEdges, + QSet selEdges, + QUndoCommand *parent = 0); + void undo() override; + void redo() override; +private: + QMap _deleteNodes; + QMap _deleteEdges; + QSet _selEdges; +}; + +class AddNodeCommand : public GraphUpdateCommand +{ +public: + explicit AddNodeCommand(TikzScene *scene, Node *node, QRectF newBounds, + QUndoCommand *parent = 0); + void undo() override; + void redo() override; +private: + Node *_node; + QRectF _oldBounds; + QRectF _newBounds; +}; + +class AddEdgeCommand : public GraphUpdateCommand +{ +public: + explicit AddEdgeCommand(TikzScene *scene, Edge *edge, QUndoCommand *parent = 0); + void undo() override; + void redo() override; +private: + Edge *_edge; +}; + +class ChangeEdgeModeCommand : public GraphUpdateCommand +{ +public: + explicit ChangeEdgeModeCommand(TikzScene *scene, Edge *edge, QUndoCommand *parent = 0); + void undo() override; + void redo() override; +private: + Edge *_edge; +}; + +class ApplyStyleToNodesCommand : public GraphUpdateCommand +{ +public: + explicit ApplyStyleToNodesCommand(TikzScene *scene, QString style, QUndoCommand *parent = 0); + void undo() override; + void redo() override; +private: + QString _style; + QMap _oldStyles; +}; + +class ApplyStyleToEdgesCommand : public GraphUpdateCommand +{ +public: + explicit ApplyStyleToEdgesCommand(TikzScene *scene, QString style, QUndoCommand *parent = 0); + void undo() override; + void redo() override; +private: + QString _style; + QMap _oldStyles; +}; + +class PasteCommand : public GraphUpdateCommand +{ +public: + explicit PasteCommand(TikzScene *scene, Graph *graph, QUndoCommand *parent = 0); + void undo() override; + void redo() override; +private: + Graph *_graph; + QSet _oldSelectedNodes; + QSet _oldSelectedEdges; +}; + +class ChangeLabelCommand : public GraphUpdateCommand +{ +public: + explicit ChangeLabelCommand(TikzScene *scene, + Graph *graph, + QMap oldLabels, + QString newLabel, + QUndoCommand *parent = 0); + void undo() override; + void redo() override; +private: + Graph *_graph; + QMap _oldLabels; + QString _newLabel; +}; + +class ReplaceGraphCommand : public GraphUpdateCommand +{ +public: + explicit ReplaceGraphCommand(TikzScene *scene, + Graph *oldGraph, + Graph *newGraph, + QUndoCommand *parent = 0); + void undo() override; + void redo() override; +private: + Graph *_oldGraph; + Graph *_newGraph; +}; + +#endif // UNDOCOMMANDS_H -- cgit v1.2.3