source: trunk/src/gui/widgets/qcombobox_p.h@ 792

Last change on this file since 792 was 769, checked in by Dmitry A. Kuminov, 15 years ago

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

File size: 13.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 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 QtGui 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#ifndef QCOMBOBOX_P_H
43#define QCOMBOBOX_P_H
44
45//
46// W A R N I N G
47// -------------
48//
49// This file is not part of the Qt API. It exists purely as an
50// implementation detail. This header file may change from version to
51// version without notice, or even be removed.
52//
53// We mean it.
54//
55
56#include "QtGui/qcombobox.h"
57
58#ifndef QT_NO_COMBOBOX
59#include "QtGui/qabstractslider.h"
60#include "QtGui/qapplication.h"
61#include "QtGui/qitemdelegate.h"
62#include "QtGui/qstandarditemmodel.h"
63#include "QtGui/qlineedit.h"
64#include "QtGui/qlistview.h"
65#include "QtGui/qpainter.h"
66#include "QtGui/qstyle.h"
67#include "QtGui/qstyleoption.h"
68#include "QtCore/qhash.h"
69#include "QtCore/qpair.h"
70#include "QtCore/qtimer.h"
71#include "private/qwidget_p.h"
72#include "QtCore/qpointer.h"
73#include "QtGui/qcompleter.h"
74#include "QtGui/qevent.h"
75#include "QtCore/qdebug.h"
76
77#include <limits.h>
78
79QT_BEGIN_NAMESPACE
80
81class QAction;
82
83class QComboBoxListView : public QListView
84{
85 Q_OBJECT
86public:
87 QComboBoxListView(QComboBox *cmb = 0) : combo(cmb) {}
88
89protected:
90 void resizeEvent(QResizeEvent *event)
91 {
92 resizeContents(viewport()->width(), contentsSize().height());
93 QListView::resizeEvent(event);
94 }
95
96 QStyleOptionViewItem viewOptions() const
97 {
98 QStyleOptionViewItem option = QListView::viewOptions();
99 option.showDecorationSelected = true;
100 if (combo)
101 option.font = combo->font();
102 return option;
103 }
104
105 void paintEvent(QPaintEvent *e)
106 {
107 if (combo) {
108 QStyleOptionComboBox opt;
109 opt.initFrom(combo);
110 opt.editable = combo->isEditable();
111 if (combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo)) {
112 //we paint the empty menu area to avoid having blank space that can happen when scrolling
113 QStyleOptionMenuItem menuOpt;
114 menuOpt.initFrom(this);
115 menuOpt.palette = palette();
116 menuOpt.state = QStyle::State_None;
117 menuOpt.checkType = QStyleOptionMenuItem::NotCheckable;
118 menuOpt.menuRect = e->rect();
119 menuOpt.maxIconWidth = 0;
120 menuOpt.tabWidth = 0;
121 QPainter p(viewport());
122 combo->style()->drawControl(QStyle::CE_MenuEmptyArea, &menuOpt, &p, this);
123 }
124 }
125 QListView::paintEvent(e);
126 }
127
128private:
129 QComboBox *combo;
130};
131
132
133class QStandardItemModel;
134
135class Q_AUTOTEST_EXPORT QComboBoxPrivateScroller : public QWidget
136{
137 Q_OBJECT
138
139public:
140 QComboBoxPrivateScroller(QAbstractSlider::SliderAction action, QWidget *parent)
141 : QWidget(parent), sliderAction(action)
142 {
143 setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
144 setAttribute(Qt::WA_NoMousePropagation);
145 }
146 QSize sizeHint() const {
147 return QSize(20, style()->pixelMetric(QStyle::PM_MenuScrollerHeight));
148 }
149
150protected:
151 inline void stopTimer() {
152 timer.stop();
153 }
154
155 inline void startTimer() {
156 timer.start(100, this);
157 fast = false;
158 }
159
160 void enterEvent(QEvent *) {
161 startTimer();
162 }
163
164 void leaveEvent(QEvent *) {
165 stopTimer();
166 }
167 void timerEvent(QTimerEvent *e) {
168 if (e->timerId() == timer.timerId()) {
169 emit doScroll(sliderAction);
170 if (fast) {
171 emit doScroll(sliderAction);
172 emit doScroll(sliderAction);
173 }
174 }
175 }
176 void hideEvent(QHideEvent *) {
177 stopTimer();
178 }
179
180 void mouseMoveEvent(QMouseEvent *e)
181 {
182 // Enable fast scrolling if the cursor is directly above or below the popup.
183 const int mouseX = e->pos().x();
184 const int mouseY = e->pos().y();
185 const bool horizontallyInside = pos().x() < mouseX && mouseX < rect().right() + 1;
186 const bool verticallyOutside = (sliderAction == QAbstractSlider::SliderSingleStepAdd) ?
187 rect().bottom() + 1 < mouseY : mouseY < pos().y();
188
189 fast = horizontallyInside && verticallyOutside;
190 }
191
192 void paintEvent(QPaintEvent *) {
193 QPainter p(this);
194 QStyleOptionMenuItem menuOpt;
195 menuOpt.init(this);
196 menuOpt.checkType = QStyleOptionMenuItem::NotCheckable;
197 menuOpt.menuRect = rect();
198 menuOpt.maxIconWidth = 0;
199 menuOpt.tabWidth = 0;
200 menuOpt.menuItemType = QStyleOptionMenuItem::Scroller;
201 if (sliderAction == QAbstractSlider::SliderSingleStepAdd)
202 menuOpt.state |= QStyle::State_DownArrow;
203#ifndef Q_WS_S60
204 p.eraseRect(rect());
205#endif
206 style()->drawControl(QStyle::CE_MenuScroller, &menuOpt, &p);
207 }
208
209Q_SIGNALS:
210 void doScroll(int action);
211
212private:
213 QAbstractSlider::SliderAction sliderAction;
214 QBasicTimer timer;
215 bool fast;
216};
217
218class Q_AUTOTEST_EXPORT QComboBoxPrivateContainer : public QFrame
219{
220 Q_OBJECT
221
222public:
223 QComboBoxPrivateContainer(QAbstractItemView *itemView, QComboBox *parent);
224 QAbstractItemView *itemView() const;
225 void setItemView(QAbstractItemView *itemView);
226 int spacing() const;
227 void updateTopBottomMargin();
228
229 QTimer blockMouseReleaseTimer;
230 QBasicTimer adjustSizeTimer;
231 QPoint initialClickPosition;
232
233public Q_SLOTS:
234 void scrollItemView(int action);
235 void updateScrollers();
236 void viewDestroyed();
237
238protected:
239 void changeEvent(QEvent *e);
240 bool eventFilter(QObject *o, QEvent *e);
241 void mousePressEvent(QMouseEvent *e);
242 void mouseReleaseEvent(QMouseEvent *e);
243 void showEvent(QShowEvent *e);
244 void hideEvent(QHideEvent *e);
245 void timerEvent(QTimerEvent *timerEvent);
246 void leaveEvent(QEvent *e);
247 void resizeEvent(QResizeEvent *e);
248 QStyleOptionComboBox comboStyleOption() const;
249
250Q_SIGNALS:
251 void itemSelected(const QModelIndex &);
252 void resetButton();
253
254private:
255 QComboBox *combo;
256 QAbstractItemView *view;
257 QComboBoxPrivateScroller *top;
258 QComboBoxPrivateScroller *bottom;
259#ifdef QT_SOFTKEYS_ENABLED
260 QAction *selectAction;
261 QAction *cancelAction;
262#endif
263};
264
265class QComboMenuDelegate : public QAbstractItemDelegate
266{ Q_OBJECT
267public:
268 QComboMenuDelegate(QObject *parent, QComboBox *cmb) : QAbstractItemDelegate(parent), mCombo(cmb) {}
269
270protected:
271 void paint(QPainter *painter,
272 const QStyleOptionViewItem &option,
273 const QModelIndex &index) const {
274 QStyleOptionMenuItem opt = getStyleOption(option, index);
275#ifndef Q_WS_S60
276 painter->fillRect(option.rect, opt.palette.background());
277#endif
278 mCombo->style()->drawControl(QStyle::CE_MenuItem, &opt, painter, mCombo);
279 }
280 QSize sizeHint(const QStyleOptionViewItem &option,
281 const QModelIndex &index) const {
282 QStyleOptionMenuItem opt = getStyleOption(option, index);
283 return mCombo->style()->sizeFromContents(
284 QStyle::CT_MenuItem, &opt, option.rect.size(), mCombo);
285 }
286
287private:
288 QStyleOptionMenuItem getStyleOption(const QStyleOptionViewItem &option,
289 const QModelIndex &index) const;
290 QComboBox *mCombo;
291};
292
293// Note that this class is intentionally not using QStyledItemDelegate
294// Vista does not use the new theme for combo boxes and there might
295// be other side effects from using the new class
296class QComboBoxDelegate : public QItemDelegate
297{ Q_OBJECT
298public:
299 QComboBoxDelegate(QObject *parent, QComboBox *cmb) : QItemDelegate(parent), mCombo(cmb) {}
300
301 static bool isSeparator(const QModelIndex &index) {
302 return index.data(Qt::AccessibleDescriptionRole).toString() == QLatin1String("separator");
303 }
304 static void setSeparator(QAbstractItemModel *model, const QModelIndex &index) {
305 model->setData(index, QString::fromLatin1("separator"), Qt::AccessibleDescriptionRole);
306 if (QStandardItemModel *m = qobject_cast<QStandardItemModel*>(model))
307 if (QStandardItem *item = m->itemFromIndex(index))
308 item->setFlags(item->flags() & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled));
309 }
310
311protected:
312 void paint(QPainter *painter,
313 const QStyleOptionViewItem &option,
314 const QModelIndex &index) const {
315 if (isSeparator(index)) {
316 QRect rect = option.rect;
317 if (const QStyleOptionViewItemV3 *v3 = qstyleoption_cast<const QStyleOptionViewItemV3*>(&option))
318 if (const QAbstractItemView *view = qobject_cast<const QAbstractItemView*>(v3->widget))
319 rect.setWidth(view->viewport()->width());
320 QStyleOption opt;
321 opt.rect = rect;
322 mCombo->style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator, &opt, painter, mCombo);
323 } else {
324 QItemDelegate::paint(painter, option, index);
325 }
326 }
327
328 QSize sizeHint(const QStyleOptionViewItem &option,
329 const QModelIndex &index) const {
330 if (isSeparator(index)) {
331 int pm = mCombo->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, mCombo);
332 return QSize(pm, pm);
333 }
334 return QItemDelegate::sizeHint(option, index);
335 }
336private:
337 QComboBox *mCombo;
338};
339
340class QComboBoxPrivate : public QWidgetPrivate
341{
342 Q_DECLARE_PUBLIC(QComboBox)
343public:
344 QComboBoxPrivate();
345 ~QComboBoxPrivate() {}
346 void init();
347 QComboBoxPrivateContainer* viewContainer();
348 void updateLineEditGeometry();
349 Qt::MatchFlags matchFlags() const;
350 void _q_editingFinished();
351 void _q_returnPressed();
352 void _q_complete();
353 void _q_itemSelected(const QModelIndex &item);
354 bool contains(const QString &text, int role);
355 void emitActivated(const QModelIndex&);
356 void _q_emitHighlighted(const QModelIndex&);
357 void _q_emitCurrentIndexChanged(const QModelIndex &index);
358 void _q_modelDestroyed();
359 void _q_modelReset();
360#ifdef QT_KEYPAD_NAVIGATION
361 void _q_completerActivated();
362#endif
363 void _q_resetButton();
364 void _q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
365 void _q_updateIndexBeforeChange();
366 void _q_rowsInserted(const QModelIndex & parent, int start, int end);
367 void _q_rowsRemoved(const QModelIndex & parent, int start, int end);
368 void updateArrow(QStyle::StateFlag state);
369 bool updateHoverControl(const QPoint &pos);
370 QRect popupGeometry(int screen = -1) const;
371 QStyle::SubControl newHoverControl(const QPoint &pos);
372 int computeWidthHint() const;
373 QSize recomputeSizeHint(QSize &sh) const;
374 void adjustComboBoxSize();
375 QString itemText(const QModelIndex &index) const;
376 QIcon itemIcon(const QModelIndex &index) const;
377 int itemRole() const;
378 void updateLayoutDirection();
379 void setCurrentIndex(const QModelIndex &index);
380 void updateDelegate(bool force = false);
381 void keyboardSearchString(const QString &text);
382 void modelChanged();
383 void updateViewContainerPaletteAndOpacity();
384
385 QAbstractItemModel *model;
386 QLineEdit *lineEdit;
387 QComboBoxPrivateContainer *container;
388 QComboBox::InsertPolicy insertPolicy;
389 QComboBox::SizeAdjustPolicy sizeAdjustPolicy;
390 int minimumContentsLength;
391 QSize iconSize;
392 uint shownOnce : 1;
393 uint autoCompletion : 1;
394 uint duplicatesEnabled : 1;
395 uint frame : 1;
396 uint padding : 26;
397 int maxVisibleItems;
398 int maxCount;
399 int modelColumn;
400 bool inserting;
401 mutable QSize minimumSizeHint;
402 mutable QSize sizeHint;
403 QStyle::StateFlag arrowState;
404 QStyle::SubControl hoverControl;
405 QRect hoverRect;
406 QPersistentModelIndex currentIndex;
407 QPersistentModelIndex root;
408 Qt::CaseSensitivity autoCompletionCaseSensitivity;
409 int indexBeforeChange;
410#ifndef QT_NO_COMPLETER
411 QPointer<QCompleter> completer;
412#endif
413 static QPalette viewContainerPalette(QComboBox *cmb)
414 { return cmb->d_func()->viewContainer()->palette(); }
415};
416
417QT_END_NAMESPACE
418
419#endif // QT_NO_COMBOBOX
420
421#endif // QCOMBOBOX_P_H
Note: See TracBrowser for help on using the repository browser.