1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Designer of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include "widgetselection.h"
30#include "formwindow.h"
31#include "formwindowmanager.h"
32
33// sdk
34#include <QtDesigner/abstractformeditor.h>
35#include <QtDesigner/qextensionmanager.h>
36
37// shared
38#include <qdesigner_command_p.h>
39#include <qdesigner_propertycommand_p.h>
40#include <layout_p.h>
41#include <layoutinfo_p.h>
42#include <formwindowbase_p.h>
43#include <grid_p.h>
44
45#include <QtWidgets/qmenu.h>
46#include <QtWidgets/qwidget.h>
47#include <QtGui/qevent.h>
48#include <QtWidgets/qstylepainter.h>
49#include <QtWidgets/qgridlayout.h>
50#include <QtWidgets/qformlayout.h>
51#include <QtWidgets/qstyleoption.h>
52#include <QtWidgets/qapplication.h>
53
54#include <QtCore/qvariant.h>
55#include <QtCore/qdebug.h>
56
57#include <algorithm>
58
59QT_BEGIN_NAMESPACE
60
61namespace qdesigner_internal {
62enum { debugWidgetSelection = 0 };
63
64// Return the layout the widget is in
65template <class Layout>
66static inline Layout *managedLayoutOf(const QDesignerFormEditorInterface *core,
67 QWidget *w,
68 const Layout * /* vs6dummy */ = nullptr)
69{
70 if (QWidget *p = w->parentWidget())
71 if (QLayout *l = LayoutInfo::managedLayout(core, widget: p))
72 return qobject_cast<Layout*>(l);
73 return nullptr;
74}
75
76// ----------- WidgetHandle
77WidgetHandle::WidgetHandle(FormWindow *parent, WidgetHandle::Type t, WidgetSelection *s) :
78 InvisibleWidget(parent->formContainer()),
79 m_widget(nullptr),
80 m_type(t),
81 m_formWindow( parent),
82 m_sel(s),
83 m_active(true)
84{
85 setMouseTracking(false);
86 setAutoFillBackground(true);
87
88 setBackgroundRole(m_active ? QPalette::Text : QPalette::Dark);
89 setFixedSize(w: 6, h: 6);
90
91 updateCursor();
92}
93
94void WidgetHandle::updateCursor()
95{
96#if QT_CONFIG(cursor)
97 if (!m_active) {
98 setCursor(Qt::ArrowCursor);
99 return;
100 }
101
102 switch (m_type) {
103 case LeftTop:
104 setCursor(Qt::SizeFDiagCursor);
105 break;
106 case Top:
107 setCursor(Qt::SizeVerCursor);
108 break;
109 case RightTop:
110 setCursor(Qt::SizeBDiagCursor);
111 break;
112 case Right:
113 setCursor(Qt::SizeHorCursor);
114 break;
115 case RightBottom:
116 setCursor(Qt::SizeFDiagCursor);
117 break;
118 case Bottom:
119 setCursor(Qt::SizeVerCursor);
120 break;
121 case LeftBottom:
122 setCursor(Qt::SizeBDiagCursor);
123 break;
124 case Left:
125 setCursor(Qt::SizeHorCursor);
126 break;
127 default:
128 Q_ASSERT(0);
129 }
130#endif
131}
132
133QDesignerFormEditorInterface *WidgetHandle::core() const
134{
135 if (m_formWindow)
136 return m_formWindow->core();
137
138 return nullptr;
139}
140
141void WidgetHandle::setActive(bool a)
142{
143 m_active = a;
144 setBackgroundRole(m_active ? QPalette::Text : QPalette::Dark);
145 updateCursor();
146}
147
148void WidgetHandle::setWidget(QWidget *w)
149{
150 m_widget = w;
151}
152
153void WidgetHandle::paintEvent(QPaintEvent *)
154{
155 QDesignerFormWindowManagerInterface *m = m_formWindow->core()->formWindowManager();
156
157 QStylePainter p(this);
158 if (m_formWindow->currentWidget() == m_widget) {
159 p.setPen(m->activeFormWindow() == m_formWindow ? Qt::blue : Qt::red);
160 p.drawRect(x: 0, y: 0, w: width() - 1, h: height() - 1);
161 }
162}
163
164void WidgetHandle::mousePressEvent(QMouseEvent *e)
165{
166 e->accept();
167
168 if (!m_formWindow->hasFeature(f: FormWindow::EditFeature))
169 return;
170
171 if (!(m_widget && e->button() == Qt::LeftButton))
172 return;
173
174 if (!(m_active))
175 return;
176
177 QWidget *container = m_widget->parentWidget();
178
179 m_origPressPos = container->mapFromGlobal(e->globalPos());
180 m_geom = m_origGeom = m_widget->geometry();
181
182 switch (WidgetSelection::widgetState(core: m_formWindow->core(), w: m_widget)) {
183 case WidgetSelection::UnlaidOut:
184 case WidgetSelection::LaidOut:
185 m_formWindow->setHandleOperation(FormWindow::ResizeHandleOperation);
186 break;
187 case WidgetSelection::ManagedGridLayout:
188 case WidgetSelection::ManagedFormLayout:
189 m_formWindow->setHandleOperation(FormWindow::ChangeLayoutSpanHandleOperation);
190 break;
191 }
192}
193
194void WidgetHandle::mouseMoveEvent(QMouseEvent *e)
195{
196 if (!(m_widget && m_active && e->buttons() & Qt::LeftButton))
197 return;
198
199 e->accept();
200
201 QWidget *container = m_widget->parentWidget();
202
203 const QPoint rp = container->mapFromGlobal(e->globalPos());
204 const QPoint d = rp - m_origPressPos;
205
206 const QRect pr = container->rect();
207
208 qdesigner_internal::Grid grid;
209 if (const qdesigner_internal::FormWindowBase *fwb = qobject_cast<const qdesigner_internal::FormWindowBase*>(object: m_formWindow))
210 grid = fwb->designerGrid();
211
212 switch (m_type) {
213
214 case LeftTop: {
215 if (rp.x() > pr.width() - 2 * width() || rp.y() > pr.height() - 2 * height())
216 return;
217
218 int w = m_origGeom.width() - d.x();
219 m_geom.setWidth(w);
220 w = grid.widgetHandleAdjustX(x: w);
221
222 int h = m_origGeom.height() - d.y();
223 m_geom.setHeight(h);
224 h = grid.widgetHandleAdjustY(y: h);
225
226 const int dx = m_widget->width() - w;
227 const int dy = m_widget->height() - h;
228
229 trySetGeometry(w: m_widget, x: m_widget->x() + dx, y: m_widget->y() + dy, width: w, height: h);
230 } break;
231
232 case Top: {
233 if (rp.y() > pr.height() - 2 * height())
234 return;
235
236 int h = m_origGeom.height() - d.y();
237 m_geom.setHeight(h);
238 h = grid.widgetHandleAdjustY(y: h);
239
240 const int dy = m_widget->height() - h;
241 trySetGeometry(w: m_widget, x: m_widget->x(), y: m_widget->y() + dy, width: m_widget->width(), height: h);
242 } break;
243
244 case RightTop: {
245 if (rp.x() < 2 * width() || rp.y() > pr.height() - 2 * height())
246 return;
247
248 int h = m_origGeom.height() - d.y();
249 m_geom.setHeight(h);
250 h = grid.widgetHandleAdjustY(y: h);
251
252 const int dy = m_widget->height() - h;
253
254 int w = m_origGeom.width() + d.x();
255 m_geom.setWidth(w);
256 w = grid.widgetHandleAdjustX(x: w);
257
258 trySetGeometry(w: m_widget, x: m_widget->x(), y: m_widget->y() + dy, width: w, height: h);
259 } break;
260
261 case Right: {
262 if (rp.x() < 2 * width())
263 return;
264
265 int w = m_origGeom.width() + d.x();
266 m_geom.setWidth(w);
267 w = grid.widgetHandleAdjustX(x: w);
268
269 tryResize(w: m_widget, width: w, height: m_widget->height());
270 } break;
271
272 case RightBottom: {
273 if (rp.x() < 2 * width() || rp.y() < 2 * height())
274 return;
275
276 int w = m_origGeom.width() + d.x();
277 m_geom.setWidth(w);
278 w = grid.widgetHandleAdjustX(x: w);
279
280 int h = m_origGeom.height() + d.y();
281 m_geom.setHeight(h);
282 h = grid.widgetHandleAdjustY(y: h);
283
284 tryResize(w: m_widget, width: w, height: h);
285 } break;
286
287 case Bottom: {
288 if (rp.y() < 2 * height())
289 return;
290
291 int h = m_origGeom.height() + d.y();
292 m_geom.setHeight(h);
293 h = grid.widgetHandleAdjustY(y: h);
294
295 tryResize(w: m_widget, width: m_widget->width(), height: h);
296 } break;
297
298 case LeftBottom: {
299 if (rp.x() > pr.width() - 2 * width() || rp.y() < 2 * height())
300 return;
301
302 int w = m_origGeom.width() - d.x();
303 m_geom.setWidth(w);
304 w = grid.widgetHandleAdjustX(x: w);
305
306 int h = m_origGeom.height() + d.y();
307 m_geom.setHeight(h);
308 h = grid.widgetHandleAdjustY(y: h);
309
310 int dx = m_widget->width() - w;
311
312 trySetGeometry(w: m_widget, x: m_widget->x() + dx, y: m_widget->y(), width: w, height: h);
313 } break;
314
315 case Left: {
316 if (rp.x() > pr.width() - 2 * width())
317 return;
318
319 int w = m_origGeom.width() - d.x();
320 m_geom.setWidth(w);
321 w = grid.widgetHandleAdjustX(x: w);
322
323 const int dx = m_widget->width() - w;
324
325 trySetGeometry(w: m_widget, x: m_widget->x() + dx, y: m_widget->y(), width: w, height: m_widget->height());
326 } break;
327
328 default: break;
329
330 } // end switch
331
332 m_sel->updateGeometry();
333
334 if (LayoutInfo::layoutType(core: m_formWindow->core(), w: m_widget) != LayoutInfo::NoLayout)
335 m_formWindow->updateChildSelections(w: m_widget);
336}
337
338void WidgetHandle::mouseReleaseEvent(QMouseEvent *e)
339{
340 m_formWindow->setHandleOperation(FormWindow::NoHandleOperation);
341
342 if (e->button() != Qt::LeftButton || !m_active)
343 return;
344
345 e->accept();
346
347 if (!m_formWindow->hasFeature(f: FormWindow::EditFeature))
348 return;
349
350 switch (WidgetSelection::widgetState(core: m_formWindow->core(), w: m_widget)) {
351 case WidgetSelection::UnlaidOut:
352 if (m_geom != m_widget->geometry()) {
353 SetPropertyCommand *cmd = new SetPropertyCommand(m_formWindow);
354 cmd->init(object: m_widget, QStringLiteral("geometry"), newValue: m_widget->geometry());
355 cmd->setOldValue(oldValue: m_origGeom);
356 m_formWindow->commandHistory()->push(cmd);
357 m_formWindow->emitSelectionChanged();
358 }
359 break;
360 case WidgetSelection::LaidOut:
361 break;
362 case WidgetSelection::ManagedGridLayout:
363 changeGridLayoutItemSpan();
364 break;
365 case WidgetSelection::ManagedFormLayout:
366 changeFormLayoutItemSpan();
367 break;
368 }
369}
370
371// Match the left/right widget handle mouse movements to form layout span-changing operations
372static inline int formLayoutLeftHandleOperation(int dx, unsigned possibleOperations)
373{
374 if (dx < 0) {
375 if (possibleOperations & ChangeFormLayoutItemRoleCommand::FieldToSpanning)
376 return ChangeFormLayoutItemRoleCommand::FieldToSpanning;
377 return 0;
378 }
379 if (possibleOperations & ChangeFormLayoutItemRoleCommand::SpanningToField)
380 return ChangeFormLayoutItemRoleCommand::SpanningToField;
381 return 0;
382}
383
384static inline int formLayoutRightHandleOperation(int dx, unsigned possibleOperations)
385{
386 if (dx < 0) {
387 if (possibleOperations & ChangeFormLayoutItemRoleCommand::SpanningToLabel)
388 return ChangeFormLayoutItemRoleCommand::SpanningToLabel;
389 return 0;
390 }
391 if (possibleOperations & ChangeFormLayoutItemRoleCommand::LabelToSpanning)
392 return ChangeFormLayoutItemRoleCommand::LabelToSpanning;
393 return 0;
394}
395
396// Change form layout item horizontal span
397void WidgetHandle::changeFormLayoutItemSpan()
398{
399 QUndoCommand *cmd = nullptr;
400 // Figure out command according to the movement
401 const int dx = m_widget->geometry().center().x() - m_origGeom.center().x();
402 if (qAbs(t: dx) >= QApplication::startDragDistance()) {
403 int operation = 0;
404 if (const unsigned possibleOperations = ChangeFormLayoutItemRoleCommand::possibleOperations(core: m_formWindow->core(), w: m_widget)) {
405 switch (m_type) {
406 case WidgetHandle::Left:
407 operation = formLayoutLeftHandleOperation(dx, possibleOperations);
408 break;
409 case WidgetHandle::Right:
410 operation = formLayoutRightHandleOperation(dx, possibleOperations);
411 break;
412 default:
413 break;
414 }
415 if (operation) {
416 ChangeFormLayoutItemRoleCommand *fcmd = new ChangeFormLayoutItemRoleCommand(m_formWindow);
417 fcmd->init(widget: m_widget, op: static_cast<ChangeFormLayoutItemRoleCommand::Operation>(operation));
418 cmd = fcmd;
419 }
420 }
421 }
422 if (cmd) {
423 m_formWindow->commandHistory()->push(cmd);
424 } else {
425 // Cancelled/Invalid. Restore the size of the widget.
426 if (QFormLayout *form = managedLayoutOf<QFormLayout>(core: m_formWindow->core(), w: m_widget)) {
427 form->invalidate();
428 form->activate();
429 m_formWindow->clearSelection(changePropertyDisplay: false);
430 m_formWindow->selectWidget(w: m_widget);
431 }
432 }
433}
434
435void WidgetHandle::changeGridLayoutItemSpan()
436{
437 QDesignerLayoutDecorationExtension *deco = qt_extension<QDesignerLayoutDecorationExtension*>(manager: core()->extensionManager(), object: m_widget->parentWidget());
438 if (!deco)
439 return;
440 QGridLayout *grid = managedLayoutOf<QGridLayout>(core: m_formWindow->core(), w: m_widget);
441 if (!grid)
442 return;
443
444 const int index = deco->indexOf(widget: m_widget);
445 const QRect info = deco->itemInfo(index);
446 const int top = deco->findItemAt(row: info.top() - 1, column: info.left());
447 const int left = deco->findItemAt(row: info.top(), column: info.left() - 1);
448 const int bottom = deco->findItemAt(row: info.bottom() + 1, column: info.left());
449 const int right = deco->findItemAt(row: info.top(), column: info.right() + 1);
450
451 const QPoint pt = m_origGeom.center() - m_widget->geometry().center();
452
453 ChangeLayoutItemGeometry *cmd = nullptr;
454
455 switch (m_type) {
456 default:
457 break;
458
459 case WidgetHandle::Top: {
460 if (pt.y() < 0 && info.height() > 1) {
461 cmd = new ChangeLayoutItemGeometry(m_formWindow);
462 cmd->init(widget: m_widget, row: info.y() + 1, column: info.x(), rowspan: info.height() - 1, colspan: info.width());
463 } else if (pt.y() > 0 && top != -1 && grid->itemAt(index: top)->spacerItem()) {
464 cmd = new ChangeLayoutItemGeometry(m_formWindow);
465 cmd->init(widget: m_widget, row: info.y() - 1, column: info.x(), rowspan: info.height() + 1, colspan: info.width());
466 }
467 }
468 break;
469
470 case WidgetHandle::Left: {
471 if (pt.x() < 0 && info.width() > 1) {
472 cmd = new ChangeLayoutItemGeometry(m_formWindow);
473 cmd->init(widget: m_widget, row: info.y(), column: info.x() + 1, rowspan: info.height(), colspan: info.width() - 1);
474 } else if (pt.x() > 0 && left != -1 && grid->itemAt(index: left)->spacerItem()) {
475 cmd = new ChangeLayoutItemGeometry(m_formWindow);
476 cmd->init(widget: m_widget, row: info.y(), column: info.x() - 1, rowspan: info.height(), colspan: info.width() + 1);
477 }
478 }
479 break;
480
481 case WidgetHandle::Right: {
482 if (pt.x() > 0 && info.width() > 1) {
483 cmd = new ChangeLayoutItemGeometry(m_formWindow);
484 cmd->init(widget: m_widget, row: info.y(), column: info.x(), rowspan: info.height(), colspan: info.width() - 1);
485 } else if (pt.x() < 0 && right != -1 && grid->itemAt(index: right)->spacerItem()) {
486 cmd = new ChangeLayoutItemGeometry(m_formWindow);
487 cmd->init(widget: m_widget, row: info.y(), column: info.x(), rowspan: info.height(), colspan: info.width() + 1);
488 }
489 }
490 break;
491
492 case WidgetHandle::Bottom: {
493 if (pt.y() > 0 && info.height() > 1) {
494 cmd = new ChangeLayoutItemGeometry(m_formWindow);
495 cmd->init(widget: m_widget, row: info.y(), column: info.x(), rowspan: info.height() - 1, colspan: info.width());
496 } else if (pt.y() < 0 && bottom != -1 && grid->itemAt(index: bottom)->spacerItem()) {
497 cmd = new ChangeLayoutItemGeometry(m_formWindow);
498 cmd->init(widget: m_widget, row: info.y(), column: info.x(), rowspan: info.height() + 1, colspan: info.width());
499 }
500 }
501 break;
502 }
503
504 if (cmd != nullptr) {
505 m_formWindow->commandHistory()->push(cmd);
506 } else {
507 grid->invalidate();
508 grid->activate();
509 m_formWindow->clearSelection(changePropertyDisplay: false);
510 m_formWindow->selectWidget(w: m_widget);
511 }
512}
513
514void WidgetHandle::trySetGeometry(QWidget *w, int x, int y, int width, int height)
515{
516 if (!m_formWindow->hasFeature(f: FormWindow::EditFeature))
517 return;
518
519 int minw = w->minimumSize().width();
520 minw = qMax(a: minw, b: 2 * m_formWindow->grid().x());
521
522 int minh = w->minimumSize().height();
523 minh = qMax(a: minh, b: 2 * m_formWindow->grid().y());
524
525 if (qMax(a: minw, b: width) > w->maximumWidth() ||
526 qMax(a: minh, b: height) > w->maximumHeight())
527 return;
528
529 if (width < minw && x != w->x())
530 x -= minw - width;
531
532 if (height < minh && y != w->y())
533 y -= minh - height;
534
535 w->setGeometry(ax: x, ay: y, aw: qMax(a: minw, b: width), ah: qMax(a: minh, b: height));
536}
537
538void WidgetHandle::tryResize(QWidget *w, int width, int height)
539{
540 int minw = w->minimumSize().width();
541 minw = qMax(a: minw, b: 16);
542
543 int minh = w->minimumSize().height();
544 minh = qMax(a: minh, b: 16);
545
546 w->resize(w: qMax(a: minw, b: width), h: qMax(a: minh, b: height));
547}
548
549// ------------------ WidgetSelection
550
551WidgetSelection::WidgetState WidgetSelection::widgetState(const QDesignerFormEditorInterface *core, QWidget *w)
552{
553 bool isManaged;
554 const LayoutInfo::Type lt = LayoutInfo::laidoutWidgetType(core, widget: w, isManaged: &isManaged);
555 if (lt == LayoutInfo::NoLayout)
556 return UnlaidOut;
557 if (!isManaged)
558 return LaidOut;
559 switch (lt) {
560 case LayoutInfo::Grid:
561 return ManagedGridLayout;
562 case LayoutInfo::Form:
563 return ManagedFormLayout;
564 default:
565 break;
566 }
567 return LaidOut;
568}
569
570WidgetSelection::WidgetSelection(FormWindow *parent) :
571 m_widget(nullptr),
572 m_formWindow(parent)
573{
574 for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i)
575 m_handles[i] = new WidgetHandle(m_formWindow, static_cast<WidgetHandle::Type>(i), this);
576 hide();
577}
578
579void WidgetSelection::setWidget(QWidget *w)
580{
581 if (m_widget != nullptr)
582 m_widget->removeEventFilter(obj: this);
583
584 if (w == nullptr) {
585 hide();
586 m_widget = nullptr;
587 return;
588 }
589
590 m_widget = w;
591
592 m_widget->installEventFilter(filterObj: this);
593
594 updateActive();
595
596 updateGeometry();
597 show();
598}
599
600void WidgetSelection::updateActive()
601{
602 const WidgetState ws = widgetState(core: m_formWindow->core(), w: m_widget);
603 bool active[WidgetHandle::TypeCount];
604 std::fill(first: active, last: active + WidgetHandle::TypeCount, value: false);
605 // Determine active handles
606 switch (ws) {
607 case UnlaidOut:
608 std::fill(first: active, last: active + WidgetHandle::TypeCount, value: true);
609 break;
610 case ManagedGridLayout: // Grid: Allow changing span
611 active[WidgetHandle::Left] = active[WidgetHandle::Top] = active[WidgetHandle::Right] = active[WidgetHandle::Bottom] = true;
612 break;
613 case ManagedFormLayout: // Form: Allow changing column span
614 if (const unsigned operation = ChangeFormLayoutItemRoleCommand::possibleOperations(core: m_formWindow->core(), w: m_widget)) {
615 active[WidgetHandle::Left] = operation & (ChangeFormLayoutItemRoleCommand::SpanningToField|ChangeFormLayoutItemRoleCommand::FieldToSpanning);
616 active[WidgetHandle::Right] = operation & (ChangeFormLayoutItemRoleCommand::SpanningToLabel|ChangeFormLayoutItemRoleCommand::LabelToSpanning);
617 }
618 break;
619 default:
620 break;
621 }
622
623 for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i)
624 if (WidgetHandle *h = m_handles[i]) {
625 h->setWidget(m_widget);
626 h->setActive(active[i]);
627 }
628}
629
630bool WidgetSelection::isUsed() const
631{
632 return m_widget != nullptr;
633}
634
635void WidgetSelection::updateGeometry()
636{
637 if (!m_widget || !m_widget->parentWidget())
638 return;
639
640 QPoint p = m_widget->parentWidget()->mapToGlobal(m_widget->pos());
641 p = m_formWindow->formContainer()->mapFromGlobal(p);
642 const QRect r(p, m_widget->size());
643
644 const int w = 6;
645 const int h = 6;
646
647 for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i) {
648 WidgetHandle *hndl = m_handles[ i ];
649 if (!hndl)
650 continue;
651 switch (i) {
652 case WidgetHandle::LeftTop:
653 hndl->move(ax: r.x() - w / 2, ay: r.y() - h / 2);
654 break;
655 case WidgetHandle::Top:
656 hndl->move(ax: r.x() + r.width() / 2 - w / 2, ay: r.y() - h / 2);
657 break;
658 case WidgetHandle::RightTop:
659 hndl->move(ax: r.x() + r.width() - w / 2, ay: r.y() - h / 2);
660 break;
661 case WidgetHandle::Right:
662 hndl->move(ax: r.x() + r.width() - w / 2, ay: r.y() + r.height() / 2 - h / 2);
663 break;
664 case WidgetHandle::RightBottom:
665 hndl->move(ax: r.x() + r.width() - w / 2, ay: r.y() + r.height() - h / 2);
666 break;
667 case WidgetHandle::Bottom:
668 hndl->move(ax: r.x() + r.width() / 2 - w / 2, ay: r.y() + r.height() - h / 2);
669 break;
670 case WidgetHandle::LeftBottom:
671 hndl->move(ax: r.x() - w / 2, ay: r.y() + r.height() - h / 2);
672 break;
673 case WidgetHandle::Left:
674 hndl->move(ax: r.x() - w / 2, ay: r.y() + r.height() / 2 - h / 2);
675 break;
676 default:
677 break;
678 }
679 }
680}
681
682void WidgetSelection::hide()
683{
684 for (WidgetHandle *h : m_handles) {
685 if (h)
686 h->hide();
687 }
688}
689
690void WidgetSelection::show()
691{
692 for (WidgetHandle *h : m_handles) {
693 if (h) {
694 h->show();
695 h->raise();
696 }
697 }
698}
699
700void WidgetSelection::update()
701{
702 for (WidgetHandle *h : m_handles) {
703 if (h)
704 h->update();
705 }
706}
707
708QWidget *WidgetSelection::widget() const
709{
710 return m_widget;
711}
712
713QDesignerFormEditorInterface *WidgetSelection::core() const
714{
715 if (m_formWindow)
716 return m_formWindow->core();
717
718 return nullptr;
719}
720
721bool WidgetSelection::eventFilter(QObject *object, QEvent *event)
722{
723 if (object != widget())
724 return false;
725
726 switch (event->type()) {
727 default: break;
728
729 case QEvent::Move:
730 case QEvent::Resize:
731 updateGeometry();
732 break;
733 case QEvent::ZOrderChange:
734 show();
735 break;
736 } // end switch
737
738 return false;
739}
740
741}
742
743QT_END_NAMESPACE
744

source code of qttools/src/designer/src/components/formeditor/widgetselection.cpp