• 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 
36 class TDECompletionBox::TDECompletionBoxPrivate
37 {
38 public:
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 
47 TDECompletionBox::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( TQ_NoFocus );
65 
66  setVScrollBarMode( Auto );
67  setHScrollBarMode( AlwaysOff );
68 
69  connect( this, TQT_SIGNAL( doubleClicked( TQListBoxItem * )),
70  TQT_SLOT( slotActivated( TQListBoxItem * )) );
71 
72  // grmbl, just TQListBox workarounds :[ Thanks Volker.
73  connect( this, TQT_SIGNAL( currentChanged( TQListBoxItem * )),
74  TQT_SLOT( slotCurrentChanged() ));
75  connect( this, TQT_SIGNAL( clicked( TQListBoxItem * )),
76  TQT_SLOT( slotItemClicked( TQListBoxItem * )) );
77 }
78 
79 TDECompletionBox::~TDECompletionBox()
80 {
81  d->m_parent = 0L;
82  delete d;
83 }
84 
85 TQStringList 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 
99 void TDECompletionBox::slotActivated( TQListBoxItem *item )
100 {
101  if ( !item )
102  return;
103 
104  hide();
105  emit activated( item->text() );
106 }
107 
108 bool TDECompletionBox::eventFilter( TQObject *o, TQEvent *e )
109 {
110  int type = e->type();
111 
112  if ( TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(d->m_parent) ) {
113  if ( isVisible() ) {
114  if ( type == TQEvent::KeyPress ) {
115  TQKeyEvent *ev = TQT_TQKEYEVENT( e );
116  switch ( ev->key() ) {
117  case Key_BackTab:
118  if ( d->tabHandling && (ev->state() == Qt::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() == Qt::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 = TQT_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() == Qt::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 = TQT_TQMOUSEEVENT( e );
234  if ( !rect().contains( ev->pos() )) // this widget
235  hide();
236 
237  if ( !d->emitSelected && currentItem() && !::tqqt_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 
250 void 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 
268 void 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 
300 void 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 
324 void TDECompletionBox::hide()
325 {
326  if ( d->m_parent )
327  tqApp->removeEventFilter( this );
328  d->cancelText = TQString::null;
329  TDEListBox::hide();
330 }
331 
332 TQRect 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_OBJECT_NAME_STRING) )
347  {
348  const TQComboBox* cb = static_cast<const TQComboBox*>(TQT_TQWIDGET_CONST(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 
376 TQSize TDECompletionBox::sizeHint() const
377 {
378  return calculateGeometry().size();
379 }
380 
381 void 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 
396 void TDECompletionBox::up()
397 {
398  if ( currentItem() > 0 )
399  setCurrentItem( currentItem() - 1 );
400 }
401 
402 void TDECompletionBox::pageDown()
403 {
404  int i = currentItem() + numItemsVisible();
405  i = i > (int)count() - 1 ? (int)count() - 1 : i;
406  setCurrentItem( i );
407 }
408 
409 void TDECompletionBox::pageUp()
410 {
411  int i = currentItem() - numItemsVisible();
412  i = i < 0 ? 0 : i;
413  setCurrentItem( i );
414 }
415 
416 void TDECompletionBox::home()
417 {
418  setCurrentItem( 0 );
419 }
420 
421 void TDECompletionBox::end()
422 {
423  setCurrentItem( count() -1 );
424 }
425 
426 void TDECompletionBox::setTabHandling( bool enable )
427 {
428  d->tabHandling = enable;
429 }
430 
431 bool TDECompletionBox::isTabHandling() const
432 {
433  return d->tabHandling;
434 }
435 
436 void TDECompletionBox::setCancelledText( const TQString& text )
437 {
438  d->cancelText = text;
439 }
440 
441 TQString TDECompletionBox::cancelledText() const
442 {
443  return d->cancelText;
444 }
445 
446 void TDECompletionBox::canceled()
447 {
448  if ( !d->cancelText.isNull() )
449  emit userCancelled( d->cancelText );
450  if ( isVisible() )
451  hide();
452 }
453 
454 class TDECompletionBoxItem : public TQListBoxItem
455 {
456 public:
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 
468 void 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 
477 void 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 
530 void TDECompletionBox::slotCurrentChanged()
531 {
532  d->down_workaround = false;
533 }
534 
535 void 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 
549 void TDECompletionBox::setActivateOnSelect(bool state)
550 {
551  d->emitSelected = state;
552 }
553 
554 bool TDECompletionBox::activateOnSelect() const
555 {
556  return d->emitSelected;
557 }
558 
559 void TDECompletionBox::virtual_hook( int id, void* data )
560 { TDEListBox::virtual_hook( id, data ); }
561 
562 #include "tdecompletionbox.moc"
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::end
void end()
Moves the selection down to the last item.
Definition: tdecompletionbox.cpp:421
TDECompletionBox::pageDown
void pageDown()
Moves the selection one page down.
Definition: tdecompletionbox.cpp:402
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::home
void home()
Moves the selection up to the first item.
Definition: tdecompletionbox.cpp:416
TDECompletionBox::insertItems
void insertItems(const TQStringList &items, int index=-1)
Inserts items into the box.
Definition: tdecompletionbox.cpp:468
TDECompletionBox::slotActivated
virtual void slotActivated(TQListBoxItem *)
Called when an item was activated.
Definition: tdecompletionbox.cpp:99
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::sizeAndPosition
void sizeAndPosition()
This properly sizes and positions the listbox.
Definition: tdecompletionbox.cpp:268
TDECompletionBox::activateOnSelect
bool activateOnSelect() const
Definition: tdecompletionbox.cpp:554
TDECompletionBox::setItems
void setItems(const TQStringList &items)
Clears the box and inserts items.
Definition: tdecompletionbox.cpp:477
TDECompletionBox::items
TQStringList items() const
Returns a list of all items currently in the box.
Definition: tdecompletionbox.cpp:85
TDEGlobalSettings::desktopGeometry
static TQRect desktopGeometry(const TQPoint &point)
TDECompletionBox::~TDECompletionBox
~TDECompletionBox()
Destroys the box.
Definition: tdecompletionbox.cpp:79
TDEListBox::doubleClicked
void doubleClicked(TQListBoxItem *item, const TQPoint &pos)
This signal gets emitted whenever the user double clicks into the listbox.
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::activated
void activated(const TQString &)
Emitted when an item was selected, contains the text of the selected item.
TDECompletionBox::TDECompletionBox
TDECompletionBox(TQWidget *parent, const char *name=0)
Constructs a TDECompletionBox.
Definition: tdecompletionbox.cpp:47
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::hide
virtual void hide()
Re-implemented for internal reasons.
Definition: tdecompletionbox.cpp:324
TDECompletionBox::show
virtual void show()
Re-implemented for internal reasons.
Definition: tdecompletionbox.cpp:300
TDECompletionBox::pageUp
void pageUp()
Moves the selection one page up.
Definition: tdecompletionbox.cpp:409
TDECompletionBox::isTabHandling
bool isTabHandling() const
Definition: tdecompletionbox.cpp:431
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::up
void up()
Moves the selection one line up or select the first item if nothing is selected yet.
Definition: tdecompletionbox.cpp:396
TDECompletionBox::cancelledText
TQString cancelledText() const
Definition: tdecompletionbox.cpp:441
TDEListBox
A variant of TQListBox that honors KDE's system-wide settings.
Definition: tdelistbox.h:40
TDECompletionBox::userCancelled
void userCancelled(const TQString &)
Emitted whenever the user chooses to ignore the available selections and close the this box...
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

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
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeui by doxygen 1.8.8
This website is maintained by Timothy Pearson.