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

Last change on this file since 846 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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