7#include <QtWidgets/qgridlayout.h>
8#include <QtWidgets/qlabel.h>
9#include <QtWidgets/qtoolbutton.h>
11#include <QtCore/qhash.h>
18 Q_DECLARE_PUBLIC(QtButtonPropertyBrowser)
27 {
return q_ptr->createEditor(property, parent); }
48 static void insertRow(QGridLayout *layout,
int row);
49 static void removeRow(QGridLayout *layout,
int row);
52 void setExpanded(
WidgetItem *item,
bool expanded);
53 static QToolButton *createButton(QWidget *parent =
nullptr);
55 QHash<QtBrowserItem *, WidgetItem *> m_indexToItem;
56 QHash<WidgetItem *, QtBrowserItem *> m_itemToIndex;
57 QHash<QWidget *, WidgetItem *> m_widgetToItem;
58 QHash<QObject *, WidgetItem *> m_buttonToItem;
59 QGridLayout *m_mainLayout =
nullptr;
60 QList<WidgetItem *> m_children;
61 QList<WidgetItem *> m_recreateQueue;
66 auto *button =
new QToolButton(parent);
67 button->setCheckable(
true);
68 button->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
69 button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
70 button->setArrowType(Qt::DownArrow);
71 button->setIconSize(QSize(3, 16));
73
74
75
76
77
83 QList<WidgetItem *> siblings;
87 siblings = m_children;
90 for (WidgetItem *sibling : std::as_const(siblings)) {
93 row += gridSpan(sibling);
107 m_mainLayout =
new QGridLayout();
108 parent->setLayout(m_mainLayout);
109 auto *item =
new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding);
110 m_mainLayout->addItem(item, 0, 0);
115 auto *editor = qobject_cast<QWidget *>(q_ptr->sender());
118 const auto it = m_widgetToItem.find(editor);
119 if (it != m_widgetToItem.end()) {
120 it.value()->widget =
nullptr;
121 m_widgetToItem.erase(it);
127 for (WidgetItem *item : std::as_const(m_recreateQueue)) {
128 WidgetItem *parent = item->parent;
129 QWidget *w =
nullptr;
130 QGridLayout *l =
nullptr;
131 const int oldRow = gridRow(item);
133 w = parent->container;
141 if (!item->widget && !item->widgetLabel)
143 item->label =
new QLabel(w);
144 item->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
145 l->addWidget(item->label, oldRow, 0, 1, span);
149 m_recreateQueue.clear();
157 if (!item->container)
161 const int row = gridRow(item);
163 QGridLayout *l =
nullptr;
170 insertRow(l, row + 1);
171 l->addWidget(item->container, row + 1, 0, 1, 2);
172 item->container->show();
174 l->removeWidget(item->container);
175 item->container->hide();
176 removeRow(l, row + 1);
179 item->button->setChecked(expanded);
180 item->button->setArrowType(expanded ? Qt::UpArrow : Qt::DownArrow);
185 WidgetItem *item = m_buttonToItem.value(q_ptr->sender());
189 setExpanded(item, checked);
192 emit q_ptr->expanded(m_itemToIndex.value(item));
194 emit q_ptr->collapsed(m_itemToIndex.value(item));
199 QMetaObject::invokeMethod(q_ptr, [
this] { slotUpdate(); }, Qt::QueuedConnection);
204 WidgetItem *afterItem = m_indexToItem.value(afterIndex);
205 WidgetItem *parentItem = m_indexToItem.value(index->parent());
210 QGridLayout *layout =
nullptr;
211 QWidget *parentWidget =
nullptr;
216 parentItem->children.insert(0, newItem);
218 m_children.insert(0, newItem);
220 row = gridRow(afterItem) + gridSpan(afterItem);
222 parentItem->children.insert(parentItem->children.indexOf(afterItem) + 1, newItem);
224 m_children.insert(m_children.indexOf(afterItem) + 1, newItem);
228 layout = m_mainLayout;
229 parentWidget = q_ptr;
231 if (!parentItem->container) {
232 m_recreateQueue.removeAll(parentItem);
234 QGridLayout *l =
nullptr;
235 const int oldRow = gridRow(parentItem);
237 l = grandParent->layout;
241 auto *container =
new QFrame();
242 container->setFrameShape(QFrame::Panel);
243 container->setFrameShadow(QFrame::Raised);
244 parentItem->container = container;
245 parentItem->button = createButton();
246 m_buttonToItem[parentItem->button] = parentItem;
247 QObject::connect(parentItem->button, &QAbstractButton::toggled,
248 q_ptr, [
this](
bool checked) { slotToggled(checked); });
249 parentItem->layout =
new QGridLayout();
250 container->setLayout(parentItem->layout);
251 if (parentItem->label) {
252 l->removeWidget(parentItem->label);
253 delete parentItem->label;
254 parentItem->label =
nullptr;
257 if (!parentItem->widget && !parentItem->widgetLabel)
259 l->addWidget(parentItem->button, oldRow, 0, 1, span);
260 updateItem(parentItem);
262 layout = parentItem->layout;
263 parentWidget = parentItem->container;
266 newItem->label =
new QLabel(parentWidget);
267 newItem->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
268 newItem->widget = createEditor(index->property(), parentWidget);
269 if (newItem->widget) {
270 QObject::connect(newItem->widget, &QWidget::destroyed,
271 q_ptr, [
this] { slotEditorDestroyed(); });
272 m_widgetToItem[newItem->widget] = newItem;
274 newItem->widgetLabel =
new QLabel(parentWidget);
275 newItem->widgetLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed));
278 insertRow(layout, row);
281 layout->addWidget(newItem->widget, row, 1);
282 else if (newItem->widgetLabel)
283 layout->addWidget(newItem->widgetLabel, row, 1);
286 layout->addWidget(newItem->label, row, 0, span, 1);
288 m_itemToIndex[newItem] = index;
289 m_indexToItem[index] = newItem;
296 WidgetItem *item = m_indexToItem.value(index);
298 m_indexToItem.remove(index);
299 m_itemToIndex.remove(item);
303 const int row = gridRow(item);
306 parentItem->children.removeAt(parentItem->children.indexOf(item));
308 m_children.removeAt(m_children.indexOf(item));
310 const int colSpan = gridSpan(item);
312 m_buttonToItem.remove(item->button);
316 delete item->widgetLabel;
318 delete item->container;
321 removeRow(m_mainLayout, row);
323 removeRow(m_mainLayout, row);
324 }
else if (!parentItem->children.empty()) {
325 removeRow(parentItem->layout, row);
327 removeRow(parentItem->layout, row);
330 QGridLayout *l =
nullptr;
332 l = grandParent->layout;
337 const int parentRow = gridRow(parentItem);
338 const int parentSpan = gridSpan(parentItem);
340 l->removeWidget(parentItem->button);
341 l->removeWidget(parentItem->container);
342 delete parentItem->button;
343 delete parentItem->container;
344 parentItem->button =
nullptr;
345 parentItem->container =
nullptr;
346 parentItem->layout =
nullptr;
347 if (!m_recreateQueue.contains(parentItem))
348 m_recreateQueue.append(parentItem);
350 removeRow(l, parentRow + 1);
354 m_recreateQueue.removeAll(item);
361 QHash<QLayoutItem *, QRect> itemToPos;
363 while (idx < layout->count()) {
365 layout->getItemPosition(idx, &r, &c, &rs, &cs);
367 itemToPos[layout->takeAt(idx)] = QRect(r + 1, c, rs, cs);
373 for (
auto it = itemToPos.constBegin(), icend = itemToPos.constEnd(); it != icend; ++it) {
374 const QRect r = it.value();
375 layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height());
381 QHash<QLayoutItem *, QRect> itemToPos;
383 while (idx < layout->count()) {
385 layout->getItemPosition(idx, &r, &c, &rs, &cs);
387 itemToPos[layout->takeAt(idx)] = QRect(r - 1, c, rs, cs);
393 for (
auto it = itemToPos.constBegin(), icend = itemToPos.constEnd(); it != icend; ++it) {
394 const QRect r = it.value();
395 layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height());
401 WidgetItem *item = m_indexToItem.value(index);
408 QtProperty *property = m_itemToIndex[item]->property();
410 QFont font = item->button->font();
412 item->button->setFont(font);
413 item->button->setText(property->propertyName());
414 item->button->setToolTip(property->descriptionToolTip());
415 item->button->setStatusTip(property->statusTip());
416 item->button->setWhatsThis(property->whatsThis());
420 QFont font = item->label->font();
422 item->label->setFont(font);
423 item->label->setText(property->propertyName());
424 item->label->setToolTip(property->descriptionToolTip());
425 item->label->setStatusTip(property->statusTip());
426 item->label->setWhatsThis(property->whatsThis());
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->setToolTip(property->valueText());
438 QFont font = item->widget->font();
439 font.setUnderline(
false);
440 item->widget->setFont(font);
442 const QString valueToolTip = property->valueToolTip();
443 item->widget->setToolTip(valueToolTip.isEmpty() ? property->valueText() : valueToolTip);
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
479
480
481
482
483
484
487
488
489
490
491
492
495
496
506
507
508
509
510
511
512
513
514
517 for (
auto it = d_ptr->m_itemToIndex.cbegin(), icend = d_ptr->m_itemToIndex.cend(); it != icend; ++it)
522
523
526 d_ptr->propertyInserted(item, afterItem);
530
531
534 d_ptr->propertyRemoved(item);
538
539
542 d_ptr->propertyChanged(item);
546
547
548
549
555 d_ptr->setExpanded(itm, expanded);
559
560
561
562
574#include "moc_qtbuttonpropertybrowser_p.cpp"
QtAbstractPropertyBrowser provides a base class for implementing property browsers.
The QtBrowserItem class represents a property in a property browser instance.
QtProperty * property() const
Returns the property which is accosiated with this item.
The QtProperty class encapsulates an instance of a property.
bool isEnabled() const
Returns whether the property is enabled.
bool hasValue() const
Returns whether the property has a value.
bool isModified() const
Returns whether the property is modified.
Combined button and popup list for selecting options.