diff options
Diffstat (limited to 'src/gui/tikzscene.cpp')
-rw-r--r-- | src/gui/tikzscene.cpp | 105 |
1 files changed, 93 insertions, 12 deletions
diff --git a/src/gui/tikzscene.cpp b/src/gui/tikzscene.cpp index 9ef4c20..4577981 100644 --- a/src/gui/tikzscene.cpp +++ b/src/gui/tikzscene.cpp @@ -67,6 +67,9 @@ TikzScene::TikzScene(TikzDocument *tikzDocument, ToolPalette *tools, _rubberBandItem->setVisible(false); addItem(_rubberBandItem); + + _highlightHeads = false; + _highlightTails = false; } TikzScene::~TikzScene() { @@ -183,6 +186,66 @@ void TikzScene::extendSelectionRight() } } +void TikzScene::mergeNodes() +{ + refreshZIndices(); + QSet<Node*> selNodes; + QSet<Edge*> selEdges; + getSelection(selNodes, selEdges); + + // build a map from locations to a chosen node at that location + QMap<QPair<int,int>,Node*> m; + foreach (Node *n, selNodes) { + // used fixed precision for hashing/comparing locations + QPair<int,int> fpPoint( + static_cast<int>(n->point().x() * 1000.0), + static_cast<int>(n->point().y() * 1000.0)); + if (!m.contains(fpPoint) || + _nodeItems[m[fpPoint]]->zValue() < _nodeItems[n]->zValue()) + { + m.insert(fpPoint, n); + } + } + + // build a second map from nodes to the node they will be merged with + QMap<Node*,Node*> m1; + foreach (Node *n, graph()->nodes()) { + QPair<int,int> fpPoint( + static_cast<int>(n->point().x() * 1000.0), + static_cast<int>(n->point().y() * 1000.0)); + Node *n1 = m[fpPoint]; + if (n1 != nullptr && n1 != n) m1.insert(n, n1); + } + + _tikzDocument->undoStack()->beginMacro("Merge nodes"); + + // copy adjacent edges from nodes that will be deleted + foreach (Edge *e, graph()->edges()) { + if (m1.contains(e->source()) || m1.contains(e->target())) { + Edge *e1 = e->copy(&m1); + AddEdgeCommand *cmd = new AddEdgeCommand(this, e1); + _tikzDocument->undoStack()->push(cmd); + } + } + + // delete nodes + QMap<int,Node*> delNodes; + QMap<int,Edge*> delEdges; + for (int i = 0; i < _tikzDocument->graph()->nodes().length(); ++i) { + Node *n = _tikzDocument->graph()->nodes()[i]; + if (m1.contains(n)) delNodes.insert(i, n); + } + for (int i = 0; i < _tikzDocument->graph()->edges().length(); ++i) { + Edge *e = _tikzDocument->graph()->edges()[i]; + if (m1.contains(e->source()) || m1.contains(e->target())) delEdges.insert(i, e); + } + DeleteCommand *cmd = new DeleteCommand(this, delNodes, delEdges, + selNodes, selEdges); + _tikzDocument->undoStack()->push(cmd); + + _tikzDocument->undoStack()->endMacro(); +} + void TikzScene::reorderSelection(bool toFront) { QVector<Node*> nodeOrd, nodeOrd1; @@ -509,6 +572,7 @@ void TikzScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) void TikzScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if (!_enabled) return; + QSettings settings("tikzit", "tikzit"); // current mouse position, in scene coordinates QPointF mousePos = event->scenePos(); @@ -593,7 +657,13 @@ void TikzScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) if (_edgeStartNodeItem != nullptr && _edgeEndNodeItem != nullptr) { Edge *e = new Edge(_edgeStartNodeItem->node(), _edgeEndNodeItem->node(), _tikzDocument); e->setStyleName(_styles->activeEdgeStyleName()); - AddEdgeCommand *cmd = new AddEdgeCommand(this, e); + + bool selectEdge = settings.value("select-new-edges", false).toBool(); + QSet<Node*> selNodes; + QSet<Edge*> selEdges; + if (selectEdge) getSelection(selNodes, selEdges); + AddEdgeCommand *cmd = new AddEdgeCommand(this, e, selectEdge, + selNodes, selEdges); _tikzDocument->undoStack()->push(cmd); } _edgeStartNodeItem = nullptr; @@ -618,12 +688,17 @@ void TikzScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) void TikzScene::keyReleaseEvent(QKeyEvent *event) { + //qDebug() << "keyrelease:" << QString::number(event->key(), 16); + //qDebug() << "modifiers:" << QString::number(QApplication::queryKeyboardModifiers(), 16); if (!_enabled) return; + // slower, but seems to be more reliable than event->modifiers() + Qt::KeyboardModifiers mod = QApplication::queryKeyboardModifiers(); + // clear highlighting for edge bends (if there was any) - if (event->modifiers() & Qt::ControlModifier) { + if (mod & Qt::ControlModifier) { // it could be the case the user has released shift and is still holding control - bool head = !(event->modifiers() & Qt::ShiftModifier); + bool head = !(mod & Qt::ShiftModifier); _highlightHeads = head; _highlightTails = !head; } else { @@ -634,7 +709,7 @@ void TikzScene::keyReleaseEvent(QKeyEvent *event) if (event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete) { deleteSelectedItems(); - } else if (event->modifiers() == Qt::NoModifier) { + } else if (mod == Qt::NoModifier) { switch(event->key()) { case Qt::Key_S: tikzit->activeWindow()->toolPalette()->setCurrentTool(ToolPalette::SELECT); @@ -657,21 +732,26 @@ void TikzScene::keyReleaseEvent(QKeyEvent *event) void TikzScene::keyPressEvent(QKeyEvent *event) { + //qDebug() << "keypress:" << QString::number(event->key(), 16); + //qDebug() << "modifiers:" << QString::number(QApplication::queryKeyboardModifiers(), 16); bool capture = false; + // slower, but seems to be more reliable than event->modifiers() + Qt::KeyboardModifiers mod = QApplication::queryKeyboardModifiers(); + if (event->key() == Qt::Key_QuoteLeft) { capture = true; _styles->nextNodeStyle(); } - if (event->modifiers() & Qt::ControlModifier) { + if (mod & Qt::ControlModifier) { 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; + qreal shift = (mod & Qt::ShiftModifier) ? 1.0 : 10.0; switch(event->key()) { case Qt::Key_Left: delta.setX(-0.025 * shift); @@ -708,7 +788,7 @@ void TikzScene::keyPressEvent(QKeyEvent *event) int deltaAngle = 0; qreal deltaWeight = 0.0; - bool head = !(event->modifiers() & Qt::ShiftModifier); + bool head = !(mod & Qt::ShiftModifier); _highlightHeads = head; _highlightTails = !head; @@ -829,12 +909,12 @@ void TikzScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) bool TikzScene::highlightTails() const { - return _highlightTails; + return _highlightTails && getSelectedNodes().isEmpty(); } bool TikzScene::highlightHeads() const { - return _highlightHeads; + return _highlightHeads && getSelectedNodes().isEmpty(); } bool TikzScene::enabled() const @@ -891,7 +971,8 @@ void TikzScene::deleteSelectedItems() //qDebug() << "nodes:" << deleteNodes; //qDebug() << "edges:" << deleteEdges; - DeleteCommand *cmd = new DeleteCommand(this, deleteNodes, deleteEdges, selEdges); + DeleteCommand *cmd = new DeleteCommand(this, deleteNodes, deleteEdges, + selNodes, selEdges); _tikzDocument->undoStack()->push(cmd); } @@ -983,7 +1064,7 @@ void TikzScene::rotateNodes(bool clockwise) } -void TikzScene::getSelection(QSet<Node *> &selNodes, QSet<Edge *> &selEdges) +void TikzScene::getSelection(QSet<Node *> &selNodes, QSet<Edge *> &selEdges) const { foreach (QGraphicsItem *gi, selectedItems()) { if (NodeItem *ni = dynamic_cast<NodeItem*>(gi)) selNodes << ni->node(); @@ -991,7 +1072,7 @@ void TikzScene::getSelection(QSet<Node *> &selNodes, QSet<Edge *> &selEdges) } } -QSet<Node *> TikzScene::getSelectedNodes() +QSet<Node *> TikzScene::getSelectedNodes() const { QSet<Node*> selNodes; foreach (QGraphicsItem *gi, selectedItems()) { |