• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KDEUI

  • kdeui
  • widgets
khistorycombobox.cpp
Go to the documentation of this file.
1/* This file is part of the KDE libraries
2
3 Copyright (c) 2000,2001 Dawit Alemayehu <adawit@kde.org>
4 Copyright (c) 2000,2001 Carsten Pfeiffer <pfeiffer@kde.org>
5 Copyright (c) 2000 Stefan Schimanski <1Stein@gmx.de>
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License (LGPL) as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This library 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 GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21*/
22
23#include "khistorycombobox.h"
24
25#include <QtGui/QAbstractItemView>
26#include <QtGui/QApplication>
27#include <QtGui/QKeyEvent>
28#include <QtGui/QMenu>
29#include <QtGui/QWheelEvent>
30
31#include <klocale.h>
32#include <knotification.h>
33#include <kpixmapprovider.h>
34#include <kstandardshortcut.h>
35#include <kicontheme.h>
36#include <kicon.h>
37
38#include <kdebug.h>
39
40class KHistoryComboBox::Private
41{
42public:
43 Private(KHistoryComboBox *q): q(q), myPixProvider(0) {}
44
45 KHistoryComboBox *q;
46
50 int myIterateIndex;
51
55 QString myText;
56
61 bool myRotated;
62 KPixmapProvider *myPixProvider;
63};
64
65// we are always read-write
66KHistoryComboBox::KHistoryComboBox( QWidget *parent )
67 : KComboBox( true, parent ), d(new Private(this))
68{
69 init( true ); // using completion
70}
71
72// we are always read-write
73KHistoryComboBox::KHistoryComboBox( bool useCompletion,
74 QWidget *parent )
75 : KComboBox( true, parent ), d(new Private(this))
76{
77 init( useCompletion );
78}
79
80void KHistoryComboBox::init( bool useCompletion )
81{
82 // Set a default history size to something reasonable, Qt sets it to INT_MAX by default
83 setMaxCount( 50 );
84
85 if ( useCompletion )
86 completionObject()->setOrder( KCompletion::Weighted );
87
88 setInsertPolicy( NoInsert );
89 d->myIterateIndex = -1;
90 d->myRotated = false;
91 d->myPixProvider = 0L;
92
93 // obey HISTCONTROL setting
94 QByteArray histControl = qgetenv("HISTCONTROL");
95 if ( histControl == "ignoredups" || histControl == "ignoreboth" )
96 setDuplicatesEnabled( false );
97
98 connect(this, SIGNAL(aboutToShowContextMenu(QMenu*)), SLOT(addContextMenuItems(QMenu*)));
99 connect(this, SIGNAL(activated(int)), SLOT(slotReset()));
100 connect(this, SIGNAL(returnPressed(QString)), SLOT(slotReset()));
101 // We want slotSimulateActivated to be called _after_ QComboBoxPrivate::_q_returnPressed
102 // otherwise there's a risk of emitting activated twice (slotSimulateActivated will find
103 // the item, after some app's slotActivated inserted the item into the combo).
104 connect(this, SIGNAL(returnPressed(QString)), SLOT(slotSimulateActivated(QString)), Qt::QueuedConnection);
105}
106
107KHistoryComboBox::~KHistoryComboBox()
108{
109 delete d->myPixProvider;
110 delete d;
111}
112
113void KHistoryComboBox::setHistoryItems( const QStringList &items )
114{
115 setHistoryItems(items, false);
116}
117
118void KHistoryComboBox::setHistoryItems( const QStringList &items,
119 bool setCompletionList )
120{
121 QStringList insertingItems = items;
122 KComboBox::clear();
123
124 // limit to maxCount()
125 const int itemCount = insertingItems.count();
126 const int toRemove = itemCount - maxCount();
127
128 if (toRemove >= itemCount) {
129 insertingItems.clear();
130 } else {
131 for (int i = 0; i < toRemove; ++i)
132 insertingItems.pop_front();
133 }
134
135 insertItems( insertingItems );
136
137 if ( setCompletionList && useCompletion() ) {
138 // we don't have any weighting information here ;(
139 KCompletion *comp = completionObject();
140 comp->setOrder( KCompletion::Insertion );
141 comp->setItems( insertingItems );
142 comp->setOrder( KCompletion::Weighted );
143 }
144
145 clearEditText();
146}
147
148QStringList KHistoryComboBox::historyItems() const
149{
150 QStringList list;
151 const int itemCount = count();
152 for ( int i = 0; i < itemCount; ++i )
153 list.append( itemText( i ) );
154
155 return list;
156}
157
158bool KHistoryComboBox::useCompletion() const
159{
160 return compObj();
161}
162
163void KHistoryComboBox::clearHistory()
164{
165 const QString temp = currentText();
166 KComboBox::clear();
167 if ( useCompletion() )
168 completionObject()->clear();
169 setEditText( temp );
170}
171
172void KHistoryComboBox::addContextMenuItems( QMenu* menu )
173{
174 if ( menu )
175 {
176 menu->addSeparator();
177 QAction* clearHistory = menu->addAction( KIcon("edit-clear-history"), i18n("Clear &History"), this, SLOT(slotClear()));
178 if (!count())
179 clearHistory->setEnabled(false);
180 }
181}
182
183void KHistoryComboBox::addToHistory( const QString& item )
184{
185 if ( item.isEmpty() || (count() > 0 && item == itemText(0) )) {
186 return;
187 }
188
189 bool wasCurrent = false;
190 // remove all existing items before adding
191 if ( !duplicatesEnabled() ) {
192 int i = 0;
193 int itemCount = count();
194 while ( i < itemCount ) {
195 if ( itemText( i ) == item ) {
196 if ( !wasCurrent )
197 wasCurrent = ( i == currentIndex() );
198 removeItem( i );
199 --itemCount;
200 } else {
201 ++i;
202 }
203 }
204 }
205
206 // now add the item
207 if ( d->myPixProvider )
208 insertItem( 0, d->myPixProvider->pixmapFor(item, iconSize().height()), item);
209 else
210 insertItem( 0, item );
211
212 if ( wasCurrent )
213 setCurrentIndex( 0 );
214
215 const bool useComp = useCompletion();
216
217 const int last = count() - 1; // last valid index
218 const int mc = maxCount();
219 const int stopAt = qMax(mc, 0);
220
221 for (int rmIndex = last; rmIndex >= stopAt; --rmIndex) {
222 // remove the last item, as long as we are longer than maxCount()
223 // remove the removed item from the completionObject if it isn't
224 // anymore available at all in the combobox.
225 const QString rmItem = itemText( rmIndex );
226 removeItem( rmIndex );
227 if ( useComp && !contains( rmItem ) )
228 completionObject()->removeItem( rmItem );
229 }
230
231 if ( useComp )
232 completionObject()->addItem( item );
233}
234
235bool KHistoryComboBox::removeFromHistory( const QString& item )
236{
237 if ( item.isEmpty() )
238 return false;
239
240 bool removed = false;
241 const QString temp = currentText();
242 int i = 0;
243 int itemCount = count();
244 while ( i < itemCount ) {
245 if ( item == itemText( i ) ) {
246 removed = true;
247 removeItem( i );
248 --itemCount;
249 } else {
250 ++i;
251 }
252 }
253
254 if ( removed && useCompletion() )
255 completionObject()->removeItem( item );
256
257 setEditText( temp );
258 return removed;
259}
260
261// going up in the history, rotating when reaching QListBox::count()
262//
263// Note: this differs from QComboBox because "up" means ++index here,
264// to simulate the way shell history works (up goes to the most
265// recent item). In QComboBox "down" means ++index, to match the popup...
266//
267void KHistoryComboBox::rotateUp()
268{
269 // save the current text in the lineedit
270 // (This is also where this differs from standard up/down in QComboBox,
271 // where a single keypress can make you lose your typed text)
272 if ( d->myIterateIndex == -1 )
273 d->myText = currentText();
274
275 ++d->myIterateIndex;
276
277 // skip duplicates/empty items
278 const int last = count() - 1; // last valid index
279 const QString currText = currentText();
280
281 while ( d->myIterateIndex < last &&
282 (currText == itemText( d->myIterateIndex ) ||
283 itemText( d->myIterateIndex ).isEmpty()) )
284 ++d->myIterateIndex;
285
286 if ( d->myIterateIndex >= count() ) {
287 d->myRotated = true;
288 d->myIterateIndex = -1;
289
290 // if the typed text is the same as the first item, skip the first
291 if ( count() > 0 && d->myText == itemText(0) )
292 d->myIterateIndex = 0;
293
294 setEditText( d->myText );
295 } else {
296 setCurrentIndex(d->myIterateIndex);
297 }
298}
299
300// going down in the history, no rotation possible. Last item will be
301// the text that was in the lineedit before Up was called.
302void KHistoryComboBox::rotateDown()
303{
304 // save the current text in the lineedit
305 if ( d->myIterateIndex == -1 )
306 d->myText = currentText();
307
308 --d->myIterateIndex;
309
310 const QString currText = currentText();
311 // skip duplicates/empty items
312 while ( d->myIterateIndex >= 0 &&
313 (currText == itemText( d->myIterateIndex ) ||
314 itemText( d->myIterateIndex ).isEmpty()) )
315 --d->myIterateIndex;
316
317
318 if ( d->myIterateIndex < 0 ) {
319 if ( d->myRotated && d->myIterateIndex == -2 ) {
320 d->myRotated = false;
321 d->myIterateIndex = count() - 1;
322 setEditText( itemText(d->myIterateIndex) );
323 }
324 else { // bottom of history
325 if ( d->myIterateIndex == -2 ) {
326 KNotification::event( "Textcompletion: No Match" ,
327 i18n("No further items in the history."),
328 QPixmap() , this, KNotification::DefaultEvent);
329 }
330
331 d->myIterateIndex = -1;
332 if ( currentText() != d->myText )
333 setEditText( d->myText );
334 }
335 } else {
336 setCurrentIndex(d->myIterateIndex);
337 }
338}
339
340void KHistoryComboBox::keyPressEvent( QKeyEvent *e )
341{
342 int event_key = e->key() | e->modifiers();
343
344 if ( KStandardShortcut::rotateUp().contains(event_key) )
345 rotateUp();
346 else if ( KStandardShortcut::rotateDown().contains(event_key) )
347 rotateDown();
348 else
349 KComboBox::keyPressEvent( e );
350}
351
352void KHistoryComboBox::wheelEvent( QWheelEvent *ev )
353{
354 // Pass to poppable listbox if it's up
355 QAbstractItemView* const iv = view();
356 if ( iv && iv->isVisible() )
357 {
358 QApplication::sendEvent( iv, ev );
359 return;
360 }
361 // Otherwise make it change the text without emitting activated
362 if ( ev->delta() > 0 ) {
363 rotateUp();
364 } else {
365 rotateDown();
366 }
367 ev->accept();
368}
369
370void KHistoryComboBox::slotReset()
371{
372 d->myIterateIndex = -1;
373 d->myRotated = false;
374}
375
376
377void KHistoryComboBox::setPixmapProvider( KPixmapProvider *prov )
378{
379 if ( d->myPixProvider == prov )
380 return;
381
382 delete d->myPixProvider;
383 d->myPixProvider = prov;
384
385 // re-insert all the items with/without pixmap
386 // I would prefer to use changeItem(), but that doesn't honor the pixmap
387 // when using an editable combobox (what we do)
388 if ( count() > 0 ) {
389 QStringList items( historyItems() );
390 clear();
391 insertItems( items );
392 }
393}
394
395void KHistoryComboBox::insertItems( const QStringList& items )
396{
397 QStringList::ConstIterator it = items.constBegin();
398 const QStringList::ConstIterator itEnd = items.constEnd();
399
400 while ( it != itEnd ) {
401 const QString item = *it;
402 if ( !item.isEmpty() ) { // only insert non-empty items
403 if ( d->myPixProvider )
404 addItem( d->myPixProvider->pixmapFor(item, iconSize().height()),
405 item );
406 else
407 addItem( item );
408 }
409 ++it;
410 }
411}
412
413void KHistoryComboBox::slotClear()
414{
415 clearHistory();
416 emit cleared();
417}
418
419void KHistoryComboBox::slotSimulateActivated( const QString& text )
420{
421 /* With the insertion policy NoInsert, which we use by default,
422 Qt doesn't emit activated on typed text if the item is not already there,
423 which is perhaps reasonable. Generate the signal ourselves if that's the case.
424 */
425 if ((insertPolicy() == NoInsert && findText(text, Qt::MatchFixedString|Qt::MatchCaseSensitive) == -1)) {
426 emit activated(text);
427 }
428
429 /*
430 Qt also doesn't emit it if the box is full, and policy is not
431 InsertAtCurrent
432 */
433 else if (insertPolicy() != InsertAtCurrent && count() >= maxCount()) {
434 emit activated(text);
435 }
436}
437
438KPixmapProvider *KHistoryComboBox::pixmapProvider() const
439{
440 return d->myPixProvider;
441}
442
443void KHistoryComboBox::reset()
444{
445 slotReset();
446}
447
448#include "khistorycombobox.moc"
KComboBox::KComboBox
KComboBox(QWidget *parent=0)
Constructs a read-only or rather select-only combo box with a parent object and a name.
Definition kcombobox.cpp:57
KComboBox::aboutToShowContextMenu
void aboutToShowContextMenu(QMenu *p)
Emitted before the context menu is displayed.
KComboBox::contains
bool contains(const QString &text) const
Convenience method which iterates over all items and checks if any of them is equal to text.
Definition kcombobox.cpp:88
KComboBox::returnPressed
void returnPressed()
Emitted when the user presses the Enter key.
KCompletionBase::compObj
KCompletion * compObj() const
Returns a pointer to the completion object.
Definition kcompletionbase.cpp:220
KCompletionBase::completionObject
KCompletion * completionObject(bool hsig=true)
Returns a pointer to the current completion object.
Definition kcompletionbase.cpp:96
KCompletion
A generic class for completing QStrings.
Definition kcompletion.h:131
KCompletion::setItems
virtual void setItems(const QStringList &list)
Sets the list of items available for completion.
Definition kcompletion.cpp:99
KCompletion::removeItem
void removeItem(const QString &item)
Removes an item from the list of available completions.
Definition kcompletion.cpp:208
KCompletion::setOrder
virtual void setOrder(CompOrder order)
KCompletion offers three different ways in which it offers its items:
Definition kcompletion.cpp:78
KCompletion::Insertion
@ Insertion
Use order of insertion.
Definition kcompletion.h:144
KCompletion::Weighted
@ Weighted
Use weighted order.
Definition kcompletion.h:145
KCompletion::clear
virtual void clear()
Removes all inserted items.
Definition kcompletion.cpp:218
KCompletion::addItem
void addItem(const QString &item)
Adds an item to the list of available completions.
Definition kcompletion.cpp:146
KHistoryComboBox::setPixmapProvider
void setPixmapProvider(KPixmapProvider *prov)
Sets a pixmap provider, so that items in the combobox can have a pixmap.
Definition khistorycombobox.cpp:377
KHistoryComboBox::addToHistory
void addToHistory(const QString &item)
Adds an item to the end of the history list and to the completion list.
Definition khistorycombobox.cpp:183
KHistoryComboBox::historyItems
QStringList historyItems
Definition khistorycombobox.h:51
KHistoryComboBox::keyPressEvent
virtual void keyPressEvent(QKeyEvent *)
Handling key-events, the shortcuts to rotate the items.
Definition khistorycombobox.cpp:340
KHistoryComboBox::removeFromHistory
bool removeFromHistory(const QString &item)
Removes all items named item.
Definition khistorycombobox.cpp:235
KHistoryComboBox::pixmapProvider
KPixmapProvider * pixmapProvider() const
Definition khistorycombobox.cpp:438
KHistoryComboBox::clearHistory
void clearHistory()
Clears the history and the completion list.
Definition khistorycombobox.cpp:163
KHistoryComboBox::~KHistoryComboBox
~KHistoryComboBox()
Destructs the combo, the completion-object and the pixmap-provider.
Definition khistorycombobox.cpp:107
KHistoryComboBox::cleared
void cleared()
Emitted when the history was cleared by the entry in the popup menu.
KHistoryComboBox::KHistoryComboBox
KHistoryComboBox(QWidget *parent=0)
Constructs a "read-write" combobox.
Definition khistorycombobox.cpp:66
KHistoryComboBox::Private
friend class Private
Definition khistorycombobox.h:274
KHistoryComboBox::insertItems
void insertItems(const QStringList &items)
Inserts items into the combo, honoring pixmapProvider() Does not update the completionObject.
Definition khistorycombobox.cpp:395
KHistoryComboBox::setHistoryItems
void setHistoryItems(const QStringList &items)
Inserts items into the combobox.
Definition khistorycombobox.cpp:113
KHistoryComboBox::wheelEvent
virtual void wheelEvent(QWheelEvent *ev)
Handling wheel-events, to rotate the items.
Definition khistorycombobox.cpp:352
KHistoryComboBox::reset
void reset()
Resets the current position of the up/down history.
Definition khistorycombobox.cpp:443
KHistoryComboBox::useCompletion
bool useCompletion() const
Definition khistorycombobox.cpp:158
KIcon
A wrapper around QIcon that provides KDE icon features.
Definition kicon.h:41
KNotification::event
static KNotification * event(const QString &eventId, const QString &title, const QString &text, const QPixmap &pixmap=QPixmap(), QWidget *widget=0L, const NotificationFlags &flags=CloseOnTimeout, const KComponentData &componentData=KComponentData())
emit an event
Definition knotification.cpp:291
KNotification::DefaultEvent
@ DefaultEvent
Definition knotification.h:247
KPixmapProvider
A tiny abstract class with just one method: pixmapFor()
Definition kpixmapprovider.h:39
QAction
QMenu
QWidget
kdebug.h
khistorycombobox.h
kicon.h
kicontheme.h
setEditText
static void setEditText(KLineEdit *edit, const QString &text)
Definition klineedit.cpp:1454
klocale.h
i18n
QString i18n(const char *text)
knotification.h
kpixmapprovider.h
addItem
static void addItem(KServiceGroup::List &sorted, const KSycocaEntry::Ptr &p, bool &addSeparator)
kstandardshortcut.h
KStandardShortcut::rotateUp
const KShortcut & rotateUp()
Help users iterate through a list of entries.
Definition kstandardshortcut.cpp:366
KStandardShortcut::rotateDown
const KShortcut & rotateDown()
Help users iterate through a list of entries.
Definition kstandardshortcut.cpp:367
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Jan 17 2025 00:00:00 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
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