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

Last change on this file since 64 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 13.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** 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 are unsure which license is appropriate for your use, please
37** contact the sales department 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 QComboBoxListView : public QListView
82{
83 Q_OBJECT
84public:
85 QComboBoxListView(QComboBox *cmb = 0) : combo(cmb) {}
86
87protected:
88 void resizeEvent(QResizeEvent *event)
89 {
90 resizeContents(viewport()->width(), contentsSize().height());
91 QListView::resizeEvent(event);
92 }
93
94 QStyleOptionViewItem viewOptions() const
95 {
96 QStyleOptionViewItem option = QListView::viewOptions();
97 option.showDecorationSelected = true;
98 if (combo)
99 option.font = combo->font();
100 return option;
101 }
102
103 void paintEvent(QPaintEvent *e)
104 {
105 if (combo) {
106 QStyleOptionComboBox opt;
107 opt.initFrom(combo);
108 opt.editable = combo->isEditable();
109 if (combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo)) {
110 //we paint the empty menu area to avoid having blank space that can happen when scrolling
111 QStyleOptionMenuItem menuOpt;
112 menuOpt.initFrom(this);
113 menuOpt.palette = palette();
114 menuOpt.state = QStyle::State_None;
115 menuOpt.checkType = QStyleOptionMenuItem::NotCheckable;
116 menuOpt.menuRect = e->rect();
117 menuOpt.maxIconWidth = 0;
118 menuOpt.tabWidth = 0;
119 QPainter p(viewport());
120 combo->style()->drawControl(QStyle::CE_MenuEmptyArea, &menuOpt, &p, this);
121 }
122 }
123 QListView::paintEvent(e);
124 }
125
126private:
127 QComboBox *combo;
128};
129
130
131class QStandardItemModel;
132
133class Q_AUTOTEST_EXPORT QComboBoxPrivateScroller : public QWidget
134{
135 Q_OBJECT
136
137public:
138 QComboBoxPrivateScroller(QAbstractSlider::SliderAction action, QWidget *parent)
139 : QWidget(parent), sliderAction(action)
140 {
141 setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
142 setAttribute(Qt::WA_NoMousePropagation);
143 }
144 QSize sizeHint() const {
145 return QSize(20, style()->pixelMetric(QStyle::PM_MenuScrollerHeight));
146 }
147
148protected:
149 inline void stopTimer() {
150 timer.stop();
151 }
152
153 inline void startTimer() {
154 timer.start(100, this);
155 fast = false;
156 }
157
158 void enterEvent(QEvent *) {
159 startTimer();
160 }
161
162 void leaveEvent(QEvent *) {
163 stopTimer();
164 }
165 void timerEvent(QTimerEvent *e) {
166 if (e->timerId() == timer.timerId()) {
167 emit doScroll(sliderAction);
168 if (fast) {
169 emit doScroll(sliderAction);
170 emit doScroll(sliderAction);
171 }
172 }
173 }
174 void hideEvent(QHideEvent *) {
175 stopTimer();
176 }
177
178 void mouseMoveEvent(QMouseEvent *e)
179 {
180 // Enable fast scrolling if the cursor is directly above or below the popup.
181 const int mouseX = e->pos().x();
182 const int mouseY = e->pos().y();
183 const bool horizontallyInside = pos().x() < mouseX && mouseX < rect().right() + 1;
184 const bool verticallyOutside = (sliderAction == QAbstractSlider::SliderSingleStepAdd) ?
185 rect().bottom() + 1 < mouseY : mouseY < pos().y();
186
187 fast = horizontallyInside && verticallyOutside;
188 }
189
190 void paintEvent(QPaintEvent *) {
191 QPainter p(this);
192 QStyleOptionMenuItem menuOpt;
193 menuOpt.init(this);
194 menuOpt.checkType = QStyleOptionMenuItem::NotCheckable;
195 menuOpt.menuRect = rect();
196 menuOpt.maxIconWidth = 0;
197 menuOpt.tabWidth = 0;
198 menuOpt.menuItemType = QStyleOptionMenuItem::Scroller;
199 if (sliderAction == QAbstractSlider::SliderSingleStepAdd)
200 menuOpt.state |= QStyle::State_DownArrow;
201 p.eraseRect(rect());
202 style()->drawControl(QStyle::CE_MenuScroller, &menuOpt, &p);
203 }
204
205Q_SIGNALS:
206 void doScroll(int action);
207
208private:
209 QAbstractSlider::SliderAction sliderAction;
210 QBasicTimer timer;
211 bool fast;
212};
213
214class Q_AUTOTEST_EXPORT QComboBoxPrivateContainer : public QFrame
215{
216 Q_OBJECT
217
218public:
219 QComboBoxPrivateContainer(QAbstractItemView *itemView, QComboBox *parent);
220 QAbstractItemView *itemView() const;
221 void setItemView(QAbstractItemView *itemView);
222 int spacing() const;
223 void updateTopBottomMargin();
224
225 QTimer blockMouseReleaseTimer;
226 QBasicTimer adjustSizeTimer;
227 QPoint initialClickPosition;
228
229public Q_SLOTS:
230 void scrollItemView(int action);
231 void updateScrollers();
232 void setCurrentIndex(const QModelIndex &index);
233 void viewDestroyed();
234
235protected:
236 void changeEvent(QEvent *e);
237 bool eventFilter(QObject *o, QEvent *e);
238 void mousePressEvent(QMouseEvent *e);
239 void mouseReleaseEvent(QMouseEvent *e);
240 void showEvent(QShowEvent *e);
241 void hideEvent(QHideEvent *e);
242 void timerEvent(QTimerEvent *timerEvent);
243 void leaveEvent(QEvent *e);
244 void resizeEvent(QResizeEvent *e);
245 QStyleOptionComboBox comboStyleOption() const;
246
247Q_SIGNALS:
248 void itemSelected(const QModelIndex &);
249 void resetButton();
250
251private:
252 QComboBox *combo;
253 QAbstractItemView *view;
254 QComboBoxPrivateScroller *top;
255 QComboBoxPrivateScroller *bottom;
256};
257
258class QComboMenuDelegate : public QAbstractItemDelegate
259{
260public:
261 QComboMenuDelegate(QObject *parent, QComboBox *cmb) : QAbstractItemDelegate(parent), mCombo(cmb) {}
262
263protected:
264 void paint(QPainter *painter,
265 const QStyleOptionViewItem &option,
266 const QModelIndex &index) const {
267 QStyleOptionMenuItem opt = getStyleOption(option, index);
268 painter->fillRect(option.rect, opt.palette.background());
269 mCombo->style()->drawControl(QStyle::CE_MenuItem, &opt, painter, mCombo);
270 }
271 QSize sizeHint(const QStyleOptionViewItem &option,
272 const QModelIndex &index) const {
273 QStyleOptionMenuItem opt = getStyleOption(option, index);
274 return mCombo->style()->sizeFromContents(
275 QStyle::CT_MenuItem, &opt, option.rect.size(), mCombo);
276 }
277
278private:
279 QStyleOptionMenuItem getStyleOption(const QStyleOptionViewItem &option,
280 const QModelIndex &index) const;
281 QComboBox *mCombo;
282};
283
284// Note that this class is intentionally not using QStyledItemDelegate
285// Vista does not use the new theme for combo boxes and there might
286// be other side effects from using the new class
287class QComboBoxDelegate : public QItemDelegate
288{
289public:
290 QComboBoxDelegate(QObject *parent, QComboBox *cmb) : QItemDelegate(parent), mCombo(cmb) {}
291
292 static bool isSeparator(const QModelIndex &index) {
293 return index.data(Qt::AccessibleDescriptionRole).toString() == QString::fromLatin1("separator");
294 }
295 static void setSeparator(QAbstractItemModel *model, const QModelIndex &index) {
296 model->setData(index, QString::fromLatin1("separator"), Qt::AccessibleDescriptionRole);
297 if (QStandardItemModel *m = qobject_cast<QStandardItemModel*>(model))
298 if (QStandardItem *item = m->itemFromIndex(index))
299 item->setFlags(item->flags() & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled));
300 }
301
302protected:
303 void paint(QPainter *painter,
304 const QStyleOptionViewItem &option,
305 const QModelIndex &index) const {
306 if (isSeparator(index)) {
307 QRect rect = option.rect;
308 if (const QStyleOptionViewItemV3 *v3 = qstyleoption_cast<const QStyleOptionViewItemV3*>(&option))
309 if (const QAbstractItemView *view = qobject_cast<const QAbstractItemView*>(v3->widget))
310 rect.setWidth(view->viewport()->width());
311 QStyleOption opt;
312 opt.rect = rect;
313 mCombo->style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator, &opt, painter, mCombo);
314 } else {
315 QItemDelegate::paint(painter, option, index);
316 }
317 }
318
319 QSize sizeHint(const QStyleOptionViewItem &option,
320 const QModelIndex &index) const {
321 if (isSeparator(index)) {
322 int pm = mCombo->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, mCombo);
323 return QSize(pm, pm);
324 }
325 return QItemDelegate::sizeHint(option, index);
326 }
327private:
328 QComboBox *mCombo;
329};
330
331class QComboBoxPrivate : public QWidgetPrivate
332{
333 Q_DECLARE_PUBLIC(QComboBox)
334public:
335 QComboBoxPrivate();
336 ~QComboBoxPrivate() {}
337 void init();
338 QComboBoxPrivateContainer* viewContainer();
339 void updateLineEditGeometry();
340 void _q_returnPressed();
341 void _q_complete();
342 void _q_itemSelected(const QModelIndex &item);
343 bool contains(const QString &text, int role);
344 void emitActivated(const QModelIndex&);
345 void _q_emitHighlighted(const QModelIndex&);
346 void _q_emitCurrentIndexChanged(const QModelIndex &index);
347 void _q_modelDestroyed();
348 void _q_modelReset();
349#ifdef QT_KEYPAD_NAVIGATION
350 void _q_completerActivated();
351#endif
352 void _q_resetButton();
353 void _q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
354 void _q_rowsAboutToBeInserted(const QModelIndex & parent, int start, int end);
355 void _q_rowsInserted(const QModelIndex & parent, int start, int end);
356 void _q_rowsAboutToBeRemoved(const QModelIndex & parent, int start, int end);
357 void _q_rowsRemoved(const QModelIndex & parent, int start, int end);
358 void updateArrow(QStyle::StateFlag state);
359 bool updateHoverControl(const QPoint &pos);
360 QRect popupGeometry(int screen = -1) const;
361 QStyle::SubControl newHoverControl(const QPoint &pos);
362 int computeWidthHint() const;
363 QSize recomputeSizeHint(QSize &sh) const;
364 void adjustComboBoxSize();
365 QString itemText(const QModelIndex &index) const;
366 QIcon itemIcon(const QModelIndex &index) const;
367 int itemRole() const;
368 void updateLayoutDirection();
369 void setCurrentIndex(const QModelIndex &index);
370 void updateDelegate();
371 void keyboardSearchString(const QString &text);
372 void modelChanged();
373
374 QAbstractItemModel *model;
375 QLineEdit *lineEdit;
376 QComboBoxPrivateContainer *container;
377 QComboBox::InsertPolicy insertPolicy;
378 QComboBox::SizeAdjustPolicy sizeAdjustPolicy;
379 int minimumContentsLength;
380 QSize iconSize;
381 uint shownOnce : 1;
382 uint autoCompletion : 1;
383 uint duplicatesEnabled : 1;
384 uint frame : 1;
385 uint padding : 26;
386 int maxVisibleItems;
387 int maxCount;
388 int modelColumn;
389 bool inserting;
390 mutable QSize minimumSizeHint;
391 mutable QSize sizeHint;
392 QStyle::StateFlag arrowState;
393 QStyle::SubControl hoverControl;
394 QRect hoverRect;
395 QPersistentModelIndex currentIndex;
396 QPersistentModelIndex root;
397 Qt::CaseSensitivity autoCompletionCaseSensitivity;
398 int indexBeforeChange;
399#ifndef QT_NO_COMPLETER
400 QPointer<QCompleter> completer;
401#endif
402 static QPalette viewContainerPalette(QComboBox *cmb)
403 { return cmb->d_func()->viewContainer()->palette(); }
404};
405
406QT_END_NAMESPACE
407
408#endif // QT_NO_COMBOBOX
409
410#endif // QCOMBOBOX_P_H
Note: See TracBrowser for help on using the repository browser.