summaryrefslogtreecommitdiff
path: root/src/gui/tikzscene.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/tikzscene.cpp')
-rw-r--r--src/gui/tikzscene.cpp105
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()) {