diff -r 000000000000 -r 16d8024aca5e src/hbcore/gui/hbmenu.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hbcore/gui/hbmenu.cpp Mon Apr 19 14:02:13 2010 +0300 @@ -0,0 +1,915 @@ +/**************************************************************************** +** +** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (developer.feedback@nokia.com) +** +** This file is part of the HbCore module of the UI Extensions for Mobile. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at developer.feedback@nokia.com. +** +****************************************************************************/ + +#include "hbmenu.h" +#include "hbmenu_p.h" +#include "hbmenuitem_p.h" +#include "hbaction.h" +#include +#include "hbinstance.h" +#include "hbmenucontainer_p.h" +#ifdef HB_EFFECTS +#include "hbeffect.h" +#include "hbeffectinternal_p.h" +bool HbMenuPrivate::menuEffectsLoaded = false; +#endif + +#include + +Q_DECLARE_METATYPE (QAction*)// krazy:exclude=qclasses + +HbMenuPrivate::HbMenuPrivate(): + HbPopupPrivate(), + menuItemView(0), + subMenuAction(0), + activeSubMenu(0), + resultAction(0), + actionTriggered(false), + menuType(HbMenu::ContextMenu), + mSubMenuItem(0), + mRightMargin(0.0), + mDownMargin(0.0), + delayMenuConstruction(true), + receiverToDisconnectOnClose(0) +{ +} + +HbMenuPrivate::~HbMenuPrivate() +{ +} + +void HbMenuPrivate::init() +{ + Q_Q(HbMenu); + + subMenuAction = new HbAction(q); + subMenuAction->setMenu(q); + q->setTimeout(HbPopup::ContextMenuTimeout); + + q->setBackgroundFaded(false); + q->setFlag(QGraphicsItem::ItemClipsChildrenToShape); +} + +void HbMenuPrivate::addPopupEffects() +{ +#ifdef HB_EFFECTS + effectType = "HB_MENU"; + hasEffects = menuEffectsLoaded; + if (menuEffectsLoaded) + return; + menuEffectsLoaded = true; + hasEffects = HbEffectInternal::add("HB_MENU", "menu_appear", "appear"); + if (hasEffects) { + //We load the disappear effect only if appear effect was also loaded + hasEffects = HbEffectInternal::add("HB_MENU", "menu_disappear", "disappear"); + + if (hasEffects) { + hasEffects = HbEffectInternal::add("HB_menuitem", "menuitem_press", "clicked"); + } + if (hasEffects ) { + hasEffects = HbEffectInternal::add("HB_POPUP", + "dialog_rotate", + "orientationswitch"); + } + } +#endif +} + +void HbMenuPrivate::_q_triggerAction(HbMenuItem *currentItem) +{ + Q_Q(HbMenu); + if (currentItem && currentItem->action()){ + HbWidgetFeedback::triggered(currentItem, Hb::InstantClicked); +#ifdef HB_EFFECTS + if (hasEffects) { + HbEffect::start(currentItem, "HB_menuitem", "clicked"); + } +#endif + HbAction *hbAction = qobject_cast(currentItem->action()); + if (hbAction && hbAction->menu()) { + hbAction->trigger(); + stopTimeout(); + openSubmenu(currentItem); + } else { + q->close(); + + resultAction = hbAction; + + if (!actionTriggered) { // prevent duplicate events + currentItem->action()->trigger(); + } + actionTriggered = true; + } + } +} + +void HbMenuPrivate::createMenuView() +{ + Q_Q(HbMenu); + if (!menuItemView && q->actions().count()){ + menuItemView = new HbMenuListView(q, q); + HbStyle::setItemName(menuItemView, "content"); + /* This is for qt versions 4.5,which had the clipping problem. + FOR http://www.qtsoftware.com/developer/task-tracker/index_html?id=257232&method=entry + see also HbMenu constructor */ +#if QT_VERSION < 0x040600 + menuItemView->setFlag( QGraphicsItem::ItemClipsChildrenToShape, false ); +#endif + //This optimises case of options menu which otherwise updates its primitives twice. + if (menuType == HbMenu::OptionsMenu) + q->setFrameType(HbPopup::Strong); + else + q->setFrameType(HbPopup::Weak); + if (polished)//This check can be removed once base class repolish is fixed. + q->repolish(); + } +} + +void HbMenuPrivate::delayedLayout() +{ + createMenuView(); + if(menuItemView) + menuItemView->doDelayedLayout(); + delayMenuConstruction = false; +} + +void HbMenuPrivate::changeToOptionsMenu() +{ + menuType = HbMenu::OptionsMenu; +} + +HbMenuItem *HbMenuPrivate::subMenuItem() +{ + return mSubMenuItem; +} + +void HbMenuPrivate::setSubMenuItem(HbMenuItem *menuItem) +{ + mSubMenuItem = menuItem; +} + +void HbMenuPrivate::_q_onActionTriggered() +{ + Q_Q(HbMenu); + HbAction *action = qobject_cast(q->sender()); + if (action && !action->menu() ) { // do not trigger from opening submenu + emit q->triggered(action); + } +} + +void HbMenuPrivate::_q_subMenuItemTriggered(HbAction *action) +{ + Q_Q(HbMenu); + + // do not close the menu tree if the triggered action is + // submenu item + if (!action->menu()) { + q->close(); + } else { + stopTimeout(); + } +} + +void HbMenuPrivate::actionAdded(QActionEvent *actionEvent) +{ + if (delayMenuConstruction) + return; + if (actionEvent->action()->isVisible()){ + Q_Q(HbMenu); + createMenuView(); + QObject::connect(actionEvent->action(), SIGNAL(triggered()), q, SLOT(_q_onActionTriggered())); + menuItemView->addActionItem(actionEvent->action()); + } +} + +void HbMenuPrivate::actionRemoved(QActionEvent *actionEvent) +{ + if (delayMenuConstruction) + return; + Q_Q(HbMenu); + QObject::disconnect(actionEvent->action(), 0, q, 0); + if (menuItemView) + menuItemView->removeActionItem(actionEvent->action()); +} + +void HbMenuPrivate::actionChanged(QActionEvent *actionEvent) +{ + if (delayMenuConstruction) + return; + if (menuItemView) + menuItemView->updateActionItem(actionEvent->action()); +} + +/* + Returns current focusable action based on current row of the menuItemView or index if specified. + If there is no focusable action it returns 0. + Also returns the active item representing the active action or 0. +*/ +HbAction *HbMenuPrivate::activeAction(HbMenuItem *&activeItem) const +{ + if(!menuItemView) + return 0; + HbAction *action = 0; + HbMenuItem *currentItem = menuItemView->currentItem(); + if(currentItem && currentItem->action() && currentItem->action()->isVisible() && + currentItem->action()->isEnabled() && !currentItem->action()->isSeparator()) { + action = static_cast(currentItem->action()); + activeItem = currentItem; + } + return action; +} + +/* + Convenience overload +*/ +HbAction *HbMenuPrivate::activeAction() const +{ + HbMenuItem* activeItem = 0; + return activeAction(activeItem); +} + +/* + Opens a submenu for activeItem. If activeItem is 0 it uses activeAction() to determine active item + and opens submenu for it if active action has submenu. +*/ +void HbMenuPrivate::openSubmenu(HbMenuItem *activeItem) +{ + Q_Q(HbMenu); + + if (!activeItem) { + activeAction(activeItem); + } + + if (activeItem && activeItem->action() && activeItem->action()->isEnabled()) { + HbAction *hbAction = qobject_cast(activeItem->action()); + if (!hbAction) + return; + HbMenu *subMenu = hbAction->menu(); + if ( subMenu ) { + subMenu->setLayoutDirection(q->layoutDirection()); + + activeSubMenu = subMenu; + subMenu->setTimeout(timeout); + QObject::disconnect(subMenu, SIGNAL(aboutToClose()), q, SLOT(_q_subMenuTimedOut())); + QObject::connect(subMenu, SIGNAL(aboutToClose()), q, SLOT(_q_subMenuTimedOut())); + QObject::connect(subMenu, SIGNAL(triggered(HbAction*)), q, SLOT(_q_subMenuItemTriggered(HbAction*))); + subMenu->show(); + + // Reset the active submenu so that mouse event handling works. + // huh ? activeSubMenu = 0; + } + } +} + +void HbMenuPrivate::_q_subMenuTimedOut() +{ + Q_Q(HbMenu); + if( menuTimedOut (activeSubMenu) ) { + if ( activeSubMenu ) { + activeSubMenu->disconnect(); + } + q->close(); + } +} + +bool HbMenuPrivate::menuTimedOut(HbMenu* menu) +{ + return (menu && menu->timeout() > 0 && HbMenuPrivate::d_ptr(menu)->timedOut); +} + +void HbMenuPrivate::closeSubmenu() +{ + // Check whether this is a submenu. + if (activeSubMenu) { + activeSubMenu->close(); + } +} + +void HbMenuPrivate::setSubMenuPosition() +{ + Q_Q(HbMenu); + if (mSubMenuItem) { + qreal upperEdge = mSubMenuItem->scenePos().y() + mSubMenuItem->size().height() * 2 / 3; + QSizeF windowSize = QSizeF(0,0); + if (q->mainWindow()) { + QGraphicsWidget *viewPortItem = q->mainWindow()->element(HbMainWindow::ViewportItem); + if (viewPortItem) { + windowSize = viewPortItem->size(); + } + } + if (windowSize.height() - mDownMargin - q->preferredHeight() < upperEdge) { + upperEdge = windowSize.height() - mDownMargin - q->preferredHeight(); + } + if (q->layoutDirection() == Qt::LeftToRight) { + qreal leftEdge = mSubMenuItem->scenePos().x() + + mSubMenuItem->size().width() - mRightMargin; + if ((windowSize.width() - q->size().width()) < leftEdge) { + leftEdge = mSubMenuItem->scenePos().x() + + mSubMenuItem->size().width() + + mRightMargin - q->size().width(); + } + q->setPreferredPos(QPointF(leftEdge, upperEdge)); + } else { + qreal rightEdge = mSubMenuItem->scenePos().x() + mRightMargin; + if ((rightEdge - q->size().width()) < 0) { + rightEdge = mSubMenuItem->scenePos().x() - mRightMargin + + q->size().width(); + } + q->setPreferredPos(QPointF(rightEdge, upperEdge), HbPopup::TopRightCorner); + } + } +} + +/*! + @stable + @hbcore + \class HbMenu + \brief HbMenu is a menu widget for use in HbView. + + \image html hbmenu.png A menu with checkable items and a sub-menu. + + Use an HbMenu to show a list of options. There are two main types of menus: + + - The view options menu + - Context menus (popup menus) + + There is one view options menu for each view. + It is shown by tapping the title bar. You can access the view options menu by calling + HbView::menu() which returns a pointer to a new empty menu if one does not already exist. + + You can create any number of context menus. + Context menus are usually invoked by a user action, such as tapping a widget. + + A menu contains a list of items. You can add three kinds of items to a menu: + + - Actions + - Sub-menus + - Separators + + An action is an object of class HbAction that performs an action when it is triggered. + Use addAction() to add an action to a menu. Actions can be checkable (QAction::setCheckable). + Use clearActions() to clear all actions from a menu. + Use removeAction() to remove individual actions from a menu. + + A sub-menu is a menu that is nested within another menu. Use addMenu() or insertMenu() to add a sub-menu to a menu. + Sub-menus can be nested within sub-menus. + + Separators group related items in a menu. + Use addSeparator() or insertSeparator() to create and add a separator to a menu. + + \image html hbmenu.png A menu with checkable actions and a sub-menu. + + After you add an action to your menu, you specify a receiver object and its slot (you can also + add an action and specify a receiver slot at the same time). + The receiver is notifed when the action is triggered (QAction::triggered()). + HbMenu also has a triggered() menu signal, which signals which HbAction was triggered in the menu. + + Context menu example: + + A menu and a few actions are created. The triggered() signal of the menu is connected to + the mute() function of the enclosing class (implementation not shown). + The exec() function shows the menu. + + User needs to connect to "longPress" signal and implement corresponding slot. This enables + longpress events to be received from list. + + \dontinclude decoratorlistdemo/contentwidget.cpp + \skip // Create new menu + \until ( coords ); + + \sa HbDialog, HbView +*/ + +/*! + \property HbMenu::menuType + \brief +*/ + +/*! + \fn void HbMenu::triggered(HbAction *action) + + This signal is emitted when one of the action items is selected. + \param action the action that was triggered in the menu. + */ + +/*! + \enum HbMenu::MenuType + + This enum describes different types of HbMenu. +*/ +/*! + \var HbMenu::ContextMenu + + ContextMenu is a menu which position is set by user. +*/ +/*! + \var HbMenu::OptionMenu + + OptionMenu is set by HbView. Its position cannot be changed. +*/ +/*! + \var HbMenu::SubMenu + + Menu becomes SubMenu when it is added to another menu. +*/ + +/*! + Constructs a menu with \a parent graphics item. + + \param parent is the parent graphics item. +*/ +HbMenu::HbMenu(QGraphicsItem *parent) : + HbPopup(*new HbMenuPrivate, parent) +{ + Q_D(HbMenu); + d->q_ptr = this; + d->init(); + /* This is for qt versions 4.5,which had the clipping problem. + FOR http://www.qtsoftware.com/developer/task-tracker/index_html?id=257232&method=entry + */ +#if QT_VERSION < 0x040600 + setFlag( QGraphicsItem::ItemClipsChildrenToShape, true ); +#endif +} + +/*! + Constructs a menu with \a title and \a parent graphics item. + \param title is the menu title. + \param parent is the parent graphics item. +*/ +HbMenu::HbMenu(const QString &title, QGraphicsItem *parent) : + HbPopup(*new HbMenuPrivate, parent) +{ + Q_D(HbMenu); + d->q_ptr = this; + d->init(); + setTitle(title); +} + +HbMenu::HbMenu(HbMenuPrivate &dd, QGraphicsItem *parent) : + HbPopup(dd, parent) +{ + Q_D(HbMenu); + d->q_ptr = this; + d->init(); +} + +HbMenu::~HbMenu() +{ + if (!scene() || !scene()->property("destructed").isValid()) { + foreach (QAction *action, actions()) {// krazy:exclude=qclasses + HbAction* hbAction = qobject_cast(action); + if (hbAction){ + if (hbAction->menu()) { + hbAction->menu()->deleteLater(); + } + hbAction->setMenu((HbMenu*)0); + } + } + } +} + +/*! + \deprecated HbMenu::exec(HbAction*) + is deprecated. Please use void HbMenu::open( QObject *receiver, const char *member ) + or HbMenu::show() instead. + + Executes the menu synchronously so that given \a action + is active. + + \param action is the action that is active when the menu is shown. + + Example usage: + \code + void MyGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *event) + { + HbMenu menu(); + menu.addAction(...); + ... + menu.setPreferredPos(event->scenePos(), HbPopup::BottomEdgeCenter); + menu.exec(); + } + \endcode + + \return the triggered HbAction in either the popup menu or one + of its sub-menus, or 0 if no item was triggered (normally because + the user closed or cancelled the menu). + */ +HbAction *HbMenu::exec(HbAction *action) +{ + Q_D(HbMenu); + if (actions().count() == 0) { + return 0; + } + + if(!action) + action = qobject_cast(actions().first()); + + setActiveAction(action); + + // Reset state variables + d->resultAction = 0; + d->actionTriggered = false; + + if (d->menuType == SubMenu && d->polished) { + d->setSubMenuPosition(); + } + QPointer menuAlive(this); + HbPopup::exec(); + + // HbMenu can be deleted while exec + if (menuAlive) { + return d->resultAction; + } else { + return 0; + } +} + +/*! + \deprecated HbMenu::exec(const QPointF&, HbAction*) + is deprecated. Please use void HbMenu::open( QObject *receiver, const char *member ) + or HbMenu::show() and setPreferredPos() instead. + + Executes the menu synchronously at \a pos so that given \a action + is active. + + \param pos is the position at which the menu is shown. + \param action is the action that is active when the menu is shown. + + Example usage: + \code + void MyGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *event) + { + HbMenu menu(); + menu.addAction(...); + ... + menu.exec(event->scenePos()); + } + \endcode + + \return the triggered HbAction in either the popup menu or one + of its sub-menus, or 0 if no item was triggered (normally because + the user closed or cancelled the menu). + */ +HbAction *HbMenu::exec(const QPointF &pos, HbAction *action ) +{ + Q_D(HbMenu); + if (d->menuType == ContextMenu) { + setPreferredPos(pos); + } + return exec(action); +} + +void HbMenu::showEvent(QShowEvent *event) +{ + Q_UNUSED(event); + Q_D(HbMenu); + d->actionTriggered = false; + + if (d->menuType == SubMenu && d->polished) { + d->setSubMenuPosition(); + } + + HbPopup::showEvent(event); +} + +/*! + Creates a new action with title \a text. It adds the newly created action to the menu's list of actions. + \param text is the text for the new action. + \return the new action. +*/ +HbAction *HbMenu::addAction(const QString &text) +{ + HbAction *action = new HbAction(text, this); + addAction(action); + return action; +} + +/*! + Creates a new action with \a text. + The action's triggered() signal is connected to the + \a receiver's \a member slot. The function adds the newly created + action to the menu's list of actions. + \return the new action. + */ +HbAction *HbMenu::addAction(const QString &text, const QObject *receiver, const char *member) +{ + HbAction *action = new HbAction(text, this); + connect(action, SIGNAL(triggered(bool)), receiver, member); + addAction(action); + return action; +} + +/*! + Adds \a menu as a sub-menu. + \param menu is the menu that is added to this one. + \return the action for the added sub-menu. + */ +HbAction *HbMenu::addMenu(HbMenu *menu) +{ + return insertMenu(0, menu); +} + +/*! + Creates a new HbMenu with \a title and adds it to this menu. + \param title is the menu title. + \return the new menu. +*/ +HbMenu *HbMenu::addMenu(const QString &title) +{ + HbMenu *menu = new HbMenu(title); + addMenu(menu); + return menu; +} + +/*! + Inserts \a menu before action \a before. + \param before is the action before which this new menu is inserted. + \param menu is the menu that is inserted. + \return the action associated with the inserted menu. + */ +HbAction *HbMenu::insertMenu(HbAction *before, HbMenu *menu) +{ + QObject::connect(menu, SIGNAL(triggered(HbAction*)), this, SLOT(_q_subMenuItemTriggered(HbAction*))); + QObject::connect(menu, SIGNAL(triggered(HbAction*)), this, SIGNAL(triggered(HbAction*))); + + menu->d_func()->menuType = HbMenu::SubMenu; + insertAction(before, menu->menuAction()); + return menu->menuAction(); +} + +/*! + \return the action associated with this menu. + */ +HbAction *HbMenu::menuAction() const +{ + Q_D(const HbMenu); + return d->subMenuAction; +} + +/*! + Creates a new separator action, which is an action that returns \c true from HbAction::isSeparator(), + and adds it to this menu's list of actions. + \return the new separator action + + \sa insertSeparator + */ +HbAction *HbMenu::addSeparator() +{ + return insertSeparator(0); +} + +/*! + Inserts a new separator action and inserts it into this menu's list of actions before \a action. + \param before is the action before which the separator is inserted. + \return the new action. + + \sa addSeparator + */ +HbAction *HbMenu::insertSeparator(HbAction *before) +{ + HbAction *action = new HbAction(this); + action->setSeparator(true); + action->setEnabled(false); + insertAction(before, action); + return action; +} + +/*! + \return the current active action, or 0 if no action item is currently active. + */ +HbAction *HbMenu::activeAction() const +{ + Q_D(const HbMenu); + return d->activeAction(); +} + +/*! + Sets the active action in menu. If \a action is not found from the list of + menu actions then the current active action remains active. + + \sa activeAction() +*/ +void HbMenu::setActiveAction(HbAction *action) +{ + Q_D(HbMenu); + if (d->menuItemView && action && action->isVisible() && !action->isSeparator()) { + d->menuItemView->setCurrentItem(action); + } +} + +/*! + \return \c true if the menu is empty (contains no actions) and \c false otherwise. + + \sa clear() + */ +bool HbMenu::isEmpty() const +{ + return actions().isEmpty(); +} + +/*! + Sets the menu title. For a sub-menu, the title is the sub-menu action text. + + \sa title() +*/ +void HbMenu::setTitle(const QString &title) +{ + menuAction()->setText(title); +} + +/*! + \return the menu title. For a sub-menu, the title is the sub-menu action text. + + \sa setTitle() +*/ +QString HbMenu::title() const +{ + return menuAction()->text(); +} + +/*! + \return the menu type. By default a menu is a context menu. +*/ +HbMenu::MenuType HbMenu::menuType() const +{ + Q_D(const HbMenu); + return d->menuType; +} + +/*! + \reimp + */ +QVariant HbMenu::itemChange( GraphicsItemChange change, const QVariant & value ) +{ + Q_D(HbMenu); + + if (change == QGraphicsItem::ItemVisibleChange) { + if (value.toBool() && d->delayMenuConstruction) { + d->delayedLayout(); + } + if (value.toBool()) { + d->resultAction = 0; + d->actionTriggered = false; + } + else if (!value.toBool() && !d->menuItemView){ + d->delayMenuConstruction = true; + } + } + return HbPopup::itemChange(change,value); +} + +/*! + \reimp + */ +void HbMenu::keyPressEvent(QKeyEvent *event) +{ + //TODO: check if non-touch version works with the key bindings below + Q_D(HbMenu); + switch( event->key() ) { + case Qt::Key_Up: + case Qt::Key_Down: + break; + case Qt::Key_Right: + layoutDirection() == Qt::LeftToRight + ? d->openSubmenu() + : d->closeSubmenu(); + break; + case Qt::Key_Left: + layoutDirection() == Qt::LeftToRight + ? d->closeSubmenu() + : d->openSubmenu(); + break; + case Qt::Key_Backspace: + d->closeSubmenu(); + break; + case Qt::Key_Escape: + close(); + break; + default: + HbPopup::keyPressEvent( event ); + break; + } +} + +/*! + \reimp + */ +void HbMenu::keyReleaseEvent(QKeyEvent *event) +{ + //TODO do we need this method? + QGraphicsWidget::keyReleaseEvent( event ); +} + +/*! + \reimp +*/ +bool HbMenu::event(QEvent *event) +{ + Q_D(HbMenu); + + if(!d->inDestruction) { + if (event->type() == QEvent::ActionAdded) { + QActionEvent *actionEvent = static_cast(event); + d->actionAdded(actionEvent); + return true; + } else if (event->type() == QEvent::ActionRemoved) { + QActionEvent *actionEvent = static_cast(event); + d->actionRemoved(actionEvent); + return true; + } else if (event->type() == QEvent::ActionChanged) { + QActionEvent *actionEvent = static_cast(event); + d->actionChanged(actionEvent); + return true; + } + } + if (event->type() == QEvent::LayoutRequest) { + resize(preferredSize()); + if(d->menuItemView) + d->menuItemView->contentWidget()->adjustSize(); + if (d->mSubMenuItem) + d->setSubMenuPosition(); + } + + return HbPopup::event(event); +} + +void HbMenu::polish(HbStyleParameters ¶ms) +{ + Q_D(HbMenu); + if (d->mSubMenuItem) { + const QString RightMargin = "submenu-right-offset"; + const QString DownMargin = "submenu-bottom-margin"; + params.addParameter(RightMargin); + params.addParameter(DownMargin); + + HbPopup::polish(params); + + if (!params.value(RightMargin).isNull()) { + d->mRightMargin = params.value(RightMargin).toDouble(); + } + if (!params.value(DownMargin).isNull()) { + d->mDownMargin = params.value(DownMargin).toDouble(); + } + d->setSubMenuPosition(); + } else { + HbPopup::polish(params); + } +} + +QPainterPath HbMenu::shape() const +{ + QRectF sceneRect = mapRectToScene(boundingRect()); + QRectF clipRect = sceneRect.intersected(geometry()); + QPainterPath path; + path.addRect(mapRectFromScene(clipRect)); + return path; +} + +/*! @alpha + * + * Opens the menu and returns immediately. + */ +void HbMenu::open( QObject *receiver, const char *member ) +{ + Q_D(HbMenu); + if ( d->receiverToDisconnectOnClose ) { // cant do on closeevent + disconnect(this, SIGNAL(triggered(HbAction*)), + d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose); + d->receiverToDisconnectOnClose = 0; + } + d->memberToDisconnectOnClose.clear(); + + if ( receiver ) { + connect(this, SIGNAL(triggered(HbAction*)), receiver, member); + d->receiverToDisconnectOnClose = receiver; + d->memberToDisconnectOnClose = member; + } else { + d->receiverToDisconnectOnClose = 0; + } + HbMenu::show(); +} + +#include "moc_hbmenu.cpp"