• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

libkdepim

  • sources
  • kde-4.14
  • kdepim
  • libkdepim
  • widgets
kcheckcombobox.cpp
Go to the documentation of this file.
1 /*
2  This file is part of libkdepim.
3 
4  Copyright (c) 2008 Thomas Thrainer <tom_t@gmx.at>
5  Copyright (c) 2010 Bertjan Broeksema <broeksema@kde.org>
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License along
18  with this program; if not, write to the Free Software Foundation, Inc.,
19  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 
21  As a special exception, permission is given to link this program
22  with any edition of Qt, and distribute the resulting executable,
23  without including the source code for Qt in the source distribution.
24 */
25 
26 #include "kcheckcombobox.h"
27 
28 #include <KLineEdit>
29 #include <KDebug>
30 
31 #include <QAbstractItemView>
32 #include <QKeyEvent>
33 #include <QLineEdit>
34 #include <QStandardItemModel>
35 
36 using namespace KPIM;
37 
39 
40 namespace KPIM {
41 
42 class KCheckComboBox::Private
43 {
44  KCheckComboBox *q;
45 
46 public:
47  Private( KCheckComboBox *qq )
48  : q( qq )
49  , mSeparator( QLatin1Char( ',' ) )
50  , mSqueezeText( false )
51  , mIgnoreHide( false )
52  , mAlwaysShowDefaultText( false )
53  { }
54 
55  void makeInsertedItemsCheckable(const QModelIndex &, int start, int end);
56  QString squeeze( const QString &text );
57  void updateCheckedItems( const QModelIndex &topLeft = QModelIndex(),
58  const QModelIndex &bottomRight = QModelIndex(),
59  int role = Qt::DisplayRole );
60  void toggleCheckState();
61 
62 public:
63  QString mSeparator;
64  QString mDefaultText;
65  bool mSqueezeText;
66  bool mIgnoreHide;
67  bool mAlwaysShowDefaultText;
68 };
69 
70 }
71 
72 void KCheckComboBox::Private::makeInsertedItemsCheckable(const QModelIndex &parent, int start, int end)
73 {
74  Q_UNUSED( parent );
75  QStandardItemModel *model = qobject_cast<QStandardItemModel *>( q->model() );
76  if ( model ) {
77  for ( int r = start; r <= end; ++r ) {
78  QStandardItem *item = model->item( r, 0 );
79  item->setCheckable( true );
80  }
81  } else {
82  kWarning() << "KCheckComboBox: model is not a QStandardItemModel but a" << q->model() << ". Cannot proceed.";
83  }
84 }
85 
86 QString KCheckComboBox::Private::squeeze( const QString &text )
87 {
88  QFontMetrics fm( q->fontMetrics() );
89  // The 4 pixels is 2 * horizontalMargin from QLineEdit.
90  // The rest is code from QLineEdit::paintEvent, where it determines whether to scroll the text
91  // (on my machine minLB=2 and minRB=2, so this removes 8 pixels in total)
92  const int minLB = qMax(0, -fm.minLeftBearing());
93  const int minRB = qMax(0, -fm.minRightBearing());
94  const int lineEditWidth = q->lineEdit()->width() - 4 - minLB - minRB;
95  const int textWidth = fm.width( text );
96  if ( textWidth > lineEditWidth ) {
97  return fm.elidedText( text, Qt::ElideMiddle, lineEditWidth );
98  }
99 
100  return text;
101 }
102 
103 void KCheckComboBox::Private::updateCheckedItems( const QModelIndex &topLeft,
104  const QModelIndex &bottomRight,
105  int role )
106 {
107  Q_UNUSED( topLeft );
108  Q_UNUSED( bottomRight );
109 
110  const QStringList items = q->checkedItems( role );
111  QString text;
112  if ( items.isEmpty() || mAlwaysShowDefaultText ) {
113  text = mDefaultText;
114  } else {
115  text = items.join( mSeparator );
116  }
117 
118  if ( mSqueezeText )
119  text = squeeze( text );
120 
121  q->lineEdit()->setText( text );
122 
123  emit q->checkedItemsChanged( items );
124 }
125 
126 void KCheckComboBox::Private::toggleCheckState()
127 {
128  if (q->view()->isVisible()) {
129  const QModelIndex index = q->view()->currentIndex();
130  QVariant value = index.data( Qt::CheckStateRole );
131  if ( value.isValid() ) {
132  Qt::CheckState state = static_cast<Qt::CheckState>( value.toInt() );
133  q->model()->setData( index, state == Qt::Unchecked ? Qt::Checked : Qt::Unchecked,
134  Qt::CheckStateRole );
135  }
136  }
137 }
138 
140 
141 KCheckComboBox::KCheckComboBox( QWidget *parent )
142  : KComboBox( parent )
143  , d( new KCheckComboBox::Private( this ) )
144 {
145  connect( this, SIGNAL(activated(int)), this, SLOT(toggleCheckState()) );
146  connect( model(), SIGNAL(rowsInserted(QModelIndex,int,int)),
147  SLOT(makeInsertedItemsCheckable(QModelIndex,int,int)) );
148  connect( model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
149  this, SLOT(updateCheckedItems(QModelIndex,QModelIndex)) );
150 
151  // read-only contents
152  setEditable( true );
153  lineEdit()->setAlignment( Qt::AlignLeft );
154  // The cast is a workaround for the fact that QLineEdit::setReadOnly isn't virtual.
155  // KLineEdit copes with this case since kdelibs-4.6 though.
156  qobject_cast<KLineEdit *>(lineEdit())->setReadOnly( true );
157  setInsertPolicy( KComboBox::NoInsert );
158 
159  view()->installEventFilter( this );
160  view()->viewport()->installEventFilter( this );
161 
162  lineEdit()->installEventFilter( this );
163 
164  d->updateCheckedItems();
165 }
166 
167 KCheckComboBox::~KCheckComboBox()
168 {
169  delete d;
170 }
171 
172 void KCheckComboBox::hidePopup()
173 {
174  if ( !d->mIgnoreHide ) {
175  KComboBox::hidePopup();
176  }
177  d->mIgnoreHide = false;
178 }
179 
180 Qt::CheckState KCheckComboBox::itemCheckState( int index ) const
181 {
182  return static_cast<Qt::CheckState>( itemData( index, Qt::CheckStateRole ).toInt() );
183 }
184 
185 void KCheckComboBox::setItemCheckState( int index, Qt::CheckState state )
186 {
187  setItemData( index, state, Qt::CheckStateRole );
188 }
189 
190 QStringList KCheckComboBox::checkedItems( int role ) const
191 {
192  QStringList items;
193  if ( model() ) {
194  const QModelIndex index = model()->index( 0, modelColumn(), rootModelIndex() );
195  const QModelIndexList indexes = model()->match( index, Qt::CheckStateRole,
196  Qt::Checked, -1, Qt::MatchExactly );
197  foreach ( const QModelIndex &index, indexes ) {
198  items += index.data( role ).toString();
199  }
200  }
201  return items;
202 }
203 
204 void KCheckComboBox::setCheckedItems( const QStringList &items, int role )
205 {
206  for ( int r = 0; r < model()->rowCount( rootModelIndex() ); ++r ) {
207  const QModelIndex indx = model()->index( r, modelColumn(), rootModelIndex() );
208 
209  const QString text = indx.data( role ).toString();
210  const bool found = items.contains( text );
211  model()->setData( indx, found ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole );
212  }
213  d->updateCheckedItems( QModelIndex(), QModelIndex(), role );
214 }
215 
216 QString KCheckComboBox::defaultText() const
217 {
218  return d->mDefaultText;
219 }
220 
221 void KCheckComboBox::setDefaultText( const QString &text )
222 {
223  if ( d->mDefaultText != text ) {
224  d->mDefaultText = text;
225  d->updateCheckedItems();
226  }
227 }
228 
229 bool KCheckComboBox::squeezeText() const
230 {
231  return d->mSqueezeText;
232 }
233 
234 void KCheckComboBox::setSqueezeText( bool squeeze )
235 {
236  if ( d->mSqueezeText != squeeze ) {
237  d->mSqueezeText = squeeze;
238  d->updateCheckedItems();
239  }
240 }
241 
242 bool KCheckComboBox::itemEnabled( int index )
243 {
244  Q_ASSERT( index >= 0 && index <= count() );
245 
246  QStandardItemModel *itemModel = qobject_cast<QStandardItemModel *>( model() );
247  Q_ASSERT( itemModel );
248 
249  QStandardItem *item = itemModel->item( index, 0 );
250  return item->isEnabled();
251 }
252 
253 void KCheckComboBox::setItemEnabled( int index, bool enabled )
254 {
255  Q_ASSERT( index >= 0 && index <= count() );
256 
257  QStandardItemModel *itemModel = qobject_cast<QStandardItemModel *>( model() );
258  Q_ASSERT( itemModel );
259 
260  QStandardItem *item = itemModel->item( index, 0 );
261  item->setEnabled( enabled );
262 }
263 
264 QString KCheckComboBox::separator() const
265 {
266  return d->mSeparator;
267 }
268 
269 void KCheckComboBox::setSeparator( const QString &separator )
270 {
271  if ( d->mSeparator != separator ) {
272  d->mSeparator = separator;
273  d->updateCheckedItems();
274  }
275 }
276 
277 void KCheckComboBox::keyPressEvent( QKeyEvent *event )
278 {
279  switch ( event->key() ) {
280  case Qt::Key_Up:
281  case Qt::Key_Down:
282  showPopup();
283  event->accept();
284  break;
285  case Qt::Key_Return:
286  case Qt::Key_Enter:
287  case Qt::Key_Escape:
288  hidePopup();
289  event->accept();
290  break;
291  default:
292  break;
293  }
294  // don't call base class implementation, we don't need all that stuff in there
295 }
296 
297 #ifndef QT_NO_WHEELEVENT
298 void KCheckComboBox::wheelEvent( QWheelEvent *event )
299 {
300  // discard mouse wheel events on the combo box
301  event->accept();
302 }
303 #endif
304 
305 void KCheckComboBox::resizeEvent( QResizeEvent * event )
306 {
307  KComboBox::resizeEvent( event );
308  if ( d->mSqueezeText )
309  d->updateCheckedItems();
310 }
311 
312 bool KCheckComboBox::eventFilter( QObject *receiver, QEvent *event )
313 {
314  switch ( event->type() ) {
315  case QEvent::KeyPress:
316  case QEvent::KeyRelease:
317  case QEvent::ShortcutOverride:
318  {
319  switch ( static_cast<QKeyEvent *>( event )->key() ) {
320  case Qt::Key_Space:
321  if ( event->type() == QEvent::KeyPress && view()->isVisible() ) {
322  d->toggleCheckState();
323  }
324  // Always eat the event: don't let QItemDelegate toggle the current index when the view is hidden.
325  return true;
326  case Qt::Key_Return:
327  case Qt::Key_Enter:
328  case Qt::Key_Escape:
329  // ignore Enter keys, they would normally select items.
330  // but we select with Space, because multiple selection is possible
331  // we simply close the popup on Enter/Escape
332  hidePopup();
333  return true;
334  }
335  }
336  break;
337  case QEvent::MouseButtonDblClick:
338  case QEvent::MouseButtonPress:
339  case QEvent::MouseButtonRelease:
340  d->mIgnoreHide = true;
341  if ( receiver == lineEdit() ) {
342  showPopup();
343  return true;
344  }
345  break;
346  default:
347  break;
348  }
349  return KComboBox::eventFilter( receiver, event );
350 }
351 
352 bool KCheckComboBox::alwaysShowDefaultText() const
353 {
354  return d->mAlwaysShowDefaultText;
355 }
356 
357 void KCheckComboBox::setAlwaysShowDefaultText( bool always )
358 {
359  if ( always != d->mAlwaysShowDefaultText ) {
360  d->mAlwaysShowDefaultText = always;
361  d->updateCheckedItems();
362  }
363 }
364 
365 #include "moc_kcheckcombobox.cpp"
KPIM::KCheckComboBox::checkedItems
QStringList checkedItems
Definition: kcheckcombobox.h:49
QStandardItemModel::index
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const
QModelIndex
QEvent
QStandardItemModel
QResizeEvent
QWidget
KPIM::KCheckComboBox::setItemCheckState
void setItemCheckState(int index, Qt::CheckState state)
Changes the check state of the given index to the given state.
Definition: kcheckcombobox.cpp:185
QEvent::type
Type type() const
KPIM::KCheckComboBox::alwaysShowDefaultText
bool alwaysShowDefaultText() const
Returns whether the default text is always shown, even if there are no checked items.
Definition: kcheckcombobox.cpp:352
KPIM::KCheckComboBox::KCheckComboBox
KCheckComboBox(QWidget *parent=0)
Creates a new checkable combobox.
Definition: kcheckcombobox.cpp:141
KPIM::KCheckComboBox::setAlwaysShowDefaultText
void setAlwaysShowDefaultText(bool always)
Sets if the default text should always be shown even if there are no checked items.
Definition: kcheckcombobox.cpp:357
QWheelEvent
QStringList::contains
bool contains(const QString &str, Qt::CaseSensitivity cs) const
KPIM::KCheckComboBox
A combobox that shows its items in such a way that they can be checked in the drop menu...
Definition: kcheckcombobox.h:42
KPIM::KCheckComboBox::itemEnabled
bool itemEnabled(int index)
Return whether or not the item at.
Definition: kcheckcombobox.cpp:242
QFontMetrics
QStringList::join
QString join(const QString &separator) const
QStandardItemModel::setData
virtual bool setData(const QModelIndex &index, const QVariant &value, int role)
KPIM::KCheckComboBox::~KCheckComboBox
virtual ~KCheckComboBox()
Destroys the time zone combobox.
Definition: kcheckcombobox.cpp:167
QAbstractItemModel::match
virtual QModelIndexList match(const QModelIndex &start, int role, const QVariant &value, int hits, QFlags< Qt::MatchFlag > flags) const
KPIM::KCheckComboBox::defaultText
QString defaultText() const
Returns the default text that is shown when no items are selected.
QVariant::toInt
int toInt(bool *ok) const
KPIM::KCheckComboBox::resizeEvent
virtual void resizeEvent(QResizeEvent *event)
Definition: kcheckcombobox.cpp:305
QObject
QStandardItem::isEnabled
bool isEnabled() const
QList::isEmpty
bool isEmpty() const
KPIM::KCheckComboBox::setItemEnabled
void setItemEnabled(int index, bool enabled=true)
Set the item at.
Definition: kcheckcombobox.cpp:253
KPIM::KCheckComboBox::eventFilter
virtual bool eventFilter(QObject *receiver, QEvent *event)
Definition: kcheckcombobox.cpp:312
KPIM::KCheckComboBox::setSeparator
void setSeparator(const QString &separator)
Sets the separator used to separate items in the line edit.
Definition: kcheckcombobox.cpp:269
QString
KPIM::KCheckComboBox::keyPressEvent
virtual void keyPressEvent(QKeyEvent *event)
Definition: kcheckcombobox.cpp:277
QStringList
KPIM::KCheckComboBox::separator
QString separator() const
Returns the current separator used to separate the selected items in the line edit of the combo box...
QStandardItem::setEnabled
void setEnabled(bool enabled)
QKeyEvent::key
int key() const
QStandardItemModel::item
QStandardItem * item(int row, int column) const
QLatin1Char
KPIM::KCheckComboBox::setDefaultText
void setDefaultText(const QString &text)
Sets the default text that is shown when no items are selected.
Definition: kcheckcombobox.cpp:221
QFontMetrics::width
int width(const QString &text, int len) const
KPIM::KCheckComboBox::setSqueezeText
void setSqueezeText(bool squeeze)
Sets whether or not the text must be squeezed.
Definition: kcheckcombobox.cpp:234
kcheckcombobox.h
QKeyEvent
KLineEdit
QModelIndex::data
QVariant data(int role) const
KPIM::KCheckComboBox::squeezeText
bool squeezeText() const
Returns whether or not the text will be squeezed to fit in the combo's line edit. ...
KComboBox
QStandardItemModel::rowCount
virtual int rowCount(const QModelIndex &parent) const
QVariant::isValid
bool isValid() const
KPIM::KCheckComboBox::itemCheckState
Qt::CheckState itemCheckState(int index) const
Returns the check state of item at given index.
Definition: kcheckcombobox.cpp:180
QStandardItem
KPIM::KCheckComboBox::setCheckedItems
void setCheckedItems(const QStringList &items, int role=Qt::DisplayRole)
Sets the currently selected items.
Definition: kcheckcombobox.cpp:204
QVariant::toString
QString toString() const
KPIM::KCheckComboBox::hidePopup
virtual void hidePopup()
Hides the popup list if it is currently shown.
Definition: kcheckcombobox.cpp:172
QStandardItem::setCheckable
void setCheckable(bool checkable)
KPIM::KCheckComboBox::wheelEvent
virtual void wheelEvent(QWheelEvent *event)
Definition: kcheckcombobox.cpp:298
QVariant
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:33:50 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

libkdepim

Skip menu "libkdepim"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer
  • pimprint

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal