diff options
Diffstat (limited to 'src/gui/tikzscene.cpp')
-rw-r--r-- | src/gui/tikzscene.cpp | 227 |
1 files changed, 193 insertions, 34 deletions
diff --git a/src/gui/tikzscene.cpp b/src/gui/tikzscene.cpp index 31d5bf6..4d14f43 100644 --- a/src/gui/tikzscene.cpp +++ b/src/gui/tikzscene.cpp @@ -29,6 +29,7 @@ #include <QInputDialog> #include <cmath> #include <delimitedstringvalidator.h> +#include <QSettings> TikzScene::TikzScene(TikzDocument *tikzDocument, ToolPalette *tools, @@ -41,7 +42,8 @@ TikzScene::TikzScene(TikzDocument *tikzDocument, ToolPalette *tools, _rubberBandItem = new QGraphicsRectItem(); _enabled = true; //setSceneRect(-310,-230,620,450); - setSceneRect(-1000,-1000,2000,2000); + //setSceneRect(-2000,-1500,4000,3000); + refreshSceneBounds(); QPen pen; pen.setColor(QColor::fromRgbF(0.5, 0.0, 0.5)); @@ -106,6 +108,7 @@ void TikzScene::graphReplaced() } refreshZIndices(); + refreshSceneBounds(); } void TikzScene::extendSelectionUp() @@ -225,6 +228,7 @@ void TikzScene::refreshZIndices() void TikzScene::mousePressEvent(QGraphicsSceneMouseEvent *event) { + QSettings settings("tikzit", "tikzit"); if (!_enabled) return; // current mouse position, in scene coordinates @@ -232,14 +236,24 @@ void TikzScene::mousePressEvent(QGraphicsSceneMouseEvent *event) _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; + if (event->button() == Qt::RightButton && + _tools->currentTool() == ToolPalette::SELECT && + settings.value("smart-tool-enabled", true).toBool()) + { + _smartTool = true; + if (!items(_mouseDownPos).isEmpty() && + dynamic_cast<NodeItem*>(items(_mouseDownPos)[0])) + { + _tools->setCurrentTool(ToolPalette::EDGE); + } else { + _tools->setCurrentTool(ToolPalette::VERTEX); + } + } + switch (_tools->currentTool()) { case ToolPalette::SELECT: // check if we grabbed a control point of an edge @@ -571,6 +585,12 @@ void TikzScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) break; } + if (_smartTool) { + _tools->setCurrentTool(ToolPalette::SELECT); + } + + _smartTool = false; + // clear artefacts from rubber band selection invalidate(QRect(), QGraphicsScene::BackgroundLayer); } @@ -581,6 +601,18 @@ void TikzScene::keyReleaseEvent(QKeyEvent *event) { if (!_enabled) return; + // clear highlighting for edge bends (if there was any) + if (event->modifiers() & Qt::ControlModifier) { + // it could be the case the user has released shift and is still holding control + bool head = !(event->modifiers() & Qt::ShiftModifier); + _highlightHeads = head; + _highlightTails = !head; + } else { + _highlightHeads = false; + _highlightTails = false; + } + + if (event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete) { deleteSelectedItems(); } else if (event->modifiers() == Qt::NoModifier) { @@ -600,6 +632,8 @@ void TikzScene::keyReleaseEvent(QKeyEvent *event) break; } } + + foreach (QGraphicsItem *it, selectedItems()) it->update(); } void TikzScene::keyPressEvent(QKeyEvent *event) @@ -612,42 +646,129 @@ void TikzScene::keyPressEvent(QKeyEvent *event) } if (event->modifiers() & Qt::ControlModifier) { - QPointF delta(0,0); - qreal shift = (event->modifiers() & Qt::ShiftModifier) ? 1.0 : 10.0; - switch(event->key()) { - case Qt::Key_Left: - delta.setX(-0.025 * shift); - break; - case Qt::Key_Right: - delta.setX(0.025 * shift); - break; - case Qt::Key_Up: - delta.setY(0.025 * shift); - break; - case Qt::Key_Down: - delta.setY(-0.025 * shift); - break; - } + QSet<Node*> selNodes; + QSet<Edge*> selEdges; + getSelection(selNodes, selEdges); + + if (!selNodes.isEmpty()) { + QPointF delta(0,0); + qreal shift = (event->modifiers() & Qt::ShiftModifier) ? 1.0 : 10.0; + switch(event->key()) { + case Qt::Key_Left: + delta.setX(-0.025 * shift); + break; + case Qt::Key_Right: + delta.setX(0.025 * shift); + break; + case Qt::Key_Up: + delta.setY(0.025 * shift); + break; + case Qt::Key_Down: + delta.setY(-0.025 * shift); + break; + } - if (!delta.isNull()) { - capture = true; - QMap<Node*,QPointF> oldNodePositions; - QMap<Node*,QPointF> newNodePositions; - QPointF pos; + if (!delta.isNull()) { + capture = true; + QMap<Node*,QPointF> oldNodePositions; + QMap<Node*,QPointF> newNodePositions; + QPointF pos; - foreach (QGraphicsItem *gi, selectedItems()) { - if (NodeItem *ni = dynamic_cast<NodeItem*>(gi)) { - pos = ni->node()->point(); - oldNodePositions.insert(ni->node(), pos); - newNodePositions.insert(ni->node(), pos + delta); + foreach (QGraphicsItem *gi, selectedItems()) { + if (NodeItem *ni = dynamic_cast<NodeItem*>(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); } + } else if (!selEdges.isEmpty()) { + int deltaAngle = 0; + qreal deltaWeight = 0.0; - MoveCommand *cmd = new MoveCommand(this, oldNodePositions, newNodePositions); - _tikzDocument->undoStack()->push(cmd); + bool head = !(event->modifiers() & Qt::ShiftModifier); + _highlightHeads = head; + _highlightTails = !head; + + switch(event->key()) { + case Qt::Key_Left: + deltaAngle = 15; + break; + case Qt::Key_Right: + deltaAngle = -15; + break; + case Qt::Key_Down: + deltaWeight = -0.1; + break; + case Qt::Key_Up: + deltaWeight = 0.1; + break; + } + + if (deltaAngle != 0) { + capture = true; + _tikzDocument->undoStack()->beginMacro("Bend edges"); + + // shift bend by deltaAngle or -deltaAngle (see below) + int sign = 1; + + foreach (Edge *e, selEdges) { + if (e->basicBendMode()) { + _tikzDocument->undoStack()->push(new ChangeEdgeModeCommand(this, e)); + } + + if (head) { + int oldInAngle = e->inAngle(); + e->setInAngle(oldInAngle + sign * deltaAngle); + EdgeBendCommand *cmd = new EdgeBendCommand(this, e, + e->weight(), + e->bend(), + oldInAngle, + e->outAngle()); + _tikzDocument->undoStack()->push(cmd); + } else { + int oldOutAngle = e->outAngle(); + e->setOutAngle(oldOutAngle + sign * deltaAngle); + EdgeBendCommand *cmd = new EdgeBendCommand(this, e, + e->weight(), + e->bend(), + e->inAngle(), + oldOutAngle); + _tikzDocument->undoStack()->push(cmd); + } + + // in the special case where 2 edges are selected, bend in opposite directions + if (selEdges.size() == 2) sign *= -1; + } + + _tikzDocument->undoStack()->endMacro(); + } else if (!almostZero(deltaWeight)) { + capture = true; + _tikzDocument->undoStack()->beginMacro("Adjust edges"); + + foreach (Edge *e, selEdges) { + qreal oldWeight = e->weight(); + // don't let weight drop below 0.1 + if (oldWeight + deltaWeight > 0.099) { + e->setWeight(oldWeight + deltaWeight); + EdgeBendCommand *cmd = new EdgeBendCommand(this, e, + oldWeight, + e->bend(), + e->inAngle(), + e->outAngle()); + _tikzDocument->undoStack()->push(cmd); + } + } + + _tikzDocument->undoStack()->endMacro(); + } } } + foreach (QGraphicsItem *it, selectedItems()) it->update(); if (!capture) QGraphicsScene::keyPressEvent(event); } @@ -687,6 +808,16 @@ void TikzScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) } } +bool TikzScene::highlightTails() const +{ + return _highlightTails; +} + +bool TikzScene::highlightHeads() const +{ + return _highlightHeads; +} + bool TikzScene::enabled() const { return _enabled; @@ -796,7 +927,13 @@ void TikzScene::selectAllNodes() void TikzScene::deselectAll() { - selectedItems().clear(); + foreach (NodeItem *ni, _nodeItems.values()) { + ni->setSelected(false); + } + + foreach (EdgeItem *ei, _edgeItems.values()) { + ei->setSelected(false); + } } bool TikzScene::parseTikz(QString tikz) @@ -870,6 +1007,28 @@ void TikzScene::reloadStyles() } } +void TikzScene::refreshSceneBounds() { + qreal maxX = 30.0, maxY = 30.0; + qreal increment = 20.0; + + foreach (Node *n, graph()->nodes()) { + while (n->point().x() - increment < -maxX || n->point().x() + increment > maxX) { + maxX += increment; + } + + while (n->point().y() - increment < -maxY || n->point().y() + increment > maxY) { + maxY += increment; + } + } + + QRectF rect(-GLOBAL_SCALEF * maxX, -GLOBAL_SCALEF * maxY, 2.0 * GLOBAL_SCALEF * maxX, 2.0 * GLOBAL_SCALEF * maxY); + + if (rect != sceneRect()) { + setSceneRect(rect); + invalidate(); + } +} + // void TikzScene::refreshSceneBounds() // { // // if (!views().empty()) { |