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 "qdesigner_menu_p.h" |
30 | #include "qdesigner_menubar_p.h" |
31 | #include "qdesigner_toolbar_p.h" |
32 | #include "qdesigner_command_p.h" |
33 | #include "qdesigner_propertycommand_p.h" |
34 | #include "actionrepository_p.h" |
35 | #include "actionprovider_p.h" |
36 | #include "actioneditor_p.h" |
37 | #include "qdesigner_utils_p.h" |
38 | #include "qdesigner_objectinspector_p.h" |
39 | |
40 | #include <QtCore/qtimer.h> |
41 | #include <QtCore/qdebug.h> |
42 | |
43 | #include <QtDesigner/abstractformeditor.h> |
44 | #include <QtDesigner/abstractwidgetfactory.h> |
45 | #include <QtDesigner/abstractmetadatabase.h> |
46 | #include <QtDesigner/qextensionmanager.h> |
47 | |
48 | #include <QtWidgets/qaction.h> |
49 | #include <QtWidgets/qapplication.h> |
50 | #include <QtWidgets/qlineedit.h> |
51 | #include <QtGui/qpainter.h> |
52 | #include <QtGui/qdrag.h> |
53 | #include <QtWidgets/qrubberband.h> |
54 | #include <QtWidgets/qtooltip.h> |
55 | #include <QtWidgets/qtoolbar.h> |
56 | #include <QtGui/qevent.h> |
57 | |
58 | Q_DECLARE_METATYPE(QAction*) |
59 | |
60 | QT_BEGIN_NAMESPACE |
61 | |
62 | using namespace qdesigner_internal; |
63 | |
64 | // give the user a little more space to click on the sub menu rectangle |
65 | static inline void extendClickableArea(QRect *, Qt::LayoutDirection dir) |
66 | { |
67 | switch (dir) { |
68 | case Qt::LayoutDirectionAuto: // Should never happen |
69 | case Qt::LeftToRight: |
70 | subMenuRect->setLeft(subMenuRect->left() - 20); |
71 | break; |
72 | case Qt::RightToLeft: |
73 | subMenuRect->setRight(subMenuRect->right() + 20); |
74 | break; |
75 | } |
76 | } |
77 | |
78 | QDesignerMenu::(QWidget *parent) : |
79 | QMenu(parent), |
80 | m_subMenuPixmap(QPixmap(QStringLiteral(":/qt-project.org/formeditor/images/submenu.png" ))), |
81 | m_currentIndex(0), |
82 | m_addItem(new SpecialMenuAction(this)), |
83 | m_addSeparator(new SpecialMenuAction(this)), |
84 | m_showSubMenuTimer(new QTimer(this)), |
85 | m_deactivateWindowTimer(new QTimer(this)), |
86 | m_adjustSizeTimer(new QTimer(this)), |
87 | m_editor(new QLineEdit(this)), |
88 | m_dragging(false), |
89 | m_lastSubMenuIndex(-1) |
90 | { |
91 | setContextMenuPolicy(Qt::DefaultContextMenu); |
92 | setAcceptDrops(true); // ### fake |
93 | setSeparatorsCollapsible(false); |
94 | |
95 | connect(sender: m_adjustSizeTimer, signal: &QTimer::timeout, receiver: this, slot: &QDesignerMenu::slotAdjustSizeNow); |
96 | m_addItem->setText(tr(s: "Type Here" )); |
97 | addAction(action: m_addItem); |
98 | |
99 | m_addSeparator->setText(tr(s: "Add Separator" )); |
100 | addAction(action: m_addSeparator); |
101 | |
102 | connect(sender: m_showSubMenuTimer, signal: &QTimer::timeout, receiver: this, slot: &QDesignerMenu::slotShowSubMenuNow); |
103 | |
104 | connect(sender: m_deactivateWindowTimer, signal: &QTimer::timeout, receiver: this, slot: &QDesignerMenu::slotDeactivateNow); |
105 | |
106 | m_editor->setObjectName(QStringLiteral("__qt__passive_editor" )); |
107 | m_editor->hide(); |
108 | |
109 | m_editor->installEventFilter(filterObj: this); |
110 | installEventFilter(filterObj: this); |
111 | } |
112 | |
113 | QDesignerMenu::() = default; |
114 | |
115 | void QDesignerMenu::() |
116 | { |
117 | // Not using a single-shot, since we want to compress the timers if many items are being |
118 | // adjusted |
119 | m_adjustSizeTimer->stop(); |
120 | adjustSize(); |
121 | } |
122 | |
123 | bool QDesignerMenu::handleEvent(QWidget *widget, QEvent *event) |
124 | { |
125 | if (event->type() == QEvent::FocusIn || event->type() == QEvent::FocusOut) { |
126 | update(); |
127 | |
128 | if (widget == m_editor) |
129 | return false; |
130 | } |
131 | |
132 | switch (event->type()) { |
133 | default: break; |
134 | |
135 | case QEvent::MouseButtonPress: |
136 | return handleMousePressEvent(widget, event: static_cast<QMouseEvent*>(event)); |
137 | case QEvent::MouseButtonRelease: |
138 | return handleMouseReleaseEvent(widget, event: static_cast<QMouseEvent*>(event)); |
139 | case QEvent::MouseButtonDblClick: |
140 | return handleMouseDoubleClickEvent(widget, event: static_cast<QMouseEvent*>(event)); |
141 | case QEvent::MouseMove: |
142 | return handleMouseMoveEvent(widget, event: static_cast<QMouseEvent*>(event)); |
143 | case QEvent::ContextMenu: |
144 | return handleContextMenuEvent(widget, event: static_cast<QContextMenuEvent*>(event)); |
145 | case QEvent::KeyPress: |
146 | return handleKeyPressEvent(widget, event: static_cast<QKeyEvent*>(event)); |
147 | } |
148 | |
149 | return true; |
150 | } |
151 | |
152 | void QDesignerMenu::(const QPoint &pos, Qt::KeyboardModifiers modifiers) |
153 | { |
154 | const int index = findAction(pos); |
155 | if (index >= realActionCount()) |
156 | return; |
157 | |
158 | QAction *action = safeActionAt(index); |
159 | |
160 | QDesignerFormWindowInterface *fw = formWindow(); |
161 | const Qt::DropAction dropAction = (modifiers & Qt::ControlModifier) ? Qt::CopyAction : Qt::MoveAction; |
162 | if (dropAction == Qt::MoveAction) { |
163 | RemoveActionFromCommand *cmd = new RemoveActionFromCommand(fw); |
164 | cmd->init(parentWidget: this, action, beforeAction: actions().at(i: index + 1)); |
165 | fw->commandHistory()->push(cmd); |
166 | } |
167 | |
168 | QDrag *drag = new QDrag(this); |
169 | drag->setPixmap(ActionRepositoryMimeData::actionDragPixmap(action)); |
170 | drag->setMimeData(new ActionRepositoryMimeData(action, dropAction)); |
171 | |
172 | const int old_index = m_currentIndex; |
173 | m_currentIndex = -1; |
174 | |
175 | if (drag->exec(supportedActions: dropAction) == Qt::IgnoreAction) { |
176 | if (dropAction == Qt::MoveAction) { |
177 | QAction *previous = safeActionAt(index); |
178 | InsertActionIntoCommand *cmd = new InsertActionIntoCommand(fw); |
179 | cmd->init(parentWidget: this, action, beforeAction: previous); |
180 | fw->commandHistory()->push(cmd); |
181 | } |
182 | |
183 | m_currentIndex = old_index; |
184 | } |
185 | } |
186 | |
187 | bool QDesignerMenu::handleKeyPressEvent(QWidget * /*widget*/, QKeyEvent *e) |
188 | { |
189 | m_showSubMenuTimer->stop(); |
190 | |
191 | if (m_editor->isHidden() && hasFocus()) { // In navigation mode |
192 | switch (e->key()) { |
193 | |
194 | case Qt::Key_Delete: |
195 | if (m_currentIndex == -1 || m_currentIndex >= realActionCount()) |
196 | break; |
197 | hideSubMenu(); |
198 | deleteAction(); |
199 | break; |
200 | |
201 | case Qt::Key_Left: |
202 | e->accept(); |
203 | moveLeft(); |
204 | return true; |
205 | |
206 | case Qt::Key_Right: |
207 | e->accept(); |
208 | moveRight(); |
209 | return true; // no update |
210 | |
211 | case Qt::Key_Up: |
212 | e->accept(); |
213 | moveUp(ctrl: e->modifiers() & Qt::ControlModifier); |
214 | return true; |
215 | |
216 | case Qt::Key_Down: |
217 | e->accept(); |
218 | moveDown(ctrl: e->modifiers() & Qt::ControlModifier); |
219 | return true; |
220 | |
221 | case Qt::Key_PageUp: |
222 | m_currentIndex = 0; |
223 | break; |
224 | |
225 | case Qt::Key_PageDown: |
226 | m_currentIndex = actions().count() - 1; |
227 | break; |
228 | |
229 | case Qt::Key_Enter: |
230 | case Qt::Key_Return: |
231 | case Qt::Key_F2: |
232 | e->accept(); |
233 | enterEditMode(); |
234 | return true; // no update |
235 | |
236 | case Qt::Key_Escape: |
237 | e->ignore(); |
238 | setFocus(); |
239 | hide(); |
240 | closeMenuChain(); |
241 | return true; |
242 | |
243 | case Qt::Key_Alt: |
244 | case Qt::Key_Shift: |
245 | case Qt::Key_Control: |
246 | e->ignore(); |
247 | setFocus(); // FIXME: this is because some other widget get the focus when CTRL is pressed |
248 | return true; // no update |
249 | |
250 | default: { |
251 | QAction *action = currentAction(); |
252 | if (!action || action->isSeparator() || action == m_addSeparator) { |
253 | e->ignore(); |
254 | return true; |
255 | } |
256 | if (!e->text().isEmpty() && e->text().at(i: 0).toLatin1() >= 32) { |
257 | showLineEdit(); |
258 | QApplication::sendEvent(receiver: m_editor, event: e); |
259 | e->accept(); |
260 | } else { |
261 | e->ignore(); |
262 | } |
263 | } |
264 | return true; |
265 | } |
266 | } else if (m_editor->hasFocus()) { // In edit mode |
267 | switch (e->key()) { |
268 | default: |
269 | e->ignore(); |
270 | return false; |
271 | |
272 | case Qt::Key_Enter: |
273 | case Qt::Key_Return: |
274 | if (!m_editor->text().isEmpty()) { |
275 | leaveEditMode(mode: ForceAccept); |
276 | m_editor->hide(); |
277 | setFocus(); |
278 | moveDown(ctrl: false); |
279 | break; |
280 | } |
281 | Q_FALLTHROUGH(); |
282 | |
283 | case Qt::Key_Escape: |
284 | m_editor->hide(); |
285 | setFocus(); |
286 | break; |
287 | } |
288 | } |
289 | |
290 | e->accept(); |
291 | update(); |
292 | |
293 | return true; |
294 | } |
295 | |
296 | static void sendMouseEventTo(QWidget *target, const QPoint &targetPoint, const QMouseEvent *event) |
297 | { |
298 | QMouseEvent e(event->type(), targetPoint, event->globalPos(), event->button(), event->buttons(), event->modifiers()); |
299 | QApplication::sendEvent(receiver: target, event: &e); |
300 | } |
301 | |
302 | bool QDesignerMenu::handleMouseDoubleClickEvent(QWidget *, QMouseEvent *event) |
303 | { |
304 | event->accept(); |
305 | m_startPosition = QPoint(); |
306 | |
307 | if ((event->buttons() & Qt::LeftButton) != Qt::LeftButton) |
308 | return true; |
309 | |
310 | if (!rect().contains(p: event->pos())) { |
311 | // special case for menubar |
312 | QWidget *target = QApplication::widgetAt(p: event->globalPos()); |
313 | QMenuBar *mb = qobject_cast<QMenuBar*>(object: target); |
314 | QDesignerMenu * = qobject_cast<QDesignerMenu*>(object: target); |
315 | if (mb != nullptr || menu != nullptr) { |
316 | const QPoint pt = target->mapFromGlobal(event->globalPos()); |
317 | QAction *action = mb == nullptr ? menu->actionAt(pt) : mb->actionAt(pt); |
318 | if (action) |
319 | sendMouseEventTo(target, targetPoint: pt, event); |
320 | } |
321 | return true; |
322 | } |
323 | |
324 | m_currentIndex = findAction(pos: event->pos()); |
325 | QAction *action = safeActionAt(index: m_currentIndex); |
326 | |
327 | QRect pm_rect; |
328 | if (action->menu() || hasSubMenuPixmap(action)) { |
329 | pm_rect = subMenuPixmapRect(action); |
330 | extendClickableArea(subMenuRect: &pm_rect, dir: layoutDirection()); |
331 | } |
332 | |
333 | if (!pm_rect.contains(p: event->pos()) && m_currentIndex != -1) |
334 | enterEditMode(); |
335 | |
336 | return true; |
337 | } |
338 | |
339 | bool QDesignerMenu::handleMousePressEvent(QWidget * /*widget*/, QMouseEvent *event) |
340 | { |
341 | if (!rect().contains(p: event->pos())) { |
342 | QWidget *clickedWidget = QApplication::widgetAt(p: event->globalPos()); |
343 | if (QMenuBar *mb = qobject_cast<QMenuBar*>(object: clickedWidget)) { |
344 | const QPoint pt = mb->mapFromGlobal(event->globalPos()); |
345 | if (QAction *action = mb->actionAt(pt)) { |
346 | QMenu * = action->menu(); |
347 | if (menu == findRootMenu()) { |
348 | // propagate the mouse press event (but don't close the popup) |
349 | sendMouseEventTo(target: mb, targetPoint: pt, event); |
350 | return true; |
351 | } |
352 | } |
353 | } |
354 | |
355 | if (QDesignerMenu *m = qobject_cast<QDesignerMenu *>(object: clickedWidget)) { |
356 | m->hideSubMenu(); |
357 | sendMouseEventTo(target: m, targetPoint: m->mapFromGlobal(event->globalPos()), event); |
358 | } else { |
359 | QDesignerMenu *root = findRootMenu(); |
360 | root->hide(); |
361 | root->hideSubMenu(); |
362 | } |
363 | if (clickedWidget) { |
364 | if (QWidget *focusProxy = clickedWidget->focusProxy()) |
365 | clickedWidget = focusProxy; |
366 | if (clickedWidget->focusPolicy() != Qt::NoFocus) |
367 | clickedWidget->setFocus(Qt::OtherFocusReason); |
368 | } |
369 | return true; |
370 | } |
371 | |
372 | m_showSubMenuTimer->stop(); |
373 | m_startPosition = QPoint(); |
374 | event->accept(); |
375 | |
376 | if (event->button() != Qt::LeftButton) |
377 | return true; |
378 | |
379 | m_startPosition = mapFromGlobal(event->globalPos()); |
380 | |
381 | const int index = findAction(pos: m_startPosition); |
382 | |
383 | QAction *action = safeActionAt(index); |
384 | QRect pm_rect = subMenuPixmapRect(action); |
385 | extendClickableArea(subMenuRect: &pm_rect, dir: layoutDirection()); |
386 | |
387 | const int old_index = m_currentIndex; |
388 | m_currentIndex = index; |
389 | if ((hasSubMenuPixmap(action) || action->menu() != nullptr) |
390 | && pm_rect.contains(p: m_startPosition)) { |
391 | if (m_currentIndex == m_lastSubMenuIndex) { |
392 | hideSubMenu(); |
393 | } else |
394 | slotShowSubMenuNow(); |
395 | } else { |
396 | if (index == old_index) { |
397 | if (m_currentIndex == m_lastSubMenuIndex) |
398 | hideSubMenu(); |
399 | } else { |
400 | hideSubMenu(); |
401 | } |
402 | } |
403 | |
404 | update(); |
405 | if (index != old_index) |
406 | selectCurrentAction(); |
407 | |
408 | return true; |
409 | } |
410 | |
411 | bool QDesignerMenu::handleMouseReleaseEvent(QWidget *, QMouseEvent *event) |
412 | { |
413 | event->accept(); |
414 | m_startPosition = QPoint(); |
415 | |
416 | return true; |
417 | } |
418 | |
419 | bool QDesignerMenu::handleMouseMoveEvent(QWidget *, QMouseEvent *event) |
420 | { |
421 | if ((event->buttons() & Qt::LeftButton) != Qt::LeftButton) |
422 | return true; |
423 | |
424 | if (!rect().contains(p: event->pos())) { |
425 | |
426 | if (QMenuBar *mb = qobject_cast<QMenuBar*>(object: QApplication::widgetAt(p: event->globalPos()))) { |
427 | const QPoint pt = mb->mapFromGlobal(event->globalPos()); |
428 | QAction *action = mb->actionAt(pt); |
429 | if (action && action->menu() == findRootMenu()) { |
430 | // propagate the mouse press event (but don't close the popup) |
431 | sendMouseEventTo(target: mb, targetPoint: pt, event); |
432 | return true; |
433 | } |
434 | // hide the popup Qt will replay the event |
435 | slotDeactivateNow(); |
436 | } |
437 | return true; |
438 | } |
439 | |
440 | if (m_startPosition.isNull()) |
441 | return true; |
442 | |
443 | event->accept(); |
444 | |
445 | const QPoint pos = mapFromGlobal(event->globalPos()); |
446 | |
447 | if ((pos - m_startPosition).manhattanLength() < qApp->startDragDistance()) |
448 | return true; |
449 | |
450 | startDrag(pos: m_startPosition, modifiers: event->modifiers()); |
451 | m_startPosition = QPoint(); |
452 | |
453 | return true; |
454 | } |
455 | |
456 | bool QDesignerMenu::handleContextMenuEvent(QWidget *, QContextMenuEvent *event) |
457 | { |
458 | event->accept(); |
459 | |
460 | const int index = findAction(pos: mapFromGlobal(event->globalPos())); |
461 | QAction *action = safeActionAt(index); |
462 | if (qobject_cast<SpecialMenuAction*>(object: action)) |
463 | return true; |
464 | |
465 | QMenu ; |
466 | QVariant itemData; |
467 | itemData.setValue(action); |
468 | |
469 | QAction *addSeparatorAction = menu.addAction(text: tr(s: "Insert separator" )); |
470 | addSeparatorAction->setData(itemData); |
471 | |
472 | QAction *removeAction = nullptr; |
473 | if (action->isSeparator()) |
474 | removeAction = menu.addAction(text: tr(s: "Remove separator" )); |
475 | else |
476 | removeAction = menu.addAction(text: tr(s: "Remove action '%1'" ).arg(a: action->objectName())); |
477 | removeAction->setData(itemData); |
478 | |
479 | connect(sender: addSeparatorAction, signal: &QAction::triggered, receiver: this, slot: &QDesignerMenu::slotAddSeparator); |
480 | connect(sender: removeAction, signal: &QAction::triggered, receiver: this, slot: &QDesignerMenu::slotRemoveSelectedAction); |
481 | menu.exec(pos: event->globalPos()); |
482 | |
483 | return true; |
484 | } |
485 | |
486 | void QDesignerMenu::() |
487 | { |
488 | QAction *action = qobject_cast<QAction *>(object: sender()); |
489 | if (!action) |
490 | return; |
491 | |
492 | QAction *a = qvariant_cast<QAction*>(v: action->data()); |
493 | Q_ASSERT(a != nullptr); |
494 | |
495 | const int pos = actions().indexOf(t: a); |
496 | QAction *action_before = nullptr; |
497 | if (pos != -1) |
498 | action_before = safeActionAt(index: pos); |
499 | |
500 | QDesignerFormWindowInterface *fw = formWindow(); |
501 | fw->beginCommand(description: tr(s: "Add separator" )); |
502 | QAction *sep = createAction(text: QString(), separator: true); |
503 | |
504 | InsertActionIntoCommand *cmd = new InsertActionIntoCommand(fw); |
505 | cmd->init(parentWidget: this, action: sep, beforeAction: action_before); |
506 | fw->commandHistory()->push(cmd); |
507 | |
508 | if (parentMenu()) { |
509 | QAction *parent_action = parentMenu()->currentAction(); |
510 | if (parent_action->menu() == nullptr) { |
511 | CreateSubmenuCommand *cmd = new CreateSubmenuCommand(fw); |
512 | cmd->init(menu: parentMenu(), action: parentMenu()->currentAction()); |
513 | fw->commandHistory()->push(cmd); |
514 | } |
515 | } |
516 | |
517 | fw->endCommand(); |
518 | } |
519 | |
520 | void QDesignerMenu::() |
521 | { |
522 | if (QAction *action = qobject_cast<QAction *>(object: sender())) |
523 | if (QAction *a = qvariant_cast<QAction*>(v: action->data())) |
524 | deleteAction(a); |
525 | } |
526 | |
527 | void QDesignerMenu::(QAction *a) |
528 | { |
529 | const int pos = actions().indexOf(t: a); |
530 | QAction *action_before = nullptr; |
531 | if (pos != -1) |
532 | action_before = safeActionAt(index: pos + 1); |
533 | |
534 | QDesignerFormWindowInterface *fw = formWindow(); |
535 | RemoveActionFromCommand *cmd = new RemoveActionFromCommand(fw); |
536 | cmd->init(parentWidget: this, action: a, beforeAction: action_before); |
537 | fw->commandHistory()->push(cmd); |
538 | } |
539 | |
540 | QRect QDesignerMenu::(QAction *action) const |
541 | { |
542 | const QRect g = actionGeometry(action); |
543 | const int x = layoutDirection() == Qt::LeftToRight ? (g.right() - m_subMenuPixmap.width() - 2) : 2; |
544 | const int y = g.top() + (g.height() - m_subMenuPixmap.height())/2 + 1; |
545 | return QRect(x, y, m_subMenuPixmap.width(), m_subMenuPixmap.height()); |
546 | } |
547 | |
548 | bool QDesignerMenu::(QAction *action) const |
549 | { |
550 | return action != nullptr |
551 | && qobject_cast<SpecialMenuAction*>(object: action) == 0 |
552 | && !action->isSeparator() |
553 | && !action->menu() |
554 | && canCreateSubMenu(action); |
555 | } |
556 | |
557 | void QDesignerMenu:: ( QShowEvent * event ) |
558 | { |
559 | selectCurrentAction(); |
560 | QMenu::showEvent (event); |
561 | } |
562 | |
563 | void QDesignerMenu::(QPaintEvent *event) |
564 | { |
565 | QMenu::paintEvent(event); |
566 | |
567 | QPainter p(this); |
568 | |
569 | QAction *current = currentAction(); |
570 | |
571 | const auto &actionList = actions(); |
572 | for (QAction *a : actionList) { |
573 | const QRect g = actionGeometry(a); |
574 | |
575 | if (qobject_cast<SpecialMenuAction*>(object: a)) { |
576 | QLinearGradient lg(g.left(), g.top(), g.left(), g.bottom()); |
577 | lg.setColorAt(pos: 0.0, color: Qt::transparent); |
578 | lg.setColorAt(pos: 0.7, color: QColor(0, 0, 0, 32)); |
579 | lg.setColorAt(pos: 1.0, color: Qt::transparent); |
580 | |
581 | p.fillRect(g, lg); |
582 | } else if (hasSubMenuPixmap(action: a)) { |
583 | p.drawPixmap(p: subMenuPixmapRect(action: a).topLeft(), pm: m_subMenuPixmap); |
584 | } |
585 | } |
586 | |
587 | if (!hasFocus() || !current || m_dragging) |
588 | return; |
589 | |
590 | if (QDesignerMenu * = parentMenu()) { |
591 | if (menu->dragging()) |
592 | return; |
593 | } |
594 | |
595 | if (QDesignerMenuBar * = qobject_cast<QDesignerMenuBar*>(object: parentWidget())) { |
596 | if (menubar->dragging()) |
597 | return; |
598 | } |
599 | |
600 | const QRect g = actionGeometry(current); |
601 | drawSelection(p: &p, r: g.adjusted(xp1: 1, yp1: 1, xp2: -3, yp2: -3)); |
602 | } |
603 | |
604 | bool QDesignerMenu::() const |
605 | { |
606 | return m_dragging; |
607 | } |
608 | |
609 | QDesignerMenu *QDesignerMenu::() const |
610 | { |
611 | if (parentMenu()) |
612 | return parentMenu()->findRootMenu(); |
613 | |
614 | return const_cast<QDesignerMenu*>(this); |
615 | } |
616 | |
617 | QDesignerMenu *QDesignerMenu::() const |
618 | { |
619 | if (QDesignerMenu * = qobject_cast<QDesignerMenu *>(object: QApplication::activeWindow())) { |
620 | if (activeDesignerMenu == this || findChildren<QDesignerMenu *>().contains(t: activeDesignerMenu)) |
621 | return activeDesignerMenu; |
622 | } |
623 | |
624 | return nullptr; |
625 | } |
626 | |
627 | bool QDesignerMenu::(QObject *object, QEvent *event) |
628 | { |
629 | if (object != this && object != m_editor) { |
630 | return false; |
631 | } |
632 | |
633 | if (!m_editor->isHidden() && object == m_editor && event->type() == QEvent::FocusOut) { |
634 | leaveEditMode(mode: Default); |
635 | m_editor->hide(); |
636 | update(); |
637 | return false; |
638 | } |
639 | |
640 | bool dispatch = true; |
641 | |
642 | switch (event->type()) { |
643 | default: break; |
644 | |
645 | case QEvent::WindowDeactivate: |
646 | deactivateMenu(); |
647 | break; |
648 | case QEvent::ContextMenu: |
649 | case QEvent::MouseButtonPress: |
650 | case QEvent::MouseButtonRelease: |
651 | case QEvent::MouseButtonDblClick: |
652 | |
653 | while (QApplication::activePopupWidget() && !qobject_cast<QDesignerMenu*>(object: QApplication::activePopupWidget())) { |
654 | QApplication::activePopupWidget()->close(); |
655 | } |
656 | |
657 | Q_FALLTHROUGH(); // fall through |
658 | case QEvent::KeyPress: |
659 | case QEvent::KeyRelease: |
660 | case QEvent::MouseMove: |
661 | dispatch = (object != m_editor); |
662 | Q_FALLTHROUGH(); // no break |
663 | |
664 | case QEvent::Enter: |
665 | case QEvent::Leave: |
666 | case QEvent::FocusIn: |
667 | case QEvent::FocusOut: |
668 | if (dispatch) |
669 | if (QWidget *widget = qobject_cast<QWidget*>(o: object)) |
670 | if (widget == this || isAncestorOf(child: widget)) |
671 | return handleEvent(widget, event); |
672 | break; |
673 | } |
674 | |
675 | return false; |
676 | }; |
677 | |
678 | int QDesignerMenu::(const QPoint &pos) const |
679 | { |
680 | const int index = actionIndexAt(w: this, pos, orientation: Qt::Vertical); |
681 | if (index == -1) |
682 | return realActionCount(); |
683 | |
684 | return index; |
685 | } |
686 | |
687 | void QDesignerMenu::(const QPoint &pos) |
688 | { |
689 | if (QDesignerActionProviderExtension *a = actionProvider()) { |
690 | a->adjustIndicator(pos); |
691 | } |
692 | } |
693 | |
694 | QDesignerMenu::ActionDragCheck QDesignerMenu::(QAction *action) const |
695 | { |
696 | if (!action || (action->menu() && action->menu()->parentWidget() != const_cast<QDesignerMenu*>(this))) |
697 | return NoActionDrag; // menu action!! nothing to do |
698 | |
699 | if (!Utils::isObjectAncestorOf(ancestor: formWindow()->mainContainer(), child: action)) |
700 | return NoActionDrag; // the action belongs to another form window |
701 | |
702 | if (actions().contains(t: action)) |
703 | return ActionDragOnSubMenu; // we already have the action in the menu |
704 | |
705 | return AcceptActionDrag; |
706 | } |
707 | |
708 | void QDesignerMenu::(QDragEnterEvent *event) |
709 | { |
710 | const ActionRepositoryMimeData *d = qobject_cast<const ActionRepositoryMimeData*>(object: event->mimeData()); |
711 | if (!d || d->actionList().isEmpty()) { |
712 | event->ignore(); |
713 | return; |
714 | } |
715 | |
716 | QAction *action = d->actionList().first(); |
717 | |
718 | switch (checkAction(action)) { |
719 | case NoActionDrag: |
720 | event->ignore(); |
721 | break; |
722 | case ActionDragOnSubMenu: |
723 | d->accept(event); |
724 | m_dragging = true; |
725 | break; |
726 | case AcceptActionDrag: |
727 | d->accept(event); |
728 | m_dragging = true; |
729 | adjustIndicator(pos: event->pos()); |
730 | break; |
731 | } |
732 | } |
733 | |
734 | void QDesignerMenu::(QDragMoveEvent *event) |
735 | { |
736 | if (actionGeometry(m_addSeparator).contains(p: event->pos())) { |
737 | event->ignore(); |
738 | adjustIndicator(pos: QPoint(-1, -1)); |
739 | return; |
740 | } |
741 | |
742 | const ActionRepositoryMimeData *d = qobject_cast<const ActionRepositoryMimeData*>(object: event->mimeData()); |
743 | if (!d || d->actionList().isEmpty()) { |
744 | event->ignore(); |
745 | return; |
746 | } |
747 | |
748 | QAction *action = d->actionList().first(); |
749 | const ActionDragCheck dc = checkAction(action); |
750 | switch (dc) { |
751 | case NoActionDrag: |
752 | event->ignore(); |
753 | break; |
754 | case ActionDragOnSubMenu: |
755 | case AcceptActionDrag: { // Do not pop up submenu of action being dragged |
756 | const int newIndex = findAction(pos: event->pos()); |
757 | if (safeActionAt(index: newIndex) != action) { |
758 | m_currentIndex = newIndex; |
759 | if (m_lastSubMenuIndex != m_currentIndex) |
760 | m_showSubMenuTimer->start(msec: 300); |
761 | } |
762 | if (dc == AcceptActionDrag) { |
763 | adjustIndicator(pos: event->pos()); |
764 | d->accept(event); |
765 | } else { |
766 | event->ignore(); |
767 | } |
768 | } |
769 | break; |
770 | } |
771 | } |
772 | |
773 | void QDesignerMenu::(QDragLeaveEvent *) |
774 | { |
775 | m_dragging = false; |
776 | adjustIndicator(pos: QPoint(-1, -1)); |
777 | m_showSubMenuTimer->stop(); |
778 | } |
779 | |
780 | void QDesignerMenu::(QDropEvent *event) |
781 | { |
782 | m_showSubMenuTimer->stop(); |
783 | hideSubMenu(); |
784 | m_dragging = false; |
785 | |
786 | QDesignerFormWindowInterface *fw = formWindow(); |
787 | const ActionRepositoryMimeData *d = qobject_cast<const ActionRepositoryMimeData*>(object: event->mimeData()); |
788 | if (!d || d->actionList().isEmpty()) { |
789 | event->ignore(); |
790 | return; |
791 | } |
792 | QAction *action = d->actionList().first(); |
793 | if (action && checkAction(action) == AcceptActionDrag) { |
794 | event->acceptProposedAction(); |
795 | int index = findAction(pos: event->pos()); |
796 | index = qMin(a: index, b: actions().count() - 1); |
797 | |
798 | fw->beginCommand(description: tr(s: "Insert action" )); |
799 | InsertActionIntoCommand *cmd = new InsertActionIntoCommand(fw); |
800 | cmd->init(parentWidget: this, action, beforeAction: safeActionAt(index)); |
801 | fw->commandHistory()->push(cmd); |
802 | |
803 | m_currentIndex = index; |
804 | |
805 | if (parentMenu()) { |
806 | QAction *parent_action = parentMenu()->currentAction(); |
807 | if (parent_action->menu() == nullptr) { |
808 | CreateSubmenuCommand *cmd = new CreateSubmenuCommand(fw); |
809 | cmd->init(menu: parentMenu(), action: parentMenu()->currentAction(), m_objectToSelect: action); |
810 | fw->commandHistory()->push(cmd); |
811 | } |
812 | } |
813 | update(); |
814 | fw->endCommand(); |
815 | } else { |
816 | event->ignore(); |
817 | } |
818 | adjustIndicator(pos: QPoint(-1, -1)); |
819 | } |
820 | |
821 | void QDesignerMenu::(QActionEvent *event) |
822 | { |
823 | QMenu::actionEvent(event); |
824 | m_adjustSizeTimer->start(msec: 0); |
825 | } |
826 | |
827 | QDesignerFormWindowInterface *QDesignerMenu::() const |
828 | { |
829 | if (parentMenu()) |
830 | return parentMenu()->formWindow(); |
831 | |
832 | return QDesignerFormWindowInterface::findFormWindow(w: parentWidget()); |
833 | } |
834 | |
835 | QDesignerActionProviderExtension *QDesignerMenu::() |
836 | { |
837 | if (QDesignerFormWindowInterface *fw = formWindow()) { |
838 | QDesignerFormEditorInterface *core = fw->core(); |
839 | return qt_extension<QDesignerActionProviderExtension*>(manager: core->extensionManager(), object: this); |
840 | } |
841 | |
842 | return nullptr; |
843 | } |
844 | |
845 | void QDesignerMenu::() |
846 | { |
847 | m_showSubMenuTimer->stop(); |
848 | |
849 | QWidget *w = this; |
850 | while (w && qobject_cast<QMenu*>(object: w)) |
851 | w = w->parentWidget(); |
852 | |
853 | if (w) { |
854 | const auto & = w->findChildren<QMenu *>(); |
855 | for (QMenu * : menus) |
856 | subMenu->hide(); |
857 | } |
858 | |
859 | m_lastSubMenuIndex = -1; |
860 | } |
861 | |
862 | // Close submenu using the left/right keys according to layoutDirection(). |
863 | // Return false to indicate the event must be propagated to the menu bar. |
864 | bool QDesignerMenu::() |
865 | { |
866 | if (parentMenu()) { |
867 | hide(); |
868 | return true; |
869 | } |
870 | closeMenuChain(); |
871 | update(); |
872 | return parentMenuBar() == nullptr; |
873 | } |
874 | |
875 | // Open a submenu using the left/right keys according to layoutDirection(). |
876 | // Return false to indicate the event must be propagated to the menu bar. |
877 | bool QDesignerMenu::() |
878 | { |
879 | const QAction *action = currentAction(); |
880 | |
881 | if (qobject_cast<const SpecialMenuAction*>(object: action) || action->isSeparator()) { |
882 | closeMenuChain(); |
883 | if (parentMenuBar()) |
884 | return false; |
885 | return true; |
886 | } |
887 | m_lastSubMenuIndex = -1; // force a refresh |
888 | slotShowSubMenuNow(); |
889 | return true; |
890 | } |
891 | |
892 | void QDesignerMenu::() |
893 | { |
894 | const bool handled = layoutDirection() == Qt::LeftToRight ? |
895 | hideSubMenuOnCursorKey() : showSubMenuOnCursorKey(); |
896 | if (!handled) |
897 | parentMenuBar()->moveLeft(); |
898 | } |
899 | |
900 | void QDesignerMenu::() |
901 | { |
902 | const bool handled = layoutDirection() == Qt::LeftToRight ? |
903 | showSubMenuOnCursorKey() : hideSubMenuOnCursorKey(); |
904 | if (!handled) |
905 | parentMenuBar()->moveRight(); |
906 | } |
907 | |
908 | void QDesignerMenu::(bool ctrl) |
909 | { |
910 | if (m_currentIndex == 0) { |
911 | hide(); |
912 | return; |
913 | } |
914 | |
915 | if (ctrl) |
916 | (void) swap(a: m_currentIndex, b: m_currentIndex - 1); |
917 | --m_currentIndex; |
918 | m_currentIndex = qMax(a: 0, b: m_currentIndex); |
919 | // Always re-select, swapping destroys order |
920 | update(); |
921 | selectCurrentAction(); |
922 | } |
923 | |
924 | void QDesignerMenu::(bool ctrl) |
925 | { |
926 | if (m_currentIndex == actions().count() - 1) { |
927 | return; |
928 | } |
929 | |
930 | if (ctrl) |
931 | (void) swap(a: m_currentIndex + 1, b: m_currentIndex); |
932 | |
933 | ++m_currentIndex; |
934 | m_currentIndex = qMin(a: actions().count() - 1, b: m_currentIndex); |
935 | update(); |
936 | if (!ctrl) |
937 | selectCurrentAction(); |
938 | } |
939 | |
940 | QAction *QDesignerMenu::() const |
941 | { |
942 | if (m_currentIndex < 0 || m_currentIndex >= actions().count()) |
943 | return nullptr; |
944 | |
945 | return safeActionAt(index: m_currentIndex); |
946 | } |
947 | |
948 | int QDesignerMenu::() const |
949 | { |
950 | return actions().count() - 2; // 2 fake actions |
951 | } |
952 | |
953 | void QDesignerMenu::() |
954 | { |
955 | QAction *action = currentAction(); |
956 | if (!action || action == m_addSeparator || action == m_addItem) |
957 | return; |
958 | |
959 | QDesignerObjectInspector *oi = nullptr; |
960 | if (QDesignerFormWindowInterface *fw = formWindow()) |
961 | oi = qobject_cast<QDesignerObjectInspector *>(object: fw->core()->objectInspector()); |
962 | |
963 | if (!oi) |
964 | return; |
965 | |
966 | oi->clearSelection(); |
967 | if (QMenu * = action->menu()) |
968 | oi->selectObject(o: menu); |
969 | else |
970 | oi->selectObject(o: action); |
971 | } |
972 | |
973 | void QDesignerMenu::(QAction *action) |
974 | { |
975 | if (action->menu()) |
976 | return; // nothing to do |
977 | |
978 | QDesignerFormWindowInterface *fw = formWindow(); |
979 | QDesignerFormEditorInterface *core = formWindow()->core(); |
980 | |
981 | QDesignerMenu * = findOrCreateSubMenu(action); |
982 | m_subMenus.remove(akey: action); |
983 | |
984 | action->setMenu(menu); |
985 | menu->setTitle(action->text()); |
986 | |
987 | Q_ASSERT(fw); |
988 | |
989 | core->widgetFactory()->initialize(object: menu); |
990 | |
991 | const QString niceObjectName = ActionEditor::actionTextToName(text: menu->title(), QStringLiteral("menu" )); |
992 | menu->setObjectName(niceObjectName); |
993 | |
994 | core->metaDataBase()->add(object: menu); |
995 | fw->ensureUniqueObjectName(object: menu); |
996 | |
997 | QAction * = menu->menuAction(); |
998 | core->metaDataBase()->add(object: menuAction); |
999 | } |
1000 | |
1001 | void QDesignerMenu::(QAction *action) |
1002 | { |
1003 | QDesignerMenu * = qobject_cast<QDesignerMenu*>(object: action->menu()); |
1004 | if (menu == nullptr) |
1005 | return; |
1006 | action->setMenu(nullptr); |
1007 | m_subMenus.insert(akey: action, avalue: menu); |
1008 | QDesignerFormEditorInterface *core = formWindow()->core(); |
1009 | core->metaDataBase()->remove(object: menu); |
1010 | } |
1011 | |
1012 | QDesignerMenu *QDesignerMenu::(QAction *action) |
1013 | { |
1014 | if (action->menu()) |
1015 | return qobject_cast<QDesignerMenu*>(object: action->menu()); |
1016 | |
1017 | QDesignerMenu * = m_subMenus.value(akey: action); |
1018 | if (!menu) { |
1019 | menu = new QDesignerMenu(this); |
1020 | m_subMenus.insert(akey: action, avalue: menu); |
1021 | } |
1022 | |
1023 | return menu; |
1024 | } |
1025 | |
1026 | bool QDesignerMenu::(QAction *action) const // ### improve it's a bit too slow |
1027 | { |
1028 | const QWidgetList &associatedWidgets = action->associatedWidgets(); |
1029 | for (const QWidget *aw : associatedWidgets) { |
1030 | if (aw != this) { |
1031 | if (const QMenu *m = qobject_cast<const QMenu *>(object: aw)) { |
1032 | if (m->actions().contains(t: action)) |
1033 | return false; // sorry |
1034 | } else { |
1035 | if (const QToolBar *tb = qobject_cast<const QToolBar *>(object: aw)) |
1036 | if (tb->actions().contains(t: action)) |
1037 | return false; // sorry |
1038 | } |
1039 | } |
1040 | } |
1041 | return true; |
1042 | } |
1043 | |
1044 | void QDesignerMenu::() |
1045 | { |
1046 | m_showSubMenuTimer->stop(); |
1047 | |
1048 | if (m_lastSubMenuIndex == m_currentIndex) |
1049 | return; |
1050 | |
1051 | if (m_lastSubMenuIndex != -1) |
1052 | hideSubMenu(); |
1053 | |
1054 | if (m_currentIndex >= realActionCount()) |
1055 | return; |
1056 | |
1057 | QAction *action = currentAction(); |
1058 | |
1059 | if (action->isSeparator() || !canCreateSubMenu(action)) |
1060 | return; |
1061 | |
1062 | if (QMenu * = findOrCreateSubMenu(action)) { |
1063 | if (!menu->isVisible()) { |
1064 | if ((menu->windowFlags() & Qt::Popup) != Qt::Popup) |
1065 | menu->setWindowFlags(Qt::Popup); |
1066 | const QRect g = actionGeometry(action); |
1067 | if (layoutDirection() == Qt::LeftToRight) { |
1068 | menu->move(mapToGlobal(g.topRight())); |
1069 | } else { |
1070 | // The position is not initially correct due to the unknown width, |
1071 | // causing it to overlap a bit the first time it is invoked. |
1072 | QPoint point = g.topLeft() - QPoint(menu->width() + 10, 0); |
1073 | menu->move(mapToGlobal(point)); |
1074 | } |
1075 | menu->show(); |
1076 | menu->setFocus(); |
1077 | } else { |
1078 | menu->raise(); |
1079 | } |
1080 | menu->setFocus(); |
1081 | |
1082 | m_lastSubMenuIndex = m_currentIndex; |
1083 | } |
1084 | } |
1085 | |
1086 | void QDesignerMenu::(QAction *action) |
1087 | { |
1088 | m_showSubMenuTimer->stop(); |
1089 | |
1090 | if (m_editor->isVisible() || !action || qobject_cast<SpecialMenuAction*>(object: action) |
1091 | || action->isSeparator() || !isVisible()) |
1092 | return; |
1093 | |
1094 | m_showSubMenuTimer->start(msec: 300); |
1095 | } |
1096 | |
1097 | QDesignerMenu *QDesignerMenu::() const |
1098 | { |
1099 | return qobject_cast<QDesignerMenu*>(object: parentWidget()); |
1100 | } |
1101 | |
1102 | QDesignerMenuBar *QDesignerMenu::() const |
1103 | { |
1104 | if (QDesignerMenuBar *mb = qobject_cast<QDesignerMenuBar*>(object: parentWidget())) |
1105 | return mb; |
1106 | if (QDesignerMenu *m = parentMenu()) |
1107 | return m->parentMenuBar(); |
1108 | |
1109 | return nullptr; |
1110 | } |
1111 | |
1112 | void QDesignerMenu::(bool visible) |
1113 | { |
1114 | if (visible) |
1115 | m_currentIndex = 0; |
1116 | else |
1117 | m_lastSubMenuIndex = -1; |
1118 | |
1119 | QMenu::setVisible(visible); |
1120 | |
1121 | } |
1122 | |
1123 | void QDesignerMenu::() |
1124 | { |
1125 | removeAction(action: m_addItem); |
1126 | removeAction(action: m_addSeparator); |
1127 | addAction(action: m_addItem); |
1128 | addAction(action: m_addSeparator); |
1129 | } |
1130 | |
1131 | void QDesignerMenu::() |
1132 | { |
1133 | if (m_currentIndex >= 0 && m_currentIndex <= realActionCount()) { |
1134 | showLineEdit(); |
1135 | } else { |
1136 | hideSubMenu(); |
1137 | QDesignerFormWindowInterface *fw = formWindow(); |
1138 | fw->beginCommand(description: tr(s: "Add separator" )); |
1139 | QAction *sep = createAction(text: QString(), separator: true); |
1140 | |
1141 | InsertActionIntoCommand *cmd = new InsertActionIntoCommand(fw); |
1142 | cmd->init(parentWidget: this, action: sep, beforeAction: safeActionAt(index: realActionCount())); |
1143 | fw->commandHistory()->push(cmd); |
1144 | |
1145 | if (parentMenu()) { |
1146 | QAction *parent_action = parentMenu()->currentAction(); |
1147 | if (parent_action->menu() == nullptr) { |
1148 | CreateSubmenuCommand *cmd = new CreateSubmenuCommand(fw); |
1149 | cmd->init(menu: parentMenu(), action: parentMenu()->currentAction()); |
1150 | fw->commandHistory()->push(cmd); |
1151 | } |
1152 | } |
1153 | |
1154 | fw->endCommand(); |
1155 | |
1156 | m_currentIndex = actions().indexOf(t: m_addItem); |
1157 | update(); |
1158 | } |
1159 | } |
1160 | |
1161 | void QDesignerMenu::(LeaveEditMode mode) |
1162 | { |
1163 | if (mode == Default) |
1164 | return; |
1165 | |
1166 | QAction *action = nullptr; |
1167 | |
1168 | QDesignerFormWindowInterface *fw = formWindow(); |
1169 | if (m_currentIndex < realActionCount()) { |
1170 | action = safeActionAt(index: m_currentIndex); |
1171 | fw->beginCommand(description: QApplication::translate(context: "Command" , key: "Set action text" )); |
1172 | } else { |
1173 | Q_ASSERT(fw != nullptr); |
1174 | fw->beginCommand(description: QApplication::translate(context: "Command" , key: "Insert action" )); |
1175 | action = createAction(text: ActionEditor::actionTextToName(text: m_editor->text())); |
1176 | InsertActionIntoCommand *cmd = new InsertActionIntoCommand(fw); |
1177 | cmd->init(parentWidget: this, action, beforeAction: currentAction()); |
1178 | fw->commandHistory()->push(cmd); |
1179 | } |
1180 | |
1181 | SetPropertyCommand *cmd = new SetPropertyCommand(fw); |
1182 | cmd->init(object: action, QStringLiteral("text" ), newValue: m_editor->text()); |
1183 | fw->commandHistory()->push(cmd); |
1184 | |
1185 | if (parentMenu()) { |
1186 | QAction *parent_action = parentMenu()->currentAction(); |
1187 | if (parent_action->menu() == nullptr) { |
1188 | CreateSubmenuCommand *cmd = new CreateSubmenuCommand(fw); |
1189 | cmd->init(menu: parentMenu(), action: parentMenu()->currentAction(), m_objectToSelect: action); |
1190 | fw->commandHistory()->push(cmd); |
1191 | } |
1192 | } |
1193 | |
1194 | update(); |
1195 | fw->endCommand(); |
1196 | } |
1197 | |
1198 | QAction *QDesignerMenu::(QDesignerMenu *) const |
1199 | { |
1200 | QAction *action = menu->menuAction(); |
1201 | |
1202 | if (!action) |
1203 | action = m_subMenus.key(avalue: menu); |
1204 | |
1205 | return action; |
1206 | } |
1207 | |
1208 | void QDesignerMenu::() |
1209 | { |
1210 | m_showSubMenuTimer->stop(); |
1211 | |
1212 | QAction *action = nullptr; |
1213 | |
1214 | if (m_currentIndex < realActionCount()) |
1215 | action = safeActionAt(index: m_currentIndex); |
1216 | else |
1217 | action = m_addItem; |
1218 | |
1219 | if (action->isSeparator()) |
1220 | return; |
1221 | |
1222 | hideSubMenu(); |
1223 | |
1224 | // open edit field for item name |
1225 | setFocus(); |
1226 | |
1227 | const QString text = action != m_addItem ? action->text() : QString(); |
1228 | m_editor->setText(text); |
1229 | m_editor->selectAll(); |
1230 | m_editor->setGeometry(actionGeometry(action).adjusted(xp1: 1, yp1: 1, xp2: -2, yp2: -2)); |
1231 | m_editor->show(); |
1232 | m_editor->setFocus(); |
1233 | } |
1234 | |
1235 | QAction *QDesignerMenu::(const QString &objectName, bool separator) |
1236 | { |
1237 | QDesignerFormWindowInterface *fw = formWindow(); |
1238 | Q_ASSERT(fw); |
1239 | return ToolBarEventFilter::createAction(fw, objectName, separator); |
1240 | } |
1241 | |
1242 | // ### share with QDesignerMenu::swap |
1243 | bool QDesignerMenu::(int a, int b) |
1244 | { |
1245 | const int left = qMin(a, b); |
1246 | int right = qMax(a, b); |
1247 | |
1248 | QAction *action_a = safeActionAt(index: left); |
1249 | QAction *action_b = safeActionAt(index: right); |
1250 | |
1251 | if (action_a == action_b |
1252 | || !action_a |
1253 | || !action_b |
1254 | || qobject_cast<SpecialMenuAction*>(object: action_a) |
1255 | || qobject_cast<SpecialMenuAction*>(object: action_b)) |
1256 | return false; // nothing to do |
1257 | |
1258 | right = qMin(a: right, b: realActionCount()); |
1259 | if (right < 0) |
1260 | return false; // nothing to do |
1261 | |
1262 | QDesignerFormWindowInterface *fw = formWindow(); |
1263 | fw->beginCommand(description: QApplication::translate(context: "Command" , key: "Move action" )); |
1264 | |
1265 | QAction *action_b_before = safeActionAt(index: right + 1); |
1266 | |
1267 | RemoveActionFromCommand *cmd1 = new RemoveActionFromCommand(fw); |
1268 | cmd1->init(parentWidget: this, action: action_b, beforeAction: action_b_before, update: false); |
1269 | fw->commandHistory()->push(cmd: cmd1); |
1270 | |
1271 | QAction *action_a_before = safeActionAt(index: left + 1); |
1272 | |
1273 | InsertActionIntoCommand *cmd2 = new InsertActionIntoCommand(fw); |
1274 | cmd2->init(parentWidget: this, action: action_b, beforeAction: action_a_before, update: false); |
1275 | fw->commandHistory()->push(cmd: cmd2); |
1276 | |
1277 | RemoveActionFromCommand *cmd3 = new RemoveActionFromCommand(fw); |
1278 | cmd3->init(parentWidget: this, action: action_a, beforeAction: action_b, update: false); |
1279 | fw->commandHistory()->push(cmd: cmd3); |
1280 | |
1281 | InsertActionIntoCommand *cmd4 = new InsertActionIntoCommand(fw); |
1282 | cmd4->init(parentWidget: this, action: action_a, beforeAction: action_b_before, update: true); |
1283 | fw->commandHistory()->push(cmd: cmd4); |
1284 | |
1285 | fw->endCommand(); |
1286 | |
1287 | return true; |
1288 | } |
1289 | |
1290 | QAction *QDesignerMenu::(int index) const |
1291 | { |
1292 | if (index < 0 || index >= actions().count()) |
1293 | return nullptr; |
1294 | |
1295 | return actions().at(i: index); |
1296 | } |
1297 | |
1298 | void QDesignerMenu::() |
1299 | { |
1300 | m_lastSubMenuIndex = -1; |
1301 | const auto & = findChildren<QMenu *>(); |
1302 | for (QMenu * : menus) |
1303 | subMenu->hide(); |
1304 | } |
1305 | |
1306 | void QDesignerMenu::() |
1307 | { |
1308 | QAction *action = currentAction(); |
1309 | const int pos = actions().indexOf(t: action); |
1310 | QAction *action_before = nullptr; |
1311 | if (pos != -1) |
1312 | action_before = safeActionAt(index: pos + 1); |
1313 | |
1314 | QDesignerFormWindowInterface *fw = formWindow(); |
1315 | RemoveActionFromCommand *cmd = new RemoveActionFromCommand(fw); |
1316 | cmd->init(parentWidget: this, action, beforeAction: action_before); |
1317 | fw->commandHistory()->push(cmd); |
1318 | |
1319 | update(); |
1320 | } |
1321 | |
1322 | void QDesignerMenu::() |
1323 | { |
1324 | m_deactivateWindowTimer->start(msec: 10); |
1325 | } |
1326 | |
1327 | void QDesignerMenu::() |
1328 | { |
1329 | m_deactivateWindowTimer->stop(); |
1330 | |
1331 | if (m_dragging) |
1332 | return; |
1333 | |
1334 | QDesignerMenu *root = findRootMenu(); |
1335 | |
1336 | if (! root->findActivatedMenu()) { |
1337 | root->hide(); |
1338 | root->hideSubMenu(); |
1339 | } |
1340 | } |
1341 | |
1342 | void QDesignerMenu::(QPainter *p, const QRect &r) |
1343 | { |
1344 | p->save(); |
1345 | |
1346 | QColor c = Qt::blue; |
1347 | p->setPen(QPen(c, 1)); |
1348 | c.setAlpha(32); |
1349 | p->setBrush(c); |
1350 | p->drawRect(r); |
1351 | |
1352 | p->restore(); |
1353 | } |
1354 | |
1355 | void QDesignerMenu::(QKeyEvent *event) |
1356 | { |
1357 | event->ignore(); |
1358 | } |
1359 | |
1360 | void QDesignerMenu::(QKeyEvent *event) |
1361 | { |
1362 | event->ignore(); |
1363 | } |
1364 | |
1365 | QT_END_NAMESPACE |
1366 | |