?? qpopupmenu.cpp
字號:
/****************************************************************************** $Id: qt/src/widgets/qpopupmenu.cpp 2.3.12 edited 2005-10-27 $**** Implementation of QPopupMenu class**** Created : 941128**** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.**** This file is part of the widgets module of the Qt GUI Toolkit.**** This file may be distributed under the terms of the Q Public License** as defined by Trolltech AS of Norway and appearing in the file** LICENSE.QPL included in the packaging of this file.**** This file may be distributed and/or modified under the terms of the** GNU General Public License version 2 as published by the Free Software** Foundation and appearing in the file LICENSE.GPL included in the** packaging of this file.**** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition** licenses may use this file in accordance with the Qt Commercial License** Agreement provided with the Software.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.**** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for** information about Qt Commercial License Agreements.** See http://www.trolltech.com/qpl/ for QPL licensing information.** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#define INCLUDE_MENUITEM_DEF#include "qpopupmenu.h"#ifndef QT_NO_POPUPMENU#include "qmenubar.h"#include "qaccel.h"#include "qpainter.h"#include "qdrawutil.h"#include "qapplication.h"#include "qbitmap.h"#include "qpixmapcache.h"#include "qtimer.h"#include "qwhatsthis.h"#include "qobjectlist.h"#include "qguardedptr.h"#include "qeffects_p.h"#include <ctype.h>//#define ANIMATED_POPUP//#define BLEND_POPUP// Motif style parametersstatic const int motifArrowHMargin = 6; // arrow horizontal marginstatic const int motifArrowVMargin = 2; // arrow vertical margin/*+-----------------------------| PopupFrame| +-------------------------| | ItemFrame| | +---------------------| | || | | \| | | ^ T E X T ^ | ItemVMargin| | | | | /| | ItemHMargin|*/// used for internal communicationstatic QPopupMenu * syncMenu = 0;static int syncMenuId = 0;// Used to detect motion prior to mouse-releasestatic int motion;// used to provide ONE single-shot timerstatic QGuardedPtr<QTimer> *singleSingleShot = 0;static bool supressAboutToShow = FALSE;static void popupSubMenuLater( int msec, QPopupMenu * receiver ) { if ( !singleSingleShot ) singleSingleShot = new QGuardedPtr<QTimer>; if ( !(*singleSingleShot) ) (*singleSingleShot) = new QTimer( qApp, "popup submenu timer" ); (*singleSingleShot)->disconnect( SIGNAL(timeout()) ); QObject::connect( *singleSingleShot, SIGNAL(timeout()), receiver, SLOT(subMenuTimer()) ); (*singleSingleShot)->start( msec, TRUE );}static bool preventAnimation = FALSE;#ifdef QT_KEYPAD_MODEextern bool qt_modalEditingEnabled;#endif// NOT REVISED/*! \class QPopupMenu qpopupmenu.h \brief The QPopupMenu class provides a popup menu widget. \ingroup application \ingroup basic A popup menu widget is a selection menu. It can be both, a pull-down menu in a menu bar or a standalone context menu. Pull-down menus are shown by the menu bar when the user clicks on the respective item or hits the specified shortcut key. Use QMenuBar::insertItem() to insert a popup menu into a menu bar. Show a context menu either asynchronously with popup() or synchronously with exec(). Technically, a popup menu consists of a list of menu items. You add items with insertItem(). An item is either a string, a pixmap or a custom item that provides its own drawing function (see QCustomMenuItem). In addition, items can have an optional icon drawn on the very left side and an accelerator key, like "Ctrl-X". There are three kind of menu items: separators, those that perform an action and those that show a submenu. Separators are inserted with insertSeparator(). For submenus, you pass a pointer to a QPopupMenu in your call to insertItem(). All other items are considered action items. When inserting actions items, you usually specify a receiver and a slot. The receiver will be notified whenever the item was selected. In addition, QPopupMenu provides two signals activated() and highlighted() that signal the identifier of the respective menu item. Sometimes it is practical to connect several items to one slot. To distinguish between them, specify a slot that takes an integer argument and use setItemParameter() to associate a unique value with each item. You clear a popup menu with clear() and remove single items with removeItem() or removeItemAt(). A popup menu can display check marks for certain items when enabled with setCheckable(TRUE). You check or uncheck items with setItemChecked(). Items are either enabled or disabled. You toggle their state with setItemEnabled(). Just before a popup menu becomes visible, it emits the aboutToShow() signal. You can use this signal to set the correct enabled/disabled states of all menu items before the user sees it. The corresponding aboutToHide() signal is emitted when the menu hides again. You can provide What's This? help for single menu items with setWhatsThis(). See QWhatsThis for general information about this kind of light-weight online help. For ultimate flexibility, you can also add entire widgets as items into a popup menu, for example a color selector. A QPopupMenu can also provide a tear-off menu. A tear-off menu is a "torn off" copy of a menu that lives in a separate window. This makes it possible for the user to "tear off" frequently used menus and position them in a convenient place on the screen. If you want that functionality for a certain menu, insert a tear-off handle with insertTearOffHandle(). When using tear-off menus, keep in mind that the concept isn't typically used on MS-Windows, so users may not be familiar with it. Consider using a QToolBar instead. menu/menu.cpp is a typical example of QMenuBar and QPopupMenu use. \important insertItem removeItem removeItemAt clear text pixmap iconSet insertSeparator changeItem whatsThis setWhatsThis accel setAccel setItemEnabled isItemEnabled setItemChecked isItemChecked connectItem disconnectItem setItemParameter itemParameter <img src=qpopmenu-m.png> <img src=qpopmenu-w.png> \sa QMenuBar <a href="guibooks.html#fowler">GUI Design Handbook: Menu, Drop-Down and Pop-Up</a>*//*! \fn void QPopupMenu::aboutToShow() This signal is emitted just before the popup menu is displayed. You can connect it to any slot that sets up the menu contents (e.g. to ensure that the right items are enabled). \sa aboutToHide(), setItemEnabled(), setItemChecked(), insertItem(), removeItem()*//*! \fn void QPopupMenu::aboutToHide() This signal is emitted just before the popup menu is hidden after it has been displayed. \warning Do not open a widget in a slot connected to this signal. \sa aboutToShow(), setItemEnabled(), setItemChecked(), insertItem(), removeItem()*//***************************************************************************** QPopupMenu member functions *****************************************************************************/class QMenuDataData { // attention: also defined in qmenudata.cpppublic: QMenuDataData(); QGuardedPtr<QWidget> aWidget; int aInt;};static QPopupMenu* active_popup_menu = 0;/*! Constructs a popup menu with a parent and a widget name. Although a popup menu is always a top level widget, if a parent is passed, the popup menu will be deleted on destruction of that parent (as with any other QObject).*/QPopupMenu::QPopupMenu( QWidget *parent, const char *name ) : QFrame( parent, name, WType_Popup | WRepaintNoErase ){ isPopupMenu = TRUE; parentMenu = 0; selfItem = 0;#ifndef QT_NO_ACCEL autoaccel = 0; accelDisabled = FALSE;#endif popupActive = -1; snapToMouse = TRUE; tab = 0; checkable = 0; tornOff = 0; maxPMWidth = 0; tab = 0; ncols = 1; setFrameStyle( QFrame::PopupPanel | QFrame::Raised ); style().polishPopupMenu( this ); setBackgroundMode( PaletteButton ); connectModalRecursionSafety = 0; setFocusPolicy( StrongFocus );}/*! Destructs the popup menu.*/QPopupMenu::~QPopupMenu(){ if ( syncMenu == this ) { qApp->exit_loop(); syncMenu = 0; } delete (QWidget*) QMenuData::d->aWidget; // tear-off menu if ( parentMenu ) parentMenu->removePopup( this ); // remove from parent menu preventAnimation = FALSE;}/*! Updates the item with identity \a id.*/void QPopupMenu::updateItem( int id ) // update popup menu item{ updateRow( indexOf(id) );}/*! Enables or disables display of check marks by the menu items. Notice that checking is always enabled when in windows-style. \sa isCheckable(), QMenuData::setItemChecked()*/void QPopupMenu::setCheckable( bool enable ){ if ( isCheckable() != enable ) { checkable = enable; badSize = TRUE; if ( QMenuData::d->aWidget ) ( (QPopupMenu*)(QWidget*)QMenuData::d->aWidget)->setCheckable( enable ); }}/*! Returns whether display of check marks by the menu items is enabled. \sa setCheckable(), QMenuData::setItemChecked()*/bool QPopupMenu::isCheckable() const{ return checkable;}void QPopupMenu::menuContentsChanged(){ badSize = TRUE; // might change the size#ifndef QT_NO_ACCEL updateAccel( 0 );#endif if ( isVisible() ) { if ( tornOff ) return; updateSize(); update(); } QPopupMenu* p = (QPopupMenu*)(QWidget*)QMenuData::d->aWidget; if ( p && p->isVisible() ) { p->mitems->clear(); for ( QMenuItemListIt it( *mitems ); it.current(); ++it ) { if ( it.current()->id() != QMenuData::d->aInt && !it.current()->widget() ) p->mitems->append( it.current() ); } p->updateSize(); p->update(); }}void QPopupMenu::menuStateChanged(){#ifndef QT_NO_ACCEL updateAccel( 0 ); // ### when we have a good solution for the accel vs. focus widget problem, remove that. That is only a workaround#endif updateSize(); update(); if ( QMenuData::d->aWidget ) QMenuData::d->aWidget->update();}void QPopupMenu::menuInsPopup( QPopupMenu *popup ){ popup->parentMenu = this; // set parent menu connect( popup, SIGNAL(activatedRedirect(int)), SLOT(subActivated(int)) ); connect( popup, SIGNAL(highlightedRedirect(int)), SLOT(subHighlighted(int)) );}void QPopupMenu::menuDelPopup( QPopupMenu *popup ){ popup->parentMenu = 0; popup->disconnect( SIGNAL(activatedRedirect(int)), this, SLOT(subActivated(int)) ); popup->disconnect( SIGNAL(highlightedRedirect(int)), this, SLOT(subHighlighted(int)) );}void QPopupMenu::frameChanged(){ menuContentsChanged();}/*! Opens the popup menu so that the item number \a indexAtPoint will be at the specified \e global position \a pos. To translate a widget's local coordinates into global coordinates, use QWidget::mapToGlobal(). When positioning a popup with exec() or popup(), keep in mind that you cannot rely on the popup menu's current size(). For performance reasons, the popup adapts its size only when actually needed. So in many cases, the size before and after the show is different. Instead, use sizeHint(). It calculates the proper size depending on the menu's current contents.*/void QPopupMenu::popup( const QPoint &pos, int indexAtPoint ){ if ( !isPopup() && isVisible() ) hide(); //avoid circularity if ( isVisible() || !isEnabled() ) return; if (parentMenu && parentMenu->actItem == -1){ //reuse parentMenu->menuDelPopup( this ); parentMenu = 0; } // #### should move to QWidget - anything might need this functionality, // #### since anything can have WType_Popup window flag. QPoint mouse = QCursor::pos(); snapToMouse = snapToMouse && pos == mouse; // have to emit here as a menu might be setup in a slot connected // to aboutToShow which will change the size of the menu bool s = supressAboutToShow; supressAboutToShow = TRUE; if ( !s) { emit aboutToShow(); updateSize(); } if ( mitems->count() == 0 ) // oops, empty insertSeparator(); // Save Our Souls if ( badSize ) updateSize(); QWidget *desktop = QApplication::desktop(); int sw = desktop->width(); // screen width int sh = desktop->height(); // screen height int sx = desktop->x(); // screen pos int sy = desktop->y(); int x = pos.x(); int y = pos.y(); if ( indexAtPoint > 0 ) // don't subtract when < 0 y -= itemGeometry( indexAtPoint ).y(); // (would subtract 2 pixels!) int w = width(); int h = height(); if ( snapToMouse ) { if ( x+w > sw ) x = mouse.x()-w; if ( y+h > sh ) y = mouse.y()-h; if ( x < sx ) x = mouse.x(); if ( y < sy ) y = sy; } if ( x+w > sw ) // the complete widget must x = sw - w; // be visible if ( y+h > sh ) y = sh - h; if ( x < sx ) x = sx; if ( y < sy ) y = sy; move( x, y ); motion=0; actItem = -1;#ifndef QT_NO_EFFECTS int hGuess = QEffects::RightScroll; int vGuess = QEffects::DownScroll;# ifdef QT_KEYPAD_MODE // ### Effects really needs to be able to have a direction hint set if ( parentWidget() && parentWidget()->isA("ContextMenu") ) vGuess = QEffects::UpScroll; bool avoidScrollView = child(0, "QScrollView");# endif if ( snapToMouse && ( x + w/2 < mouse.x() ) || ( parentMenu && parentMenu->isPopupMenu && ( x + w/2 < ((QPopupMenu*)parentMenu)->x() ) ) ) hGuess = QEffects::LeftScroll; if ( snapToMouse && ( y + h/2 < mouse.y() )#ifndef QT_NO_MENUBAR || ( parentMenu && parentMenu->isMenuBar && ( y + h/2 < ((QMenuBar*)parentMenu)->mapToGlobal( ((QMenuBar*)parentMenu)->pos() ).y() ) )#endif ) vGuess = QEffects::UpScroll;#ifdef QT_KEYPAD_MODE if ( avoidScrollView ) show(); else#endif if ( QApplication::isEffectEnabled( UI_AnimateMenu ) && preventAnimation == FALSE ) { if ( QApplication::isEffectEnabled( UI_FadeMenu ) ) qFadeEffect( this ); else if ( parentMenu ) qScrollEffect( this, parentMenu->isPopupMenu ? hGuess : vGuess ); else# ifdef QT_KEYPAD_MODE //QT_KEYPAD_MODE qScrollEffect( this, vGuess, 300 );# else qScrollEffect( this, hGuess | vGuess );# endif } else#endif { show(); }}/*! \fn void QPopupMenu::activated( int id ) This signal is emitted when a menu item is selected; \a id is the id of the selected item. Normally, you will connect each menu item to a single slot using QMenuData::insertItem(), but sometimes you will want to connect several items to a single slot (most often if the user selects from an array). This signal is handy in such cases. \sa highlighted(), QMenuData::insertItem()*//*! \fn void QPopupMenu::highlighted( int id ) This signal is emitted when a menu item is highlighted; \a id is the id of the highlighted item. Normally, you will connect each menu item to a single slot using QMenuData::insertItem(), but sometimes you will want to connect
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -