16#include <QtDesigner/abstractformeditor.h>
17#include <QtDesigner/abstractwidgetfactory.h>
18#include <QtDesigner/abstractmetadatabase.h>
19#include <QtDesigner/qextensionmanager.h>
21#include <QtWidgets/qapplication.h>
22#include <QtWidgets/qlineedit.h>
23#include <QtWidgets/qrubberband.h>
24#include <QtWidgets/qtooltip.h>
25#include <QtWidgets/qtoolbar.h>
27#include <QtGui/qaction.h>
28#include <QtGui/qdrag.h>
29#include <QtGui/qevent.h>
30#include <QtGui/qpainter.h>
32#include <QtCore/qtimer.h>
33#include <QtCore/qdebug.h>
37using namespace Qt::StringLiterals;
43 case Qt::LayoutDirectionAuto:
45 subMenuRect->setLeft(subMenuRect->left() - 20);
48 subMenuRect->setRight(subMenuRect->right() + 20);
63QDesignerMenu::QDesignerMenu(QWidget *parent) :
65 m_subMenuPixmap(QPixmap(u":/qt-project.org/formeditor/images/submenu.png"_s)),
67 m_addItem(
new qdesigner_internal::SpecialMenuAction(
this)),
68 m_addSeparator(
new qdesigner_internal::SpecialMenuAction(
this)),
69 m_showSubMenuTimer(
new QTimer(
this)),
70 m_deactivateWindowTimer(
new QTimer(
this)),
71 m_adjustSizeTimer(
new QTimer(
this)),
72 m_editor(
new qdesigner_internal::MenuActionLineEdit(
this)),
74 m_lastSubMenuIndex(-1)
76 setContextMenuPolicy(Qt::DefaultContextMenu);
78 setSeparatorsCollapsible(
false);
80 connect(m_adjustSizeTimer, &QTimer::timeout,
this, &QDesignerMenu::slotAdjustSizeNow);
81 m_addItem->setText(tr(
"Type Here"));
84 m_addSeparator->setText(tr(
"Add Separator"));
85 addAction(m_addSeparator);
87 connect(m_showSubMenuTimer, &QTimer::timeout,
this, &QDesignerMenu::slotShowSubMenuNow);
89 connect(m_deactivateWindowTimer, &QTimer::timeout,
this, &QDesignerMenu::slotDeactivateNow);
91 m_editor->setObjectName(u"__qt__passive_editor"_s);
94 connect(m_editor, &qdesigner_internal::MenuActionLineEdit::focusOut,
95 this, &QDesignerMenu::stopInlineEditing);
96 installEventFilter(
new qdesigner_internal::MenuEventFilter(
this));
99QDesignerMenu::~QDesignerMenu() =
default;
101void QDesignerMenu::slotAdjustSizeNow()
105 m_adjustSizeTimer->stop();
109void QDesignerMenu::stopInlineEditing()
111 if (!m_editor->isHidden()) {
112 leaveEditMode(Default);
118bool QDesignerMenu::handleEvent(QEvent *event)
120 switch (event->type()) {
121 case QEvent::MouseButtonPress:
122 return handleMousePressEvent(
static_cast<QMouseEvent*>(event));
123 case QEvent::MouseButtonRelease:
124 return handleMouseReleaseEvent(
static_cast<QMouseEvent*>(event));
125 case QEvent::MouseButtonDblClick:
126 return handleMouseDoubleClickEvent(
static_cast<QMouseEvent*>(event));
127 case QEvent::MouseMove:
128 return handleMouseMoveEvent(
static_cast<QMouseEvent*>(event));
129 case QEvent::ContextMenu:
130 return handleContextMenuEvent(
static_cast<QContextMenuEvent*>(event));
131 case QEvent::KeyPress:
132 return handleKeyPressEvent(
static_cast<QKeyEvent*>(event));
133 case QEvent::FocusIn:
134 case QEvent::FocusOut:
144void QDesignerMenu::startDrag(
const QPoint &pos, Qt::KeyboardModifiers modifiers)
146 using namespace qdesigner_internal;
148 const int index = findAction(pos);
149 if (index >= realActionCount())
152 QAction *action = safeActionAt(index);
154 QDesignerFormWindowInterface *fw = formWindow();
155 const Qt::DropAction dropAction = (modifiers & Qt::ControlModifier) ? Qt::CopyAction : Qt::MoveAction;
156 if (dropAction == Qt::MoveAction) {
157 auto *cmd =
new RemoveActionFromCommand(fw);
158 cmd->init(
this, action, actions().at(index + 1));
159 fw->commandHistory()->push(cmd);
162 QDrag *drag =
new QDrag(
this);
163 drag->setPixmap(ActionRepositoryMimeData::actionDragPixmap(action));
164 drag->setMimeData(
new ActionRepositoryMimeData(action, dropAction));
166 const int old_index = m_currentIndex;
169 if (drag->exec(dropAction) == Qt::IgnoreAction) {
170 if (dropAction == Qt::MoveAction) {
171 QAction *previous = safeActionAt(index);
172 auto *cmd =
new InsertActionIntoCommand(fw);
173 cmd->init(
this, action, previous);
174 fw->commandHistory()->push(cmd);
177 m_currentIndex = old_index;
181bool QDesignerMenu::handleKeyPressEvent(QKeyEvent *e)
183 m_showSubMenuTimer->stop();
185 if (m_editor->isHidden() && hasFocus()) {
189 if (m_currentIndex == -1 || m_currentIndex >= realActionCount())
207 moveUp(e->modifiers() & Qt::ControlModifier);
212 moveDown(e->modifiers() & Qt::ControlModifier);
219 case Qt::Key_PageDown:
220 m_currentIndex = actions().size() - 1;
239 case Qt::Key_Control:
245 QAction *action = currentAction();
246 if (!action || action->isSeparator() || action == m_addSeparator) {
250 if (!e->text().isEmpty() && e->text().at(0).toLatin1() >= 32) {
252 QApplication::sendEvent(m_editor, e);
260 }
else if (m_editor->hasFocus()) {
268 if (!m_editor->text().isEmpty()) {
269 leaveEditMode(ForceAccept);
292 QMouseEvent e(event->type(), targetPoint, event->globalPosition().toPoint(), event->button(), event->buttons(), event->modifiers());
293 QApplication::sendEvent(target, &e);
296bool QDesignerMenu::handleMouseDoubleClickEvent(QMouseEvent *event)
299 m_startPosition = QPoint();
301 if ((event->buttons() & Qt::LeftButton) != Qt::LeftButton)
304 if (!rect().contains(event->position().toPoint())) {
306 QWidget *target = QApplication::widgetAt(event->globalPosition().toPoint());
307 QMenuBar *mb = qobject_cast<QMenuBar*>(target);
308 QDesignerMenu *menu = qobject_cast<QDesignerMenu*>(target);
309 if (mb !=
nullptr || menu !=
nullptr) {
310 const QPoint pt = target->mapFromGlobal(event->globalPosition().toPoint());
311 QAction *action = mb ==
nullptr ? menu->actionAt(pt) : mb->actionAt(pt);
313 sendMouseEventTo(target, pt, event);
318 m_currentIndex = findAction(event->position().toPoint());
319 QAction *action = safeActionAt(m_currentIndex);
322 if (action->menu() || hasSubMenuPixmap(action)) {
323 pm_rect = subMenuPixmapRect(action);
324 extendClickableArea(&pm_rect, layoutDirection());
327 if (!pm_rect.contains(event->position().toPoint()) && m_currentIndex != -1)
333bool QDesignerMenu::handleMousePressEvent(QMouseEvent *event)
335 if (!rect().contains(event->position().toPoint())) {
336 QWidget *clickedWidget = QApplication::widgetAt(event->globalPosition().toPoint());
337 if (QMenuBar *mb = qobject_cast<QMenuBar*>(clickedWidget)) {
338 const QPoint pt = mb->mapFromGlobal(event->globalPosition().toPoint());
339 if (QAction *action = mb->actionAt(pt)) {
340 QMenu * menu = action->menu();
341 if (menu == findRootMenu()) {
343 sendMouseEventTo(mb, pt, event);
349 if (QDesignerMenu *m = qobject_cast<QDesignerMenu *>(clickedWidget)) {
351 sendMouseEventTo(m, m->mapFromGlobal(event->globalPosition().toPoint()), event);
353 QDesignerMenu *root = findRootMenu();
358 if (QWidget *focusProxy = clickedWidget->focusProxy())
359 clickedWidget = focusProxy;
360 if (clickedWidget->focusPolicy() != Qt::NoFocus)
361 clickedWidget->setFocus(Qt::OtherFocusReason);
366 m_showSubMenuTimer->stop();
367 m_startPosition = QPoint();
370 if (event->button() != Qt::LeftButton)
373 m_startPosition = mapFromGlobal(event->globalPosition().toPoint());
375 const int index = findAction(m_startPosition);
377 QAction *action = safeActionAt(index);
378 QRect pm_rect = subMenuPixmapRect(action);
379 extendClickableArea(&pm_rect, layoutDirection());
381 const int old_index = m_currentIndex;
382 m_currentIndex = index;
383 if ((hasSubMenuPixmap(action) || action->menu() !=
nullptr)
384 && pm_rect.contains(m_startPosition)) {
385 if (m_currentIndex == m_lastSubMenuIndex) {
388 slotShowSubMenuNow();
390 if (index == old_index) {
391 if (m_currentIndex == m_lastSubMenuIndex)
399 if (index != old_index)
400 selectCurrentAction();
405bool QDesignerMenu::handleMouseReleaseEvent(QMouseEvent *event)
408 m_startPosition = QPoint();
413bool QDesignerMenu::handleMouseMoveEvent(QMouseEvent *event)
415 if ((event->buttons() & Qt::LeftButton) != Qt::LeftButton)
418 if (!rect().contains(event->position().toPoint())) {
420 if (QMenuBar *mb = qobject_cast<QMenuBar*>(QApplication::widgetAt(event->globalPosition().toPoint()))) {
421 const QPoint pt = mb->mapFromGlobal(event->globalPosition().toPoint());
422 QAction *action = mb->actionAt(pt);
423 if (action && action->menu() == findRootMenu()) {
425 sendMouseEventTo(mb, pt, event);
434 if (m_startPosition.isNull())
439 const QPoint pos = mapFromGlobal(event->globalPosition().toPoint());
441 if ((pos - m_startPosition).manhattanLength() < qApp->startDragDistance())
444 startDrag(m_startPosition, event->modifiers());
445 m_startPosition = QPoint();
450bool QDesignerMenu::handleContextMenuEvent(QContextMenuEvent *event)
454 const int index = findAction(mapFromGlobal(event->globalPos()));
455 QAction *action = safeActionAt(index);
456 if (qobject_cast<qdesigner_internal::SpecialMenuAction*>(action))
461 itemData.setValue(action);
463 QAction *addSeparatorAction = menu.addAction(tr(
"Insert separator"));
464 addSeparatorAction->setData(itemData);
466 QAction *removeAction =
nullptr;
467 if (action->isSeparator())
468 removeAction = menu.addAction(tr(
"Remove separator"));
470 removeAction = menu.addAction(tr(
"Remove action '%1'").arg(action->objectName()));
471 removeAction->setData(itemData);
473 connect(addSeparatorAction, &QAction::triggered,
this, &QDesignerMenu::slotAddSeparator);
474 connect(removeAction, &QAction::triggered,
this, &QDesignerMenu::slotRemoveSelectedAction);
475 menu.exec(event->globalPos());
480void QDesignerMenu::slotAddSeparator()
482 QAction *action = qobject_cast<QAction *>(sender());
486 QAction *a = qvariant_cast<QAction*>(action->data());
487 Q_ASSERT(a !=
nullptr);
489 const int pos = actions().indexOf(a);
490 QAction *action_before =
nullptr;
492 action_before = safeActionAt(pos);
494 QDesignerFormWindowInterface *fw = formWindow();
495 fw->beginCommand(tr(
"Add separator"));
496 QAction *sep = createAction(QString(),
true);
498 auto *cmd =
new qdesigner_internal::InsertActionIntoCommand(fw);
499 cmd->init(
this, sep, action_before);
500 fw->commandHistory()->push(cmd);
503 QAction *parent_action = parentMenu()->currentAction();
504 if (parent_action->menu() ==
nullptr) {
505 auto *cmd =
new qdesigner_internal::CreateSubmenuCommand(fw);
506 cmd->init(parentMenu(), parentMenu()->currentAction());
507 fw->commandHistory()->push(cmd);
514void QDesignerMenu::slotRemoveSelectedAction()
516 if (QAction *action = qobject_cast<QAction *>(sender()))
517 if (QAction *a = qvariant_cast<QAction*>(action->data()))
521void QDesignerMenu::deleteAction(QAction *a)
523 const int pos = actions().indexOf(a);
524 QAction *action_before =
nullptr;
526 action_before = safeActionAt(pos + 1);
528 QDesignerFormWindowInterface *fw = formWindow();
529 auto *cmd =
new qdesigner_internal::RemoveActionFromCommand(fw);
530 cmd->init(
this, a, action_before);
531 fw->commandHistory()->push(cmd);
534QRect QDesignerMenu::subMenuPixmapRect(QAction *action)
const
536 const QRect g = actionGeometry(action);
537 const int x = layoutDirection() == Qt::LeftToRight ? (g.right() - m_subMenuPixmap.width() - 2) : 2;
538 const int y = g.top() + (g.height() - m_subMenuPixmap.height())/2 + 1;
539 return QRect(x, y, m_subMenuPixmap.width(), m_subMenuPixmap.height());
542bool QDesignerMenu::hasSubMenuPixmap(QAction *action)
const
544 return action !=
nullptr
545 && qobject_cast<qdesigner_internal::SpecialMenuAction*>(action) ==
nullptr
546 && !action->isSeparator()
548 && canCreateSubMenu(action);
551void QDesignerMenu::showEvent ( QShowEvent * event )
553 selectCurrentAction();
554 QMenu::showEvent (event);
557void QDesignerMenu::paintEvent(QPaintEvent *event)
559 using namespace qdesigner_internal;
561 QMenu::paintEvent(event);
565 QAction *current = currentAction();
567 const auto &actionList = actions();
568 for (QAction *a : actionList) {
569 const QRect g = actionGeometry(a);
571 if (qobject_cast<SpecialMenuAction*>(a)) {
572 QLinearGradient lg(g.left(), g.top(), g.left(), g.bottom());
573 lg.setColorAt(0.0, Qt::transparent);
574 lg.setColorAt(0.7, QColor(0, 0, 0, 32));
575 lg.setColorAt(1.0, Qt::transparent);
578 }
else if (hasSubMenuPixmap(a)) {
579 p.drawPixmap(subMenuPixmapRect(a).topLeft(), m_subMenuPixmap);
583 if (!hasFocus() || !current || m_dragging)
586 if (QDesignerMenu *menu = parentMenu()) {
587 if (menu->dragging())
591 if (QDesignerMenuBar *menubar = qobject_cast<QDesignerMenuBar*>(parentWidget())) {
592 if (menubar->dragging())
596 const QRect g = actionGeometry(current);
597 drawSelection(&p, g.adjusted(1, 1, -3, -3));
600bool QDesignerMenu::dragging()
const
605QDesignerMenu *QDesignerMenu::findRootMenu()
const
608 return parentMenu()->findRootMenu();
610 return const_cast<QDesignerMenu*>(
this);
613QDesignerMenu *QDesignerMenu::findActivatedMenu()
const
615 if (QDesignerMenu *activeDesignerMenu = qobject_cast<QDesignerMenu *>(QApplication::activeWindow())) {
616 if (activeDesignerMenu ==
this || findChildren<QDesignerMenu *>().contains(activeDesignerMenu))
617 return activeDesignerMenu;
625 switch (event->type()) {
626 case QEvent::WindowDeactivate:
627 if (
auto *menu = qobject_cast<QDesignerMenu *>(object))
628 menu->deactivateMenu();
630 case QEvent::ContextMenu:
631 case QEvent::MouseButtonPress:
632 case QEvent::MouseButtonRelease:
633 case QEvent::MouseButtonDblClick:
635 while (QApplication::activePopupWidget() && !qobject_cast<QDesignerMenu*>(QApplication::activePopupWidget())) {
636 QApplication::activePopupWidget()->close();
640 case QEvent::KeyPress:
641 case QEvent::KeyRelease:
642 case QEvent::MouseMove:
645 case QEvent::FocusIn:
646 case QEvent::FocusOut: {
647 auto *menu = qobject_cast<QDesignerMenu *>(object);
649 return menu->handleEvent(event);
655 return QObject::eventFilter(object, event);
658int QDesignerMenu::findAction(
const QPoint &pos)
const
660 const int index = actionIndexAt(
this, pos, Qt::Vertical);
662 return realActionCount();
667void QDesignerMenu::adjustIndicator(
const QPoint &pos)
669 if (QDesignerActionProviderExtension *a = actionProvider()) {
670 a->adjustIndicator(pos);
674QDesignerMenu::ActionDragCheck QDesignerMenu::checkAction(QAction *action)
const
676 if (!action || (action->menu() && action->menu()->parentWidget() !=
const_cast<QDesignerMenu*>(
this)))
679 if (!qdesigner_internal::Utils::isObjectAncestorOf(formWindow()->mainContainer(), action))
682 if (actions().contains(action))
683 return ActionDragOnSubMenu;
685 return AcceptActionDrag;
688void QDesignerMenu::dragEnterEvent(QDragEnterEvent *event)
690 auto *d = qobject_cast<
const qdesigner_internal::ActionRepositoryMimeData*>(event->mimeData());
691 if (!d || d->actionList().isEmpty()) {
696 QAction *action = d->actionList().first();
698 switch (checkAction(action)) {
702 case ActionDragOnSubMenu:
706 case AcceptActionDrag:
709 adjustIndicator(event->position().toPoint());
714void QDesignerMenu::dragMoveEvent(QDragMoveEvent *event)
716 if (actionGeometry(m_addSeparator).contains(event->position().toPoint())) {
718 adjustIndicator(QPoint(-1, -1));
722 auto *d = qobject_cast<
const qdesigner_internal::ActionRepositoryMimeData*>(event->mimeData());
723 if (!d || d->actionList().isEmpty()) {
728 QAction *action = d->actionList().first();
729 const ActionDragCheck dc = checkAction(action);
734 case ActionDragOnSubMenu:
735 case AcceptActionDrag: {
736 const int newIndex = findAction(event->position().toPoint());
737 if (safeActionAt(newIndex) != action) {
738 m_currentIndex = newIndex;
739 if (m_lastSubMenuIndex != m_currentIndex)
740 m_showSubMenuTimer->start(300);
742 if (dc == AcceptActionDrag) {
743 adjustIndicator(event->position().toPoint());
753void QDesignerMenu::dragLeaveEvent(QDragLeaveEvent *)
756 adjustIndicator(QPoint(-1, -1));
757 m_showSubMenuTimer->stop();
760void QDesignerMenu::dropEvent(QDropEvent *event)
762 m_showSubMenuTimer->stop();
766 QDesignerFormWindowInterface *fw = formWindow();
767 auto *d = qobject_cast<
const qdesigner_internal::ActionRepositoryMimeData*>(event->mimeData());
768 if (!d || d->actionList().isEmpty()) {
772 QAction *action = d->actionList().first();
773 if (action && checkAction(action) == AcceptActionDrag) {
774 event->acceptProposedAction();
775 int index = findAction(event->position().toPoint());
776 index = qMin(index, actions().size() - 1);
778 fw->beginCommand(tr(
"Insert action"));
779 auto *cmd =
new qdesigner_internal::InsertActionIntoCommand(fw);
780 cmd->init(
this, action, safeActionAt(index));
781 fw->commandHistory()->push(cmd);
783 m_currentIndex = index;
786 QAction *parent_action = parentMenu()->currentAction();
787 if (parent_action->menu() ==
nullptr) {
788 auto *cmd =
new qdesigner_internal::CreateSubmenuCommand(fw);
789 cmd->init(parentMenu(), parentMenu()->currentAction(), action);
790 fw->commandHistory()->push(cmd);
798 adjustIndicator(QPoint(-1, -1));
801void QDesignerMenu::actionEvent(QActionEvent *event)
803 QMenu::actionEvent(event);
804 m_adjustSizeTimer->start(0);
807QDesignerFormWindowInterface *QDesignerMenu::formWindow()
const
810 return parentMenu()->formWindow();
812 return QDesignerFormWindowInterface::findFormWindow(parentWidget());
815QDesignerActionProviderExtension *QDesignerMenu::actionProvider()
817 if (QDesignerFormWindowInterface *fw = formWindow()) {
818 QDesignerFormEditorInterface *core = fw->core();
819 return qt_extension<QDesignerActionProviderExtension*>(core->extensionManager(),
this);
825void QDesignerMenu::closeMenuChain()
827 m_showSubMenuTimer->stop();
830 while (w && qobject_cast<QMenu*>(w))
831 w = w->parentWidget();
834 const auto &menus = w->findChildren<QMenu *>();
835 for (QMenu *subMenu : menus)
839 m_lastSubMenuIndex = -1;
844bool QDesignerMenu::hideSubMenuOnCursorKey()
852 return parentMenuBar() ==
nullptr;
857bool QDesignerMenu::showSubMenuOnCursorKey()
859 using namespace qdesigner_internal;
861 const QAction *action = currentAction();
863 if (qobject_cast<
const SpecialMenuAction*>(action) || action->isSeparator()) {
869 m_lastSubMenuIndex = -1;
870 slotShowSubMenuNow();
874void QDesignerMenu::moveLeft()
876 const bool handled = layoutDirection() == Qt::LeftToRight ?
877 hideSubMenuOnCursorKey() : showSubMenuOnCursorKey();
879 parentMenuBar()->moveLeft();
882void QDesignerMenu::moveRight()
884 const bool handled = layoutDirection() == Qt::LeftToRight ?
885 showSubMenuOnCursorKey() : hideSubMenuOnCursorKey();
887 parentMenuBar()->moveRight();
890void QDesignerMenu::moveUp(
bool ctrl)
892 if (m_currentIndex == 0) {
898 (
void) swap(m_currentIndex, m_currentIndex - 1);
900 m_currentIndex = qMax(0, m_currentIndex);
903 selectCurrentAction();
906void QDesignerMenu::moveDown(
bool ctrl)
908 if (m_currentIndex == actions().size() - 1) {
913 (
void) swap(m_currentIndex + 1, m_currentIndex);
916 m_currentIndex = qMin(actions().size() - 1, m_currentIndex);
919 selectCurrentAction();
922QAction *QDesignerMenu::currentAction()
const
924 if (m_currentIndex < 0 || m_currentIndex >= actions().size())
927 return safeActionAt(m_currentIndex);
930int QDesignerMenu::realActionCount()
const
932 return actions().size() - 2;
935void QDesignerMenu::selectCurrentAction()
937 using namespace qdesigner_internal;
939 QAction *action = currentAction();
940 if (!action || action == m_addSeparator || action == m_addItem)
943 QDesignerObjectInspector *oi =
nullptr;
944 ActionEditor *ae =
nullptr;
945 if (QDesignerFormWindowInterface *fw = formWindow()) {
946 auto core = fw->core();
947 oi = qobject_cast<QDesignerObjectInspector *>(core->objectInspector());
948 ae = qobject_cast<ActionEditor *>(core->actionEditor());
954 oi->clearSelection();
955 if (QMenu *menu = action->menu()) {
956 oi->selectObject(menu);
958 ae->clearSelection();
960 oi->selectObject(action);
962 ae->selectAction(action);
966void QDesignerMenu::createRealMenuAction(QAction *action)
968 using namespace qdesigner_internal;
973 QDesignerFormWindowInterface *fw = formWindow();
974 QDesignerFormEditorInterface *core = formWindow()->core();
976 QDesignerMenu *menu = findOrCreateSubMenu(action);
977 m_subMenus.remove(action);
979 action->setMenu(menu);
980 menu->setTitle(action->text());
984 core->widgetFactory()->initialize(menu);
986 const QString niceObjectName = ActionEditor::actionTextToName(menu->title(), u"menu"_s);
987 menu->setObjectName(niceObjectName);
989 core->metaDataBase()->add(menu);
990 fw->ensureUniqueObjectName(menu);
992 QAction *menuAction = menu->menuAction();
993 core->metaDataBase()->add(menuAction);
996void QDesignerMenu::removeRealMenu(QAction *action)
998 QDesignerMenu *menu = qobject_cast<QDesignerMenu*>(action->menu());
1001 action->setMenu(
nullptr);
1002 m_subMenus.insert(action, menu);
1003 QDesignerFormEditorInterface *core = formWindow()->core();
1004 core->metaDataBase()->remove(menu);
1007QDesignerMenu *QDesignerMenu::findOrCreateSubMenu(QAction *action)
1010 return qobject_cast<QDesignerMenu*>(action->menu());
1012 QDesignerMenu *menu = m_subMenus.value(action);
1014 menu =
new QDesignerMenu(
this);
1015 m_subMenus.insert(action, menu);
1021bool QDesignerMenu::canCreateSubMenu(QAction *action)
const
1023 const QObjectList associatedObjects = action->associatedObjects();
1024 for (
const QObject *ao : associatedObjects) {
1026 if (
const QMenu *m = qobject_cast<
const QMenu *>(ao)) {
1027 if (m->actions().contains(action))
1029 }
else if (
const QToolBar *tb = qobject_cast<
const QToolBar *>(ao)) {
1030 if (tb->actions().contains(action))
1038void QDesignerMenu::slotShowSubMenuNow()
1040 m_showSubMenuTimer->stop();
1042 if (m_lastSubMenuIndex == m_currentIndex)
1045 if (m_lastSubMenuIndex != -1)
1048 if (m_currentIndex >= realActionCount())
1051 QAction *action = currentAction();
1053 if (action->isSeparator() || !canCreateSubMenu(action))
1056 if (QMenu *menu = findOrCreateSubMenu(action)) {
1057 if (!menu->isVisible()) {
1058 if ((menu->windowFlags() & Qt::Popup) != Qt::Popup)
1059 menu->setWindowFlags(Qt::Popup);
1060 const QRect g = actionGeometry(action);
1061 if (layoutDirection() == Qt::LeftToRight) {
1062 menu->move(mapToGlobal(g.topRight()));
1066 QPoint point = g.topLeft() - QPoint(menu->width() + 10, 0);
1067 menu->move(mapToGlobal(point));
1076 m_lastSubMenuIndex = m_currentIndex;
1080void QDesignerMenu::showSubMenu(QAction *action)
1082 using namespace qdesigner_internal;
1084 m_showSubMenuTimer->stop();
1086 if (m_editor->isVisible() || !action || qobject_cast<SpecialMenuAction*>(action)
1087 || action->isSeparator() || !isVisible())
1090 m_showSubMenuTimer->start(300);
1093QDesignerMenu *QDesignerMenu::parentMenu()
const
1095 return qobject_cast<QDesignerMenu*>(parentWidget());
1098QDesignerMenuBar *QDesignerMenu::parentMenuBar()
const
1100 if (QDesignerMenuBar *mb = qobject_cast<QDesignerMenuBar*>(parentWidget()))
1102 if (QDesignerMenu *m = parentMenu())
1103 return m->parentMenuBar();
1108void QDesignerMenu::setVisible(
bool visible)
1113 m_lastSubMenuIndex = -1;
1115 QMenu::setVisible(visible);
1119void QDesignerMenu::adjustSpecialActions()
1121 removeAction(m_addItem);
1122 removeAction(m_addSeparator);
1123 addAction(m_addItem);
1124 addAction(m_addSeparator);
1127void QDesignerMenu::enterEditMode()
1129 if (m_currentIndex >= 0 && m_currentIndex <= realActionCount()) {
1133 QDesignerFormWindowInterface *fw = formWindow();
1134 fw->beginCommand(tr(
"Add separator"));
1135 QAction *sep = createAction(QString(),
true);
1137 auto *cmd =
new qdesigner_internal::InsertActionIntoCommand(fw);
1138 cmd->init(
this, sep, safeActionAt(realActionCount()));
1139 fw->commandHistory()->push(cmd);
1142 QAction *parent_action = parentMenu()->currentAction();
1143 if (parent_action->menu() ==
nullptr) {
1144 auto *cmd =
new qdesigner_internal::CreateSubmenuCommand(fw);
1145 cmd->init(parentMenu(), parentMenu()->currentAction());
1146 fw->commandHistory()->push(cmd);
1152 m_currentIndex = actions().indexOf(m_addItem);
1157void QDesignerMenu::leaveEditMode(LeaveEditMode mode)
1159 using namespace qdesigner_internal;
1161 if (mode == Default)
1164 QAction *action =
nullptr;
1166 QDesignerFormWindowInterface *fw = formWindow();
1167 if (m_currentIndex < realActionCount()) {
1168 action = safeActionAt(m_currentIndex);
1169 fw->beginCommand(QApplication::translate(
"Command",
"Set action text"));
1171 Q_ASSERT(fw !=
nullptr);
1172 fw->beginCommand(QApplication::translate(
"Command",
"Insert action"));
1173 action = createAction(ActionEditor::actionTextToName(m_editor->text()));
1174 auto *cmd =
new qdesigner_internal::InsertActionIntoCommand(fw);
1175 cmd->init(
this, action, currentAction());
1176 fw->commandHistory()->push(cmd);
1179 auto *cmd =
new qdesigner_internal::SetPropertyCommand(fw);
1180 cmd->init(action, u"text"_s, m_editor->text());
1181 fw->commandHistory()->push(cmd);
1184 QAction *parent_action = parentMenu()->currentAction();
1185 if (parent_action->menu() ==
nullptr) {
1186 auto *cmd =
new qdesigner_internal::CreateSubmenuCommand(fw);
1187 cmd->init(parentMenu(), parentMenu()->currentAction(), action);
1188 fw->commandHistory()->push(cmd);
1196QAction *QDesignerMenu::safeMenuAction(QDesignerMenu *menu)
const
1198 QAction *action = menu->menuAction();
1201 action = m_subMenus.key(menu);
1206void QDesignerMenu::showLineEdit()
1208 m_showSubMenuTimer->stop();
1210 QAction *action =
nullptr;
1212 if (m_currentIndex < realActionCount())
1213 action = safeActionAt(m_currentIndex);
1217 if (action->isSeparator())
1225 const QString text = action != m_addItem ? action->text() : QString();
1226 m_editor->setText(text);
1227 m_editor->selectAll();
1228 m_editor->setGeometry(actionGeometry(action).adjusted(1, 1, -2, -2));
1230 m_editor->setFocus();
1233QAction *QDesignerMenu::createAction(
const QString &objectName,
bool separator)
1235 QDesignerFormWindowInterface *fw = formWindow();
1237 return qdesigner_internal::ToolBarEventFilter::createAction(fw, objectName, separator);
1241bool QDesignerMenu::swap(
int a,
int b)
1243 using namespace qdesigner_internal;
1245 const int left = qMin(a, b);
1246 int right = qMax(a, b);
1248 QAction *action_a = safeActionAt(left);
1249 QAction *action_b = safeActionAt(right);
1251 if (action_a == action_b
1254 || qobject_cast<SpecialMenuAction*>(action_a)
1255 || qobject_cast<SpecialMenuAction*>(action_b))
1258 right = qMin(right, realActionCount());
1262 QDesignerFormWindowInterface *fw = formWindow();
1263 fw->beginCommand(QApplication::translate(
"Command",
"Move action"));
1265 QAction *action_b_before = safeActionAt(right + 1);
1267 auto *cmd1 =
new qdesigner_internal::RemoveActionFromCommand(fw);
1268 cmd1->init(
this, action_b, action_b_before,
false);
1269 fw->commandHistory()->push(cmd1);
1271 QAction *action_a_before = safeActionAt(left + 1);
1273 auto *cmd2 =
new qdesigner_internal::InsertActionIntoCommand(fw);
1274 cmd2->init(
this, action_b, action_a_before,
false);
1275 fw->commandHistory()->push(cmd2);
1277 auto *cmd3 =
new qdesigner_internal::RemoveActionFromCommand(fw);
1278 cmd3->init(
this, action_a, action_b,
false);
1279 fw->commandHistory()->push(cmd3);
1281 auto *cmd4 =
new qdesigner_internal::InsertActionIntoCommand(fw);
1282 cmd4->init(
this, action_a, action_b_before,
true);
1283 fw->commandHistory()->push(cmd4);
1290QAction *QDesignerMenu::safeActionAt(
int index)
const
1292 if (index < 0 || index >= actions().size())
1295 return actions().at(index);
1298void QDesignerMenu::hideSubMenu()
1300 m_lastSubMenuIndex = -1;
1301 const auto &menus = findChildren<QMenu *>();
1302 for (QMenu *subMenu : menus)
1306void QDesignerMenu::deleteAction()
1308 QAction *action = currentAction();
1309 const int pos = actions().indexOf(action);
1310 QAction *action_before =
nullptr;
1312 action_before = safeActionAt(pos + 1);
1314 QDesignerFormWindowInterface *fw = formWindow();
1315 auto *cmd =
new qdesigner_internal::RemoveActionFromCommand(fw);
1316 cmd->init(
this, action, action_before);
1317 fw->commandHistory()->push(cmd);
1322void QDesignerMenu::deactivateMenu()
1324 m_deactivateWindowTimer->start(10);
1327void QDesignerMenu::slotDeactivateNow()
1329 m_deactivateWindowTimer->stop();
1334 QDesignerMenu *root = findRootMenu();
1336 if (! root->findActivatedMenu()) {
1338 root->hideSubMenu();
1342void QDesignerMenu::drawSelection(QPainter *p,
const QRect &r)
1346 QColor c = Qt::blue;
1347 p->setPen(QPen(c, 1));
1355void QDesignerMenu::keyPressEvent(QKeyEvent *event)
1360void QDesignerMenu::keyReleaseEvent(QKeyEvent *event)
Combined button and popup list for selecting options.
Auxiliary methods to store/retrieve settings.