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