From ba8e3d516afefbb4a43227525ddb6525547a650e Mon Sep 17 00:00:00 2001 From: Aleks Kissinger Date: Mon, 9 Apr 2018 11:40:54 +0200 Subject: added support for tikz editing/parsing --- src/data/edge.cpp | 10 ++++++++++ src/data/edge.h | 5 +++++ src/data/graph.cpp | 1 + src/data/tikzdocument.cpp | 42 +++++++++++++++++++++++++++++++++++++++++- src/data/tikzdocument.h | 3 +++ src/data/tikzlexer.l | 2 +- src/data/tikzparserdefs.h | 2 +- src/gui/edgeitem.cpp | 13 ++++++++++--- src/gui/mainmenu.cpp | 11 +++++++++++ src/gui/mainmenu.h | 1 + src/gui/mainmenu.ui | 9 +++++++++ src/gui/mainwindow.cpp | 37 ++++++++++++++++++++++--------------- src/gui/mainwindow.h | 8 +++----- src/gui/tikzscene.cpp | 34 +++++++++++++++++++++++++--------- src/gui/tikzscene.h | 1 + src/tikzit.cpp | 5 ++++- 16 files changed, 148 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/data/edge.cpp b/src/data/edge.cpp index 5c49aba..d0f0deb 100644 --- a/src/data/edge.cpp +++ b/src/data/edge.cpp @@ -329,6 +329,16 @@ void Edge::setWeight(float weight) _weight = weight; } +int Edge::tikzLine() const +{ + return _tikzLine; +} + +void Edge::setTikzLine(int tikzLine) +{ + _tikzLine = tikzLine; +} + QPointF Edge::mid() const { return _mid; diff --git a/src/data/edge.h b/src/data/edge.h index f010acd..7df899f 100644 --- a/src/data/edge.h +++ b/src/data/edge.h @@ -57,6 +57,9 @@ public: void setOutAngle(int outAngle); void setWeight(float weight); + int tikzLine() const; + void setTikzLine(int tikzLine); + signals: public slots: @@ -86,6 +89,8 @@ private: QPointF _cp1; QPointF _cp2; QPointF _mid; + + int _tikzLine; }; #endif // EDGE_H diff --git a/src/data/graph.cpp b/src/data/graph.cpp index 33af93d..dec992f 100644 --- a/src/data/graph.cpp +++ b/src/data/graph.cpp @@ -179,6 +179,7 @@ QString Graph::tikz() Edge *e; foreach (e, _edges) { + e->setTikzLine(line); e->updateData(); code << "\t\t\\draw "; diff --git a/src/data/tikzdocument.cpp b/src/data/tikzdocument.cpp index bf39f67..206ec5b 100644 --- a/src/data/tikzdocument.cpp +++ b/src/data/tikzdocument.cpp @@ -17,6 +17,7 @@ TikzDocument::TikzDocument(QObject *parent) : QObject(parent) _fileName = ""; _shortName = ""; _undoStack = new QUndoStack(); + _undoStack->setClean(); } TikzDocument::~TikzDocument() @@ -68,6 +69,8 @@ void TikzDocument::open(QString fileName) foreach (Node *n, _graph->nodes()) n->attachStyle(); foreach (Edge *e, _graph->edges()) e->updateControls(); _parseSuccess = true; + refreshTikz(); + setClean(); } else { delete newGraph; _parseSuccess = false; @@ -78,6 +81,18 @@ void TikzDocument::save() { if (_fileName == "") { saveAs(); } else { + MainWindow *win = tikzit->activeWindow(); + if (win != 0 && !win->tikzScene()->enabled()) { + win->tikzScene()->parseTikz(win->tikzSource()); + if (!win->tikzScene()->enabled()) { + auto resp = QMessageBox::question(0, + tr("Tikz failed to parse"), + tr("Cannot save file with invalid TiKZ source. Revert changes and save?")); + if (resp == QMessageBox::Yes) win->tikzScene()->setEnabled(true); + else return; // ABORT the save + } + } + refreshTikz(); QFile file(_fileName); QFileInfo fi(file); @@ -89,13 +104,23 @@ void TikzDocument::save() { QTextStream stream(&file); stream << _tikz; file.close(); - tikzit->activeWindow()->updateFileName(); + setClean(); } else { QMessageBox::warning(0, "Save Failed", "Could not open file: '" + _fileName + "' for writing."); } } } +bool TikzDocument::isClean() const +{ + return _undoStack->isClean(); +} + +void TikzDocument::setClean() +{ + _undoStack->setClean(); +} + void TikzDocument::setGraph(Graph *graph) { _graph = graph; @@ -103,6 +128,18 @@ void TikzDocument::setGraph(Graph *graph) } void TikzDocument::saveAs() { + MainWindow *win = tikzit->activeWindow(); + if (win != 0 && !win->tikzScene()->enabled()) { + win->tikzScene()->parseTikz(win->tikzSource()); + if (!win->tikzScene()->enabled()) { + auto resp = QMessageBox::question(0, + tr("Tikz failed to parse"), + tr("Cannot save file with invalid TiKZ source. Revert changes and save?")); + if (resp == QMessageBox::Yes) win->tikzScene()->setEnabled(true); + else return; // ABORT the save + } + } + QSettings settings("tikzit", "tikzit"); QString fileName = QFileDialog::getSaveFileName(tikzit->activeWindow(), tr("Save File As"), @@ -112,6 +149,9 @@ void TikzDocument::saveAs() { if (!fileName.isEmpty()) { _fileName = fileName; save(); + + // clean state might not change, so update title bar manually + tikzit->activeWindow()->updateFileName(); } } diff --git a/src/data/tikzdocument.h b/src/data/tikzdocument.h index 9b6893a..8f16a53 100644 --- a/src/data/tikzdocument.h +++ b/src/data/tikzdocument.h @@ -32,6 +32,9 @@ public: void saveAs(); void save(); + bool isClean() const; + void setClean(); + private: Graph *_graph; QString _tikz; diff --git a/src/data/tikzlexer.l b/src/data/tikzlexer.l index 0a7ff39..d90ad4b 100644 --- a/src/data/tikzlexer.l +++ b/src/data/tikzlexer.l @@ -97,7 +97,7 @@ to { return TO; } } \) { BEGIN(INITIAL); - return COORD; + return TCOORD; } /* when we see "[", change parsing mode */ diff --git a/src/data/tikzparserdefs.h b/src/data/tikzparserdefs.h index 1625136..5865739 100644 --- a/src/data/tikzparserdefs.h +++ b/src/data/tikzparserdefs.h @@ -17,6 +17,6 @@ struct noderef { char *anchor; }; -inline int isatty(void*) { return 0; } +inline int isatty(int) { return 0; } #endif // TIKZPARSERDEFS_H diff --git a/src/gui/edgeitem.cpp b/src/gui/edgeitem.cpp index 04ee7b6..f174186 100644 --- a/src/gui/edgeitem.cpp +++ b/src/gui/edgeitem.cpp @@ -34,9 +34,16 @@ void EdgeItem::readPos() QPainterPath path; path.moveTo (toScreen(_edge->tail())); - path.cubicTo(toScreen(_edge->cp1()), - toScreen(_edge->cp2()), - toScreen(_edge->head())); + + 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())); diff --git a/src/gui/mainmenu.cpp b/src/gui/mainmenu.cpp index 7ebb6af..7e2584c 100644 --- a/src/gui/mainmenu.cpp +++ b/src/gui/mainmenu.cpp @@ -1,6 +1,8 @@ #include "mainmenu.h" #include "tikzit.h" +#include + MainMenu::MainMenu() { ui.setupUi(this); @@ -109,6 +111,15 @@ void MainMenu::on_actionRevert_triggered() } } +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() diff --git a/src/gui/mainmenu.h b/src/gui/mainmenu.h index 103a74a..bceb69d 100644 --- a/src/gui/mainmenu.h +++ b/src/gui/mainmenu.h @@ -36,6 +36,7 @@ public slots: // Tikz void on_actionParse_triggered(); void on_actionRevert_triggered(); + void on_actionJump_to_Selection_triggered(); // View void on_actionZoom_In_triggered(); diff --git a/src/gui/mainmenu.ui b/src/gui/mainmenu.ui index ccd6c38..6a2511e 100644 --- a/src/gui/mainmenu.ui +++ b/src/gui/mainmenu.ui @@ -44,6 +44,7 @@ + @@ -190,6 +191,14 @@ Revert Tikz + + + Jump to Selection + + + Ctrl+J + + diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 9436eb3..15b6943 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -13,6 +13,7 @@ #include #include #include +#include int MainWindow::_numWindows = 0; @@ -32,15 +33,9 @@ MainWindow::MainWindow(QWidget *parent) : _stylePalette = new StylePalette(this); addDockWidget(Qt::RightDockWidgetArea, _stylePalette); - - _tikzScene = new TikzScene(_tikzDocument, _toolPalette, _stylePalette, this); ui->tikzView->setScene(_tikzScene); - - _pristine = true; - - // TODO: check if each window should have a menu _menu = new MainMenu(); _menu->setParent(this); @@ -52,6 +47,10 @@ MainWindow::MainWindow(QWidget *parent) : 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() @@ -62,15 +61,16 @@ MainWindow::~MainWindow() void MainWindow::open(QString fileName) { - _pristine = false; _tikzDocument->open(fileName); - ui->tikzSource->setText(_tikzDocument->tikz()); + + //ui->tikzSource->setText(_tikzDocument->tikz()); if (_tikzDocument->parseSuccess()) { statusBar()->showMessage("TiKZ parsed successfully", 2000); - setWindowTitle("TiKZiT - " + _tikzDocument->shortName()); + //setWindowTitle("TiKZiT - " + _tikzDocument->shortName()); _tikzScene->setTikzDocument(_tikzDocument); + updateFileName(); } else { statusBar()->showMessage("Cannot read TiKZ source"); } @@ -102,9 +102,21 @@ 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() { - setWindowTitle("TiKZiT - " + _tikzDocument->shortName()); + QString nm = _tikzDocument->shortName(); + if (nm.isEmpty()) nm = "untitled"; + if (!_tikzDocument->isClean()) nm += "*"; + setWindowTitle("TiKZiT - " + nm); } void MainWindow::refreshTikz() @@ -140,11 +152,6 @@ TikzView *MainWindow::tikzView() const return ui->tikzView; } -bool MainWindow::pristine() const -{ - return _pristine; -} - void MainWindow::on_tikzSource_textChanged() { if (_tikzScene->enabled()) _tikzScene->setEnabled(false); diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h index dc69fbc..1e05239 100644 --- a/src/gui/mainwindow.h +++ b/src/gui/mainwindow.h @@ -29,7 +29,6 @@ public: ~MainWindow(); void open(QString fileName); - bool pristine() const; int windowId() const; TikzView *tikzView() const; TikzScene *tikzScene() const; @@ -37,12 +36,12 @@ public: ToolPalette *toolPalette() const; StylePalette *stylePalette() const; QString tikzSource(); - - void updateFileName(); - void refreshTikz(); + void setSourceLine(int line); public slots: void on_tikzSource_textChanged(); + void updateFileName(); + void refreshTikz(); protected: void closeEvent(QCloseEvent *event); void changeEvent(QEvent *event); @@ -54,7 +53,6 @@ private: ToolPalette *_toolPalette; StylePalette *_stylePalette; Ui::MainWindow *ui; - bool _pristine; int _windowId; static int _numWindows; }; diff --git a/src/gui/tikzscene.cpp b/src/gui/tikzscene.cpp index a650961..b26c4ba 100644 --- a/src/gui/tikzscene.cpp +++ b/src/gui/tikzscene.cpp @@ -20,6 +20,7 @@ TikzScene::TikzScene(TikzDocument *tikzDocument, ToolPalette *tools, _edgeStartNodeItem = 0; _drawEdgeItem = new QGraphicsLineItem(); _rubberBandItem = new QGraphicsRectItem(); + _enabled = true; //setSceneRect(-310,-230,620,450); setSceneRect(-1000,-1000,2000,2000); @@ -72,6 +73,7 @@ void TikzScene::graphReplaced() } foreach (Node *n, graph()->nodes()) { + n->attachStyle(); NodeItem *ni = new NodeItem(n); _nodeItems.insert(n, ni); addItem(ni); @@ -366,19 +368,25 @@ void TikzScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) _rubberBandItem->setVisible(false); if (!_oldNodePositions.empty()) { - QMap newNodePositions; + QPointF shift = mousePos - _mouseDownPos; + shift = QPointF(round(shift.x()/GRID_SEP)*GRID_SEP, round(shift.y()/GRID_SEP)*GRID_SEP); - foreach (QGraphicsItem *gi, selectedItems()) { - if (NodeItem *ni = dynamic_cast(gi)) { - ni->writePos(); - newNodePositions.insert(ni->node(), ni->node()->point()); + 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; + //qDebug() << _oldNodePositions; + //qDebug() << newNodePositions; + + _tikzDocument->undoStack()->push(new MoveCommand(this, _oldNodePositions, newNodePositions)); + } - _tikzDocument->undoStack()->push(new MoveCommand(this, _oldNodePositions, newNodePositions)); _oldNodePositions.clear(); } } @@ -483,6 +491,14 @@ void TikzScene::setEnabled(bool 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(); + } +} + void TikzScene::applyActiveStyleToNodes() { ApplyStyleToNodesCommand *cmd = new ApplyStyleToNodesCommand(this, _styles->activeNodeStyleName()); diff --git a/src/gui/tikzscene.h b/src/gui/tikzscene.h index 3cc2e87..3b4a1e1 100644 --- a/src/gui/tikzscene.h +++ b/src/gui/tikzscene.h @@ -47,6 +47,7 @@ public: void parseTikz(QString tikz); bool enabled() const; void setEnabled(bool enabled); + int lineNumberForSelection(); public slots: void graphReplaced(); diff --git a/src/tikzit.cpp b/src/tikzit.cpp index e91976c..a55473e 100644 --- a/src/tikzit.cpp +++ b/src/tikzit.cpp @@ -92,7 +92,10 @@ void Tikzit::open() tr("TiKZ Files (*.tikz)")); if (!fileName.isEmpty()) { - if (_windows.size() == 1 && _windows[0]->pristine()) { + if (_windows.size() == 1 && + _windows[0]->tikzDocument()->isClean() && + _windows[0]->tikzDocument()->shortName().isEmpty()) + { _windows[0]->open(fileName); _windows[0]->show(); } else { -- cgit v1.2.3