src/hbcore/gui/hbmenu.cpp
changeset 34 ed14f46c0e55
parent 6 c3690ec91ef8
equal deleted inserted replaced
31:7516d6d86cf5 34:ed14f46c0e55
    34 #include "hbeffect.h"
    34 #include "hbeffect.h"
    35 #include "hbeffectinternal_p.h"
    35 #include "hbeffectinternal_p.h"
    36 bool HbMenuPrivate::menuEffectsLoaded = false;
    36 bool HbMenuPrivate::menuEffectsLoaded = false;
    37 #endif
    37 #endif
    38 #include "hbglobal_p.h"
    38 #include "hbglobal_p.h"
    39 
    39 #include <QGraphicsSceneMouseEvent>
    40 #include <QPointer>
    40 #include <QPointer>
       
    41 #include <QGraphicsLinearLayout>
    41 
    42 
    42 Q_DECLARE_METATYPE (QAction*)// krazy:exclude=qclasses
    43 Q_DECLARE_METATYPE (QAction*)// krazy:exclude=qclasses
    43 
    44 
    44 HbMenuPrivate::HbMenuPrivate():
    45 HbMenuPrivate::HbMenuPrivate():
    45     HbPopupPrivate(),
    46     HbPopupPrivate(),
    51     mSubMenuItem(0),
    52     mSubMenuItem(0),
    52     mRightMargin(0.0),
    53     mRightMargin(0.0),
    53     mDownMargin(0.0),
    54     mDownMargin(0.0),
    54     delayMenuConstruction(true),
    55     delayMenuConstruction(true),
    55     receiverToDisconnectOnClose(0),
    56     receiverToDisconnectOnClose(0),
    56     mNumberOfColumns(1)
    57     mNumberOfColumns(1),
       
    58     mCloseAllMenus(false)
    57 {
    59 {
    58 }
    60 }
    59 
    61 
    60 HbMenuPrivate::~HbMenuPrivate()
    62 HbMenuPrivate::~HbMenuPrivate()
    61 {
    63 {
    73 }
    75 }
    74 
    76 
    75 void HbMenuPrivate::addPopupEffects()
    77 void HbMenuPrivate::addPopupEffects()
    76 {
    78 {
    77 #ifdef HB_EFFECTS
    79 #ifdef HB_EFFECTS
    78     effectType = "HB_MENU";
    80     if (menuType == HbMenu::OptionsMenu) {
       
    81         effectType = "HB_MENU";
       
    82     } else {
       
    83         effectType = "HB_SUBMENU";
       
    84     }
    79     hasEffects = menuEffectsLoaded;
    85     hasEffects = menuEffectsLoaded;
    80     if (menuEffectsLoaded)
    86     if (menuEffectsLoaded)
    81         return;
    87         return;
    82     menuEffectsLoaded = true;
    88     menuEffectsLoaded = true;
    83     hasEffects = HbEffectInternal::add("HB_MENU", "menu_appear", "appear");
    89     hasEffects = HbEffectInternal::add("HB_MENU", "menu_appear", "appear");
    84     if (hasEffects) {
    90     if (hasEffects) {
    85         //We load the disappear effect only if appear effect was also loaded
       
    86         hasEffects = HbEffectInternal::add("HB_MENU", "menu_disappear", "disappear");
    91         hasEffects = HbEffectInternal::add("HB_MENU", "menu_disappear", "disappear");
    87 
    92 
    88         if (hasEffects) {
    93         if (hasEffects) {
    89             hasEffects = HbEffectInternal::add("HB_menuitem", "menuitem_press", "clicked");
    94             hasEffects = HbEffectInternal::add("HB_menuitem", "menuitem_press", "clicked");
       
    95         }
       
    96         if (hasEffects) {
       
    97             hasEffects = HbEffectInternal::add("HB_SUBMENU", "submenu_appear", "appear");
       
    98         }
       
    99         if (hasEffects) {
       
   100             hasEffects = HbEffectInternal::add("HB_SUBMENU", "submenu_disappear", "disappear");
    90         }
   101         }
    91     }
   102     }
    92 #endif
   103 #endif
    93 }
   104 }
    94 
   105 
   101         if (hasEffects) {
   112         if (hasEffects) {
   102             HbEffect::start(currentItem, "HB_menuitem", "clicked");
   113             HbEffect::start(currentItem, "HB_menuitem", "clicked");
   103         }
   114         }
   104 #endif
   115 #endif
   105         HbAction *hbAction = qobject_cast<HbAction *>(currentItem->action());
   116         HbAction *hbAction = qobject_cast<HbAction *>(currentItem->action());
   106         q->setActiveAction(hbAction);
       
   107         if (hbAction && hbAction->menu() && !actionTriggered) {
   117         if (hbAction && hbAction->menu() && !actionTriggered) {
   108             hbAction->trigger();
   118             hbAction->trigger();
   109             stopTimeout();
   119             stopTimeout();
   110             openSubmenu(currentItem);
   120             openSubmenu(currentItem);
   111         } else {
   121         } else {
   120 
   130 
   121 void HbMenuPrivate::createMenuView()
   131 void HbMenuPrivate::createMenuView()
   122 {
   132 {
   123     Q_Q(HbMenu);
   133     Q_Q(HbMenu);
   124     if (!menuItemView && q->actions().count()){
   134     if (!menuItemView && q->actions().count()){
   125         menuItemView = new HbMenuListView(q, q);        
   135         menuItemView = new HbMenuListView(q, q);
       
   136 
   126         HbStyle::setItemName(menuItemView, "content");
   137         HbStyle::setItemName(menuItemView, "content");
   127         //This optimises case of options menu which otherwise updates its primitives twice.
   138         //This optimises case of options menu which otherwise updates its primitives twice.
   128         if (menuType ==  HbMenu::OptionsMenu)
   139         if (menuType ==  HbMenu::OptionsMenu)
   129             q->setFrameType(HbPopup::Strong);
   140             q->setFrameType(HbPopup::Strong);
   130     	else
   141         else
   131             q->setFrameType(HbPopup::Weak);
   142             q->setFrameType(HbPopup::Weak);
   132         if (polished)//This check can be removed once base class repolish is fixed.
   143         if (polished)//This check can be removed once base class repolish is fixed.
   133             q->repolish();
   144             q->repolish();
   134     }	
   145     }   
   135 }
   146 }
   136 
   147 
   137 void HbMenuPrivate::delayedLayout()
   148 void HbMenuPrivate::delayedLayout()
   138 {
   149 {
   139     createMenuView();
   150     if (delayMenuConstruction) {
   140     if(menuItemView)
   151         createMenuView();
   141         menuItemView->doDelayedLayout();
   152         if(menuItemView) {
   142     delayMenuConstruction = false;
   153             menuItemView->doDelayedLayout();
       
   154         }
       
   155         addPopupEffects();
       
   156         delayMenuConstruction = false;
       
   157     }
   143 }
   158 }
   144 
   159 
   145 void HbMenuPrivate::changeToOptionsMenu()
   160 void HbMenuPrivate::changeToOptionsMenu()
   146 {
   161 {
   147     menuType = HbMenu::OptionsMenu;
   162     menuType = HbMenu::OptionsMenu;
       
   163     effectType = "HB_MENU";
   148 }
   164 }
   149 
   165 
   150 HbMenuItem *HbMenuPrivate::subMenuItem()
   166 HbMenuItem *HbMenuPrivate::subMenuItem()
   151 {
   167 {
   152     return mSubMenuItem;
   168     return mSubMenuItem;
   158 }
   174 }
   159 
   175 
   160 void HbMenuPrivate::_q_onActionTriggered()
   176 void HbMenuPrivate::_q_onActionTriggered()
   161 {
   177 {
   162     Q_Q(HbMenu);
   178     Q_Q(HbMenu);
   163        HbAction *action = qobject_cast<HbAction *>(q->sender());
   179     HbAction *action = qobject_cast<HbAction *>(q->sender());
   164     if (action && !action->menu() ) { // do not trigger from opening submenu
   180     if (action) {
   165         emit q->triggered(action);
   181         q->setActiveAction(action);
       
   182         if (!action->menu()) { // do not trigger from opening submenu
       
   183             emit q->triggered(action);
       
   184         }
   166     }
   185     }
   167 }
   186 }
   168 
   187 
   169 void HbMenuPrivate::_q_subMenuItemTriggered(HbAction *action)
   188 void HbMenuPrivate::_q_subMenuItemTriggered(HbAction *action)
   170 {
   189 {
   171     Q_Q(HbMenu);    
   190     Q_Q(HbMenu);    
   172  
   191  
   173     // do not close the menu tree if the triggered action is
   192     // do not close the menu tree if the triggered action is
   174     // submenu item
   193     // submenu item
   175     if (!action->menu()) { 
   194     if (!action->menu()) { 
       
   195         mCloseAllMenus = true;
   176         q->close();
   196         q->close();
   177     } else {
   197     } else {
   178         stopTimeout();
   198         stopTimeout();
   179     }
   199     }
   180 }
   200 }
   208     if (menuItemView)
   228     if (menuItemView)
   209         menuItemView->updateActionItem(actionEvent->action());
   229         menuItemView->updateActionItem(actionEvent->action());
   210 }
   230 }
   211 
   231 
   212 /*
   232 /*
   213    Returns current focusable action based on current row of the menuItemView or index if specified.
   233     Returns current focusable action based on current row of the menuItemView or index if specified.
   214    If there is no focusable action it returns 0.
   234     If there is no focusable action it returns 0.
   215    Also returns the active item representing the active action or 0.
   235     Also returns the active item representing the active action or 0.
   216 */
   236 */
   217 HbAction *HbMenuPrivate::activeAction(HbMenuItem *&activeItem) const
   237 HbAction *HbMenuPrivate::activeAction(HbMenuItem *&activeItem) const
   218 {
   238 {
   219     if(!menuItemView)
   239     if(!menuItemView)
   220         return 0;
   240         return 0;
   227     }
   247     }
   228     return action;
   248     return action;
   229 }
   249 }
   230 
   250 
   231 /*
   251 /*
   232   Convenience overload
   252     Convenience overload
   233 */
   253 */
   234 HbAction *HbMenuPrivate::activeAction() const
   254 HbAction *HbMenuPrivate::activeAction() const
   235 {
   255 {
   236     HbMenuItem* activeItem = 0;
   256     HbMenuItem* activeItem = 0;
   237     return activeAction(activeItem);
   257     return activeAction(activeItem);
   238 }
   258 }
   239 
   259 
   240 /*
   260 /*
   241   Opens a submenu for activeItem. If activeItem is 0 it uses activeAction() to determine active item
   261     Opens a submenu for activeItem. If activeItem is 0 it uses activeAction() to determine active item
   242   and opens submenu for it if active action has submenu.
   262     and opens submenu for it if active action has submenu.
   243 */
   263 */
   244 void HbMenuPrivate::openSubmenu(HbMenuItem *activeItem)
   264 void HbMenuPrivate::openSubmenu(HbMenuItem *activeItem)
   245 {
   265 {
   246     Q_Q(HbMenu);
   266     Q_Q(HbMenu);
   247 
   267 
   267             // huh ? activeSubMenu = 0;
   287             // huh ? activeSubMenu = 0;
   268         }
   288         }
   269     }
   289     }
   270 }
   290 }
   271 
   291 
       
   292 /*
       
   293     reimp
       
   294 */
       
   295 void HbMenuPrivate::handleBackgroundMouseReleaseEvent(QGraphicsSceneMouseEvent *event)
       
   296 {
       
   297     Q_Q(HbMenu);
       
   298 
       
   299     // Handle cases only for Background or Popup originated mouse presses and when
       
   300     // any dismiss policy defined
       
   301     if (mousePressLocation != None && dismissPolicy != HbPopup::NoDismiss) {
       
   302 
       
   303         MouseEventLocationType mouseReleaseLocation = Background;
       
   304         HbMenu* tempMenu = 0;
       
   305         QList<QGraphicsItem*> itemList = q->scene()->items(event->pos());
       
   306         foreach (QGraphicsItem* sceneItem, itemList ){
       
   307             QGraphicsWidget *focusWidget = 0;
       
   308             HbMenu *focusMenu = 0;
       
   309             if (sceneItem && sceneItem->isWidget()) {
       
   310                 focusWidget = static_cast<QGraphicsWidget*>(sceneItem);
       
   311                 focusMenu = qobject_cast<HbMenu *>(focusWidget);
       
   312             }
       
   313             if( focusMenu ) {
       
   314                 mouseReleaseLocation = Popup;
       
   315                 tempMenu = focusMenu;
       
   316                 break;
       
   317             }
       
   318         }
       
   319         // Mouse is released within menu
       
   320         if (mouseReleaseLocation == Popup) {
       
   321             HbAction* menuAction = tempMenu->activeAction();
       
   322             if(menuAction){
       
   323                 mCloseAllMenus = false;
       
   324                 closeMenuRecursively(menuAction);
       
   325             }
       
   326         mousePressLocation = None;
       
   327         }
       
   328         else {
       
   329             // trigger the menu to close whole menu
       
   330             mCloseAllMenus = true;
       
   331             q->close();
       
   332             mousePressLocation = None;
       
   333         }
       
   334     }
       
   335 }
       
   336 
   272 void HbMenuPrivate::_q_subMenuTimedOut()
   337 void HbMenuPrivate::_q_subMenuTimedOut()
   273 {
   338 {
   274     Q_Q(HbMenu);
   339     Q_Q(HbMenu);
   275     if( menuTimedOut (activeSubMenu) ) {
   340     if( menuTimedOut (activeSubMenu) ) {
   276         if ( activeSubMenu ) {
   341         if ( activeSubMenu ) {
   278         }
   343         }
   279         timedOut = true;
   344         timedOut = true;
   280         q->close();
   345         q->close();
   281     } else {
   346     } else {
   282         startTimeout();
   347         startTimeout();
   283     }
   348         mCloseAllMenus = false;
       
   349     }
       
   350     if (activeSubMenu && HbMenuPrivate::d_ptr(activeSubMenu)->mCloseAllMenus) {
       
   351         mCloseAllMenus = true;
       
   352         q->close();
       
   353    }
   284 }
   354 }
   285 
   355 
   286 void HbMenuPrivate::_q_handleMenuClose()
   356 void HbMenuPrivate::_q_handleMenuClose()
   287 {
   357 {
   288     Q_Q(HbMenu);
   358     Q_Q(HbMenu);
   296         }
   366         }
   297         q->close();
   367         q->close();
   298     }
   368     }
   299 }
   369 }
   300 
   370 
   301 /*!
   371 /*
   302  Handles menu close
   372     Handles menu close
   303 */
   373 */
   304 void HbMenuPrivate::closeMenu()
   374 void HbMenuPrivate::closeMenu()
   305 {
   375 {
   306     Q_Q(HbMenu);
   376     Q_Q(HbMenu);
   307     HbMainWindow* w(q->mainWindow());
   377     HbMainWindow* w(q->mainWindow());
   359             if ((windowSize.width() - q->size().width()) < leftEdge) {
   429             if ((windowSize.width() - q->size().width()) < leftEdge) {
   360                 leftEdge = mSubMenuItem->scenePos().x() +
   430                 leftEdge = mSubMenuItem->scenePos().x() +
   361                            mSubMenuItem->size().width() +
   431                            mSubMenuItem->size().width() +
   362                            mRightMargin - q->size().width();
   432                            mRightMargin - q->size().width();
   363             }
   433             }
   364             q->setPreferredPos(QPointF(leftEdge, upperEdge));
   434             q->setPreferredPos(QPointF(leftEdge, upperEdge), HbPopup::TopLeftCorner);
   365         } else {
   435         } else {
   366             qreal rightEdge = mSubMenuItem->scenePos().x() + mRightMargin;
   436             qreal rightEdge = mSubMenuItem->scenePos().x() + mRightMargin;
   367             if ((rightEdge - q->size().width()) < 0) {
   437             if ((rightEdge - q->size().width()) < 0) {
   368                 rightEdge = mSubMenuItem->scenePos().x() - mRightMargin +
   438                 rightEdge = mSubMenuItem->scenePos().x() - mRightMargin +
   369                             q->size().width();
   439                             q->size().width();
   375 
   445 
   376 /*!
   446 /*!
   377     @beta
   447     @beta
   378     @hbcore
   448     @hbcore
   379     \class HbMenu
   449     \class HbMenu
   380     \brief HbMenu is a menu widget for use in HbView.
   450     \brief The HbMenu class provides a widget that shows a list of options.
   381 
   451 
   382     \image html hbmenu.png A menu with checkable items and a sub-menu.
   452     A menu consists of a list of options that the user can select. When the user selects
   383 
   453     an option, it triggers a command. Menus are hidden by default and open in response
   384     Use an HbMenu to show a list of options. There are two main types of menus:
   454     to an action from the user. For this reason, the toolbar (HbToolBar class) usually
   385 
   455     provides access to the most important commands (called first order commands) and
   386     - The view options menu
   456     menus provide access to second order commands.
   387     - Context menus (popup menus)
   457 
   388 
   458     \image html hbmenu.png An options menu with a submenu that has checkable actions
   389     There is one view options menu for each view.
   459 
   390     It is shown by tapping the title bar. You can access the view options menu by calling
   460     You can use the %HbMenu class to create the following:
   391     HbView::menu() which returns a pointer to a new empty menu if one does not already exist.
   461 
   392 
   462     - An \b options \b menu, which shows options that relate to the whole view. It is
   393     You can create any number of context menus.
   463     a drop-down menu that is directly owned by the view (HbView object). It opens when the
   394     Context menus are usually invoked by a user action, such as tapping a widget.
   464     user taps on the view's title bar. You can access a view's options menu by calling
   395 
   465     HbView::menu(). This returns a pointer to a new empty menu if the menu does not
   396     A menu contains a list of items. You can add three kinds of items to a menu:
   466     already exist. A view can have only one options menu.
   397 
   467 
   398     - Actions
   468     - A \b context \b menu, which is a pop-up menu that shows options that relate to a
   399     - Sub-menus
   469     specific item, rather than to the entire view. It typically opens in response to a
   400     - Separators
   470     UI event, such as a tap on a widget or a particular point within the view. You can
   401 
   471     create any number of context menus.
   402     An action is an object of class HbAction that performs an action when it is triggered.
   472 
   403     Use addAction() to add an action to a menu. Actions can be checkable (QAction::setCheckable).
   473     A menu is a list of actions, which are objects of class HbAction. A menu can contain:
   404     Use clearActions() to clear all actions from a menu.
   474 
   405     Use removeAction() to remove individual actions from a menu.
   475     - \b Separators, which are actions that group related items. Use addSeparator() or
   406 
   476     insertSeparator() to create a separator and add it to a menu.
   407     A sub-menu is a menu that is nested within another menu. Use addMenu() or insertMenu() to add a sub-menu to a menu.
   477 
   408     Sub-menus can be nested within sub-menus.
   478     - Actions that trigger a \b submenu to open. Submenus are menus that are nested within
   409 
   479     another menu. Use addMenu() or insertMenu() to add a submenu to a menu. Although it is
   410     Separators group related items in a menu.
   480     possible to nest submenus within other submenus, generally this is not considered good
   411     Use addSeparator() or insertSeparator() to create and add a separator to a menu.
   481     design practice.
   412 
   482 
   413     \image html hbmenu.png A menu with checkable actions and a sub-menu.
   483     - \b Action \b items, which represent the menu options. Use addAction() and insertAction() to
   414 
   484     add an action to a menu. Use addActions() and insertActions() to add and insert multiple
   415     After you add an action to your menu, you specify a receiver object and its slot (you can also
   485     actions in one operation. Use clearActions() to clear all of the actions from a menu and
   416     add an action and specify a receiver slot at the same time).
   486     removeAction() to remove individual actions from a menu.
   417     The receiver is notifed when the action is triggered (QAction::triggered()).
   487 
   418     HbMenu also has a triggered() menu signal, which signals which HbAction was triggered in the menu.
   488     The order of the actions within the menu controls the order of the options that the user sees.
   419 
   489     When you add the actions directly to the menu, addAction() and addActions() append the actions
   420     An example of how to create an option menu.
   490     to the end of the menu and insertAction() and insertActions() enable you to specify the position.
       
   491     For options menus, however, there is an alternative approach to ordering the action items.
       
   492     This is to call HbView::addAction() to add actions to the \b view and let the view distribute
       
   493     them to the options menu or toolbar, depending on the preference set, the UI command distribution
       
   494     template, and taking into account the available space in the toolbar. The menu and toolbar
       
   495     then order the actions according to their defined roles and the UI command container template.
       
   496     This approach makes it easier to create consistent user interfaces and applications that
       
   497     work well on a variety of different devices.
       
   498 
       
   499     An action item can be checkable, which means that it has an on/off state. You specify that an
       
   500     action item is checkable by calling \c setCheckable() on the action. Use \c isChecked()
       
   501     to discover if an action is checked. You can also use the QAction::toggled(bool) signal to
       
   502     receive notification of a change in the checked status.
       
   503 
       
   504     After you add an action item to a menu, you can connect its \link HbAction::triggered()
       
   505     triggered()\endlink signal to a slot on a receiver object. Alternatively you can use the
       
   506     addAction(const QString &, const QObject *, const char *) overload to add an action item and
       
   507     specify a receiver slot at the same time. The receiver is notified when the action item
       
   508     is \link HbAction::triggered() triggered()\endlink.
       
   509 
       
   510     You can also connect the HbMenu::triggered(HbAction*) signal to a receiver object's slot. This
       
   511     signal is emitted when any menu action is triggered. You can find out which action was
       
   512     triggered from the HbAction parameter.
       
   513 
       
   514     \section _usecases_hbmenu Using the HbMenu class
       
   515 
       
   516     \subsection _uc_001_hbmenu Creating an options menu
       
   517 
       
   518     The following example creates an options menu for a view.
   421     \snippet{ultimatecodesnippet/ultimatecodesnippet.cpp,2}
   519     \snippet{ultimatecodesnippet/ultimatecodesnippet.cpp,2}
   422 
   520 
   423     An example of how to create and show a context menu from the gesture.
   521     \subsection _uc_002_hbmenu Creating a context menu
       
   522 
       
   523     The following example creates a context menu and shows it in response to a tap and hold gesture.
   424     \snippet{ultimatecodesnippet/ultimatecodesnippet.cpp,54}
   524     \snippet{ultimatecodesnippet/ultimatecodesnippet.cpp,54}
   425 
   525 
   426     \sa HbDialog, HbView
   526     \subsection _uc_004_hbmenu Adding actions to the view
       
   527 
       
   528     The following example creates two action items, specifies their command roles, and then
       
   529     adds them to the view. The view places them in the menu or toolbar according to the
       
   530     priorities of the actions and the space available in the toolbar and the menu orders them
       
   531     according to their roles and priorities.
       
   532 
       
   533     \code
       
   534     HbAction* actionExit = new HbAction(tr("Exit"));
       
   535     actionExit->setCommandRole(HbAction::ExitRole);
       
   536 
       
   537     HbAction* actionHelp = new HbAction(tr("Help"));
       
   538     actionHelp->setCommandRole(HbAction::HelpRole);
       
   539 
       
   540     // Add actions to the view.
       
   541     myView->addAction(actionExit);
       
   542     myView->addAction(actionHelp);
       
   543     \endcode
       
   544 
       
   545     \subsection _uc_003_hbmenu Creating action items that are checkable
       
   546 
       
   547     You can create a menu that contains multiple checkable actions (actions with checkbox behavior).
       
   548     For simple checkbox behavior, just set the actions to be checkable by calling \c setCheckable(true).
       
   549     For example:
       
   550 
       
   551     \code
       
   552     ...
       
   553     checkAction1->setCheckable(true);
       
   554     checkAction2->setCheckable(true);
       
   555     checkAction3->setCheckable(true);
       
   556     ...
       
   557     \endcode
       
   558 
       
   559     \subsection _uc_005_hbmenu Creating radio button style options
       
   560 
       
   561     To create a group of related actions, only one of which can be checked (radio button behavior),
       
   562     create a QActionGroup object and add the actions to that. For example:
       
   563 
       
   564     \code
       
   565     HbAction *redAction = menu->addAction(tr("Red"));
       
   566     HbAction *blueAction = menu->addAction(tr("Blue"));
       
   567 
       
   568     redAction->setCheckable(true);
       
   569     blueAction->setCheckable(true);
       
   570 
       
   571     QActionGroup *actionGroup = new QActionGroup(view);
       
   572     actionGroup->addAction(redAction);
       
   573     actionGroup->addAction(blueAction);
       
   574     \endcode
       
   575 
       
   576     \sa HbView, HbToolBar, HbAction
   427 */
   577 */
   428 
   578 
   429 /*!
   579 /*!
   430     \property HbMenu::menuType
   580     \property HbMenu::menuType
   431     \brief
   581     \brief
   432 */
   582 */
   433 
   583 
   434 /*!
   584 /*!
   435     \fn void HbMenu::triggered(HbAction *action)
   585     \fn void HbMenu::triggered(HbAction *action)
   436 
   586 
   437     This signal is emitted when one of the action items is selected.
   587     This signal is emitted when one of the menu options is selected.
   438     \param action the action that was triggered in the menu.
   588     \param action The action that was selected.
   439  */
   589 */
   440 
   590 
   441 /*!
   591 /*!
   442     \enum HbMenu::MenuType
   592     \enum HbMenu::MenuType
   443 
   593 
   444     This enum describes different types of HbMenu.
   594     The MenuType enum identifies the possible HbMenu types.
   445 */
   595 */
   446 /*!
   596 /*!
   447     \var HbMenu::ContextMenu
   597     \var HbMenu::ContextMenu
   448 
   598     A popup menu.
   449     ContextMenu is a menu which position is set by user.
   599 */
   450 */
   600 /*!
   451 /*!
   601     \var HbMenu::OptionsMenu
   452     \var HbMenu::OptionMenu
   602     The main options menu in a view. Its position cannot be changed.
   453 
       
   454     OptionMenu is set by HbView. Its position cannot be changed.
       
   455 */
   603 */
   456 /*!
   604 /*!
   457     \var HbMenu::SubMenu
   605     \var HbMenu::SubMenu
   458 
   606     A submenu, which is a menu that has been added to another menu.
   459     Menu becomes SubMenu when it is added to another menu.
       
   460 */
   607 */
   461 
   608 
   462 /*!
   609 /*!
   463     Constructs a menu with \a parent graphics item.
   610     Constructs a menu with \a parent graphics item.
   464 
       
   465     \param parent is the parent graphics item.
       
   466 */
   611 */
   467 HbMenu::HbMenu(QGraphicsItem *parent) :
   612 HbMenu::HbMenu(QGraphicsItem *parent) :
   468         HbPopup(*new HbMenuPrivate, parent)
   613         HbPopup(*new HbMenuPrivate, parent)
   469 {
   614 {
   470     Q_D(HbMenu);
   615     Q_D(HbMenu);
   473     setModal(true);
   618     setModal(true);
   474 }
   619 }
   475 
   620 
   476 /*!
   621 /*!
   477     Constructs a menu with \a title and \a parent graphics item.
   622     Constructs a menu with \a title and \a parent graphics item.
   478     \param title is the menu title.
       
   479     \param parent is the parent graphics item.
       
   480 */
   623 */
   481 HbMenu::HbMenu(const QString &title, QGraphicsItem *parent) :
   624 HbMenu::HbMenu(const QString &title, QGraphicsItem *parent) :
   482         HbPopup(*new HbMenuPrivate, parent)
   625         HbPopup(*new HbMenuPrivate, parent)
   483 {
   626 {
   484     Q_D(HbMenu);
   627     Q_D(HbMenu);
   496     Q_D(HbMenu);
   639     Q_D(HbMenu);
   497     d->q_ptr = this;
   640     d->q_ptr = this;
   498     d->init();
   641     d->init();
   499 }
   642 }
   500 
   643 
       
   644 /*!
       
   645     Destructor
       
   646 */
   501 HbMenu::~HbMenu()
   647 HbMenu::~HbMenu()
   502 {
   648 {
   503     if (!scene() || !scene()->property("destructed").isValid()) {
   649     if (!scene() || !scene()->property("destructed").isValid()) {
   504         foreach (QAction *action, actions()) {// krazy:exclude=qclasses
   650         foreach (QAction *action, actions()) {// krazy:exclude=qclasses
   505             HbAction* hbAction = qobject_cast<HbAction *>(action);
   651             HbAction* hbAction = qobject_cast<HbAction *>(action);
   525 
   671 
   526     HbPopup::showEvent(event);
   672     HbPopup::showEvent(event);
   527 }
   673 }
   528 
   674 
   529 /*!
   675 /*!
   530     Creates a new action with title \a text. It adds the newly created action to the menu's list of actions.
   676     Creates a new action and adds it to the end of the menu.
   531     \param text is the text for the new action.
   677 
   532     \return the new action.
   678     \overload
       
   679 
       
   680     \param text The menu text for the new action.
       
   681     \return The new action.
   533 */
   682 */
   534 HbAction *HbMenu::addAction(const QString &text)
   683 HbAction *HbMenu::addAction(const QString &text)
   535 {
   684 {
   536     HbAction *action = new HbAction(text, this);
   685     HbAction *action = new HbAction(text, this);
   537     addAction(action);
   686     addAction(action);
   538     return action;
   687     return action;
   539 }
   688 }
   540 
   689 
   541 /*!
   690 /*!
   542     Creates a new action with \a text.
   691     Creates a new action, adds it to the end of the menu and connects the action's
   543     The action's triggered() signal is connected to the
   692     \link HbAction::triggered() triggered()\endlink signal to a receiver's slot.
   544     \a receiver's \a member slot. The function adds the newly created
   693 
   545     action to the menu's list of actions.
   694     \overload
   546     \return the new action.
   695 
   547  */
   696     \param text The menu text for the new action.
       
   697     \param receiver The object that is to receive the new action's signal.
       
   698     \param member The slot on the receiver to which the action's signal is to connect.
       
   699     \return The new action.
       
   700 */
   548 HbAction *HbMenu::addAction(const QString &text, const QObject *receiver, const char *member)
   701 HbAction *HbMenu::addAction(const QString &text, const QObject *receiver, const char *member)
   549 {
   702 {
   550     HbAction *action = new HbAction(text, this);
   703     HbAction *action = new HbAction(text, this);
   551     connect(action, SIGNAL(triggered(bool)), receiver, member);
   704     connect(action, SIGNAL(triggered(bool)), receiver, member);
   552     addAction(action);
   705     addAction(action);
   553     return action;
   706     return action;
   554 }
   707 }
   555 
   708 
   556 /*!
   709 /*!
   557     Adds \a menu as a sub-menu.
   710     Adds \a menu to the current menu as a submenu.
   558     \param menu is the menu that is added to this one.
   711 
   559     \return the action for the added sub-menu.
   712     \return  The action for the added submenu.
   560  */
   713 */
   561 HbAction *HbMenu::addMenu(HbMenu *menu)
   714 HbAction *HbMenu::addMenu(HbMenu *menu)
   562 {
   715 {
   563     return insertMenu(0, menu);
   716     return insertMenu(0, menu);
   564 }
   717 }
   565 
   718 
   566 /*!
   719 /*!
   567     Creates a new HbMenu with \a title and adds it to this menu.
   720     Creates a new HbMenu with \a title and adds it to the current menu as a submenu.
   568     \param title is the menu title.
   721 
   569     \return the new menu.
   722     \return The new menu.
   570 */
   723 */
   571 HbMenu *HbMenu::addMenu(const QString &title)
   724 HbMenu *HbMenu::addMenu(const QString &title)
   572 {
   725 {
   573     HbMenu *menu = new HbMenu(title);
   726     HbMenu *menu = new HbMenu(title);
   574     addMenu(menu);
   727     if ( menu ) {
       
   728         menu->setParent(this);
       
   729         addMenu(menu);
       
   730     }
   575     return menu;
   731     return menu;
   576 }
   732 }
   577 
   733 
   578 /*!
   734 /*!
   579     Inserts \a menu before action \a before.
   735     Inserts \a menu into the current menu as a submenu before the \a before action.
   580     \param before is the action before which this new menu is inserted.
   736 
   581     \param menu is the menu that is inserted.
       
   582     \return the action associated with the inserted menu.
   737     \return the action associated with the inserted menu.
   583  */
   738 */
   584 HbAction *HbMenu::insertMenu(HbAction *before, HbMenu *menu)
   739 HbAction *HbMenu::insertMenu(HbAction *before, HbMenu *menu)
   585 {    
   740 {    
   586     QObject::connect(menu, SIGNAL(triggered(HbAction*)), this, SLOT(_q_subMenuItemTriggered(HbAction*)));
   741     QObject::connect(menu, SIGNAL(triggered(HbAction*)), this, SLOT(_q_subMenuItemTriggered(HbAction*)));
   587     QObject::connect(menu, SIGNAL(triggered(HbAction*)), this, SIGNAL(triggered(HbAction*)));
   742     QObject::connect(menu, SIGNAL(triggered(HbAction*)), this, SIGNAL(triggered(HbAction*)));
   588 
   743 
   590     insertAction(before, menu->menuAction());
   745     insertAction(before, menu->menuAction());
   591     return menu->menuAction();
   746     return menu->menuAction();
   592 }
   747 }
   593 
   748 
   594 /*!
   749 /*!
   595     \return the action associated with this menu.
   750     Returns the action that is directly associated with a menu (rather than actions that are contained
   596  */
   751     within the menu). Although all menus have an assoicated action, it is only actually used for submenus.
       
   752     The parent menu uses a submenu's action to trigger the opening of the submenu. A submenu's action
       
   753     also defines the submenu's title.
       
   754 */
   597 HbAction *HbMenu::menuAction() const
   755 HbAction *HbMenu::menuAction() const
   598 {
   756 {
   599     Q_D(const HbMenu);
   757     Q_D(const HbMenu);
   600     return d->subMenuAction;
   758     return d->subMenuAction;
   601 }
   759 }
   602 
   760 
   603 /*!
   761 /*!
   604     Creates a new separator action, which is an action that returns \c true from HbAction::isSeparator(),
   762     Creates a new separator and adds it to the current menu's list of actions. A separator
   605     and adds it to this menu's list of actions.
   763     is an action for which HbAction::isSeparator() returns \c true.
   606     \return the new separator action
   764 
   607 
   765     \return The new separator action.
   608     \sa insertSeparator
   766 
   609  */
   767     \sa insertSeparator()
       
   768 */
   610 HbAction *HbMenu::addSeparator()
   769 HbAction *HbMenu::addSeparator()
   611 {
   770 {
   612     //functionality removed for now
   771         //functionality removed for now
   613     //return insertSeparator(0);
   772     //return insertSeparator(0);
   614     return 0;
   773     return 0;
   615 }
   774 }
   616 
   775 
   617 /*!
   776 /*!
   618     Inserts a new separator action and inserts it into this menu's list of actions before \a action.
   777     Creates a new separator and inserts it into the current menu's list of actions before \a before.
   619     \param before is the action before which the separator is inserted.
   778     A separator is an action for which HbAction::isSeparator() returns \c true.
   620     \return the new action.
   779 
   621 
   780     \return The new separator action.
   622     \sa addSeparator
   781     \sa addSeparator()
   623  */
   782 */
   624 HbAction *HbMenu::insertSeparator(HbAction *before)
   783 HbAction *HbMenu::insertSeparator(HbAction *before)
   625 {
   784 {
   626     Q_UNUSED(before);
   785     Q_UNUSED(before);
   627     //functionality removed for now
   786     //functionality removed for now
   628     /*HbAction *action = new HbAction(this);
   787     /*HbAction *action = new HbAction(this);
   633     return action;*/
   792     return action;*/
   634     return 0;
   793     return 0;
   635 }
   794 }
   636 
   795 
   637 /*!
   796 /*!
   638     \return the current active action, or 0 if no action item is currently active.
   797     Returns the active action or 0 if no action item is currently active. The active action is
   639  */
   798     the last action that was triggered, unless this has been overridden by a call to setActiveAction().
       
   799 */
   640 HbAction *HbMenu::activeAction() const
   800 HbAction *HbMenu::activeAction() const
   641 {
   801 {
   642     Q_D(const HbMenu);
   802     Q_D(const HbMenu);
   643     return d->activeAction();
   803     return d->activeAction();
   644 }
   804 }
   645 
   805 
   646 /*!
   806 /*!
   647     Sets the active action in menu. If \a action is not found from the list of
   807     Sets \a action as the current active action in the menu. If \a action is not
   648     menu actions then the current active action remains active.
   808     found in the list of menu actions, the action that is currently active remains active.
   649 
   809 
   650     \sa activeAction()
   810     \sa activeAction()
   651 */
   811 */
   652 void HbMenu::setActiveAction(HbAction *action)
   812 void HbMenu::setActiveAction(HbAction *action)
   653 {
   813 {
   656         d->menuItemView->setCurrentItem(action);
   816         d->menuItemView->setCurrentItem(action);
   657     }
   817     }
   658 }
   818 }
   659 
   819 
   660 /*!
   820 /*!
   661     \return \c true if the menu is empty (contains no actions) and \c false otherwise.
   821     Returns \c true if the menu contains no actions and \c false otherwise.
   662 
   822 
   663     \sa clear()
   823     \sa clearActions()
   664  */
   824 */
   665 bool HbMenu::isEmpty() const
   825 bool HbMenu::isEmpty() const
   666 {
   826 {
   667     return actions().isEmpty();
   827     return actions().isEmpty();
   668 }
   828 }
   669 
   829 
   670 /*!
   830 /*!
   671     Sets the menu title. For a sub-menu, the title is the sub-menu action text.
   831     Sets the menu title. For a submenu, the title is the submenu's action text.
   672 
   832 
   673     \sa title()
   833     \sa title()
   674 */
   834 */
   675 void HbMenu::setTitle(const QString &title)
   835 void HbMenu::setTitle(const QString &title)
   676 {
   836 {
   677     menuAction()->setText(title);
   837     menuAction()->setText(title);
   678 }
   838 }
   679 
   839 
   680 /*!
   840 /*!
   681     Returns the menu title. For a sub-menu, the title is the sub-menu action text.
   841     Returns the menu title. For a submenu, the title is the submenu's action text.
   682 
       
   683     \return the menu title.
       
   684 
   842 
   685     \sa setTitle()
   843     \sa setTitle()
   686 */
   844 */
   687 QString HbMenu::title() const
   845 QString HbMenu::title() const
   688 {
   846 {
   689     return menuAction()->text();
   847     return menuAction()->text();
   690 }
   848 }
   691 
   849 
   692 /*!
   850 /*!
   693     Returns the menu type. By default a menu is a context menu.
   851     Returns the menu type. The default menu type is context menu.
   694 
   852 
   695     \return the menu type.
       
   696 */
   853 */
   697 HbMenu::MenuType HbMenu::menuType() const
   854 HbMenu::MenuType HbMenu::menuType() const
   698 {
   855 {
   699     Q_D(const HbMenu);
   856     Q_D(const HbMenu);
   700     return d->menuType;
   857     return d->menuType;
   701 }
   858 }
   702 
   859 
   703 /*!
       
   704     \reimp
       
   705  */
       
   706 QVariant HbMenu::itemChange( GraphicsItemChange change, const QVariant & value )
   860 QVariant HbMenu::itemChange( GraphicsItemChange change, const QVariant & value )
   707 {
   861 {
   708     Q_D(HbMenu);
   862     Q_D(HbMenu);
   709 
   863 
   710     if (change == QGraphicsItem::ItemSceneHasChanged) {
   864     if (change == QGraphicsItem::ItemSceneHasChanged) {
   711         d->closeMenu();
   865         d->closeMenu();
   712     }
   866     }
   713     if (change == QGraphicsItem::ItemVisibleChange) {
   867     if (change == QGraphicsItem::ItemVisibleChange) {
   714         if (value.toBool() && d->delayMenuConstruction) {
   868         if (value.toBool() && d->polished) {
   715             d->delayedLayout();
   869             d->delayedLayout();
   716         }
   870         }
   717         if (value.toBool()) {
   871         if (value.toBool()) {
   718             d->actionTriggered = false;
   872             d->actionTriggered = false;
   719         }
   873         }
   722         }
   876         }
   723     }
   877     }
   724     return HbPopup::itemChange(change,value);
   878     return HbPopup::itemChange(change,value);
   725 }
   879 }
   726 
   880 
   727 /*!
       
   728    \reimp
       
   729 */
       
   730 bool HbMenu::event(QEvent *event)
   881 bool HbMenu::event(QEvent *event)
   731 {
   882 {
   732     Q_D(HbMenu);
   883     Q_D(HbMenu);
   733 
   884 
   734     if(!d->inDestruction) {
   885     if(!d->inDestruction) {
   752     }
   903     }
   753 
   904 
   754     return HbPopup::event(event);
   905     return HbPopup::event(event);
   755 }
   906 }
   756 
   907 
   757 /*!
       
   758   \reimp
       
   759   */
       
   760 void HbMenu::polish(HbStyleParameters &params)
   908 void HbMenu::polish(HbStyleParameters &params)
   761 {
   909 {
   762     Q_D(HbMenu);
   910     if (isVisible()) {
   763     const QString NumberOfCols = "number-of-columns";
   911         Q_D(HbMenu);
   764     params.addParameter(NumberOfCols);
   912         const QLatin1String NumberOfCols("number-of-columns");
   765 
   913         params.addParameter(NumberOfCols);
   766     if (d->mSubMenuItem) {
   914 
   767         const QString RightMargin = "submenu-right-offset";
   915         if (d->mSubMenuItem) {
   768         const QString DownMargin = "submenu-bottom-margin";
   916             const QLatin1String RightMargin("submenu-right-offset");
   769         params.addParameter(RightMargin);
   917             const QLatin1String DownMargin("submenu-bottom-margin");
   770         params.addParameter(DownMargin);
   918             params.addParameter(RightMargin);
   771 
   919             params.addParameter(DownMargin);
   772         HbPopup::polish(params);
   920 
   773 
   921             HbPopup::polish(params);
   774         if (!params.value(RightMargin).isNull()) {
   922 
   775             d->mRightMargin = params.value(RightMargin).toDouble();
   923             if (!params.value(RightMargin).isNull()) {
   776         }
   924                 d->mRightMargin = params.value(RightMargin).toDouble();
   777         if (!params.value(DownMargin).isNull()) {
   925             }
   778             d->mDownMargin = params.value(DownMargin).toDouble();
   926             if (!params.value(DownMargin).isNull()) {
   779         }
   927                 d->mDownMargin = params.value(DownMargin).toDouble();
   780         d->setSubMenuPosition();
   928             }
       
   929             d->setSubMenuPosition();
       
   930         } else {
       
   931             HbPopup::polish(params);
       
   932         }
       
   933 
       
   934         if (!params.value(NumberOfCols).isNull()) {
       
   935             int cols = params.value(NumberOfCols).toInt();
       
   936             if (d->mNumberOfColumns != cols) {
       
   937                 d->mNumberOfColumns = cols;
       
   938                 if (d->menuItemView) {
       
   939                     d->menuItemView->updateContainer();
       
   940                 }
       
   941             }
       
   942         }
       
   943         d->delayedLayout();
   781     } else {
   944     } else {
   782         HbPopup::polish(params);
   945         HbPopup::polish(params);
   783     }
   946     }
   784 
   947 }
   785     if (!params.value(NumberOfCols).isNull()) {
   948 
   786         int cols = params.value(NumberOfCols).toInt();
   949 /*!
   787         if (d->mNumberOfColumns != cols) {
   950     Returns the shape of this item as a QPainterPath.
   788             d->mNumberOfColumns = cols;
   951 */
   789             if (d->menuItemView) {
       
   790                 d->menuItemView->updateContainer();
       
   791             }
       
   792         }
       
   793     }
       
   794 }
       
   795 
       
   796 /*!
       
   797   \reimp
       
   798   Returns the shape of this item as a QPainterPath.
       
   799  */
       
   800 QPainterPath HbMenu::shape() const
   952 QPainterPath HbMenu::shape() const
   801 {
   953 {
   802     /*QRectF rect = QRectF(-1.0, -1.0, boundingRect().width() + 1.0, boundingRect().height() + 1.0);
   954     QRectF rect = QRectF(-1.0, -1.0, boundingRect().width() + 1.0, boundingRect().height() + 1.0);
   803     QRectF clipRect = rect.intersected(mapRectFromParent(QRectF(pos().x() - 1.0, pos().y() - 1.0, size().width() + 1.0, size().height() + 1.0)));
   955     QRectF clipRect = rect.intersected(mapRectFromParent(QRectF(pos().x() - 1.0, pos().y() - 1.0, size().width() + 1.0, size().height() + 1.0)));
   804 
   956 
   805     QPainterPath path;
   957     QPainterPath path;
   806     path.addRect(clipRect);
   958     path.addRect(clipRect);
   807 
   959 
   808     return path;*/
   960     return path;
   809     return HbPopup::shape();
   961 //    return HbPopup::shape();
   810 }
   962 }
   811 
   963 
   812 /*!
   964 /*!
   813  
   965     Displays the menu on the screen and returns immediately. It can also connect the HbMenu::triggered()
   814   Opens the menu and returns immediately.
   966     signal to a specified slot. The signal is disconnected when the menu closes.
   815  
   967 
   816   Connects triggered(HbAction*) signal to the slot specified by \a
   968     \param receiver The object that is to receive the signal.
   817   receiver and \a member. The signal will be disconnected when menu
   969     \param member The slot on the receiver to which the signal is to connect.
   818   is closed.
   970 */
   819  
       
   820    An example of how to create a simple context menu and show it
       
   821    \snippet{ultimatecodesnippet/ultimatecodesnippet.cpp,54}
       
   822  
       
   823  
       
   824  */
       
   825 void HbMenu::open( QObject *receiver, const char *member )
   971 void HbMenu::open( QObject *receiver, const char *member )
   826 {
   972 {
   827     Q_D(HbMenu);
   973     Q_D(HbMenu);
   828     if ( d->receiverToDisconnectOnClose ) { // cant do on closeevent
   974     if ( d->receiverToDisconnectOnClose ) { // cant do on closeevent
   829         disconnect(this, SIGNAL(triggered(HbAction*)),
   975         disconnect(this, SIGNAL(triggered(HbAction*)),
   840         d->receiverToDisconnectOnClose = 0;
   986         d->receiverToDisconnectOnClose = 0;
   841     }
   987     }
   842     HbMenu::show();
   988     HbMenu::show();
   843 }
   989 }
   844 
   990 
       
   991 /*!
       
   992     Overidden from popup. Sets the preferred position of the menu.
       
   993 
       
   994     \param preferredPos Defines the coordinates of preferred position on the screen where
       
   995            the menu is to open.
       
   996     \param placement The corner or edge of the dialog that is to be placed at \a preferredPos.
       
   997 
       
   998     \b Example:
       
   999     \code
       
  1000     HbMenu *menu = new HbMenu();
       
  1001 
       
  1002     menu->setPreferredPos( QPointF(x,y), HbPopup::BottomEdgeCenter );
       
  1003     menu->show();
       
  1004     \endcode
       
  1005  */
       
  1006 void HbMenu::setPreferredPos( const QPointF& preferredPos,
       
  1007                                HbPopup::Placement placement )
       
  1008 {
       
  1009     Q_D(HbMenu);
       
  1010     bool layoutFlag = false;
       
  1011     if (d->preferredPos != preferredPos ) {
       
  1012         d->preferredPos = preferredPos;
       
  1013         layoutFlag = true;
       
  1014     }
       
  1015     if (d->placement != placement) {
       
  1016         d->placement = placement;
       
  1017         layoutFlag = true;
       
  1018     }
       
  1019     d->preferredPosSet = true;
       
  1020     //If position updated, informing layoutproxy with layoutrequest
       
  1021     if (layoutFlag) {
       
  1022         QEvent layoutRequest = QEvent::LayoutRequest;
       
  1023         QApplication::sendEvent(this, &layoutRequest);
       
  1024     }
       
  1025 }
       
  1026 
       
  1027 
   845 #include "moc_hbmenu.cpp"
  1028 #include "moc_hbmenu.cpp"