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

kopete/libkopete

  • sources
  • kde-4.14
  • kdenetwork
  • kopete
  • libkopete
  • ui
kopetelistview.cpp
Go to the documentation of this file.
1 /*
2  kopetelistview.cpp - List View providing support for ListView::Items
3 
4  Copyright (c) 2004 by Engin AYDOGAN <engin@bzzzt.biz>
5  Copyright (c) 2004 by Richard Smith <kde@metafoo.co.uk>
6 
7  Kopete (c) 2004 by the Kopete developers <kopete-devel@kde.org>
8 
9  *************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  *************************************************************************
17 */
18 
19 #include "kopetelistview.h"
20 #include "kopetelistviewitem.h"
21 #include "kopeteuiglobal.h"
22 #include "kopeteglobal.h"
23 #include "kopetebehaviorsettings.h"
24 
25 #include <QApplication>
26 #include <QStyleOptionSlider>
27 #include <QStyle>
28 #include <QWheelEvent>
29 #include <QKeyEvent>
30 #include <QEvent>
31 #include <QHelpEvent>
32 #include <QDragMoveEvent>
33 #include <QTimerEvent>
34 #include <QMouseEvent>
35 #include <QTimer>
36 #include <QToolTip>
37 
38 #include <kdebug.h>
39 #include <kde_file.h>
40 
41 #include <utility>
42 #include <memory>
43 
44 namespace Kopete {
45 namespace UI {
46 namespace ListView {
47 
48 
49 class ListView::Private
50 {
51 public:
52  QTimer sortTimer;
54  bool smoothScrollingEnabled;
56  double smoothScrollingTimer;
58  double smoothScrollingTimerInterval;
61  double targetScrollBarValue;
64  double metaScrollBarCurrentValue;
66  double scrollBarAccelerationConstant;
68  int smoothScrollingLineStep;
70  int smoothScrollingPageStep;
72  int scrollBarSliderDragStartY;
74  bool mousePressed;
77  bool smoothScrollDragAutoScroll;
80  int smoothAutoScrollOffset;
83  QStyle::SubControl pressedControl;
86  int smoothScrollContinuousCounter;
88  int continuousLinePressTimer;
90  int continuousLinePressTimerWait;
92  int continuousLinePressTimerInterval;
94  int continuousPagePressTimer;
96  int continuousPagePressTimerWait;
98  int continuousPagePressTimerInterval;
100  int scrollAutoHideTimer;
102  int scrollAutoHideCounter;
104  int scrollAutoHideTimeout;
106  bool scrollAutoHide;
108  bool scrollHide;
110  int mouseNavigationOffset;
112  bool mouseNavigation;
114  Private()
115  : smoothScrollingEnabled(false),
116  smoothScrollingTimer(0),
117  smoothScrollingTimerInterval(30),
118  targetScrollBarValue(0),
119  metaScrollBarCurrentValue(0.0),
120  scrollBarAccelerationConstant(6.0),
121  smoothScrollingLineStep(0),
122  smoothScrollingPageStep(0),
123  scrollBarSliderDragStartY(0),
124  mousePressed(false),
125  smoothScrollDragAutoScroll(false),
126  smoothAutoScrollOffset(60),
127  pressedControl( QStyle::SC_None ),
128  smoothScrollContinuousCounter(0),
129  continuousLinePressTimer(0),
130  continuousLinePressTimerWait(10),
131  continuousLinePressTimerInterval(40),
132  continuousPagePressTimer(0),
133  continuousPagePressTimerWait(2),
134  continuousPagePressTimerInterval(200),
135  scrollAutoHideTimer(0),
136  scrollAutoHideCounter(10),
137  scrollAutoHideTimeout(10),
138  scrollAutoHide(false),
139  scrollHide(false),
140  mouseNavigationOffset(20),
141  mouseNavigation(false)
142  {}
143 };
144 
145 ListView::ListView( QWidget *parent )
146  : K3ListView( parent ), d( new Private )
147 {
148  connect( &d->sortTimer, SIGNAL(timeout()), this, SLOT(slotSort()) );
149 
150  // We have our own tooltips, don't use the default QListView ones
151  setShowToolTips( false );
152 
153  connect( this, SIGNAL(contextMenu(K3ListView*,Q3ListViewItem*,QPoint)),
154  SLOT(slotContextMenu(K3ListView*,Q3ListViewItem*,QPoint)) );
155  connect( this, SIGNAL(doubleClicked(Q3ListViewItem*)),
156  SLOT(slotDoubleClicked(Q3ListViewItem*)) );
157 
158  // set up flags for nicer painting
159  setAttribute( Qt::WA_StaticContents, false );
160 
161 
162  // clear the appropriate flags from the viewport - qt docs say we have to mask
163  // these flags out of the QListView to make weirdly painted list items work, but
164  // that doesn't do the job. masking them out of the viewport does.
165 // class MyWidget : public QWidget { public: using QWidget::clearWFlags; };
166 // static_cast<MyWidget*>( viewport() )->clearWFlags( WStaticContents );
167 // static_cast<MyWidget*>( viewport() )->setWFlags( WNoAutoErase );
168 
169  // The above causes compiler errors with the (broken) native TRU64 and IRIX compilers.
170  // This should make it compile for both platforms and still seems to work.
171  // This is, of course, a nasty hack, but it works, so...
172  static_cast<ListView*>(viewport())->setAttribute( Qt::WA_StaticContents, false );
173 
174  // init smooth scrolling
175  // NOTE: Disabled smooth scrolling in KDE4 because it is buggy -DarkShock
176  setSmoothScrolling( false );
177 }
178 
179 ListView::~ListView()
180 {
181  delete d;
182 }
183 
184 void ListView::slotDoubleClicked( Q3ListViewItem *item )
185 {
186  kDebug( 14000 ) ;
187 
188  if ( item )
189  setOpen( item, !isOpen( item ) );
190 }
191 
192 void ListView::slotContextMenu( K3ListView * /*listview*/,
193  Q3ListViewItem *item, const QPoint &/*point*/ )
194 {
195  if ( item && !item->isSelected() )
196  {
197  clearSelection();
198  item->setSelected( true );
199  }
200  if ( !item )
201  clearSelection();
202 
203 // if( Item *myItem = dynamic_cast<Item*>( item ) )
204  // TODO: myItem->contextMenu( point );
205 }
206 
207 void ListView::setShowTreeLines( bool bShowAsTree )
208 {
209  if ( bShowAsTree )
210  {
211  setRootIsDecorated( true );
212  setTreeStepSize( 20 );
213  }
214  else
215  {
216  setRootIsDecorated( false );
217  setTreeStepSize( 0 );
218  }
219  // TODO: relayout all items. their width may have changed, but they won't know about it.
220 }
221 
222 /* This is a small hack ensuring that only F2 triggers inline
223  * renaming. Won't win a beauty award, but whoever wrote it thinks
224  * relying on the fact that QListView intercepts and processes the
225  * F2 event through this event filter is sorta safe.
226  *
227  * Also use enter to execute the item since executed is not usually
228  * called when enter is pressed.
229  */
230 void ListView::keyPressEvent( QKeyEvent *e )
231 {
232  Q3ListViewItem *item = currentItem();
233  if ( (e->key() == Qt::Key_F2) && item && item->isVisible() )
234  rename( item, 0 );
235  else if ( (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) && item && item->isVisible() )
236  {
237  // must provide a point within the item; emitExecute checks for this
238  QPoint p = viewport()->mapToGlobal(itemRect(item).center());
239  emitExecute( currentItem(), p, 0 );
240  }
241  else
242  K3ListView::keyPressEvent(e);
243 }
244 
245 void ListView::delayedSort()
246 {
247  if ( !d->sortTimer.isActive() )
248  {
249  d->sortTimer.setSingleShot( true );
250  d->sortTimer.start( 500 );
251  }
252 }
253 
255 // Here begins the smooth scrolling hack
257 // What is this: This hack enables smooth scrolling, and intercepts all events that goes to scrollbar. Unless we do so, scrollbar
258 // will react to the mouse clicks and go _immedietly_ to the target value (i.e. next page) then when the smoothscroll
259 // takes effect the scrollbar slider will start to scroll smoothly, so the first slider movement due to scrollbar
260 // click causes a flickery. So we avoid all scrollbar events, and emulate them smoothly.
262 // Bugs: * Scroll bar loses it's onMouseOver color when we drag the scroll bar and move the mouse outside of the slider
263 // * Next/Prev page areas don't get mouse clicks, some styles gives some feedback on such an event
264 // and that feedback is unintentionally avoided by this hack. Many many contraints caused this choice.
265 // * Horizontal scroll bar seems to flicker when the scrollbars are being showed in auto-hide mode
267 
268 void ListView::setSmoothScrolling( bool b )
269 {
270  if( d->smoothScrollingEnabled == b ) // Is setting changed?
271  return; // If no, just return
272  else // else
273  d->smoothScrollingEnabled = b; // update the setting
274 
275  if( d->smoothScrollingEnabled ) // If enabled
276  {
277  // Intercept scrollbar's events
278  verticalScrollBar()->installEventFilter( this );
279  // Install the timer
280  d->smoothScrollingTimer = startTimer( (int)d->smoothScrollingTimerInterval );
281  // If we want to enable smooth scrolling when item has changed with keypresses etc, we need this
282  connect( this, SIGNAL(currentChanged(Q3ListViewItem*)), this, SLOT(slotCurrentChanged(Q3ListViewItem*)) );
283  // Disable autoscroll, we will do it the smooth way.
284  d->smoothScrollDragAutoScroll = dragAutoScroll();
285  setDragAutoScroll( false );
286  // Init the timers to simulate continuous press
287  d->continuousLinePressTimer = startTimer( d->continuousLinePressTimerInterval );
288  d->continuousPagePressTimer = startTimer( d->continuousPagePressTimerInterval );
289 
290  }
291  else // If disabled
292  {
293  // Uninstall the event interception from the scroll bar
294  verticalScrollBar()->removeEventFilter( this );
295  // Restore line/page step sizes
296  verticalScrollBar()->setSingleStep( d->smoothScrollingLineStep );
297  // Kill the already started timer
298  killTimer( (int)d->smoothScrollingTimer );
299  d->smoothScrollingTimer = 0;
300  // We don't need to list currentChanged anymore
301  disconnect( this, SIGNAL(currentChanged(Q3ListViewItem*)), this, SLOT(slotCurrentChanged(Q3ListViewItem*)) );
302  // Restore the autoscroll
303  setDragAutoScroll( d->smoothScrollDragAutoScroll );
304  // Kill the continuous press timers
305  killTimer( d->continuousLinePressTimer );
306  d->continuousLinePressTimer = 0;
307  killTimer( d->continuousPagePressTimer );
308  d->continuousPagePressTimer = 0;
309  }
310 }
311 
312 bool ListView::smoothScrolling() const
313 {
314  return d->smoothScrollingEnabled;
315 }
316 
317 void ListView::setSmoothScrollingTimerInterval( double i )
318 {
319  d->smoothScrollingTimerInterval = i;
320 }
321 
322 double ListView::smoothScrollingTimerInterval() const
323 {
324  return d->smoothScrollingTimerInterval;
325 }
326 
327 void ListView::setScrollAutoHide( bool b )
328 {
329  // If no change, just bail
330  if( d->scrollAutoHide == b ) return;
331 
332  if( b )
333  {
334  // Set scrollbar auto-hiding state true
335  d->scrollAutoHide = true;
336  // Turn of the bar now
337  setVScrollBarMode( AlwaysOff );
338  // Start the timer to handle auto-hide
339  killTimer( d->scrollAutoHideTimer );
340  d->scrollAutoHideTimer = startTimer( 1000 );
341  }
342  else
343  {
344  d->scrollAutoHide = false;
345  setVScrollBarMode( Auto );
346  killTimer( d->scrollAutoHideTimer );
347  }
348 }
349 
350 bool ListView::scrollAutoHide() const
351 {
352  return d->scrollAutoHide;
353 }
354 
355 void ListView::setScrollAutoHideTimeout( int t )
356 {
357  d->scrollAutoHideTimeout = t;
358 }
359 
360 int ListView::scrollAutoHideTimeout() const
361 {
362  return d->scrollAutoHideTimeout;
363 }
364 
365 void ListView::setScrollHide( bool b )
366 {
367  // if no change, just bail
368  if( d->scrollHide == b ) return;
369 
370  d->scrollHide = b;
371  if( b )
372  setVScrollBarMode( AlwaysOff );
373  else
374  setVScrollBarMode( Auto );
375 }
376 
377 bool ListView::scrollHide() const
378 {
379  return d->scrollHide;
380 }
381 
382 void ListView::setMouseNavigation( bool b )
383 {
384  d->mouseNavigation = b;
385 }
386 
387 bool ListView::mouseNavigation() const
388 {
389  return d->mouseNavigation;
390 }
391 
392 void ListView::timerEvent( QTimerEvent *e )
393 {
394  if( e->timerId() == d->smoothScrollingTimer )
395  { // This is a smooth scroll update
396  // Find how war we are away from the target scroll bar value and divide it by our constant (it can be both negative/positive)
397  double offset = static_cast<double>( ( d->targetScrollBarValue - d->metaScrollBarCurrentValue ) / d->scrollBarAccelerationConstant );
398  // Add the offset to our meta current value, this is the desired precise value
399  d->metaScrollBarCurrentValue += offset;
400  // Cast it to integer and update the vertical scroll bar value
401  verticalScrollBar()->setValue( static_cast<int>( d->metaScrollBarCurrentValue ) );
402  }
403  else if( e->timerId() == d->continuousLinePressTimer )
404  {
405  // If the button is being pressed for a longer time, get faster
406  // X = time spent untill continuous button press begins to take effect
407  // Wait for X more amount of time after the continuous button press actually begins, the start to accelerate the scrolling linearly
408  double acceleration = static_cast<double>( ( d->smoothScrollContinuousCounter - d->continuousLinePressTimerWait * 2 ) ) /
409  static_cast<double>( d->continuousLinePressTimerWait );
410  // Let's make sure if the acceleration coefficient is between 1 and 3
411  acceleration = qMax( 1.0, acceleration );
412  acceleration = qMin( 3.0, acceleration );
413 
414  // Check if any scrollbar buttons are being pressed right, if any, honor them
415  if( d->pressedControl == QStyle::SC_ScrollBarSubLine )
416  { // Check if the user has pressed for long enough to activate continuous mouse press effect
417  if( d->smoothScrollContinuousCounter++ > d->continuousLinePressTimerWait ) // pressed long enough ?
418  {
419  d->targetScrollBarValue -= d->smoothScrollingLineStep * acceleration; // if so start continuous scrolling
420  // Make sure the target value is not below the minimum range.
421  d->targetScrollBarValue = qMax( d->targetScrollBarValue, ( double ) verticalScrollBar()->minimum() );
422  }
423  }
424  else if( d->pressedControl == QStyle::SC_ScrollBarAddLine )
425  {
426  if( d->smoothScrollContinuousCounter++ > d->continuousLinePressTimerWait ) // pressed long enough ?
427  {
428  d->targetScrollBarValue += d->smoothScrollingLineStep * acceleration; // if so start continuous scrolling
429  // Make sure the target value is not aboce the maximum range.
430  d->targetScrollBarValue = qMin( d->targetScrollBarValue, ( double )verticalScrollBar()->maximum() );
431  }
432  }
433  }
434  else if( e->timerId() == d->continuousPagePressTimer )
435  {
436  // If the button is being pressed for a longer time, get faster
437  // X = time spent untill continuous button press begins to take effect
438  // Wait for X more amount of time after the continuous button press actually begins, the start to accelerate the scrolling linearly
439  double acceleration = static_cast<double>( ( d->smoothScrollContinuousCounter - d->continuousPagePressTimerWait * 2 ) ) /
440  static_cast<double>( d->continuousPagePressTimerWait );
441  // Let's make sure if the acceleration coefficient is between 1 and 3
442  acceleration = qMax( 1.0, acceleration );
443  acceleration = qMin( 3.0, acceleration );
444 
445  if( d->pressedControl == QStyle::SC_ScrollBarSubPage )
446  {
447  if( d->smoothScrollContinuousCounter++ > d->continuousPagePressTimerWait ) // pressed long enough ?
448  {
449  d->targetScrollBarValue -= d->smoothScrollingPageStep + acceleration; // if so start continuous scrolling
450  d->targetScrollBarValue = qMax( d->targetScrollBarValue, ( double )verticalScrollBar()->minimum() );
451  }
452  }
453  else if( d->pressedControl == QStyle::SC_ScrollBarAddPage )
454  {
455  if( d->smoothScrollContinuousCounter++ > d->continuousPagePressTimerWait ) // pressed long enough ?
456  {
457  d->targetScrollBarValue += d->smoothScrollingPageStep * acceleration; // if so start continuous scrolling
458  d->targetScrollBarValue = qMin( d->targetScrollBarValue, ( double )verticalScrollBar()->maximum() );
459  }
460  }
461  }
462  else if( e->timerId() == d->scrollAutoHideTimer )
463  {
464  if( !d->scrollAutoHideCounter-- )
465  setVScrollBarMode( AlwaysOff );
466  }
467 }
468 
469 bool ListView::eventFilter( QObject *o, QEvent *e )
470 {
471  if( o == verticalScrollBar() ) // Event's to scroll bar
472  {
473  // Our scroll bar
474  QScrollBar *bar = static_cast<QScrollBar*>(o);
475  if( e->type() == QEvent::Wheel )
476  {
477  // OK, this is a wheel event, let's get our QWheelEvent in an unsafe way, due to a bug in RTTI of QT.
478  QWheelEvent *event = static_cast<QWheelEvent*>(e);
479  // Set new target value
480  d->targetScrollBarValue -= event->delta();
481  // Make sure it's in the boundaries of scroll bar
482  d->targetScrollBarValue = qMax( d->targetScrollBarValue, ( double )bar->minimum() );
483  d->targetScrollBarValue = qMin( d->targetScrollBarValue, ( double )bar->maximum() );
484  return true; // Ignore the event
485  }
486  else if( e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonDblClick )
487  {
488  QMouseEvent* event = static_cast<QMouseEvent*>(e);
489  // We are intercepting all clicks and double clicks on the scrollbar. Unless we do so
490  // scroll bar immediately goes to the point wherever user's click requests it to.
491  // Then smooth scroll begins, and animates the scrolling, but since the scrollbar
492  // goes to the destionation point for a very small amount of time at the very beginning of
493  // the click, this causes flickering. So we intercept each click, and make the scroll bar
494  // go to it's destination by smoothly.
495 
497  // The slider handle's starting position.
498  QStyleOptionSlider qsos;
499  qsos.init( bar );
500  QRect sliderRect = style()->subControlRect( QStyle::CC_ScrollBar, &qsos, QStyle::SC_ScrollBarSlider, 0 );
501  int sliderStart = sliderRect.y();
502  // The slider handle's ending position
503  int sliderEnd = sliderStart + sliderRect.height();
504  // The slider handle's width
505  int width = sliderRect.width();
506  // This is masking the upper previous line button
507  QRect prevLineUpper( 0, 0, width, 15 );
508  // This is masking the previous page, which is between the upper previous line button and the slider
509  QRect prevPage( 0, 15, width, sliderStart - 15 );
510  // This is masking the next page, which is between bottom previous line and the slider
511  QRect nextPage( 0, sliderEnd, width, bar->height() - sliderEnd - 30 );
512  // This is masking the bottom previous line button
513  QRect prevLineBottom( 0, bar->height() - 30, width, 15 );
514  // This is masking the next line button
515  QRect nextLine( 0, bar->height() - 15, width, 30 );
516 
517  // Get page/line step sizes. You may ask, why we are not doing this in setSmoothScrolling
518  // the reason is, scroll bar might not be initialized at that moment. When we are receiving
519  // MouseButtonPress or such event, we're sure that it's initialized!
520  if( d->smoothScrollingLineStep == 0 && d->smoothScrollingPageStep == 0 ){
521  d->smoothScrollingLineStep = bar->singleStep();
522  d->smoothScrollingPageStep = bar->pageStep();
523  // Set page/line steps of the scroll bar to zero, we'll emulate them, smoothly!
524  // If we don't set this to 0, when we pass the event to the button, the scollbar
525  // will scroll the list too.
526  verticalScrollBar()->setSingleStep( 0 );
527  }
528 
529  // OK, now we can understand which partion of the scroll bar is clicked, and do the requested thing
530  // animated. Then set the step sizes to zero, and pass the event to the slider, so that user can
531  // feel like he/she really pressed the buttons (on click color change).
532 
533  switch( d->pressedControl )
534  {
535  case QStyle::SC_ScrollBarSlider:
536  d->scrollBarSliderDragStartY = event->y();
537  break;
538  case QStyle::SC_ScrollBarSubLine:
539  d->targetScrollBarValue -= d->smoothScrollingLineStep;
540  // Make sure if the targetScrollBarValue is in the scroll bar values range
541  d->targetScrollBarValue = qMax( d->targetScrollBarValue, ( double )verticalScrollBar()->minimum() );
542  return false; // pass the event to the scroll bar so the button gets "clicked"
543  break;
544  case QStyle::SC_ScrollBarSubPage:
545  d->targetScrollBarValue -= d->smoothScrollingPageStep;
546  // Make sure if the targetScrollBarValue is in the scroll bar values range
547  d->targetScrollBarValue = qMax( d->targetScrollBarValue, ( double )verticalScrollBar()->minimum() );
548  break;
549  case QStyle::SC_ScrollBarAddPage:
550  d->targetScrollBarValue += d->smoothScrollingPageStep;
551  // Make sure if the targetScrollBarValue is in the scroll bar values range
552  d->targetScrollBarValue = qMin( d->targetScrollBarValue, ( double )verticalScrollBar()->maximum() );
553  break;
554  case QStyle::SC_ScrollBarAddLine:
555  d->targetScrollBarValue += d->smoothScrollingLineStep;
556  // Make sure if the targetScrollBarValue is in the scroll bar values range
557  d->targetScrollBarValue = qMin( d->targetScrollBarValue, ( double )verticalScrollBar()->maximum() );
558  return false; // pass the event to the scroll bar so the button gets "clicked"
559  break;
560  default:
561  kDebug( 14010 ) << "Unhandled sub control";
562  }
563  return true; // Now, ignore the event.
564  }
565  else if( e->type() == QEvent::MouseMove )
566  {
567  // Get our QMouseEvent so that we can have our relative mouse position
568  QMouseEvent *event = static_cast<QMouseEvent*>(e);
569  if( d->pressedControl == QStyle::SC_ScrollBarSlider )
570  {
571  // Mouse movement distance for this MouseMove event
572  double delta = event->y() - d->scrollBarSliderDragStartY;
573  // Update the drag start value so in the next MouseMove event we can calculate new movement distance
574  d->scrollBarSliderDragStartY = event->y();
575  // The length which we can move the mouse over the bar
576  QStyleOptionSlider qsos;
577  qsos.init( bar );
578  QRect sliderRect = style()->subControlRect( QStyle::CC_ScrollBar, &qsos, QStyle::SC_ScrollBarSlider, 0 );
579  double scale = bar->geometry().height() - sliderRect.height() - 45;
580  // Scale it to scroll bar value
581  d->targetScrollBarValue += static_cast<int>( static_cast<double>( ( bar->maximum() / scale ) * delta ) );
582  }
583 
584  if( d->scrollAutoHide ) // If auto-hide scroll bar is enabled
585  {
586  d->scrollAutoHideCounter = 9999; // Mouse is dragging the scrollbar slider
587  }
588  }
589  else if( e->type() == QEvent::Enter )
590  {
591  if( d->scrollAutoHide ) // If auto-hide scroll bar is enabled
592  {
593  d->scrollAutoHideCounter = 9999; // Mouse is on the scroll bar
594  }
595  }
596  else if( e->type() == QEvent::Leave )
597  {
598  if( d->scrollAutoHide ) // If auto-hide scroll bar is enabled
599  { // show the scroll bar
600  d->scrollAutoHideCounter = d->scrollAutoHideTimeout; // Mouse is on the scroll bar
601  }
602  }
603  else if( e->type() == QEvent::MouseButtonRelease )
604  {
605  // Reset waiting counter. This is used to wait before simulating continuous mouse press
606  d->smoothScrollContinuousCounter = 0;
607  // Mark all buttons as not pressed now
608  d->pressedControl = QStyle::SC_None;
609  // Make sure if the targetScrollBarValue is in the scroll bar values range
610  d->targetScrollBarValue = qMax( d->targetScrollBarValue, ( double )bar->minimum() );
611  d->targetScrollBarValue = qMin( d->targetScrollBarValue, ( double )bar->maximum() );
612  return false; // Pass the release event to the scroll bar, which will put the buttons in off-state
613  }
614  else
615  {
616  return false; // Pass the event to the scroll bar
617  }
618  }
619  else if( o == viewport() )
620  {
621  if( e->type() == QEvent::MouseButtonPress )
622  {
623  // Mark that we have pressed the button. This will prevent the list from scrolling when
624  // the current item has changed due to mouse click. It's fine when the keypresses cause
625  // it scroll, but not mouse.
626  d->mousePressed = true;
627  }
628  else if( e->type() == QEvent::MouseButtonRelease )
629  {
630  d->mousePressed = false;
631  }
632  else if( e->type() == QEvent::DragMove )
633  {
634  // OK, user is dragging something in the list
635  QDragMoveEvent *event = static_cast<QDragMoveEvent*>(e);
636  if( event->pos().y() < d->smoothAutoScrollOffset )
637  { // If he's too close to the upper edge, let's smootly scroll up
638  d->targetScrollBarValue -= ( d->smoothAutoScrollOffset - event->pos().y() ) * d->scrollBarAccelerationConstant / 3;
639  }
640  else if( event->pos().y() > ( visibleHeight() - d->smoothAutoScrollOffset ) )
641  { // If he's too close to the bottom edege, then let's smoothle scroll down
642  d->targetScrollBarValue += ( event->pos().y() - visibleHeight() + d->smoothAutoScrollOffset ) * d->scrollBarAccelerationConstant / 3;
643  }
644  // Make sure if the targetScrollBarValue is in the scroll bar values range
645  d->targetScrollBarValue = qMax( d->targetScrollBarValue, ( double )verticalScrollBar()->minimum() );
646  d->targetScrollBarValue = qMin( d->targetScrollBarValue, ( double )verticalScrollBar()->maximum() );
647  }
648  else if( e->type() == QEvent::MouseMove ) // Activity detected ( used to aut-hide scroll bar )
649  {
650  // Get our QMouseEvent so that we can have our relative mouse position
651  QMouseEvent *event = static_cast<QMouseEvent*>(e);
652 
653  if( d->scrollAutoHide ) // If auto-hide scroll bar is enabled
654  {
655  setVScrollBarMode( Auto ); // show the scroll bar
656  d->scrollAutoHideCounter = 9999; // Mouse is on the contact list, so don't hide it
657  }
658 
659  if( d->mouseNavigation )
660  {
661  const double offset = static_cast<double>(visibleHeight())/50.0 + d->mouseNavigationOffset;
662  d->targetScrollBarValue = ( event->y() - offset ) * ( static_cast<double>(verticalScrollBar()->maximum()) /
663  ( static_cast<double>(visibleHeight()) - offset * 2 ) );
664  }
665  }
666  else if( e->type() == QEvent::Leave )
667  {
668  if( d->scrollAutoHide ) // If auto-hide scroll bar is enabled
669  {
670  d->scrollAutoHideCounter = d->scrollAutoHideTimeout; // Mouse left the contact list, hide it after timeout
671  }
672  }
673  else if( e->type() == QEvent::ToolTip )
674  {
675  QHelpEvent *helpEvent = static_cast<QHelpEvent *>(e);
676  if( Item *item = dynamic_cast<Item*>( itemAt( helpEvent->pos() ) ) )
677  {
678  QRect itemRegion = this->itemRect( item );
679 
680  uint leftMargin = this->treeStepSize() * ( item->depth() + ( this->rootIsDecorated() ? 1 : 0 ) ) + itemMargin();
681 
682  uint xAdjust = itemRegion.left() + leftMargin;
683  uint yAdjust = itemRegion.top();
684  QPoint relativePosition( helpEvent->pos().x() - xAdjust, helpEvent->pos().y() - yAdjust );
685 
686  std::pair<QString,QRect> toolTip = item->toolTip( relativePosition );
687  if ( toolTip.first.isEmpty() )
688  return false;
689 
690  toolTip.second.translate( xAdjust, yAdjust );
691 
692  QToolTip::showText( helpEvent->globalPos(), toolTip.first );
693  }
694  }
695 
696  return K3ListView::eventFilter( o, e ); // Pass the event to K3ListView
697  }
698  else
699  {
700 // kDebug( 14000 ) << "Unhandled event: [" << o << "][" << o->name() << "][" << o->metaObject()->className() << "][" << e->type() << "]";
701  return K3ListView::eventFilter( o, e ); // Pass the event to K3ListView
702  }
703 
704  return false;
705 }
706 
707 void ListView::slotCurrentChanged( Q3ListViewItem *item )
708 {
709  if( !item ) return;
710  // If the current item changed due to mouse click then don't center it in the listview. Do this just for key presses.
711  if( d->mousePressed ){ d->mousePressed = false; return; }
712  d->targetScrollBarValue = itemPos(item) - static_cast<double>(visibleHeight()/2.0) + item->height();
713  // Make sure it's in the boundaries of scroll bar
714  d->targetScrollBarValue = qMax( d->targetScrollBarValue, ( double )verticalScrollBar()->minimum() );
715  d->targetScrollBarValue = qMin( d->targetScrollBarValue, ( double )verticalScrollBar()->maximum() );
716 }
717 
718 
719 } // END namespace ListView
720 } // END namespace UI
721 } // END namespace Kopete
722 
723 #include "kopetelistview.moc"
724 
725 // vim: set noet ts=4 sts=4 sw=4:
QEvent
QWidget
QEvent::type
Type type() const
kopetelistview.h
Q3ListViewItem::isVisible
bool isVisible() const
QDragMoveEvent
QMouseEvent::y
int y() const
QWheelEvent
Kopete::UI::ListView::ListView::scrollAutoHide
bool scrollAutoHide() const
Gets scroll auto hide feature status.
Definition: kopetelistview.cpp:350
QScrollBar
QHelpEvent::pos
const QPoint & pos() const
Kopete::UI::ListView::ListView
Definition: kopetelistview.h:37
QRect::height
int height() const
QRect::y
int y() const
QAbstractSlider::pageStep
pageStep
QPoint
QMouseEvent
QToolTip::showText
void showText(const QPoint &pos, const QString &text, QWidget *w)
Kopete::UI::ListView::ListView::slotSort
void slotSort()
Calls QListView::sort()
Definition: kopetelistview.h:135
QPoint::x
int x() const
QPoint::y
int y() const
kopeteuiglobal.h
QWidget::geometry
geometry
QTimerEvent
QRect
Q3ListViewItem::setSelected
virtual void setSelected(bool s)
Q3ListViewItem
QTimer
QRect::top
int top() const
QObject
QHelpEvent::globalPos
const QPoint & globalPos() const
QRect::left
int left() const
Kopete::UI::ListView::ListView::setSmoothScrolling
void setSmoothScrolling(bool)
Sets the smooth scrolling.
Definition: kopetelistview.cpp:268
QAbstractSlider::minimum
minimum
K3ListView
QKeyEvent::key
int key() const
Q3ListViewItem::isSelected
bool isSelected() const
Kopete::UI::ListView::ListView::scrollAutoHideTimeout
int scrollAutoHideTimeout() const
Gets the scroll bar auto-hide timeout value.
Definition: kopetelistview.cpp:360
QKeyEvent
QRect::width
int width() const
QAbstractSlider::singleStep
singleStep
Kopete::UI::ListView::ListView::scrollHide
bool scrollHide() const
Gets always hide feature state.
Definition: kopetelistview.cpp:377
Q3ListViewItem::height
int height() const
kopetelistviewitem.h
QTimerEvent::timerId
int timerId() const
Kopete::UI::ListView::Item
List-view item composed of Component items.
Definition: kopetelistviewitem.h:396
QStyleOption::init
void init(const QWidget *widget)
Kopete::UI::ListView::ListView::mouseNavigation
bool mouseNavigation() const
Gets the mouse navigation status.
Definition: kopetelistview.cpp:387
QAbstractSlider::maximum
maximum
QHelpEvent
kopetebehaviorsettings.h
QWidget::height
height
kopeteglobal.h
QStyleOptionSlider
Q3ListViewItem::depth
int depth() const
Kopete::UI::ListView::ListView::smoothScrollingTimerInterval
double smoothScrollingTimerInterval() const
Gets the current update interval.
Definition: kopetelistview.cpp:322
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:29:19 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kopete/libkopete

Skip menu "kopete/libkopete"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdenetwork API Reference

Skip menu "kdenetwork API Reference"
  • kget
  • kopete
  •   kopete
  •   libkopete
  • krdc
  • krfb

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