tools/designer/src/lib/shared/qdesigner_menubar.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
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_menubar_p.h"
       
    43 #include "qdesigner_menu_p.h"
       
    44 #include "qdesigner_command_p.h"
       
    45 #include "qdesigner_propertycommand_p.h"
       
    46 #include "actionrepository_p.h"
       
    47 #include "actionprovider_p.h"
       
    48 #include "actioneditor_p.h"
       
    49 #include "qdesigner_utils_p.h"
       
    50 #include "promotiontaskmenu_p.h"
       
    51 #include "qdesigner_objectinspector_p.h"
       
    52 
       
    53 #include <QtDesigner/QDesignerFormWindowInterface>
       
    54 #include <QtDesigner/QDesignerFormEditorInterface>
       
    55 #include <QtDesigner/QDesignerWidgetFactoryInterface>
       
    56 #include <QtDesigner/QExtensionManager>
       
    57 
       
    58 #include <QtCore/QMimeData>
       
    59 
       
    60 #include <QtCore/qdebug.h>
       
    61 
       
    62 #include <QtGui/QApplication>
       
    63 #include <QtGui/QDrag>
       
    64 #include <QtGui/QLineEdit>
       
    65 #include <QtGui/QPainter>
       
    66 #include <QtGui/qevent.h>
       
    67 
       
    68 Q_DECLARE_METATYPE(QAction*)
       
    69 
       
    70 QT_BEGIN_NAMESPACE
       
    71 
       
    72 typedef QList<QAction *> ActionList;
       
    73 
       
    74 using namespace qdesigner_internal;
       
    75 
       
    76 namespace qdesigner_internal
       
    77 {
       
    78 
       
    79 /////////////////////////////////////////////////////////////////////////////////////////////////////////
       
    80 SpecialMenuAction::SpecialMenuAction(QObject *parent)
       
    81     : QAction(parent)
       
    82 {
       
    83 }
       
    84 
       
    85 SpecialMenuAction::~SpecialMenuAction()
       
    86 {
       
    87 }
       
    88 
       
    89 
       
    90 } // namespace qdesigner_internal
       
    91 
       
    92 
       
    93 /////////////////////////////////////////////////////////////////////////////////////////////////////////
       
    94 QDesignerMenuBar::QDesignerMenuBar(QWidget *parent)  :
       
    95     QMenuBar(parent),
       
    96     m_addMenu(new SpecialMenuAction(this)),
       
    97     m_currentIndex(0),
       
    98     m_interactive(true),
       
    99     m_editor(new QLineEdit(this)),
       
   100     m_dragging(false),
       
   101     m_lastMenuActionIndex( -1),
       
   102     m_promotionTaskMenu(new PromotionTaskMenu(this, PromotionTaskMenu::ModeSingleWidget, this))
       
   103 {
       
   104     setContextMenuPolicy(Qt::DefaultContextMenu);
       
   105 
       
   106     setAcceptDrops(true); // ### fake
       
   107     // Fake property: Keep the menu bar editable in the form even if a native menu bar is used.
       
   108     setNativeMenuBar(false);
       
   109 
       
   110     m_addMenu->setText(tr("Type Here"));
       
   111     addAction(m_addMenu);
       
   112 
       
   113     QFont italic;
       
   114     italic.setItalic(true);
       
   115     m_addMenu->setFont(italic);
       
   116 
       
   117     m_editor->setObjectName(QLatin1String("__qt__passive_editor"));
       
   118     m_editor->hide();
       
   119     m_editor->installEventFilter(this);
       
   120     installEventFilter(this);
       
   121 }
       
   122 
       
   123 QDesignerMenuBar::~QDesignerMenuBar()
       
   124 {
       
   125 }
       
   126 
       
   127 void QDesignerMenuBar::paintEvent(QPaintEvent *event)
       
   128 {
       
   129     QMenuBar::paintEvent(event);
       
   130 
       
   131     QPainter p(this);
       
   132 
       
   133     foreach (QAction *a, actions()) {
       
   134         if (qobject_cast<SpecialMenuAction*>(a)) {
       
   135             const QRect g = actionGeometry(a);
       
   136             QLinearGradient lg(g.left(), g.top(), g.left(), g.bottom());
       
   137             lg.setColorAt(0.0, Qt::transparent);
       
   138             lg.setColorAt(0.7, QColor(0, 0, 0, 32));
       
   139             lg.setColorAt(1.0, Qt::transparent);
       
   140 
       
   141             p.fillRect(g, lg);
       
   142         }
       
   143     }
       
   144 
       
   145     QAction *action = currentAction();
       
   146 
       
   147     if (m_dragging || !action)
       
   148         return;
       
   149 
       
   150     if (hasFocus()) {
       
   151         const QRect g = actionGeometry(action);
       
   152         QDesignerMenu::drawSelection(&p, g.adjusted(1, 1, -1, -1));
       
   153     } else if (action->menu() && action->menu()->isVisible()) {
       
   154         const QRect g = actionGeometry(action);
       
   155         p.drawRect(g.adjusted(1, 1, -1, -1));
       
   156     }
       
   157 }
       
   158 
       
   159 bool QDesignerMenuBar::handleEvent(QWidget *widget, QEvent *event)
       
   160 {
       
   161     if (!formWindow())
       
   162         return false;
       
   163 
       
   164     if (event->type() == QEvent::FocusIn || event->type() == QEvent::FocusOut)
       
   165         update();
       
   166 
       
   167     switch (event->type()) {
       
   168         default: break;
       
   169 
       
   170         case QEvent::MouseButtonDblClick:
       
   171             return handleMouseDoubleClickEvent(widget, static_cast<QMouseEvent*>(event));
       
   172         case QEvent::MouseButtonPress:
       
   173             return handleMousePressEvent(widget, static_cast<QMouseEvent*>(event));
       
   174         case QEvent::MouseButtonRelease:
       
   175             return handleMouseReleaseEvent(widget, static_cast<QMouseEvent*>(event));
       
   176         case QEvent::MouseMove:
       
   177             return handleMouseMoveEvent(widget, static_cast<QMouseEvent*>(event));
       
   178         case QEvent::ContextMenu:
       
   179             return handleContextMenuEvent(widget, static_cast<QContextMenuEvent*>(event));
       
   180         case QEvent::KeyPress:
       
   181             return handleKeyPressEvent(widget, static_cast<QKeyEvent*>(event));
       
   182         case QEvent::FocusIn:
       
   183         case QEvent::FocusOut:
       
   184             return widget != m_editor;
       
   185     }
       
   186 
       
   187     return true;
       
   188 }
       
   189 
       
   190 bool QDesignerMenuBar::handleMouseDoubleClickEvent(QWidget *, QMouseEvent *event)
       
   191 {
       
   192     if (!rect().contains(event->pos()))
       
   193         return true;
       
   194 
       
   195     if ((event->buttons() & Qt::LeftButton) != Qt::LeftButton)
       
   196         return true;
       
   197 
       
   198     event->accept();
       
   199 
       
   200     m_startPosition = QPoint();
       
   201 
       
   202     m_currentIndex = actionIndexAt(this, event->pos(), Qt::Horizontal);
       
   203     if (m_currentIndex != -1) {
       
   204         showLineEdit();
       
   205     }
       
   206 
       
   207     return true;
       
   208 }
       
   209 
       
   210 bool QDesignerMenuBar::handleKeyPressEvent(QWidget *, QKeyEvent *e)
       
   211 {
       
   212     if (m_editor->isHidden()) { // In navigation mode
       
   213         switch (e->key()) {
       
   214 
       
   215         case Qt::Key_Delete:
       
   216             if (m_currentIndex == -1 || m_currentIndex >= realActionCount())
       
   217                 break;
       
   218             hideMenu();
       
   219             deleteMenu();
       
   220             break;
       
   221 
       
   222         case Qt::Key_Left:
       
   223             e->accept();
       
   224             moveLeft(e->modifiers() & Qt::ControlModifier);
       
   225             return true;
       
   226 
       
   227         case Qt::Key_Right:
       
   228             e->accept();
       
   229             moveRight(e->modifiers() & Qt::ControlModifier);
       
   230             return true; // no update
       
   231 
       
   232         case Qt::Key_Up:
       
   233             e->accept();
       
   234             moveUp();
       
   235             return true;
       
   236 
       
   237         case Qt::Key_Down:
       
   238             e->accept();
       
   239             moveDown();
       
   240             return true;
       
   241 
       
   242         case Qt::Key_PageUp:
       
   243             m_currentIndex = 0;
       
   244             break;
       
   245 
       
   246         case Qt::Key_PageDown:
       
   247             m_currentIndex = actions().count() - 1;
       
   248             break;
       
   249 
       
   250         case Qt::Key_Enter:
       
   251         case Qt::Key_Return:
       
   252             e->accept();
       
   253             enterEditMode();
       
   254             return true; // no update
       
   255 
       
   256         case Qt::Key_Alt:
       
   257         case Qt::Key_Shift:
       
   258         case Qt::Key_Control:
       
   259         case Qt::Key_Escape:
       
   260             e->ignore();
       
   261             setFocus(); // FIXME: this is because some other widget get the focus when CTRL is pressed
       
   262             return true; // no update
       
   263 
       
   264         default:
       
   265             if (!e->text().isEmpty() && e->text().at(0).toLatin1() >= 32) {
       
   266                 showLineEdit();
       
   267                 QApplication::sendEvent(m_editor, e);
       
   268                 e->accept();
       
   269             } else {
       
   270                 e->ignore();
       
   271             }
       
   272             return true;
       
   273         }
       
   274     } else { // In edit mode
       
   275         switch (e->key()) {
       
   276         default:
       
   277             return false;
       
   278 
       
   279         case Qt::Key_Control:
       
   280             e->ignore();
       
   281             return true;
       
   282 
       
   283         case Qt::Key_Enter:
       
   284         case Qt::Key_Return:
       
   285             if (!m_editor->text().isEmpty()) {
       
   286                 leaveEditMode(ForceAccept);
       
   287                 if (m_lastFocusWidget)
       
   288                     m_lastFocusWidget->setFocus();
       
   289 
       
   290                 m_editor->hide();
       
   291                 showMenu();
       
   292                 break;
       
   293             }
       
   294             // fall through
       
   295 
       
   296         case Qt::Key_Escape:
       
   297             update();
       
   298             setFocus();
       
   299             break;
       
   300         }
       
   301     }
       
   302 
       
   303     e->accept();
       
   304     update();
       
   305 
       
   306     return true;
       
   307 }
       
   308 
       
   309 void QDesignerMenuBar::startDrag(const QPoint &pos)
       
   310 {
       
   311     const int index = findAction(pos);
       
   312     if (m_currentIndex == -1 || index >= realActionCount())
       
   313         return;
       
   314 
       
   315     QAction *action = safeActionAt(index);
       
   316 
       
   317     QDesignerFormWindowInterface *fw = formWindow();
       
   318     RemoveActionFromCommand *cmd = new RemoveActionFromCommand(fw);
       
   319     cmd->init(this, action, actions().at(index + 1));
       
   320     fw->commandHistory()->push(cmd);
       
   321 
       
   322     adjustSize();
       
   323 
       
   324     hideMenu(index);
       
   325 
       
   326     QDrag *drag = new QDrag(this);
       
   327     drag->setPixmap(ActionRepositoryMimeData::actionDragPixmap(action));
       
   328     drag->setMimeData(new ActionRepositoryMimeData(action, Qt::MoveAction));
       
   329 
       
   330     const int old_index = m_currentIndex;
       
   331     m_currentIndex = -1;
       
   332 
       
   333     if (drag->start(Qt::MoveAction) == Qt::IgnoreAction) {
       
   334         InsertActionIntoCommand *cmd = new InsertActionIntoCommand(fw);
       
   335         cmd->init(this, action, safeActionAt(index));
       
   336         fw->commandHistory()->push(cmd);
       
   337 
       
   338         m_currentIndex = old_index;
       
   339         adjustSize();
       
   340     }
       
   341 }
       
   342 
       
   343 bool QDesignerMenuBar::handleMousePressEvent(QWidget *, QMouseEvent *event)
       
   344 {
       
   345     m_startPosition = QPoint();
       
   346     event->accept();
       
   347 
       
   348     if (event->button() != Qt::LeftButton)
       
   349         return true;
       
   350 
       
   351     m_startPosition = event->pos();
       
   352     const int newIndex = actionIndexAt(this, m_startPosition, Qt::Horizontal);
       
   353     const bool changed = newIndex != m_currentIndex;
       
   354     m_currentIndex =  newIndex;
       
   355     updateCurrentAction(changed);
       
   356 
       
   357     return true;
       
   358 }
       
   359 
       
   360 bool QDesignerMenuBar::handleMouseReleaseEvent(QWidget *, QMouseEvent *event)
       
   361 {
       
   362     m_startPosition = QPoint();
       
   363 
       
   364     if (event->button() != Qt::LeftButton)
       
   365         return true;
       
   366 
       
   367     event->accept();
       
   368     m_currentIndex = actionIndexAt(this, event->pos(), Qt::Horizontal);
       
   369     if (!m_editor->isVisible() && m_currentIndex != -1 && m_currentIndex < realActionCount())
       
   370         showMenu();
       
   371 
       
   372     return true;
       
   373 }
       
   374 
       
   375 bool QDesignerMenuBar::handleMouseMoveEvent(QWidget *, QMouseEvent *event)
       
   376 {
       
   377     if ((event->buttons() & Qt::LeftButton) != Qt::LeftButton)
       
   378         return true;
       
   379 
       
   380     if (m_startPosition.isNull())
       
   381         return true;
       
   382 
       
   383     const QPoint pos = mapFromGlobal(event->globalPos());
       
   384 
       
   385     if ((pos - m_startPosition).manhattanLength() < qApp->startDragDistance())
       
   386         return true;
       
   387 
       
   388     const int index =  actionIndexAt(this, m_startPosition, Qt::Horizontal);
       
   389     if (index < actions().count()) {
       
   390         hideMenu(index);
       
   391         update();
       
   392     }
       
   393 
       
   394     startDrag(m_startPosition);
       
   395     m_startPosition = QPoint();
       
   396 
       
   397     return true;
       
   398 }
       
   399 
       
   400 ActionList QDesignerMenuBar::contextMenuActions()
       
   401 {
       
   402     ActionList rc;
       
   403     if (QAction *action = safeActionAt(m_currentIndex)) {
       
   404         if (!qobject_cast<SpecialMenuAction*>(action)) {
       
   405             QVariant itemData;
       
   406             qVariantSetValue(itemData, action);
       
   407 
       
   408             QAction *remove_action = new QAction(tr("Remove Menu '%1'").arg(action->menu()->objectName()), 0);
       
   409             remove_action->setData(itemData);
       
   410             connect(remove_action, SIGNAL(triggered()), this, SLOT(deleteMenu()));
       
   411             rc.push_back(remove_action);
       
   412             QAction *sep = new QAction(0);
       
   413             sep->setSeparator(true);
       
   414             rc.push_back(sep);
       
   415         }
       
   416     }
       
   417 
       
   418     m_promotionTaskMenu->addActions(formWindow(), PromotionTaskMenu::TrailingSeparator, rc);
       
   419 
       
   420     QAction *remove_menubar = new QAction(tr("Remove Menu Bar"), 0);
       
   421     connect(remove_menubar, SIGNAL(triggered()), this, SLOT(slotRemoveMenuBar()));
       
   422     rc.push_back(remove_menubar);
       
   423     return rc;
       
   424 }
       
   425 
       
   426 bool QDesignerMenuBar::handleContextMenuEvent(QWidget *, QContextMenuEvent *event)
       
   427 {
       
   428     event->accept();
       
   429 
       
   430     m_currentIndex = actionIndexAt(this, mapFromGlobal(event->globalPos()), Qt::Horizontal);
       
   431 
       
   432     update();
       
   433 
       
   434     QMenu menu;
       
   435     const ActionList al = contextMenuActions();
       
   436     const ActionList::const_iterator acend = al.constEnd();
       
   437     for (ActionList::const_iterator it =  al.constBegin(); it != acend; ++it)
       
   438         menu.addAction(*it);
       
   439     menu.exec(event->globalPos());
       
   440     return true;
       
   441 }
       
   442 
       
   443 void QDesignerMenuBar::slotRemoveMenuBar()
       
   444 {
       
   445     Q_ASSERT(formWindow() != 0);
       
   446 
       
   447     QDesignerFormWindowInterface *fw = formWindow();
       
   448 
       
   449     DeleteMenuBarCommand *cmd = new DeleteMenuBarCommand(fw);
       
   450     cmd->init(this);
       
   451     fw->commandHistory()->push(cmd);
       
   452 }
       
   453 
       
   454 void QDesignerMenuBar::focusOutEvent(QFocusEvent *event)
       
   455 {
       
   456     QMenuBar::focusOutEvent(event);
       
   457 }
       
   458 
       
   459 void QDesignerMenuBar::enterEditMode()
       
   460 {
       
   461     if (m_currentIndex >= 0 && m_currentIndex <= realActionCount()) {
       
   462         showLineEdit();
       
   463     }
       
   464 }
       
   465 
       
   466 void QDesignerMenuBar::leaveEditMode(LeaveEditMode mode)
       
   467 {
       
   468     m_editor->releaseKeyboard();
       
   469 
       
   470     if (mode == Default)
       
   471         return;
       
   472 
       
   473     if (m_editor->text().isEmpty())
       
   474         return;
       
   475 
       
   476     QAction *action = 0;
       
   477 
       
   478     QDesignerFormWindowInterface *fw = formWindow();
       
   479     Q_ASSERT(fw);
       
   480 
       
   481     if (m_currentIndex >= 0 && m_currentIndex < realActionCount()) {
       
   482         action = safeActionAt(m_currentIndex);
       
   483         fw->beginCommand(QApplication::translate("Command", "Change Title"));
       
   484     } else {
       
   485         fw->beginCommand(QApplication::translate("Command", "Insert Menu"));
       
   486         const QString niceObjectName = ActionEditor::actionTextToName(m_editor->text(), QLatin1String("menu"));
       
   487         QMenu *menu = qobject_cast<QMenu*>(fw->core()->widgetFactory()->createWidget(QLatin1String("QMenu"), this));
       
   488         fw->core()->widgetFactory()->initialize(menu);
       
   489         menu->setObjectName(niceObjectName);
       
   490         menu->setTitle(tr("Menu"));
       
   491         fw->ensureUniqueObjectName(menu);
       
   492         action = menu->menuAction();
       
   493         AddMenuActionCommand *cmd = new AddMenuActionCommand(fw);
       
   494         cmd->init(action, m_addMenu, this, this);
       
   495         fw->commandHistory()->push(cmd);
       
   496     }
       
   497 
       
   498     SetPropertyCommand *cmd = new SetPropertyCommand(fw);
       
   499     cmd->init(action, QLatin1String("text"), m_editor->text());
       
   500     fw->commandHistory()->push(cmd);
       
   501     fw->endCommand();
       
   502 }
       
   503 
       
   504 void QDesignerMenuBar::showLineEdit()
       
   505 {
       
   506     QAction *action = 0;
       
   507 
       
   508     if (m_currentIndex >= 0 && m_currentIndex < realActionCount())
       
   509         action = safeActionAt(m_currentIndex);
       
   510     else
       
   511         action = m_addMenu;
       
   512 
       
   513     if (action->isSeparator())
       
   514         return;
       
   515 
       
   516     // hideMenu();
       
   517 
       
   518     m_lastFocusWidget = qApp->focusWidget();
       
   519 
       
   520     // open edit field for item name
       
   521     const QString text = action != m_addMenu ? action->text() : QString();
       
   522 
       
   523     m_editor->setText(text);
       
   524     m_editor->selectAll();
       
   525     m_editor->setGeometry(actionGeometry(action));
       
   526     m_editor->show();
       
   527     qApp->setActiveWindow(m_editor);
       
   528     m_editor->setFocus();
       
   529     m_editor->grabKeyboard();
       
   530 }
       
   531 
       
   532 bool QDesignerMenuBar::eventFilter(QObject *object, QEvent *event)
       
   533 {
       
   534     if (object != this && object != m_editor)
       
   535         return false;
       
   536 
       
   537     if (!m_editor->isHidden() && object == m_editor && event->type() == QEvent::FocusOut) {
       
   538         leaveEditMode(Default);
       
   539         m_editor->hide();
       
   540         update();
       
   541         return true;
       
   542     }
       
   543 
       
   544     bool dispatch = true;
       
   545 
       
   546     switch (event->type()) {
       
   547         default: break;
       
   548 
       
   549         case QEvent::KeyPress:
       
   550         case QEvent::KeyRelease:
       
   551         case QEvent::ContextMenu:
       
   552         case QEvent::MouseMove:
       
   553         case QEvent::MouseButtonPress:
       
   554         case QEvent::MouseButtonRelease:
       
   555         case QEvent::MouseButtonDblClick:
       
   556             dispatch = (object != m_editor);
       
   557             // no break
       
   558 
       
   559         case QEvent::Enter:
       
   560         case QEvent::Leave:
       
   561         case QEvent::FocusIn:
       
   562         case QEvent::FocusOut:
       
   563         {
       
   564             QWidget *widget = qobject_cast<QWidget*>(object);
       
   565 
       
   566             if (dispatch && widget && (widget == this || isAncestorOf(widget)))
       
   567                 return handleEvent(widget, event);
       
   568         } break;
       
   569 
       
   570         case QEvent::Shortcut:
       
   571             event->accept();
       
   572             return true;
       
   573     }
       
   574 
       
   575     return false;
       
   576 };
       
   577 
       
   578 int QDesignerMenuBar::findAction(const QPoint &pos) const
       
   579 {
       
   580     const int index = actionIndexAt(this, pos, Qt::Horizontal);
       
   581     if (index == -1)
       
   582         return realActionCount();
       
   583 
       
   584     return index;
       
   585 }
       
   586 
       
   587 void QDesignerMenuBar::adjustIndicator(const QPoint &pos)
       
   588 {
       
   589     const int index = findAction(pos);
       
   590     QAction *action = safeActionAt(index);
       
   591     Q_ASSERT(action != 0);
       
   592 
       
   593     if (pos != QPoint(-1, -1)) {
       
   594         QDesignerMenu *m = qobject_cast<QDesignerMenu*>(action->menu());
       
   595         if (!m || m->parentMenu()) {
       
   596             m_currentIndex = index;
       
   597             showMenu(index);
       
   598         }
       
   599     }
       
   600 
       
   601     if (QDesignerActionProviderExtension *a = actionProvider()) {
       
   602         a->adjustIndicator(pos);
       
   603     }
       
   604 }
       
   605 
       
   606 QDesignerMenuBar::ActionDragCheck QDesignerMenuBar::checkAction(QAction *action) const
       
   607 {
       
   608     // action belongs to another form
       
   609     if (!action || !Utils::isObjectAncestorOf(formWindow()->mainContainer(), action))
       
   610         return NoActionDrag;
       
   611 
       
   612     if (!action->menu())
       
   613         return ActionDragOnSubMenu; // simple action only on sub menus
       
   614 
       
   615     QDesignerMenu *m = qobject_cast<QDesignerMenu*>(action->menu());
       
   616     if (m && m->parentMenu())
       
   617         return ActionDragOnSubMenu; // it looks like a submenu
       
   618 
       
   619     if (actions().contains(action))
       
   620         return ActionDragOnSubMenu; // we already have the action in the menubar
       
   621 
       
   622     return AcceptActionDrag;
       
   623 }
       
   624 
       
   625 void QDesignerMenuBar::dragEnterEvent(QDragEnterEvent *event)
       
   626 {
       
   627     const ActionRepositoryMimeData *d = qobject_cast<const ActionRepositoryMimeData*>(event->mimeData());
       
   628     if (!d || d->actionList().empty()) {
       
   629         event->ignore();
       
   630         return;
       
   631     }
       
   632 
       
   633     QAction *action = d->actionList().first();
       
   634     switch (checkAction(action)) {
       
   635     case NoActionDrag:
       
   636         event->ignore();
       
   637         break;
       
   638     case ActionDragOnSubMenu:
       
   639         m_dragging = true;
       
   640         d->accept(event);
       
   641         break;
       
   642     case AcceptActionDrag:
       
   643         m_dragging = true;
       
   644         d->accept(event);
       
   645         adjustIndicator(event->pos());
       
   646         break;
       
   647     }
       
   648 }
       
   649 
       
   650 void QDesignerMenuBar::dragMoveEvent(QDragMoveEvent *event)
       
   651 {
       
   652     const ActionRepositoryMimeData *d = qobject_cast<const ActionRepositoryMimeData*>(event->mimeData());
       
   653     if (!d || d->actionList().empty()) {
       
   654         event->ignore();
       
   655         return;
       
   656     }
       
   657     QAction *action = d->actionList().first();
       
   658 
       
   659     switch (checkAction(action)) {
       
   660     case NoActionDrag:
       
   661         event->ignore();
       
   662         break;
       
   663     case ActionDragOnSubMenu:
       
   664         event->ignore();
       
   665         showMenu(findAction(event->pos()));
       
   666         break;
       
   667     case AcceptActionDrag:
       
   668         d->accept(event);
       
   669         adjustIndicator(event->pos());
       
   670         break;
       
   671     }
       
   672 }
       
   673 
       
   674 void QDesignerMenuBar::dragLeaveEvent(QDragLeaveEvent *)
       
   675 {
       
   676     m_dragging = false;
       
   677 
       
   678     adjustIndicator(QPoint(-1, -1));
       
   679 }
       
   680 
       
   681 void QDesignerMenuBar::dropEvent(QDropEvent *event)
       
   682 {
       
   683     m_dragging = false;
       
   684 
       
   685     if (const ActionRepositoryMimeData *d = qobject_cast<const ActionRepositoryMimeData*>(event->mimeData())) {
       
   686 
       
   687         QAction *action = d->actionList().first();
       
   688         if (checkAction(action) == AcceptActionDrag) {
       
   689             event->acceptProposedAction();
       
   690             int index = findAction(event->pos());
       
   691             index = qMin(index, actions().count() - 1);
       
   692 
       
   693             QDesignerFormWindowInterface *fw = formWindow();
       
   694             InsertActionIntoCommand *cmd = new InsertActionIntoCommand(fw);
       
   695             cmd->init(this, action, safeActionAt(index));
       
   696             fw->commandHistory()->push(cmd);
       
   697 
       
   698             m_currentIndex = index;
       
   699             update();
       
   700             adjustIndicator(QPoint(-1, -1));
       
   701             return;
       
   702         }
       
   703     }
       
   704     event->ignore();
       
   705 }
       
   706 
       
   707 void QDesignerMenuBar::actionEvent(QActionEvent *event)
       
   708 {
       
   709     QMenuBar::actionEvent(event);
       
   710 }
       
   711 
       
   712 QDesignerFormWindowInterface *QDesignerMenuBar::formWindow() const
       
   713 {
       
   714     return QDesignerFormWindowInterface::findFormWindow(const_cast<QDesignerMenuBar*>(this));
       
   715 }
       
   716 
       
   717 QDesignerActionProviderExtension *QDesignerMenuBar::actionProvider()
       
   718 {
       
   719     if (QDesignerFormWindowInterface *fw = formWindow()) {
       
   720         QDesignerFormEditorInterface *core = fw->core();
       
   721         return qt_extension<QDesignerActionProviderExtension*>(core->extensionManager(), this);
       
   722     }
       
   723 
       
   724     return 0;
       
   725 }
       
   726 
       
   727 QAction *QDesignerMenuBar::currentAction() const
       
   728 {
       
   729     if (m_currentIndex < 0 || m_currentIndex >= actions().count())
       
   730         return 0;
       
   731 
       
   732     return safeActionAt(m_currentIndex);
       
   733 }
       
   734 
       
   735 int QDesignerMenuBar::realActionCount() const
       
   736 {
       
   737     return actions().count() - 1; // 1 fake actions
       
   738 }
       
   739 
       
   740 bool QDesignerMenuBar::dragging() const
       
   741 {
       
   742     return m_dragging;
       
   743 }
       
   744 
       
   745 void QDesignerMenuBar::moveLeft(bool ctrl)
       
   746 {
       
   747     if (layoutDirection() == Qt::LeftToRight) {
       
   748         movePrevious(ctrl);
       
   749     } else {
       
   750         moveNext(ctrl);
       
   751     }
       
   752 }
       
   753 
       
   754 void QDesignerMenuBar::moveRight(bool ctrl)
       
   755 {
       
   756     if (layoutDirection() == Qt::LeftToRight) {
       
   757         moveNext(ctrl);
       
   758     } else {
       
   759         movePrevious(ctrl);
       
   760     }
       
   761 }
       
   762 
       
   763 void QDesignerMenuBar::movePrevious(bool ctrl)
       
   764 {
       
   765     const bool swapped = ctrl && swapActions(m_currentIndex, m_currentIndex - 1);
       
   766     const int newIndex = qMax(0, m_currentIndex - 1);
       
   767     // Always re-select, swapping destroys order
       
   768     if (swapped || newIndex != m_currentIndex) {
       
   769         m_currentIndex = newIndex;
       
   770         updateCurrentAction(true);
       
   771     }
       
   772 }
       
   773 
       
   774 void QDesignerMenuBar::moveNext(bool ctrl)
       
   775 {
       
   776     const bool swapped = ctrl && swapActions(m_currentIndex + 1, m_currentIndex);
       
   777     const int newIndex = qMin(actions().count() - 1, m_currentIndex + 1);
       
   778     if (swapped || newIndex != m_currentIndex) {
       
   779         m_currentIndex = newIndex;
       
   780         updateCurrentAction(!ctrl);
       
   781     }
       
   782 }
       
   783 
       
   784 void QDesignerMenuBar::moveUp()
       
   785 {
       
   786     update();
       
   787 }
       
   788 
       
   789 void QDesignerMenuBar::moveDown()
       
   790 {
       
   791     showMenu();
       
   792 }
       
   793 
       
   794 void QDesignerMenuBar::adjustSpecialActions()
       
   795 {
       
   796     removeAction(m_addMenu);
       
   797     addAction(m_addMenu);
       
   798 }
       
   799 
       
   800 bool QDesignerMenuBar::interactive(bool i)
       
   801 {
       
   802     const bool old = m_interactive;
       
   803     m_interactive = i;
       
   804     return old;
       
   805 }
       
   806 
       
   807 void QDesignerMenuBar::hideMenu(int index)
       
   808 {
       
   809     if (index < 0 && m_currentIndex >= 0)
       
   810         index = m_currentIndex;
       
   811 
       
   812     if (index < 0 || index >= realActionCount())
       
   813         return;
       
   814 
       
   815     QAction *action = safeActionAt(index);
       
   816 
       
   817     if (action && action->menu()) {
       
   818         action->menu()->hide();
       
   819 
       
   820         if (QDesignerMenu *menu = qobject_cast<QDesignerMenu*>(action->menu())) {
       
   821             menu->closeMenuChain();
       
   822         }
       
   823     }
       
   824 }
       
   825 
       
   826 void QDesignerMenuBar::deleteMenu()
       
   827 {
       
   828     deleteMenuAction(currentAction());
       
   829 }
       
   830 
       
   831 void QDesignerMenuBar::deleteMenuAction(QAction *action)
       
   832 {
       
   833     if (action && !qobject_cast<SpecialMenuAction*>(action)) {
       
   834         const int pos = actions().indexOf(action);
       
   835         QAction *action_before = 0;
       
   836         if (pos != -1)
       
   837             action_before = safeActionAt(pos + 1);
       
   838 
       
   839         QDesignerFormWindowInterface *fw = formWindow();
       
   840         RemoveMenuActionCommand *cmd = new RemoveMenuActionCommand(fw);
       
   841         cmd->init(action, action_before, this, this);
       
   842         fw->commandHistory()->push(cmd);
       
   843     }
       
   844 }
       
   845 
       
   846 void QDesignerMenuBar::showMenu(int index)
       
   847 {
       
   848     if (index < 0 && m_currentIndex >= 0)
       
   849         index = m_currentIndex;
       
   850 
       
   851     if (index < 0 || index >= realActionCount())
       
   852         return;
       
   853 
       
   854     m_currentIndex = index;
       
   855     QAction *action = currentAction();
       
   856 
       
   857     if (action && action->menu()) {
       
   858         if (m_lastMenuActionIndex != -1 && m_lastMenuActionIndex != index) {
       
   859             hideMenu(m_lastMenuActionIndex);
       
   860         }
       
   861 
       
   862         m_lastMenuActionIndex = index;
       
   863         QMenu *menu = action->menu();
       
   864         const QRect g = actionGeometry(action);
       
   865 
       
   866         if (!menu->isVisible()) {
       
   867             if ((menu->windowFlags() & Qt::Popup) != Qt::Popup)
       
   868                 menu->setWindowFlags(Qt::Popup);
       
   869             menu->adjustSize();
       
   870             menu->move(mapToGlobal(g.bottomLeft()));
       
   871             menu->setFocus(Qt::MouseFocusReason);
       
   872             menu->raise();
       
   873             menu->show();
       
   874         } else {
       
   875             menu->raise();
       
   876         }
       
   877     }
       
   878 }
       
   879 
       
   880 QAction *QDesignerMenuBar::safeActionAt(int index) const
       
   881 {
       
   882     if (index < 0 || index >= actions().count())
       
   883         return 0;
       
   884 
       
   885     return actions().at(index);
       
   886 }
       
   887 
       
   888 bool QDesignerMenuBar::swapActions(int a, int b)
       
   889 {
       
   890     const int left = qMin(a, b);
       
   891     int right = qMax(a, b);
       
   892 
       
   893     QAction *action_a = safeActionAt(left);
       
   894     QAction *action_b = safeActionAt(right);
       
   895 
       
   896     if (action_a == action_b
       
   897             || !action_a
       
   898             || !action_b
       
   899             || qobject_cast<SpecialMenuAction*>(action_a)
       
   900             || qobject_cast<SpecialMenuAction*>(action_b))
       
   901         return false; // nothing to do
       
   902 
       
   903     right = qMin(right, realActionCount());
       
   904     if (right < 0)
       
   905         return false; // nothing to do
       
   906 
       
   907     formWindow()->beginCommand(QApplication::translate("Command", "Move action"));
       
   908 
       
   909     QAction *action_b_before = safeActionAt(right + 1);
       
   910 
       
   911     QDesignerFormWindowInterface *fw = formWindow();
       
   912     RemoveActionFromCommand *cmd1 = new RemoveActionFromCommand(fw);
       
   913     cmd1->init(this, action_b, action_b_before, false);
       
   914     fw->commandHistory()->push(cmd1);
       
   915 
       
   916     QAction *action_a_before = safeActionAt(left + 1);
       
   917 
       
   918     InsertActionIntoCommand *cmd2 = new InsertActionIntoCommand(fw);
       
   919     cmd2->init(this, action_b, action_a_before, false);
       
   920     fw->commandHistory()->push(cmd2);
       
   921 
       
   922     RemoveActionFromCommand *cmd3 = new RemoveActionFromCommand(fw);
       
   923     cmd3->init(this, action_a, action_b, false);
       
   924     fw->commandHistory()->push(cmd3);
       
   925 
       
   926     InsertActionIntoCommand *cmd4 = new InsertActionIntoCommand(fw);
       
   927     cmd4->init(this, action_a, action_b_before, true);
       
   928     fw->commandHistory()->push(cmd4);
       
   929 
       
   930     fw->endCommand();
       
   931 
       
   932     return true;
       
   933 }
       
   934 
       
   935 void QDesignerMenuBar::keyPressEvent(QKeyEvent *event)
       
   936 {
       
   937     event->ignore();
       
   938 }
       
   939 
       
   940 void QDesignerMenuBar::keyReleaseEvent(QKeyEvent *event)
       
   941 {
       
   942     event->ignore();
       
   943 }
       
   944 
       
   945 void QDesignerMenuBar::updateCurrentAction(bool selectAction)
       
   946 {
       
   947     update();
       
   948 
       
   949     if (!selectAction)
       
   950         return;
       
   951 
       
   952     QAction *action = currentAction();
       
   953     if (!action || action == m_addMenu)
       
   954         return;
       
   955 
       
   956     QMenu *menu = action->menu();
       
   957     if (!menu)
       
   958         return;
       
   959 
       
   960     QDesignerObjectInspector *oi = 0;
       
   961     if (QDesignerFormWindowInterface *fw = formWindow())
       
   962         oi = qobject_cast<QDesignerObjectInspector *>(fw->core()->objectInspector());
       
   963 
       
   964     if (!oi)
       
   965         return;
       
   966 
       
   967     oi->clearSelection();
       
   968     oi->selectObject(menu);
       
   969 }
       
   970 
       
   971 QT_END_NAMESPACE