7#include <qlayout_widget_p.h>
9#include <qdesigner_propertycommand_p.h>
10#include <qdesigner_utils_p.h>
11#include <iconloader_p.h>
13#include <QtDesigner/abstractformeditor.h>
14#include <QtDesigner/abstractformwindow.h>
15#include <QtDesigner/abstractwidgetdatabase.h>
16#include <QtDesigner/container.h>
17#include <QtDesigner/abstractmetadatabase.h>
18#include <QtDesigner/qextensionmanager.h>
19#include <QtWidgets/qlayout.h>
20#include <QtWidgets/qlayoutitem.h>
21#include <QtWidgets/qmenu.h>
22#include <QtWidgets/qbuttongroup.h>
24#include <QtGui/qaction.h>
26#include <QtCore/qset.h>
27#include <QtCore/qdebug.h>
28#include <QtCore/qcoreapplication.h>
34using namespace Qt::StringLiterals;
37 enum { DataRole = 1000 };
41 return qvariant_cast<QObject *>(item->data(DataRole));
44static bool sameIcon(
const QIcon &i1,
const QIcon &i2)
46 if (i1.isNull() && i2.isNull())
48 if (i1.isNull() != i2.isNull())
50 return i1.cacheKey() == i2.cacheKey();
55 if (
auto *action = qobject_cast<
const QAction *>(o))
56 return !action->isSeparator();
62 qdesigner_internal::ObjectData::StandardItemList rc;
63 const Qt::ItemFlags baseFlags = Qt::ItemIsSelectable|Qt::ItemIsDropEnabled|Qt::ItemIsEnabled;
65 QStandardItem *item =
new QStandardItem;
66 Qt::ItemFlags flags = baseFlags;
67 if (i == qdesigner_internal::ObjectInspectorModel::ObjectNameColumn && isNameColumnEditable(o))
68 flags |= Qt::ItemIsEditable;
69 item->setFlags(flags);
77 return o->metaObject() == &QLayoutWidget::staticMetaObject;
89 QDesignerFormEditorInterface *
core;
124 if (object->isWidgetType()) {
125 initWidget(
static_cast<
QWidget*>(object), ctx);
129 if (m_className.startsWith(ctx.designerPrefix))
130 m_className.remove(1, ctx.designerPrefix.size() - 1);
136 if (
const QAction *act = qobject_cast<
const QAction*>(m_object)) {
137 if (act->isSeparator()) {
138 m_objectName = ctx.separator;
143 m_classIcon = act->icon();
152 bool isContainer =
false;
153 if (
const QDesignerWidgetDataBaseItemInterface *widgetItem = ctx.db->item(ctx.db->indexOfObject(w,
true))) {
154 m_classIcon = widgetItem->icon();
155 m_className = widgetItem->name();
156 isContainer = widgetItem->isContainer();
161 if (isQLayoutWidget(w)) {
162 if (
const QLayout *layout = w->layout()) {
164 m_managedLayoutType = LayoutInfo::layoutType(ctx.core, layout);
165 m_className = QLatin1StringView(layout->metaObject()->className());
166 m_objectName = layout->objectName();
171 if (qt_extension<QDesignerContainerExtension*>(ctx.core->extensionManager(), w)) {
177 m_managedLayoutType = LayoutInfo::managedLayoutType(ctx.core, w);
185 return m_parent == me.m_parent && m_object == me.m_object;
191 if (m_className != rhs.m_className)
193 if (m_objectName != rhs.m_objectName)
195 if (!sameIcon(m_classIcon, rhs.m_classIcon))
197 if (m_type != rhs.m_type)
199 if (m_managedLayoutType != rhs.m_managedLayoutType)
234 const QVariant object = QVariant::fromValue(m_object);
237 setItemsDisplayData(row, icons, ClassNameChanged|ObjectNameChanged|ClassIconChanged|TypeChanged|LayoutTypeChanged);
247 using ButtonGroupList = QList<QButtonGroup *>;
250 model.push_back(entry);
253 const QDesignerContainerExtension *containerExtension =
nullptr;
255 containerExtension = qt_extension<QDesignerContainerExtension*>(fwi->core()->extensionManager(), object);
256 Q_ASSERT(containerExtension);
257 const int count = containerExtension->count();
258 for (
int i=0; i < count; ++i) {
259 QObject *page = containerExtension->widget(i);
260 Q_ASSERT(page !=
nullptr);
261 createModelRecursion(fwi, object, page, model, ctx);
265 if (!object->children().isEmpty()) {
266 ButtonGroupList buttonGroups;
267 for (QObject *childObject : object->children()) {
269 if (childObject->isWidgetType()) {
270 if (!containerExtension) {
271 QWidget *widget = qobject_cast<QWidget*>(childObject);
272 if (fwi->isManaged(widget))
273 createModelRecursion(fwi, object, widget, model, ctx);
276 if (ctx.mdb->item(childObject)) {
277 if (
auto bg = qobject_cast<QButtonGroup*>(childObject))
278 buttonGroups.push_back(bg);
283 if (!buttonGroups.isEmpty()) {
284 for (QButtonGroup *group : std::as_const(buttonGroups))
285 createModelRecursion(fwi, object, group, model, ctx);
288 if (object->isWidgetType()) {
290 const auto actions =
static_cast<
QWidget*>(object)->actions();
291 for (QAction *action : actions) {
292 if (ctx.mdb->item(action)) {
293 QObject *childObject = action;
294 if (
auto menu = action->menu())
296 createModelRecursion(fwi, object, childObject, model, ctx);
307 headers += QCoreApplication::translate(
"ObjectInspectorModel",
"Object");
308 headers += QCoreApplication::translate(
"ObjectInspectorModel",
"Class");
311 setHorizontalHeaderLabels(headers);
313 m_icons.layoutIcons[LayoutInfo::NoLayout] = createIconSet(
"editbreaklayout.png"_L1);
314 m_icons.layoutIcons[LayoutInfo::HSplitter] = createIconSet(
"edithlayoutsplit.png"_L1);
315 m_icons.layoutIcons[LayoutInfo::VSplitter] = createIconSet(
"editvlayoutsplit.png"_L1);
316 m_icons.layoutIcons[LayoutInfo::HBox] = createIconSet(
"edithlayout.png"_L1);
317 m_icons.layoutIcons[LayoutInfo::VBox] = createIconSet(
"editvlayout.png"_L1);
318 m_icons.layoutIcons[LayoutInfo::Grid] = createIconSet(
"editgrid.png"_L1);
319 m_icons.layoutIcons[LayoutInfo::Form] = createIconSet(
"editform.png"_L1);
325 m_objectIndexMultiMap.clear();
333 QWidget *mainContainer = fw ? fw->mainContainer() :
nullptr;
334 if (!mainContainer) {
336 m_formWindow =
nullptr;
342 ObjectModel newModel;
344 static const QString separator = QCoreApplication::translate(
"ObjectInspectorModel",
"separator");
346 createModelRecursion(fw,
nullptr, mainContainer, newModel, ctx);
348 if (newModel == m_model) {
349 updateItemContents(m_model, newModel);
361 if (
const QStandardItem *item = itemFromIndex(index))
362 return objectOfItem(item);
371 rc += itemFromIndex(index);
372 const int nextColumn = index.column() + 1;
375 index = index.sibling(index.row(), nextColumn);
384 if (newModel.isEmpty())
387 const auto mcend = newModel.cend();
388 auto it = newModel.cbegin();
390 StandardItemList rootRow = createModelRow(it->object());
391 it->setItems(rootRow, m_icons);
393 m_objectIndexMultiMap.insert(it->object(), indexFromItem(rootRow.constFirst()));
394 for (++it; it != mcend; ++it) {
396 const QModelIndex parentIndex = m_objectIndexMultiMap.value(it->parent(), QModelIndex());
397 Q_ASSERT(parentIndex.isValid());
398 QStandardItem *parentItem = itemFromIndex(parentIndex);
399 StandardItemList row = createModelRow(it->object());
400 it->setItems(row, m_icons);
401 parentItem->appendRow(row);
402 m_objectIndexMultiMap.insert(it->object(), indexFromItem(row.constFirst()));
407 void ObjectInspectorModel::updateItemContents(ObjectModel &oldModel,
const ObjectModel &newModel)
411 using QObjectSet = QSet<QObject *>;
413 QObjectSet changedObjects;
415 const auto size = newModel.size();
416 Q_ASSERT(oldModel.size() == size);
417 for (qsizetype i = 0; i < size; ++i) {
421 if (
const unsigned changedMask = entry
.compare(newEntry
)) {
423 QObject * o = entry.object();
424 if (!changedObjects.contains(o)) {
425 changedObjects.insert(o);
426 const QModelIndexList indexes = m_objectIndexMultiMap.values(o);
427 for (
const QModelIndex &index : indexes)
428 entry.setItemsDisplayData(rowAt(index), m_icons, changedMask);
436 const QVariant rc = QStandardItemModel::data(index, role);
439 if (role == Qt::DisplayRole && rc.metaType().id() == QMetaType::QString) {
440 const QString s = rc.toString();
442 static const QString noName = QCoreApplication::translate(
"ObjectInspectorModel",
"<noname>");
443 return QVariant(noName);
451 if (role != Qt::EditRole || !m_formWindow)
454 QObject *object = objectAt(index);
458 const QString nameProperty = isQLayoutWidget(object) ? u"layoutName"_s : u"objectName"_s;
459 m_formWindow->commandHistory()->push(createTextPropertyCommand(nameProperty, value.toString(), object, m_formWindow));
ObjectData(QObject *parent, QObject *object, const ModelRecursionContext &ctx)
bool equals(const ObjectData &me) const
void setItemsDisplayData(const StandardItemList &row, const ObjectInspectorIcons &icons, unsigned mask) const
void setItems(const StandardItemList &row, const ObjectInspectorIcons &icons) const
unsigned compare(const ObjectData &me) const
ObjectInspectorModel(QObject *parent)
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Returns the data stored under the given role for the item referred to by the index.
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
Sets the role data for the item at index to value.
UpdateResult update(QDesignerFormWindowInterface *fw)
QObject * objectAt(const QModelIndex &index) const
Auxiliary methods to store/retrieve settings.
void createModelRecursion(const QDesignerFormWindowInterface *fwi, QObject *parent, QObject *object, ObjectModel &model, const ModelRecursionContext &ctx)
static bool sameIcon(const QIcon &i1, const QIcon &i2)
static bool isQLayoutWidget(const QObject *o)
static bool isNameColumnEditable(const QObject *o)
static qdesigner_internal::ObjectData::StandardItemList createModelRow(const QObject *o)
static QObject * objectOfItem(const QStandardItem *item)
const QDesignerWidgetDataBaseInterface * db
const QDesignerMetaDataBaseInterface * mdb
QDesignerFormEditorInterface * core
ModelRecursionContext(QDesignerFormEditorInterface *core, const QString &sepName)
const QString designerPrefix