File indexing completed on 2024-05-12 04:35:03

0001 /* This file is part of the TikZKit project.
0002  *
0003  * Copyright (C) 2013-2018 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 "Node.h"
0021 #include "Style.h"
0022 #include "Document.h"
0023 #include "Visitor.h"
0024 #include "MetaPos.h"
0025 
0026 #include "UndoSetNodePos.h"
0027 
0028 #include <cmath>
0029 
0030 #include <QUndoStack>
0031 #include <QDebug>
0032 
0033 namespace tikz {
0034 namespace core {
0035 
0036 class NodePrivate
0037 {
0038     public:
0039         NodePrivate(Document * doc)
0040             : pos(doc)
0041         {}
0042 
0043         // node position
0044         MetaPos pos;
0045 
0046         // node text
0047         QString text;
0048 
0049         // this node's style
0050         Uid styleUid;
0051         Style * style = nullptr;
0052 };
0053 
0054 Node::Node(const Uid & uid)
0055     : Entity(uid)
0056     , d(new NodePrivate(uid.document()))
0057 {
0058     setStyle(Uid());
0059 }
0060 
0061 Node::~Node()
0062 {
0063     if (d->style) {
0064         delete d->style;
0065         d->style = nullptr;
0066     }
0067     delete d;
0068 }
0069 
0070 tikz::EntityType Node::entityType() const
0071 {
0072     return EntityType::Node;
0073 }
0074 
0075 bool Node::accept(Visitor & visitor)
0076 {
0077     visitor.visit(this);
0078     return true;
0079 }
0080 
0081 void Node::loadData(const QJsonObject & json)
0082 {
0083     ConfigTransaction transaction(this);
0084 
0085     if (json.contains("text")) {
0086         setText(json["text"].toString());
0087     }
0088 
0089     if (json.contains("pos")) {
0090         d->pos = MetaPos(json["pos"].toString(), document());
0091     }
0092 
0093     if (json.contains("style")) {
0094         const Uid styleId(json["style"].toString(), document());
0095         setStyle(styleId);
0096     }
0097 }
0098 
0099 QJsonObject Node::saveData() const
0100 {
0101     QJsonObject json = Entity::saveData();
0102 
0103     json["text"] = d->text;
0104     json["pos"] = d->pos.toString();
0105     json["style"] = style()->uid().toString();
0106 
0107     return json;
0108 }
0109 
0110 void Node::setPos(const tikz::Pos & pos)
0111 {
0112     auto newPos = metaPos();
0113     newPos.setPos(pos);
0114     setMetaPos(newPos);
0115 
0116     Q_ASSERT(d->pos.pos() == pos);
0117 }
0118 
0119 tikz::Pos Node::pos() const
0120 {
0121     return d->pos.pos();
0122 }
0123 
0124 void Node::setMetaPos(const tikz::core::MetaPos & pos)
0125 {
0126     if (d->pos == pos) {
0127         return;
0128     }
0129 
0130     if (document()->undoActive()) {
0131         ConfigTransaction transaction(this);
0132         d->pos = pos;
0133     } else {
0134         document()->addUndoItem(new UndoSetNodePos(this, pos, document()));
0135     }
0136 }
0137 
0138 const tikz::core::MetaPos & Node::metaPos() const
0139 {
0140     return d->pos;
0141 }
0142 
0143 void Node::setText(const QString& text)
0144 {
0145     // only continue when change is required
0146     if (d->text == text) {
0147         return;
0148     }
0149 
0150     ConfigTransaction transaction(this);
0151     d->text = text;
0152     Q_EMIT textChanged(d->text);
0153 }
0154 
0155 QString Node::text() const
0156 {
0157     return d->text;
0158 }
0159 
0160 Style* Node::style() const
0161 {
0162     return d->styleUid.isValid() ? d->styleUid.entity<Style>() : d->style;
0163 }
0164 
0165 Uid Node::styleUid() const
0166 {
0167     return d->styleUid;
0168 }
0169 
0170 void Node::setStyle(const Uid & styleUid)
0171 {
0172     if (!d->styleUid.isValid()) {
0173         delete d->style;
0174         d->style = nullptr;
0175     } else {
0176         disconnect(d->styleUid.entity<Style>(), SIGNAL(changed()), this, SLOT(emitChangedIfNeeded()));
0177     }
0178 
0179     if (styleUid.isValid()) {
0180         d->styleUid = styleUid;
0181     } else {
0182         d->style = new Style();
0183         d->style->setParentStyle(document()->style()->uid());
0184     }
0185 
0186     connect(style(), SIGNAL(changed()), this, SLOT(emitChangedIfNeeded()));
0187 }
0188 
0189 }
0190 }
0191 
0192 // kate: indent-width 4; replace-tabs on;