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

Plasma

  • sources
  • kde-4.12
  • kdelibs
  • plasma
  • widgets
toolbutton.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Marco Martin <notmart@gmail.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Library General Public License as
6  * published by the Free Software Foundation; either version 2, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this program; if not, write to the
16  * Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19 
20 #include "toolbutton.h"
21 
22 #include <QDir>
23 #include <QPainter>
24 #include <QPropertyAnimation>
25 #include <QStyleOptionGraphicsItem>
26 #include <QToolButton>
27 
28 #include <kcolorutils.h>
29 #include <kicon.h>
30 #include <kiconeffect.h>
31 #include <kmimetype.h>
32 
33 #include "animator.h"
34 #include "framesvg.h"
35 #include "paintutils.h"
36 #include "private/actionwidgetinterface_p.h"
37 #include "private/themedwidgetinterface_p.h"
38 #include "theme.h"
39 
40 namespace Plasma
41 {
42 
43 class ToolButtonPrivate : public ActionWidgetInterface<ToolButton>
44 {
45 public:
46  ToolButtonPrivate(ToolButton *toolButton)
47  : ActionWidgetInterface<ToolButton>(toolButton),
48  background(0),
49  svg(0),
50  underMouse(false)
51  {
52  }
53 
54  ~ToolButtonPrivate()
55  {
56  delete svg;
57  }
58 
59  void setPixmap()
60  {
61  if (imagePath.isEmpty()) {
62  delete svg;
63  svg = 0;
64  return;
65  }
66 
67  KMimeType::Ptr mime = KMimeType::findByPath(absImagePath);
68  QPixmap pm;
69 
70  if (mime->is("image/svg+xml") || mime->is("image/svg+xml-compressed")) {
71  if (!svg || svg->imagePath() != absImagePath) {
72  delete svg;
73  svg = new Svg();
74  svg->setImagePath(imagePath);
75  QObject::connect(svg, SIGNAL(repaintNeeded()), q, SLOT(setPixmap()));
76  if (!svgElement.isNull()) {
77  svg->setContainsMultipleImages(true);
78  }
79  }
80 
81  //QPainter p(&pm);
82  if (!svgElement.isNull() && svg->hasElement(svgElement)) {
83  QSizeF elementSize = svg->elementSize(svgElement);
84  float scale = pm.width() / qMax(elementSize.width(), elementSize.height());
85 
86  svg->resize(svg->size() * scale);
87  pm = svg->pixmap(svgElement);
88  } else {
89  svg->resize(pm.size());
90  pm = svg->pixmap();
91  }
92  } else {
93  delete svg;
94  svg = 0;
95  pm = QPixmap(absImagePath);
96  }
97 
98  static_cast<QToolButton*>(q->widget())->setIcon(KIcon(pm));
99  }
100 
101  void syncActiveRect();
102  void syncBorders();
103  void animationUpdate(qreal progress);
104 
105  FrameSvg *background;
106  QPropertyAnimation *animation;
107  qreal opacity;
108  QRectF activeRect;
109 
110  QString imagePath;
111  QString absImagePath;
112  Svg *svg;
113  QString svgElement;
114  bool underMouse;
115 };
116 
117 void ToolButtonPrivate::syncActiveRect()
118 {
119  background->setElementPrefix("normal");
120 
121  qreal left, top, right, bottom;
122  background->getMargins(left, top, right, bottom);
123 
124  background->setElementPrefix("active");
125  qreal activeLeft, activeTop, activeRight, activeBottom;
126  background->getMargins(activeLeft, activeTop, activeRight, activeBottom);
127 
128  activeRect = QRectF(QPointF(0, 0), q->size());
129  activeRect.adjust(left - activeLeft, top - activeTop,
130  -(right - activeRight), -(bottom - activeBottom));
131 
132  background->setElementPrefix("normal");
133 }
134 
135 void ToolButtonPrivate::syncBorders()
136 {
137  //set margins from the normal element
138  qreal left, top, right, bottom;
139 
140  background->setElementPrefix("normal");
141  background->getMargins(left, top, right, bottom);
142  q->setContentsMargins(left, top, right, bottom);
143 
144  //calc the rect for the over effect
145  syncActiveRect();
146 }
147 
148 void ToolButtonPrivate::animationUpdate(qreal progress)
149 {
150  opacity = progress;
151 
152  // explicit update
153  q->update();
154 }
155 
156 ToolButton::ToolButton(QGraphicsWidget *parent)
157  : QGraphicsProxyWidget(parent),
158  d(new ToolButtonPrivate(this))
159 {
160  d->background = new FrameSvg(this);
161  d->background->setImagePath("widgets/button");
162  d->background->setCacheAllRenderedFrames(true);
163  d->background->setElementPrefix("normal");
164 
165  QToolButton *native = new QToolButton;
166  connect(native, SIGNAL(clicked()), this, SIGNAL(clicked()));
167  connect(native, SIGNAL(pressed()), this, SIGNAL(pressed()));
168  connect(native, SIGNAL(released()), this, SIGNAL(released()));
169  setWidget(native);
170  native->setWindowIcon(QIcon());
171  native->setAttribute(Qt::WA_NoSystemBackground);
172  native->setAutoRaise(true);
173 
174  d->syncBorders();
175  setAcceptHoverEvents(true);
176  connect(d->background, SIGNAL(repaintNeeded()), SLOT(syncBorders()));
177 
178  d->animation = new QPropertyAnimation(this, "animationUpdate");
179  d->animation->setStartValue(0);
180  d->animation->setEndValue(1);
181 
182  d->initTheming();
183 }
184 
185 ToolButton::~ToolButton()
186 {
187  delete d->animation;
188  delete d;
189 }
190 
191 void ToolButton::setAnimationUpdate(qreal progress)
192 {
193  d->animationUpdate(progress);
194 }
195 
196 qreal ToolButton::animationUpdate() const
197 {
198  return d->opacity;
199 }
200 
201 void ToolButton::setAction(QAction *action)
202 {
203  d->setAction(action);
204 }
205 
206 QAction *ToolButton::action() const
207 {
208  return d->action;
209 }
210 
211 void ToolButton::setAutoRaise(bool raise)
212 {
213  nativeWidget()->setAutoRaise(raise);
214 }
215 
216 bool ToolButton::autoRaise() const
217 {
218  return nativeWidget()->autoRaise();
219 }
220 
221 void ToolButton::setText(const QString &text)
222 {
223  static_cast<QToolButton*>(widget())->setText(text);
224  updateGeometry();
225 }
226 
227 QString ToolButton::text() const
228 {
229  return static_cast<QToolButton*>(widget())->text();
230 }
231 
232 void ToolButton::setImage(const QString &path)
233 {
234  if (d->imagePath == path) {
235  return;
236  }
237 
238  delete d->svg;
239  d->svg = 0;
240  d->imagePath = path;
241 
242  bool absolutePath = !path.isEmpty() &&
243  #ifdef Q_WS_WIN
244  !QDir::isRelativePath(path)
245  #else
246  (path[0] == '/' || path.startsWith(QLatin1String(":/")))
247  #endif
248  ;
249 
250  if (absolutePath) {
251  d->absImagePath = path;
252  } else {
253  //TODO: package support
254  d->absImagePath = Theme::defaultTheme()->imagePath(path);
255  }
256 
257  d->setPixmap();
258 }
259 
260 void ToolButton::setImage(const QString &path, const QString &elementid)
261 {
262  d->svgElement = elementid;
263  setImage(path);
264 }
265 
266 void ToolButton::setIcon(const QIcon &icon)
267 {
268  nativeWidget()->setIcon(icon);
269 }
270 
271 QIcon ToolButton::icon() const
272 {
273  return nativeWidget()->icon();
274 }
275 
276 QString ToolButton::image() const
277 {
278  return d->imagePath;
279 }
280 
281 void ToolButton::setDown(bool down)
282 {
283  nativeWidget()->setDown(down);
284 }
285 
286 bool ToolButton::isDown() const
287 {
288  return nativeWidget()->isDown();
289 }
290 
291 void ToolButton::setStyleSheet(const QString &stylesheet)
292 {
293  widget()->setStyleSheet(stylesheet);
294 }
295 
296 QString ToolButton::styleSheet()
297 {
298  return widget()->styleSheet();
299 }
300 
301 QToolButton *ToolButton::nativeWidget() const
302 {
303  return static_cast<QToolButton*>(widget());
304 }
305 
306 void ToolButton::resizeEvent(QGraphicsSceneResizeEvent *event)
307 {
308  d->setPixmap();
309 
310  if (d->background) {
311  //resize all four panels
312  d->background->setElementPrefix("pressed");
313  d->background->resizeFrame(size());
314  d->background->setElementPrefix("focus");
315  d->background->resizeFrame(size());
316 
317  d->syncActiveRect();
318 
319  d->background->setElementPrefix("active");
320  d->background->resizeFrame(d->activeRect.size());
321 
322  d->background->setElementPrefix("normal");
323  d->background->resizeFrame(size());
324  }
325 
326  QGraphicsProxyWidget::resizeEvent(event);
327 }
328 
329 void ToolButton::paint(QPainter *painter,
330  const QStyleOptionGraphicsItem *option,
331  QWidget *widget)
332 {
333  if (!styleSheet().isNull() || Theme::defaultTheme()->useNativeWidgetStyle()) {
334  QGraphicsProxyWidget::paint(painter, option, widget);
335  return;
336  }
337 
338  QToolButton *button = nativeWidget();
339 
340  QStyleOptionToolButton buttonOpt;
341  buttonOpt.initFrom(button);
342  buttonOpt.icon = button->icon();
343  buttonOpt.text = button->text();
344  buttonOpt.iconSize = button->iconSize();
345  buttonOpt.toolButtonStyle = button->toolButtonStyle();
346 
347  bool animationState = (d->animation->state() == QAbstractAnimation::Running)? \
348  1:0;
349  if (button->isEnabled() && (animationState || !button->autoRaise() || d->underMouse || (buttonOpt.state & QStyle::State_On) || button->isChecked() || button->isDown())) {
350  if (button->isDown() || (buttonOpt.state & QStyle::State_On) || button->isChecked()) {
351  d->background->setElementPrefix("pressed");
352  } else {
353  d->background->setElementPrefix("normal");
354  }
355  d->background->resizeFrame(size());
356 
357  if (animationState) {
358  QPixmap buffer = d->background->framePixmap();
359 
360  QPainter bufferPainter(&buffer);
361  bufferPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
362  QColor alphaColor(Qt::black);
363  alphaColor.setAlphaF(qMin(qreal(0.95), d->opacity));
364  bufferPainter.fillRect(buffer.rect(), alphaColor);
365  bufferPainter.end();
366 
367  painter->drawPixmap(QPoint(0,0), buffer);
368 
369  buttonOpt.palette.setColor(QPalette::ButtonText, KColorUtils::mix(Plasma::Theme::defaultTheme()->color(Plasma::Theme::ButtonTextColor), Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor), 1-d->opacity));
370  } else {
371  d->background->paintFrame(painter);
372  buttonOpt.palette.setColor(QPalette::ButtonText, Plasma::Theme::defaultTheme()->color(Plasma::Theme::ButtonTextColor));
373  }
374 
375  } else {
376  buttonOpt.palette.setColor(QPalette::ButtonText, Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor));
377  }
378 
379  buttonOpt.font = font();
380 
381  painter->setFont(buttonOpt.font);
382  button->style()->drawControl(QStyle::CE_ToolButtonLabel, &buttonOpt, painter, button);
383 }
384 
385 void ToolButton::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
386 {
387  d->underMouse = true;
388  if (nativeWidget()->isDown() || !nativeWidget()->autoRaise()) {
389  return;
390  }
391 
392  const int FadeInDuration = 75;
393 
394  if (d->animation->state() != QAbstractAnimation::Stopped) {
395  d->animation->stop();
396  }
397  d->animation->setDuration(FadeInDuration);
398  d->animation->setDirection(QAbstractAnimation::Forward);
399  d->animation->start();
400 
401  d->background->setElementPrefix("active");
402 
403  QGraphicsProxyWidget::hoverEnterEvent(event);
404 }
405 
406 void ToolButton::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
407 {
408  d->underMouse = false;
409  if (nativeWidget()->isDown() || !nativeWidget()->autoRaise()) {
410  return;
411  }
412 
413  const int FadeOutDuration = 150;
414 
415  if (d->animation->state() != QAbstractAnimation::Stopped) {
416  d->animation->stop();
417  }
418 
419  d->animation->setDuration(FadeOutDuration);
420  d->animation->setDirection(QAbstractAnimation::Backward);
421  d->animation->start();
422 
423  d->background->setElementPrefix("active");
424 
425  QGraphicsProxyWidget::hoverLeaveEvent(event);
426 }
427 
428 void ToolButton::changeEvent(QEvent *event)
429 {
430  d->changeEvent(event);
431 
432  if (event->type() == QEvent::EnabledChange && !isEnabled()) {
433  d->underMouse = false;
434  }
435 
436  QGraphicsProxyWidget::changeEvent(event);
437 }
438 
439 QVariant ToolButton::itemChange(GraphicsItemChange change, const QVariant &value)
440 {
441  //If the widget is hidden while it's hovered and then we show it again
442  //we have to disable the hover otherwise it will remain hovered.
443  if (change == ItemVisibleHasChanged){
444  d->underMouse = false;
445  }
446 
447  return QGraphicsProxyWidget::itemChange(change, value);
448 }
449 
450 QSizeF ToolButton::sizeHint(Qt::SizeHint which, const QSizeF & constraint) const
451 {
452  QSizeF hint = QGraphicsProxyWidget::sizeHint(which, constraint);
453 
454  return hint;
455 }
456 
457 } // namespace Plasma
458 
459 #include <toolbutton.moc>
460 
Plasma::ToolButton::image
QString image() const
Plasma::Theme::imagePath
Q_INVOKABLE QString imagePath(const QString &name) const
Retrieve the path for an SVG image in the current theme.
Definition: theme.cpp:794
Plasma::ToolButton::setText
void setText(const QString &text)
Sets the display text for this ToolButton.
Definition: toolbutton.cpp:221
Plasma::ToolButton::itemChange
QVariant itemChange(GraphicsItemChange change, const QVariant &value)
Definition: toolbutton.cpp:439
Plasma::ToolButton::nativeWidget
QToolButton * nativeWidget() const
Plasma::ToolButton::resizeEvent
void resizeEvent(QGraphicsSceneResizeEvent *event)
Definition: toolbutton.cpp:306
Plasma::ToolButton::hoverEnterEvent
void hoverEnterEvent(QGraphicsSceneHoverEvent *event)
Definition: toolbutton.cpp:385
Plasma::ToolButton::setAction
void setAction(QAction *action)
Associate an action with this IconWidget this makes the button follow the state of the action...
Definition: toolbutton.cpp:201
Plasma::ToolButton::autoRaise
bool autoRaise() const
Plasma::ToolButton::action
QAction * action() const
Plasma::ToolButton::paint
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=0)
Definition: toolbutton.cpp:329
QWidget
Plasma::ToolButton::setDown
void setDown(bool down)
Sets the status of the button to pressed.
Definition: toolbutton.cpp:281
Plasma::Theme::TextColor
the text color to be used by items resting on the background
Definition: theme.h:63
theme.h
Plasma::ToolButton::sizeHint
QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
Definition: toolbutton.cpp:450
Plasma::FrameSvg
Provides an SVG with borders.
Definition: framesvg.h:76
Plasma::AnimationScriptEngine::animation
QScriptValue animation(const QString &anim)
Definition: animationscriptengine.cpp:55
Plasma::ToolButton::setStyleSheet
void setStyleSheet(const QString &stylesheet)
Sets the stylesheet used to control the visual display of this ToolButton.
Definition: toolbutton.cpp:291
Plasma::ToolButton::icon
QIcon icon() const
Definition: toolbutton.cpp:271
Plasma::ToolButton::released
void released()
paintutils.h
Plasma::ToolButton::setAutoRaise
void setAutoRaise(bool raise)
Sets if the toolbutton has an autoraise behaviour.
Definition: toolbutton.cpp:211
QGraphicsProxyWidget
Plasma::Theme::ButtonTextColor
Definition: theme.h:67
Plasma::ToolButton::hoverLeaveEvent
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
Definition: toolbutton.cpp:406
Plasma::ToolButton::setImage
void setImage(const QString &path)
Sets the path to an image to display.
Definition: toolbutton.cpp:232
Plasma::ToolButton::ToolButton
ToolButton(QGraphicsWidget *parent=0)
Definition: toolbutton.cpp:156
Plasma::ToolButton::setIcon
void setIcon(const QIcon &icon)
sets the icon for this toolbutton
Definition: toolbutton.cpp:266
Plasma::ToolButton::isDown
bool isDown() const
Definition: toolbutton.cpp:286
Plasma::Theme::defaultTheme
static Theme * defaultTheme()
Singleton pattern accessor.
Definition: theme.cpp:544
Plasma::ToolButton::changeEvent
void changeEvent(QEvent *event)
Definition: toolbutton.cpp:428
framesvg.h
Plasma::ToolButton::pressed
void pressed()
toolbutton.h
Plasma::ToolButton::clicked
void clicked()
animator.h
Plasma::ToolButton::styleSheet
QString styleSheet()
QStyleOptionGraphicsItem
Plasma::ToolButton::text
QString text() const
Plasma::ToolButton::~ToolButton
~ToolButton()
Definition: toolbutton.cpp:185
QGraphicsWidget
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:48:34 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Plasma

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

kdelibs API Reference

Skip menu "kdelibs 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
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

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