7#include <QtWidgets/QGridLayout>
8#include <QtWidgets/QLabel>
9#include <QtWidgets/QToolButton>
16 Q_DECLARE_PUBLIC(QtButtonPropertyBrowser)
25 {
return q_ptr->createEditor(property, parent); }
46 static void insertRow(QGridLayout *layout,
int row);
47 static void removeRow(QGridLayout *layout,
int row);
50 void setExpanded(
WidgetItem *item,
bool expanded);
51 static QToolButton *createButton(QWidget *parent =
nullptr);
53 QHash<QtBrowserItem *, WidgetItem *> m_indexToItem;
54 QHash<WidgetItem *, QtBrowserItem *> m_itemToIndex;
55 QHash<QWidget *, WidgetItem *> m_widgetToItem;
56 QHash<QObject *, WidgetItem *> m_buttonToItem;
57 QGridLayout *m_mainLayout =
nullptr;
58 QList<WidgetItem *> m_children;
59 QList<WidgetItem *> m_recreateQueue;
64 auto *button =
new QToolButton(parent);
65 button->setCheckable(
true);
66 button->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
67 button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
68 button->setArrowType(Qt::DownArrow);
69 button->setIconSize(QSize(3, 16));
71
72
73
74
75
81 QList<WidgetItem *> siblings;
85 siblings = m_children;
88 for (WidgetItem *sibling : std::as_const(siblings)) {
91 row += gridSpan(sibling);
105 m_mainLayout =
new QGridLayout();
106 parent->setLayout(m_mainLayout);
107 auto *item =
new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding);
108 m_mainLayout->addItem(item, 0, 0);
113 auto *editor = qobject_cast<QWidget *>(q_ptr->sender());
116 const auto it = m_widgetToItem.find(editor);
117 if (it != m_widgetToItem.end()) {
118 it.value()->widget =
nullptr;
119 m_widgetToItem.erase(it);
125 for (WidgetItem *item : std::as_const(m_recreateQueue)) {
126 WidgetItem *parent = item->parent;
127 QWidget *w =
nullptr;
128 QGridLayout *l =
nullptr;
129 const int oldRow = gridRow(item);
131 w = parent->container;
139 if (!item->widget && !item->widgetLabel)
141 item->label =
new QLabel(w);
142 item->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
143 l->addWidget(item->label, oldRow, 0, 1, span);
147 m_recreateQueue.clear();
155 if (!item->container)
159 const int row = gridRow(item);
161 QGridLayout *l =
nullptr;
168 insertRow(l, row + 1);
169 l->addWidget(item->container, row + 1, 0, 1, 2);
170 item->container->show();
172 l->removeWidget(item->container);
173 item->container->hide();
174 removeRow(l, row + 1);
177 item->button->setChecked(expanded);
178 item->button->setArrowType(expanded ? Qt::UpArrow : Qt::DownArrow);
183 WidgetItem *item = m_buttonToItem.value(q_ptr->sender());
187 setExpanded(item, checked);
190 emit q_ptr->expanded(m_itemToIndex.value(item));
192 emit q_ptr->collapsed(m_itemToIndex.value(item));
197 QMetaObject::invokeMethod(q_ptr, [
this] { slotUpdate(); }, Qt::QueuedConnection);
202 WidgetItem *afterItem = m_indexToItem.value(afterIndex);
203 WidgetItem *parentItem = m_indexToItem.value(index->parent());
208 QGridLayout *layout =
nullptr;
209 QWidget *parentWidget =
nullptr;
214 parentItem->children.insert(0, newItem);
216 m_children.insert(0, newItem);
218 row = gridRow(afterItem) + gridSpan(afterItem);
220 parentItem->children.insert(parentItem->children.indexOf(afterItem) + 1, newItem);
222 m_children.insert(m_children.indexOf(afterItem) + 1, newItem);
226 layout = m_mainLayout;
227 parentWidget = q_ptr;
229 if (!parentItem->container) {
230 m_recreateQueue.removeAll(parentItem);
232 QGridLayout *l =
nullptr;
233 const int oldRow = gridRow(parentItem);
235 l = grandParent->layout;
239 auto *container =
new QFrame();
240 container->setFrameShape(QFrame::Panel);
241 container->setFrameShadow(QFrame::Raised);
242 parentItem->container = container;
243 parentItem->button = createButton();
244 m_buttonToItem[parentItem->button] = parentItem;
245 QObject::connect(parentItem->button, &QAbstractButton::toggled,
246 q_ptr, [
this](
bool checked) { slotToggled(checked); });
247 parentItem->layout =
new QGridLayout();
248 container->setLayout(parentItem->layout);
249 if (parentItem->label) {
250 l->removeWidget(parentItem->label);
251 delete parentItem->label;
252 parentItem->label =
nullptr;
255 if (!parentItem->widget && !parentItem->widgetLabel)
257 l->addWidget(parentItem->button, oldRow, 0, 1, span);
258 updateItem(parentItem);
260 layout = parentItem->layout;
261 parentWidget = parentItem->container;
264 newItem->label =
new QLabel(parentWidget);
265 newItem->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
266 newItem->widget = createEditor(index->property(), parentWidget);
267 if (newItem->widget) {
268 QObject::connect(newItem->widget, &QWidget::destroyed,
269 q_ptr, [
this] { slotEditorDestroyed(); });
270 m_widgetToItem[newItem->widget] = newItem;
272 newItem->widgetLabel =
new QLabel(parentWidget);
273 newItem->widgetLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed));
276 insertRow(layout, row);
279 layout->addWidget(newItem->widget, row, 1);
280 else if (newItem->widgetLabel)
281 layout->addWidget(newItem->widgetLabel, row, 1);
284 layout->addWidget(newItem->label, row, 0, span, 1);
286 m_itemToIndex[newItem] = index;
287 m_indexToItem[index] = newItem;
294 WidgetItem *item = m_indexToItem.value(index);
296 m_indexToItem.remove(index);
297 m_itemToIndex.remove(item);
301 const int row = gridRow(item);
304 parentItem->children.removeAt(parentItem->children.indexOf(item));
306 m_children.removeAt(m_children.indexOf(item));
308 const int colSpan = gridSpan(item);
310 m_buttonToItem.remove(item->button);
314 delete item->widgetLabel;
316 delete item->container;
319 removeRow(m_mainLayout, row);
321 removeRow(m_mainLayout, row);
322 }
else if (!parentItem->children.empty()) {
323 removeRow(parentItem->layout, row);
325 removeRow(parentItem->layout, row);
328 QGridLayout *l =
nullptr;
330 l = grandParent->layout;
335 const int parentRow = gridRow(parentItem);
336 const int parentSpan = gridSpan(parentItem);
338 l->removeWidget(parentItem->button);
339 l->removeWidget(parentItem->container);
340 delete parentItem->button;
341 delete parentItem->container;
342 parentItem->button =
nullptr;
343 parentItem->container =
nullptr;
344 parentItem->layout =
nullptr;
345 if (!m_recreateQueue.contains(parentItem))
346 m_recreateQueue.append(parentItem);
348 removeRow(l, parentRow + 1);
352 m_recreateQueue.removeAll(item);
359 QHash<QLayoutItem *, QRect> itemToPos;
361 while (idx < layout->count()) {
363 layout->getItemPosition(idx, &r, &c, &rs, &cs);
365 itemToPos[layout->takeAt(idx)] = QRect(r + 1, c, rs, cs);
371 for (
auto it = itemToPos.constBegin(), icend = itemToPos.constEnd(); it != icend; ++it) {
372 const QRect r = it.value();
373 layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height());
379 QHash<QLayoutItem *, QRect> itemToPos;
381 while (idx < layout->count()) {
383 layout->getItemPosition(idx, &r, &c, &rs, &cs);
385 itemToPos[layout->takeAt(idx)] = QRect(r - 1, c, rs, cs);
391 for (
auto it = itemToPos.constBegin(), icend = itemToPos.constEnd(); it != icend; ++it) {
392 const QRect r = it.value();
393 layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height());
399 WidgetItem *item = m_indexToItem.value(index);
406 QtProperty *property = m_itemToIndex[item]->property();
408 QFont font = item->button->font();
410 item->button->setFont(font);
411 item->button->setText(property->propertyName());
412 item->button->setToolTip(property->descriptionToolTip());
413 item->button->setStatusTip(property->statusTip());
414 item->button->setWhatsThis(property->whatsThis());
418 QFont font = item->label->font();
420 item->label->setFont(font);
421 item->label->setText(property->propertyName());
422 item->label->setToolTip(property->descriptionToolTip());
423 item->label->setStatusTip(property->statusTip());
424 item->label->setWhatsThis(property->whatsThis());
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->setToolTip(property->valueText());
436 QFont font = item->widget->font();
437 font.setUnderline(
false);
438 item->widget->setFont(font);
440 const QString valueToolTip = property->valueToolTip();
441 item->widget->setToolTip(valueToolTip.isEmpty() ? property->valueText() : valueToolTip);
448
449
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
477
478
479
480
481
482
485
486
487
488
489
490
493
494
504
505
506
507
508
509
510
511
512
515 for (
auto it = d_ptr->m_itemToIndex.cbegin(), icend = d_ptr->m_itemToIndex.cend(); it != icend; ++it)
520
521
524 d_ptr->propertyInserted(item, afterItem);
528
529
532 d_ptr->propertyRemoved(item);
536
537
540 d_ptr->propertyChanged(item);
544
545
546
547
553 d_ptr->setExpanded(itm, expanded);
557
558
559
560
572#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.