6#include <QtWidgets/qgridlayout.h>
7#include <QtWidgets/qlabel.h>
8#include <QtWidgets/qtoolbutton.h>
10#include <QtCore/qhash.h>
17 Q_DECLARE_PUBLIC(QtButtonPropertyBrowser)
26 {
return q_ptr->createEditor(property, parent); }
47 static void insertRow(QGridLayout *layout,
int row);
48 static void removeRow(QGridLayout *layout,
int row);
51 void setExpanded(
WidgetItem *item,
bool expanded);
52 static QToolButton *createButton(QWidget *parent =
nullptr);
54 QHash<QtBrowserItem *, WidgetItem *> m_indexToItem;
55 QHash<WidgetItem *, QtBrowserItem *> m_itemToIndex;
56 QHash<QWidget *, WidgetItem *> m_widgetToItem;
57 QHash<QObject *, WidgetItem *> m_buttonToItem;
58 QGridLayout *m_mainLayout =
nullptr;
59 QList<WidgetItem *> m_children;
60 QList<WidgetItem *> m_recreateQueue;
65 auto *button =
new QToolButton(parent);
66 button->setCheckable(
true);
67 button->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
68 button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
69 button->setArrowType(Qt::DownArrow);
70 button->setIconSize(QSize(3, 16));
72
73
74
75
76
82 QList<WidgetItem *> siblings;
86 siblings = m_children;
89 for (WidgetItem *sibling : std::as_const(siblings)) {
92 row += gridSpan(sibling);
106 m_mainLayout =
new QGridLayout();
107 parent->setLayout(m_mainLayout);
108 auto *item =
new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding);
109 m_mainLayout->addItem(item, 0, 0);
114 auto *editor = qobject_cast<QWidget *>(q_ptr->sender());
117 const auto it = m_widgetToItem.find(editor);
118 if (it != m_widgetToItem.end()) {
119 it.value()->widget =
nullptr;
120 m_widgetToItem.erase(it);
126 for (WidgetItem *item : std::as_const(m_recreateQueue)) {
127 WidgetItem *parent = item->parent;
128 QWidget *w =
nullptr;
129 QGridLayout *l =
nullptr;
130 const int oldRow = gridRow(item);
132 w = parent->container;
140 if (!item->widget && !item->widgetLabel)
142 item->label =
new QLabel(w);
143 item->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
144 l->addWidget(item->label, oldRow, 0, 1, span);
148 m_recreateQueue.clear();
156 if (!item->container)
160 const int row = gridRow(item);
162 QGridLayout *l =
nullptr;
169 insertRow(l, row + 1);
170 l->addWidget(item->container, row + 1, 0, 1, 2);
171 item->container->show();
173 l->removeWidget(item->container);
174 item->container->hide();
175 removeRow(l, row + 1);
178 item->button->setChecked(expanded);
179 item->button->setArrowType(expanded ? Qt::UpArrow : Qt::DownArrow);
184 WidgetItem *item = m_buttonToItem.value(q_ptr->sender());
188 setExpanded(item, checked);
191 emit q_ptr->expanded(m_itemToIndex.value(item));
193 emit q_ptr->collapsed(m_itemToIndex.value(item));
198 QMetaObject::invokeMethod(q_ptr, [
this] { slotUpdate(); }, Qt::QueuedConnection);
203 WidgetItem *afterItem = m_indexToItem.value(afterIndex);
204 WidgetItem *parentItem = m_indexToItem.value(index->parent());
209 QGridLayout *layout =
nullptr;
210 QWidget *parentWidget =
nullptr;
215 parentItem->children.insert(0, newItem);
217 m_children.insert(0, newItem);
219 row = gridRow(afterItem) + gridSpan(afterItem);
221 parentItem->children.insert(parentItem->children.indexOf(afterItem) + 1, newItem);
223 m_children.insert(m_children.indexOf(afterItem) + 1, newItem);
227 layout = m_mainLayout;
228 parentWidget = q_ptr;
230 if (!parentItem->container) {
231 m_recreateQueue.removeAll(parentItem);
233 QGridLayout *l =
nullptr;
234 const int oldRow = gridRow(parentItem);
236 l = grandParent->layout;
240 auto *container =
new QFrame();
241 container->setFrameShape(QFrame::Panel);
242 container->setFrameShadow(QFrame::Raised);
243 parentItem->container = container;
244 parentItem->button = createButton();
245 m_buttonToItem[parentItem->button] = parentItem;
246 QObject::connect(parentItem->button, &QAbstractButton::toggled,
247 q_ptr, [
this](
bool checked) { slotToggled(checked); });
248 parentItem->layout =
new QGridLayout();
249 container->setLayout(parentItem->layout);
250 if (parentItem->label) {
251 l->removeWidget(parentItem->label);
252 delete parentItem->label;
253 parentItem->label =
nullptr;
256 if (!parentItem->widget && !parentItem->widgetLabel)
258 l->addWidget(parentItem->button, oldRow, 0, 1, span);
259 updateItem(parentItem);
261 layout = parentItem->layout;
262 parentWidget = parentItem->container;
265 newItem->label =
new QLabel(parentWidget);
266 newItem->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
267 newItem->widget = createEditor(index->property(), parentWidget);
268 if (newItem->widget) {
269 QObject::connect(newItem->widget, &QWidget::destroyed,
270 q_ptr, [
this] { slotEditorDestroyed(); });
271 m_widgetToItem[newItem->widget] = newItem;
273 newItem->widgetLabel =
new QLabel(parentWidget);
274 newItem->widgetLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed));
277 insertRow(layout, row);
280 layout->addWidget(newItem->widget, row, 1);
281 else if (newItem->widgetLabel)
282 layout->addWidget(newItem->widgetLabel, row, 1);
285 layout->addWidget(newItem->label, row, 0, span, 1);
287 m_itemToIndex[newItem] = index;
288 m_indexToItem[index] = newItem;
295 WidgetItem *item = m_indexToItem.value(index);
297 m_indexToItem.remove(index);
298 m_itemToIndex.remove(item);
302 const int row = gridRow(item);
305 parentItem->children.removeAt(parentItem->children.indexOf(item));
307 m_children.removeAt(m_children.indexOf(item));
309 const int colSpan = gridSpan(item);
311 m_buttonToItem.remove(item->button);
315 delete item->widgetLabel;
317 delete item->container;
320 removeRow(m_mainLayout, row);
322 removeRow(m_mainLayout, row);
323 }
else if (!parentItem->children.empty()) {
324 removeRow(parentItem->layout, row);
326 removeRow(parentItem->layout, row);
329 QGridLayout *l =
nullptr;
331 l = grandParent->layout;
336 const int parentRow = gridRow(parentItem);
337 const int parentSpan = gridSpan(parentItem);
339 l->removeWidget(parentItem->button);
340 l->removeWidget(parentItem->container);
341 delete parentItem->button;
342 delete parentItem->container;
343 parentItem->button =
nullptr;
344 parentItem->container =
nullptr;
345 parentItem->layout =
nullptr;
346 if (!m_recreateQueue.contains(parentItem))
347 m_recreateQueue.append(parentItem);
349 removeRow(l, parentRow + 1);
353 m_recreateQueue.removeAll(item);
360 QHash<QLayoutItem *, QRect> itemToPos;
362 while (idx < layout->count()) {
364 layout->getItemPosition(idx, &r, &c, &rs, &cs);
366 itemToPos[layout->takeAt(idx)] = QRect(r + 1, c, rs, cs);
372 for (
auto it = itemToPos.constBegin(), icend = itemToPos.constEnd(); it != icend; ++it) {
373 const QRect r = it.value();
374 layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height());
380 QHash<QLayoutItem *, QRect> itemToPos;
382 while (idx < layout->count()) {
384 layout->getItemPosition(idx, &r, &c, &rs, &cs);
386 itemToPos[layout->takeAt(idx)] = QRect(r - 1, c, rs, cs);
392 for (
auto it = itemToPos.constBegin(), icend = itemToPos.constEnd(); it != icend; ++it) {
393 const QRect r = it.value();
394 layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height());
400 WidgetItem *item = m_indexToItem.value(index);
407 QtProperty *property = m_itemToIndex[item]->property();
409 QFont font = item->button->font();
411 item->button->setFont(font);
412 item->button->setText(property->propertyName());
413 item->button->setToolTip(property->descriptionToolTip());
414 item->button->setStatusTip(property->statusTip());
415 item->button->setWhatsThis(property->whatsThis());
419 QFont font = item->label->font();
421 item->label->setFont(font);
422 item->label->setText(property->propertyName());
423 item->label->setToolTip(property->descriptionToolTip());
424 item->label->setStatusTip(property->statusTip());
425 item->label->setWhatsThis(property->whatsThis());
428 if (item->widgetLabel) {
429 QFont font = item->widgetLabel->font();
430 font.setUnderline(
false);
431 item->widgetLabel->setFont(font);
432 item->widgetLabel->setText(property->valueText());
433 item->widgetLabel->setToolTip(property->valueText());
437 QFont font = item->widget->font();
438 font.setUnderline(
false);
439 item->widget->setFont(font);
441 const QString valueToolTip = property->valueToolTip();
442 item->widget->setToolTip(valueToolTip.isEmpty() ? property->valueText() : valueToolTip);
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
475
478
479
480
481
482
483
486
487
488
489
490
491
494
495
505
506
507
508
509
510
511
512
513
516 for (
auto it = d_ptr->m_itemToIndex.cbegin(), icend = d_ptr->m_itemToIndex.cend(); it != icend; ++it)
521
522
525 d_ptr->propertyInserted(item, afterItem);
529
530
533 d_ptr->propertyRemoved(item);
537
538
541 d_ptr->propertyChanged(item);
545
546
547
548
554 d_ptr->setExpanded(itm, expanded);
558
559
560
561
573#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.