24#include <QPropertyAnimation>
25#include <QStyleOptionGraphicsItem>
28#include <kcolorutils.h>
30#include <kiconeffect.h>
36#include "private/actionwidgetinterface_p.h"
37#include "private/themedwidgetinterface_p.h"
43class ToolButtonPrivate :
public ActionWidgetInterface<ToolButton>
46 ToolButtonPrivate(ToolButton *toolButton)
47 : ActionWidgetInterface<ToolButton>(toolButton),
61 if (imagePath.isEmpty()) {
67 KMimeType::Ptr mime = KMimeType::findByPath(absImagePath);
70 if (mime->is(
"image/svg+xml") || mime->is(
"image/svg+xml-compressed")) {
71 if (!svg || svg->imagePath() != absImagePath) {
74 svg->setImagePath(imagePath);
75 QObject::connect(svg, SIGNAL(repaintNeeded()), q, SLOT(setPixmap()));
76 if (!svgElement.isNull()) {
77 svg->setContainsMultipleImages(
true);
82 if (!svgElement.isNull() && svg->hasElement(svgElement)) {
83 QSizeF elementSize = svg->elementSize(svgElement);
84 float scale = pm.width() / qMax(elementSize.width(), elementSize.height());
86 svg->resize(svg->size() * scale);
87 pm = svg->pixmap(svgElement);
89 svg->resize(pm.size());
95 pm = QPixmap(absImagePath);
98 static_cast<QToolButton*
>(q->widget())->setIcon(KIcon(pm));
101 void syncActiveRect();
103 void animationUpdate(qreal progress);
105 FrameSvg *background;
111 QString absImagePath;
117void ToolButtonPrivate::syncActiveRect()
119 background->setElementPrefix(
"normal");
121 qreal left, top, right, bottom;
122 background->getMargins(left, top, right, bottom);
124 background->setElementPrefix(
"active");
125 qreal activeLeft, activeTop, activeRight, activeBottom;
126 background->getMargins(activeLeft, activeTop, activeRight, activeBottom);
128 activeRect = QRectF(QPointF(0, 0), q->size());
129 activeRect.adjust(left - activeLeft, top - activeTop,
130 -(right - activeRight), -(bottom - activeBottom));
132 background->setElementPrefix(
"normal");
135void ToolButtonPrivate::syncBorders()
138 qreal left, top, right, bottom;
140 background->setElementPrefix(
"normal");
141 background->getMargins(left, top, right, bottom);
142 q->setContentsMargins(left, top, right, bottom);
148void ToolButtonPrivate::animationUpdate(qreal progress)
158 d(new ToolButtonPrivate(this))
161 d->background->setImagePath(
"widgets/button");
162 d->background->setCacheAllRenderedFrames(
true);
163 d->background->setElementPrefix(
"normal");
165 QToolButton *native =
new QToolButton;
170 native->setWindowIcon(QIcon());
171 native->setAttribute(Qt::WA_NoSystemBackground);
172 native->setAutoRaise(
true);
175 setAcceptHoverEvents(
true);
176 connect(d->background, SIGNAL(repaintNeeded()), SLOT(syncBorders()));
178 d->animation =
new QPropertyAnimation(
this,
"animationUpdate");
179 d->animation->setStartValue(0);
180 d->animation->setEndValue(1);
185ToolButton::~ToolButton()
191void ToolButton::setAnimationUpdate(qreal progress)
193 d->animationUpdate(progress);
196qreal ToolButton::animationUpdate()
const
201void ToolButton::setAction(QAction *action)
206QAction *ToolButton::action()
const
211void ToolButton::setAutoRaise(
bool raise)
216bool ToolButton::autoRaise()
const
221void ToolButton::setText(
const QString &text)
223 static_cast<QToolButton*
>(widget())->
setText(
text);
227QString ToolButton::text()
const
229 return static_cast<QToolButton*
>(widget())->
text();
232void ToolButton::setImage(
const QString &path)
234 if (d->imagePath == path) {
242 bool absolutePath = !path.isEmpty() &&
244 !QDir::isRelativePath(path)
246 (path[0] ==
'/' || path.startsWith(QLatin1String(
":/")))
251 d->absImagePath = path;
260void ToolButton::setImage(
const QString &path,
const QString &elementid)
262 d->svgElement = elementid;
266void ToolButton::setIcon(
const QIcon &icon)
271QIcon ToolButton::icon()
const
276QString ToolButton::image()
const
281void ToolButton::setDown(
bool down)
286bool ToolButton::isDown()
const
291void ToolButton::setStyleSheet(
const QString &stylesheet)
293 widget()->setStyleSheet(stylesheet);
296QString ToolButton::styleSheet()
298 return widget()->styleSheet();
301QToolButton *ToolButton::nativeWidget()
const
303 return static_cast<QToolButton*
>(widget());
306void ToolButton::resizeEvent(QGraphicsSceneResizeEvent *event)
312 d->background->setElementPrefix(
"pressed");
313 d->background->resizeFrame(size());
314 d->background->setElementPrefix(
"focus");
315 d->background->resizeFrame(size());
319 d->background->setElementPrefix(
"active");
320 d->background->resizeFrame(d->activeRect.size());
322 d->background->setElementPrefix(
"normal");
323 d->background->resizeFrame(size());
326 QGraphicsProxyWidget::resizeEvent(event);
329void ToolButton::paint(QPainter *painter,
334 QGraphicsProxyWidget::paint(painter, option, widget);
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();
347 bool animationState = (d->animation->state() == QAbstractAnimation::Running)? \
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");
353 d->background->setElementPrefix(
"normal");
355 d->background->resizeFrame(size());
357 if (animationState) {
358 QPixmap buffer = d->background->framePixmap();
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);
367 painter->drawPixmap(QPoint(0,0), buffer);
371 d->background->paintFrame(painter);
379 buttonOpt.font = font();
381 painter->setFont(buttonOpt.font);
382 button->style()->drawControl(QStyle::CE_ToolButtonLabel, &buttonOpt, painter, button);
385void ToolButton::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
387 d->underMouse =
true;
392 const int FadeInDuration = 75;
394 if (d->animation->state() != QAbstractAnimation::Stopped) {
395 d->animation->stop();
397 d->animation->setDuration(FadeInDuration);
398 d->animation->setDirection(QAbstractAnimation::Forward);
399 d->animation->start();
401 d->background->setElementPrefix(
"active");
403 QGraphicsProxyWidget::hoverEnterEvent(event);
406void ToolButton::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
408 d->underMouse =
false;
413 const int FadeOutDuration = 150;
415 if (d->animation->state() != QAbstractAnimation::Stopped) {
416 d->animation->stop();
419 d->animation->setDuration(FadeOutDuration);
420 d->animation->setDirection(QAbstractAnimation::Backward);
421 d->animation->start();
423 d->background->setElementPrefix(
"active");
425 QGraphicsProxyWidget::hoverLeaveEvent(event);
428void ToolButton::changeEvent(QEvent *event)
430 d->changeEvent(event);
432 if (event->type() == QEvent::EnabledChange && !isEnabled()) {
433 d->underMouse =
false;
436 QGraphicsProxyWidget::changeEvent(event);
439QVariant ToolButton::itemChange(GraphicsItemChange change,
const QVariant &value)
443 if (change == ItemVisibleHasChanged){
444 d->underMouse =
false;
447 return QGraphicsProxyWidget::itemChange(change, value);
450QSizeF ToolButton::sizeHint(Qt::SizeHint which,
const QSizeF & constraint)
const
452 QSizeF hint = QGraphicsProxyWidget::sizeHint(which, constraint);
459#include <toolbutton.moc>
Provides an SVG with borders.
Q_INVOKABLE QString imagePath(const QString &name) const
Retrieve the path for an SVG image in the current theme.
static Theme * defaultTheme()
Singleton pattern accessor.
@ TextColor
the text color to be used by items resting on the background
QScriptValue animation(const QString &anim)
Namespace for everything in libplasma.