source: trunk/tools/shared/qtpropertybrowser/qtgroupboxpropertybrowser.cpp@ 109

Last change on this file since 109 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 17.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the tools applications of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qtgroupboxpropertybrowser.h"
43#include <QtCore/QSet>
44#include <QtGui/QGridLayout>
45#include <QtGui/QLabel>
46#include <QtGui/QGroupBox>
47#include <QtCore/QTimer>
48#include <QtCore/QMap>
49
50#if QT_VERSION >= 0x040400
51QT_BEGIN_NAMESPACE
52#endif
53
54class QtGroupBoxPropertyBrowserPrivate
55{
56 QtGroupBoxPropertyBrowser *q_ptr;
57 Q_DECLARE_PUBLIC(QtGroupBoxPropertyBrowser)
58public:
59
60 void init(QWidget *parent);
61
62 void propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex);
63 void propertyRemoved(QtBrowserItem *index);
64 void propertyChanged(QtBrowserItem *index);
65 QWidget *createEditor(QtProperty *property, QWidget *parent) const
66 { return q_ptr->createEditor(property, parent); }
67
68 void slotEditorDestroyed();
69 void slotUpdate();
70
71 struct WidgetItem
72 {
73 WidgetItem() : widget(0), label(0), widgetLabel(0),
74 groupBox(0), layout(0), line(0), parent(0) { }
75 QWidget *widget; // can be null
76 QLabel *label;
77 QLabel *widgetLabel;
78 QGroupBox *groupBox;
79 QGridLayout *layout;
80 QFrame *line;
81 WidgetItem *parent;
82 QList<WidgetItem *> children;
83 };
84private:
85 void updateLater();
86 void updateItem(WidgetItem *item);
87 void insertRow(QGridLayout *layout, int row) const;
88 void removeRow(QGridLayout *layout, int row) const;
89
90 bool hasHeader(WidgetItem *item) const;
91
92 QMap<QtBrowserItem *, WidgetItem *> m_indexToItem;
93 QMap<WidgetItem *, QtBrowserItem *> m_itemToIndex;
94 QMap<QWidget *, WidgetItem *> m_widgetToItem;
95 QGridLayout *m_mainLayout;
96 QList<WidgetItem *> m_children;
97 QList<WidgetItem *> m_recreateQueue;
98};
99
100void QtGroupBoxPropertyBrowserPrivate::init(QWidget *parent)
101{
102 m_mainLayout = new QGridLayout();
103 parent->setLayout(m_mainLayout);
104 QLayoutItem *item = new QSpacerItem(0, 0,
105 QSizePolicy::Fixed, QSizePolicy::Expanding);
106 m_mainLayout->addItem(item, 0, 0);
107}
108
109void QtGroupBoxPropertyBrowserPrivate::slotEditorDestroyed()
110{
111 QWidget *editor = qobject_cast<QWidget *>(q_ptr->sender());
112 if (!editor)
113 return;
114 if (!m_widgetToItem.contains(editor))
115 return;
116 m_widgetToItem[editor]->widget = 0;
117 m_widgetToItem.remove(editor);
118}
119
120void QtGroupBoxPropertyBrowserPrivate::slotUpdate()
121{
122 QListIterator<WidgetItem *> itItem(m_recreateQueue);
123 while (itItem.hasNext()) {
124 WidgetItem *item = itItem.next();
125
126 WidgetItem *par = item->parent;
127 QWidget *w = 0;
128 QGridLayout *l = 0;
129 int oldRow = -1;
130 if (!par) {
131 w = q_ptr;
132 l = m_mainLayout;
133 oldRow = m_children.indexOf(item);
134 } else {
135 w = par->groupBox;
136 l = par->layout;
137 oldRow = par->children.indexOf(item);
138 if (hasHeader(par))
139 oldRow += 2;
140 }
141
142 if (item->widget) {
143 item->widget->setParent(w);
144 } else if (item->widgetLabel) {
145 item->widgetLabel->setParent(w);
146 } else {
147 item->widgetLabel = new QLabel(w);
148 }
149 int span = 1;
150 if (item->widget)
151 l->addWidget(item->widget, oldRow, 1, 1, 1);
152 else if (item->widgetLabel)
153 l->addWidget(item->widgetLabel, oldRow, 1, 1, 1);
154 else
155 span = 2;
156 item->label = new QLabel(w);
157 item->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
158 l->addWidget(item->label, oldRow, 0, 1, span);
159
160 updateItem(item);
161 }
162 m_recreateQueue.clear();
163}
164
165void QtGroupBoxPropertyBrowserPrivate::updateLater()
166{
167 QTimer::singleShot(0, q_ptr, SLOT(slotUpdate()));
168}
169
170void QtGroupBoxPropertyBrowserPrivate::propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex)
171{
172 WidgetItem *afterItem = m_indexToItem.value(afterIndex);
173 WidgetItem *parentItem = m_indexToItem.value(index->parent());
174
175 WidgetItem *newItem = new WidgetItem();
176 newItem->parent = parentItem;
177
178 QGridLayout *layout = 0;
179 QWidget *parentWidget = 0;
180 int row = -1;
181 if (!afterItem) {
182 row = 0;
183 if (parentItem)
184 parentItem->children.insert(0, newItem);
185 else
186 m_children.insert(0, newItem);
187 } else {
188 if (parentItem) {
189 row = parentItem->children.indexOf(afterItem) + 1;
190 parentItem->children.insert(row, newItem);
191 } else {
192 row = m_children.indexOf(afterItem) + 1;
193 m_children.insert(row, newItem);
194 }
195 }
196 if (parentItem && hasHeader(parentItem))
197 row += 2;
198
199 if (!parentItem) {
200 layout = m_mainLayout;
201 parentWidget = q_ptr;;
202 } else {
203 if (!parentItem->groupBox) {
204 m_recreateQueue.removeAll(parentItem);
205 WidgetItem *par = parentItem->parent;
206 QWidget *w = 0;
207 QGridLayout *l = 0;
208 int oldRow = -1;
209 if (!par) {
210 w = q_ptr;
211 l = m_mainLayout;
212 oldRow = m_children.indexOf(parentItem);
213 } else {
214 w = par->groupBox;
215 l = par->layout;
216 oldRow = par->children.indexOf(parentItem);
217 if (hasHeader(par))
218 oldRow += 2;
219 }
220 parentItem->groupBox = new QGroupBox(w);
221 parentItem->layout = new QGridLayout();
222 parentItem->groupBox->setLayout(parentItem->layout);
223 if (parentItem->label) {
224 l->removeWidget(parentItem->label);
225 delete parentItem->label;
226 parentItem->label = 0;
227 }
228 if (parentItem->widget) {
229 l->removeWidget(parentItem->widget);
230 parentItem->widget->setParent(parentItem->groupBox);
231 parentItem->layout->addWidget(parentItem->widget, 0, 0, 1, 2);
232 parentItem->line = new QFrame(parentItem->groupBox);
233 } else if (parentItem->widgetLabel) {
234 l->removeWidget(parentItem->widgetLabel);
235 delete parentItem->widgetLabel;
236 parentItem->widgetLabel = 0;
237 }
238 if (parentItem->line) {
239 parentItem->line->setFrameShape(QFrame::HLine);
240 parentItem->line->setFrameShadow(QFrame::Sunken);
241 parentItem->layout->addWidget(parentItem->line, 1, 0, 1, 2);
242 }
243 l->addWidget(parentItem->groupBox, oldRow, 0, 1, 2);
244 updateItem(parentItem);
245 }
246 layout = parentItem->layout;
247 parentWidget = parentItem->groupBox;
248 }
249
250 newItem->label = new QLabel(parentWidget);
251 newItem->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
252 newItem->widget = createEditor(index->property(), parentWidget);
253 if (!newItem->widget) {
254 newItem->widgetLabel = new QLabel(parentWidget);
255 } else {
256 QObject::connect(newItem->widget, SIGNAL(destroyed()), q_ptr, SLOT(slotEditorDestroyed()));
257 m_widgetToItem[newItem->widget] = newItem;
258 }
259
260 insertRow(layout, row);
261 int span = 1;
262 if (newItem->widget)
263 layout->addWidget(newItem->widget, row, 1);
264 else if (newItem->widgetLabel)
265 layout->addWidget(newItem->widgetLabel, row, 1);
266 else
267 span = 2;
268 layout->addWidget(newItem->label, row, 0, 1, span);
269
270 m_itemToIndex[newItem] = index;
271 m_indexToItem[index] = newItem;
272
273 updateItem(newItem);
274}
275
276void QtGroupBoxPropertyBrowserPrivate::propertyRemoved(QtBrowserItem *index)
277{
278 WidgetItem *item = m_indexToItem.value(index);
279
280 m_indexToItem.remove(index);
281 m_itemToIndex.remove(item);
282
283 WidgetItem *parentItem = item->parent;
284
285 int row = -1;
286
287 if (parentItem) {
288 row = parentItem->children.indexOf(item);
289 parentItem->children.removeAt(row);
290 if (hasHeader(parentItem))
291 row += 2;
292 } else {
293 row = m_children.indexOf(item);
294 m_children.removeAt(row);
295 }
296
297 if (item->widget)
298 delete item->widget;
299 if (item->label)
300 delete item->label;
301 if (item->widgetLabel)
302 delete item->widgetLabel;
303 if (item->groupBox)
304 delete item->groupBox;
305
306 if (!parentItem) {
307 removeRow(m_mainLayout, row);
308 } else if (parentItem->children.count() != 0) {
309 removeRow(parentItem->layout, row);
310 } else {
311 WidgetItem *par = parentItem->parent;
312 QWidget *w = 0;
313 QGridLayout *l = 0;
314 int oldRow = -1;
315 if (!par) {
316 w = q_ptr;
317 l = m_mainLayout;
318 oldRow = m_children.indexOf(parentItem);
319 } else {
320 w = par->groupBox;
321 l = par->layout;
322 oldRow = par->children.indexOf(parentItem);
323 if (hasHeader(par))
324 oldRow += 2;
325 }
326
327 if (parentItem->widget) {
328 parentItem->widget->hide();
329 parentItem->widget->setParent(0);
330 } else if (parentItem->widgetLabel) {
331 parentItem->widgetLabel->hide();
332 parentItem->widgetLabel->setParent(0);
333 } else {
334 //parentItem->widgetLabel = new QLabel(w);
335 }
336 l->removeWidget(parentItem->groupBox);
337 delete parentItem->groupBox;
338 parentItem->groupBox = 0;
339 parentItem->line = 0;
340 parentItem->layout = 0;
341 if (!m_recreateQueue.contains(parentItem))
342 m_recreateQueue.append(parentItem);
343 updateLater();
344 }
345 m_recreateQueue.removeAll(item);
346
347 delete item;
348}
349
350void QtGroupBoxPropertyBrowserPrivate::insertRow(QGridLayout *layout, int row) const
351{
352 QMap<QLayoutItem *, QRect> itemToPos;
353 int idx = 0;
354 while (idx < layout->count()) {
355 int r, c, rs, cs;
356 layout->getItemPosition(idx, &r, &c, &rs, &cs);
357 if (r >= row) {
358 itemToPos[layout->takeAt(idx)] = QRect(r + 1, c, rs, cs);
359 } else {
360 idx++;
361 }
362 }
363
364 const QMap<QLayoutItem *, QRect>::ConstIterator icend = itemToPos.constEnd();
365 for (QMap<QLayoutItem *, QRect>::ConstIterator it = itemToPos.constBegin(); it != icend; ++it) {
366 const QRect r = it.value();
367 layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height());
368 }
369}
370
371void QtGroupBoxPropertyBrowserPrivate::removeRow(QGridLayout *layout, int row) const
372{
373 QMap<QLayoutItem *, QRect> itemToPos;
374 int idx = 0;
375 while (idx < layout->count()) {
376 int r, c, rs, cs;
377 layout->getItemPosition(idx, &r, &c, &rs, &cs);
378 if (r > row) {
379 itemToPos[layout->takeAt(idx)] = QRect(r - 1, c, rs, cs);
380 } else {
381 idx++;
382 }
383 }
384
385 const QMap<QLayoutItem *, QRect>::ConstIterator icend = itemToPos.constEnd();
386 for (QMap<QLayoutItem *, QRect>::ConstIterator it = itemToPos.constBegin(); it != icend; ++it) {
387 const QRect r = it.value();
388 layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height());
389 }
390}
391
392bool QtGroupBoxPropertyBrowserPrivate::hasHeader(WidgetItem *item) const
393{
394 if (item->widget)
395 return true;
396 return false;
397}
398
399void QtGroupBoxPropertyBrowserPrivate::propertyChanged(QtBrowserItem *index)
400{
401 WidgetItem *item = m_indexToItem.value(index);
402
403 updateItem(item);
404}
405
406void QtGroupBoxPropertyBrowserPrivate::updateItem(WidgetItem *item)
407{
408 QtProperty *property = m_itemToIndex[item]->property();
409 if (item->groupBox) {
410 QFont font = item->groupBox->font();
411 font.setUnderline(property->isModified());
412 item->groupBox->setFont(font);
413 item->groupBox->setTitle(property->propertyName());
414 item->groupBox->setToolTip(property->toolTip());
415 item->groupBox->setStatusTip(property->statusTip());
416 item->groupBox->setWhatsThis(property->whatsThis());
417 item->groupBox->setEnabled(property->isEnabled());
418 }
419 if (item->label) {
420 QFont font = item->label->font();
421 font.setUnderline(property->isModified());
422 item->label->setFont(font);
423 item->label->setText(property->propertyName());
424 item->label->setToolTip(property->toolTip());
425 item->label->setStatusTip(property->statusTip());
426 item->label->setWhatsThis(property->whatsThis());
427 item->label->setEnabled(property->isEnabled());
428 }
429 if (item->widgetLabel) {
430 QFont font = item->widgetLabel->font();
431 font.setUnderline(false);
432 item->widgetLabel->setFont(font);
433 item->widgetLabel->setText(property->valueText());
434 item->widgetLabel->setEnabled(property->isEnabled());
435 }
436 if (item->widget) {
437 QFont font = item->widget->font();
438 font.setUnderline(false);
439 item->widget->setFont(font);
440 item->widget->setEnabled(property->isEnabled());
441 item->widget->setToolTip(property->valueText());
442 }
443 //item->setIcon(1, property->valueIcon());
444}
445
446
447
448/*!
449 \class QtGroupBoxPropertyBrowser
450 \internal
451 \inmodule QtDesigner
452 \since 4.4
453
454 \brief The QtGroupBoxPropertyBrowser class provides a QGroupBox
455 based property browser.
456
457 A property browser is a widget that enables the user to edit a
458 given set of properties. Each property is represented by a label
459 specifying the property's name, and an editing widget (e.g. a line
460 edit or a combobox) holding its value. A property can have zero or
461 more subproperties.
462
463 QtGroupBoxPropertyBrowser provides group boxes for all nested
464 properties, i.e. subproperties are enclosed by a group box with
465 the parent property's name as its title. For example:
466
467 \image qtgroupboxpropertybrowser.png
468
469 Use the QtAbstractPropertyBrowser API to add, insert and remove
470 properties from an instance of the QtGroupBoxPropertyBrowser
471 class. The properties themselves are created and managed by
472 implementations of the QtAbstractPropertyManager class.
473
474 \sa QtTreePropertyBrowser, QtAbstractPropertyBrowser
475*/
476
477/*!
478 Creates a property browser with the given \a parent.
479*/
480QtGroupBoxPropertyBrowser::QtGroupBoxPropertyBrowser(QWidget *parent)
481 : QtAbstractPropertyBrowser(parent)
482{
483 d_ptr = new QtGroupBoxPropertyBrowserPrivate;
484 d_ptr->q_ptr = this;
485
486 d_ptr->init(this);
487}
488
489/*!
490 Destroys this property browser.
491
492 Note that the properties that were inserted into this browser are
493 \e not destroyed since they may still be used in other
494 browsers. The properties are owned by the manager that created
495 them.
496
497 \sa QtProperty, QtAbstractPropertyManager
498*/
499QtGroupBoxPropertyBrowser::~QtGroupBoxPropertyBrowser()
500{
501 const QMap<QtGroupBoxPropertyBrowserPrivate::WidgetItem *, QtBrowserItem *>::ConstIterator icend = d_ptr->m_itemToIndex.constEnd();
502 for (QMap<QtGroupBoxPropertyBrowserPrivate::WidgetItem *, QtBrowserItem *>::ConstIterator it = d_ptr->m_itemToIndex.constBegin(); it != icend; ++it)
503 delete it.key();
504 delete d_ptr;
505}
506
507/*!
508 \reimp
509*/
510void QtGroupBoxPropertyBrowser::itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem)
511{
512 d_ptr->propertyInserted(item, afterItem);
513}
514
515/*!
516 \reimp
517*/
518void QtGroupBoxPropertyBrowser::itemRemoved(QtBrowserItem *item)
519{
520 d_ptr->propertyRemoved(item);
521}
522
523/*!
524 \reimp
525*/
526void QtGroupBoxPropertyBrowser::itemChanged(QtBrowserItem *item)
527{
528 d_ptr->propertyChanged(item);
529}
530
531#if QT_VERSION >= 0x040400
532QT_END_NAMESPACE
533#endif
534
535#include "moc_qtgroupboxpropertybrowser.cpp"
Note: See TracBrowser for help on using the repository browser.