source: trunk/src/qt3support/widgets/q3combobox.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 60.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the Qt3Support module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "q3combobox.h"
43#ifndef QT_NO_COMBOBOX
44#include "qpainter.h"
45#include "qdrawutil.h"
46#include "qpixmap.h"
47#include "qtimer.h"
48#include "qapplication.h"
49#include "qlineedit.h"
50#include "qbitmap.h"
51#include "qstringlist.h"
52#include "qstyle.h"
53#include "qevent.h"
54#include "qmenu.h"
55#include "qmenudata.h"
56#include "qstyleoption.h"
57#include "qdesktopwidget.h"
58#include "q3popupmenu.h"
59#include "q3listbox.h"
60#include "q3strlist.h"
61#include "q3frame.h"
62#include <limits.h>
63#include <qdebug.h>
64#ifndef QT_NO_EFFECTS
65# include <private/qeffects_p.h>
66#endif
67#if defined(QT_ACCESSIBILITY_SUPPORT)
68#include "qaccessible.h"
69#endif
70
71QT_BEGIN_NAMESPACE
72
73/*!
74 \class Q3ComboBox
75 \brief The Q3ComboBox widget is a combined button and popup list.
76 \since 4.1
77 \compat
78
79 A combobox is a selection widget which displays the current item
80 and can pop up a list of items. A combobox may be editable in
81 which case the user can enter arbitrary strings.
82
83 Comboboxes provide a means of showing the user's current choice
84 out of a list of options in a way that takes up the minimum amount
85 of screen space.
86
87 Q3ComboBox supports three different display styles: Aqua/Motif 1.x,
88 Motif 2.0 and Windows. In Motif 1.x, a combobox was called
89 XmOptionMenu. In Motif 2.0, OSF introduced an improved combobox
90 and named that XmComboBox. Q3ComboBox provides both.
91
92 Q3ComboBox provides two different constructors. The simplest
93 constructor creates an "old-style" combobox in Motif (or Aqua)
94 style:
95 \snippet doc/src/snippets/code/src_qt3support_widgets_q3combobox.cpp 0
96
97 The other constructor creates a new-style combobox in Motif style,
98 and can create both read-only and editable comboboxes:
99 \snippet doc/src/snippets/code/src_qt3support_widgets_q3combobox.cpp 1
100
101 New-style comboboxes use a list box in both Motif and Windows
102 styles, and both the content size and the on-screen size of the
103 list box can be limited with sizeLimit() and setMaxCount()
104 respectively. Old-style comboboxes use a popup in Aqua and Motif
105 style, and that popup will happily grow larger than the desktop if
106 you put enough data into it.
107
108 The two constructors create identical-looking comboboxes in
109 Windows style.
110
111 Comboboxes can contain pixmaps as well as strings; the
112 insertItem() and changeItem() functions are suitably overloaded.
113 For editable comboboxes, the function clearEdit() is provided,
114 to clear the displayed string without changing the combobox's
115 contents.
116
117 A combobox emits two signals, activated() and highlighted(), when
118 a new item has been activated (selected) or highlighted (made
119 current). Both signals exist in two versions, one with a \c
120 QString argument and one with an \c int argument. If the user
121 highlights or activates a pixmap, only the \c int signals are
122 emitted. Whenever the text of an editable combobox is changed the
123 textChanged() signal is emitted.
124
125 When the user enters a new string in an editable combobox, the
126 widget may or may not insert it, and it can insert it in several
127 locations. The default policy is is \c AtBottom but you can change
128 this using setInsertionPolicy().
129
130 It is possible to constrain the input to an editable combobox
131 using QValidator; see setValidator(). By default, any input is
132 accepted.
133
134 If the combobox is not editable then it has a default
135 focusPolicy() of \c TabFocus, i.e. it will not grab focus if
136 clicked. This differs from both Windows and Motif. If the combobox
137 is editable then it has a default focusPolicy() of \c StrongFocus,
138 i.e. it will grab focus if clicked.
139
140 A combobox can be populated using the insert functions,
141 insertStringList() and insertItem() for example. Items can be
142 changed with changeItem(). An item can be removed with
143 removeItem() and all items can be removed with clear(). The text
144 of the current item is returned by currentText(), and the text of
145 a numbered item is returned with text(). The current item can be
146 set with setCurrentItem() or setCurrentText(). The number of items
147 in the combobox is returned by count(); the maximum number of
148 items can be set with setMaxCount(). You can allow editing using
149 setEditable(). For editable comboboxes you can set auto-completion
150 using setAutoCompletion() and whether or not the user can add
151 duplicates is set with setDuplicatesEnabled().
152
153 Depending on the style, Q3ComboBox will use a list box or a
154 popup menu to display the list of items. See setListBox() for
155 more information.
156
157 \sa QComboBox, QLineEdit, QSpinBox
158 {GUI Design Handbook}{GUI Design Handbook: Combo Box, Drop-Down List Box}
159*/
160
161
162/*!
163 \enum Q3ComboBox::Policy
164
165 This enum specifies what the Q3ComboBox should do when a new string
166 is entered by the user.
167
168 \value NoInsertion the string will not be inserted into the
169 combobox.
170
171 \value AtTop insert the string as the first item in the combobox.
172
173 \value AtCurrent replace the previously selected item with the
174 string the user has entered.
175
176 \value AtBottom insert the string as the last item in the
177 combobox.
178
179 \value AfterCurrent insert the string after the previously
180 selected item.
181
182 \value BeforeCurrent insert the string before the previously
183 selected item.
184
185 activated() is always emitted when the string is entered.
186
187 If inserting the new string would cause the combobox to breach its
188 content size limit, the item at the other end of the list is
189 deleted. The definition of "other end" is
190 implementation-dependent.
191
192 \omitvalue NoInsert
193 \omitvalue InsertAtTop
194 \omitvalue InsertAtCurrent
195 \omitvalue InsertAtBottom
196 \omitvalue InsertAfterCurrent
197 \omitvalue InsertBeforeCurrent
198*/
199
200
201/*!
202 \fn void Q3ComboBox::activated( int index )
203
204 This signal is emitted when a new item has been activated
205 (selected). The \a index is the position of the item in the
206 combobox.
207
208 This signal is not emitted if the item is changed
209 programmatically, e.g. using setCurrentItem().
210*/
211
212/*!
213 \overload
214 \fn void Q3ComboBox::activated( const QString &string )
215
216 This signal is emitted when a new item has been activated
217 (selected). \a string is the selected string.
218
219 You can also use the activated(int) signal, but be aware that its
220 argument is meaningful only for selected strings, not for user
221 entered strings.
222*/
223
224/*!
225 \fn void Q3ComboBox::highlighted( int index )
226
227 This signal is emitted when a new item has been set to be the
228 current item. The \a index is the position of the item in the
229 combobox.
230
231 This signal is not emitted if the item is changed
232 programmatically, e.g. using setCurrentItem().
233*/
234
235/*!
236 \overload
237 \fn void Q3ComboBox::highlighted( const QString &string )
238
239 This signal is emitted when a new item has been set to be the
240 current item. \a string is the item's text.
241
242 You can also use the highlighted(int) signal.
243*/
244
245/*!
246 \fn void Q3ComboBox::textChanged( const QString &string )
247
248 This signal is used for editable comboboxes. It is emitted
249 whenever the contents of the text entry field changes. \a string
250 contains the new text.
251*/
252
253/*!
254 \property Q3ComboBox::autoCompletion
255 \brief whether auto-completion is enabled
256
257 This property can only be set for editable comboboxes, for
258 non-editable comboboxes it has no effect. It is false by default.
259*/
260
261/*!
262 \property Q3ComboBox::autoResize
263 \brief whether auto-resize is enabled
264 \obsolete
265
266 If this property is set to true then the combobox will resize
267 itself whenever its contents change. The default is false.
268*/
269
270/*!
271 \property Q3ComboBox::count
272 \brief the number of items in the combobox
273*/
274
275/*!
276 \property Q3ComboBox::currentItem
277 \brief the index of the current item in the combobox
278
279 Note that the activated() and highlighted() signals are only
280 emitted when the user changes the current item, not when it is
281 changed programmatically.
282*/
283
284/*!
285 \property Q3ComboBox::currentText
286 \brief the text of the combobox's current item
287*/
288
289/*!
290 \property Q3ComboBox::duplicatesEnabled
291 \brief whether duplicates are allowed
292
293 If the combobox is editable and the user enters some text in the
294 combobox's lineedit and presses Enter (and the insertionPolicy()
295 is not \c NoInsertion), then what happens is this:
296 \list
297 \i If the text is not already in the list, the text is inserted.
298 \i If the text is in the list and this property is true (the
299 default), the text is inserted.
300 \i If the text is in the list and this property is false, the text
301 is \e not inserted; instead the item which has matching text becomes
302 the current item.
303 \endlist
304
305 This property only affects user-interaction. You can use
306 insertItem() to insert duplicates if you wish regardless of this
307 setting.
308*/
309
310/*!
311 \property Q3ComboBox::editable
312 \brief whether the combobox is editable
313
314 This property's default is false. Note that the combobox will be
315 cleared if this property is set to true for a 1.x Motif style
316 combobox. To avoid this, use setEditable() before inserting any
317 items. Also note that the 1.x version of Motif didn't have any
318 editable comboboxes, so the combobox will change its appearance
319 to a 2.0 style Motif combobox is it is set to be editable.
320*/
321
322/*!
323 \property Q3ComboBox::insertionPolicy
324 \brief the position of the items inserted by the user
325
326 The default insertion policy is \c AtBottom. See \l Policy.
327*/
328
329/*!
330 \property Q3ComboBox::maxCount
331 \brief the maximum number of items allowed in the combobox
332*/
333
334/*!
335 \property Q3ComboBox::sizeLimit
336 \brief the maximum on-screen size of the combobox.
337
338 This property is ignored for both Motif 1.x style and non-editable
339 comboboxes in Mac style. The default limit is ten
340 lines. If the number of items in the combobox is or grows larger
341 than lines, a scroll bar is added.
342*/
343
344class Q3ComboBoxPopup : public Q3PopupMenu
345{
346public:
347 Q3ComboBoxPopup( QWidget *parent=0, const char *name=0 )
348 : Q3PopupMenu( parent, name )
349 {
350 }
351
352 int itemHeight( int index )
353 {
354 return Q3PopupMenu::itemHeight( index );
355 }
356};
357
358static inline QString escapedComboString(const QString &str)
359{
360 QString stringToReturn = str;
361 return stringToReturn.replace(QLatin1Char('&'), QLatin1String("&&"));
362}
363
364class Q3ComboBoxPopupItem : public QMenuItem
365{
366 Q3ListBoxItem *li;
367 QSize sc; // Size cache optimization
368public:
369 Q3ComboBoxPopupItem(Q3ListBoxItem *i) : QMenuItem(), li(i), sc(0, 0) { }
370 virtual bool fullSpan() const { return true; }
371 virtual void paint( QPainter*, const QColorGroup&, bool, bool, int, int, int, int);
372 virtual QSize sizeHint() { if (sc.isNull()) sc = QSize(li->width(li->listBox()), QMAX(25, li->height(li->listBox()))); return sc; }
373};
374void Q3ComboBoxPopupItem::paint( QPainter* p, const QColorGroup&, bool,
375 bool, int x, int y, int, int)
376{
377 p->save();
378 p->translate(x, y + ((sizeHint().height() / 2) - (li->height(li->listBox()) / 2)));
379 li->paint(p);
380 p->restore();
381}
382
383
384class Q3ComboBoxData
385{
386public:
387 Q3ComboBoxData( Q3ComboBox *cb ): current( 0 ), arrowDown(false), ed( 0 ), usingLBox( false ), pop( 0 ), lBox( 0 ), combo( cb )
388 {
389 duplicatesEnabled = true;
390 cb->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed ) );
391 }
392
393 inline bool usingListBox() { return usingLBox; }
394 inline Q3ListBox * listBox() { return lBox; }
395 inline Q3ComboBoxPopup * popup() { return pop; }
396 void updateLinedGeometry();
397
398 void setListBox( Q3ListBox *l ) { lBox = l ; usingLBox = true;
399 l->setMouseTracking( true );}
400
401 void setPopupMenu( Q3ComboBoxPopup * pm, bool isPopup=true )
402 { pop = pm; if(isPopup) usingLBox = false; }
403
404 QStyleOptionComboBox getStyleOption() const
405 {
406 QStyleOptionComboBox opt;
407 opt.init(combo);
408 if (!combo->editable() && combo->hasFocus())
409 opt.state |= QStyle::State_Selected;
410 opt.subControls = QStyle::SC_All;
411 if (arrowDown) {
412 opt.activeSubControls = QStyle::SC_ComboBoxArrow;
413 opt.state |= QStyle::State_Sunken;
414 }
415 opt.editable = combo->editable();
416 opt.frame = 1; // ### get from style?
417 if (current > -1 && current < combo->count()) {
418 opt.currentText = combo->text(current);
419 if (combo->pixmap(current))
420 opt.currentIcon = QIcon(*combo->pixmap(current));
421 }
422 opt.iconSize = QSize(22, 22); // ### need a sane value here
423// if (container && container->isVisible())
424// opt.state |= QStyle::State_On;
425 return opt;
426 }
427
428 int current;
429 int maxCount;
430 int sizeLimit;
431 Q3ComboBox::Policy p;
432 bool autoresize;
433 bool poppedUp;
434 bool mouseWasInsidePopup;
435 bool arrowPressed;
436 bool arrowDown;
437 bool discardNextMousePress;
438 bool shortClick;
439 bool useCompletion;
440 bool completeNow;
441 int completeAt;
442 bool duplicatesEnabled;
443 int fullHeight, currHeight;
444
445 QLineEdit * ed; // /bin/ed rules!
446 QTimer *completionTimer;
447
448 QSize sizeHint;
449 QHash<int, QPixmap> popupPixmaps;
450
451private:
452 bool usingLBox;
453 Q3ComboBoxPopup *pop;
454 Q3ListBox *lBox;
455 Q3ComboBox *combo;
456};
457
458void Q3ComboBoxData::updateLinedGeometry()
459{
460 if ( !ed || !combo )
461 return;
462
463 QStyleOptionComboBox opt = getStyleOption();
464 QRect r = combo->style()->subControlRect(
465 QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, combo);
466
467 const QPixmap *pix = current < combo->count() ? combo->pixmap( current ) : 0;
468 if ( pix && pix->width() < r.width() )
469 r.setLeft( r.left() + pix->width() + 4 );
470 if ( r != ed->geometry() )
471 ed->setGeometry( r );
472}
473
474static inline bool checkInsertIndex( const char *method, const char * name,
475 int count, int *index)
476{
477 bool range_err = (*index > count);
478#if defined(QT_CHECK_RANGE)
479 if ( range_err )
480 qWarning( "Q3ComboBox::%s: (%s) Index %d out of range",
481 method, name ? name : "<no name>", *index );
482#else
483 Q_UNUSED( method )
484 Q_UNUSED( name )
485#endif
486 if ( *index < 0 ) // append
487 *index = count;
488 return !range_err;
489}
490
491
492static inline bool checkIndex( const char *method, const char * name,
493 int count, int index )
494{
495 bool range_err = (index >= count);
496#if defined(QT_CHECK_RANGE)
497 if ( range_err )
498 qWarning( "Q3ComboBox::%s: (%s) Index %i out of range",
499 method, name ? name : "<no name>", index );
500#else
501 Q_UNUSED( method )
502 Q_UNUSED( name )
503#endif
504 return !range_err;
505}
506
507
508
509/*!
510 Constructs a combobox widget with parent \a parent called \a name.
511
512 This constructor creates a popup list if the program uses Motif
513 (or Aqua) look and feel; this is compatible with Motif 1.x and
514 Aqua.
515
516 Note: If you use this constructor to create your Q3ComboBox, then
517 the pixmap() function will always return 0. To workaround this,
518 use the other constructor.
519
520*/
521
522
523
524Q3ComboBox::Q3ComboBox( QWidget *parent, const char *name )
525 : QWidget( parent, name, Qt::WNoAutoErase )
526{
527 d = new Q3ComboBoxData( this );
528 QStyleOptionComboBox opt;
529 opt.init(this);
530 if ( style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this) ||
531 style()->styleHint(QStyle::SH_GUIStyle, &opt, this) == Qt::MotifStyle ) {
532 d->setPopupMenu( new Q3ComboBoxPopup( this, "in-combo" ) );
533 d->popup()->setFont( font() );
534 connect( d->popup(), SIGNAL(activated(int)),
535 SLOT(internalActivate(int)) );
536 connect( d->popup(), SIGNAL(highlighted(int)),
537 SLOT(internalHighlight(int)) );
538 } else {
539 setUpListBox();
540 }
541 d->ed = 0;
542 d->current = 0;
543 d->maxCount = INT_MAX;
544 d->sizeLimit = 10;
545 d->p = AtBottom;
546 d->autoresize = false;
547 d->poppedUp = false;
548 d->arrowDown = false;
549 d->arrowPressed = false;
550 d->discardNextMousePress = false;
551 d->shortClick = false;
552 d->useCompletion = false;
553 d->completeAt = 0;
554 d->completeNow = false;
555 d->completionTimer = new QTimer( this );
556
557 setFocusPolicy( Qt::TabFocus );
558 setBackgroundMode( Qt::PaletteButton );
559}
560
561
562/*!
563 Constructs a combobox with a maximum size and either Motif 2.0 or
564 Windows look and feel.
565
566 The input field can be edited if \a rw is true, otherwise the user
567 may only choose one of the items in the combobox.
568
569 The \a parent and \a name arguments are passed on to the QWidget
570 constructor.
571*/
572
573
574Q3ComboBox::Q3ComboBox( bool rw, QWidget *parent, const char *name )
575 : QWidget( parent, name, Qt::WNoAutoErase )
576{
577 d = new Q3ComboBoxData( this );
578 setUpListBox();
579
580 QStyleOptionComboBox opt = d->getStyleOption();
581 if(d->popup() && style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this))
582 d->popup()->setItemChecked(d->current, false);
583 d->maxCount = INT_MAX;
584 setSizeLimit(10);
585 d->p = AtBottom;
586 d->autoresize = false;
587 d->poppedUp = false;
588 d->arrowDown = false;
589 d->discardNextMousePress = false;
590 d->shortClick = false;
591 d->useCompletion = false;
592 d->completeAt = 0;
593 d->completeNow = false;
594 d->completionTimer = new QTimer( this );
595
596 setFocusPolicy( Qt::StrongFocus );
597
598 d->ed = 0;
599 if ( rw )
600 setUpLineEdit();
601 setBackgroundMode( Qt::PaletteButton, Qt::PaletteBase );
602}
603
604
605
606/*!
607 Destroys the combobox.
608*/
609
610Q3ComboBox::~Q3ComboBox()
611{
612 delete d;
613}
614
615void Q3ComboBox::setDuplicatesEnabled( bool enable )
616{
617 d->duplicatesEnabled = enable;
618}
619
620bool Q3ComboBox::duplicatesEnabled() const
621{
622 return d->duplicatesEnabled;
623}
624
625int Q3ComboBox::count() const
626{
627 if ( d->usingListBox() )
628 return d->listBox()->count();
629 else if (d->popup())
630 return d->popup()->count();
631 else
632 return 0;
633}
634
635
636/*!
637 \overload
638
639 Inserts the \a list of strings at position \a index in the
640 combobox.
641
642 This is only for compatibility since it does not support Unicode
643 strings. See insertStringList().
644*/
645
646void Q3ComboBox::insertStrList( const Q3StrList &list, int index )
647{
648 insertStrList( &list, index );
649}
650
651/*!
652 \overload
653
654 Inserts the \a list of strings at position \a index in the
655 combobox.
656
657 This is only for compatibility since it does not support Unicode
658 strings. See insertStringList().
659*/
660
661void Q3ComboBox::insertStrList( const Q3StrList *list, int index )
662{
663 if ( !list ) {
664#if defined(QT_CHECK_NULL)
665 Q_ASSERT( list != 0 );
666#endif
667 return;
668 }
669 Q3StrListIterator it( *list );
670 const char* tmp;
671 if ( index < 0 )
672 index = count();
673 while ( (tmp=it.current()) ) {
674 ++it;
675 if ( d->usingListBox() )
676 d->listBox()->insertItem( QString::fromLatin1(tmp), index );
677 else
678 d->popup()->insertItem( escapedComboString(QString::fromLatin1(tmp)), index, index );
679 if ( index++ == d->current && d->current < count() ) {
680 if ( d->ed ) {
681 d->ed->setText( text( d->current ) );
682 d->updateLinedGeometry();
683 } else
684 update();
685 currentChanged();
686 }
687 }
688 if ( index != count() )
689 reIndex();
690}
691
692/*!
693 Inserts the \a list of strings at position \a index in the
694 combobox.
695*/
696
697void Q3ComboBox::insertStringList( const QStringList &list, int index )
698{
699 QStringList::ConstIterator it = list.begin();
700 if ( index < 0 )
701 index = count();
702 while ( it != list.end() ) {
703 if ( d->usingListBox() )
704 d->listBox()->insertItem( *it, index );
705 else
706 d->popup()->insertItem( escapedComboString(*it), index, index );
707 if ( index++ == d->current && d->current < count() ) {
708 if ( d->ed ) {
709 d->ed->setText( text( d->current ) );
710 d->updateLinedGeometry();
711 } else
712 update();
713 currentChanged();
714 }
715 ++it;
716 }
717 if ( index != count() )
718 reIndex();
719}
720
721/*!
722 Inserts the array of char * \a strings at position \a index in the
723 combobox.
724
725 The \a numStrings argument is the number of strings. If \a
726 numStrings is -1 (default), the \a strings array must be
727 terminated with 0.
728
729 Example:
730 \snippet doc/src/snippets/code/src_qt3support_widgets_q3combobox.cpp 2
731
732 \sa insertStringList()
733*/
734
735void Q3ComboBox::insertStrList( const char **strings, int numStrings, int index)
736{
737 if ( !strings ) {
738#if defined(QT_CHECK_NULL)
739 Q_ASSERT( strings != 0 );
740#endif
741 return;
742 }
743 if ( index < 0 )
744 index = count();
745 int i = 0;
746 while ( (numStrings<0 && strings[i]!=0) || i<numStrings ) {
747 if ( d->usingListBox() )
748 d->listBox()->insertItem( QString::fromLatin1(strings[i]), index );
749 else
750 d->popup()->insertItem( escapedComboString(QString::fromLatin1(strings[i])), index, index );
751 i++;
752 if ( index++ == d->current && d->current < count() ) {
753 if ( d->ed ) {
754 d->ed->setText( text( d->current ) );
755 d->updateLinedGeometry();
756 } else
757 update();
758 currentChanged();
759 }
760 }
761 if ( index != count() )
762 reIndex();
763}
764
765
766/*!
767 Inserts a text item with text \a t, at position \a index. The item
768 will be appended if \a index is negative.
769*/
770
771void Q3ComboBox::insertItem( const QString &t, int index )
772{
773 int cnt = count();
774 if ( !checkInsertIndex( "insertItem", name(), cnt, &index ) )
775 return;
776 if ( d->usingListBox() )
777 d->listBox()->insertItem( t, index );
778 else
779 d->popup()->insertItem( escapedComboString(t), index, index );
780 if ( index != cnt )
781 reIndex();
782 if ( index == d->current && d->current < count() ) {
783 if ( d->ed ) {
784 d->ed->setText( text( d->current ) );
785 d->updateLinedGeometry();
786 } else
787 update();
788 }
789 if ( index == d->current )
790 currentChanged();
791}
792
793/*!
794 \overload
795
796 Inserts a \a pixmap item at position \a index. The item will be
797 appended if \a index is negative.
798*/
799
800void Q3ComboBox::insertItem( const QPixmap &pixmap, int index )
801{
802 int cnt = count();
803 if ( !checkInsertIndex( "insertItem", name(), cnt, &index ) )
804 return;
805 if ( d->usingListBox() )
806 d->listBox()->insertItem( pixmap, index );
807 else
808 d->popup()->insertItem( pixmap, index, index );
809 if ( index != cnt )
810 reIndex();
811 if ( index == d->current && d->current < count() ) {
812 if ( d->ed ) {
813 d->ed->setText( text( d->current ) );
814 d->updateLinedGeometry();
815 } else
816 update();
817 }
818 if ( index == d->current )
819 currentChanged();
820}
821
822/*!
823 \overload
824
825 Inserts a \a pixmap item with additional text \a text at position
826 \a index. The item will be appended if \a index is negative.
827*/
828
829void Q3ComboBox::insertItem( const QPixmap &pixmap, const QString& text, int index )
830{
831 int cnt = count();
832 if ( !checkInsertIndex( "insertItem", name(), cnt, &index ) )
833 return;
834 if ( d->usingListBox() )
835 d->listBox()->insertItem( pixmap, text, index );
836 else
837 d->popup()->insertItem( pixmap, escapedComboString(text), index, index );
838 if ( index != cnt )
839 reIndex();
840 if ( index == d->current && d->current < count() ) {
841 if ( d->ed ) {
842 d->ed->setText( this->text( d->current ) );
843 d->updateLinedGeometry();
844 } else
845 update();
846 }
847 if ( index == d->current )
848 currentChanged();
849}
850
851
852/*!
853 Removes the item at position \a index.
854*/
855
856void Q3ComboBox::removeItem( int index )
857{
858 int cnt = count();
859 if ( !checkIndex( "removeItem", name(), cnt, index ) )
860 return;
861 if ( d->usingListBox() ) {
862 QStyleOptionComboBox opt = d->getStyleOption();
863 if ( style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this) && d->popup() )
864 d->popup()->removeItemAt( index );
865 d->listBox()->removeItem( index );
866 } else {
867 d->popup()->removeItemAt( index );
868 }
869 if ( index != cnt-1 )
870 reIndex();
871 if ( index == d->current ) {
872 if ( d->ed ) {
873 QString s = QString::fromLatin1("");
874 if (d->current < cnt - 1)
875 s = text( d->current );
876 d->ed->setText( s );
877 d->updateLinedGeometry();
878 }
879 else {
880 if ( d->usingListBox() ) {
881 d->current = d->listBox()->currentItem();
882 } else {
883 if (d->current > count()-1 && d->current > 0)
884 d->current--;
885 }
886 update();
887 }
888 currentChanged();
889 }
890 else {
891 if ( !d->ed ) {
892 if (d->current < cnt - 1)
893 setCurrentItem( d->current );
894 else
895 setCurrentItem( d->current - 1 );
896 }
897 }
898
899}
900
901
902/*!
903 Removes all combobox items.
904*/
905
906void Q3ComboBox::clear()
907{
908 QStyleOptionComboBox opt = d->getStyleOption();
909 if ( d->usingListBox() ) {
910 if ( style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this) && d->popup() )
911 d->popup()->clear();
912 d->listBox()->resize( 0, 0 );
913 d->listBox()->clear();
914 } else {
915 d->popup()->clear();
916 }
917
918 if(d->popup() && style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this))
919 d->popup()->setItemChecked(d->current, false);
920 d->current = 0;
921 if ( d->ed ) {
922 d->ed->setText( QString::fromLatin1("") );
923 d->updateLinedGeometry();
924 }
925 currentChanged();
926}
927
928
929QString Q3ComboBox::currentText() const
930{
931 if ( d->ed )
932 return d->ed->text();
933 else if ( d->current < count() )
934 return text( currentItem() );
935 else
936 return QString::null;
937}
938
939void Q3ComboBox::setCurrentText( const QString& txt )
940{
941 int i;
942 for ( i = 0; i < count(); i++)
943 if ( text( i ) == txt )
944 break;
945 if ( i < count() )
946 setCurrentItem( i );
947 else if ( d->ed )
948 d->ed->setText( txt );
949 else
950 changeItem( txt, currentItem() );
951}
952
953
954/*!
955 Returns the text item at position \a index, or QString::null if
956 the item is not a string.
957
958 \sa currentText()
959*/
960
961QString Q3ComboBox::text( int index ) const
962{
963 if ( !checkIndex( "text", name(), count(), index ) )
964 return QString::null;
965 if ( d->usingListBox() ) {
966 return d->listBox()->text( index );
967 } else {
968 QString retText = d->popup()->text(index);
969 retText.replace(QLatin1String("&&"), QString(QLatin1Char('&')));
970 return retText;
971 }
972}
973
974/*!
975 Returns the pixmap item at position \a index, or 0 if the item is
976 not a pixmap.
977*/
978
979const QPixmap *Q3ComboBox::pixmap( int index ) const
980{
981 if ( !checkIndex( "pixmap", name(), count(), index ) )
982 return 0;
983
984 if (d->usingListBox()) {
985 return d->listBox()->pixmap( index );
986 } else {
987 d->popupPixmaps[index] = d->popup()->pixmap(index);
988 return d->popupPixmaps[index].isNull() ? 0 : &d->popupPixmaps[index];
989 }
990}
991
992/*!
993 Replaces the item at position \a index with the text \a t.
994*/
995
996void Q3ComboBox::changeItem( const QString &t, int index )
997{
998 if ( !checkIndex( "changeItem", name(), count(), index ) )
999 return;
1000 if ( d->usingListBox() )
1001 d->listBox()->changeItem( t, index );
1002 else
1003 d->popup()->changeItem(index, t);
1004 if ( index == d->current ) {
1005 if ( d->ed ) {
1006 d->ed->setText( text( d->current ) );
1007 d->updateLinedGeometry();
1008 } else
1009 update();
1010 }
1011}
1012
1013/*!
1014 \overload
1015
1016 Replaces the item at position \a index with the pixmap \a im,
1017 unless the combobox is editable.
1018
1019 \sa insertItem()
1020*/
1021
1022void Q3ComboBox::changeItem( const QPixmap &im, int index )
1023{
1024 if ( !checkIndex( "changeItem", name(), count(), index ) )
1025 return;
1026 if ( d->usingListBox() )
1027 d->listBox()->changeItem( im, index );
1028 else
1029 d->popup()->changeItem(index, im);
1030 if ( index == d->current )
1031 update();
1032}
1033
1034/*!
1035 \overload
1036
1037 Replaces the item at position \a index with the pixmap \a im and
1038 the text \a t.
1039
1040 \sa insertItem()
1041*/
1042
1043void Q3ComboBox::changeItem( const QPixmap &im, const QString &t, int index )
1044{
1045 if ( !checkIndex( "changeItem", name(), count(), index ) )
1046 return;
1047 if ( d->usingListBox() )
1048 d->listBox()->changeItem( im, t, index );
1049 else
1050 d->popup()->changeItem(index, im, t);
1051 if ( index == d->current )
1052 update();
1053}
1054
1055
1056int Q3ComboBox::currentItem() const
1057{
1058 return d->current;
1059}
1060
1061void Q3ComboBox::setCurrentItem( int index )
1062{
1063 if ( index == d->current && !d->ed ) {
1064 return;
1065 }
1066 if ( !checkIndex( "setCurrentItem", name(), count(), index ) ) {
1067 return;
1068 }
1069
1070 if ( d->usingListBox() && !( listBox()->item(index) && listBox()->item(index)->isSelectable() ) )
1071 return;
1072
1073 QStyleOptionComboBox opt = d->getStyleOption();
1074 if(d->popup() && style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this))
1075 d->popup()->setItemChecked(d->current, false);
1076 d->current = index;
1077 d->completeAt = 0;
1078 if ( d->ed ) {
1079 d->ed->setText( text( index ) );
1080 d->updateLinedGeometry();
1081 }
1082 // ### We want to keep ListBox's currentItem in sync, even if NOT popuped...
1083 if ( d->usingListBox() && d->listBox() ) {
1084 d->listBox()->setCurrentItem( index );
1085 } else {
1086 internalHighlight( index );
1087 // internalActivate( index ); ### this leads to weird behavior, as in 3.0.1
1088 }
1089
1090 currentChanged();
1091}
1092
1093/*!
1094 Returns true if auto-resize is enabled; otherwise returns false.
1095
1096 \sa autoResize
1097*/
1098
1099bool Q3ComboBox::autoResize() const
1100{
1101 return d->autoresize;
1102}
1103
1104/*!
1105 If \a enable is true, enable auto-resize; disable it otherwise.
1106
1107 \sa autoResize
1108*/
1109
1110void Q3ComboBox::setAutoResize( bool enable )
1111{
1112 if ( (bool)d->autoresize != enable ) {
1113 d->autoresize = enable;
1114 if ( enable )
1115 adjustSize();
1116 }
1117}
1118
1119
1120/*!
1121 \reimp
1122
1123 This implementation caches the size hint to avoid resizing when
1124 the contents change dynamically. To invalidate the cached value
1125 call setFont().
1126*/
1127QSize Q3ComboBox::sizeHint() const
1128{
1129 if ( isVisible() && d->sizeHint.isValid() )
1130 return d->sizeHint;
1131
1132 constPolish();
1133 int i, w;
1134 QFontMetrics fm = fontMetrics();
1135
1136 int maxW = count() ? 18 : 7 * fm.width(QLatin1Char('x')) + 18;
1137 int maxH = QMAX( fm.lineSpacing(), 14 ) + 2;
1138
1139 if ( !d->usingListBox() ) {
1140 w = d->popup()->sizeHint().width() - 2* d->popup()->frameWidth();
1141 if ( w > maxW )
1142 maxW = w;
1143 } else {
1144 for( i = 0; i < count(); i++ ) {
1145 w = d->listBox()->item( i )->width( d->listBox() );
1146 if ( w > maxW )
1147 maxW = w;
1148 }
1149 }
1150
1151 QStyleOptionComboBox opt = d->getStyleOption();
1152 d->sizeHint = (style()->sizeFromContents(QStyle::CT_ComboBox, &opt, QSize(maxW, maxH), this).
1153 expandedTo(QApplication::globalStrut()));
1154
1155 return d->sizeHint;
1156}
1157
1158
1159/*!
1160 \internal
1161 Receives activated signals from an internal popup list and emits
1162 the activated() signal.
1163*/
1164
1165void Q3ComboBox::internalActivate( int index )
1166{
1167 QStyleOptionComboBox opt = d->getStyleOption();
1168 if ( d->current != index ) {
1169 if ( !d->usingListBox() || listBox()->item( index )->isSelectable() ) {
1170 if (d->popup() && style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this))
1171 d->popup()->setItemChecked(d->current, false);
1172 d->current = index;
1173 currentChanged();
1174 }
1175 }
1176 if ( d->usingListBox() )
1177 popDownListBox();
1178 else
1179 d->popup()->removeEventFilter( this );
1180 d->poppedUp = false;
1181
1182 QString t( text( index ) );
1183 if ( d->ed ) {
1184 d->ed->setText( t );
1185 d->updateLinedGeometry();
1186 }
1187 emit activated( index );
1188 emit activated( t );
1189}
1190
1191/*!
1192 \internal
1193 Receives highlighted signals from an internal popup list and emits
1194 the highlighted() signal.
1195*/
1196
1197void Q3ComboBox::internalHighlight( int index )
1198{
1199 emit highlighted( index );
1200 QString t = text( index );
1201 if ( !t.isNull() )
1202 emit highlighted( t );
1203}
1204
1205/*!
1206 \internal
1207 Receives timeouts after a click. Used to decide if a Motif style
1208 popup should stay up or not after a click.
1209*/
1210void Q3ComboBox::internalClickTimeout()
1211{
1212 d->shortClick = false;
1213}
1214
1215/*!
1216 Sets the palette for both the combobox button and the combobox
1217 popup list to \a palette.
1218*/
1219
1220void Q3ComboBox::setPalette( const QPalette &palette )
1221{
1222 QWidget::setPalette( palette );
1223 if ( d->listBox() )
1224 d->listBox()->setPalette( palette );
1225 if ( d->popup() )
1226 d->popup()->setPalette( palette );
1227}
1228
1229/*!
1230 Sets the font for both the combobox button and the combobox popup
1231 list to \a font.
1232*/
1233
1234void Q3ComboBox::setFont( const QFont &font )
1235{
1236 d->sizeHint = QSize(); // invalidate size hint
1237 QWidget::setFont( font );
1238 if ( d->usingListBox() )
1239 d->listBox()->setFont( font );
1240 else
1241 d->popup()->setFont( font );
1242 if (d->ed)
1243 d->ed->setFont( font );
1244 if ( d->autoresize )
1245 adjustSize();
1246}
1247
1248
1249/*!\reimp
1250*/
1251
1252void Q3ComboBox::resizeEvent( QResizeEvent * e )
1253{
1254 if ( d->ed )
1255 d->updateLinedGeometry();
1256 if ( d->listBox() )
1257 d->listBox()->resize( width(), d->listBox()->height() );
1258 QWidget::resizeEvent( e );
1259}
1260
1261/*!\reimp
1262*/
1263
1264void Q3ComboBox::paintEvent( QPaintEvent * )
1265{
1266 QPainter p( this );
1267 const QColorGroup & g = colorGroup();
1268 p.setPen(g.text());
1269
1270 if ( width() < 5 || height() < 5 ) {
1271 qDrawShadePanel( &p, rect(), g, false, 2,
1272 &g.brush( QColorGroup::Button ) );
1273 return;
1274 }
1275
1276 QStyleOptionComboBox opt = d->getStyleOption();
1277 bool reverse = QApplication::reverseLayout();
1278 if ( !d->usingListBox() &&
1279 style()->styleHint(QStyle::SH_GUIStyle) == Qt::MotifStyle) { // motif 1.x style
1280 int dist, buttonH, buttonW;
1281 dist = 8;
1282 buttonH = 7;
1283 buttonW = 11;
1284 int xPos;
1285 int x0;
1286 int w = width() - dist - buttonW - 1;
1287 if ( reverse ) {
1288 xPos = dist + 1;
1289 x0 = xPos + 4;
1290 } else {
1291 xPos = w;
1292 x0 = 4;
1293 }
1294 qDrawShadePanel( &p, rect(), g, false,
1295 style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, this),
1296 &g.brush( QColorGroup::Button ) );
1297 qDrawShadePanel( &p, xPos, (height() - buttonH)/2,
1298 buttonW, buttonH, g, false,
1299 style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, this) );
1300 QRect clip( x0, 2, w - 2 - 4 - 5, height() - 4 );
1301 QString str = d->popup()->text( this->d->current );
1302 if ( !str.isNull() ) {
1303 p.drawText( clip, Qt::AlignCenter | Qt::TextSingleLine, str );
1304 }
1305
1306 QPixmap pix = d->popup()->pixmap( this->d->current );
1307 QIcon iconSet = d->popup()->iconSet( this->d->current );
1308 if (!pix.isNull() || !iconSet.isNull()) {
1309 QPixmap pm = ( !pix.isNull() ? pix : iconSet.pixmap() );
1310 p.setClipRect( clip );
1311 p.drawPixmap( 4, (height()-pm.height())/2, pm );
1312 p.setClipping( false );
1313 }
1314
1315 if ( hasFocus() )
1316 p.drawRect( xPos - 5, 4, width() - xPos + 1 , height() - 8 );
1317 } else if(!d->usingListBox()) {
1318 style()->drawComplexControl(QStyle::CC_ComboBox, &opt, &p, this);
1319 QRect re = style()->subControlRect(QStyle::CC_ComboBox, &opt,
1320 QStyle::SC_ComboBoxEditField, this);
1321 p.setClipRect( re );
1322
1323 QString str = d->popup()->text( this->d->current );
1324 QPixmap pix = d->popup()->pixmap( this->d->current );
1325 if ( !str.isNull() ) {
1326 p.save();
1327 p.setFont(font());
1328 QFontMetrics fm(font());
1329 int x = re.x(), y = re.y() + fm.ascent();
1330 x += pix.width() + 5;
1331 p.drawText( x, y, str );
1332 p.restore();
1333 }
1334 if (!pix.isNull()) {
1335 p.fillRect(re.x(), re.y(), pix.width() + 4, re.height(),
1336 colorGroup().brush(QColorGroup::Base));
1337 p.drawPixmap(re.x() + 2, re.y() + (re.height() - pix.height()) / 2, pix);
1338 }
1339 } else {
1340 style()->drawComplexControl(QStyle::CC_ComboBox, &opt, &p, this);
1341 QRect re = style()->subControlRect(QStyle::CC_ComboBox, &opt,
1342 QStyle::SC_ComboBoxEditField, this);
1343 p.setClipRect(re);
1344
1345 if ( !d->ed ) {
1346 Q3ListBoxItem * item = d->listBox()->item( d->current );
1347 if ( item ) {
1348 int itemh = item->height( d->listBox() );
1349 p.translate( re.x(), re.y() + (re.height() - itemh)/2 );
1350 item->paint( &p );
1351 }
1352 } else if ( d->listBox() && d->listBox()->item( d->current ) ) {
1353 Q3ListBoxItem * item = d->listBox()->item( d->current );
1354 const QPixmap *pix = item->pixmap();
1355 if ( pix ) {
1356 p.fillRect( re.x(), re.y(), pix->width() + 4, re.height(),
1357 colorGroup().brush( QColorGroup::Base ) );
1358 p.drawPixmap( re.x() + 2, re.y() +
1359 ( re.height() - pix->height() ) / 2, *pix );
1360 }
1361 }
1362 p.setClipping( false );
1363 }
1364}
1365
1366
1367/*!\reimp
1368*/
1369
1370void Q3ComboBox::mousePressEvent( QMouseEvent *e )
1371{
1372 if ( e->button() != Qt::LeftButton )
1373 return;
1374 if ( d->discardNextMousePress ) {
1375 d->discardNextMousePress = false;
1376 return;
1377 }
1378
1379 QStyleOptionComboBox opt = d->getStyleOption();
1380 QRect arrowRect = style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxArrow
1381 , this);
1382
1383 // Correction for motif style, where arrow is smaller
1384 // and thus has a rect that doesn't fit the button.
1385 arrowRect.setHeight( QMAX( height() - (2 * arrowRect.y()), arrowRect.height() ) );
1386
1387 if ( count() && ( !editable() || arrowRect.contains( e->pos() ) ) ) {
1388 d->arrowPressed = false;
1389
1390 if ( d->usingListBox() ) {
1391 listBox()->blockSignals( true );
1392 qApp->sendEvent( listBox(), e ); // trigger the listbox's autoscroll
1393 listBox()->setCurrentItem(d->current);
1394 listBox()->blockSignals( false );
1395 popup();
1396 if ( arrowRect.contains( e->pos() ) ) {
1397 d->arrowPressed = true;
1398 d->arrowDown = true;
1399 repaint( false );
1400 }
1401 } else {
1402 popup();
1403 }
1404 QTimer::singleShot( 200, this, SLOT(internalClickTimeout()));
1405 d->shortClick = true;
1406 }
1407}
1408
1409/*!\reimp
1410*/
1411
1412void Q3ComboBox::mouseMoveEvent( QMouseEvent * )
1413{
1414}
1415
1416/*!\reimp
1417*/
1418
1419void Q3ComboBox::mouseReleaseEvent( QMouseEvent * )
1420{
1421}
1422
1423/*!\reimp
1424*/
1425
1426void Q3ComboBox::mouseDoubleClickEvent( QMouseEvent *e )
1427{
1428 mousePressEvent( e );
1429}
1430
1431
1432/*!\reimp
1433*/
1434
1435void Q3ComboBox::keyPressEvent( QKeyEvent *e )
1436{
1437 bool handleEventHere = d->usingListBox() || !d->poppedUp;
1438
1439 int c = currentItem();
1440 if ( ( e->key() == Qt::Key_F4 && e->state() == 0 ) ||
1441 ( e->key() == Qt::Key_Down && (e->state() & Qt::AltModifier) ) ||
1442 ( !d->ed && e->key() == Qt::Key_Space ) ) {
1443 if ( count() ) {
1444 if ( !d->usingListBox() )
1445 d->popup()->setActiveItem( this->d->current );
1446 popup();
1447 }
1448 return;
1449 } else if ( handleEventHere && e->key() == Qt::Key_Up ) {
1450 if ( c > 0 )
1451 setCurrentItem( c-1 );
1452 } else if ( handleEventHere && e->key() == Qt::Key_Down ) {
1453 if ( ++c < count() )
1454 setCurrentItem( c );
1455 } else if ( handleEventHere && e->key() == Qt::Key_Home && ( !d->ed || !d->ed->hasFocus() ) ) {
1456 setCurrentItem( 0 );
1457 } else if ( handleEventHere && e->key() == Qt::Key_End && ( !d->ed || !d->ed->hasFocus() ) ) {
1458 setCurrentItem( count()-1 );
1459 } else if ( !d->ed && e->ascii() >= 32 && !e->text().isEmpty() ) {
1460 if ( !d->completionTimer->isActive() ) {
1461 d->completeAt = 0;
1462 c = completionIndex( e->text(), ++c );
1463 if ( c >= 0 ) {
1464 setCurrentItem( c );
1465 d->completeAt = e->text().length();
1466 }
1467 } else {
1468 d->completionTimer->stop();
1469 QString ct = currentText().left( d->completeAt ) + e->text();
1470 c = completionIndex( ct, c );
1471 if ( c < 0 && d->completeAt > 0 ) {
1472 c = completionIndex( e->text(), 0 );
1473 ct = e->text();
1474 }
1475 d->completeAt = 0;
1476 if ( c >= 0 ) {
1477 setCurrentItem( c );
1478 d->completeAt = ct.length();
1479 }
1480 }
1481 d->completionTimer->start( 400, true );
1482 } else {
1483 e->ignore();
1484 return;
1485 }
1486
1487 c = currentItem();
1488 if ( count() && !text( c ).isNull() )
1489 emit activated( text( c ) );
1490 emit activated( c );
1491}
1492
1493
1494/*!\reimp
1495*/
1496
1497void Q3ComboBox::focusInEvent( QFocusEvent * e )
1498{
1499 QWidget::focusInEvent( e );
1500 d->completeNow = false;
1501 d->completeAt = 0;
1502}
1503
1504/*!\reimp
1505*/
1506
1507void Q3ComboBox::focusOutEvent( QFocusEvent * e )
1508{
1509 QWidget::focusOutEvent( e );
1510 d->completeNow = false;
1511 d->completeAt = 0;
1512}
1513
1514/*!\reimp
1515*/
1516#ifndef QT_NO_WHEELEVENT
1517void Q3ComboBox::wheelEvent( QWheelEvent *e )
1518{
1519 if ( d->poppedUp ) {
1520 if ( d->usingListBox() ) {
1521 QApplication::sendEvent( d->listBox(), e );
1522 }
1523 } else {
1524 if ( e->delta() > 0 ) {
1525 int c = currentItem();
1526 if ( c > 0 ) {
1527 setCurrentItem( c-1 );
1528 emit activated( currentItem() );
1529 emit activated( currentText() );
1530 }
1531 } else {
1532 int c = currentItem();
1533 if ( ++c < count() ) {
1534 setCurrentItem( c );
1535 emit activated( currentItem() );
1536 emit activated( currentText() );
1537 }
1538 }
1539 e->accept();
1540 }
1541}
1542#endif
1543
1544/*!
1545 \internal
1546 Calculates the listbox height needed to contain all items, or as
1547 many as the list box is supposed to contain.
1548*/
1549static int listHeight( Q3ListBox *l, int sl )
1550{
1551 if ( l->count() > 0 )
1552 return QMIN( l->count(), (uint)sl) * l->item( 0 )->height(l);
1553 else
1554 return l->sizeHint().height();
1555}
1556
1557
1558/*!
1559 Pops up the combobox popup list.
1560
1561 If the list is empty, no items appear.
1562*/
1563
1564void Q3ComboBox::popup()
1565{
1566 if ( !count() || d->poppedUp )
1567 return;
1568
1569 QStyleOptionComboBox opt = d->getStyleOption();
1570 if( !d->usingListBox() || style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this) ) {
1571 if(d->usingListBox()) {
1572 if(!d->popup()) {
1573 Q3ComboBoxPopup *p = new Q3ComboBoxPopup( this, "in-combo" );
1574 d->setPopupMenu( p, false );
1575 p->setFont( font() );
1576 connect( p, SIGNAL(activated(int)), SLOT(internalActivate(int)) );
1577 connect( p, SIGNAL(highlighted(int)), SLOT(internalHighlight(int)) );
1578 }
1579 d->popup()->clear();
1580 for(unsigned int i = 0; i < d->listBox()->count(); i++) {
1581 Q3ListBoxItem *item = d->listBox()->item(i);
1582 if(item->rtti() == Q3ListBoxText::RTTI) {
1583 d->popup()->insertItem(escapedComboString(item->text()), i, i);
1584 } else if(item->rtti() == Q3ListBoxPixmap::RTTI) {
1585 if(item->pixmap())
1586 d->popup()->insertItem(QIcon(*item->pixmap()), escapedComboString(item->text()), i, i);
1587 else
1588 d->popup()->insertItem(escapedComboString(item->text()), i, i);
1589 } else {
1590 d->popup()->insertItem(new Q3ComboBoxPopupItem(item), i, i);
1591 }
1592 }
1593 }
1594 d->popup()->installEventFilter( this );
1595 if(d->popup() && style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this))
1596 d->popup()->setItemChecked(this->d->current, true);
1597 d->popup()->popup( mapToGlobal( QPoint(0,0) ), this->d->current );
1598 update();
1599 } else {
1600 // Send all listbox events to eventFilter():
1601 Q3ListBox* lb = d->listBox();
1602 lb->triggerUpdate( true );
1603 lb->installEventFilter( this );
1604 d->mouseWasInsidePopup = false;
1605 int w = lb->variableWidth() ? lb->sizeHint().width() : width();
1606 int h = listHeight( lb, d->sizeLimit ) + 2;
1607 QRect screen = QApplication::desktop()->availableGeometry( this );
1608
1609 int sx = screen.x(); // screen pos
1610 int sy = screen.y();
1611 int sw = screen.width(); // screen width
1612 int sh = screen.height(); // screen height
1613 QPoint pos = mapToGlobal( QPoint(0,height()) );
1614 // ## Similar code is in QPopupMenu
1615 int x = pos.x();
1616 int y = pos.y();
1617
1618 // the complete widget must be visible
1619 if ( x + w > sx + sw )
1620 x = sx+sw - w;
1621 if ( x < sx )
1622 x = sx;
1623 if (y + h > sy+sh && y - h - height() >= 0 )
1624 y = y - h - height();
1625
1626 opt.rect = QRect(x, y, w, h);
1627 QRect rect = style()->subControlRect(QStyle::CC_ComboBox, &opt,
1628 QStyle::SC_ComboBoxListBoxPopup, this);
1629
1630 // work around older styles that don't implement the combobox
1631 // listbox popup subcontrol
1632 if ( rect.isNull() )
1633 rect.setRect( x, y, w, h );
1634 lb->setGeometry( rect );
1635
1636 lb->raise();
1637 bool block = lb->signalsBlocked();
1638 lb->blockSignals( true );
1639 Q3ListBoxItem* currentLBItem = 0;
1640 if ( editable() && currentText() != text( currentItem() ) )
1641 currentLBItem = lb->findItem( currentText() );
1642
1643 currentLBItem = currentLBItem ? currentLBItem : lb->item( d->current );
1644
1645 lb->setCurrentItem( currentLBItem );
1646 lb->setContentsPos( lb->contentsX(),
1647 lb->viewportToContents( lb->itemRect( currentLBItem ).topLeft() ).y() );
1648
1649 // set the current item to also be the selected item if it isn't already
1650 if ( currentLBItem && currentLBItem->isSelectable() && !currentLBItem->isSelected() )
1651 lb->setSelected( currentLBItem, true );
1652 lb->blockSignals( block );
1653 lb->setVScrollBarMode(Q3ScrollView::Auto);
1654
1655#ifndef QT_NO_EFFECTS
1656 if ( QApplication::isEffectEnabled( Qt::UI_AnimateCombo ) ) {
1657 if ( lb->y() < mapToGlobal(QPoint(0,0)).y() )
1658 qScrollEffect( lb, QEffects::UpScroll );
1659 else
1660 qScrollEffect( lb );
1661 } else
1662#endif
1663 lb->show();
1664 }
1665 d->poppedUp = true;
1666}
1667
1668
1669/*!
1670 Updates the widget mask.
1671
1672 \sa QWidget::setMask()
1673*/
1674void Q3ComboBox::updateMask()
1675{
1676 QBitmap bm( size() );
1677 bm.fill( Qt::color0 );
1678
1679 QStyleOptionComboBox opt = d->getStyleOption();
1680 {
1681 QPainter p(&bm);
1682 p.initFrom(this);
1683 p.fillRect(opt.rect, Qt::color1); // qcommonstyle old drawComplexControl implementation
1684 }
1685
1686 setMask( bm );
1687}
1688
1689/*!
1690 \internal
1691 Pops down (removes) the combobox popup list box.
1692*/
1693void Q3ComboBox::popDownListBox()
1694{
1695 Q_ASSERT( d->usingListBox() );
1696 d->listBox()->removeEventFilter( this );
1697 d->listBox()->viewport()->removeEventFilter( this );
1698 d->listBox()->hide();
1699 d->listBox()->setCurrentItem( d->current );
1700 if ( d->arrowDown ) {
1701 d->arrowDown = false;
1702 repaint( false );
1703 }
1704 d->poppedUp = false;
1705}
1706
1707
1708/*!
1709 \internal
1710 Re-indexes the identifiers in the popup list.
1711*/
1712
1713void Q3ComboBox::reIndex()
1714{
1715 if ( !d->usingListBox() ) {
1716 int cnt = count();
1717 while ( cnt-- )
1718 d->popup()->setId( cnt, cnt );
1719 }
1720}
1721
1722/*!
1723 \internal
1724 Repaints the combobox.
1725*/
1726
1727void Q3ComboBox::currentChanged()
1728{
1729 if ( d->autoresize )
1730 adjustSize();
1731 update();
1732
1733#if defined(QT_ACCESSIBILITY_SUPPORT)
1734 QAccessible::updateAccessibility( this, 0, QAccessible::ValueChanged );
1735#endif
1736}
1737
1738/*! \reimp
1739
1740 \internal
1741
1742 The event filter steals events from the popup or listbox when they
1743 are popped up. It makes the popup stay up after a short click in
1744 motif style. In windows style it toggles the arrow button of the
1745 combobox field, and activates an item and takes down the listbox
1746 when the mouse button is released.
1747*/
1748
1749bool Q3ComboBox::eventFilter( QObject *object, QEvent *event )
1750{
1751 QStyleOptionComboBox opt = d->getStyleOption();
1752 if ( !event )
1753 return true;
1754 else if ( object == d->ed ) {
1755 if ( event->type() == QEvent::KeyPress ) {
1756 bool isAccepted = ( (QKeyEvent*)event )->isAccepted();
1757 keyPressEvent( (QKeyEvent *)event );
1758 if ( ((QKeyEvent *)event)->isAccepted() ) {
1759 d->completeNow = false;
1760 return true;
1761 } else if ( ((QKeyEvent *)event)->key() != Qt::Key_End ) {
1762 d->completeNow = true;
1763 d->completeAt = d->ed->cursorPosition();
1764 }
1765 if ( isAccepted )
1766 ( (QKeyEvent*)event )->accept();
1767 else
1768 ( (QKeyEvent*)event )->ignore();
1769 } else if ( event->type() == QEvent::KeyRelease ) {
1770 keyReleaseEvent( (QKeyEvent *)event );
1771 return ((QKeyEvent *)event)->isAccepted();
1772 } else if ( event->type() == QEvent::FocusIn ) {
1773 focusInEvent( (QFocusEvent *)event );
1774 } else if ( event->type() == QEvent::FocusOut ) {
1775 focusOutEvent( (QFocusEvent *)event );
1776 } else if ( d->useCompletion && d->completeNow ) {
1777 d->completeNow = false;
1778 if ( !d->ed->text().isNull() &&
1779 d->ed->cursorPosition() > d->completeAt &&
1780 d->ed->cursorPosition() == (int)d->ed->text().length() ) {
1781 QString ct( d->ed->text() );
1782 int i = completionIndex( ct, currentItem() );
1783 if ( i > -1 ) {
1784 QString it = text( i );
1785 d->ed->validateAndSet( it, ct.length(),
1786 ct.length(), it.length() );
1787 d->current = i;
1788 // ### sets current item without emitting signals. This is to
1789 // make sure the right item is current if you change current with
1790 // wheel/up/down. While typing current is not valid anyway. Fix properly
1791 // in 4.0.
1792 }
1793 }
1794 }
1795 } else if ( d->usingListBox() && ( object == d->listBox() ||
1796 object == d->listBox()->viewport() )) {
1797 QMouseEvent *e = (QMouseEvent*)event;
1798 switch( event->type() ) {
1799 case QEvent::MouseMove:
1800 if ( !d->mouseWasInsidePopup ) {
1801 QPoint pos = e->pos();
1802 if ( d->listBox()->rect().contains( pos ) )
1803 d->mouseWasInsidePopup = true;
1804 // Check if arrow button should toggle
1805 if ( d->arrowPressed ) {
1806 QPoint comboPos;
1807 comboPos = mapFromGlobal( d->listBox()->mapToGlobal(pos) );
1808 QRect arrowRect = style()->subControlRect(QStyle::CC_ComboBox, &opt,
1809 QStyle::SC_ComboBoxArrow, this);
1810 if ( arrowRect.contains( comboPos ) ) {
1811 if ( !d->arrowDown ) {
1812 d->arrowDown = true;
1813 repaint( false );
1814 }
1815 } else {
1816 if ( d->arrowDown ) {
1817 d->arrowDown = false;
1818 repaint( false );
1819 }
1820 }
1821 }
1822 } else if ((e->state() & ( Qt::RightButton | Qt::LeftButton | Qt::MidButton ) ) == 0 &&
1823 style()->styleHint(QStyle::SH_ComboBox_ListMouseTracking, &opt, this)) {
1824 QWidget *mouseW = QApplication::widgetAt( e->globalPos(), true );
1825 if ( mouseW == d->listBox()->viewport() ) { //###
1826 QMouseEvent m( QEvent::MouseMove, e->pos(), e->globalPos(),
1827 Qt::NoButton, Qt::LeftButton );
1828 QApplication::sendEvent( object, &m ); //### Evil
1829 return true;
1830 }
1831 }
1832
1833 break;
1834 case QEvent::MouseButtonRelease:
1835 if ( d->listBox()->rect().contains( e->pos() ) ) {
1836 QMouseEvent tmp( QEvent::MouseButtonDblClick,
1837 e->pos(), e->button(), e->state() ) ;
1838 // will hide popup
1839 QApplication::sendEvent( object, &tmp );
1840 return true;
1841 } else {
1842 if ( d->mouseWasInsidePopup ) {
1843 popDownListBox();
1844 } else {
1845 d->arrowPressed = false;
1846 if ( d->arrowDown ) {
1847 d->arrowDown = false;
1848 repaint( false );
1849 }
1850 }
1851 }
1852 break;
1853 case QEvent::MouseButtonDblClick:
1854 case QEvent::MouseButtonPress:
1855 if ( !d->listBox()->rect().contains( e->pos() ) ) {
1856 QPoint globalPos = d->listBox()->mapToGlobal(e->pos());
1857 if ( QApplication::widgetAt( globalPos, true ) == this ) {
1858 d->discardNextMousePress = true;
1859 // avoid popping up again
1860 }
1861 popDownListBox();
1862 return true;
1863 }
1864 break;
1865 case QEvent::KeyPress:
1866 switch( ((QKeyEvent *)event)->key() ) {
1867 case Qt::Key_Up:
1868 case Qt::Key_Down:
1869 if ( !(((QKeyEvent *)event)->state() & Qt::AltModifier) )
1870 break;
1871 case Qt::Key_F4:
1872 case Qt::Key_Escape:
1873 if ( d->poppedUp ) {
1874 popDownListBox();
1875 return true;
1876 }
1877 break;
1878 case Qt::Key_Enter:
1879 case Qt::Key_Return:
1880 // work around QDialog's enter handling
1881 return false;
1882 default:
1883 break;
1884 }
1885 break;
1886 case QEvent::Hide:
1887 popDownListBox();
1888 break;
1889 default:
1890 break;
1891 }
1892 } else if ( (!d->usingListBox() || style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)) &&
1893 object == d->popup() ) {
1894 QMouseEvent *e = (QMouseEvent*)event;
1895 switch ( event->type() ) {
1896 case QEvent::MouseButtonRelease:
1897 if ( d->shortClick ) {
1898 QMouseEvent tmp( QEvent::MouseMove,
1899 e->pos(), e->button(), e->state() ) ;
1900 // highlight item, but don't pop down:
1901 QApplication::sendEvent( object, &tmp );
1902 return true;
1903 }
1904 break;
1905 case QEvent::MouseButtonDblClick:
1906 case QEvent::MouseButtonPress:
1907 if ( !d->popup()->rect().contains( e->pos() ) ) {
1908 d->poppedUp = false;
1909 d->arrowDown = false;
1910 // remove filter, event will take down popup:
1911 d->popup()->removeEventFilter( this );
1912 // ### uglehack!
1913 // call internalHighlight so the highlighed signal
1914 // will be emitted at least as often as necessary.
1915 // it may be called more often than necessary
1916 internalHighlight( d->current );
1917 }
1918 break;
1919 case QEvent::Hide:
1920 d->poppedUp = false;
1921 break;
1922 default:
1923 break;
1924 }
1925 }
1926 return QWidget::eventFilter( object, event );
1927}
1928
1929
1930/*!
1931 Returns the index of the first item \e after \a startingAt of
1932 which \a prefix is a case-insensitive prefix. Returns -1 if no
1933 items start with \a prefix.
1934*/
1935
1936int Q3ComboBox::completionIndex( const QString & prefix,
1937 int startingAt = 0 ) const
1938{
1939 int start = startingAt;
1940 if ( start < 0 || start >= count() )
1941 start = 0;
1942 if ( start >= count() )
1943 return -1;
1944 QString match = prefix.lower();
1945 if ( match.length() < 1 )
1946 return start;
1947
1948 QString current;
1949 int i = start;
1950 do {
1951 current = text( i ).lower();
1952 if ( current.startsWith( match ) )
1953 return i;
1954 i++;
1955 if ( i == count() )
1956 i = 0;
1957 } while ( i != start );
1958 return -1;
1959}
1960
1961int Q3ComboBox::sizeLimit() const
1962{
1963 return d ? d->sizeLimit : INT_MAX;
1964}
1965
1966void Q3ComboBox::setSizeLimit( int lines )
1967{
1968 d->sizeLimit = lines;
1969}
1970
1971
1972int Q3ComboBox::maxCount() const
1973{
1974 return d ? d->maxCount : INT_MAX;
1975}
1976
1977void Q3ComboBox::setMaxCount( int count )
1978{
1979 int l = this->count();
1980 while( --l > count )
1981 removeItem( l );
1982 d->maxCount = count;
1983}
1984
1985Q3ComboBox::Policy Q3ComboBox::insertionPolicy() const
1986{
1987 return d->p;
1988}
1989
1990void Q3ComboBox::setInsertionPolicy( Policy policy )
1991{
1992 d->p = policy;
1993}
1994
1995
1996
1997/*!
1998 Internal slot to keep the line editor up to date.
1999*/
2000
2001void Q3ComboBox::returnPressed()
2002{
2003 QString s( d->ed->text() );
2004
2005 if ( s.isEmpty() )
2006 return;
2007
2008 int c = 0;
2009 bool doInsert = true;
2010 if ( !d->duplicatesEnabled ) {
2011 for ( int i = 0; i < count(); ++i ) {
2012 if ( s == text( i ) ) {
2013 doInsert = false;
2014 c = i;
2015 break;
2016 }
2017 }
2018 }
2019
2020 if ( doInsert ) {
2021 if ( insertionPolicy() != NoInsert ) {
2022 int cnt = count();
2023 while ( cnt >= d->maxCount ) {
2024 removeItem( --cnt );
2025 }
2026 }
2027
2028 switch ( insertionPolicy() ) {
2029 case InsertAtCurrent:
2030 if (count() == 0)
2031 insertItem(s);
2032 else if ( s != text( currentItem() ) )
2033 changeItem( s, currentItem() );
2034 emit activated( currentItem() );
2035 emit activated( s );
2036 return;
2037 case NoInsert:
2038 emit activated( s );
2039 return;
2040 case InsertAtTop:
2041 c = 0;
2042 break;
2043 case InsertAtBottom:
2044 c = count();
2045 break;
2046 case InsertBeforeCurrent:
2047 c = currentItem();
2048 break;
2049 case InsertAfterCurrent:
2050 c = count() == 0 ? 0 : currentItem() + 1;
2051 break;
2052 }
2053 insertItem( s, c );
2054 }
2055
2056 setCurrentItem( c );
2057 emit activated( c );
2058 emit activated( s );
2059}
2060
2061
2062/*!
2063 Enables the combobox if \a enable is true; otherwise disables it.
2064
2065 \sa QWidget::enabled
2066*/
2067
2068void Q3ComboBox::setEnabled( bool enable )
2069{
2070 if ( !enable ) {
2071 if ( d->usingListBox() ) {
2072 popDownListBox();
2073 } else {
2074 d->popup()->removeEventFilter( this );
2075 d->popup()->close();
2076 d->poppedUp = false;
2077 }
2078 }
2079 QWidget::setEnabled( enable );
2080}
2081
2082
2083
2084/*!
2085 Applies the validator \a v to the combobox so that only text which
2086 is valid according to \a v is accepted.
2087
2088 This function does nothing if the combobox is not editable.
2089
2090 \sa validator() clearValidator() QValidator
2091*/
2092
2093void Q3ComboBox::setValidator( const QValidator * v )
2094{
2095 if ( d && d->ed )
2096 d->ed->setValidator( v );
2097}
2098
2099
2100/*!
2101 Returns the validator which constrains editing for this combobox
2102 if there is one; otherwise returns 0.
2103
2104 \sa setValidator() clearValidator() QValidator
2105*/
2106
2107const QValidator * Q3ComboBox::validator() const
2108{
2109 return d && d->ed ? d->ed->validator() : 0;
2110}
2111
2112
2113/*!
2114 This slot is equivalent to setValidator( 0 ).
2115*/
2116
2117void Q3ComboBox::clearValidator()
2118{
2119 if ( d && d->ed )
2120 d->ed->setValidator( 0 );
2121}
2122
2123
2124/*!
2125 Sets the combobox to use \a newListBox instead of the current list
2126 box or popup. As a side effect, it clears the combobox of its
2127 current contents.
2128
2129 \warning Q3ComboBox assumes that newListBox->text(n) returns
2130 non-null for 0 \<= n \< newListbox->count(). This assumption is
2131 necessary because of the line edit in Q3ComboBox.
2132*/
2133
2134void Q3ComboBox::setListBox( Q3ListBox * newListBox )
2135{
2136 clear();
2137
2138 if ( d->usingListBox() ) {
2139 delete d->listBox();
2140 } else {
2141 delete d->popup();
2142 d->setPopupMenu(0, false);
2143 }
2144
2145 newListBox->reparent( this, Qt::WType_Popup, QPoint(0,0), false );
2146 d->setListBox( newListBox );
2147 d->listBox()->setFont( font() );
2148 d->listBox()->setPalette( palette() );
2149 d->listBox()->setVScrollBarMode(Q3ScrollView::AlwaysOff);
2150 d->listBox()->setHScrollBarMode(Q3ScrollView::AlwaysOff);
2151 d->listBox()->setFrameStyle( Q3Frame::Box | Q3Frame::Plain );
2152 d->listBox()->setLineWidth( 1 );
2153 d->listBox()->resize( 100, 10 );
2154
2155 connect( d->listBox(), SIGNAL(selected(int)),
2156 SLOT(internalActivate(int)) );
2157 connect( d->listBox(), SIGNAL(highlighted(int)),
2158 SLOT(internalHighlight(int)));
2159}
2160
2161
2162/*!
2163 Returns the current list box, or 0 if there is no list box.
2164 (Q3ComboBox can use QPopupMenu instead of QListBox.) Provided to
2165 match setListBox().
2166
2167 \sa setListBox()
2168*/
2169
2170Q3ListBox * Q3ComboBox::listBox() const
2171{
2172 return d && d->usingListBox() ? d->listBox() : 0;
2173}
2174
2175/*!
2176 Returns the line edit, or 0 if there is no line edit.
2177
2178 Only editable listboxes have a line editor.
2179*/
2180QLineEdit* Q3ComboBox::lineEdit() const
2181{
2182 return d->ed;
2183}
2184
2185
2186
2187/*!
2188 Clears the line edit without changing the combobox's contents.
2189 Does nothing if the combobox isn't editable.
2190
2191 This is particularly useful when using a combobox as a line edit
2192 with history. For example you can connect the combobox's
2193 activated() signal to clearEdit() in order to present the user
2194 with a new, empty line as soon as Enter is pressed.
2195
2196 \sa setEditText()
2197*/
2198
2199void Q3ComboBox::clearEdit()
2200{
2201 if ( d && d->ed )
2202 d->ed->clear();
2203}
2204
2205
2206/*!
2207 Sets the text in the line edit to \a newText without changing the
2208 combobox's contents. Does nothing if the combobox isn't editable.
2209
2210 This is useful e.g. for providing a good starting point for the
2211 user's editing and entering the change in the combobox only when
2212 the user presses Enter.
2213
2214 \sa clearEdit() insertItem()
2215*/
2216
2217void Q3ComboBox::setEditText( const QString &newText )
2218{
2219 if ( d && d->ed ) {
2220 d->updateLinedGeometry();
2221 d->ed->setText( newText );
2222 }
2223}
2224
2225void Q3ComboBox::setAutoCompletion( bool enable )
2226{
2227 d->useCompletion = enable;
2228 d->completeNow = false;
2229}
2230
2231
2232bool Q3ComboBox::autoCompletion() const
2233{
2234 return d->useCompletion;
2235}
2236
2237/*!
2238 \internal
2239 */
2240void Q3ComboBox::styleChange( QStyle& s )
2241{
2242 d->sizeHint = QSize(); // invalidate size hint...
2243 if ( d->ed )
2244 d->updateLinedGeometry();
2245 QWidget::styleChange( s );
2246}
2247
2248bool Q3ComboBox::editable() const
2249{
2250 return d->ed != 0;
2251}
2252
2253void Q3ComboBox::setEditable( bool y )
2254{
2255 if ( y == editable() )
2256 return;
2257 if ( y ) {
2258 if ( !d->usingListBox() )
2259 setUpListBox();
2260 setUpLineEdit();
2261 d->ed->show();
2262 if ( currentItem() )
2263 setEditText( currentText() );
2264 } else {
2265 delete d->ed;
2266 d->ed = 0;
2267 }
2268
2269 setFocusPolicy(Qt::StrongFocus);
2270 updateGeometry();
2271 update();
2272}
2273
2274
2275void Q3ComboBox::setUpListBox()
2276{
2277 d->setListBox( new Q3ListBox( this, "in-combo", Qt::WType_Popup ) );
2278 d->listBox()->setFont( font() );
2279 d->listBox()->setPalette( palette() );
2280 d->listBox()->setVScrollBarMode( Q3ListBox::AlwaysOff );
2281 d->listBox()->setHScrollBarMode( Q3ListBox::AlwaysOff );
2282 d->listBox()->setFrameStyle( Q3Frame::Box | Q3Frame::Plain );
2283 d->listBox()->setLineWidth( 1 );
2284 d->listBox()->resize( 100, 10 );
2285
2286 connect( d->listBox(), SIGNAL(selected(int)),
2287 SLOT(internalActivate(int)) );
2288 connect( d->listBox(), SIGNAL(highlighted(int)),
2289 SLOT(internalHighlight(int)));
2290}
2291
2292
2293void Q3ComboBox::setUpLineEdit()
2294{
2295 if ( !d->ed )
2296 setLineEdit( new QLineEdit( this, "combo edit" ) );
2297}
2298
2299/*!
2300 Sets the line edit to use \a edit instead of the current line edit.
2301*/
2302
2303void Q3ComboBox::setLineEdit( QLineEdit *edit )
2304{
2305 if ( !edit ) {
2306#if defined(QT_CHECK_NULL)
2307 Q_ASSERT( edit != 0 );
2308#endif
2309 return;
2310 }
2311
2312 edit->setText( currentText() );
2313 delete d->ed;
2314 d->ed = edit;
2315
2316 if ( edit->parent() != this )
2317 edit->reparent( this, QPoint(0,0), false );
2318
2319 connect (edit, SIGNAL(textChanged(QString)),
2320 this, SIGNAL(textChanged(QString)) );
2321 connect( edit, SIGNAL(returnPressed()), SLOT(returnPressed()) );
2322
2323 edit->setFrame( false );
2324 d->updateLinedGeometry();
2325 edit->installEventFilter( this );
2326 setFocusProxy( edit );
2327 setFocusPolicy(Qt::StrongFocus);
2328 setInputMethodEnabled( true );
2329
2330 if ( !d->usingListBox() )
2331 setUpListBox();
2332
2333 if ( isVisible() )
2334 edit->show();
2335
2336 updateGeometry();
2337 update();
2338}
2339
2340/*!
2341 Hides the combobox.
2342
2343 \sa QWidget::hide()
2344*/
2345void Q3ComboBox::hide()
2346{
2347 QWidget::hide();
2348
2349 if (listBox())
2350 listBox()->hide();
2351 else if (d->popup())
2352 d->popup()->hide();
2353}
2354
2355QT_END_NAMESPACE
2356
2357#endif // QT_NO_COMBOBOX
Note: See TracBrowser for help on using the repository browser.