00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef QCOMBOBOX_P_H
00025 #define QCOMBOBOX_P_H
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "QtGui/qcombobox.h"
00039
00040 #ifndef QT_NO_COMBOBOX
00041 #include "QtGui/qabstractslider.h"
00042 #include "QtGui/qapplication.h"
00043 #include "qitemdelegate.h"
00044 #include "QtGui/qlineedit.h"
00045 #include "QtGui/qlistview.h"
00046 #include "QtGui/qpainter.h"
00047 #include "QtGui/qstyle.h"
00048 #include "QtGui/qstyleoption.h"
00049 #include "QtCore/qhash.h"
00050 #include "QtCore/qpair.h"
00051 #include "QtCore/qtimer.h"
00052 #include "private/qwidget_p.h"
00053 #include "QtCore/qpointer.h"
00054 #include "QtGui/qcompleter.h"
00055 #include "QtGui/qevent.h"
00056 #include "QtCore/qdebug.h"
00057
00058 #include <limits.h>
00059
00060 class QComboBoxListView : public QListView
00061 {
00062 Q_OBJECT
00063 protected:
00064 void resizeEvent(QResizeEvent *event)
00065 {
00066 resizeContents(viewport()->width(), contentsSize().height());
00067 QListView::resizeEvent(event);
00068 }
00069
00070 QStyleOptionViewItem viewOptions() const
00071 {
00072 QStyleOptionViewItem option = QListView::viewOptions();
00073 option.showDecorationSelected = true;
00074 return option;
00075 }
00076 };
00077
00078
00079 class QStandardItemModel;
00080
00081 class QComboBoxPrivateScroller : public QWidget
00082 {
00083 Q_OBJECT
00084
00085 public:
00086 QComboBoxPrivateScroller(QAbstractSlider::SliderAction action, QWidget *parent)
00087 : QWidget(parent), sliderAction(action) {
00088 setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
00089 }
00090 QSize sizeHint() const {
00091 return QSize(20, style()->pixelMetric(QStyle::PM_MenuScrollerHeight));
00092 }
00093
00094 protected:
00095 inline void stopTimer() {
00096 timer.stop();
00097 }
00098
00099 inline void startTimer() {
00100 timer.start(100, this);
00101 fast = false;
00102 }
00103
00104 void enterEvent(QEvent *) {
00105 startTimer();
00106 }
00107
00108 void leaveEvent(QEvent *) {
00109 stopTimer();
00110 }
00111 void timerEvent(QTimerEvent *e) {
00112 if (e->timerId() == timer.timerId()) {
00113 emit doScroll(sliderAction);
00114 if (fast) {
00115 emit doScroll(sliderAction);
00116 emit doScroll(sliderAction);
00117 }
00118 }
00119 }
00120 void hideEvent(QHideEvent *) {
00121 stopTimer();
00122 }
00123
00124 void mouseMoveEvent(QMouseEvent *e)
00125 {
00126
00127 const int mouseX = e->pos().x();
00128 const int mouseY = e->pos().y();
00129 const bool horizontallyInside = pos().x() < mouseX && mouseX < rect().right() + 1;
00130 const bool verticallyOutside = (sliderAction == QAbstractSlider::SliderSingleStepAdd) ?
00131 rect().bottom() + 1 < mouseY : mouseY < pos().y();
00132
00133 fast = horizontallyInside && verticallyOutside;
00134 }
00135
00136 void paintEvent(QPaintEvent *) {
00137 QPainter p(this);
00138 QStyleOptionMenuItem menuOpt;
00139 menuOpt.init(this);
00140 menuOpt.checkType = QStyleOptionMenuItem::NotCheckable;
00141 menuOpt.menuRect = rect();
00142 menuOpt.maxIconWidth = 0;
00143 menuOpt.tabWidth = 0;
00144 menuOpt.menuItemType = QStyleOptionMenuItem::Scroller;
00145 if (sliderAction == QAbstractSlider::SliderSingleStepAdd)
00146 menuOpt.state |= QStyle::State_DownArrow;
00147 p.eraseRect(rect());
00148 style()->drawControl(QStyle::CE_MenuScroller, &menuOpt, &p);
00149 }
00150
00151 Q_SIGNALS:
00152 void doScroll(int action);
00153
00154 private:
00155 QAbstractSlider::SliderAction sliderAction;
00156 QBasicTimer timer;
00157 bool fast;
00158 };
00159
00160 class QComboBoxPrivateContainer : public QFrame
00161 {
00162 Q_OBJECT
00163
00164 public:
00165 QComboBoxPrivateContainer(QAbstractItemView *itemView, QComboBox *parent);
00166 QAbstractItemView *itemView() const;
00167 void setItemView(QAbstractItemView *itemView);
00168 int spacing() const;
00169
00170 QTimer blockMouseReleaseTimer;
00171 QPoint initialClickPosition;
00172
00173 public Q_SLOTS:
00174 void scrollItemView(int action);
00175 void updateScrollers();
00176 void setCurrentIndex(const QModelIndex &index);
00177 void viewDestroyed();
00178
00179 protected:
00180 void changeEvent(QEvent *e);
00181 bool eventFilter(QObject *o, QEvent *e);
00182 void mousePressEvent(QMouseEvent *e);
00183 void mouseReleaseEvent(QMouseEvent *e);
00184 void showEvent(QShowEvent *e);
00185 void hideEvent(QHideEvent *e);
00186 QStyleOptionComboBox comboStyleOption() const;
00187
00188 Q_SIGNALS:
00189 void itemSelected(const QModelIndex &);
00190 void resetButton();
00191
00192 private:
00193 QComboBox *combo;
00194 QAbstractItemView *view;
00195 QComboBoxPrivateScroller *top;
00196 QComboBoxPrivateScroller *bottom;
00197 };
00198
00199 class QComboMenuDelegate : public QAbstractItemDelegate
00200 {
00201 public:
00202 QComboMenuDelegate(QObject *parent, QComboBox *cmb) : QAbstractItemDelegate(parent), mCombo(cmb), pal(QApplication::palette("QMenu")) {}
00203
00204 protected:
00205 void paint(QPainter *painter,
00206 const QStyleOptionViewItem &option,
00207 const QModelIndex &index) const {
00208 QStyleOptionMenuItem opt = getStyleOption(option, index);
00209 painter->eraseRect(option.rect);
00210 mCombo->style()->drawControl(QStyle::CE_MenuItem, &opt, painter, mCombo);
00211 }
00212 QSize sizeHint(const QStyleOptionViewItem &option,
00213 const QModelIndex &index) const {
00214 QStyleOptionMenuItem opt = getStyleOption(option, index);
00215 QVariant value = index.model()->data(index, Qt::FontRole);
00216 QFont fnt = value.isValid() ? qvariant_cast<QFont>(value) : option.font;
00217 return mCombo->style()->sizeFromContents(
00218 QStyle::CT_MenuItem, &opt, option.rect.size(), mCombo);
00219 }
00220
00221 private:
00222 QStyleOptionMenuItem getStyleOption(const QStyleOptionViewItem &option,
00223 const QModelIndex &index) const;
00224 QComboBox *mCombo;
00225 QPalette pal;
00226 };
00227
00228 class QComboBoxPrivate : public QWidgetPrivate
00229 {
00230 Q_DECLARE_PUBLIC(QComboBox)
00231 public:
00232 QComboBoxPrivate();
00233 ~QComboBoxPrivate() {}
00234 void init();
00235 QComboBoxPrivateContainer* viewContainer();
00236 QStyleOptionComboBox getStyleOption() const;
00237 void updateLineEditGeometry();
00238 void _q_returnPressed();
00239 void _q_complete();
00240 void _q_itemSelected(const QModelIndex &item);
00241 bool contains(const QString &text, int role);
00242 void emitActivated(const QModelIndex&);
00243 void _q_emitHighlighted(const QModelIndex&);
00244 void _q_emitCurrentIndexChanged(int index);
00245 void _q_modelDestroyed();
00246 void _q_modelReset();
00247 void _q_resetButton();
00248 void _q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
00249 void _q_rowsAboutToBeInserted(const QModelIndex & parent, int start, int end);
00250 void _q_rowsInserted(const QModelIndex & parent, int start, int end);
00251 void _q_rowsAboutToBeRemoved(const QModelIndex & parent, int start, int end);
00252 void _q_rowsRemoved(const QModelIndex & parent, int start, int end);
00253 void updateArrow(QStyle::StateFlag state);
00254 bool updateHoverControl(const QPoint &pos);
00255 QRect popupGeometry(int screen = -1) const;
00256 QStyle::SubControl newHoverControl(const QPoint &pos);
00257 int computeWidthHint() const;
00258 QSize recomputeSizeHint(QSize &sh) const;
00259 QString itemText(const QModelIndex &index) const;
00260 int itemRole() const;
00261
00262 QAbstractItemModel *model;
00263 QLineEdit *lineEdit;
00264 QComboBoxPrivateContainer *container;
00265 QComboBox::InsertPolicy insertPolicy;
00266 QComboBox::SizeAdjustPolicy sizeAdjustPolicy;
00267 int minimumContentsLength;
00268 QSize iconSize;
00269 uint shownOnce : 1;
00270 uint autoCompletion : 1;
00271 uint duplicatesEnabled : 1;
00272 uint frame : 1;
00273 uint padding : 26;
00274 int maxVisibleItems;
00275 int maxCount;
00276 int modelColumn;
00277 mutable QSize minimumSizeHint;
00278 mutable QSize sizeHint;
00279 QStyle::StateFlag arrowState;
00280 QStyle::SubControl hoverControl;
00281 QRect hoverRect;
00282 QPersistentModelIndex currentIndex;
00283 QPersistentModelIndex root;
00284 Qt::CaseSensitivity autoCompletionCaseSensitivity;
00285 int indexBeforeChange;
00286 #ifndef QT_NO_COMPLETER
00287 QPointer<QCompleter> completer;
00288 #endif
00289 };
00290
00291 #endif // QT_NO_COMBOBOX
00292
00293 #endif // QCOMBOBOX_P_H