• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeui
 

tdeui

  • tdeui
tdecompletionbox.cpp
1/* This file is part of the KDE libraries
2
3 Copyright (c) 2000,2001,2002 Carsten Pfeiffer <pfeiffer@kde.org>
4 Copyright (c) 2000 Stefan Schimanski <1Stein@gmx.de>
5 Copyright (c) 2000,2001,2002,2003,2004 Dawit Alemayehu <adawit@kde.org>
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library 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 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library 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
24#include <tqapplication.h>
25#include <tqcombobox.h>
26#include <tqevent.h>
27#include <tqstyle.h>
28
29#include <kdebug.h>
30#include <tdeconfig.h>
31#include <knotifyclient.h>
32#include <tdeglobalsettings.h>
33
34#include "tdecompletionbox.h"
35
36class TDECompletionBox::TDECompletionBoxPrivate
37{
38public:
39 TQWidget *m_parent; // necessary to set the focus back
40 TQString cancelText;
41 bool tabHandling;
42 bool down_workaround;
43 bool upwardBox;
44 bool emitSelected;
45};
46
47TDECompletionBox::TDECompletionBox( TQWidget *parent, const char *name )
48 :TDEListBox( parent, name, (WFlags)WType_Popup ), d(new TDECompletionBoxPrivate)
49{
50
51 d->m_parent = parent;
52 d->tabHandling = true;
53 d->down_workaround = false;
54 d->upwardBox = false;
55 d->emitSelected = true;
56
57 setColumnMode( 1 );
58 setLineWidth( 1 );
59 setFrameStyle( TQFrame::Box | TQFrame::Plain );
60
61 if ( parent )
62 setFocusProxy( parent );
63 else
64 setFocusPolicy( TQWidget::NoFocus );
65
66 setVScrollBarMode( Auto );
67 setHScrollBarMode( AlwaysOff );
68
69 connect( this, TQ_SIGNAL( doubleClicked( TQListBoxItem * )),
70 TQ_SLOT( slotActivated( TQListBoxItem * )) );
71
72 // grmbl, just TQListBox workarounds :[ Thanks Volker.
73 connect( this, TQ_SIGNAL( currentChanged( TQListBoxItem * )),
74 TQ_SLOT( slotCurrentChanged() ));
75 connect( this, TQ_SIGNAL( clicked( TQListBoxItem * )),
76 TQ_SLOT( slotItemClicked( TQListBoxItem * )) );
77}
78
79TDECompletionBox::~TDECompletionBox()
80{
81 d->m_parent = 0L;
82 delete d;
83}
84
85TQStringList TDECompletionBox::items() const
86{
87 TQStringList list;
88
89 const TQListBoxItem* currItem = firstItem();
90
91 while (currItem) {
92 list.append(currItem->text());
93 currItem = currItem->next();
94 }
95
96 return list;
97}
98
99void TDECompletionBox::slotActivated( TQListBoxItem *item )
100{
101 if ( !item )
102 return;
103
104 hide();
105 emit activated( item->text() );
106}
107
108bool TDECompletionBox::eventFilter( TQObject *o, TQEvent *e )
109{
110 int type = e->type();
111
112 if ( o == d->m_parent ) {
113 if ( isVisible() ) {
114 if ( type == TQEvent::KeyPress ) {
115 TQKeyEvent *ev = static_cast<TQKeyEvent*>( e );
116 switch ( ev->key() ) {
117 case Key_BackTab:
118 if ( d->tabHandling && (ev->state() == TQt::NoButton ||
119 (ev->state() & ShiftButton)) ) {
120 up();
121 ev->accept();
122 return true;
123 }
124 break;
125 case Key_Tab:
126 if ( d->tabHandling && (ev->state() == TQt::NoButton) ) {
127 down(); // Only on TAB!!
128 ev->accept();
129 return true;
130 }
131 break;
132 case Key_Down:
133 down();
134 ev->accept();
135 return true;
136 case Key_Up:
137 // If there is no selected item and we've popped up above
138 // our parent, select the first item when they press up.
139 if ( selectedItem() ||
140 mapToGlobal( TQPoint( 0, 0 ) ).y() >
141 d->m_parent->mapToGlobal( TQPoint( 0, 0 ) ).y() )
142 up();
143 else
144 down();
145 ev->accept();
146 return true;
147 case Key_Prior:
148 pageUp();
149 ev->accept();
150 return true;
151 case Key_Next:
152 pageDown();
153 ev->accept();
154 return true;
155 case Key_Escape:
156 canceled();
157 ev->accept();
158 return true;
159 case Key_Enter:
160 case Key_Return:
161 if ( ev->state() & ShiftButton ) {
162 hide();
163 ev->accept(); // Consume the Enter event
164 return true;
165 }
166 break;
167 case Key_End:
168 if ( ev->state() & ControlButton )
169 {
170 end();
171 ev->accept();
172 return true;
173 }
174 case Key_Home:
175 if ( ev->state() & ControlButton )
176 {
177 home();
178 ev->accept();
179 return true;
180 }
181 default:
182 break;
183 }
184 }
185 else if ( type == TQEvent::AccelOverride ) {
186 // Override any acceleartors that match
187 // the key sequences we use here...
188 TQKeyEvent *ev = static_cast<TQKeyEvent*>( e );
189 switch ( ev->key() ) {
190 case Key_Down:
191 case Key_Up:
192 case Key_Prior:
193 case Key_Next:
194 case Key_Escape:
195 case Key_Enter:
196 case Key_Return:
197 ev->accept();
198 return true;
199 break;
200 case Key_Tab:
201 case Key_BackTab:
202 if ( ev->state() == TQt::NoButton ||
203 (ev->state() & ShiftButton))
204 {
205 ev->accept();
206 return true;
207 }
208 break;
209 case Key_Home:
210 case Key_End:
211 if ( ev->state() & ControlButton )
212 {
213 ev->accept();
214 return true;
215 }
216 break;
217 default:
218 break;
219 }
220 }
221
222 // parent loses focus or gets a click -> we hide
223 else if ( type == TQEvent::FocusOut || type == TQEvent::Resize ||
224 type == TQEvent::Close || type == TQEvent::Hide ||
225 type == TQEvent::Move ) {
226 hide();
227 }
228 }
229 }
230
231 // any mouse-click on something else than "this" makes us hide
232 else if ( type == TQEvent::MouseButtonPress ) {
233 TQMouseEvent *ev = static_cast<TQMouseEvent*>( e );
234 if ( !rect().contains( ev->pos() )) // this widget
235 hide();
236
237 if ( !d->emitSelected && currentItem() && !::tqt_cast<TQScrollBar*>(o) )
238 {
239 emit highlighted( currentText() );
240 hide();
241 ev->accept(); // Consume the mouse click event...
242 return true;
243 }
244 }
245
246 return TDEListBox::eventFilter( o, e );
247}
248
249
250void TDECompletionBox::popup()
251{
252 if ( count() == 0 )
253 hide();
254 else {
255 ensureCurrentVisible();
256 bool block = signalsBlocked();
257 blockSignals( true );
258 setCurrentItem( 0 );
259 blockSignals( block );
260 clearSelection();
261 if ( !isVisible() )
262 show();
263 else if ( size().height() != sizeHint().height() )
264 sizeAndPosition();
265 }
266}
267
268void TDECompletionBox::sizeAndPosition()
269{
270 int currentGeom = height();
271 TQPoint currentPos = pos();
272 TQRect geom = calculateGeometry();
273 resize( geom.size() );
274
275 int x = currentPos.x(), y = currentPos.y();
276 if ( d->m_parent ) {
277 if ( !isVisible() ) {
278 TQRect screenSize = TDEGlobalSettings::desktopGeometry(d->m_parent);
279
280 TQPoint orig = d->m_parent->mapToGlobal( TQPoint(0, d->m_parent->height()) );
281 x = orig.x() + geom.x();
282 y = orig.y() + geom.y();
283
284 if ( x + width() > screenSize.right() )
285 x = screenSize.right() - width();
286 if (y + height() > screenSize.bottom() ) {
287 y = y - height() - d->m_parent->height();
288 d->upwardBox = true;
289 }
290 }
291 else {
292 // Are we above our parent? If so we must keep bottom edge anchored.
293 if (d->upwardBox)
294 y += (currentGeom-height());
295 }
296 move( x, y);
297 }
298}
299
300void TDECompletionBox::show()
301{
302 d->upwardBox = false;
303 if ( d->m_parent ) {
304 sizeAndPosition();
305 tqApp->installEventFilter( this );
306 }
307
308 // ### we shouldn't need to call this, but without this, the scrollbars
309 // are pretty b0rked.
310 //triggerUpdate( true );
311
312 // Workaround for I'm not sure whose bug - if this TDECompletionBox' parent
313 // is in a layout, that layout will detect inserting new child (posted
314 // ChildInserted event), and will trigger relayout (post LayoutHint event).
315 // TQWidget::show() sends also posted ChildInserted events for the parent,
316 // and later all LayoutHint events, which causes layout updating.
317 // The problem is, TDECompletionBox::eventFilter() detects resizing
318 // of the parent, and calls hide() - and this hide() happen in the middle
319 // of show(), causing inconsistent state. I'll try to submit a Qt patch too.
320 tqApp->sendPostedEvents();
321 TDEListBox::show();
322}
323
324void TDECompletionBox::hide()
325{
326 if ( d->m_parent )
327 tqApp->removeEventFilter( this );
328 d->cancelText = TQString::null;
329 TDEListBox::hide();
330}
331
332TQRect TDECompletionBox::calculateGeometry() const
333{
334 int x = 0, y = 0;
335 int ih = itemHeight();
336 int h = TQMIN( 15 * ih, (int) count() * ih ) + 2*frameWidth();
337
338 int w = (d->m_parent) ? d->m_parent->width() : TDEListBox::minimumSizeHint().width();
339 w = TQMAX( TDEListBox::minimumSizeHint().width(), w );
340
341 //If we're inside a combox, Qt by default makes the dropdown
342 // as wide as the combo, and gives the style a chance
343 // to adjust it. Do that here as well, for consistency
344 const TQObject* combo;
345 if ( d->m_parent && (combo = d->m_parent->parent() ) &&
346 combo->inherits("TQComboBox") )
347 {
348 const TQComboBox* cb = static_cast<const TQComboBox*>(combo);
349
350 //Expand to the combo width
351 w = TQMAX( w, cb->width() );
352
353 TQPoint parentCorner = d->m_parent->mapToGlobal(TQPoint(0, 0));
354 TQPoint comboCorner = cb->mapToGlobal(TQPoint(0, 0));
355
356 //We need to adjust our horizontal position to also be WRT to the combo
357 x += comboCorner.x() - parentCorner.x();
358
359 //The same with vertical one
360 y += cb->height() - d->m_parent->height() +
361 comboCorner.y() - parentCorner.y();
362
363 //Ask the style to refine this a bit
364 TQRect styleAdj = style().querySubControlMetrics(TQStyle::CC_ComboBox,
365 cb, TQStyle::SC_ComboBoxListBoxPopup,
366 TQStyleOption(x, y, w, h));
367 //TQCommonStyle returns TQRect() by default, so this is what we get if the
368 //style doesn't implement this
369 if (!styleAdj.isNull())
370 return styleAdj;
371
372 }
373 return TQRect(x, y, w, h);
374}
375
376TQSize TDECompletionBox::sizeHint() const
377{
378 return calculateGeometry().size();
379}
380
381void TDECompletionBox::down()
382{
383 int i = currentItem();
384
385 if ( i == 0 && d->down_workaround ) {
386 d->down_workaround = false;
387 setCurrentItem( 0 );
388 setSelected( 0, true );
389 emit highlighted( currentText() );
390 }
391
392 else if ( i < (int) count() - 1 )
393 setCurrentItem( i + 1 );
394}
395
396void TDECompletionBox::up()
397{
398 if ( currentItem() > 0 )
399 setCurrentItem( currentItem() - 1 );
400}
401
402void TDECompletionBox::pageDown()
403{
404 int i = currentItem() + numItemsVisible();
405 i = i > (int)count() - 1 ? (int)count() - 1 : i;
406 setCurrentItem( i );
407}
408
409void TDECompletionBox::pageUp()
410{
411 int i = currentItem() - numItemsVisible();
412 i = i < 0 ? 0 : i;
413 setCurrentItem( i );
414}
415
416void TDECompletionBox::home()
417{
418 setCurrentItem( 0 );
419}
420
421void TDECompletionBox::end()
422{
423 setCurrentItem( count() -1 );
424}
425
426void TDECompletionBox::setTabHandling( bool enable )
427{
428 d->tabHandling = enable;
429}
430
431bool TDECompletionBox::isTabHandling() const
432{
433 return d->tabHandling;
434}
435
436void TDECompletionBox::setCancelledText( const TQString& text )
437{
438 d->cancelText = text;
439}
440
441TQString TDECompletionBox::cancelledText() const
442{
443 return d->cancelText;
444}
445
446void TDECompletionBox::canceled()
447{
448 if ( !d->cancelText.isNull() )
449 emit userCancelled( d->cancelText );
450 if ( isVisible() )
451 hide();
452}
453
454class TDECompletionBoxItem : public TQListBoxItem
455{
456public:
457 //Returns true if dirty.
458 bool reuse( const TQString& newText )
459 {
460 if ( text() == newText )
461 return false;
462 setText( newText );
463 return true;
464 }
465};
466
467
468void TDECompletionBox::insertItems( const TQStringList& items, int index )
469{
470 bool block = signalsBlocked();
471 blockSignals( true );
472 insertStringList( items, index );
473 blockSignals( block );
474 d->down_workaround = true;
475}
476
477void TDECompletionBox::setItems( const TQStringList& items )
478{
479 bool block = signalsBlocked();
480 blockSignals( true );
481
482 TQListBoxItem* item = firstItem();
483 if ( !item ) {
484 insertStringList( items );
485 }
486 else {
487 //Keep track of whether we need to change anything,
488 //so we can avoid a repaint for identical updates,
489 //to reduce flicker
490 bool dirty = false;
491
492 TQStringList::ConstIterator it = items.constBegin();
493 const TQStringList::ConstIterator itEnd = items.constEnd();
494
495 for ( ; it != itEnd; ++it) {
496 if ( item ) {
497 const bool changed = ((TDECompletionBoxItem*)item)->reuse( *it );
498 dirty = dirty || changed;
499 item = item->next();
500 }
501 else {
502 dirty = true;
503 //Inserting an item is a way of making this dirty
504 insertItem( new TQListBoxText( *it ) );
505 }
506 }
507
508 //If there is an unused item, mark as dirty -> less items now
509 if ( item ) {
510 dirty = true;
511 }
512
513 TQListBoxItem* tmp = item;
514 while ( (item = tmp ) ) {
515 tmp = item->next();
516 delete item;
517 }
518
519 if (dirty)
520 triggerUpdate( false );
521 }
522
523 if ( isVisible() && size().height() != sizeHint().height() )
524 sizeAndPosition();
525
526 blockSignals( block );
527 d->down_workaround = true;
528}
529
530void TDECompletionBox::slotCurrentChanged()
531{
532 d->down_workaround = false;
533}
534
535void TDECompletionBox::slotItemClicked( TQListBoxItem *item )
536{
537 if ( item )
538 {
539 if ( d->down_workaround ) {
540 d->down_workaround = false;
541 emit highlighted( item->text() );
542 }
543
544 hide();
545 emit activated( item->text() );
546 }
547}
548
549void TDECompletionBox::setActivateOnSelect(bool state)
550{
551 d->emitSelected = state;
552}
553
554bool TDECompletionBox::activateOnSelect() const
555{
556 return d->emitSelected;
557}
558
559void TDECompletionBox::virtual_hook( int id, void* data )
560{ TDEListBox::virtual_hook( id, data ); }
561
562#include "tdecompletionbox.moc"
TDECompletionBox::hide
virtual void hide()
Re-implemented for internal reasons.
Definition: tdecompletionbox.cpp:324
TDECompletionBox::userCancelled
void userCancelled(const TQString &)
Emitted whenever the user chooses to ignore the available selections and close the this box.
TDECompletionBox::cancelledText
TQString cancelledText() const
Definition: tdecompletionbox.cpp:441
TDECompletionBox::~TDECompletionBox
~TDECompletionBox()
Destroys the box.
Definition: tdecompletionbox.cpp:79
TDECompletionBox::TDECompletionBox
TDECompletionBox(TQWidget *parent, const char *name=0)
Constructs a TDECompletionBox.
Definition: tdecompletionbox.cpp:47
TDECompletionBox::activated
void activated(const TQString &)
Emitted when an item was selected, contains the text of the selected item.
TDECompletionBox::slotActivated
virtual void slotActivated(TQListBoxItem *)
Called when an item was activated.
Definition: tdecompletionbox.cpp:99
TDECompletionBox::down
void down()
Moves the selection one line down or select the first item if nothing is selected yet.
Definition: tdecompletionbox.cpp:381
TDECompletionBox::setItems
void setItems(const TQStringList &items)
Clears the box and inserts items.
Definition: tdecompletionbox.cpp:477
TDECompletionBox::eventFilter
virtual bool eventFilter(TQObject *, TQEvent *)
Reimplemented from TDEListBox to get events from the viewport (to hide this widget on mouse-click,...
Definition: tdecompletionbox.cpp:108
TDECompletionBox::pageDown
void pageDown()
Moves the selection one page down.
Definition: tdecompletionbox.cpp:402
TDECompletionBox::setActivateOnSelect
void setActivateOnSelect(bool state)
Set whether or not the selected signal should be emitted when an item is selected.
Definition: tdecompletionbox.cpp:549
TDECompletionBox::up
void up()
Moves the selection one line up or select the first item if nothing is selected yet.
Definition: tdecompletionbox.cpp:396
TDECompletionBox::setCancelledText
void setCancelledText(const TQString &txt)
Sets the text to be emitted if the user chooses not to pick from the available matches.
Definition: tdecompletionbox.cpp:436
TDECompletionBox::home
void home()
Moves the selection up to the first item.
Definition: tdecompletionbox.cpp:416
TDECompletionBox::popup
virtual void popup()
Adjusts the size of the box to fit the width of the parent given in the constructor and pops it up at...
Definition: tdecompletionbox.cpp:250
TDECompletionBox::calculateGeometry
TQRect calculateGeometry() const
This calculates the size of the dropdown and the relative position of the top left corner with respec...
Definition: tdecompletionbox.cpp:332
TDECompletionBox::insertItems
void insertItems(const TQStringList &items, int index=-1)
Inserts items into the box.
Definition: tdecompletionbox.cpp:468
TDECompletionBox::pageUp
void pageUp()
Moves the selection one page up.
Definition: tdecompletionbox.cpp:409
TDECompletionBox::setTabHandling
void setTabHandling(bool enable)
Makes this widget (when visible) capture Tab-key events to traverse the items in the dropdown list.
Definition: tdecompletionbox.cpp:426
TDECompletionBox::activateOnSelect
bool activateOnSelect() const
Definition: tdecompletionbox.cpp:554
TDECompletionBox::show
virtual void show()
Re-implemented for internal reasons.
Definition: tdecompletionbox.cpp:300
TDECompletionBox::end
void end()
Moves the selection down to the last item.
Definition: tdecompletionbox.cpp:421
TDECompletionBox::isTabHandling
bool isTabHandling() const
Definition: tdecompletionbox.cpp:431
TDECompletionBox::items
TQStringList items() const
Returns a list of all items currently in the box.
Definition: tdecompletionbox.cpp:85
TDECompletionBox::sizeAndPosition
void sizeAndPosition()
This properly sizes and positions the listbox.
Definition: tdecompletionbox.cpp:268
TDEGlobalSettings::desktopGeometry
static TQRect desktopGeometry(const TQPoint &point)
TDEListBox
A variant of TQListBox that honors KDE's system-wide settings.
Definition: tdelistbox.h:41
TDEListBox::doubleClicked
void doubleClicked(TQListBoxItem *item, const TQPoint &pos)
This signal gets emitted whenever the user double clicks into the listbox.

tdeui

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

tdeui

Skip menu "tdeui"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeui by doxygen 1.9.4
This website is maintained by Timothy Pearson.