16#include <metadatabase_p.h>
17#include <qdesigner_tabwidget_p.h>
18#include <qdesigner_toolbox_p.h>
19#include <qdesigner_stackedbox_p.h>
20#include <qdesigner_resource.h>
21#include <qdesigner_command_p.h>
22#include <qdesigner_command2_p.h>
23#include <qdesigner_propertycommand_p.h>
24#include <qdesigner_taskmenu_p.h>
25#include <qdesigner_widget_p.h>
26#include <qdesigner_utils_p.h>
27#include <qlayout_widget_p.h>
28#include <spacer_widget_p.h>
29#include <invisible_widget_p.h>
30#include <layoutinfo_p.h>
31#include <qdesigner_objectinspector_p.h>
32#include <connectionedit_p.h>
33#include <actionprovider_p.h>
34#include <private/ui4_p.h>
35#include <deviceprofile_p.h>
36#include <shared_settings_p.h>
39#include <QtDesigner/qextensionmanager.h>
40#include <QtDesigner/abstractwidgetdatabase.h>
41#include <QtDesigner/propertysheet.h>
42#include <QtDesigner/abstractwidgetfactory.h>
43#include <QtDesigner/container.h>
44#include <QtDesigner/taskmenu.h>
45#include <QtDesigner/abstractwidgetbox.h>
46#include <QtDesigner/private/ui4_p.h>
48#include <abstractdialoggui_p.h>
50#include <QtWidgets/qmenu.h>
51#include <QtWidgets/qscrollarea.h>
52#include <QtWidgets/qrubberband.h>
53#include <QtWidgets/qapplication.h>
54#include <QtWidgets/qsplitter.h>
55#include <QtWidgets/qgroupbox.h>
56#include <QtWidgets/qdockwidget.h>
57#include <QtWidgets/qtoolbox.h>
58#include <QtWidgets/qstackedwidget.h>
59#include <QtWidgets/qtabwidget.h>
60#include <QtWidgets/qbuttongroup.h>
62#include <QtGui/qaction.h>
63#include <QtGui/qactiongroup.h>
64#if QT_CONFIG(clipboard)
65# include <QtGui/qclipboard.h>
67#include <QtGui/qpainter.h>
68#include <QtGui/qundogroup.h>
70#include <QtCore/qdebug.h>
71#include <QtCore/qbuffer.h>
72#include <QtCore/qtimer.h>
73#include <QtCore/qlist.h>
74#include <QtCore/qxmlstream.h>
76Q_DECLARE_METATYPE(QWidget*)
80using namespace Qt::StringLiterals;
85 Q_DISABLE_COPY_MOVE(BlockSelection)
87 BlockSelection(qdesigner_internal::FormWindow *fw)
89 m_blocked(m_formWindow->blockSelectionChanged(
true))
96 m_formWindow->blockSelectionChanged(m_blocked);
100 QPointer<qdesigner_internal::FormWindow> m_formWindow;
101 const bool m_blocked;
104enum { debugFormWindow = 0 };
146 SelectionPool m_selectionPool;
148 QHash<QWidget *, WidgetSelection *> m_usedSelections;
160 if (!m_usedSelections.isEmpty()) {
161 for (
auto it = m_usedSelections.begin(), mend = m_usedSelections.end(); it != mend; ++it)
162 it.value()->setWidget(
nullptr);
163 m_usedSelections.clear();
170 qDeleteAll(m_selectionPool);
171 m_selectionPool.clear();
183 for (
auto *s : std::as_const(m_selectionPool)) {
191 rc =
new WidgetSelection(fw);
192 m_selectionPool.push_back(rc);
195 m_usedSelections.insert(w, rc);
207 m_usedSelections.remove(w);
209 if (m_usedSelections.isEmpty())
212 return (*m_usedSelections.begin())->widget();
223 for (
auto it = m_usedSelections.begin(), mend = m_usedSelections.end(); it != mend; ++it)
224 it.value()->update();
228 return m_usedSelections.contains(w);
233 return m_usedSelections.keys();
238 for (
auto it = m_usedSelections.constBegin(), mend = m_usedSelections.constEnd(); it != mend; ++it) {
273 m_mouseState(NoMouseState),
280 deviceProfile().apply(core, m_widgetStack->formContainer(), qdesigner_internal::DeviceProfile::ApplyFormParent);
282 setLayout(m_widgetStack->layout());
285 m_cursor =
new FormWindowCursor(
this,
this);
287 core->formWindowManager()->addFormWindow(
this);
290 setAcceptDrops(
true);
295 Q_ASSERT(core() !=
nullptr);
296 Q_ASSERT(core()->metaDataBase() !=
nullptr);
297 Q_ASSERT(core()->formWindowManager() !=
nullptr);
299 core()->formWindowManager()->removeFormWindow(
this);
300 core()->metaDataBase()->remove(
this);
302 const QWidgetList &l = widgets();
304 core()->metaDataBase()->remove(w);
306 m_widgetStack =
nullptr;
307 m_rubberBand =
nullptr;
309 core()->resourceModel()->removeResourceSet(resourceSet());
312 if (FormWindowManager *manager = qobject_cast<FormWindowManager*> (core()->formWindowManager()))
313 manager->undoGroup()->removeStack(&m_undoStack);
314 m_undoStack.disconnect();
329 if (!m_mainContainer)
336 while (w && !w->isWindow()) {
338 w = w->parentWidget();
349 c = c->parentWidget();
358 const QWidgetList widgets = start->findChildren<QWidget*>();
359 for (QWidget *widget : widgets) {
360 if (!qobject_cast<WidgetHandle*>(widget)) {
361 widget->setCursor(c);
369 if (
FormWindowManager *manager = qobject_cast<FormWindowManager*> (core()->formWindowManager())) {
370 manager->undoGroup()->addStack(&m_undoStack);
373 m_blockSelectionChanged =
false;
375 m_defaultMargin = INT_MIN;
376 m_defaultSpacing = INT_MIN;
378 connect(m_widgetStack, &FormWindowWidgetStack::currentToolChanged,
379 this, &QDesignerFormWindowInterface::toolChanged);
381 m_selectionChangedTimer =
new QTimer(
this);
382 m_selectionChangedTimer->setSingleShot(
true);
383 connect(m_selectionChangedTimer, &QTimer::timeout,
this,
384 &FormWindow::selectionChangedTimerDone);
386 m_checkSelectionTimer =
new QTimer(
this);
387 m_checkSelectionTimer->setSingleShot(
true);
388 connect(m_checkSelectionTimer, &QTimer::timeout,
389 this, &FormWindow::checkSelectionNow);
391 m_geometryChangedTimer =
new QTimer(
this);
392 m_geometryChangedTimer->setSingleShot(
true);
393 connect(m_geometryChangedTimer, &QTimer::timeout,
394 this, &QDesignerFormWindowInterface::geometryChanged);
396 m_rubberBand =
nullptr;
398 setFocusPolicy(Qt::StrongFocus);
400 m_mainContainer =
nullptr;
401 m_currentWidget =
nullptr;
403 connect(&m_undoStack, &QUndoStack::indexChanged,
404 this, &QDesignerFormWindowInterface::changed);
405 connect(&m_undoStack, &QUndoStack::cleanChanged,
406 this, &FormWindow::slotCleanChanged);
407 connect(
this, &QDesignerFormWindowInterface::changed,
408 this, &FormWindow::checkSelection);
410 core()->metaDataBase()->add(
this);
412 initializeCoreTools();
414 QAction *a =
new QAction(
this);
415 a->setText(tr(
"Edit contents"));
416 a->setShortcut(tr(
"F2"));
417 connect(a, &QAction::triggered,
this, &FormWindow::editContents);
423 return m_mainContainer;
429 if (m_mainContainer) {
432 core()->metaDataBase()->remove(m_mainContainer);
434 delete m_mainContainer;
435 m_mainContainer =
nullptr;
441 if (w == m_mainContainer) {
446 clearMainContainer();
449 const QSize sz = m_mainContainer->size();
452 m_widgetStack->setCurrentTool(m_widgetEditor);
454 setCurrentWidget(m_mainContainer);
458 sheet->setVisible(sheet->indexOf(u"windowTitle"_s),
true);
459 sheet->setVisible(sheet->indexOf(u"windowIcon"_s),
true);
460 sheet->setVisible(sheet->indexOf(u"windowModality"_s),
true);
461 sheet->setVisible(sheet->indexOf(u"windowOpacity"_s),
true);
462 sheet->setVisible(sheet->indexOf(u"windowFilePath"_s),
true);
466 m_mainContainer->setFocusPolicy(Qt::StrongFocus);
467 m_mainContainer->resize(sz);
469 emit mainContainerChanged(m_mainContainer);
476 while (
QWidget *parentWidget = widget->parentWidget()) {
477 if (LayoutInfo::layoutType(m_core, parentWidget) == LayoutInfo::NoLayout && isManaged(widget))
480 widget = parentWidget;
488 if (QDesignerObjectInspector *oi = qobject_cast<QDesignerObjectInspector *>(core->objectInspector()))
489 oi->clearSelection();
495 const QDesignerFormWindowCursorInterface *cursor = fw->cursor();
496 QWidget *mainContainer = fw->mainContainer();
497 for (
QWidget *p = w->parentWidget(); p && p != mainContainer; p = p->parentWidget())
498 if (fw->isManaged(p))
499 if (cursor->isWidgetSelected(p) == selected)
511 case Qt::ShiftModifier:
515 case Qt::AltModifier:
516 return CopyDragModifier;
518 case Qt::ControlModifier:
531 const bool sameWidget = managedWidget == m_lastClickedWidget;
532 m_lastClickedWidget = managedWidget;
536 qDebug() <<
"handleClickSelection" << managedWidget <<
" same=" << sameWidget <<
" mouse= " << mouseMode <<
" selected=" << selected;
544 QWidget *selectionCandidate =
nullptr;
548 if (
QWidget *currentlySelectedParent = selected ? managedWidget : findSelectedParent(
this, managedWidget,
true))
549 selectionCandidate = findSelectedParent(
this, currentlySelectedParent,
false);
551 if (!selectionCandidate && !selected)
552 selectionCandidate = managedWidget;
554 if (selectionCandidate)
555 selectSingleWidget(selectionCandidate);
567 m_mouseState = NoMouseState;
568 m_startPos = QPoint();
571 BlockSelection blocker(
this);
573 if (core()->formWindowManager()->activeFormWindow() !=
this)
574 core()->formWindowManager()->setActiveFormWindow(
this);
576 const Qt::MouseButtons buttons = e->buttons();
577 if (buttons != Qt::LeftButton && buttons != Qt::MiddleButton)
580 m_startPos = mapFromGlobal(e->globalPosition().toPoint());
583 qDebug() <<
"handleMousePressEvent:" << widget <<
',' << managedWidget;
585 if (buttons == Qt::MiddleButton || isMainContainer(managedWidget)) {
586 clearObjectInspectorSelection(m_core);
589 m_mouseState = MouseDrawRubber;
590 m_currRect = QRect();
591 startRectDraw(mapFromGlobal(e->globalPosition().toPoint()),
this, Rubber);
594 if (buttons != Qt::LeftButton)
597 const unsigned mouseMode = mouseFlags(e->modifiers());
600
601
602
603
604
605
606
607 const bool deferSelection =
isWidgetSelected(managedWidget
) || findSelectedParent(
this, managedWidget,
true);
608 if (deferSelection) {
609 m_mouseState = MouseDeferredSelection;
613 handleClickSelection(managedWidget, effectiveMouseMode);
622 const LayoutInfo::Type type = LayoutInfo::laidoutWidgetType(core ,w, &managed);
626 case LayoutInfo::NoLayout:
627 case LayoutInfo::HSplitter:
628 case LayoutInfo::VSplitter:
639 if (m_startPos.isNull())
642 const QPoint pos = mapFromGlobal(e->globalPosition().toPoint());
644 switch (m_mouseState) {
645 case MouseDrawRubber:
646 continueRectDraw(pos,
this, Rubber);
654 if (e->buttons() != Qt::LeftButton)
657 const bool canStartDrag = (m_startPos - pos).manhattanLength() > QApplication::startDragDistance();
662 m_mouseState = MouseMoveDrag;
665 QWidgetList sel = selectedWidgets();
666 const QWidgetList originalSelection = sel;
667 simplifySelection(&sel);
669 QSet<QWidget*> widget_set;
671 for (QWidget *child : std::as_const(sel)) {
672 QWidget *current = child;
675 while (!isMainContainer(current) && !done) {
676 if (!isManaged(current)) {
677 current = current->parentWidget();
680 if (LayoutInfo::isWidgetLaidout(core(), current)) {
682 if (!canDragWidgetInLayout(core(), current)) {
683 current = current->parentWidget();
690 if (current == mainContainer())
693 widget_set.insert(current);
696 sel = widget_set.values();
697 QDesignerFormWindowCursorInterface *c = cursor();
698 QWidget *current = c->current();
699 if (sel.contains(current)) {
700 sel.removeAll(current);
701 sel.prepend(current);
704 QList<QDesignerDnDItemInterface*> item_list;
705 const QPoint globalPos = mapToGlobal(m_startPos);
706 const QDesignerDnDItemInterface::DropType dropType = (mouseFlags(e->modifiers()) & CopyDragModifier) ?
707 QDesignerDnDItemInterface::CopyDrop : QDesignerDnDItemInterface::MoveDrop;
708 for (QWidget *widget : std::as_const(sel)) {
709 item_list.append(
new FormWindowDnDItem(dropType,
this, widget, globalPos));
710 if (dropType == QDesignerDnDItemInterface::MoveDrop) {
711 m_selection->hide(widget);
718 for (
auto *widget : originalSelection)
719 m_selection->hide(widget);
724 if (QDesignerMimeData::execDrag(item_list, core()->topLevel()) == Qt::IgnoreAction && dropType == QDesignerDnDItemInterface::MoveDrop)
725 for (QWidget *widget : std::as_const(sel))
726 m_selection->show(widget);
728 m_startPos = QPoint();
735 const MouseState oldState = m_mouseState;
736 m_mouseState = NoMouseState;
739 qDebug() <<
"handleMouseeleaseEvent:" << w <<
',' << mw <<
"state=" << oldState;
741 if (oldState == MouseDoubleClicked)
747 case MouseDrawRubber: {
755 case MouseDeferredSelection:
756 handleClickSelection(mw, mouseFlags(e->modifiers()));
762 m_startPos = QPoint();
765
766
767 switch (e->button()) {
769 case Qt::MiddleButton:
770 case Qt::RightButton:
780void FormWindow::checkPreviewGeometry(QRect &r)
782 if (!rect().contains(r)) {
783 if (r.left() < rect().left())
784 r.moveTopLeft(QPoint(0, r.top()));
785 if (r.right() > rect().right())
786 r.moveBottomRight(QPoint(rect().right(), r.bottom()));
787 if (r.top() < rect().top())
788 r.moveTopLeft(QPoint(r.left(), rect().top()));
789 if (r.bottom() > rect().bottom())
790 r.moveBottomRight(QPoint(r.right(), rect().bottom()));
796 m_rectAnchor = (t == Insert) ? designerGrid().snapPoint(pos) : pos;
798 m_currRect = QRect(m_rectAnchor, QSize(0, 0));
800 m_rubberBand =
new QRubberBand(QRubberBand::Rectangle,
this);
801 m_rubberBand->setGeometry(m_currRect);
802 m_rubberBand->show();
807 const QPoint p2 = (t == Insert) ? designerGrid().snapPoint(pos) : pos;
809 QRect r(m_rectAnchor, p2);
815 if (r.width() > 1 || r.height() > 1) {
818 m_rubberBand->setGeometry(m_currRect);
826 m_rubberBand =
nullptr;
832 return m_currentWidget;
838 qDebug() <<
"setCurrentWidget:" << m_currentWidget <<
" --> " << currentWidget;
839 if (currentWidget == m_currentWidget)
846 m_currentWidget = currentWidget;
855 if (trySelectWidget(w, select))
863 qDebug() <<
"trySelectWidget:" << w << select;
885 setCurrentWidget(newCurrent);
893 qDebug() <<
"clearSelection(" << changePropertyDisplay <<
')';
898 if (changePropertyDisplay)
904 if (m_blockSelectionChanged)
907 m_selectionChangedTimer->start(0);
912 emit selectionChanged();
927 const QWidgetList l = w->findChildren<QWidget*>();
946 if (!w->isVisibleTo(
this)) {
956 w = w->parentWidget();
963 if (QMainWindow *mainWindow = qobject_cast<QMainWindow*>(
mainContainer()))
964 return w == mainWindow->centralWidget();
971 QString name = object->objectName();
972 if (name.isEmpty()) {
973 QDesignerWidgetDataBaseInterface *db = core()->widgetDataBase();
974 if (QDesignerWidgetDataBaseItemInterface *item = db->item(db->indexOfObject(object)))
975 name = qdesigner_internal::qtify(item->name());
977 unify(object, name,
true);
978 object->setObjectName(name);
981template <
class Iterator>
982static inline void insertNames(
const QDesignerMetaDataBaseInterface *metaDataBase,
983 Iterator it,
const Iterator &end,
984 QObject *excludedObject, QSet<QString> &nameSet)
986 for ( ; it != end; ++it)
987 if (excludedObject != *it && metaDataBase->item(*it))
988 nameSet.insert((*it)->objectName());
993 static const QSet<QString> keywords = {
1039 u"reinterpret_cast"_s,
1090 using StringSet = QSet<QString>;
1096 StringSet existingNames = languageKeywords();
1099 existingNames.insert(main->objectName());
1101 const QDesignerMetaDataBaseInterface *metaDataBase = core()->metaDataBase();
1102 const QWidgetList widgetChildren = main->findChildren<QWidget*>();
1103 if (!widgetChildren.isEmpty())
1104 insertNames(metaDataBase, widgetChildren.constBegin(), widgetChildren.constEnd(), w, existingNames);
1106 const auto layoutChildren = main->findChildren<QLayout*>();
1107 if (!layoutChildren.isEmpty())
1108 insertNames(metaDataBase, layoutChildren.constBegin(), layoutChildren.constEnd(), w, existingNames);
1110 const auto actionChildren = main->findChildren<QAction*>();
1111 if (!actionChildren.isEmpty())
1112 insertNames(metaDataBase, actionChildren.constBegin(), actionChildren.constEnd(), w, existingNames);
1114 const auto buttonGroupChildren = main->findChildren<QButtonGroup*>();
1115 if (!buttonGroupChildren.isEmpty())
1116 insertNames(metaDataBase, buttonGroupChildren.constBegin(), buttonGroupChildren.constEnd(), w, existingNames);
1118 if (!existingNames.contains(s))
1125 qlonglong factor = 1;
1126 qsizetype idx = s.size() - 1;
1127 const char16_t zeroUnicode = u'0';
1128 for ( ; idx > 0 && s.at(idx).isDigit(); --idx) {
1129 num += (s.at(idx).unicode() - zeroUnicode) * factor;
1133 const QChar underscore = u'_';
1134 if (idx >= 0 && s.at(idx) == underscore) {
1142 for (num++ ; ;num++) {
1144 s += QString::number(num);
1145 if (!existingNames.contains(s))
1151
1157 beginCommand(tr(
"Insert widget '%1'").arg(WidgetFactory::classNameOf(m_core, w)));
1160
1161
1163 Q_ASSERT(r.isValid());
1164 SetPropertyCommand *geom_cmd =
new SetPropertyCommand(
this);
1165 geom_cmd->init(w, u"geometry"_s, r);
1167 if (w->parentWidget() != container) {
1168 ReparentWidgetCommand *cmd =
new ReparentWidgetCommand(
this);
1169 cmd->init(w, container);
1170 m_undoStack.push(cmd);
1173 m_undoStack.push(geom_cmd);
1175 QUndoCommand *cmd =
nullptr;
1176 if (
auto dockWidget = qobject_cast<QDockWidget *>(w)) {
1177 if (
auto mainWindow = qobject_cast<QMainWindow *>(container)) {
1178 auto addDockCmd =
new AddDockWidgetCommand(
this);
1179 addDockCmd->init(mainWindow, dockWidget);
1183 if (cmd ==
nullptr) {
1184 auto insertCmd =
new InsertWidgetCommand(
this);
1185 insertCmd->init(w, already_in_form);
1188 m_undoStack.push(cmd);
1201 if (QMainWindow *mw = qobject_cast<QMainWindow*>(container)) {
1202 Q_ASSERT(mw->centralWidget() !=
nullptr);
1203 container = mw->centralWidget();
1207 const FormBuilderClipboard clipboard = resource.paste(ui, container);
1208 if (clipboard.m_widgets.size() != 1)
1210 QWidget *widget = clipboard.m_widgets.first();
1211 insertWidget(widget, rc, container);
1217 for (; child !=
nullptr; child = child->parentWidget()) {
1218 if (child == parent)
1226 Q_ASSERT(isDescendant(
this, widget));
1229 SetPropertyCommand *cmd =
new SetPropertyCommand(
this);
1230 cmd->init(widget, u"geometry"_s, r);
1231 cmd->setText(tr(
"Resize"));
1232 m_undoStack.push(cmd);
1237 const QWidgetList l = w->findChildren<QWidget*>();
1240 m_selection->raiseList(l);
1247 const QWidgetList selected = selectedWidgets();
1248 if (rect().contains(mapFromGlobal(pos))) {
1250 depth = widgetDepth(container);
1253 for (QWidget *wit : std::as_const(m_widgets)) {
1254 if (qobject_cast<QLayoutWidget*>(wit) || qobject_cast<QSplitter*>(wit))
1256 if (!wit->isVisibleTo(
this))
1258 if (selected.indexOf(wit) != -1)
1260 if (!core()->widgetDataBase()->isContainer(wit) &&
1261 wit != mainContainer())
1266 while (w && !w->isWindow()) {
1267 if (!w->rect().contains((w->mapFromGlobal(pos))))
1269 w = w->parentWidget();
1271 if (!(w ==
nullptr || w->isWindow()))
1274 int wd = widgetDepth(wit);
1275 if (wd == depth && container) {
1276 if (wit->parentWidget()->children().indexOf(wit) >
1277 container->parentWidget()->children().indexOf(container))
1280 if (wd > depth && !isChildOf(wit, notParentOf)) {
1290 return m_selection->selectedWidgets();
1295 bool selectionChanged =
false;
1296 const QWidgetList l = mainContainer()->findChildren<QWidget*>();
1297 const QRect selRect(mapToGlobal(m_currRect.topLeft()), m_currRect.size());
1298 for (QWidget *w : l) {
1299 if (w->isVisibleTo(
this) && isManaged(w)) {
1300 const QPoint p = w->mapToGlobal(QPoint(0,0));
1301 const QRect r(p, w->size());
1302 if (r.intersects(selRect) && !r.contains(selRect) && trySelectWidget(w,
true))
1303 selectionChanged =
true;
1307 if (selectionChanged)
1313 if (qobject_cast<
const FormWindow*>(widget) || qobject_cast<
const QMenu*>(widget))
1321 case Qt::Key_Delete:
1322 case Qt::Key_Backspace:
1323 if (e->modifiers() == Qt::NoModifier)
1328 if (e->modifiers() == Qt::NoModifier)
1329 cursor()->movePosition(QDesignerFormWindowCursorInterface::Next);
1332 case Qt::Key_Backtab:
1333 if (e->modifiers() == Qt::NoModifier)
1334 cursor()->movePosition(QDesignerFormWindowCursorInterface::Prev);
1341 handleArrowKeyEvent(e->key(), e->modifiers());
1348int FormWindow::getValue(QRect rect,
int key,
bool size)
const
1351 if (key == Qt::Key_Left || key == Qt::Key_Right)
1352 return rect.width();
1353 return rect.height();
1355 if (key == Qt::Key_Left || key == Qt::Key_Right)
1360int FormWindow::calcValue(
int val,
bool forward,
bool snap,
int snapOffset)
const
1363 const int rest = val % snapOffset;
1365 const int offset = forward ? snapOffset : 0;
1366 const int newOffset = rest < 0 ? offset - snapOffset : offset;
1367 return val + newOffset - rest;
1369 return (forward ? val + snapOffset : val - snapOffset);
1371 return (forward ? val + 1 : val - 1);
1388Q_DECLARE_METATYPE(qdesigner_internal::ArrowKeyOperation)
1391namespace qdesigner_internal {
1393QRect ArrowKeyOperation::apply(QRect rect)
const
1397 if (arrowKey == Qt::Key_Left || arrowKey == Qt::Key_Right)
1398 r.setWidth(r.width() + distance);
1400 r.setHeight(r.height() + distance);
1402 if (arrowKey == Qt::Key_Left || arrowKey == Qt::Key_Right)
1403 r.moveLeft(r.x() + distance);
1405 r.moveTop(r.y() + distance);
1410QDebug operator<<(QDebug in, ArrowKeyOperation op)
1412 in.nospace() <<
"Resize=" << op.resize <<
" dist=" << op.distance <<
" Key=" << op.arrowKey <<
' ';
1424class ArrowKeyPropertyHelper :
public PropertyHelper {
1426 ArrowKeyPropertyHelper(QObject* o, SpecialProperty sp,
1427 QDesignerPropertySheetExtension *s,
int i) :
1428 PropertyHelper(o, sp, s, i) {}
1430 Value setValue(QDesignerFormWindowInterface *fw,
const QVariant &value,
bool changed,
1431 quint64 subPropertyMask) override;
1434PropertyHelper::Value ArrowKeyPropertyHelper::setValue(QDesignerFormWindowInterface *fw,
const QVariant &value,
1435 bool changed, quint64 subPropertyMask)
1438 QWidget *w = qobject_cast<QWidget*>(object());
1439 const ArrowKeyOperation operation = qvariant_cast<ArrowKeyOperation>(value);
1440 const QRect newGeom = operation.apply(w->geometry());
1441 return PropertyHelper::setValue(fw, QVariant(newGeom), changed, subPropertyMask);
1447class ArrowKeyPropertyCommand:
public SetPropertyCommand {
1449 explicit ArrowKeyPropertyCommand(QDesignerFormWindowInterface *fw,
1450 QUndoCommand *p =
nullptr);
1452 void init(QWidgetList &l, ArrowKeyOperation op);
1455 std::unique_ptr<PropertyHelper>
1456 createPropertyHelper(QObject *o, SpecialProperty sp,
1457 QDesignerPropertySheetExtension *s,
int i)
const override
1458 {
return std::make_unique<ArrowKeyPropertyHelper>(o, sp, s, i); }
1459 QVariant mergeValue(
const QVariant &newValue) override;
1462ArrowKeyPropertyCommand::ArrowKeyPropertyCommand(QDesignerFormWindowInterface *fw,
1464 SetPropertyCommand(fw, p)
1466 static const int mid = qRegisterMetaType<qdesigner_internal::ArrowKeyOperation>();
1470void ArrowKeyPropertyCommand::init(QWidgetList &l, ArrowKeyOperation op)
1473 for (QWidget *w : std::as_const(l))
1475 SetPropertyCommand::init(ol, u"geometry"_s, QVariant::fromValue(op));
1477 setText(op.resize ? FormWindow::tr(
"Key Resize") : FormWindow::tr(
"Key Move"));
1480QVariant ArrowKeyPropertyCommand::mergeValue(
const QVariant &newMergeValue)
1483 if (!newMergeValue.canConvert<ArrowKeyOperation>())
1485 ArrowKeyOperation mergedOperation = qvariant_cast<ArrowKeyOperation>(newValue());
1486 const ArrowKeyOperation newMergeOperation = qvariant_cast<ArrowKeyOperation>(newMergeValue);
1487 if (mergedOperation.resize != newMergeOperation.resize || mergedOperation.arrowKey != newMergeOperation.arrowKey)
1489 mergedOperation.distance += newMergeOperation.distance;
1490 return QVariant::fromValue(mergedOperation);
1493void FormWindow::handleArrowKeyEvent(
int key, Qt::KeyboardModifiers modifiers)
1495 const QDesignerFormWindowCursorInterface *c = cursor();
1496 if (!c->hasSelection())
1499 QWidgetList selection;
1502 const int count = c->selectedWidgetCount();
1503 for (
int index = 0; index < count; ++index) {
1504 QWidget *w = c->selectedWidget(index);
1505 if (!LayoutInfo::isWidgetLaidout(m_core, w))
1506 selection.append(w);
1509 simplifySelection(&selection);
1511 if (selection.isEmpty())
1514 QWidget *current = c->current();
1515 if (!current || LayoutInfo::isWidgetLaidout(m_core, current)) {
1516 current = selection.first();
1519 const bool size = modifiers & Qt::ShiftModifier;
1521 const bool snap = !(modifiers & Qt::ControlModifier);
1522 const bool forward = (key == Qt::Key_Right || key == Qt::Key_Down);
1523 const int snapPoint = (key == Qt::Key_Left || key == Qt::Key_Right) ? grid().x() : grid().y();
1525 const int oldValue = getValue(current->geometry(), key, size);
1527 const int newValue = calcValue(oldValue, forward, snap, snapPoint);
1529 ArrowKeyOperation operation;
1530 operation.resize = modifiers & Qt::ShiftModifier;
1531 operation.distance = newValue - oldValue;
1532 operation.arrowKey = key;
1534 ArrowKeyPropertyCommand *cmd =
new ArrowKeyPropertyCommand(
this);
1535 cmd->init(selection, operation);
1536 m_undoStack.push(cmd);
1539bool FormWindow::handleKeyReleaseEvent(QWidget *, QWidget *, QKeyEvent *e)
1545void FormWindow::selectAll()
1547 bool selectionChanged =
false;
1548 for (QWidget *widget : std::as_const(m_widgets)) {
1549 if (widget->isVisibleTo(
this) && trySelectWidget(widget,
true))
1550 selectionChanged =
true;
1552 if (selectionChanged)
1553 emitSelectionChanged();
1556void FormWindow::createLayout(
int type, QWidget *container)
1559 layoutContainer(container, type);
1561 LayoutCommand *cmd =
new LayoutCommand(
this);
1562 cmd->init(mainContainer(), selectedWidgets(),
static_cast<LayoutInfo::Type>(type));
1563 commandHistory()->push(cmd);
1567void FormWindow::morphLayout(QWidget *container,
int newType)
1569 MorphLayoutCommand *cmd =
new MorphLayoutCommand(
this);
1570 if (cmd->init(container, newType)) {
1571 commandHistory()->push(cmd);
1573 qDebug() <<
"** WARNING Unable to morph layout.";
1578void FormWindow::deleteWidgets()
1580 QWidgetList selection = selectedWidgets();
1581 simplifySelection(&selection);
1583 deleteWidgetList(selection);
1586QString FormWindow::fileName()
const
1591void FormWindow::setFileName(
const QString &fileName)
1593 if (m_fileName == fileName)
1596 m_fileName = fileName;
1597 emit fileNameChanged(fileName);
1600QString FormWindow::contents()
const
1603 if (!mainContainer() || !b.open(QIODevice::WriteOnly))
1606 QDesignerResource resource(
const_cast<FormWindow*>(
this));
1607 resource.save(&b, mainContainer());
1609 return QString::fromUtf8(b.buffer());
1612#if QT_CONFIG(clipboard)
1613void FormWindow::copy()
1616 if (!b.open(QIODevice::WriteOnly))
1619 FormBuilderClipboard clipboard;
1620 QDesignerResource resource(
this);
1621 resource.setSaveRelative(
false);
1622 clipboard.m_widgets = selectedWidgets();
1623 simplifySelection(&clipboard.m_widgets);
1624 resource.copy(&b, clipboard);
1626 qApp->clipboard()->setText(QString::fromUtf8(b.buffer()), QClipboard::Clipboard);
1629void FormWindow::cut()
1635void FormWindow::paste()
1642QWidget *FormWindow::innerContainer(QWidget *outerContainer)
const
1644 if (m_core->widgetDataBase()->isContainer(outerContainer))
1645 if (
const QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(m_core->extensionManager(), outerContainer)) {
1646 const int currentIndex = container->currentIndex();
1647 return currentIndex >= 0 ? container->widget(currentIndex) :
nullptr;
1649 return outerContainer;
1652QWidget *FormWindow::containerForPaste()
const
1654 QWidget *w = mainContainer();
1660 QWidgetList selection = selectedWidgets();
1661 if (selection.isEmpty())
1663 simplifySelection(&selection);
1665 QWidget *containerOfW = findContainer(selection.first(),
true);
1666 if (!containerOfW || containerOfW == mainContainer())
1669 containerOfW = innerContainer(containerOfW);
1672 if (LayoutInfo::layoutType(m_core, containerOfW) != LayoutInfo::NoLayout || !m_core->widgetDataBase()->isContainer(containerOfW))
1679 w = innerContainer(w);
1682 if (LayoutInfo::layoutType(m_core, w) != LayoutInfo::NoLayout)
1685 w = m_core->widgetFactory()->containerOfWidget(w);
1686 if (w ==
nullptr || LayoutInfo::layoutType(m_core, w) != LayoutInfo::NoLayout)
1689 if (debugFormWindow)
1690 qDebug() <<
"containerForPaste() " << w;
1694#if QT_CONFIG(clipboard)
1696static inline DomUI *domUIFromClipboard(
int *widgetCount,
int *actionCount)
1698 *widgetCount = *actionCount = 0;
1699 const QString clipboardText = qApp->clipboard()->text();
1700 if (clipboardText.isEmpty() || clipboardText.indexOf(u'<') == -1)
1703 QXmlStreamReader reader(clipboardText);
1704 DomUI *ui =
nullptr;
1705 while (!reader.atEnd()) {
1706 if (reader.readNext() == QXmlStreamReader::StartElement) {
1707 if (reader.name().compare(
"ui"_L1, Qt::CaseInsensitive) == 0 && !ui) {
1712 reader.raiseError(QCoreApplication::translate(
"FormWindow",
"Unexpected element <%1>").arg(reader.name().toString()));
1715 if (reader.hasError()) {
1718 designerWarning(QCoreApplication::translate(
"FormWindow",
"Error while pasting clipboard contents at line %1, column %2: %3").
1719 arg(reader.lineNumber()).arg(reader.columnNumber()).arg(reader.errorString()));
1723 if (
const DomWidget *topLevel = ui->elementWidget()) {
1724 *widgetCount = topLevel->elementWidget().size();
1725 *actionCount = topLevel->elementAction().size();
1727 if (*widgetCount == 0 && *actionCount == 0) {
1735static inline QString pasteCommandDescription(
int widgetCount,
int actionCount)
1737 if (widgetCount == 0)
1738 return FormWindow::tr(
"Paste %n action(s)",
nullptr, actionCount);
1739 if (actionCount == 0)
1740 return FormWindow::tr(
"Paste %n widget(s)",
nullptr, widgetCount);
1741 return FormWindow::tr(
"Paste (%1 widgets, %2 actions)").arg(widgetCount).arg(actionCount);
1744#if QT_CONFIG(clipboard)
1745static void positionPastedWidgetsAtMousePosition(FormWindow *fw, QPoint contextMenuPosition, QWidget *parent,
const QWidgetList &l)
1750 QPoint currentPos = contextMenuPosition.x() >=0 ? parent->mapFrom(fw, contextMenuPosition) : parent->mapFromGlobal(QCursor::pos());
1751 const Grid &grid = fw->designerGrid();
1752 QPoint cursorPos = grid.snapPoint(currentPos);
1753 const QRect parentGeometry = QRect(QPoint(0, 0), parent->size());
1754 const bool outside = !parentGeometry.contains(cursorPos);
1756 cursorPos = grid.snapPoint(QPoint(0, 0));
1760 pasteArea = pasteArea.isNull() ? w->geometry() : pasteArea.united(w->geometry());
1765 const QPoint bottomRight = cursorPos + QPoint(pasteArea.width(), pasteArea.height()) - QPoint(1, 1);
1766 if (bottomRight.y() > parentGeometry.bottom() || parent->childAt(bottomRight) ==
nullptr)
1768 cursorPos += QPoint(grid.deltaX(), grid.deltaY());
1771 const QPoint offset = cursorPos - pasteArea.topLeft();
1773 w->move(w->pos() + offset);
1776void FormWindow::paste(PasteMode pasteMode)
1780 DomUI *ui =
nullptr;
1784 ui = domUIFromClipboard(&widgetCount, &actionCount);
1789 if (pasteMode == PasteActionsOnly)
1790 if (widgetCount != 0 || actionCount == 0)
1794 QWidget *pasteContainer = widgetCount ? containerForPaste() :
nullptr;
1795 if (widgetCount && pasteContainer ==
nullptr) {
1797 const QString message = tr(
"Cannot paste widgets. Designer could not find a container "
1798 "without a layout to paste into.");
1799 const QString infoMessage = tr(
"Break the layout of the "
1800 "container you want to paste into, select this container "
1801 "and then paste again.");
1802 core()->dialogGui()->message(
this, QDesignerDialogGuiInterface::FormEditorMessage, QMessageBox::Information,
1803 tr(
"Paste error"), message, infoMessage, QMessageBox::Ok);
1807 QDesignerResource resource(
this);
1811 const FormBuilderClipboard clipboard = resource.paste(ui, pasteContainer,
this);
1813 clearSelection(
false);
1815 beginCommand(pasteCommandDescription(widgetCount, actionCount));
1818 positionPastedWidgetsAtMousePosition(
this, m_contextMenuPosition, pasteContainer, clipboard.m_widgets);
1819 for (QWidget *w : clipboard.m_widgets) {
1820 InsertWidgetCommand *cmd =
new InsertWidgetCommand(
this);
1822 m_undoStack.push(cmd);
1828 for (QAction *a : clipboard.m_actions) {
1829 ensureUniqueObjectName(a);
1830 AddActionCommand *cmd =
new AddActionCommand(
this);
1832 m_undoStack.push(cmd);
1841bool FormWindow::frameNeeded(QWidget *w)
const
1843 if (!core()->widgetDataBase()->isContainer(w))
1845 if (qobject_cast<QGroupBox *>(w))
1847 if (qobject_cast<QToolBox *>(w))
1849 if (qobject_cast<QTabWidget *>(w))
1851 if (qobject_cast<QStackedWidget *>(w))
1853 if (qobject_cast<QDockWidget *>(w))
1855 if (qobject_cast<QDesignerWidget *>(w))
1857 if (qobject_cast<QMainWindow *>(w))
1859 if (qobject_cast<QDialog *>(w))
1861 if (qobject_cast<QLayoutWidget *>(w))
1866bool FormWindow::eventFilter(QObject *watched, QEvent *event)
1868 const bool ret = FormWindowBase::eventFilter(watched, event);
1869 if (event->type() != QEvent::Paint)
1872 Q_ASSERT(watched->isWidgetType());
1873 QWidget *w =
static_cast<QWidget *>(watched);
1874 QPaintEvent *pe =
static_cast<QPaintEvent*>(event);
1875 const QRect widgetRect = w->rect();
1876 const QRect paintRect = pe->rect();
1878 if (paintRect.x() > widgetRect.x() && paintRect.y() > widgetRect.y() &&
1879 paintRect.right() < widgetRect.right() && paintRect.bottom() < widgetRect.bottom())
1882 const QPen pen(QColor(0, 0, 0, 32), 0, Qt::DotLine);
1884 p.setBrush(QBrush(Qt::NoBrush));
1885 p.drawRect(widgetRect.adjusted(0, 0, -1, -1));
1889void FormWindow::manageWidget(QWidget *w)
1894 Q_ASSERT(qobject_cast<QMenu*>(w) == 0);
1899 core()->metaDataBase()->add(w);
1901 m_insertedWidgets.insert(w);
1902 m_widgets.append(w);
1904#if QT_CONFIG(cursor)
1905 setCursorToAll(Qt::ArrowCursor, w);
1909 emit widgetManaged(w);
1912 w->installEventFilter(
this);
1915void FormWindow::unmanageWidget(QWidget *w)
1920 m_selection->removeWidget(w);
1922 emit aboutToUnmanageWidget(w);
1924 if (w == m_currentWidget)
1925 setCurrentWidget(mainContainer());
1927 core()->metaDataBase()->remove(w);
1929 m_insertedWidgets.remove(w);
1930 m_widgets.removeAt(m_widgets.indexOf(w));
1933 emit widgetUnmanaged(w);
1936 w->removeEventFilter(
this);
1939bool FormWindow::isManaged(QWidget *w)
const
1941 return m_insertedWidgets.contains(w);
1944void FormWindow::breakLayout(QWidget *w)
1947 w = mainContainer();
1949 QWidgetList widgets;
1951 const QDesignerMetaDataBaseInterface *mdb = core()->metaDataBase();
1952 for (
auto *o : w->children()) {
1953 if (o->isWidgetType()) {
1954 auto *w =
static_cast<QWidget*>(o);
1956 widgets.push_back(w);
1960 BreakLayoutCommand *cmd =
new BreakLayoutCommand(
this);
1961 cmd->init(widgets, w);
1962 commandHistory()->push(cmd);
1963 clearSelection(
false);
1966void FormWindow::beginCommand(
const QString &description)
1968 m_undoStack.beginMacro(description);
1971void FormWindow::endCommand()
1973 m_undoStack.endMacro();
1976void FormWindow::raiseWidgets()
1978 QWidgetList widgets = selectedWidgets();
1979 simplifySelection(&widgets);
1981 if (widgets.isEmpty())
1984 beginCommand(tr(
"Raise widgets"));
1985 for (QWidget *widget : std::as_const(widgets)) {
1986 RaiseWidgetCommand *cmd =
new RaiseWidgetCommand(
this);
1988 m_undoStack.push(cmd);
1993void FormWindow::lowerWidgets()
1995 QWidgetList widgets = selectedWidgets();
1996 simplifySelection(&widgets);
1998 if (widgets.isEmpty())
2001 beginCommand(tr(
"Lower widgets"));
2002 for (QWidget *widget : std::as_const(widgets)) {
2003 LowerWidgetCommand *cmd =
new LowerWidgetCommand(
this);
2005 m_undoStack.push(cmd);
2010bool FormWindow::handleMouseButtonDblClickEvent(QWidget *w, QWidget *managedWidget, QMouseEvent *e)
2012 if (debugFormWindow)
2013 qDebug() <<
"handleMouseButtonDblClickEvent:" << w <<
',' << managedWidget <<
"state=" << m_mouseState;
2019 if (isWidgetSelected(managedWidget))
2020 emit activated(managedWidget);
2022 m_mouseState = MouseDoubleClicked;
2027QMenu *FormWindow::initializePopupMenu(QWidget *managedWidget)
2029 if (!isManaged(managedWidget) || currentTool())
2036 const bool selected = isWidgetSelected(managedWidget);
2037 bool update =
false;
2039 update = setCurrentWidget(managedWidget);
2041 clearObjectInspectorSelection(m_core);
2042 clearSelection(
false);
2043 update = trySelectWidget(managedWidget,
true);
2044 raiseChildSelections(managedWidget);
2048 emitSelectionChanged();
2049 QMetaObject::invokeMethod(core()->formWindowManager(),
"slotUpdateActions");
2052 QWidget *contextMenuWidget =
nullptr;
2054 if (isMainContainer(managedWidget)) {
2055 contextMenuWidget = mainContainer();
2058 QWidget *realWidget = managedWidget;
2059 QMainWindow *mw = qobject_cast<QMainWindow*>(mainContainer());
2061 if (mw && mw->centralWidget() == realWidget) {
2062 contextMenuWidget = managedWidget;
2064 contextMenuWidget = realWidget;
2068 if (!contextMenuWidget)
2071 QMenu *contextMenu = createPopupMenu(contextMenuWidget);
2075 emit contextMenuRequested(contextMenu, contextMenuWidget);
2079bool FormWindow::handleContextMenu(QWidget *, QWidget *managedWidget, QContextMenuEvent *e)
2081 QMenu *contextMenu = initializePopupMenu(managedWidget);
2084 const QPoint globalPos = e->globalPos();
2085 m_contextMenuPosition = mapFromGlobal (globalPos);
2086 contextMenu->exec(globalPos);
2089 m_contextMenuPosition = QPoint(-1, -1);
2093bool FormWindow::setContents(QIODevice *dev, QString *errorMessageIn )
2095 QDesignerResource r(
this);
2096 QScopedPointer<DomUI> ui(r.readUi(dev));
2099 *errorMessageIn = r.errorString();
2103 UpdateBlocker ub(
this);
2105 m_selection->clearSelectionPool();
2106 m_insertedWidgets.clear();
2110 clearMainContainer();
2111 m_undoStack.clear();
2114 QWidget *w = r.loadUi(ui.data(), formContainer());
2116 setMainContainer(w);
2120 *errorMessageIn = r.errorString();
2121 return w !=
nullptr;
2124bool FormWindow::setContents(
const QString &contents)
2126 QString errorMessage;
2127 QByteArray data = contents.toUtf8();
2129 const bool success = b.open(QIODevice::ReadOnly) && setContents(&b, &errorMessage);
2130 if (!success && !errorMessage.isEmpty())
2131 designerWarning(errorMessage);
2135void FormWindow::layoutContainer(QWidget *w,
int type)
2138 w = mainContainer();
2140 w = core()->widgetFactory()->containerOfWidget(w);
2143 QWidgetList widgets;
2144 for (
auto *o : w->children()) {
2145 if (o->isWidgetType() ) {
2146 auto *widget =
static_cast<QWidget*>(o);
2147 if (widget->isVisibleTo(
this) && isManaged(widget))
2148 widgets.append(widget);
2152 if (widgets.isEmpty())
2155 LayoutCommand *cmd =
new LayoutCommand(
this);
2156 cmd->init(mainContainer(), widgets,
static_cast<LayoutInfo::Type>(type), w);
2157 clearSelection(
false);
2158 commandHistory()->push(cmd);
2161bool FormWindow::hasInsertedChildren(QWidget *widget)
const
2163 if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), widget)) {
2164 const int index = container->currentIndex();
2167 widget = container->widget(index);
2170 const QWidgetList l = widgets(widget);
2172 for (QWidget *child : l) {
2173 if (isManaged(child) && !LayoutInfo::isWidgetLaidout(core(), child) && child->isVisibleTo(
const_cast<FormWindow*>(
this)))
2181void FormWindow::slotSelectWidget(QAction *a)
2183 if (QWidget *w = qvariant_cast<QWidget*>(a->data()))
2184 selectSingleWidget(w);
2187void FormWindow::slotCleanChanged(
bool clean)
2193static inline QString objectNameOf(
const QWidget *w)
2195 if (
const QLayoutWidget *lw = qobject_cast<
const QLayoutWidget *>(w)) {
2196 const QLayout *layout = lw->layout();
2197 const QString rc = layout->objectName();
2201 return QString::fromUtf8(layout->metaObject()->className());
2203 return w->objectName();
2206QAction *FormWindow::createSelectAncestorSubMenu(QWidget *w)
2209 QWidgetList parents;
2210 QWidget *mc = mainContainer();
2211 for (QWidget *p = w->parentWidget(); p && p != mc; p = p->parentWidget())
2212 if (isManaged(p) && !isWidgetSelected(p))
2213 parents.push_back(p);
2214 if (parents.isEmpty())
2217 QMenu *menu =
new QMenu;
2218 QActionGroup *ag =
new QActionGroup(menu);
2219 QObject::connect(ag, &QActionGroup::triggered,
this, &FormWindow::slotSelectWidget);
2220 for (
auto *w : std::as_const(parents)) {
2221 QAction *a = ag->addAction(objectNameOf(w));
2222 a->setData(QVariant::fromValue(w));
2225 QAction *ma =
new QAction(tr(
"Select Ancestor"),
nullptr);
2230QMenu *FormWindow::createPopupMenu(QWidget *w)
2232 QMenu *popup = createExtensionTaskMenu(
this, w,
true);
2238 QDesignerFormWindowManagerInterface *manager = core()->formWindowManager();
2239 const bool isFormWindow = qobject_cast<
const FormWindow*>(w);
2242 if (!isFormWindow) {
2243 if (QStackedWidget *stackedWidget = qobject_cast<QStackedWidget*>(w)) {
2244 QStackedWidgetEventFilter::addStackedWidgetContextMenuActions(stackedWidget, popup);
2245 }
else if (QTabWidget *tabWidget = qobject_cast<QTabWidget*>(w)) {
2246 QTabWidgetEventFilter::addTabWidgetContextMenuActions(tabWidget, popup);
2247 }
else if (QToolBox *toolBox = qobject_cast<QToolBox*>(w)) {
2248 QToolBoxHelper::addToolBoxContextMenuActions(toolBox, popup);
2251 if (manager->action(QDesignerFormWindowManagerInterface::LowerAction)->isEnabled()) {
2252 popup->addAction(manager->action(QDesignerFormWindowManagerInterface::LowerAction));
2253 popup->addAction(manager->action(QDesignerFormWindowManagerInterface::RaiseAction));
2254 popup->addSeparator();
2256#if QT_CONFIG(clipboard)
2257 popup->addAction(manager->action(QDesignerFormWindowManagerInterface::CutAction));
2258 popup->addAction(manager->action(QDesignerFormWindowManagerInterface::CopyAction));
2262#if QT_CONFIG(clipboard)
2263 popup->addAction(manager->action(QDesignerFormWindowManagerInterface::PasteAction));
2266 if (QAction *selectAncestorAction = createSelectAncestorSubMenu(w))
2267 popup->addAction(selectAncestorAction);
2268 popup->addAction(manager->action(QDesignerFormWindowManagerInterface::SelectAllAction));
2270 if (!isFormWindow) {
2271 popup->addAction(manager->action(QDesignerFormWindowManagerInterface::DeleteAction));
2274 popup->addSeparator();
2275 QMenu *layoutMenu = popup->addMenu(tr(
"Lay out"));
2276 layoutMenu->addAction(manager->action(QDesignerFormWindowManagerInterface::AdjustSizeAction));
2277 layoutMenu->addAction(manager->action(QDesignerFormWindowManagerInterface::HorizontalLayoutAction));
2278 layoutMenu->addAction(manager->action(QDesignerFormWindowManagerInterface::VerticalLayoutAction));
2279 if (!isFormWindow) {
2280 layoutMenu->addAction(manager->action(QDesignerFormWindowManagerInterface::SplitHorizontalAction));
2281 layoutMenu->addAction(manager->action(QDesignerFormWindowManagerInterface::SplitVerticalAction));
2283 layoutMenu->addAction(manager->action(QDesignerFormWindowManagerInterface::GridLayoutAction));
2284 layoutMenu->addAction(manager->action(QDesignerFormWindowManagerInterface::FormLayoutAction));
2285 layoutMenu->addAction(manager->action(QDesignerFormWindowManagerInterface::BreakLayoutAction));
2286 layoutMenu->addAction(manager->action(QDesignerFormWindowManagerInterface::SimplifyLayoutAction));
2291void FormWindow::resizeEvent(QResizeEvent *e)
2293 m_geometryChangedTimer->start(10);
2295 QWidget::resizeEvent(e);
2299
2300
2301
2302
2303
2304QPoint FormWindow::mapToForm(
const QWidget *w, QPoint pos)
const
2307 const QWidget* i = w;
2308 while (i && !i->isWindow() && !isMainContainer(i)) {
2309 p = i->mapToParent(p);
2310 i = i->parentWidget();
2313 return mapFromGlobal(w->mapToGlobal(pos));
2316bool FormWindow::canBeBuddy(QWidget *w)
const
2318 if (QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), w)) {
2319 const int index = sheet->indexOf(u"focusPolicy"_s);
2322 const Qt::FocusPolicy q =
static_cast<Qt::FocusPolicy>(Utils::valueOf(sheet->property(index), &ok));
2323 return ok && q != Qt::NoFocus;
2330QWidget *FormWindow::findContainer(QWidget *w,
bool excludeLayout)
const
2332 if (!isChildOf(w,
this)
2333 ||
const_cast<
const QWidget *>(w) ==
this)
2336 QDesignerWidgetFactoryInterface *widgetFactory = core()->widgetFactory();
2337 QDesignerWidgetDataBaseInterface *widgetDataBase = core()->widgetDataBase();
2338 QDesignerMetaDataBaseInterface *metaDataBase = core()->metaDataBase();
2340 QWidget *container = widgetFactory->containerOfWidget(mainContainer());
2341 if (!isMainContainer(w)) {
2343 if (qobject_cast<InvisibleWidget*>(w) || !metaDataBase->item(w)) {
2344 w = w->parentWidget();
2348 const bool isContainer = widgetDataBase->isContainer(w,
true) || w == mainContainer();
2350 if (!isContainer || (excludeLayout && qobject_cast<QLayoutWidget*>(w))) {
2351 w = w->parentWidget();
2362void FormWindow::simplifySelection(QWidgetList *sel)
const
2364 if (sel->size() < 2)
2371 QWidget *mainC = mainContainer();
2372 if (sel->contains(mainC)) {
2374 sel->push_back(mainC);
2377 QWidgetList toBeRemoved;
2378 toBeRemoved.reserve(sel->size());
2379 for (
auto *child : std::as_const(*sel)) {
2380 for (QWidget *w = child;
true ; ) {
2381 QWidget *parent = w->parentWidget();
2382 if (!parent || parent == mainC)
2384 if (sel->contains(parent)) {
2385 toBeRemoved.append(child);
2393 for (
auto *r : std::as_const(toBeRemoved))
2397FormWindow *FormWindow::findFormWindow(QWidget *w)
2399 return qobject_cast<FormWindow*>(QDesignerFormWindowInterface::findFormWindow(w));
2402bool FormWindow::isDirty()
const
2404 return !m_undoStack.isClean();
2407void FormWindow::setDirty(
bool dirty)
2410 m_undoStack.resetClean();
2412 m_undoStack.setClean();
2415QWidget *FormWindow::containerAt(
const QPoint &pos)
2417 QWidget *widget = widgetAt(pos);
2418 return findContainer(widget,
true);
2421static QWidget *childAt_SkipDropLine(QWidget *w, QPoint pos)
2423 const QObjectList &child_list = w->children();
2424 for (
auto i = child_list.size() - 1; i >= 0; --i) {
2425 QObject *child_obj = child_list.at(i);
2426 if (qobject_cast<WidgetHandle*>(child_obj) !=
nullptr)
2428 QWidget *child = qobject_cast<QWidget*>(child_obj);
2429 if (!child || child->isWindow() || !child->isVisible() ||
2430 !child->geometry().contains(pos) || child->testAttribute(Qt::WA_TransparentForMouseEvents))
2432 const QPoint childPos = child->mapFromParent(pos);
2433 if (QWidget *res = childAt_SkipDropLine(child, childPos))
2435 if (child->testAttribute(Qt::WA_MouseNoMask) || child->mask().contains(pos)
2436 || child->mask().isEmpty())
2443QWidget *FormWindow::widgetAt(
const QPoint &pos)
2445 QWidget *w = childAt(pos);
2446 if (qobject_cast<
const WidgetHandle*>(w) != 0)
2447 w = childAt_SkipDropLine(
this, pos);
2448 return (w ==
nullptr || w == formContainer()) ?
this : w;
2451void FormWindow::highlightWidget(QWidget *widget,
const QPoint &pos, HighlightMode mode)
2455 if (QMainWindow *mainWindow = qobject_cast<QMainWindow*> (widget)) {
2456 widget = mainWindow->centralWidget();
2459 QWidget *container = findContainer(widget,
false);
2461 if (container ==
nullptr || core()->metaDataBase()->item(container) ==
nullptr)
2464 if (QDesignerActionProviderExtension *g = qt_extension<QDesignerActionProviderExtension*>(core()->extensionManager(), container)) {
2465 if (mode == Restore) {
2466 g->adjustIndicator(QPoint());
2468 const QPoint pt = widget->mapTo(container, pos);
2469 g->adjustIndicator(pt);
2471 }
else if (QDesignerLayoutDecorationExtension *g = qt_extension<QDesignerLayoutDecorationExtension*>(core()->extensionManager(), container)) {
2472 if (mode == Restore) {
2473 g->adjustIndicator(QPoint(), -1);
2475 const QPoint pt = widget->mapTo(container, pos);
2476 const int index = g->findItemAt(pt);
2477 g->adjustIndicator(pt, index);
2481 QMainWindow *mw = qobject_cast<QMainWindow*> (container);
2482 if (container == mainContainer() || (mw && mw->centralWidget() && mw->centralWidget() == container))
2485 if (mode == Restore) {
2486 const auto pit = m_palettesBeforeHighlight.find(container);
2487 if (pit != m_palettesBeforeHighlight.end()) {
2488 container->setPalette(pit.value().first);
2489 container->setAutoFillBackground(pit.value().second);
2490 m_palettesBeforeHighlight.erase(pit);
2493 QPalette p = container->palette();
2494 if (!m_palettesBeforeHighlight.contains(container)) {
2495 PaletteAndFill paletteAndFill;
2496 if (container->testAttribute(Qt::WA_SetPalette))
2497 paletteAndFill.first = p;
2498 paletteAndFill.second = container->autoFillBackground();
2499 m_palettesBeforeHighlight.insert(container, paletteAndFill);
2502 p.setColor(backgroundRole(), p.midlight().color());
2503 container->setPalette(p);
2504 container->setAutoFillBackground(
true);
2508QWidgetList FormWindow::widgets(QWidget *widget)
const
2510 if (widget->children().isEmpty())
2511 return QWidgetList();
2513 for (QObject *o : widget->children()) {
2514 if (o->isWidgetType()) {
2515 QWidget *w = qobject_cast<QWidget*>(o);
2523int FormWindow::toolCount()
const
2525 return m_widgetStack->count();
2528QDesignerFormWindowToolInterface *FormWindow::tool(
int index)
const
2530 return m_widgetStack->tool(index);
2533void FormWindow::registerTool(QDesignerFormWindowToolInterface *tool)
2535 Q_ASSERT(tool !=
nullptr);
2537 m_widgetStack->addTool(tool);
2539 if (m_mainContainer)
2540 m_mainContainer->update();
2543void FormWindow::setCurrentTool(
int index)
2545 m_widgetStack->setCurrentTool(index);
2548int FormWindow::currentTool()
const
2550 return m_widgetStack->currentIndex();
2553bool FormWindow::handleEvent(QWidget *widget, QWidget *managedWidget, QEvent *event)
2555 if (m_widgetStack ==
nullptr)
2558 QDesignerFormWindowToolInterface *tool = m_widgetStack->currentTool();
2559 if (tool ==
nullptr)
2562 return tool->handleEvent(widget, managedWidget, event);
2565void FormWindow::initializeCoreTools()
2567 m_widgetEditor =
new WidgetEditorTool(
this);
2568 registerTool(m_widgetEditor);
2571void FormWindow::checkSelection()
2573 m_checkSelectionTimer->start(0);
2576void FormWindow::checkSelectionNow()
2578 m_checkSelectionTimer->stop();
2580 const QWidgetList &sel = selectedWidgets();
2581 for (QWidget *widget : sel) {
2582 updateSelection(widget);
2584 if (LayoutInfo::layoutType(core(), widget) != LayoutInfo::NoLayout)
2585 updateChildSelections(widget);
2589QString FormWindow::author()
const
2594QString FormWindow::comment()
const
2599void FormWindow::setAuthor(
const QString &author)
2604void FormWindow::setComment(
const QString &comment)
2606 m_comment = comment;
2609void FormWindow::editWidgets()
2611 m_widgetEditor->action()->trigger();
2614QStringList FormWindow::resourceFiles()
const
2616 return m_resourceFiles;
2619void FormWindow::addResourceFile(
const QString &path)
2621 if (!m_resourceFiles.contains(path)) {
2622 m_resourceFiles.append(path);
2624 emit resourceFilesChanged();
2628void FormWindow::removeResourceFile(
const QString &path)
2630 if (m_resourceFiles.removeAll(path) > 0) {
2632 emit resourceFilesChanged();
2636bool FormWindow::blockSelectionChanged(
bool b)
2638 const bool blocked = m_blockSelectionChanged;
2639 m_blockSelectionChanged = b;
2643void FormWindow::editContents()
2645 const QWidgetList sel = selectedWidgets();
2646 if (sel.size() == 1) {
2647 QWidget *widget = sel.first();
2649 if (QAction *a = preferredEditAction(core(), widget))
2654void FormWindow::dragWidgetWithinForm(QWidget *widget, QRect targetGeometry, QWidget *targetContainer)
2656 const bool fromLayout = canDragWidgetInLayout(core(), widget);
2657 const QDesignerLayoutDecorationExtension *targetDeco = qt_extension<QDesignerLayoutDecorationExtension*>(core()->extensionManager(), targetContainer);
2658 const bool toLayout = targetDeco !=
nullptr;
2664 DeleteWidgetCommand *cmd =
new DeleteWidgetCommand(
this);
2665 unsigned deleteFlags = DeleteWidgetCommand::DoNotUnmanage;
2667 deleteFlags |= DeleteWidgetCommand::DoNotSimplifyLayout;
2668 cmd->init(widget, deleteFlags);
2669 commandHistory()->push(cmd);
2674 insertWidget(widget, targetGeometry, targetContainer,
true);
2677 if (targetContainer != widget->parent()) {
2678 ReparentWidgetCommand *cmd =
new ReparentWidgetCommand(
this);
2679 cmd->init(widget, targetContainer );
2680 commandHistory()->push(cmd);
2682 resizeWidget(widget, targetGeometry);
2683 selectWidget(widget,
true);
2688static Qt::DockWidgetArea detectDropArea(QMainWindow *mainWindow, QRect area, QPoint drop)
2690 QPoint offset = area.topLeft();
2692 rect.moveTopLeft(QPoint(0, 0));
2693 QPoint point = drop - offset;
2694 const int x = point.x();
2695 const int y = point.y();
2696 const int w = rect.width();
2697 const int h = rect.height();
2699 if (rect.contains(point)) {
2700 bool topRight =
false;
2701 bool topLeft =
false;
2704 if (w * y < h * (w - x))
2707 if (topRight && topLeft)
2708 return Qt::TopDockWidgetArea;
2709 if (topRight && !topLeft)
2710 return Qt::RightDockWidgetArea;
2711 if (!topRight && topLeft)
2712 return Qt::LeftDockWidgetArea;
2713 return Qt::BottomDockWidgetArea;
2718 return mainWindow->corner(Qt::TopLeftCorner);
2719 return y > h ? mainWindow->corner(Qt::BottomLeftCorner) : Qt::LeftDockWidgetArea;
2723 return mainWindow->corner(Qt::TopRightCorner);
2724 return y > h ? mainWindow->corner(Qt::BottomRightCorner) : Qt::RightDockWidgetArea;
2726 return y < 0 ? Qt::TopDockWidgetArea :Qt::LeftDockWidgetArea;
2729bool FormWindow::dropDockWidget(QDesignerDnDItemInterface *item, QPoint global_mouse_pos)
2731 DomUI *dom_ui = item->domUi();
2733 QMainWindow *mw = qobject_cast<QMainWindow *>(mainContainer());
2737 QDesignerResource resource(
this);
2738 const FormBuilderClipboard clipboard = resource.paste(dom_ui, mw);
2739 if (clipboard.m_widgets.size() != 1)
2742 QWidget *centralWidget = mw->centralWidget();
2743 QPoint localPos = centralWidget->mapFromGlobal(global_mouse_pos);
2744 const QRect centralWidgetAreaRect = centralWidget->rect();
2745 Qt::DockWidgetArea area = detectDropArea(mw, centralWidgetAreaRect, localPos);
2747 beginCommand(tr(
"Drop widget"));
2749 clearSelection(
false);
2750 highlightWidget(mw, QPoint(0, 0), FormWindow::Restore);
2752 QWidget *widget = clipboard.m_widgets.first();
2754 insertWidget(widget, QRect(0, 0, 1, 1), mw);
2756 selectWidget(widget,
true);
2757 mw->setFocus(Qt::MouseFocusReason);
2759 core()->formWindowManager()->setActiveFormWindow(
this);
2760 mainContainer()->activateWindow();
2762 QDesignerPropertySheetExtension *propertySheet = qobject_cast<QDesignerPropertySheetExtension*>(m_core->extensionManager()->extension(widget, Q_TYPEID(QDesignerPropertySheetExtension)));
2763 if (propertySheet) {
2764 const QString dockWidgetAreaName = u"dockWidgetArea"_s;
2765 PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(propertySheet->property(propertySheet->indexOf(dockWidgetAreaName)));
2769 SetPropertyCommand *cmd =
new SetPropertyCommand(
this);
2770 cmd->init(widget, dockWidgetAreaName, v);
2771 m_undoStack.push(cmd);
2778bool FormWindow::dropWidgets(
const QList<QDesignerDnDItemInterface*> &item_list, QWidget *target,
2779 const QPoint &global_mouse_pos)
2782 QWidget *parent = target;
2783 if (parent ==
nullptr)
2784 parent = mainContainer();
2787 if (QMainWindow *main_win = qobject_cast<QMainWindow*>(target)) {
2788 if (!main_win->centralWidget()) {
2789 designerWarning(tr(
"A QMainWindow-based form does not contain a central widget."));
2792 const QPoint main_win_pos = main_win->mapFromGlobal(global_mouse_pos);
2793 const QRect central_wgt_geo = main_win->centralWidget()->geometry();
2794 if (!central_wgt_geo.contains(main_win_pos))
2798 QWidget *container = findContainer(parent,
false);
2799 if (container ==
nullptr)
2802 beginCommand(tr(
"Drop widget"));
2804 clearSelection(
false);
2805 highlightWidget(target, target->mapFromGlobal(global_mouse_pos), FormWindow::Restore);
2808 QDesignerDnDItemInterface *current =
nullptr;
2809 QDesignerFormWindowCursorInterface *c = cursor();
2810 for (QDesignerDnDItemInterface *item : std::as_const(item_list)) {
2811 QWidget *w = item->widget();
2814 if (c->current() == w) {
2820 QRect geom = current->decoration()->geometry();
2821 QPoint topLeft = container->mapFromGlobal(geom.topLeft());
2822 offset = designerGrid().snapPoint(topLeft) - topLeft;
2825 for (QDesignerDnDItemInterface *item : std::as_const(item_list)) {
2826 DomUI *dom_ui = item->domUi();
2827 QRect geometry = item->decoration()->geometry();
2828 Q_ASSERT(dom_ui !=
nullptr);
2830 geometry.moveTopLeft(container->mapFromGlobal(geometry.topLeft()) + offset);
2831 if (item->type() == QDesignerDnDItemInterface::CopyDrop) {
2832 QWidget *widget = createWidget(dom_ui, geometry, parent);
2837 selectWidget(widget,
true);
2838 mainContainer()->setFocus(Qt::MouseFocusReason);
2840 QWidget *widget = item->widget();
2841 Q_ASSERT(widget !=
nullptr);
2842 QDesignerFormWindowInterface *dest = findFormWindow(widget);
2844 dragWidgetWithinForm(widget, geometry, container);
2846 FormWindow *source = qobject_cast<FormWindow*>(item->source());
2847 Q_ASSERT(source !=
nullptr);
2849 source->deleteWidgetList(QWidgetList() << widget);
2850 QWidget *new_widget = createWidget(dom_ui, geometry, parent);
2852 selectWidget(new_widget,
true);
2857 core()->formWindowManager()->setActiveFormWindow(
this);
2858 mainContainer()->activateWindow();
2863QDir FormWindow::absoluteDir()
const
2865 if (fileName().isEmpty())
2866 return QDir::current();
2868 return QFileInfo(fileName()).absoluteDir();
2871void FormWindow::layoutDefault(
int *margin,
int *spacing)
2873 *margin = m_defaultMargin;
2874 *spacing = m_defaultSpacing;
2877void FormWindow::setLayoutDefault(
int margin,
int spacing)
2879 m_defaultMargin = margin;
2880 m_defaultSpacing = spacing;
2883void FormWindow::layoutFunction(QString *margin, QString *spacing)
2885 *margin = m_marginFunction;
2886 *spacing = m_spacingFunction;
2889void FormWindow::setLayoutFunction(
const QString &margin,
const QString &spacing)
2891 m_marginFunction = margin;
2892 m_spacingFunction = spacing;
2895QString FormWindow::pixmapFunction()
const
2897 return m_pixmapFunction;
2900void FormWindow::setPixmapFunction(
const QString &pixmapFunction)
2902 m_pixmapFunction = pixmapFunction;
2905QStringList FormWindow::includeHints()
const
2907 return m_includeHints;
2910void FormWindow::setIncludeHints(
const QStringList &includeHints)
2912 m_includeHints = includeHints;
2915QString FormWindow::exportMacro()
const
2917 return m_exportMacro;
2920void FormWindow::setExportMacro(
const QString &exportMacro)
2922 m_exportMacro = exportMacro;
2925QEditorFormBuilder *FormWindow::createFormBuilder()
2927 return new QDesignerResource(
this);
2930QWidget *FormWindow::formContainer()
const
2932 return m_widgetStack->formContainer();
2935QUndoStack *FormWindow::commandHistory()
const
2937 return &
const_cast<QUndoStack &>(m_undoStack);
QDesignerResource(FormWindow *fw)
Auxiliary methods to store/retrieve settings.
static unsigned mouseFlags(Qt::KeyboardModifiers mod)
static void insertNames(const QDesignerMetaDataBaseInterface *metaDataBase, Iterator it, const Iterator &end, QObject *excludedObject, QSet< QString > &nameSet)
static void clearObjectInspectorSelection(const QDesignerFormEditorInterface *core)
static bool canDragWidgetInLayout(const QDesignerFormEditorInterface *core, QWidget *w)
@ ToggleSelectionModifier
static bool isDescendant(const QWidget *parent, const QWidget *child)
static QSet< QString > languageKeywords()
static QWidget * findSelectedParent(QDesignerFormWindowInterface *fw, const QWidget *w, bool selected)
QRect apply(QRect rect) const