13#include <QtDesigner/qextensionmanager.h>
14#include <QtDesigner/container.h>
15#include <QtDesigner/abstractformwindow.h>
16#include <QtDesigner/abstractformeditor.h>
17#include <QtDesigner/abstractlanguage.h>
18#include <QtDesigner/abstractwidgetdatabase.h>
19#include <QtDesigner/abstractmetadatabase.h>
20#include <QtDesigner/propertysheet.h>
22#include <QtWidgets/qwidget.h>
23#include <QtWidgets/qmenu.h>
24#include <QtWidgets/qapplication.h>
25#include <QtWidgets/qlayout.h>
26#include <QtGui/qundostack.h>
27#include <QtWidgets/qsplitter.h>
29#include <QtWidgets/qframe.h>
30#include <QtWidgets/qgroupbox.h>
31#include <QtWidgets/qtabwidget.h>
32#include <QtWidgets/qstackedwidget.h>
33#include <QtWidgets/qtoolbox.h>
34#include <QtWidgets/qabstractitemview.h>
35#include <QtWidgets/qabstractbutton.h>
36#include <QtWidgets/qabstractspinbox.h>
37#include <QtWidgets/qtextedit.h>
38#include <QtWidgets/qplaintextedit.h>
39#include <QtWidgets/qlabel.h>
41#include <QtGui/qaction.h>
43#include <QtCore/qstringlist.h>
44#include <QtCore/qmap.h>
45#include <QtCore/qvariant.h>
46#include <QtCore/qdebug.h>
48Q_DECLARE_METATYPE(QWidgetList)
52using namespace Qt::StringLiterals;
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
91
104 const QMetaObject *mo = w->metaObject();
105 if (mo == &QWidget::staticMetaObject || mo == &QFrame::staticMetaObject || mo == &QGroupBox::staticMetaObject || mo == &QLayoutWidget::staticMetaObject)
107 if (mo == &QTabWidget::staticMetaObject || mo == &QStackedWidget::staticMetaObject || mo == &QToolBox::staticMetaObject)
109 if (qobject_cast<
const QAbstractItemView*>(w))
111 if (qobject_cast<
const QAbstractButton *>(w))
113 if (qobject_cast<
const QAbstractSpinBox *>(w))
115 if (qobject_cast<
const QPlainTextEdit *>(w) || qobject_cast<
const QTextEdit*>(w))
122
123
124
128 static QMap<MorphCategory, QStringList> candidateCache;
129 auto it = candidateCache.find(cat);
130 if (it == candidateCache.end()) {
131 it = candidateCache.insert(cat, QStringList());
132 QStringList &l = it.value();
136 case MorphSimpleContainer:
139 l << u"QWidget"_s << u"QFrame"_s << u"QGroupBox"_s;
141 case MorphPageContainer:
142 l << u"QTabWidget"_s << u"QStackedWidget"_s << u"QToolBox"_s;
145 l << u"QListView"_s << u"QListWidget"_s
146 << u"QTreeView"_s << u"QTreeWidget"_s
147 << u"QTableView"_s << u"QTableWidget"_s
151 l << u"QCheckBox"_s << u"QRadioButton"_s
152 << u"QPushButton"_s << u"QToolButton"_s
153 << u"QCommandLinkButton"_s;
156 l << u"QDateTimeEdit"_s << u"QDateEdit"_s
158 << u"QSpinBox"_s << u"QDoubleSpinBox"_s;
161 l << u"QTextEdit"_s << u"QPlainTextEdit"_s << u"QTextBrowser"_s;
172 if (
const QDesignerContainerExtension *ce = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), w)) {
173 QWidgetList children;
174 if (
const int count = ce->count()) {
175 for (
int i = 0; i < count; i++)
176 children.push_back(ce->widget(i));
187static QString
suggestObjectName(
const QString &oldClassName,
const QString &newClassName,
const QString &oldName)
189 QString oldClassPart = oldClassName;
190 QString newClassPart = newClassName;
191 if (oldClassPart.startsWith(u'Q'))
192 oldClassPart.remove(0, 1);
193 if (newClassPart.startsWith(u'Q'))
194 newClassPart.remove(0, 1);
196 QString newName = oldName;
197 newName.replace(oldClassPart, newClassPart);
198 oldClassPart[0] = oldClassPart.at(0).toLower();
199 newClassPart[0] = newClassPart.at(0).toLower();
200 newName.replace(oldClassPart, newClassPart);
207 const auto labelList = fw->findChildren<QLabel*>();
208 for (QLabel *label : labelList)
209 if (label->buddy() == w)
220 QWidgetList list = qvariant_cast<QWidgetList>(parentWidget->property(name));
221 const int index = list.indexOf(oldWidget);
223 list.replace(index, newWidget);
224 parentWidget->setProperty(name, QVariant::fromValue(list));
229
230
252 static bool canMorph(QDesignerFormWindowInterface *fw,
QWidget *w,
int *childContainerCount =
nullptr,
MorphCategory *cat =
nullptr);
263 qWarning(
"*** Unable to create a MorphWidgetCommand");
267 QLabel *buddyLabel = buddyLabelOf(fw, w);
269 QUndoStack *us = fw->commandHistory();
270 us->beginMacro(morphCmd->text());
272 if (FormWindowBase *fwb = qobject_cast<FormWindowBase*>(fw))
273 fwb->emitWidgetRemoved(w);
275 const QString newWidgetName = morphCmd->newWidgetName();
280 SetPropertyCommand *buddyCmd =
new SetPropertyCommand(fw);
281 buddyCmd->init(buddyLabel, u"buddy"_s, QVariant(newWidgetName.toUtf8()));
289 QDesignerFormWindowCommand(QString(), formWindow),
290 m_beforeWidget(
nullptr),
291 m_afterWidget(
nullptr)
299 QDesignerFormWindowInterface *fw = formWindow();
300 QDesignerFormEditorInterface *core = fw->core();
302 if (!canMorph(fw, widget))
305 const QString oldClassName = WidgetFactory::classNameOf(core, widget);
306 const QString oldName = widget->objectName();
308 setText(QApplication::translate(
"Command",
"Morph %1/'%2' into %3").arg(oldClassName, oldName, newClassName));
310 m_beforeWidget = widget;
311 m_afterWidget = core->widgetFactory()->createWidget(newClassName, fw);
316 m_afterWidget->setObjectName(suggestObjectName(oldClassName, newClassName, oldName));
320 if (QDesignerContainerExtension* c = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), m_afterWidget)) {
321 if (
const auto pageCount = childContainers(core, m_beforeWidget).size()) {
322 const QString containerName = m_afterWidget->objectName();
323 for (qsizetype i = 0; i < pageCount; ++i) {
324 QString name = containerName;
326 name += QString::number(i + 1);
327 QWidget *page = core->widgetFactory()->createWidget(u"QWidget"_s);
328 page->setObjectName(name);
329 fw->ensureUniqueObjectName(page);
331 core->metaDataBase()->add(page);
339 const int count = beforeSheet->count();
340 for (
int i = 0; i < count; i++)
341 if (beforeSheet->isVisible(i) && beforeSheet->isChanged(i)) {
342 const QString name = beforeSheet->propertyName(i);
343 if (name !=
"objectName"_L1) {
344 const int afterIndex = afterSheet->indexOf(name);
345 if (afterIndex != -1 && afterSheet->isVisible(afterIndex) && afterSheet->propertyGroup(afterIndex) == beforeSheet->propertyGroup(i)) {
346 afterSheet->setProperty(i, beforeSheet->property(i));
347 afterSheet->setChanged(i,
true);
359 morph(m_beforeWidget, m_afterWidget);
364 morph(m_afterWidget, m_beforeWidget);
369 QDesignerFormWindowInterface *fw = formWindow();
371 fw->unmanageWidget(before);
373 const QRect oldGeom = before->geometry();
374 QWidget *parent = before->parentWidget();
377
378
381 QWidgetList beforeChildContainers = childContainers(fw->core(), before);
382 QWidgetList afterChildContainers = childContainers(fw->core(), after);
383 Q_ASSERT(beforeChildContainers.size() == afterChildContainers.size());
384 const auto childContainerCount = beforeChildContainers.size();
385 for (qsizetype i = 0; i < childContainerCount; ++i) {
386 QWidget *beforeChildContainer = beforeChildContainers.at(i);
387 QWidget *afterChildContainer = afterChildContainers.at(i);
388 if (QLayout *childLayout = beforeChildContainer->layout()) {
390 afterChildContainer->setLayout(childLayout);
393 for (QObject *o : beforeChildContainer->children()) {
394 if (o->isWidgetType()) {
395 QWidget *w =
static_cast<QWidget*>(o);
396 if (fw->isManaged(w)) {
397 const QRect geom = w->geometry();
398 w->setParent(afterChildContainer);
399 w->setGeometry(geom);
409 after->setGeometry(oldGeom);
410 if (QLayout *containingLayout = LayoutInfo::managedLayout(fw->core(), parent)) {
413 lh->replaceWidget(containingLayout, before, after);
415 }
else if (QSplitter *splitter = qobject_cast<QSplitter *>(parent)) {
416 const int index = splitter->indexOf(before);
418 before->setParent(
nullptr);
419 splitter->insertWidget(index, after);
420 after->setParent(parent);
421 after->setGeometry(oldGeom);
424 before->setParent(
nullptr);
425 after->setParent(parent);
426 after->setGeometry(oldGeom);
433 QDesignerMetaDataBaseItemInterface *formItem = fw->core()->metaDataBase()->item(fw);
434 QWidgetList tabOrder = formItem->tabOrder();
435 const int tabIndex = tabOrder.indexOf(before);
436 if (tabIndex != -1) {
437 tabOrder.replace(tabIndex, after);
438 formItem->setTabOrder(tabOrder);
442 fw->manageWidget(after);
444 fw->clearSelection(
false);
445 fw->selectWidget(after);
449
450
453 if (ptrToChildContainerCount)
454 *ptrToChildContainerCount = 0;
461 QDesignerFormEditorInterface *core = fw->core();
463 if (qt_extension<QDesignerLanguageExtension *>(core->extensionManager(), core))
465 if (!fw->isManaged(w) || w == fw->mainContainer())
469 QWidget *parent = w->parentWidget();
470 if (parent ==
nullptr)
472 if (QLayout *pl = LayoutInfo::managedLayout(core, parent))
473 if (pl->indexOf(w) < 0 || !core->metaDataBase()->item(pl))
476 const QDesignerWidgetDataBaseInterface *wdb = core->widgetDataBase();
477 const int wdbindex = wdb->indexOfObject(w);
480 const bool isContainer = wdb->item(wdbindex)->isContainer();
484 const QWidgetList pages = childContainers(core, w);
485 const auto pageCount = pages.size();
486 if (ptrToChildContainerCount)
487 *ptrToChildContainerCount = pageCount;
489 for (qsizetype i = 0; i < pageCount; ++i)
490 if (QLayout *cl = pages.at(i)->layout())
491 if (!core->metaDataBase()->item(cl))
499 int childContainerCount;
501 if (!canMorph(fw, w, &childContainerCount, &cat))
502 return QStringList();
504 QStringList rc = classesOfCategory(cat);
507 case MorphSimpleContainer:
508 rc += classesOfCategory(MorphPageContainer);
512 case MorphPageContainer:
513 if (childContainerCount == 1)
514 rc += classesOfCategory(MorphSimpleContainer);
static LayoutHelper * createLayoutHelper(int type)
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)