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

krdc

  • sources
  • kde-4.12
  • kdenetwork
  • krdc
floatingtoolbar.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2007-2008 Urs Wolfer <uwolfer @ kde.org>
4 ** Parts of this file have been take from okular:
5 ** Copyright (C) 2004-2005 Enrico Ros <eros.kde@email.it>
6 **
7 ** This file is part of KDE.
8 **
9 ** This program is free software; you can redistribute it and/or modify
10 ** it under the terms of the GNU General Public License as published by
11 ** the Free Software Foundation; either version 2 of the License, or
12 ** (at your option) any later version.
13 **
14 ** This program is distributed in the hope that it will be useful,
15 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ** GNU General Public License for more details.
18 **
19 ** You should have received a copy of the GNU General Public License
20 ** along with this program; see the file COPYING. If not, write to
21 ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 ** Boston, MA 02110-1301, USA.
23 **
24 ****************************************************************************/
25 
26 #include "floatingtoolbar.h"
27 
28 #include <KDebug>
29 #include <KGlobalSettings>
30 
31 #include <QApplication>
32 #include <QBitmap>
33 #include <QDesktopWidget>
34 #include <QMouseEvent>
35 #include <QPainter>
36 #include <QTimer>
37 
38 static const int actionIconSize = 22;
39 static const int toolBarRBMargin = 2;
40 static const double toolBarOpacity = 0.8;
41 static const int visiblePixelWhenAutoHidden = 6;
42 static const int autoHideTimeout = 500;
43 static const int initialAutoHideTimeout = 2000;
44 
48 enum AnimState {
49  Hiding,
50  Showing,
51  Still
52 };
53 
54 class FloatingToolBarPrivate
55 {
56 public:
57  FloatingToolBarPrivate(FloatingToolBar *qq)
58  : q(qq)
59  , anchorSide(FloatingToolBar::Left)
60  , offsetPlaceHolder(new QWidget(qq))
61  , animState(Still)
62  , toDelete(false)
63  , visible(false)
64  , sticky(false)
65  , opacity(toolBarOpacity)
66  // set queuedShow to true so we show the toolbar if we get a resize event on the anchorWidget
67  , queuedShow(true) {
68  }
69 
70  // rebuild contents and reposition then widget
71  void buildToolBar();
72  void reposition();
73  // compute the visible and hidden positions along current side
74  QPoint getInnerPoint() const;
75  QPoint getOuterPoint() const;
76 
77  FloatingToolBar *q;
78 
79  QWidget *anchorWidget;
80  FloatingToolBar::Side anchorSide;
81  QWidget *offsetPlaceHolder;
82 
83  QTimer *animTimer;
84  QTimer *autoHideTimer;
85  QPoint currentPosition;
86  QPoint endPosition;
87  AnimState animState;
88  bool toDelete;
89  bool visible;
90  bool sticky;
91  qreal opacity;
92  bool queuedShow;
93 
94  QPixmap backgroundPixmap;
95 };
96 
97 FloatingToolBar::FloatingToolBar(QWidget *parent, QWidget *anchorWidget)
98  : QToolBar(parent), d(new FloatingToolBarPrivate(this))
99 {
100  ;
101  addWidget(d->offsetPlaceHolder);
102 
103  setMouseTracking(true);
104  setIconSize(QSize(actionIconSize, actionIconSize));
105  d->anchorWidget = anchorWidget;
106 
107  d->animTimer = new QTimer(this);
108  connect(d->animTimer, SIGNAL(timeout()), this, SLOT(animate()));
109 
110  d->autoHideTimer = new QTimer(this);
111  connect(d->autoHideTimer, SIGNAL(timeout()), this, SLOT(hide()));
112 
113  // apply a filter to get notified when anchor changes geometry
114  d->anchorWidget->installEventFilter(this);
115 }
116 
117 FloatingToolBar::~FloatingToolBar()
118 {
119  delete d;
120 }
121 
122 void FloatingToolBar::addAction(QAction *action)
123 {
124  QToolBar::addAction(action);
125 
126  // rebuild toolbar shape and contents only if the toolbar is already visible,
127  // otherwise it will be done in showAndAnimate()
128  if (isVisible())
129  d->reposition();
130 }
131 
132 void FloatingToolBar::setSide(Side side)
133 {
134  d->anchorSide = side;
135 
136  if (isVisible())
137  d->reposition();
138 }
139 
140 void FloatingToolBar::setSticky(bool sticky)
141 {
142  d->sticky = sticky;
143 
144  if (sticky)
145  d->autoHideTimer->stop();
146 }
147 
148 void FloatingToolBar::showAndAnimate()
149 {
150  if (d->animState == Showing)
151  return;
152 
153  d->animState = Showing;
154 
155  show();
156 
157  // force update for case when toolbar has not been built yet
158  d->reposition();
159 
160  // start scrolling in
161  d->animTimer->start(20);
162 
163  // This permits to show the toolbar for a while when going full screen.
164  if (!d->sticky)
165  d->autoHideTimer->start(initialAutoHideTimeout);
166 }
167 
168 void FloatingToolBar::hideAndDestroy()
169 {
170  if (d->animState == Hiding)
171  return;
172 
173  // set parameters for sliding out
174  d->animState = Hiding;
175  d->toDelete = true;
176  d->endPosition = d->getOuterPoint();
177 
178  // start scrolling out
179  d->animTimer->start(20);
180 }
181 
182 void FloatingToolBar::hide()
183 {
184  if (underMouse())
185  return;
186 
187  if (d->visible) {
188  QPoint diff;
189  switch (d->anchorSide) {
190  case Left:
191  diff = QPoint(visiblePixelWhenAutoHidden, 0);
192  break;
193  case Right:
194  diff = QPoint(-visiblePixelWhenAutoHidden, 0);
195  break;
196  case Top:
197  diff = QPoint(0, visiblePixelWhenAutoHidden);
198  break;
199  case Bottom:
200  diff = QPoint(0, -visiblePixelWhenAutoHidden);
201  break;
202  }
203  d->animState = Hiding;
204  d->endPosition = d->getOuterPoint() + diff;
205 
206  // start scrolling out
207  d->animTimer->start(20);
208  }
209 }
210 
211 bool FloatingToolBar::eventFilter(QObject *obj, QEvent *e)
212 {
213  if (obj == d->anchorWidget && e->type() == QEvent::Resize) {
214  if (d->queuedShow) { // if the toolbar is not visible yet, try to show it if the anchor widget is in fullscreen already
215  d->queuedShow = false;
216  showAndAnimate();
217  return true;
218  }
219 
220  // if anchorWidget changed geometry reposition toolbar
221  d->animTimer->stop();
222  if ((d->animState == Hiding || !d->visible) && d->toDelete)
223  deleteLater();
224  else
225  d->reposition();
226  }
227 
228  return QToolBar::eventFilter(obj, e);
229 }
230 
231 void FloatingToolBar::paintEvent(QPaintEvent *e)
232 {
233  QToolBar::paintEvent(e);
234 
235  // paint the internal pixmap over the widget
236  QPainter p(this);
237  p.setOpacity(d->opacity);
238  p.drawImage(e->rect().topLeft(), d->backgroundPixmap.toImage(), e->rect());
239 }
240 
241 void FloatingToolBar::mousePressEvent(QMouseEvent *e)
242 {
243  if (e->button() == Qt::LeftButton)
244  setCursor(Qt::SizeAllCursor);
245 
246  QToolBar::mousePressEvent(e);
247 }
248 
249 void FloatingToolBar::mouseMoveEvent(QMouseEvent *e)
250 {
251  // show the toolbar again when it is auto-hidden
252  if (!d->visible) {
253  showAndAnimate();
254  return;
255  }
256 
257  if ((QApplication::mouseButtons() & Qt::LeftButton) != Qt::LeftButton)
258  return;
259 
260  // compute the nearest side to attach the widget to
261  const QPoint parentPos = mapToParent(e->pos());
262  const float nX = (float)parentPos.x() / (float)d->anchorWidget->width();
263  const float nY = (float)parentPos.y() / (float)d->anchorWidget->height();
264  if (nX > 0.3 && nX < 0.7 && nY > 0.3 && nY < 0.7)
265  return;
266  bool LT = nX < (1.0 - nY);
267  bool LB = nX < (nY);
268  Side side = LT ? (LB ? Left : Top) : (LB ? Bottom : Right);
269 
270  // check if side changed
271  if (side == d->anchorSide)
272  return;
273 
274  d->anchorSide = side;
275  d->reposition();
276  emit orientationChanged((int)side);
277 
278  QToolBar::mouseMoveEvent(e);
279 }
280 
281 void FloatingToolBar::enterEvent(QEvent *e)
282 {
283  // Stop the autohide timer while the mouse is inside
284  d->autoHideTimer->stop();
285 
286  if (!d->visible)
287  showAndAnimate();
288  QToolBar::enterEvent(e);
289 }
290 
291 void FloatingToolBar::leaveEvent(QEvent *e)
292 {
293  if (!d->sticky)
294  d->autoHideTimer->start(autoHideTimeout);
295  QToolBar::leaveEvent(e);
296 }
297 
298 void FloatingToolBar::mouseReleaseEvent(QMouseEvent *e)
299 {
300  if (e->button() == Qt::LeftButton)
301  setCursor(Qt::ArrowCursor);
302 
303  QToolBar::mouseReleaseEvent(e);
304 }
305 
306 void FloatingToolBar::wheelEvent(QWheelEvent *e)
307 {
308  e->accept();
309 
310  const qreal diff = e->delta() / 100.0 / 15.0;
311 // kDebug(5010) << diff;
312  if (((d->opacity <= 1) && (diff > 0)) || ((d->opacity >= 0) && (diff < 0)))
313  d->opacity += diff;
314 
315  update();
316 
317  QToolBar::wheelEvent(e);
318 }
319 
320 void FloatingToolBarPrivate::buildToolBar()
321 {
322  const bool prevUpdates = q->updatesEnabled();
323  q->setUpdatesEnabled(false);
324 
325  // 1. init numbers we are going to use
326  const bool topLeft = anchorSide == FloatingToolBar::Left || anchorSide == FloatingToolBar::Top;
327  const bool vertical = anchorSide == FloatingToolBar::Left || anchorSide == FloatingToolBar::Right;
328 
329  if (vertical) {
330  offsetPlaceHolder->setFixedSize(1, 7);
331  q->setOrientation(Qt::Vertical);
332  } else {
333  offsetPlaceHolder->setFixedSize(7, 1);
334  q->setOrientation(Qt::Horizontal);
335  }
336 
337  // 2. compute widget size
338  const int myWidth = q->sizeHint().width() - 1;
339  const int myHeight = q->sizeHint().height() - 1;
340 
341  // 3. resize pixmap, mask and widget
342  QBitmap mask(myWidth + 1, myHeight + 1);
343  backgroundPixmap = QPixmap(myWidth + 1, myHeight + 1);
344  backgroundPixmap.fill(Qt::transparent);
345 
346  q->resize(myWidth + 1, myHeight + 1);
347 
348  // 4. create and set transparency mask
349  QPainter maskPainter(&mask);
350  mask.fill(Qt::white);
351  maskPainter.setBrush(Qt::black);
352  if (vertical)
353  maskPainter.drawRoundRect(topLeft ? -10 : 0, 0, myWidth + 10, myHeight, 2000 / (myWidth + 10), 2000 / myHeight);
354  else
355  maskPainter.drawRoundRect(0, topLeft ? -10 : 0, myWidth, myHeight + 10, 2000 / myWidth, 2000 / (myHeight + 10));
356  maskPainter.end();
357  q->setMask(mask);
358 
359  // 5. draw background
360  QPainter bufferPainter(&backgroundPixmap);
361  bufferPainter.translate(0.5, 0.5);
362  QPalette pal = q->palette();
363  // 5.1. draw horizontal/vertical gradient
364  QLinearGradient grad;
365  switch (anchorSide) {
366  case FloatingToolBar::Left:
367  grad = QLinearGradient(0, 1, myWidth + 1, 1);
368  break;
369  case FloatingToolBar::Right:
370  grad = QLinearGradient(myWidth + 1, 1, 0, 1);
371  break;
372  case FloatingToolBar::Top:
373  grad = QLinearGradient(1, 0, 1, myHeight + 1);
374  break;
375  case FloatingToolBar::Bottom:
376  grad = QLinearGradient(1, myHeight + 1, 0, 1);
377  break;
378  }
379  grad.setColorAt(0, pal.color(QPalette::Active, QPalette::Button));
380  grad.setColorAt(1, pal.color(QPalette::Active, QPalette::Light));
381  bufferPainter.setBrush(QBrush(grad));
382  // 5.2. draw rounded border
383  bufferPainter.setPen( pal.color(QPalette::Active, QPalette::Dark).lighter(40));
384  bufferPainter.setRenderHints(QPainter::Antialiasing);
385  if (vertical)
386  bufferPainter.drawRoundRect(topLeft ? -10 : 0, 0, myWidth + 10, myHeight, 2000 / (myWidth + 10), 2000 / myHeight);
387  else
388  bufferPainter.drawRoundRect(0, topLeft ? -10 : 0, myWidth, myHeight + 10, 2000 / myWidth, 2000 / (myHeight + 10));
389  // 5.3. draw handle
390  bufferPainter.translate(-0.5, -0.5);
391  bufferPainter.setPen(pal.color(QPalette::Active, QPalette::Mid));
392  if (vertical) {
393  int dx = anchorSide == FloatingToolBar::Left ? 2 : 4;
394  bufferPainter.drawLine(dx, 6, dx + myWidth - 8, 6);
395  bufferPainter.drawLine(dx, 9, dx + myWidth - 8, 9);
396  bufferPainter.setPen(pal.color(QPalette::Active, QPalette::Light));
397  bufferPainter.drawLine(dx + 1, 7, dx + myWidth - 7, 7);
398  bufferPainter.drawLine(dx + 1, 10, dx + myWidth - 7, 10);
399  } else {
400  int dy = anchorSide == FloatingToolBar::Top ? 2 : 4;
401  bufferPainter.drawLine(6, dy, 6, dy + myHeight - 8);
402  bufferPainter.drawLine(9, dy, 9, dy + myHeight - 8);
403  bufferPainter.setPen(pal.color(QPalette::Active, QPalette::Light));
404  bufferPainter.drawLine(7, dy + 1, 7, dy + myHeight - 7);
405  bufferPainter.drawLine(10, dy + 1, 10, dy + myHeight - 7);
406  }
407 
408  q->setUpdatesEnabled(prevUpdates);
409 }
410 
411 void FloatingToolBarPrivate::reposition()
412 {
413  // note: hiding widget here will gives better gfx, but ends drag operation
414  // rebuild widget and move it to its final place
415  buildToolBar();
416  if (!visible) {
417  currentPosition = getOuterPoint();
418  endPosition = getInnerPoint();
419  } else {
420  currentPosition = getInnerPoint();
421  endPosition = getOuterPoint();
422  }
423  q->move(currentPosition);
424 }
425 
426 QPoint FloatingToolBarPrivate::getInnerPoint() const
427 {
428  // returns the final position of the widget
429  if (anchorSide == FloatingToolBar::Left)
430  return QPoint(0, (anchorWidget->height() - q->height()) / 2);
431  if (anchorSide == FloatingToolBar::Top)
432  return QPoint((anchorWidget->width() - q->width()) / 2, 0);
433  if (anchorSide == FloatingToolBar::Right)
434  return QPoint(anchorWidget->width() - q->width() + toolBarRBMargin, (anchorWidget->height() - q->height()) / 2);
435  return QPoint((anchorWidget->width() - q->width()) / 2, anchorWidget->height() - q->height() + toolBarRBMargin);
436 }
437 
438 QPoint FloatingToolBarPrivate::getOuterPoint() const
439 {
440  // returns the point from which the transition starts
441  if (anchorSide == FloatingToolBar::Left)
442  return QPoint(-q->width(), (anchorWidget->height() - q->height()) / 2);
443  if (anchorSide == FloatingToolBar::Top)
444  return QPoint((anchorWidget->width() - q->width()) / 2, -q->height());
445  if (anchorSide == FloatingToolBar::Right)
446  return QPoint(anchorWidget->width() + toolBarRBMargin, (anchorWidget->height() - q->height()) / 2);
447  return QPoint((anchorWidget->width() - q->width()) / 2, anchorWidget->height() + toolBarRBMargin);
448 }
449 
450 void FloatingToolBar::animate()
451 {
452  if (KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects) {
453  // move currentPosition towards endPosition
454  int dX = d->endPosition.x() - d->currentPosition.x();
455  int dY = d->endPosition.y() - d->currentPosition.y();
456  dX = dX / 6 + qMax(-1, qMin(1, dX));
457  dY = dY / 6 + qMax(-1, qMin(1, dY));
458  d->currentPosition.setX(d->currentPosition.x() + dX);
459  d->currentPosition.setY(d->currentPosition.y() + dY);
460  } else {
461  d->currentPosition = d->endPosition;
462  }
463 
464  move(d->currentPosition);
465 
466  // handle arrival to the end
467  if (d->currentPosition == d->endPosition) {
468  d->animTimer->stop();
469  switch (d->animState) {
470  case Hiding:
471  d->visible = false;
472  d->animState = Still;
473  if (d->toDelete)
474  deleteLater();
475  break;
476  case Showing:
477  d->visible = true;
478  d->animState = Still;
479  break;
480  default:
481  kDebug(5010) << "Illegal state";
482  }
483  }
484 }
485 
486 #include "floatingtoolbar.moc"
initialAutoHideTimeout
static const int initialAutoHideTimeout
Definition: floatingtoolbar.cpp:43
FloatingToolBar::mousePressEvent
void mousePressEvent(QMouseEvent *e)
Definition: floatingtoolbar.cpp:241
FloatingToolBar::Top
Definition: floatingtoolbar.h:46
toolBarRBMargin
static const int toolBarRBMargin
Definition: floatingtoolbar.cpp:39
toolBarOpacity
static const double toolBarOpacity
Definition: floatingtoolbar.cpp:40
FloatingToolBar::paintEvent
void paintEvent(QPaintEvent *)
Definition: floatingtoolbar.cpp:231
Hiding
Definition: floatingtoolbar.cpp:49
FloatingToolBar::hideAndDestroy
void hideAndDestroy()
Definition: floatingtoolbar.cpp:168
FloatingToolBar::wheelEvent
void wheelEvent(QWheelEvent *e)
Definition: floatingtoolbar.cpp:306
actionIconSize
static const int actionIconSize
Definition: floatingtoolbar.cpp:38
QWidget
AnimState
AnimState
Denotes the verious states of the animation.
Definition: floatingtoolbar.cpp:48
FloatingToolBar::Side
Side
Definition: floatingtoolbar.h:46
FloatingToolBar::showAndAnimate
void showAndAnimate()
Definition: floatingtoolbar.cpp:148
QObject
FloatingToolBar::eventFilter
bool eventFilter(QObject *o, QEvent *e)
Definition: floatingtoolbar.cpp:211
floatingtoolbar.h
FloatingToolBar
A toolbar widget that slides in from a side.
Definition: floatingtoolbar.h:38
FloatingToolBar::mouseReleaseEvent
void mouseReleaseEvent(QMouseEvent *e)
Definition: floatingtoolbar.cpp:298
QToolBar
FloatingToolBar::~FloatingToolBar
~FloatingToolBar()
Definition: floatingtoolbar.cpp:117
FloatingToolBar::enterEvent
void enterEvent(QEvent *e)
Definition: floatingtoolbar.cpp:281
FloatingToolBar::leaveEvent
void leaveEvent(QEvent *e)
Definition: floatingtoolbar.cpp:291
autoHideTimeout
static const int autoHideTimeout
Definition: floatingtoolbar.cpp:42
FloatingToolBar::orientationChanged
void orientationChanged(int side)
FloatingToolBar::setSticky
void setSticky(bool sticky)
Definition: floatingtoolbar.cpp:140
FloatingToolBar::addAction
void addAction(QAction *action)
Definition: floatingtoolbar.cpp:122
FloatingToolBar::Right
Definition: floatingtoolbar.h:46
FloatingToolBar::mouseMoveEvent
void mouseMoveEvent(QMouseEvent *e)
Definition: floatingtoolbar.cpp:249
FloatingToolBar::Bottom
Definition: floatingtoolbar.h:46
FloatingToolBar::Left
Definition: floatingtoolbar.h:46
Showing
Definition: floatingtoolbar.cpp:50
FloatingToolBar::setSide
void setSide(Side side)
Definition: floatingtoolbar.cpp:132
visiblePixelWhenAutoHidden
static const int visiblePixelWhenAutoHidden
Definition: floatingtoolbar.cpp:41
Still
Definition: floatingtoolbar.cpp:51
FloatingToolBar::FloatingToolBar
FloatingToolBar(QWidget *parent, QWidget *anchorWidget)
Definition: floatingtoolbar.cpp:97
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:54:04 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

krdc

Skip menu "krdc"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

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