17#include <QtDesigner/abstractformeditor.h>
18#include <QtDesigner/abstractwidgetfactory.h>
19#include <QtDesigner/abstractmetadatabase.h>
20#include <QtDesigner/qextensionmanager.h>
22#include <QtWidgets/qapplication.h>
23#include <QtWidgets/qlineedit.h>
24#include <QtWidgets/qrubberband.h>
25#include <QtWidgets/qtooltip.h>
26#include <QtWidgets/qtoolbar.h>
28#include <QtGui/qaction.h>
29#include <QtGui/qdrag.h>
30#include <QtGui/qevent.h>
31#include <QtGui/qpainter.h>
33#include <QtCore/qtimer.h>
34#include <QtCore/qdebug.h>
38using namespace Qt::StringLiterals;
44 case Qt::LayoutDirectionAuto:
46 subMenuRect->setLeft(subMenuRect->left() - 20);
49 subMenuRect->setRight(subMenuRect->right() + 20);
64QDesignerMenu::QDesignerMenu(QWidget *parent) :
66 m_subMenuPixmap(QPixmap(u":/qt-project.org/formeditor/images/submenu.png"_s)),
68 m_addItem(
new qdesigner_internal::SpecialMenuAction(
this)),
69 m_addSeparator(
new qdesigner_internal::SpecialMenuAction(
this)),
70 m_showSubMenuTimer(
new QTimer(
this)),
71 m_deactivateWindowTimer(
new QTimer(
this)),
72 m_adjustSizeTimer(
new QTimer(
this)),
73 m_editor(
new qdesigner_internal::MenuActionLineEdit(
this)),
75 m_lastSubMenuIndex(-1)
77 setContextMenuPolicy(Qt::DefaultContextMenu);
79 setSeparatorsCollapsible(
false);
81 connect(m_adjustSizeTimer, &QTimer::timeout,
this, &QDesignerMenu::slotAdjustSizeNow);
82 m_addItem->setText(tr(
"Type Here"));
85 m_addSeparator->setText(tr(
"Add Separator"));
86 addAction(m_addSeparator);
88 connect(m_showSubMenuTimer, &QTimer::timeout,
this, &QDesignerMenu::slotShowSubMenuNow);
90 connect(m_deactivateWindowTimer, &QTimer::timeout,
this, &QDesignerMenu::slotDeactivateNow);
92 m_editor->setObjectName(u"__qt__passive_editor"_s);
95 connect(m_editor, &qdesigner_internal::MenuActionLineEdit::focusOut,
96 this, &QDesignerMenu::stopInlineEditing);
97 installEventFilter(
new qdesigner_internal::MenuEventFilter(
this));
100QDesignerMenu::~QDesignerMenu() =
default;
102void QDesignerMenu::slotAdjustSizeNow()
106 m_adjustSizeTimer->stop();
110void QDesignerMenu::stopInlineEditing()
112 if (!m_editor->isHidden()) {
113 leaveEditMode(Default);
119bool QDesignerMenu::handleEvent(QEvent *event)
121 switch (event->type()) {
122 case QEvent::MouseButtonPress:
123 return handleMousePressEvent(
static_cast<QMouseEvent*>(event));
124 case QEvent::MouseButtonRelease:
125 return handleMouseReleaseEvent(
static_cast<QMouseEvent*>(event));
126 case QEvent::MouseButtonDblClick:
127 return handleMouseDoubleClickEvent(
static_cast<QMouseEvent*>(event));
128 case QEvent::MouseMove:
129 return handleMouseMoveEvent(
static_cast<QMouseEvent*>(event));
130 case QEvent::ContextMenu:
131 return handleContextMenuEvent(
static_cast<QContextMenuEvent*>(event));
132 case QEvent::KeyPress:
133 return handleKeyPressEvent(
static_cast<QKeyEvent*>(event));
134 case QEvent::FocusIn:
135 case QEvent::FocusOut:
145void QDesignerMenu::startDrag(
const QPoint &pos, Qt::KeyboardModifiers modifiers)
147 using namespace qdesigner_internal;
149 const int index = findAction(pos);
150 if (index >= realActionCount())
153 QAction *action = safeActionAt(index);
155 QDesignerFormWindowInterface *fw = formWindow();
156 const Qt::DropAction dropAction = (modifiers & Qt::ControlModifier) ? Qt::CopyAction : Qt::MoveAction;
157 if (dropAction == Qt::MoveAction) {
158 auto *cmd =
new RemoveActionFromCommand(fw);
159 cmd->init(
this, action, actions().at(index + 1));
160 fw->commandHistory()->push(cmd);
163 QDrag *drag =
new QDrag(
this);
164 drag->setPixmap(ActionRepositoryMimeData::actionDragPixmap(action));
165 drag->setMimeData(
new ActionRepositoryMimeData(action, dropAction));
167 const int old_index = m_currentIndex;
170 if (drag->exec(dropAction) == Qt::IgnoreAction) {
171 if (dropAction == Qt::MoveAction) {
172 QAction *previous = safeActionAt(index);
173 auto *cmd =
new InsertActionIntoCommand(fw);
174 cmd->init(
this, action, previous);
175 fw->commandHistory()->push(cmd);
178 m_currentIndex = old_index;
182bool QDesignerMenu::handleKeyPressEvent(QKeyEvent *e)
184 m_showSubMenuTimer->stop();
186 if (m_editor->isHidden() && hasFocus()) {
190 if (m_currentIndex == -1 || m_currentIndex >= realActionCount())
208 moveUp(e->modifiers() & Qt::ControlModifier);
213 moveDown(e->modifiers() & Qt::ControlModifier);
220 case Qt::Key_PageDown:
221 m_currentIndex = actions().size() - 1;
240 case Qt::Key_Control:
246 QAction *action = currentAction();
247 if (!action || action->isSeparator() || action == m_addSeparator) {
251 if (!e->text().isEmpty() && e->text().at(0).toLatin1() >= 32) {
253 QApplication::sendEvent(m_editor, e);
261 }
else if (m_editor->hasFocus()) {
269 if (!m_editor->text().isEmpty()) {
270 leaveEditMode(ForceAccept);
293 QMouseEvent e(event->type(), targetPoint, event->globalPosition().toPoint(), event->button(), event->buttons(), event->modifiers());
294 QApplication::sendEvent(target, &e);
297bool QDesignerMenu::handleMouseDoubleClickEvent(QMouseEvent *event)
300 m_startPosition = QPoint();
302 if ((event->buttons() & Qt::LeftButton) != Qt::LeftButton)
305 if (!rect().contains(event->position().toPoint())) {
307 QWidget *target = QApplication::widgetAt(event->globalPosition().toPoint());
308 QMenuBar *mb = qobject_cast<QMenuBar*>(target);
309 QDesignerMenu *menu = qobject_cast<QDesignerMenu*>(target);
310 if (mb !=
nullptr || menu !=
nullptr) {
311 const QPoint pt = target->mapFromGlobal(event->globalPosition().toPoint());
312 QAction *action = mb ==
nullptr ? menu->actionAt(pt) : mb->actionAt(pt);
314 sendMouseEventTo(target, pt, event);
319 m_currentIndex = findAction(event->position().toPoint());
320 QAction *action = safeActionAt(m_currentIndex);
323 if (action->menu() || hasSubMenuPixmap(action)) {
324 pm_rect = subMenuPixmapRect(action);
325 extendClickableArea(&pm_rect, layoutDirection());
328 if (!pm_rect.contains(event->position().toPoint()) && m_currentIndex != -1)
334bool QDesignerMenu::handleMousePressEvent(QMouseEvent *event)
336 if (!rect().contains(event->position().toPoint())) {
337 QWidget *clickedWidget = QApplication::widgetAt(event->globalPosition().toPoint());
338 if (QMenuBar *mb = qobject_cast<QMenuBar*>(clickedWidget)) {
339 const QPoint pt = mb->mapFromGlobal(event->globalPosition().toPoint());
340 if (QAction *action = mb->actionAt(pt)) {
341 QMenu * menu = action->menu();
342 if (menu == findRootMenu()) {
344 sendMouseEventTo(mb, pt, event);
350 if (QDesignerMenu *m = qobject_cast<QDesignerMenu *>(clickedWidget)) {
352 sendMouseEventTo(m, m->mapFromGlobal(event->globalPosition().toPoint()), event);
354 QDesignerMenu *root = findRootMenu();
359 if (QWidget *focusProxy = clickedWidget->focusProxy())
360 clickedWidget = focusProxy;
361 if (clickedWidget->focusPolicy() != Qt::NoFocus)
362 clickedWidget->setFocus(Qt::OtherFocusReason);
367 m_showSubMenuTimer->stop();
368 m_startPosition = QPoint();
371 if (event->button() != Qt::LeftButton)
374 m_startPosition = mapFromGlobal(event->globalPosition().toPoint());
376 const int index = findAction(m_startPosition);
378 QAction *action = safeActionAt(index);
379 QRect pm_rect = subMenuPixmapRect(action);
380 extendClickableArea(&pm_rect, layoutDirection());
382 const int old_index = m_currentIndex;
383 m_currentIndex = index;
384 if ((hasSubMenuPixmap(action) || action->menu() !=
nullptr)
385 && pm_rect.contains(m_startPosition)) {
386 if (m_currentIndex == m_lastSubMenuIndex) {
389 slotShowSubMenuNow();
391 if (index == old_index) {
392 if (m_currentIndex == m_lastSubMenuIndex)
400 if (index != old_index)
401 selectCurrentAction();
406bool QDesignerMenu::handleMouseReleaseEvent(QMouseEvent *event)
409 m_startPosition = QPoint();
414bool QDesignerMenu::handleMouseMoveEvent(QMouseEvent *event)
416 if ((event->buttons() & Qt::LeftButton) != Qt::LeftButton)
419 if (!rect().contains(event->position().toPoint())) {
421 if (QMenuBar *mb = qobject_cast<QMenuBar*>(QApplication::widgetAt(event->globalPosition().toPoint()))) {
422 const QPoint pt = mb->mapFromGlobal(event->globalPosition().toPoint());
423 QAction *action = mb->actionAt(pt);
424 if (action && action->menu() == findRootMenu()) {
426 sendMouseEventTo(mb, pt, event);
435 if (m_startPosition.isNull())
440 const QPoint pos = mapFromGlobal(event->globalPosition().toPoint());
442 if ((pos - m_startPosition).manhattanLength() < qApp->startDragDistance())
445 startDrag(m_startPosition, event->modifiers());
446 m_startPosition = QPoint();
451bool QDesignerMenu::handleContextMenuEvent(QContextMenuEvent *event)
455 const int index = findAction(mapFromGlobal(event->globalPos()));
456 QAction *action = safeActionAt(index);
457 if (qobject_cast<qdesigner_internal::SpecialMenuAction*>(action))
462 itemData.setValue(action);
464 QAction *addSeparatorAction = menu.addAction(tr(
"Insert separator"));
465 addSeparatorAction->setData(itemData);
467 QAction *removeAction =
nullptr;
468 if (action->isSeparator())
469 removeAction = menu.addAction(tr(
"Remove separator"));
471 removeAction = menu.addAction(tr(
"Remove action '%1'").arg(action->objectName()));
472 removeAction->setData(itemData);
474 connect(addSeparatorAction, &QAction::triggered,
this, &QDesignerMenu::slotAddSeparator);
475 connect(removeAction, &QAction::triggered,
this, &QDesignerMenu::slotRemoveSelectedAction);
476 menu.exec(event->globalPos());
481void QDesignerMenu::slotAddSeparator()
483 QAction *action = qobject_cast<QAction *>(sender());
487 QAction *a = qvariant_cast<QAction*>(action->data());
488 Q_ASSERT(a !=
nullptr);
490 const int pos = actions().indexOf(a);
491 QAction *action_before =
nullptr;
493 action_before = safeActionAt(pos);
495 QDesignerFormWindowInterface *fw = formWindow();
496 fw->beginCommand(tr(
"Add separator"));
497 QAction *sep = createAction(QString(),
true);
499 auto *cmd =
new qdesigner_internal::InsertActionIntoCommand(fw);
500 cmd->init(
this, sep, action_before);
501 fw->commandHistory()->push(cmd);
504 QAction *parent_action = parentMenu()->currentAction();
505 if (parent_action->menu() ==
nullptr) {
506 auto *cmd =
new qdesigner_internal::CreateSubmenuCommand(fw);
507 cmd->init(parentMenu(), parentMenu()->currentAction());
508 fw->commandHistory()->push(cmd);
515void QDesignerMenu::slotRemoveSelectedAction()
517 if (QAction *action = qobject_cast<QAction *>(sender()))
518 if (QAction *a = qvariant_cast<QAction*>(action->data()))
522void QDesignerMenu::deleteAction(QAction *a)
524 const int pos = actions().indexOf(a);
525 QAction *action_before =
nullptr;
527 action_before = safeActionAt(pos + 1);
529 QDesignerFormWindowInterface *fw = formWindow();
530 auto *cmd =
new qdesigner_internal::RemoveActionFromCommand(fw);
531 cmd->init(
this, a, action_before);
532 fw->commandHistory()->push(cmd);
535QRect QDesignerMenu::subMenuPixmapRect(QAction *action)
const
537 const QRect g = actionGeometry(action);
538 const int x = layoutDirection() == Qt::LeftToRight ? (g.right() - m_subMenuPixmap.width() - 2) : 2;
539 const int y = g.top() + (g.height() - m_subMenuPixmap.height())/2 + 1;
540 return QRect(x, y, m_subMenuPixmap.width(), m_subMenuPixmap.height());
543bool QDesignerMenu::hasSubMenuPixmap(QAction *action)
const
545 return action !=
nullptr
546 && qobject_cast<qdesigner_internal::SpecialMenuAction*>(action) ==
nullptr
547 && !action->isSeparator()
549 && canCreateSubMenu(action);
552void QDesignerMenu::showEvent ( QShowEvent * event )
554 selectCurrentAction();
555 QMenu::showEvent (event);
558void QDesignerMenu::paintEvent(QPaintEvent *event)
560 using namespace qdesigner_internal;
562 QMenu::paintEvent(event);
566 QAction *current = currentAction();
568 const auto &actionList = actions();
569 for (QAction *a : actionList) {
570 const QRect g = actionGeometry(a);
572 if (qobject_cast<SpecialMenuAction*>(a)) {
573 QLinearGradient lg(g.left(), g.top(), g.left(), g.bottom());
574 lg.setColorAt(0.0, Qt::transparent);
575 lg.setColorAt(0.7, QColor(0, 0, 0, 32));
576 lg.setColorAt(1.0, Qt::transparent);
579 }
else if (hasSubMenuPixmap(a)) {
580 p.drawPixmap(subMenuPixmapRect(a).topLeft(), m_subMenuPixmap);
584 if (!hasFocus() || !current || m_dragging)
587 if (QDesignerMenu *menu = parentMenu()) {
588 if (menu->dragging())
592 if (QDesignerMenuBar *menubar = qobject_cast<QDesignerMenuBar*>(parentWidget())) {
593 if (menubar->dragging())
597 const QRect g = actionGeometry(current);
598 drawSelection(&p, g.adjusted(1, 1, -3, -3));
601bool QDesignerMenu::dragging()
const
606QDesignerMenu *QDesignerMenu::findRootMenu()
const
609 return parentMenu()->findRootMenu();
611 return const_cast<QDesignerMenu*>(
this);
614QDesignerMenu *QDesignerMenu::findActivatedMenu()
const
616 if (QDesignerMenu *activeDesignerMenu = qobject_cast<QDesignerMenu *>(QApplication::activeWindow())) {
617 if (activeDesignerMenu ==
this || findChildren<QDesignerMenu *>().contains(activeDesignerMenu))
618 return activeDesignerMenu;
626 switch (event->type()) {
627 case QEvent::WindowDeactivate:
628 if (
auto *menu = qobject_cast<QDesignerMenu *>(object))
629 menu->deactivateMenu();
631 case QEvent::ContextMenu:
632 case QEvent::MouseButtonPress:
633 case QEvent::MouseButtonRelease:
634 case QEvent::MouseButtonDblClick:
636 while (QApplication::activePopupWidget() && !qobject_cast<QDesignerMenu*>(QApplication::activePopupWidget())) {
637 QApplication::activePopupWidget()->close();
641 case QEvent::KeyPress:
642 case QEvent::KeyRelease:
643 case QEvent::MouseMove:
646 case QEvent::FocusIn:
647 case QEvent::FocusOut: {
648 auto *menu = qobject_cast<QDesignerMenu *>(object);
650 return menu->handleEvent(event);
656 return QObject::eventFilter(object, event);
659int QDesignerMenu::findAction(
const QPoint &pos)
const
661 const int index = actionIndexAt(
this, pos, Qt::Vertical);
663 return realActionCount();
668void QDesignerMenu::adjustIndicator(
const QPoint &pos)
670 if (QDesignerActionProviderExtension *a = actionProvider()) {
671 a->adjustIndicator(pos);
675QDesignerMenu::ActionDragCheck QDesignerMenu::checkAction(QAction *action)
const
677 if (!action || (action->menu() && action->menu()->parentWidget() !=
const_cast<QDesignerMenu*>(
this)))
680 if (!qdesigner_internal::Utils::isObjectAncestorOf(formWindow()->mainContainer(), action))
683 if (actions().contains(action))
684 return ActionDragOnSubMenu;
686 return AcceptActionDrag;
689void QDesignerMenu::dragEnterEvent(QDragEnterEvent *event)
691 auto *d = qobject_cast<
const qdesigner_internal::ActionRepositoryMimeData*>(event->mimeData());
692 if (!d || d->actionList().isEmpty()) {
697 QAction *action = d->actionList().first();
699 switch (checkAction(action)) {
703 case ActionDragOnSubMenu:
707 case AcceptActionDrag:
710 adjustIndicator(event->position().toPoint());
715void QDesignerMenu::dragMoveEvent(QDragMoveEvent *event)
717 if (actionGeometry(m_addSeparator).contains(event->position().toPoint())) {
719 adjustIndicator(QPoint(-1, -1));
723 auto *d = qobject_cast<
const qdesigner_internal::ActionRepositoryMimeData*>(event->mimeData());
724 if (!d || d->actionList().isEmpty()) {
729 QAction *action = d->actionList().first();
730 const ActionDragCheck dc = checkAction(action);
735 case ActionDragOnSubMenu:
736 case AcceptActionDrag: {
737 const int newIndex = findAction(event->position().toPoint());
738 if (safeActionAt(newIndex) != action) {
739 m_currentIndex = newIndex;
740 if (m_lastSubMenuIndex != m_currentIndex)
741 m_showSubMenuTimer->start(300);
743 if (dc == AcceptActionDrag) {
744 adjustIndicator(event->position().toPoint());
754void QDesignerMenu::dragLeaveEvent(QDragLeaveEvent *)
757 adjustIndicator(QPoint(-1, -1));
758 m_showSubMenuTimer->stop();
761void QDesignerMenu::dropEvent(QDropEvent *event)
763 m_showSubMenuTimer->stop();
767 QDesignerFormWindowInterface *fw = formWindow();
768 auto *d = qobject_cast<
const qdesigner_internal::ActionRepositoryMimeData*>(event->mimeData());
769 if (!d || d->actionList().isEmpty()) {
773 QAction *action = d->actionList().first();
774 if (action && checkAction(action) == AcceptActionDrag) {
775 event->acceptProposedAction();
776 int index = findAction(event->position().toPoint());
777 index = qMin(index, actions().size() - 1);
779 fw->beginCommand(tr(
"Insert action"));
780 auto *cmd =
new qdesigner_internal::InsertActionIntoCommand(fw);
781 cmd->init(
this, action, safeActionAt(index));
782 fw->commandHistory()->push(cmd);
784 m_currentIndex = index;
787 QAction *parent_action = parentMenu()->currentAction();
788 if (parent_action->menu() ==
nullptr) {
789 auto *cmd =
new qdesigner_internal::CreateSubmenuCommand(fw);
790 cmd->init(parentMenu(), parentMenu()->currentAction(), action);
791 fw->commandHistory()->push(cmd);
799 adjustIndicator(QPoint(-1, -1));
802void QDesignerMenu::actionEvent(QActionEvent *event)
804 QMenu::actionEvent(event);
805 m_adjustSizeTimer->start(0);
808QDesignerFormWindowInterface *QDesignerMenu::formWindow()
const
811 return parentMenu()->formWindow();
813 return QDesignerFormWindowInterface::findFormWindow(parentWidget());
816QDesignerActionProviderExtension *QDesignerMenu::actionProvider()
818 if (QDesignerFormWindowInterface *fw = formWindow()) {
819 QDesignerFormEditorInterface *core = fw->core();
820 return qt_extension<QDesignerActionProviderExtension*>(core->extensionManager(),
this);
826void QDesignerMenu::closeMenuChain()
828 m_showSubMenuTimer->stop();
831 while (w && qobject_cast<QMenu*>(w))
832 w = w->parentWidget();
835 const auto &menus = w->findChildren<QMenu *>();
836 for (QMenu *subMenu : menus)
840 m_lastSubMenuIndex = -1;
845bool QDesignerMenu::hideSubMenuOnCursorKey()
853 return parentMenuBar() ==
nullptr;
858bool QDesignerMenu::showSubMenuOnCursorKey()
860 using namespace qdesigner_internal;
862 const QAction *action = currentAction();
864 if (qobject_cast<
const SpecialMenuAction*>(action) || action->isSeparator()) {
870 m_lastSubMenuIndex = -1;
871 slotShowSubMenuNow();
875void QDesignerMenu::moveLeft()
877 const bool handled = layoutDirection() == Qt::LeftToRight ?
878 hideSubMenuOnCursorKey() : showSubMenuOnCursorKey();
880 parentMenuBar()->moveLeft();
883void QDesignerMenu::moveRight()
885 const bool handled = layoutDirection() == Qt::LeftToRight ?
886 showSubMenuOnCursorKey() : hideSubMenuOnCursorKey();
888 parentMenuBar()->moveRight();
891void QDesignerMenu::moveUp(
bool ctrl)
893 if (m_currentIndex == 0) {
899 (
void) swap(m_currentIndex, m_currentIndex - 1);
901 m_currentIndex = qMax(0, m_currentIndex);
904 selectCurrentAction();
907void QDesignerMenu::moveDown(
bool ctrl)
909 if (m_currentIndex == actions().size() - 1) {
914 (
void) swap(m_currentIndex + 1, m_currentIndex);
917 m_currentIndex = qMin(actions().size() - 1, m_currentIndex);
920 selectCurrentAction();
923QAction *QDesignerMenu::currentAction()
const
925 if (m_currentIndex < 0 || m_currentIndex >= actions().size())
928 return safeActionAt(m_currentIndex);
931int QDesignerMenu::realActionCount()
const
933 return actions().size() - 2;
936void QDesignerMenu::selectCurrentAction()
938 using namespace qdesigner_internal;
940 QAction *action = currentAction();
941 if (!action || action == m_addSeparator || action == m_addItem)
944 QDesignerObjectInspector *oi =
nullptr;
945 ActionEditor *ae =
nullptr;
946 if (QDesignerFormWindowInterface *fw = formWindow()) {
947 auto core = fw->core();
948 oi = qobject_cast<QDesignerObjectInspector *>(core->objectInspector());
949 ae = qobject_cast<ActionEditor *>(core->actionEditor());
955 oi->clearSelection();
956 if (QMenu *menu = action->menu()) {
957 oi->selectObject(menu);
959 ae->clearSelection();
961 oi->selectObject(action);
963 ae->selectAction(action);
967void QDesignerMenu::createRealMenuAction(QAction *action)
969 using namespace qdesigner_internal;
974 QDesignerFormWindowInterface *fw = formWindow();
975 QDesignerFormEditorInterface *core = formWindow()->core();
977 QDesignerMenu *menu = findOrCreateSubMenu(action);
978 m_subMenus.remove(action);
980 action->setMenu(menu);
981 menu->setTitle(action->text());
985 core->widgetFactory()->initialize(menu);
987 const QString niceObjectName = ActionEditor::actionTextToName(menu->title(), u"menu"_s);
988 menu->setObjectName(niceObjectName);
990 core->metaDataBase()->add(menu);
991 fw->ensureUniqueObjectName(menu);
993 QAction *menuAction = menu->menuAction();
994 core->metaDataBase()->add(menuAction);
997void QDesignerMenu::removeRealMenu(QAction *action)
999 QDesignerMenu *menu = qobject_cast<QDesignerMenu*>(action->menu());
1000 if (menu ==
nullptr)
1002 action->setMenu(
nullptr);
1003 m_subMenus.insert(action, menu);
1004 QDesignerFormEditorInterface *core = formWindow()->core();
1005 core->metaDataBase()->remove(menu);
1008QDesignerMenu *QDesignerMenu::findOrCreateSubMenu(QAction *action)
1011 return qobject_cast<QDesignerMenu*>(action->menu());
1013 QDesignerMenu *menu = m_subMenus.value(action);
1015 menu =
new QDesignerMenu(
this);
1016 m_subMenus.insert(action, menu);
1022bool QDesignerMenu::canCreateSubMenu(QAction *action)
const
1024 const QObjectList associatedObjects = action->associatedObjects();
1025 for (
const QObject *ao : associatedObjects) {
1027 if (
const QMenu *m = qobject_cast<
const QMenu *>(ao)) {
1028 if (m->actions().contains(action))
1030 }
else if (
const QToolBar *tb = qobject_cast<
const QToolBar *>(ao)) {
1031 if (tb->actions().contains(action))
1039void QDesignerMenu::slotShowSubMenuNow()
1041 m_showSubMenuTimer->stop();
1043 if (m_lastSubMenuIndex == m_currentIndex)
1046 if (m_lastSubMenuIndex != -1)
1049 if (m_currentIndex >= realActionCount())
1052 QAction *action = currentAction();
1054 if (action->isSeparator() || !canCreateSubMenu(action))
1057 if (QMenu *menu = findOrCreateSubMenu(action)) {
1058 if (!menu->isVisible()) {
1059 if ((menu->windowFlags() & Qt::Popup) != Qt::Popup)
1060 menu->setWindowFlags(Qt::Popup);
1061 const QRect g = actionGeometry(action);
1062 if (layoutDirection() == Qt::LeftToRight) {
1063 menu->move(mapToGlobal(g.topRight()));
1067 QPoint point = g.topLeft() - QPoint(menu->width() + 10, 0);
1068 menu->move(mapToGlobal(point));
1077 m_lastSubMenuIndex = m_currentIndex;
1081void QDesignerMenu::showSubMenu(QAction *action)
1083 using namespace qdesigner_internal;
1085 m_showSubMenuTimer->stop();
1087 if (m_editor->isVisible() || !action || qobject_cast<SpecialMenuAction*>(action)
1088 || action->isSeparator() || !isVisible())
1091 m_showSubMenuTimer->start(300);
1094QDesignerMenu *QDesignerMenu::parentMenu()
const
1096 return qobject_cast<QDesignerMenu*>(parentWidget());
1099QDesignerMenuBar *QDesignerMenu::parentMenuBar()
const
1101 if (QDesignerMenuBar *mb = qobject_cast<QDesignerMenuBar*>(parentWidget()))
1103 if (QDesignerMenu *m = parentMenu())
1104 return m->parentMenuBar();
1109void QDesignerMenu::setVisible(
bool visible)
1114 m_lastSubMenuIndex = -1;
1116 QMenu::setVisible(visible);
1120void QDesignerMenu::adjustSpecialActions()
1122 removeAction(m_addItem);
1123 removeAction(m_addSeparator);
1124 addAction(m_addItem);
1125 addAction(m_addSeparator);
1128void QDesignerMenu::enterEditMode()
1130 if (m_currentIndex >= 0 && m_currentIndex <= realActionCount()) {
1134 QDesignerFormWindowInterface *fw = formWindow();
1135 fw->beginCommand(tr(
"Add separator"));
1136 QAction *sep = createAction(QString(),
true);
1138 auto *cmd =
new qdesigner_internal::InsertActionIntoCommand(fw);
1139 cmd->init(
this, sep, safeActionAt(realActionCount()));
1140 fw->commandHistory()->push(cmd);
1143 QAction *parent_action = parentMenu()->currentAction();
1144 if (parent_action->menu() ==
nullptr) {
1145 auto *cmd =
new qdesigner_internal::CreateSubmenuCommand(fw);
1146 cmd->init(parentMenu(), parentMenu()->currentAction());
1147 fw->commandHistory()->push(cmd);
1153 m_currentIndex = actions().indexOf(m_addItem);
1158void QDesignerMenu::leaveEditMode(LeaveEditMode mode)
1160 using namespace qdesigner_internal;
1162 if (mode == Default)
1165 QAction *action =
nullptr;
1167 QDesignerFormWindowInterface *fw = formWindow();
1168 if (m_currentIndex < realActionCount()) {
1169 action = safeActionAt(m_currentIndex);
1170 fw->beginCommand(QApplication::translate(
"Command",
"Set action text"));
1172 Q_ASSERT(fw !=
nullptr);
1173 fw->beginCommand(QApplication::translate(
"Command",
"Insert action"));
1174 action = createAction(ActionEditor::actionTextToName(m_editor->text()));
1175 auto *cmd =
new qdesigner_internal::InsertActionIntoCommand(fw);
1176 cmd->init(
this, action, currentAction());
1177 fw->commandHistory()->push(cmd);
1180 auto *cmd =
new qdesigner_internal::SetPropertyCommand(fw);
1181 cmd->init(action, u"text"_s, m_editor->text());
1182 fw->commandHistory()->push(cmd);
1185 QAction *parent_action = parentMenu()->currentAction();
1186 if (parent_action->menu() ==
nullptr) {
1187 auto *cmd =
new qdesigner_internal::CreateSubmenuCommand(fw);
1188 cmd->init(parentMenu(), parentMenu()->currentAction(), action);
1189 fw->commandHistory()->push(cmd);
1197QAction *QDesignerMenu::safeMenuAction(QDesignerMenu *menu)
const
1199 QAction *action = menu->menuAction();
1202 action = m_subMenus.key(menu);
1207void QDesignerMenu::showLineEdit()
1209 m_showSubMenuTimer->stop();
1211 QAction *action =
nullptr;
1213 if (m_currentIndex < realActionCount())
1214 action = safeActionAt(m_currentIndex);
1218 if (action->isSeparator())
1226 const QString text = action != m_addItem ? action->text() : QString();
1227 m_editor->setText(text);
1228 m_editor->selectAll();
1229 m_editor->setGeometry(actionGeometry(action).adjusted(1, 1, -2, -2));
1231 m_editor->setFocus();
1234QAction *QDesignerMenu::createAction(
const QString &objectName,
bool separator)
1236 QDesignerFormWindowInterface *fw = formWindow();
1238 return qdesigner_internal::ToolBarEventFilter::createAction(fw, objectName, separator);
1242bool QDesignerMenu::swap(
int a,
int b)
1244 using namespace qdesigner_internal;
1246 const int left = qMin(a, b);
1247 int right = qMax(a, b);
1249 QAction *action_a = safeActionAt(left);
1250 QAction *action_b = safeActionAt(right);
1252 if (action_a == action_b
1255 || qobject_cast<SpecialMenuAction*>(action_a)
1256 || qobject_cast<SpecialMenuAction*>(action_b))
1259 right = qMin(right, realActionCount());
1263 QDesignerFormWindowInterface *fw = formWindow();
1264 fw->beginCommand(QApplication::translate(
"Command",
"Move action"));
1266 QAction *action_b_before = safeActionAt(right + 1);
1268 auto *cmd1 =
new qdesigner_internal::RemoveActionFromCommand(fw);
1269 cmd1->init(
this, action_b, action_b_before,
false);
1270 fw->commandHistory()->push(cmd1);
1272 QAction *action_a_before = safeActionAt(left + 1);
1274 auto *cmd2 =
new qdesigner_internal::InsertActionIntoCommand(fw);
1275 cmd2->init(
this, action_b, action_a_before,
false);
1276 fw->commandHistory()->push(cmd2);
1278 auto *cmd3 =
new qdesigner_internal::RemoveActionFromCommand(fw);
1279 cmd3->init(
this, action_a, action_b,
false);
1280 fw->commandHistory()->push(cmd3);
1282 auto *cmd4 =
new qdesigner_internal::InsertActionIntoCommand(fw);
1283 cmd4->init(
this, action_a, action_b_before,
true);
1284 fw->commandHistory()->push(cmd4);
1291QAction *QDesignerMenu::safeActionAt(
int index)
const
1293 if (index < 0 || index >= actions().size())
1296 return actions().at(index);
1299void QDesignerMenu::hideSubMenu()
1301 m_lastSubMenuIndex = -1;
1302 const auto &menus = findChildren<QMenu *>();
1303 for (QMenu *subMenu : menus)
1307void QDesignerMenu::deleteAction()
1309 QAction *action = currentAction();
1310 const int pos = actions().indexOf(action);
1311 QAction *action_before =
nullptr;
1313 action_before = safeActionAt(pos + 1);
1315 QDesignerFormWindowInterface *fw = formWindow();
1316 auto *cmd =
new qdesigner_internal::RemoveActionFromCommand(fw);
1317 cmd->init(
this, action, action_before);
1318 fw->commandHistory()->push(cmd);
1323void QDesignerMenu::deactivateMenu()
1325 m_deactivateWindowTimer->start(10);
1328void QDesignerMenu::slotDeactivateNow()
1330 m_deactivateWindowTimer->stop();
1335 QDesignerMenu *root = findRootMenu();
1337 if (! root->findActivatedMenu()) {
1339 root->hideSubMenu();
1343void QDesignerMenu::drawSelection(QPainter *p,
const QRect &r)
1347 QColor c = Qt::blue;
1348 p->setPen(QPen(c, 1));
1356void QDesignerMenu::keyPressEvent(QKeyEvent *event)
1361void QDesignerMenu::keyReleaseEvent(QKeyEvent *event)
Combined button and popup list for selecting options.
Auxiliary methods to store/retrieve settings.