1 /*
2 TikZiT - a GUI diagram editor for TikZ
3 Copyright (C) 2018 Aleks Kissinger
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
19 #include "graphelementdata.h"
20
21 #include <QDebug>
22 #include <QTextStream>
23
GraphElementData(QVector<GraphElementProperty> init,QObject * parent)24 GraphElementData::GraphElementData(QVector<GraphElementProperty> init, QObject *parent) : QAbstractItemModel(parent)
25 {
26 _properties = init;
27 }
28
GraphElementData(QObject * parent)29 GraphElementData::GraphElementData(QObject *parent) : QAbstractItemModel(parent) {
30 }
31
32
copy()33 GraphElementData *GraphElementData::copy()
34 {
35 return new GraphElementData(_properties);
36 }
37
setProperty(QString key,QString value)38 void GraphElementData::setProperty(QString key, QString value)
39 {
40 int i = indexOfKey(key);
41 if (i != -1) {
42 _properties[i].setValue(value);
43 } else {
44 GraphElementProperty p(key, value);
45 _properties << p;
46 }
47 }
48
unsetProperty(QString key)49 void GraphElementData::unsetProperty(QString key)
50 {
51 int i = indexOfKey(key);
52 if (i != -1)
53 _properties.remove(i);
54 }
55
add(GraphElementProperty p)56 void GraphElementData::add(GraphElementProperty p)
57 {
58 int i = _properties.size();
59 beginInsertRows(QModelIndex(), i, i);
60 _properties << p;
61 endInsertRows();
62 }
63
operator <<(GraphElementProperty p)64 void GraphElementData::operator <<(GraphElementProperty p)
65 {
66 add(p);
67 }
68
setAtom(QString atom)69 void GraphElementData::setAtom(QString atom)
70 {
71 int i = indexOfKey(atom);
72 if (i == -1)
73 _properties << GraphElementProperty(atom);
74 }
75
unsetAtom(QString atom)76 void GraphElementData::unsetAtom(QString atom)
77 {
78 int i = indexOfKey(atom);
79 if (i != -1)
80 _properties.remove(i);
81 }
82
property(QString key)83 QString GraphElementData::property(QString key)
84 {
85 int i = indexOfKey(key);
86 if (i != -1) {
87 return _properties[i].value();
88 } else {
89 return QString(); // null QString
90 }
91 }
92
hasProperty(QString key)93 bool GraphElementData::hasProperty(QString key)
94 {
95 return (indexOfKey(key) != -1);
96 }
97
atom(QString atom)98 bool GraphElementData::atom(QString atom)
99 {
100 int idx = indexOfKey(atom);
101 return (idx != -1 && _properties[idx].atom());
102 }
103
indexOfKey(QString key)104 int GraphElementData::indexOfKey(QString key)
105 {
106 for (int i = 0; i < _properties.size(); ++i) {
107 QString key1 = _properties[i].key();
108 if (key1 == key) return i;
109 }
110 return -1;
111 }
112
mergeData(GraphElementData * d)113 void GraphElementData::mergeData(GraphElementData *d)
114 {
115 GraphElementProperty p;
116 foreach (p, d->properties()) {
117 if (!hasProperty(p.key())) add(p);
118 }
119 }
120
removeRows(int row,int,const QModelIndex & parent)121 bool GraphElementData::removeRows(int row, int /*count*/, const QModelIndex &parent)
122 {
123 if (row >= 0 && row < _properties.length()) {
124 beginRemoveRows(parent, row, row+1);
125 _properties.remove(row);
126 endRemoveRows();
127 return true;
128 } else {
129 return false;
130 }
131 }
132
moveRows(const QModelIndex & sourceParent,int sourceRow,int,const QModelIndex & destinationParent,int destinationRow)133 bool GraphElementData::moveRows(const QModelIndex &sourceParent,
134 int sourceRow,
135 int /*count*/,
136 const QModelIndex &destinationParent,
137 int destinationRow)
138 {
139 if (sourceRow >= 0 && sourceRow < _properties.length() &&
140 destinationRow >= 0 && destinationRow <= _properties.length())
141 {
142 beginMoveRows(sourceParent, sourceRow, sourceRow, destinationParent, destinationRow);
143 GraphElementProperty p = _properties[sourceRow];
144 _properties.remove(sourceRow);
145 if (sourceRow < destinationRow) {
146 _properties.insert(destinationRow - 1, p);
147 } else {
148 _properties.insert(destinationRow, p);
149 }
150 endMoveRows();
151 return true;
152 } else {
153 return false;
154 }
155 }
156
data(const QModelIndex & index,int role) const157 QVariant GraphElementData::data(const QModelIndex &index, int role) const
158 {
159 if (role == Qt::DisplayRole || role == Qt::EditRole) {
160 if (index.row() >= 0 && index.row() < _properties.length()) {
161 const GraphElementProperty &p = _properties[index.row()];
162 QString s = (index.column() == 0) ? p.key() : p.value();
163 return QVariant(s);
164 }
165 }
166
167 return QVariant();
168 }
169
headerData(int section,Qt::Orientation orientation,int role) const170 QVariant GraphElementData::headerData(int section, Qt::Orientation orientation, int role) const
171 {
172 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
173 if (section == 0) return QVariant("Key/Atom");
174 else return QVariant("Value");
175 }
176
177 return QVariant();
178 }
179
index(int row,int column,const QModelIndex &) const180 QModelIndex GraphElementData::index(int row, int column, const QModelIndex &) const
181 {
182 return createIndex(row, column, (void*)0);
183 }
184
parent(const QModelIndex &) const185 QModelIndex GraphElementData::parent(const QModelIndex &) const
186 {
187 // there is no nesting, so always return an invalid index
188 return QModelIndex();
189 }
190
rowCount(const QModelIndex & parent) const191 int GraphElementData::rowCount(const QModelIndex &parent) const
192 {
193 if (parent.isValid()) {
194 return 0;
195 } else {
196 return _properties.size();
197 }
198 }
199
columnCount(const QModelIndex &) const200 int GraphElementData::columnCount(const QModelIndex &) const
201 {
202 return 2;
203 }
204
flags(const QModelIndex & index) const205 Qt::ItemFlags GraphElementData::flags(const QModelIndex &index) const
206 {
207 if (index.row() >= 0 && index.row() < _properties.length()) {
208 if (index.column() == 0 ||
209 (!_properties[index.row()].atom() && index.column() == 1))
210 {
211 return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
212 }
213 }
214 return QAbstractItemModel::flags(index);
215 }
216
setData(const QModelIndex & index,const QVariant & value,int role)217 bool GraphElementData::setData(const QModelIndex &index, const QVariant &value, int role)
218 {
219 bool success = false;
220 if (index.row() >= 0 && index.row() < _properties.length()) {
221 if (index.column() == 0) {
222 _properties[index.row()].setKey(value.toString());
223 success = true;
224 } else if (index.column() == 1 && !_properties[index.row()].atom()) {
225 _properties[index.row()].setValue(value.toString());
226 success = true;
227 }
228 }
229
230 if (success) {
231 QVector<int> roles;
232 roles << role;
233 emit dataChanged(index, index, roles);
234 }
235
236 return success;
237 }
238
tikz()239 QString GraphElementData::tikz() {
240 if (_properties.length() == 0) return "";
241 QString str;
242 QTextStream code(&str);
243 code << "[";
244
245 GraphElementProperty p;
246 bool first = true;
247 foreach(p, _properties) {
248 if (!first) code << ", ";
249 code << p.tikz();
250 first = false;
251 }
252
253 code << "]";
254
255 code.flush();
256 return str;
257 }
258
isEmpty()259 bool GraphElementData::isEmpty()
260 {
261 return _properties.isEmpty();
262 }
263
properties() const264 QVector<GraphElementProperty> GraphElementData::properties() const
265 {
266 return _properties;
267 }
268
pathData() const269 GraphElementData *GraphElementData::pathData() const
270 {
271 GraphElementData *d = new GraphElementData();
272 foreach(GraphElementProperty p, _properties) {
273 if (isPathProperty(p.key())) d->add(p);
274 }
275 return d;
276 }
277
nonPathData() const278 GraphElementData *GraphElementData::nonPathData() const
279 {
280 GraphElementData *d = new GraphElementData();
281 foreach(GraphElementProperty p, _properties) {
282 if (!isPathProperty(p.key())) d->add(p);
283 }
284 return d;
285 }
286
isPathProperty(QString key)287 bool GraphElementData::isPathProperty(QString key)
288 {
289 return (key == "bend left" ||
290 key == "bend right" ||
291 key == "in" ||
292 key == "out" ||
293 key == "looseness");
294 }
295