source: vendor/trolltech/current/src/widgets/qmenudata.cpp

Last change on this file was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 43.3 KB
Line 
1/****************************************************************************
2** $Id: qmenudata.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of QMenuData class
5**
6** Created : 941128
7**
8** Copyright (C) 1992-2002 Trolltech AS. All rights reserved.
9**
10** This file is part of the widgets module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "qmenudata.h"
39#ifndef QT_NO_MENUDATA
40#include "qpopupmenu.h"
41#include "qmenubar.h"
42#include "qapplication.h"
43#include "qguardedptr.h"
44
45class QMenuItemData {
46public:
47 QCustomMenuItem *custom_item; // custom menu item
48};
49
50class QMenuDataData {
51 // attention: also defined in qmenubar.cpp and qpopupmenu.cpp
52public:
53 QMenuDataData();
54 QGuardedPtr<QWidget> aWidget;
55 int aInt;
56};
57QMenuDataData::QMenuDataData()
58 : aInt(-1)
59{}
60
61/*!
62 \class QMenuData qmenudata.h
63 \brief The QMenuData class is a base class for QMenuBar and QPopupMenu.
64
65 \ingroup misc
66
67 QMenuData has an internal list of menu items. A menu item can have
68 a text(), an \link accel() accelerator\endlink, a pixmap(), an
69 iconSet(), a whatsThis() text and a popup menu (unless it is a
70 separator). Menu items may optionally be \link setItemChecked()
71 checked\endlink (except for separators).
72
73 The menu item sends out an \link QMenuBar::activated()
74 activated()\endlink signal when it is chosen and a \link
75 QMenuBar::highlighted() highlighted()\endlink signal when it
76 receives the user input focus.
77
78 \keyword menu identifier
79
80 Menu items are assigned the menu identifier \e id that is passed
81 in insertItem() or an automatically generated identifier if \e id
82 is < 0 (the default). The generated identifiers (negative
83 integers) are guaranteed to be unique within the entire
84 application. The identifier is used to access the menu item in
85 other functions.
86
87 Menu items can be removed with removeItem() and removeItemAt(), or
88 changed with changeItem(). All menu items can be removed with
89 clear(). Accelerators can be changed or set with setAccel().
90 Checkable items can be checked or unchecked with setItemChecked().
91 Items can be enabled or disabled using setItemEnabled() and
92 connected and disconnected with connectItem() and disconnectItem()
93 respectively. By default, newly created menu items are visible.
94 They can be hidden (and shown again) with setItemVisible().
95
96 Menu items are stored in a list. Use findItem() to find an item by
97 its list position or by its menu identifier. (See also indexOf()
98 and idAt().)
99
100 \sa QAccel QPopupMenu QAction
101*/
102
103
104/*****************************************************************************
105 QMenuItem member functions
106 *****************************************************************************/
107
108QMenuItem::QMenuItem()
109 :ident( -1 ), iconset_data( 0 ), pixmap_data( 0 ), popup_menu( 0 ),
110 widget_item( 0 ), signal_data( 0 ), is_separator( FALSE ), is_enabled( TRUE ),
111 is_checked( FALSE ), is_dirty( TRUE ), is_visible( TRUE ), d( 0)
112{}
113
114QMenuItem::~QMenuItem()
115{
116 delete iconset_data;
117 delete pixmap_data;
118 delete signal_data;
119 delete widget_item;
120 if ( d )
121 delete d->custom_item;
122 delete d;
123}
124
125
126/*****************************************************************************
127 QMenuData member functions
128 *****************************************************************************/
129
130QMenuItemData* QMenuItem::extra()
131{
132 if ( !d ) d = new QMenuItemData;
133 return d;
134}
135
136QCustomMenuItem *QMenuItem::custom() const
137{
138 if ( !d ) return 0;
139 return d->custom_item;
140}
141
142
143static int get_seq_id()
144{
145 static int seq_no = -2;
146 return seq_no--;
147}
148
149
150/*!
151 Constructs an empty menu data list.
152*/
153
154QMenuData::QMenuData()
155{
156 actItem = -1; // no active menu item
157 mitems = new QMenuItemList; // create list of menu items
158 Q_CHECK_PTR( mitems );
159 mitems->setAutoDelete( TRUE );
160 parentMenu = 0; // assume top level
161 isPopupMenu = FALSE;
162 isMenuBar = FALSE;
163 mouseBtDn = FALSE;
164 badSize = TRUE;
165 avoid_circularity = 0;
166 actItemDown = FALSE;
167 d = new QMenuDataData;
168}
169
170/*!
171 Removes all menu items and disconnects any signals that have been
172 connected.
173*/
174
175QMenuData::~QMenuData()
176{
177 delete mitems; // delete menu item list
178 delete d;
179}
180
181
182/*!
183 Virtual function; notifies subclasses about an item with \a id
184 that has been changed.
185*/
186
187void QMenuData::updateItem( int /* id */ ) // reimplemented in subclass
188{
189}
190
191/*!
192 Virtual function; notifies subclasses that one or more items have
193 been inserted or removed.
194*/
195
196void QMenuData::menuContentsChanged() // reimplemented in subclass
197{
198}
199
200/*!
201 Virtual function; notifies subclasses that one or more items have
202 changed state (enabled/disabled or checked/unchecked).
203*/
204
205void QMenuData::menuStateChanged() // reimplemented in subclass
206{
207}
208
209/*!
210 Virtual function; notifies subclasses that a popup menu item has
211 been inserted.
212*/
213
214void QMenuData::menuInsPopup( QPopupMenu * ) // reimplemented in subclass
215{
216}
217
218/*!
219 Virtual function; notifies subclasses that a popup menu item has
220 been removed.
221*/
222
223void QMenuData::menuDelPopup( QPopupMenu * ) // reimplemented in subclass
224{
225}
226
227
228/*!
229 Returns the number of items in the menu.
230*/
231
232uint QMenuData::count() const
233{
234 return mitems->count();
235}
236
237
238
239/*!
240 \internal
241
242 Internal function that insert a menu item. Called by all insert()
243 functions.
244*/
245
246int QMenuData::insertAny( const QString *text, const QPixmap *pixmap,
247 QPopupMenu *popup, const QIconSet* iconset, int id, int index,
248 QWidget* widget, QCustomMenuItem* custom )
249{
250 if ( index < 0 ) { // append, but not if the rightmost item is an mdi separator in the menubar
251 index = mitems->count();
252 if ( isMenuBar && mitems->last() && mitems->last()->widget() && mitems->last()->isSeparator() )
253 index--;
254 } else if ( index > (int) mitems->count() ) { // append
255 index = mitems->count();
256 }
257 if ( id < 0 ) // -2, -3 etc.
258 id = get_seq_id();
259
260 register QMenuItem *mi = new QMenuItem;
261 Q_CHECK_PTR( mi );
262 mi->ident = id;
263 if ( widget != 0 ) {
264 mi->widget_item = widget;
265 mi->is_separator = !widget->isFocusEnabled();
266 } else if ( custom != 0 ) {
267 mi->extra()->custom_item = custom;
268 mi->is_separator = custom->isSeparator();
269 if ( iconset && !iconset->isNull() )
270 mi->iconset_data = new QIconSet( *iconset );
271 } else if ( text == 0 && pixmap == 0 && popup == 0 ) {
272 mi->is_separator = TRUE; // separator
273 } else {
274#ifndef Q_OS_TEMP
275 mi->text_data = text?*text:QString();
276#else
277 QString newText( *text );
278 newText.truncate( newText.findRev( '\t' ) );
279 mi->text_data = newText.isEmpty()?QString():newText;
280#endif
281#ifndef QT_NO_ACCEL
282 mi->accel_key = Qt::Key_unknown;
283#endif
284 if ( pixmap && !pixmap->isNull() )
285 mi->pixmap_data = new QPixmap( *pixmap );
286 if ( (mi->popup_menu = popup) )
287 menuInsPopup( popup );
288 if ( iconset && !iconset->isNull() )
289 mi->iconset_data = new QIconSet( *iconset );
290 }
291
292 mitems->insert( index, mi );
293 menuContentsChanged(); // menu data changed
294 return mi->ident;
295}
296
297/*!
298 \internal
299
300 Internal function that finds the menu item where \a popup is located,
301 storing its index at \a index if \a index is not NULL.
302*/
303QMenuItem *QMenuData::findPopup( QPopupMenu *popup, int *index )
304{
305 int i = 0;
306 QMenuItem *mi = mitems->first();
307 while ( mi ) {
308 if ( mi->popup_menu == popup ) // found popup
309 break;
310 i++;
311 mi = mitems->next();
312 }
313 if ( index && mi )
314 *index = i;
315 return mi;
316}
317
318void QMenuData::removePopup( QPopupMenu *popup )
319{
320 int index = 0;
321 QMenuItem *mi = findPopup( popup, &index );
322 if ( mi ) {
323 mi->popup_menu = 0;
324 removeItemAt( index );
325 }
326}
327
328
329/*!
330 The family of insertItem() functions inserts menu items into a
331 popup menu or a menu bar.
332
333 A menu item is usually either a text string or a pixmap, both with
334 an optional icon or keyboard accelerator. For special cases it is
335 also possible to insert custom items (see \l{QCustomMenuItem}) or
336 even widgets into popup menus.
337
338 Some insertItem() members take a popup menu as an additional
339 argument. Use this to insert submenus into existing menus or
340 pulldown menus into a menu bar.
341
342 The number of insert functions may look confusing, but they are
343 actually quite simple to use.
344
345 This default version inserts a menu item with the text \a text,
346 the accelerator key \a accel, an id and an optional index and
347 connects it to the slot \a member in the object \a receiver.
348
349 Example:
350 \code
351 QMenuBar *mainMenu = new QMenuBar;
352 QPopupMenu *fileMenu = new QPopupMenu;
353 fileMenu->insertItem( "New", myView, SLOT(newFile()), CTRL+Key_N );
354 fileMenu->insertItem( "Open", myView, SLOT(open()), CTRL+Key_O );
355 mainMenu->insertItem( "File", fileMenu );
356 \endcode
357
358 Not all insert functions take an object/slot parameter or an
359 accelerator key. Use connectItem() and setAccel() on those items.
360
361 If you need to translate accelerators, use tr() with the text and
362 accelerator. (For translations use a string \link QKeySequence key
363 sequence\endlink.):
364 \code
365 fileMenu->insertItem( tr("Open"), myView, SLOT(open()),
366 tr("Ctrl+O") );
367 \endcode
368
369 In the example above, pressing Ctrl+O or selecting "Open" from the
370 menu activates the myView->open() function.
371
372 Some insert functions take a QIconSet parameter to specify the
373 little menu item icon. Note that you can always pass a QPixmap
374 object instead.
375
376 The \a id specifies the identification number associated with the
377 menu item. Note that only positive values are valid, as a negative
378 value will make Qt select a unique id for the item.
379
380 The \a index specifies the position in the menu. The menu item is
381 appended at the end of the list if \a index is negative.
382
383 Note that keyboard accelerators in Qt are not application-global,
384 instead they are bound to a certain top-level window. For example,
385 accelerators in QPopupMenu items only work for menus that are
386 associated with a certain window. This is true for popup menus
387 that live in a menu bar since their accelerators will then be
388 installed in the menu bar itself. This also applies to stand-alone
389 popup menus that have a top-level widget in their parentWidget()
390 chain. The menu will then install its accelerator object on that
391 top-level widget. For all other cases use an independent QAccel
392 object.
393
394 \warning Be careful when passing a literal 0 to insertItem()
395 because some C++ compilers choose the wrong overloaded function.
396 Cast the 0 to what you mean, e.g. \c{(QObject*)0}.
397
398 \warning On Mac OS X, items that connect to a slot that are inserted into a
399 menubar will not function as we use the native menubar that knows nothing
400 about signals or slots. Instead insert the items into a popup menu and
401 insert the popup menu into the menubar. This may be fixed in a future Qt
402 version.
403
404 Returns the allocated menu identifier number (\a id if \a id >= 0).
405
406 \sa removeItem(), changeItem(), setAccel(), connectItem(), QAccel,
407 qnamespace.h
408*/
409
410int QMenuData::insertItem( const QString &text,
411 const QObject *receiver, const char* member,
412 const QKeySequence& accel, int id, int index )
413{
414 int actualID = insertAny( &text, 0, 0, 0, id, index );
415 connectItem( actualID, receiver, member );
416#ifndef QT_NO_ACCEL
417 if ( accel )
418 setAccel( accel, actualID );
419#endif
420 return actualID;
421}
422
423/*!
424 \overload
425
426 Inserts a menu item with icon \a icon, text \a text, accelerator
427 \a accel, optional id \a id, and optional \a index position. The
428 menu item is connected it to the \a receiver's \a member slot. The
429 icon will be displayed to the left of the text in the item.
430
431 Returns the allocated menu identifier number (\a id if \a id >= 0).
432
433 \sa removeItem(), changeItem(), setAccel(), connectItem(), QAccel,
434 qnamespace.h
435*/
436
437int QMenuData::insertItem( const QIconSet& icon,
438 const QString &text,
439 const QObject *receiver, const char* member,
440 const QKeySequence& accel, int id, int index )
441{
442 int actualID = insertAny( &text, 0, 0, &icon, id, index );
443 connectItem( actualID, receiver, member );
444#ifndef QT_NO_ACCEL
445 if ( accel )
446 setAccel( accel, actualID );
447#endif
448 return actualID;
449}
450
451/*!
452 \overload
453
454 Inserts a menu item with pixmap \a pixmap, accelerator \a accel,
455 optional id \a id, and optional \a index position. The menu item
456 is connected it to the \a receiver's \a member slot. The icon will
457 be displayed to the left of the text in the item.
458
459 To look best when being highlighted as a menu item, the pixmap
460 should provide a mask (see QPixmap::mask()).
461
462 Returns the allocated menu identifier number (\a id if \a id >= 0).
463
464 \sa removeItem(), changeItem(), setAccel(), connectItem()
465*/
466
467int QMenuData::insertItem( const QPixmap &pixmap,
468 const QObject *receiver, const char* member,
469 const QKeySequence& accel, int id, int index )
470{
471 int actualID = insertAny( 0, &pixmap, 0, 0, id, index );
472 connectItem( actualID, receiver, member );
473#ifndef QT_NO_ACCEL
474 if ( accel )
475 setAccel( accel, actualID );
476#endif
477 return actualID;
478}
479
480
481/*!
482 \overload
483
484 Inserts a menu item with icon \a icon, pixmap \a pixmap,
485 accelerator \a accel, optional id \a id, and optional \a index
486 position. The icon will be displayed to the left of the pixmap in
487 the item. The item is connected to the \a member slot in the \a
488 receiver object.
489
490 To look best when being highlighted as a menu item, the pixmap
491 should provide a mask (see QPixmap::mask()).
492
493 Returns the allocated menu identifier number (\a id if \a id >= 0).
494
495 \sa removeItem(), changeItem(), setAccel(), connectItem(), QAccel,
496 qnamespace.h
497*/
498
499int QMenuData::insertItem( const QIconSet& icon,
500 const QPixmap &pixmap,
501 const QObject *receiver, const char* member,
502 const QKeySequence& accel, int id, int index )
503{
504 int actualID = insertAny( 0, &pixmap, 0, &icon, id, index );
505 connectItem( actualID, receiver, member );
506#ifndef QT_NO_ACCEL
507 if ( accel )
508 setAccel( accel, actualID );
509#endif
510 return actualID;
511}
512
513
514
515/*!
516 \overload
517
518 Inserts a menu item with text \a text, optional id \a id, and
519 optional \a index position.
520
521 Returns the allocated menu identifier number (\a id if \a id >= 0).
522
523 \sa removeItem(), changeItem(), setAccel(), connectItem()
524*/
525
526int QMenuData::insertItem( const QString &text, int id, int index )
527{
528 return insertAny( &text, 0, 0, 0, id, index );
529}
530
531/*!
532 \overload
533
534 Inserts a menu item with icon \a icon, text \a text, optional id
535 \a id, and optional \a index position. The icon will be displayed
536 to the left of the text in the item.
537
538 Returns the allocated menu identifier number (\a id if \a id >= 0).
539
540 \sa removeItem(), changeItem(), setAccel(), connectItem()
541*/
542
543int QMenuData::insertItem( const QIconSet& icon,
544 const QString &text, int id, int index )
545{
546 return insertAny( &text, 0, 0, &icon, id, index );
547}
548
549/*!
550 \overload
551
552 Inserts a menu item with text \a text, submenu \a popup, optional
553 id \a id, and optional \a index position.
554
555 The \a popup must be deleted by the programmer or by its parent
556 widget. It is not deleted when this menu item is removed or when
557 the menu is deleted.
558
559 Returns the allocated menu identifier number (\a id if \a id >= 0).
560
561 \sa removeItem(), changeItem(), setAccel(), connectItem()
562*/
563
564int QMenuData::insertItem( const QString &text, QPopupMenu *popup,
565 int id, int index )
566{
567 return insertAny( &text, 0, popup, 0, id, index );
568}
569
570/*!
571 \overload
572
573 Inserts a menu item with icon \a icon, text \a text, submenu \a
574 popup, optional id \a id, and optional \a index position. The icon
575 will be displayed to the left of the text in the item.
576
577 The \a popup must be deleted by the programmer or by its parent
578 widget. It is not deleted when this menu item is removed or when
579 the menu is deleted.
580
581 Returns the allocated menu identifier number (\a id if \a id >= 0).
582
583 \sa removeItem(), changeItem(), setAccel(), connectItem()
584*/
585
586int QMenuData::insertItem( const QIconSet& icon,
587 const QString &text, QPopupMenu *popup,
588 int id, int index )
589{
590 return insertAny( &text, 0, popup, &icon, id, index );
591}
592
593/*!
594 \overload
595
596 Inserts a menu item with pixmap \a pixmap, optional id \a id, and
597 optional \a index position.
598
599 To look best when being highlighted as a menu item, the pixmap
600 should provide a mask (see QPixmap::mask()).
601
602 Returns the allocated menu identifier number (\a id if \a id >= 0).
603
604 \sa removeItem(), changeItem(), setAccel(), connectItem()
605*/
606
607int QMenuData::insertItem( const QPixmap &pixmap, int id, int index )
608{
609 return insertAny( 0, &pixmap, 0, 0, id, index );
610}
611
612/*!
613 \overload
614
615 Inserts a menu item with icon \a icon, pixmap \a pixmap, optional
616 id \a id, and optional \a index position. The icon will be
617 displayed to the left of the pixmap in the item.
618
619 Returns the allocated menu identifier number (\a id if \a id >= 0).
620
621 \sa removeItem(), changeItem(), setAccel(), connectItem()
622*/
623
624int QMenuData::insertItem( const QIconSet& icon,
625 const QPixmap &pixmap, int id, int index )
626{
627 return insertAny( 0, &pixmap, 0, &icon, id, index );
628}
629
630
631/*!
632 \overload
633
634 Inserts a menu item with pixmap \a pixmap, submenu \a popup,
635 optional id \a id, and optional \a index position.
636
637 The \a popup must be deleted by the programmer or by its parent
638 widget. It is not deleted when this menu item is removed or when
639 the menu is deleted.
640
641 Returns the allocated menu identifier number (\a id if \a id >= 0).
642
643 \sa removeItem(), changeItem(), setAccel(), connectItem()
644*/
645
646int QMenuData::insertItem( const QPixmap &pixmap, QPopupMenu *popup,
647 int id, int index )
648{
649 return insertAny( 0, &pixmap, popup, 0, id, index );
650}
651
652
653/*!
654 \overload
655
656 Inserts a menu item with icon \a icon, pixmap \a pixmap submenu \a
657 popup, optional id \a id, and optional \a index position. The icon
658 will be displayed to the left of the pixmap in the item.
659
660 The \a popup must be deleted by the programmer or by its parent
661 widget. It is not deleted when this menu item is removed or when
662 the menu is deleted.
663
664 Returns the allocated menu identifier number (\a id if \a id >= 0).
665
666 \sa removeItem(), changeItem(), setAccel(), connectItem()
667*/
668
669int QMenuData::insertItem( const QIconSet& icon,
670 const QPixmap &pixmap, QPopupMenu *popup,
671 int id, int index )
672{
673 return insertAny( 0, &pixmap, popup, &icon, id, index );
674}
675
676
677
678/*!
679 \overload
680
681 Inserts a menu item that consists of the widget \a widget with
682 optional id \a id, and optional \a index position.
683
684 Ownership of \a widget is transferred to the popup menu or to the
685 menu bar.
686
687 Theoretically, any widget can be inserted into a popup menu. In
688 practice, this only makes sense with certain widgets.
689
690 If a widget is not focus-enabled (see
691 \l{QWidget::isFocusEnabled()}), the menu treats it as a separator;
692 this means that the item is not selectable and will never get
693 focus. In this way you can, for example, simply insert a QLabel if
694 you need a popup menu with a title.
695
696 If the widget is focus-enabled it will get focus when the user
697 traverses the popup menu with the arrow keys. If the widget does
698 not accept \c ArrowUp and \c ArrowDown in its key event handler,
699 the focus will move back to the menu when the respective arrow key
700 is hit one more time. This works with a QLineEdit, for example. If
701 the widget accepts the arrow key itself, it must also provide the
702 possibility to put the focus back on the menu again by calling
703 QWidget::focusNextPrevChild(). Futhermore, if the embedded widget
704 closes the menu when the user made a selection, this can be done
705 safely by calling:
706 \code
707 if ( isVisible() &&
708 parentWidget() &&
709 parentWidget()->inherits("QPopupMenu") )
710 parentWidget()->close();
711 \endcode
712
713 Returns the allocated menu identifier number (\a id if \a id >= 0).
714
715 \sa removeItem()
716*/
717int QMenuData::insertItem( QWidget* widget, int id, int index )
718{
719 return insertAny( 0, 0, 0, 0, id, index, widget );
720}
721
722
723/*!
724 \overload
725
726 Inserts a custom menu item \a custom with optional id \a id, and
727 optional \a index position.
728
729 This only works with popup menus. It is not supported for menu
730 bars. Ownership of \a custom is transferred to the popup menu.
731
732 If you want to connect a custom item to a slot, use connectItem().
733
734 Returns the allocated menu identifier number (\a id if \a id >= 0).
735
736 \sa connectItem(), removeItem(), QCustomMenuItem
737*/
738int QMenuData::insertItem( QCustomMenuItem* custom, int id, int index )
739{
740 return insertAny( 0, 0, 0, 0, id, index, 0, custom );
741}
742
743/*!
744 \overload
745
746 Inserts a custom menu item \a custom with an \a icon and with
747 optional id \a id, and optional \a index position.
748
749 This only works with popup menus. It is not supported for menu
750 bars. Ownership of \a custom is transferred to the popup menu.
751
752 If you want to connect a custom item to a slot, use connectItem().
753
754 Returns the allocated menu identifier number (\a id if \a id >= 0).
755
756 \sa connectItem(), removeItem(), QCustomMenuItem
757*/
758int QMenuData::insertItem( const QIconSet& icon, QCustomMenuItem* custom, int id, int index )
759{
760 return insertAny( 0, 0, 0, &icon, id, index, 0, custom );
761}
762
763
764/*!
765 Inserts a separator at position \a index. The separator becomes
766 the last menu item if \a index is negative.
767
768 In a popup menu a separator is rendered as a horizontal line. In a
769 Motif menu bar a separator is spacing, so the rest of the items
770 (normally just "Help") are drawn right-justified. In a Windows
771 menu bar separators are ignored (to comply with the Windows style
772 guidelines).
773*/
774int QMenuData::insertSeparator( int index )
775{
776 return insertAny( 0, 0, 0, 0, -1, index );
777}
778
779/*!
780 \fn void QMenuData::removeItem( int id )
781
782 Removes the menu item that has the identifier \a id.
783
784 \sa removeItemAt(), clear()
785*/
786
787void QMenuData::removeItem( int id )
788{
789 QMenuData *parent;
790 if ( findItem( id, &parent ) )
791 parent->removeItemAt(parent->indexOf(id));
792}
793
794/*!
795 Removes the menu item at position \a index.
796
797 \sa removeItem(), clear()
798*/
799
800void QMenuData::removeItemAt( int index )
801{
802 if ( index < 0 || index >= (int)mitems->count() ) {
803#if defined(QT_CHECK_RANGE)
804 qWarning( "QMenuData::removeItem: Index %d out of range", index );
805#endif
806 return;
807 }
808 QMenuItem *mi = mitems->at( index );
809 if ( mi->popup_menu )
810 menuDelPopup( mi->popup_menu );
811 mitems->remove();
812 if ( !QApplication::closingDown() ) // avoid trouble
813 menuContentsChanged();
814}
815
816
817/*!
818 Removes all menu items.
819
820 \sa removeItem(), removeItemAt()
821*/
822
823void QMenuData::clear()
824{
825 register QMenuItem *mi = mitems->first();
826 while ( mi ) {
827 if ( mi->popup_menu )
828 menuDelPopup( mi->popup_menu );
829 mitems->remove();
830 mi = mitems->current();
831 }
832 if ( !QApplication::closingDown() ) // avoid trouble
833 menuContentsChanged();
834}
835
836#ifndef QT_NO_ACCEL
837
838/*!
839 Returns the accelerator key that has been defined for the menu
840 item \a id, or 0 if it has no accelerator key or if there is no
841 such menu item.
842
843 \sa setAccel(), QAccel, qnamespace.h
844*/
845
846QKeySequence QMenuData::accel( int id ) const
847{
848 QMenuItem *mi = findItem( id );
849 if ( mi )
850 return mi->key();
851 return QKeySequence();
852}
853
854/*!
855 Sets the accelerator key for the menu item \a id to \a key.
856
857 An accelerator key consists of a key code and a combination of the
858 modifiers \c SHIFT, \c CTRL, \c ALT or \c UNICODE_ACCEL (OR'ed or
859 added). The header file \c qnamespace.h contains a list of key
860 codes.
861
862 Defining an accelerator key produces a text that is added to the
863 menu item; for instance, \c CTRL + \c Key_O produces "Ctrl+O". The
864 text is formatted differently for different platforms.
865
866 Note that keyboard accelerators in Qt are not application-global,
867 instead they are bound to a certain top-level window. For example,
868 accelerators in QPopupMenu items only work for menus that are
869 associated with a certain window. This is true for popup menus
870 that live in a menu bar since their accelerators will then be
871 installed in the menu bar itself. This also applies to stand-alone
872 popup menus that have a top-level widget in their parentWidget()
873 chain. The menu will then install its accelerator object on that
874 top-level widget. For all other cases use an independent QAccel
875 object.
876
877 Example:
878 \code
879 QMenuBar *mainMenu = new QMenuBar;
880 QPopupMenu *fileMenu = new QPopupMenu; // file sub menu
881 fileMenu->insertItem( "Open Document", 67 ); // add "Open" item
882 fileMenu->setAccel( CTRL + Key_O, 67 ); // Ctrl+O to open
883 fileMenu->insertItem( "Quit", 69 ); // add "Quit" item
884 fileMenu->setAccel( CTRL + ALT + Key_Delete, 69 ); // add Alt+Del to quit
885 mainMenu->insertItem( "File", fileMenu ); // add the file menu
886 \endcode
887
888 If you need to translate accelerators, use tr() with a string:
889 \code
890 fileMenu->setAccel( tr("Ctrl+O"), 67 );
891 \endcode
892
893 You can also specify the accelerator in the insertItem() function.
894 You may prefer to use QAction to associate accelerators with menu
895 items.
896
897 \sa accel() insertItem() QAccel QAction
898*/
899
900void QMenuData::setAccel( const QKeySequence& key, int id )
901{
902 QMenuData *parent;
903 QMenuItem *mi = findItem( id, &parent );
904 if ( mi ) {
905 mi->accel_key = key;
906 parent->menuContentsChanged();
907 }
908}
909
910#endif // QT_NO_ACCEL
911
912/*!
913 Returns the icon set that has been set for menu item \a id, or 0
914 if no icon set has been set.
915
916 \sa changeItem(), text(), pixmap()
917*/
918
919QIconSet* QMenuData::iconSet( int id ) const
920{
921 QMenuItem *mi = findItem( id );
922 return mi ? mi->iconSet() : 0;
923}
924
925/*!
926 Returns the text that has been set for menu item \a id, or
927 QString::null if no text has been set.
928
929 \sa changeItem(), pixmap(), iconSet()
930*/
931
932QString QMenuData::text( int id ) const
933{
934 QMenuItem *mi = findItem( id );
935 return mi ? mi->text() : QString::null;
936}
937
938/*!
939 Returns the pixmap that has been set for menu item \a id, or 0 if
940 no pixmap has been set.
941
942 \sa changeItem(), text(), iconSet()
943*/
944
945QPixmap *QMenuData::pixmap( int id ) const
946{
947 QMenuItem *mi = findItem( id );
948 return mi ? mi->pixmap() : 0;
949}
950
951/*!
952 \fn void QMenuData::changeItem( const QString &, int )
953 \obsolete
954
955 Changes the text of the menu item \a id. If the item has an icon,
956 the icon remains unchanged.
957
958 \sa text()
959*/
960/*!
961 \fn void QMenuData::changeItem( const QPixmap &, int )
962 \obsolete
963
964 Changes the pixmap of the menu item \a id. If the item has an icon,
965 the icon remains unchanged.
966
967 \sa pixmap()
968*/
969
970/*!
971 \fn void QMenuData::changeItem( const QIconSet &, const QString &, int )
972 \obsolete
973
974 Changes the icon and text of the menu item \a id.
975
976 \sa pixmap()
977*/
978
979/*!
980 Changes the text of the menu item \a id to \a text. If the item
981 has an icon, the icon remains unchanged.
982
983 \sa text()
984*/
985
986void QMenuData::changeItem( int id, const QString &text )
987{
988 QMenuData *parent;
989 QMenuItem *mi = findItem( id, &parent );
990 if ( mi ) { // item found
991 if ( mi->text_data == text ) // same string
992 return;
993 if ( mi->pixmap_data ) { // delete pixmap
994 delete mi->pixmap_data;
995 mi->pixmap_data = 0;
996 }
997 mi->text_data = text;
998#ifndef QT_NO_ACCEL
999 if ( !mi->accel_key && text.find( '\t' ) != -1 )
1000 mi->accel_key = Qt::Key_unknown;
1001#endif
1002 parent->menuContentsChanged();
1003 }
1004}
1005
1006/*!
1007 \overload
1008
1009 Changes the pixmap of the menu item \a id to the pixmap \a pixmap.
1010 If the item has an icon, the icon is unchanged.
1011
1012 \sa pixmap()
1013*/
1014
1015void QMenuData::changeItem( int id, const QPixmap &pixmap )
1016{
1017 QMenuData *parent;
1018 QMenuItem *mi = findItem( id, &parent );
1019 if ( mi ) { // item found
1020 register QPixmap *i = mi->pixmap_data;
1021 bool fast_refresh = i != 0 &&
1022 i->width() == pixmap.width() &&
1023 i->height() == pixmap.height() &&
1024 !mi->text();
1025 if ( !mi->text_data.isNull() ) // delete text
1026 mi->text_data = QString::null;
1027 if ( !pixmap.isNull() )
1028 mi->pixmap_data = new QPixmap( pixmap );
1029 else
1030 mi->pixmap_data = 0;
1031 delete i; // old mi->pixmap_data, could be &pixmap
1032 if ( fast_refresh )
1033 parent->updateItem( id );
1034 else
1035 parent->menuContentsChanged();
1036 }
1037}
1038
1039/*!
1040 \overload
1041
1042 Changes the iconset and text of the menu item \a id to the \a icon
1043 and \a text respectively.
1044
1045 \sa pixmap()
1046*/
1047
1048void QMenuData::changeItem( int id, const QIconSet &icon, const QString &text )
1049{
1050 changeItem( id, text );
1051 changeItemIconSet( id, icon );
1052}
1053
1054/*!
1055 \overload
1056
1057 Changes the iconset and pixmap of the menu item \a id to \a icon
1058 and \a pixmap respectively.
1059
1060 \sa pixmap()
1061*/
1062
1063void QMenuData::changeItem( int id, const QIconSet &icon, const QPixmap &pixmap )
1064{
1065 changeItem( id, pixmap );
1066 changeItemIconSet( id, icon );
1067}
1068
1069
1070
1071/*!
1072 Changes the icon of the menu item \a id to \a icon.
1073
1074 \sa pixmap()
1075*/
1076
1077void QMenuData::changeItemIconSet( int id, const QIconSet &icon )
1078{
1079 QMenuData *parent;
1080 QMenuItem *mi = findItem( id, &parent );
1081 if ( mi ) { // item found
1082 register QIconSet *i = mi->iconset_data;
1083 bool fast_refresh = i != 0;
1084 if ( !icon.isNull() )
1085 mi->iconset_data = new QIconSet( icon );
1086 else
1087 mi->iconset_data = 0;
1088 delete i; // old mi->iconset_data, could be &icon
1089 if ( fast_refresh )
1090 parent->updateItem( id );
1091 else
1092 parent->menuContentsChanged();
1093 }
1094}
1095
1096
1097/*!
1098 Returns TRUE if the item with identifier \a id is enabled;
1099 otherwise returns FALSE
1100
1101 \sa setItemEnabled(), isItemVisible()
1102*/
1103
1104bool QMenuData::isItemEnabled( int id ) const
1105{
1106 QMenuItem *mi = findItem( id );
1107 return mi ? mi->isEnabled() : FALSE;
1108}
1109
1110/*!
1111 If \a enable is TRUE, enables the menu item with identifier \a id;
1112 otherwise disables the menu item with identifier \a id.
1113
1114 \sa isItemEnabled()
1115*/
1116
1117void QMenuData::setItemEnabled( int id, bool enable )
1118{
1119 QMenuData *parent;
1120 QMenuItem *mi = findItem( id, &parent );
1121 if ( mi && (bool)mi->is_enabled != enable ) {
1122 mi->is_enabled = enable;
1123#if !defined(QT_NO_ACCEL) && !defined(QT_NO_POPUPMENU)
1124 if ( mi->popup() )
1125 mi->popup()->enableAccel( enable );
1126#endif
1127 parent->menuStateChanged();
1128 }
1129}
1130
1131
1132/*!
1133 Returns TRUE if the menu item with the id \a id is currently
1134 active; otherwise returns FALSE.
1135*/
1136bool QMenuData::isItemActive( int id ) const
1137{
1138 if ( actItem == -1 )
1139 return FALSE;
1140 return indexOf( id ) == actItem;
1141}
1142
1143/*!
1144 Returns TRUE if the menu item with the id \a id has been checked;
1145 otherwise returns FALSE.
1146
1147 \sa setItemChecked()
1148*/
1149
1150bool QMenuData::isItemChecked( int id ) const
1151{
1152 QMenuItem *mi = findItem( id );
1153 return mi ? mi->isChecked() : FALSE;
1154}
1155
1156/*!
1157 If \a check is TRUE, checks the menu item with id \a id; otherwise
1158 unchecks the menu item with id \a id. Calls
1159 QPopupMenu::setCheckable( TRUE ) if necessary.
1160
1161 \sa isItemChecked()
1162*/
1163
1164void QMenuData::setItemChecked( int id, bool check )
1165{
1166 QMenuData *parent;
1167 QMenuItem *mi = findItem( id, &parent );
1168 if ( mi && (bool)mi->is_checked != check ) {
1169 mi->is_checked = check;
1170#ifndef QT_NO_POPUPMENU
1171 if ( parent->isPopupMenu && !((QPopupMenu *)parent)->isCheckable() )
1172 ((QPopupMenu *)parent)->setCheckable( TRUE );
1173#endif
1174 parent->menuStateChanged();
1175 }
1176}
1177
1178/*!
1179 Returns TRUE if the menu item with the id \a id is visible;
1180 otherwise returns FALSE.
1181
1182 \sa setItemVisible()
1183*/
1184
1185bool QMenuData::isItemVisible( int id ) const
1186{
1187 QMenuItem *mi = findItem( id );
1188 return mi ? mi->isVisible() : FALSE;
1189}
1190
1191/*!
1192 If \a visible is TRUE, shows the menu item with id \a id; otherwise
1193 hides the menu item with id \a id.
1194
1195 \sa isItemVisible(), isItemEnabled()
1196*/
1197
1198void QMenuData::setItemVisible( int id, bool visible )
1199{
1200 QMenuData *parent;
1201 QMenuItem *mi = findItem( id, &parent );
1202 if ( mi && (bool)mi->is_visible != visible ) {
1203 mi->is_visible = visible;
1204 parent->menuContentsChanged();
1205 }
1206}
1207
1208
1209/*!
1210 Returns the menu item with identifier \a id, or 0 if there is no
1211 item with this identifier.
1212
1213 Note that QMenuItem is an internal class, and that you should not
1214 need to call this function. Use the higher level functions like
1215 text(), pixmap() and changeItem() to get and modify menu item
1216 attributes instead.
1217
1218 \sa indexOf()
1219*/
1220
1221QMenuItem *QMenuData::findItem( int id ) const
1222{
1223 return findItem( id, 0 );
1224}
1225
1226
1227/*!
1228 \overload
1229
1230 Returns the menu item with identifier \a id, or 0 if there is no
1231 item with this identifier. Changes \a *parent to point to the
1232 parent of the return value.
1233
1234 Note that QMenuItem is an internal class, and that you should not
1235 need to call this function. Use the higher level functions like
1236 text(), pixmap() and changeItem() to get and modify menu item
1237 attributes instead.
1238
1239 \sa indexOf()
1240*/
1241
1242QMenuItem * QMenuData::findItem( int id, QMenuData ** parent ) const
1243{
1244 if ( parent )
1245 *parent = (QMenuData *)this; // ###
1246
1247 if ( id == -1 ) // bad identifier
1248 return 0;
1249 QMenuItemListIt it( *mitems );
1250 QMenuItem *mi;
1251 while ( (mi=it.current()) ) { // search this menu
1252 ++it;
1253 if ( mi->ident == id ) // found item
1254 return mi;
1255 }
1256 it.toFirst();
1257 while ( (mi=it.current()) ) { // search submenus
1258 ++it;
1259#ifndef QT_NO_POPUPMENU
1260 if ( mi->popup_menu ) {
1261 QPopupMenu *p = mi->popup_menu;
1262 if (!p->avoid_circularity) {
1263 p->avoid_circularity = 1;
1264 mi = mi->popup_menu->findItem( id, parent );
1265 p->avoid_circularity = 0;
1266 if ( mi ) // found item
1267 return mi;
1268 }
1269 }
1270#endif
1271 }
1272 return 0; // not found
1273}
1274
1275/*!
1276 Returns the index of the menu item with identifier \a id, or -1 if
1277 there is no item with this identifier.
1278
1279 \sa idAt(), findItem()
1280*/
1281
1282int QMenuData::indexOf( int id ) const
1283{
1284 if ( id == -1 ) // bad identifier
1285 return -1;
1286 QMenuItemListIt it( *mitems );
1287 QMenuItem *mi;
1288 int index = 0;
1289 while ( (mi=it.current()) ) {
1290 if ( mi->ident == id ) // this one?
1291 return index;
1292 ++index;
1293 ++it;
1294 }
1295 return -1; // not found
1296}
1297
1298/*!
1299 Returns the identifier of the menu item at position \a index in
1300 the internal list, or -1 if \a index is out of range.
1301
1302 \sa setId(), indexOf()
1303*/
1304
1305int QMenuData::idAt( int index ) const
1306{
1307 return index < (int)mitems->count() && index >= 0 ?
1308 mitems->at(index)->id() : -1;
1309}
1310
1311/*!
1312 Sets the menu identifier of the item at \a index to \a id.
1313
1314 If \a index is out of range, the operation is ignored.
1315
1316 \sa idAt()
1317*/
1318
1319void QMenuData::setId( int index, int id )
1320{
1321 if ( index < (int)mitems->count() )
1322 mitems->at(index)->ident = id;
1323}
1324
1325
1326/*!
1327 Sets the parameter of the activation signal of item \a id to \a
1328 param.
1329
1330 If any receiver takes an integer parameter, this value is passed.
1331
1332 \sa connectItem(), disconnectItem(), itemParameter()
1333*/
1334bool QMenuData::setItemParameter( int id, int param ) {
1335 QMenuItem *mi = findItem( id );
1336 if ( !mi ) // no such identifier
1337 return FALSE;
1338 if ( !mi->signal_data ) { // create new signal
1339 mi->signal_data = new QSignal;
1340 Q_CHECK_PTR( mi->signal_data );
1341 }
1342 mi->signal_data->setValue( param );
1343 return TRUE;
1344}
1345
1346
1347/*!
1348 Returns the parameter of the activation signal of item \a id.
1349
1350 If no parameter has been specified for this item with
1351 setItemParameter(), the value defaults to \a id.
1352
1353 \sa connectItem(), disconnectItem(), setItemParameter()
1354*/
1355int QMenuData::itemParameter( int id ) const
1356{
1357 QMenuItem *mi = findItem( id );
1358 if ( !mi || !mi->signal_data )
1359 return id;
1360 return mi->signal_data->value().toInt();
1361}
1362
1363
1364/*!
1365 Connects the menu item with identifier \a id to \a{receiver}'s \a
1366 member slot or signal.
1367
1368 The receiver's slot (or signal) is activated when the menu item is
1369 activated.
1370
1371 \sa disconnectItem(), setItemParameter()
1372*/
1373
1374bool QMenuData::connectItem( int id, const QObject *receiver,
1375 const char* member )
1376{
1377 QMenuItem *mi = findItem( id );
1378 if ( !mi ) // no such identifier
1379 return FALSE;
1380 if ( !mi->signal_data ) { // create new signal
1381 mi->signal_data = new QSignal;
1382 Q_CHECK_PTR( mi->signal_data );
1383 mi->signal_data->setValue( id );
1384 }
1385 return mi->signal_data->connect( receiver, member );
1386}
1387
1388
1389/*!
1390 Disconnects the \a{receiver}'s \a member from the menu item with
1391 identifier \a id.
1392
1393 All connections are removed when the menu data object is
1394 destroyed.
1395
1396 \sa connectItem(), setItemParameter()
1397*/
1398
1399bool QMenuData::disconnectItem( int id, const QObject *receiver,
1400 const char* member )
1401{
1402 QMenuItem *mi = findItem( id );
1403 if ( !mi || !mi->signal_data ) // no identifier or no signal
1404 return FALSE;
1405 return mi->signal_data->disconnect( receiver, member );
1406}
1407
1408/*!
1409 Sets \a text as What's This help for the menu item with identifier
1410 \a id.
1411
1412 \sa whatsThis()
1413*/
1414void QMenuData::setWhatsThis( int id, const QString& text )
1415{
1416
1417 QMenuData *parent;
1418 QMenuItem *mi = findItem( id, &parent );
1419 if ( mi ) {
1420 mi->setWhatsThis( text );
1421 parent->menuContentsChanged();
1422 }
1423}
1424
1425/*!
1426 Returns the What's This help text for the item with identifier \a
1427 id or QString::null if no text has yet been defined.
1428
1429 \sa setWhatsThis()
1430*/
1431QString QMenuData::whatsThis( int id ) const
1432{
1433
1434 QMenuItem *mi = findItem( id );
1435 return mi? mi->whatsThis() : QString::null;
1436}
1437
1438
1439
1440/*!
1441 \class QCustomMenuItem qmenudata.h
1442 \brief The QCustomMenuItem class is an abstract base class for custom menu items in popup menus.
1443
1444 \ingroup misc
1445
1446 A custom menu item is a menu item that is defined by two pure
1447 virtual functions, paint() and sizeHint(). The size hint tells the
1448 menu how much space it needs to reserve for this item, and paint
1449 is called whenever the item needs painting.
1450
1451 This simple mechanism allows you to create all kinds of
1452 application specific menu items. Examples are items showing
1453 different fonts in a word processor or menus that allow the
1454 selection of drawing utilities in a vector drawing program.
1455
1456 A custom item is inserted into a popup menu with
1457 QPopupMenu::insertItem().
1458
1459 By default, a custom item can also have an icon and a keyboard
1460 accelerator. You can reimplement fullSpan() to return TRUE if you
1461 want the item to span the entire popup menu width. This is
1462 particularly useful for labels.
1463
1464 If you want the custom item to be treated just as a separator,
1465 reimplement isSeparator() to return TRUE.
1466
1467 Note that you can insert pixmaps or bitmaps as items into a popup
1468 menu without needing to create a QCustomMenuItem. However, custom
1469 menu items offer more flexibility, and -- especially important
1470 with Windows style -- provide the possibility of drawing the item
1471 with a different color when it is highlighted.
1472
1473 \link menu-example.html menu/menu.cpp\endlink shows a simple
1474 example how custom menu items can be used.
1475
1476 Note: the current implementation of QCustomMenuItem will not
1477 recognize shortcut keys that are from text with ampersands. Normal
1478 accelerators work though.
1479
1480 <img src=qpopmenu-fancy.png>
1481
1482 \sa QMenuData, QPopupMenu
1483*/
1484
1485
1486
1487/*!
1488 Constructs a QCustomMenuItem
1489*/
1490QCustomMenuItem::QCustomMenuItem()
1491{
1492}
1493
1494/*!
1495 Destroys a QCustomMenuItem
1496*/
1497QCustomMenuItem::~QCustomMenuItem()
1498{
1499}
1500
1501
1502/*!
1503 Sets the font of the custom menu item to \a font.
1504
1505 This function is called whenever the font in the popup menu
1506 changes. For menu items that show their own individual font entry,
1507 you want to ignore this.
1508*/
1509void QCustomMenuItem::setFont( const QFont& /* font */ )
1510{
1511}
1512
1513
1514
1515/*!
1516 Returns TRUE if this item wants to span the entire popup menu
1517 width; otherwise returns FALSE. The default is FALSE, meaning that
1518 the menu may show an icon and an accelerator key for this item as
1519 well.
1520*/
1521bool QCustomMenuItem::fullSpan() const
1522{
1523 return FALSE;
1524}
1525
1526/*!
1527 Returns TRUE if this item is just a separator; otherwise returns
1528 FALSE.
1529*/
1530bool QCustomMenuItem::isSeparator() const
1531{
1532 return FALSE;
1533}
1534
1535
1536/*!
1537 \fn void QCustomMenuItem::paint( QPainter* p, const QColorGroup& cg, bool act, bool enabled, int x, int y, int w, int h );
1538
1539 Paints this item. When this function is invoked, the painter \a p
1540 is set to a font and foreground color suitable for a menu item
1541 text using color group \a cg. The item is active if \a act is TRUE
1542 and enabled if \a enabled is TRUE. The geometry values \a x, \a y,
1543 \a w and \a h specify where to draw the item.
1544
1545 Do not draw any background, this has already been done by the
1546 popup menu according to the current GUI style.
1547*/
1548
1549
1550/*!
1551 \fn QSize QCustomMenuItem::sizeHint();
1552
1553 Returns the item's size hint.
1554*/
1555
1556
1557
1558/*!
1559 Activates the menu item at position \a index.
1560
1561 If the index is invalid (for example, -1), the object itself is
1562 deactivated.
1563*/
1564void QMenuData::activateItemAt( int index )
1565{
1566#ifndef QT_NO_MENUBAR
1567 if ( isMenuBar )
1568 ( (QMenuBar*)this )->activateItemAt( index );
1569 else
1570#endif
1571 {
1572#ifndef QT_NO_POPUPMENU
1573 if ( isPopupMenu )
1574 ( (QPopupMenu*)this )->activateItemAt( index );
1575#endif
1576 }
1577}
1578
1579#endif
Note: See TracBrowser for help on using the repository browser.