12#include <QtDesigner/qextensionmanager.h>
13#include <QtDesigner/container.h>
14#include <QtDesigner/abstractformwindow.h>
15#include <QtDesigner/abstractformeditor.h>
16#include <QtDesigner/abstractlanguage.h>
17#include <QtDesigner/abstractwidgetdatabase.h>
18#include <QtDesigner/abstractmetadatabase.h>
19#include <QtDesigner/propertysheet.h>
21#include <QtWidgets/qwidget.h>
22#include <QtWidgets/qmenu.h>
23#include <QtWidgets/qapplication.h>
24#include <QtWidgets/qlayout.h>
25#include <QtGui/qundostack.h>
26#include <QtWidgets/qsplitter.h>
28#include <QtWidgets/qframe.h>
29#include <QtWidgets/qgroupbox.h>
30#include <QtWidgets/qtabwidget.h>
31#include <QtWidgets/qstackedwidget.h>
32#include <QtWidgets/qtoolbox.h>
33#include <QtWidgets/qabstractitemview.h>
34#include <QtWidgets/qabstractbutton.h>
35#include <QtWidgets/qabstractspinbox.h>
36#include <QtWidgets/qtextedit.h>
37#include <QtWidgets/qplaintextedit.h>
38#include <QtWidgets/qlabel.h>
40#include <QtGui/qaction.h>
42#include <QtCore/qstringlist.h>
43#include <QtCore/qmap.h>
44#include <QtCore/qvariant.h>
45#include <QtCore/qdebug.h>
47Q_DECLARE_METATYPE(QWidgetList)
51using namespace Qt::StringLiterals;
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
103 const QMetaObject *mo = w->metaObject();
104 if (mo == &QWidget::staticMetaObject || mo == &QFrame::staticMetaObject || mo == &QGroupBox::staticMetaObject || mo == &QLayoutWidget::staticMetaObject)
106 if (mo == &QTabWidget::staticMetaObject || mo == &QStackedWidget::staticMetaObject || mo == &QToolBox::staticMetaObject)
108 if (qobject_cast<
const QAbstractItemView*>(w))
110 if (qobject_cast<
const QAbstractButton *>(w))
112 if (qobject_cast<
const QAbstractSpinBox *>(w))
114 if (qobject_cast<
const QPlainTextEdit *>(w) || qobject_cast<
const QTextEdit*>(w))
121
122
123
127 static QMap<MorphCategory, QStringList> candidateCache;
128 auto it = candidateCache.find(cat);
129 if (it == candidateCache.end()) {
130 it = candidateCache.insert(cat, QStringList());
131 QStringList &l = it.value();
135 case MorphSimpleContainer:
138 l << u"QWidget"_s << u"QFrame"_s << u"QGroupBox"_s;
140 case MorphPageContainer:
141 l << u"QTabWidget"_s << u"QStackedWidget"_s << u"QToolBox"_s;
144 l << u"QListView"_s << u"QListWidget"_s
145 << u"QTreeView"_s << u"QTreeWidget"_s
146 << u"QTableView"_s << u"QTableWidget"_s
150 l << u"QCheckBox"_s << u"QRadioButton"_s
151 << u"QPushButton"_s << u"QToolButton"_s
152 << u"QCommandLinkButton"_s;
155 l << u"QDateTimeEdit"_s << u"QDateEdit"_s
157 << u"QSpinBox"_s << u"QDoubleSpinBox"_s;
160 l << u"QTextEdit"_s << u"QPlainTextEdit"_s << u"QTextBrowser"_s;
171 if (
const QDesignerContainerExtension *ce = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), w)) {
172 QWidgetList children;
173 if (
const int count = ce->count()) {
174 for (
int i = 0; i < count; i++)
175 children.push_back(ce->widget(i));
186static QString
suggestObjectName(
const QString &oldClassName,
const QString &newClassName,
const QString &oldName)
188 QString oldClassPart = oldClassName;
189 QString newClassPart = newClassName;
190 if (oldClassPart.startsWith(u'Q'))
191 oldClassPart.remove(0, 1);
192 if (newClassPart.startsWith(u'Q'))
193 newClassPart.remove(0, 1);
195 QString newName = oldName;
196 newName.replace(oldClassPart, newClassPart);
197 oldClassPart[0] = oldClassPart.at(0).toLower();
198 newClassPart[0] = newClassPart.at(0).toLower();
199 newName.replace(oldClassPart, newClassPart);
206 const auto labelList = fw->findChildren<QLabel*>();
207 for (QLabel *label : labelList)
208 if (label->buddy() == w)
219 QWidgetList list = qvariant_cast<QWidgetList>(parentWidget->property(name));
220 const int index = list.indexOf(oldWidget);
222 list.replace(index, newWidget);
223 parentWidget->setProperty(name, QVariant::fromValue(list));
228
229
251 static bool canMorph(QDesignerFormWindowInterface *fw,
QWidget *w,
int *childContainerCount =
nullptr,
MorphCategory *cat =
nullptr);
262 qWarning(
"*** Unable to create a MorphWidgetCommand");
266 QLabel *buddyLabel = buddyLabelOf(fw, w);
268 QUndoStack *us = fw->commandHistory();
269 us->beginMacro(morphCmd->text());
271 if (FormWindowBase *fwb = qobject_cast<FormWindowBase*>(fw))
272 fwb->emitWidgetRemoved(w);
274 const QString newWidgetName = morphCmd->newWidgetName();
279 SetPropertyCommand *buddyCmd =
new SetPropertyCommand(fw);
280 buddyCmd->init(buddyLabel, u"buddy"_s, QVariant(newWidgetName.toUtf8()));
288 QDesignerFormWindowCommand(QString(), formWindow),
289 m_beforeWidget(
nullptr),
290 m_afterWidget(
nullptr)
298 QDesignerFormWindowInterface *fw = formWindow();
299 QDesignerFormEditorInterface *core = fw->core();
301 if (!canMorph(fw, widget))
304 const QString oldClassName = WidgetFactory::classNameOf(core, widget);
305 const QString oldName = widget->objectName();
307 setText(QApplication::translate(
"Command",
"Morph %1/'%2' into %3").arg(oldClassName, oldName, newClassName));
309 m_beforeWidget = widget;
310 m_afterWidget = core->widgetFactory()->createWidget(newClassName, fw);
315 m_afterWidget->setObjectName(suggestObjectName(oldClassName, newClassName, oldName));
319 if (QDesignerContainerExtension* c = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), m_afterWidget)) {
320 if (
const auto pageCount = childContainers(core, m_beforeWidget).size()) {
321 const QString containerName = m_afterWidget->objectName();
322 for (qsizetype i = 0; i < pageCount; ++i) {
323 QString name = containerName;
325 name += QString::number(i + 1);
326 QWidget *page = core->widgetFactory()->createWidget(u"QWidget"_s);
327 page->setObjectName(name);
328 fw->ensureUniqueObjectName(page);
330 core->metaDataBase()->add(page);
338 const int count = beforeSheet->count();
339 for (
int i = 0; i < count; i++)
340 if (beforeSheet->isVisible(i) && beforeSheet->isChanged(i)) {
341 const QString name = beforeSheet->propertyName(i);
342 if (name !=
"objectName"_L1) {
343 const int afterIndex = afterSheet->indexOf(name);
344 if (afterIndex != -1 && afterSheet->isVisible(afterIndex) && afterSheet->propertyGroup(afterIndex) == beforeSheet->propertyGroup(i)) {
345 afterSheet->setProperty(i, beforeSheet->property(i));
346 afterSheet->setChanged(i,
true);
358 morph(m_beforeWidget, m_afterWidget);
363 morph(m_afterWidget, m_beforeWidget);
368 QDesignerFormWindowInterface *fw = formWindow();
370 fw->unmanageWidget(before);
372 const QRect oldGeom = before->geometry();
373 QWidget *parent = before->parentWidget();
376
377
380 QWidgetList beforeChildContainers = childContainers(fw->core(), before);
381 QWidgetList afterChildContainers = childContainers(fw->core(), after);
382 Q_ASSERT(beforeChildContainers.size() == afterChildContainers.size());
383 const auto childContainerCount = beforeChildContainers.size();
384 for (qsizetype i = 0; i < childContainerCount; ++i) {
385 QWidget *beforeChildContainer = beforeChildContainers.at(i);
386 QWidget *afterChildContainer = afterChildContainers.at(i);
387 if (QLayout *childLayout = beforeChildContainer->layout()) {
389 afterChildContainer->setLayout(childLayout);
392 for (QObject *o : beforeChildContainer->children()) {
393 if (o->isWidgetType()) {
394 QWidget *w =
static_cast<QWidget*>(o);
395 if (fw->isManaged(w)) {
396 const QRect geom = w->geometry();
397 w->setParent(afterChildContainer);
398 w->setGeometry(geom);
408 after->setGeometry(oldGeom);
409 if (QLayout *containingLayout = LayoutInfo::managedLayout(fw->core(), parent)) {
410 LayoutHelper *lh = LayoutHelper::createLayoutHelper(LayoutInfo::layoutType(fw->core(), containingLayout));
412 lh->replaceWidget(containingLayout, before, after);
414 }
else if (QSplitter *splitter = qobject_cast<QSplitter *>(parent)) {
415 const int index = splitter->indexOf(before);
417 before->setParent(
nullptr);
418 splitter->insertWidget(index, after);
419 after->setParent(parent);
420 after->setGeometry(oldGeom);
423 before->setParent(
nullptr);
424 after->setParent(parent);
425 after->setGeometry(oldGeom);
432 QDesignerMetaDataBaseItemInterface *formItem = fw->core()->metaDataBase()->item(fw);
433 QWidgetList tabOrder = formItem->tabOrder();
434 const int tabIndex = tabOrder.indexOf(before);
435 if (tabIndex != -1) {
436 tabOrder.replace(tabIndex, after);
437 formItem->setTabOrder(tabOrder);
441 fw->manageWidget(after);
443 fw->clearSelection(
false);
444 fw->selectWidget(after);
448
449
452 if (ptrToChildContainerCount)
453 *ptrToChildContainerCount = 0;
460 QDesignerFormEditorInterface *core = fw->core();
462 if (qt_extension<QDesignerLanguageExtension *>(core->extensionManager(), core))
464 if (!fw->isManaged(w) || w == fw->mainContainer())
468 QWidget *parent = w->parentWidget();
469 if (parent ==
nullptr)
471 if (QLayout *pl = LayoutInfo::managedLayout(core, parent))
472 if (pl->indexOf(w) < 0 || !core->metaDataBase()->item(pl))
475 const QDesignerWidgetDataBaseInterface *wdb = core->widgetDataBase();
476 const int wdbindex = wdb->indexOfObject(w);
479 const bool isContainer = wdb->item(wdbindex)->isContainer();
483 const QWidgetList pages = childContainers(core, w);
484 const auto pageCount = pages.size();
485 if (ptrToChildContainerCount)
486 *ptrToChildContainerCount = pageCount;
488 for (qsizetype i = 0; i < pageCount; ++i)
489 if (QLayout *cl = pages.at(i)->layout())
490 if (!core->metaDataBase()->item(cl))
498 int childContainerCount;
500 if (!canMorph(fw, w, &childContainerCount, &cat))
501 return QStringList();
503 QStringList rc = classesOfCategory(cat);
506 case MorphSimpleContainer:
507 rc += classesOfCategory(MorphPageContainer);
511 case MorphPageContainer:
512 if (childContainerCount == 1)
513 rc += classesOfCategory(MorphSimpleContainer);
Auxiliary methods to store/retrieve settings.
static QStringList classesOfCategory(MorphCategory cat)
static QString suggestObjectName(const QString &oldClassName, const QString &newClassName, const QString &oldName)
QLabel * buddyLabelOf(QDesignerFormWindowInterface *fw, QWidget *w)
static QWidgetList childContainers(const QDesignerFormEditorInterface *core, QWidget *w)
static MorphCategory category(const QWidget *w)
static void replaceWidgetListDynamicProperty(QWidget *parentWidget, QWidget *oldWidget, QWidget *newWidget, const char *name)