1 /* This file is part of the KDE project
2 Copyright (C) 2003 Lucijan Busch <lucijan@gmx.at>
3 Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
4 Copyright (C) 2006-2010 Jarosław Staniek <staniek@kde.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 #include <QDebug>
23 #include <QWidget>
24 #include <QVariant>
25 #include <QTextStream>
26 #include <QDomElement>
27
28 #include "form.h"
29 #include "container.h"
30 #include "objecttree.h"
31
32
33 using namespace KFormDesigner;
34
35 /////////////////////////////////////////////////////////////////////////////////////////
36 ///////////////// ObjectTreeItem /////////////
37 ////////////////////////////////////////////////////////////////////////////////////////
38
39 class Q_DECL_HIDDEN ObjectTreeItem::Private
40 {
41 public:
42 Private(const QString &classn, const QString &name_, QWidget *widget_,
43 Container *parentContainer_, Container *c);
44
45 ~Private();
46
47 QString className;
48 QString name;
49 ObjectTreeList children;
50 QPointer<Container> container;
51 QHash<QString, QVariant> props;
52 QHash<QString, QVariant> *subprops;
53 QString unknownProps;
54 QHash<QByteArray, QString> pixmapNames;
55 ObjectTreeItem* parent;
56 QPointer<QWidget> widget;
57 QPointer<EventEater> eater;
58
59 bool enabled;
60
61 int row, col, rowspan, colspan;
62 bool span;
63 };
64
Private(const QString & classn,const QString & name_,QWidget * widget_,Container * parentContainer_,Container * c)65 ObjectTreeItem::Private::Private(const QString &classn, const QString &name_, QWidget *widget_,
66 Container *parentContainer_, Container *c)
67 : className(classn), name(name_), container(c)
68 , subprops(0), parent(0), widget(widget_), eater(new EventEater(widget_, parentContainer_))
69 , enabled(true), row(-1), col(-1), rowspan(-1), colspan(-1), span(false)
70 {
71
72 }
73
~Private()74 ObjectTreeItem::Private::~Private()
75 {
76 delete subprops;
77 }
78
ObjectTreeItem(const QString & classn,const QString & name,QWidget * widget,Container * parentContainer,Container * container)79 ObjectTreeItem::ObjectTreeItem(const QString &classn, const QString &name, QWidget *widget,
80 Container *parentContainer, Container *container)
81 : d(new Private(classn, name, widget, parentContainer, container))
82 {
83 //qDebug() << classn << name << widget->objectName() << "parentContainer:" << parentContainer << "container:" << container;
84 }
85
~ObjectTreeItem()86 ObjectTreeItem::~ObjectTreeItem()
87 {
88 delete d;
89 }
90
91 void
rename(const QString & name)92 ObjectTreeItem::rename(const QString &name)
93 {
94 d->name = name;
95 }
96
97 void
addChild(ObjectTreeItem * c)98 ObjectTreeItem::addChild(ObjectTreeItem *c)
99 {
100 d->children.append(c);
101 c->setParent(this);
102 }
103
104 void
removeChild(ObjectTreeItem * c)105 ObjectTreeItem::removeChild(ObjectTreeItem *c)
106 {
107 d->children.removeAt( d->children.indexOf(c) );
108 }
109
110 void
addModifiedProperty(const QByteArray & property,const QVariant & oldValue)111 ObjectTreeItem::addModifiedProperty(const QByteArray &property, const QVariant &oldValue)
112 {
113 if (property == "objectName")
114 return;
115
116 if (!d->props.contains(property)) {
117 d->props.insert(property, oldValue);
118 //qDebug() << "Added this property in the list: " << property << " oldValue: " << oldValue;
119 }
120 }
121
122 void
addSubproperty(const QByteArray & property,const QVariant & value)123 ObjectTreeItem::addSubproperty(const QByteArray &property, const QVariant& value)
124 {
125 if (!d->subprops)
126 d->subprops = new QHash<QString, QVariant>();
127 if (!d->props.contains(property))
128 d->subprops->insert(property, value);
129 }
130
131 void
storeUnknownProperty(QDomElement & el)132 ObjectTreeItem::storeUnknownProperty(QDomElement &el)
133 {
134 if (!el.isNull()) {
135 QTextStream ts(&d->unknownProps, QIODevice::WriteOnly | QIODevice::Append);
136 el.save(ts, 0);
137 }
138 }
139
unknownProperties()140 QString ObjectTreeItem::unknownProperties()
141 {
142 return d->unknownProps;
143 }
144
setUnknownProperties(const QString & set)145 void ObjectTreeItem::setUnknownProperties(const QString &set)
146 {
147 d->unknownProps = set;
148 }
149
150 void
setPixmapName(const QByteArray & property,const QString & name)151 ObjectTreeItem::setPixmapName(const QByteArray &property, const QString &name)
152 {
153 d->pixmapNames.insert(property, name);
154 }
155
156 QString
pixmapName(const QByteArray & property)157 ObjectTreeItem::pixmapName(const QByteArray &property)
158 {
159 return d->pixmapNames.value(property);
160 }
161
162 void
setGridPos(int row,int col,int rowspan,int colspan)163 ObjectTreeItem::setGridPos(int row, int col, int rowspan, int colspan)
164 {
165 d->row = row; d->col = col;
166 d->rowspan = rowspan;
167 d->colspan = colspan;
168 if (colspan || rowspan)
169 d->span = true;
170 else
171 d->span = false;
172 }
173
subproperties() const174 QHash<QString, QVariant>* ObjectTreeItem::subproperties() const
175 {
176 return d->subprops;
177 }
178
setEnabled(bool enabled)179 void ObjectTreeItem::setEnabled(bool enabled)
180 {
181 d->enabled = enabled;
182 }
183
isEnabled() const184 bool ObjectTreeItem::isEnabled() const
185 {
186 return d->enabled;
187 }
188
gridRow() const189 int ObjectTreeItem::gridRow() const
190 {
191 return d->row;
192 }
193
gridCol() const194 int ObjectTreeItem::gridCol() const
195 {
196 return d->col;
197 }
198
gridRowSpan() const199 int ObjectTreeItem::gridRowSpan() const
200 {
201 return d->rowspan;
202 }
203
gridColSpan() const204 int ObjectTreeItem::gridColSpan() const
205 {
206 return d->colspan;
207 }
208
spanMultipleCells() const209 bool ObjectTreeItem::spanMultipleCells() const
210 {
211 return d->span;
212 }
213
name() const214 QString ObjectTreeItem::name() const
215 {
216 return d->name;
217 }
218
className() const219 QString ObjectTreeItem::className() const
220 {
221 return d->className;
222 }
223
widget() const224 QWidget* ObjectTreeItem::widget() const
225 {
226 return d->widget;
227 }
228
eventEater() const229 EventEater* ObjectTreeItem::eventEater() const
230 {
231 return d->eater;
232 }
233
parent() const234 ObjectTreeItem* ObjectTreeItem::parent() const
235 {
236 return d->parent;
237 }
238
children()239 ObjectTreeList* ObjectTreeItem::children()
240 {
241 return &d->children;
242 }
243
modifiedProperties() const244 const QHash<QString, QVariant>* ObjectTreeItem::modifiedProperties() const
245 {
246 return &d->props;
247 }
248
container() const249 Container* ObjectTreeItem::container() const
250 {
251 return d->container;
252 }
253
setWidget(QWidget * w)254 void ObjectTreeItem::setWidget(QWidget *w)
255 {
256 d->widget = w;
257 }
258
setParent(ObjectTreeItem * parent)259 void ObjectTreeItem::setParent(ObjectTreeItem *parent)
260 {
261 d->parent = parent;
262 }
263
264
265 /////////////////////////////////////////////////////////////////////////////////////////
266 /// ObjectTree /////////
267 ////////////////////////////////////////////////////////////////////////////////////////
268
269 class Q_DECL_HIDDEN ObjectTree::Private
270 {
271 public:
Private()272 Private()
273 {
274
275 }
276
~Private()277 ~Private()
278 {
279
280 }
281
282 ObjectTreeHash treeHash;
283 };
284
ObjectTree(const QString & classn,const QString & name,QWidget * widget,Container * container)285 ObjectTree::ObjectTree(const QString &classn, const QString &name, QWidget *widget, Container *container)
286 : ObjectTreeItem(classn, name, widget, container, container), d(new Private())
287 {
288 }
289
~ObjectTree()290 ObjectTree::~ObjectTree()
291 {
292 while (!children()->isEmpty()) {
293 removeItem(children()->first());
294 }
295 delete d;
296 }
297
298 bool
rename(const QString & oldname,const QString & newname)299 ObjectTree::rename(const QString &oldname, const QString &newname)
300 {
301 if (oldname == name()) {
302 ObjectTreeItem::rename(newname);
303 return true;
304 }
305
306 ObjectTreeItem *it = lookup(oldname);
307 if (!it)
308 return false;
309
310 it->rename(newname);
311 d->treeHash.remove(oldname);
312 d->treeHash.insert(newname, it);
313
314 return true;
315 }
316
317 bool
reparent(const QString & name,const QString & newparent)318 ObjectTree::reparent(const QString &name, const QString &newparent)
319 {
320 ObjectTreeItem *item = lookup(name);
321 if (!item) return false;
322 ObjectTreeItem *parent = lookup(newparent);
323 if (!parent) return false;
324
325 item->parent()->removeChild(item);
326 parent->addChild(item);
327 return true;
328 }
329
330 ObjectTreeItem*
lookup(const QString & name)331 ObjectTree::lookup(const QString &name)
332 {
333 if (name == this->name())
334 return this;
335 else
336 return d->treeHash.value(name);
337 }
338
339 void
addItem(ObjectTreeItem * parent,ObjectTreeItem * c)340 ObjectTree::addItem(ObjectTreeItem *parent, ObjectTreeItem *c)
341 {
342 d->treeHash.insert(c->name(), c);
343
344 if (!parent)
345 parent = this;
346 parent->addChild(c);
347 container()->form()->emitChildAdded(c);
348
349 //qDebug() << "adding " << c->name() << " to " << parent->name();
350 }
351
352 void
removeItem(const QString & name)353 ObjectTree::removeItem(const QString &name)
354 {
355 ObjectTreeItem *c = lookup(name);
356 removeItem(c);
357 }
358
359 void
removeItem(ObjectTreeItem * c)360 ObjectTree::removeItem(ObjectTreeItem *c)
361 {
362 if (container() && container()->form())
363 container()->form()->emitChildRemoved(c);
364
365 foreach (ObjectTreeItem *titem, *c->children()) {
366 removeItem(titem->name());
367 }
368
369 d->treeHash.remove(c->name());
370 c->parent()->removeChild(c);
371 delete c;
372 }
373
374 QByteArray
generateUniqueName(const QByteArray & prefix,bool numberSuffixRequired)375 ObjectTree::generateUniqueName(const QByteArray &prefix, bool numberSuffixRequired)
376 {
377 if (!numberSuffixRequired && !lookup(prefix))
378 return prefix;
379 QString name(prefix);
380 int i = 2; //start from 2, i.e. we have: "widget", "widget2", etc.
381 while (lookup(name + QString::number(i)))
382 i++;
383
384 return (name + QString::number(i)).toLatin1();
385 }
386
hash()387 ObjectTreeHash* ObjectTree::hash()
388 {
389 return &d->treeHash;
390 }
391