File indexing completed on 2025-01-05 04:14:56
0001 /* This file is part of the TikZKit project. 0002 * 0003 * Copyright (C) 2013-2014 Dominik Haumann <dhaumann@kde.org> 0004 * 0005 * This library is free software; you can redistribute it and/or modify 0006 * it under the terms of the GNU Library General Public License as published 0007 * by the Free Software Foundation, either version 2 of the License, or 0008 * (at your option) any later version. 0009 * 0010 * This library is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 * GNU Library General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU Library General Public License 0016 * along with this library; see the file COPYING.LIB. If not, see 0017 * <http://www.gnu.org/licenses/>. 0018 */ 0019 0020 #include "EdgePath.h" 0021 #include "UndoSetEdgePos.h" 0022 #include "Node.h" 0023 #include "Document.h" 0024 0025 namespace tikz { 0026 namespace core { 0027 0028 class EdgePathPrivate 0029 { 0030 public: 0031 EdgePathPrivate(Document * doc) 0032 : start(doc) 0033 , end(doc) 0034 {} 0035 0036 // the element type of this edge 0037 PathType type; 0038 0039 // start meta node this edge points to 0040 MetaPos start; 0041 0042 // target/end meta node this edge points to 0043 MetaPos end; 0044 }; 0045 0046 EdgePath::EdgePath(PathType type, const Uid & uid) 0047 : Path(uid) 0048 , d(new EdgePathPrivate(uid.document())) 0049 { 0050 d->type = type; 0051 0052 connect(d->start.notificationObject(), SIGNAL(changed(tikz::core::MetaPos*)), this, SLOT(emitChangedIfNeeded())); 0053 connect(d->end.notificationObject(), SIGNAL(changed(tikz::core::MetaPos*)), this, SLOT(emitChangedIfNeeded())); 0054 } 0055 0056 EdgePath::~EdgePath() 0057 { 0058 delete d; 0059 } 0060 0061 const tikz::core::MetaPos & EdgePath::startMetaPos() const 0062 { 0063 return d->start; 0064 } 0065 0066 const tikz::core::MetaPos & EdgePath::endMetaPos() const 0067 { 0068 return d->end; 0069 } 0070 0071 void EdgePath::deconstruct() 0072 { 0073 // just set both the start and end pos to (0, 0). 0074 // undo (i.e., creating the node again), will then restore the initial 0075 // connections correctly. 0076 ConfigTransaction transaction(this); 0077 setStartPos(tikz::Pos()); 0078 setEndPos(tikz::Pos()); 0079 } 0080 0081 void EdgePath::detachFromNode(Node * node) 0082 { 0083 Q_ASSERT(node != nullptr); 0084 0085 // disconnect start from node, if currently attached 0086 if (d->start.node() == node) { 0087 auto newPos = startMetaPos(); 0088 newPos.setNode(nullptr); 0089 setStartMetaPos(newPos); 0090 } 0091 0092 // disconnect end from node, if currently attached 0093 if (d->end.node() == node) { 0094 auto newPos = endMetaPos(); 0095 newPos.setNode(nullptr); 0096 setEndMetaPos(newPos); 0097 } 0098 0099 Q_ASSERT(d->start.node() != node); 0100 Q_ASSERT(d->end.node() != node); 0101 } 0102 0103 PathType EdgePath::type() const 0104 { 0105 return d->type; 0106 } 0107 0108 void EdgePath::setStartNode(Node* node) 0109 { 0110 auto newPos = startMetaPos(); 0111 newPos.setNode(node); 0112 setStartMetaPos(newPos); 0113 0114 Q_ASSERT(d->start.node() == node); 0115 } 0116 0117 void EdgePath::setEndNode(Node* node) 0118 { 0119 auto newPos = endMetaPos(); 0120 newPos.setNode(node); 0121 setEndMetaPos(newPos); 0122 0123 Q_ASSERT(d->end.node() == node); 0124 } 0125 0126 Node* EdgePath::startNode() const 0127 { 0128 return d->start.node(); 0129 } 0130 0131 Node* EdgePath::endNode() 0132 { 0133 return d->end.node(); 0134 } 0135 0136 tikz::Pos EdgePath::startPos() const 0137 { 0138 return d->start.pos(); 0139 } 0140 0141 tikz::Pos EdgePath::endPos() const 0142 { 0143 return d->end.pos(); 0144 } 0145 0146 void EdgePath::setStartPos(const tikz::Pos & pos) 0147 { 0148 auto newPos = startMetaPos(); 0149 newPos.setPos(pos); 0150 setStartMetaPos(newPos); 0151 0152 Q_ASSERT(d->start.pos() == pos); 0153 } 0154 0155 void EdgePath::setEndPos(const tikz::Pos & pos) 0156 { 0157 auto newPos = endMetaPos(); 0158 newPos.setPos(pos); 0159 setEndMetaPos(newPos); 0160 0161 Q_ASSERT(d->end.pos() == pos); 0162 } 0163 0164 void EdgePath::setStartMetaPos(const tikz::core::MetaPos & pos) 0165 { 0166 if (d->start == pos) { 0167 return; 0168 } 0169 0170 if (document()->undoActive()) { 0171 ConfigTransaction transaction(this); 0172 auto oldNode = startNode(); 0173 d->start = pos; 0174 auto newNode = startNode(); 0175 if (oldNode != newNode) { 0176 Q_EMIT startNodeChanged(newNode); 0177 } 0178 } else { 0179 document()->addUndoItem( 0180 new UndoSetEdgePos(this, pos, true, document())); 0181 } 0182 } 0183 0184 void EdgePath::setEndMetaPos(const tikz::core::MetaPos & pos) 0185 { 0186 if (d->end == pos) { 0187 return; 0188 } 0189 0190 if (document()->undoActive()) { 0191 ConfigTransaction transaction(this); 0192 auto oldNode = endNode(); 0193 d->end = pos; 0194 auto newNode = endNode(); 0195 if (oldNode != newNode) { 0196 Q_EMIT endNodeChanged(newNode); 0197 } 0198 } else { 0199 document()->addUndoItem( 0200 new UndoSetEdgePos(this, pos, false, document())); 0201 } 0202 } 0203 0204 QString EdgePath::startAnchor() const 0205 { 0206 return d->start.anchor(); 0207 } 0208 0209 QString EdgePath::endAnchor() const 0210 { 0211 return d->end.anchor(); 0212 } 0213 0214 void EdgePath::setStartAnchor(const QString & anchor) 0215 { 0216 auto newPos = startMetaPos(); 0217 newPos.setAnchor(anchor); 0218 setStartMetaPos(newPos); 0219 0220 Q_ASSERT(d->start.anchor() == anchor); 0221 } 0222 0223 void EdgePath::setEndAnchor(const QString & anchor) 0224 { 0225 auto newPos = endMetaPos(); 0226 newPos.setAnchor(anchor); 0227 setEndMetaPos(newPos); 0228 0229 Q_ASSERT(d->end.anchor() == anchor); 0230 } 0231 0232 void EdgePath::loadData(const QJsonObject & json) 0233 { 0234 ConfigTransaction transaction(this); 0235 Path::loadData(json); 0236 0237 if (json.contains("start")) { 0238 setStartMetaPos(MetaPos(json["start"].toString(), document())); 0239 } 0240 0241 if (json.contains("end")) { 0242 setEndMetaPos(MetaPos(json["end"].toString(), document())); 0243 } 0244 0245 if (json.contains("style")) { 0246 const Uid styleId(json["style"].toString(), document()); 0247 setStyle(styleId); 0248 } 0249 } 0250 0251 QJsonObject EdgePath::saveData() const 0252 { 0253 QJsonObject json = Path::saveData(); 0254 0255 json["start"] = d->start.toString(); 0256 json["end"] = d->end.toString(); 0257 json["style"] = styleUid().toString(); 0258 0259 return json; 0260 } 0261 0262 0263 } 0264 } 0265 0266 // kate: indent-width 4; replace-tabs on;