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

libkdepim

  • sources
  • kde-4.12
  • 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 "kcheckcombobox.moc"
KPIM::KCheckComboBox::checkedItems
QStringList checkedItems
Definition: kcheckcombobox.h:49
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
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
QWidget
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
QObject
KPIM::KCheckComboBox::~KCheckComboBox
virtual ~KCheckComboBox()
Destroys the time zone combobox.
Definition: kcheckcombobox.cpp:167
KPIM::KCheckComboBox::defaultText
QString defaultText() const
Returns the default text that is shown when no items are selected.
KPIM::KCheckComboBox::resizeEvent
virtual void resizeEvent(QResizeEvent *event)
Definition: kcheckcombobox.cpp:305
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
KPIM::KCheckComboBox::keyPressEvent
virtual void keyPressEvent(QKeyEvent *event)
Definition: kcheckcombobox.cpp:277
KPIM::KCheckComboBox::separator
QString separator() const
Returns the current separator used to separate the selected items in the line edit of the combo box...
KPIM::KCheckComboBox::setDefaultText
void setDefaultText(const QString &text)
Sets the default text that is shown when no items are selected.
Definition: kcheckcombobox.cpp:221
KPIM::KCheckComboBox::setSqueezeText
void setSqueezeText(bool squeeze)
Sets whether or not the text must be squeezed.
Definition: kcheckcombobox.cpp:234
kcheckcombobox.h
KLineEdit
KPIM::KCheckComboBox::squeezeText
bool squeezeText() const
Returns whether or not the text will be squeezed to fit in the combo's line edit. ...
KComboBox
KPIM::KCheckComboBox::itemCheckState
Qt::CheckState itemCheckState(int index) const
Returns the check state of item at given index.
Definition: kcheckcombobox.cpp:180
KPIM::KCheckComboBox::setCheckedItems
void setCheckedItems(const QStringList &items, int role=Qt::DisplayRole)
Sets the currently selected items.
Definition: kcheckcombobox.cpp:204
KPIM::KCheckComboBox::hidePopup
virtual void hidePopup()
Hides the popup list if it is currently shown.
Definition: kcheckcombobox.cpp:172
KPIM::KCheckComboBox::wheelEvent
virtual void wheelEvent(QWheelEvent *event)
Definition: kcheckcombobox.cpp:298
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:58:03 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

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