25#include <QStyleOptionGraphicsItem>
26#include <QWeakPointer>
29#include <kiconeffect.h>
31#include <kpushbutton.h>
37#include "private/actionwidgetinterface_p.h"
38#include "private/focusindicator_p.h"
39#include "private/themedwidgetinterface_p.h"
45class PushButtonPrivate :
public ActionWidgetInterface<PushButton>
48 PushButtonPrivate(PushButton *pushButton)
49 : ActionWidgetInterface<PushButton>(pushButton),
63 if (imagePath.isEmpty()) {
69 KMimeType::Ptr mime = KMimeType::findByPath(absImagePath);
72 if (mime->is(
"image/svg+xml") || mime->is(
"image/svg+xml-compressed")) {
73 if (!svg || svg->
imagePath() != absImagePath) {
77 QObject::connect(svg, SIGNAL(repaintNeeded()), q, SLOT(setPixmap()));
78 if (!svgElement.isNull()) {
85 if (!svgElement.isEmpty() && svg->
hasElement(svgElement)) {
88 float scale = q->nativeWidget()->iconSize().width() / qMax(elementSize.width(), elementSize.height());
90 svg->
resize(elementSize * scale);
91 pm = svg->
pixmap(svgElement);
93 svg->
resize(q->nativeWidget()->iconSize());
99 pm = QPixmap(absImagePath);
102 static_cast<KPushButton*
>(q->widget())->setIcon(KIcon(pm));
105 void pressedChanged()
107 if (q->nativeWidget()->isDown() || q->nativeWidget()->isChecked()) {
108 focusIndicator->animateVisibility(
false);
110 focusIndicator->animateVisibility(
true);
125 hoverAnimation->setProperty(
"startPixmap", background->
framePixmap());
129 hoverAnimation->setProperty(
"targetPixmap", background->
framePixmap());
133 void syncActiveRect();
136 FrameSvg *background;
141 Animation *hoverAnimation;
143 FocusIndicator *focusIndicator;
145 QString absImagePath;
150void PushButtonPrivate::syncActiveRect()
154 qreal left, top, right, bottom;
155 background->
getMargins(left, top, right, bottom);
158 qreal activeLeft, activeTop, activeRight, activeBottom;
159 background->
getMargins(activeLeft, activeTop, activeRight, activeBottom);
161 activeRect = QRectF(QPointF(0, 0), q->size());
162 activeRect.adjust(left - activeLeft, top - activeTop,
163 -(right - activeRight), -(bottom - activeBottom));
168void PushButtonPrivate::syncBorders()
171 qreal left, top, right, bottom;
174 background->
getMargins(left, top, right, bottom);
175 q->setContentsMargins(left, top, right, bottom);
184 d(new PushButtonPrivate(this))
195 KPushButton *native =
new KPushButton;
197 connect(native, SIGNAL(
pressed()),
this, SLOT(pressedChanged()));
199 connect(native, SIGNAL(
released()),
this, SLOT(pressedChanged()));
201 connect(native, SIGNAL(
toggled(
bool)),
this, SIGNAL(
toggled(
bool)));
203 native->setAttribute(Qt::WA_NoSystemBackground);
204 native->setWindowIcon(QIcon());
206 setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
208 d->focusIndicator =
new FocusIndicator(
this, d->background);
211 setAcceptHoverEvents(
true);
213 connect(d->background, SIGNAL(repaintNeeded()), SLOT(syncBorders()));
218PushButton::~PushButton()
223void PushButton::setText(
const QString &text)
225 static_cast<KPushButton*
>(widget())->
setText(
text);
229QString PushButton::text()
const
231 return static_cast<KPushButton*
>(widget())->
text();
234void PushButton::setImage(
const QString &path)
236 if (d->imagePath == path) {
244 bool absolutePath = !path.isEmpty() &&
246 !QDir::isRelativePath(path)
248 (path[0] ==
'/' || path.startsWith(QLatin1String(
":/")))
253 d->absImagePath = path;
262void PushButton::setImage(
const QString &path,
const QString &elementid)
264 d->svgElement = elementid;
268QString PushButton::image()
const
273void PushButton::setStyleSheet(
const QString &stylesheet)
275 d->focusIndicator->setVisible(stylesheet.isEmpty());
276 widget()->setStyleSheet(stylesheet);
279QString PushButton::styleSheet()
281 return widget()->styleSheet();
284void PushButton::setAction(QAction *action)
289QAction *PushButton::action()
const
294void PushButton::setIcon(
const KIcon &icon)
299void PushButton::setIcon(
const QIcon &icon)
304QIcon PushButton::icon()
const
309void PushButton::setCheckable(
bool checkable)
314bool PushButton::isCheckable()
const
319void PushButton::setChecked(
bool checked)
324void PushButton::click()
329bool PushButton::isChecked()
const
334bool PushButton::isDown()
const
339KPushButton *PushButton::nativeWidget()
const
341 return static_cast<KPushButton*
>(widget());
344void PushButton::resizeEvent(QGraphicsSceneResizeEvent *event)
350 QGraphicsProxyWidget::resizeEvent(event);
353void PushButton::paint(QPainter *painter,
358 QGraphicsProxyWidget::paint(painter, option, widget);
362 QPixmap bufferPixmap;
374 bufferPixmap = QPixmap(rect().size().toSize());
375 bufferPixmap.fill(Qt::transparent);
377 QPainter buffPainter(&bufferPixmap);
379 buffPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
380 buffPainter.fillRect(bufferPixmap.rect(), QColor(0, 0, 0, 128));
382 painter->drawPixmap(0, 0, bufferPixmap);
387 if (d->hoverAnimation->state() == QAbstractAnimation::Running && !isUnderMouse() && !
nativeWidget()->isDefault()) {
389 d->background->
paintFrame(painter, d->activeRect.topLeft());
392 d->activeRect.topLeft(),
393 d->hoverAnimation->property(
"currentPixmap").value<QPixmap>());
395 }
else if (isEnabled()) {
403 painter->translate(QPoint(1, 1));
406 QRectF rect = contentsRect();
409 const qreal iconSize = qMin(rect.width(), rect.height());
410 QPixmap iconPix =
nativeWidget()->icon().pixmap(iconSize);
412 KIconEffect *effect = KIconLoader::global()->iconEffect();
413 iconPix = effect->apply(iconPix, KIconLoader::Toolbar, KIconLoader::DisabledState);
418 pixmapRect =
nativeWidget()->style()->alignedRect(option->direction, Qt::AlignCenter, iconPix.size(), rect.toRect());
420 pixmapRect =
nativeWidget()->style()->alignedRect(option->direction, Qt::AlignLeft|Qt::AlignVCenter, iconPix.size(), rect.toRect());
422 painter->drawPixmap(pixmapRect.topLeft(), iconPix);
424 if (option->direction == Qt::LeftToRight) {
425 rect.adjust(rect.height(), 0, 0, 0);
427 rect.adjust(0, 0, -rect.height(), 0);
431 QFontMetricsF fm(font());
433 if (rect.height() < fm.height()) {
434 rect.setHeight(fm.height());
435 rect.moveTop(boundingRect().center().y() - rect.height() / 2);
440 if (bufferPixmap.isNull()) {
441 bufferPixmap = QPixmap(rect.size().toSize());
443 bufferPixmap.fill(Qt::transparent);
445 QPainter p(&bufferPixmap);
446 p.setPen(painter->pen());
450 QLinearGradient alphaGradient(0, 0, 1, 0);
451 alphaGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
452 if (option->direction == Qt::LeftToRight) {
453 alphaGradient.setColorAt(0, QColor(0, 0, 0, 255));
454 alphaGradient.setColorAt(1, QColor(0, 0, 0, 0));
455 p.drawText(bufferPixmap.rect(), Qt::AlignLeft|Qt::AlignVCenter|Qt::TextShowMnemonic,
458 alphaGradient.setColorAt(0, QColor(0, 0, 0, 0));
459 alphaGradient.setColorAt(1, QColor(0, 0, 0, 255));
460 p.drawText(bufferPixmap.rect(), Qt::AlignRight|Qt::AlignVCenter|Qt::TextShowMnemonic,
464 p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
465 p.fillRect(bufferPixmap.rect(), alphaGradient);
467 painter->drawPixmap(rect.topLeft(), bufferPixmap);
469 painter->setFont(font());
470 painter->drawText(rect, Qt::AlignCenter|Qt::TextShowMnemonic,
nativeWidget()->
text());
474void PushButton::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
480 d->hoverAnimation->setProperty(
"duration", 75);
483 d->hoverAnimation->setProperty(
"startPixmap", d->background->
framePixmap());
486 d->hoverAnimation->setProperty(
"targetPixmap", d->background->
framePixmap());
488 d->hoverAnimation->start();
490 QGraphicsProxyWidget::hoverEnterEvent(event);
493void PushButton::changeEvent(QEvent *event)
495 d->changeEvent(event);
496 QGraphicsProxyWidget::changeEvent(event);
499void PushButton::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
505 d->hoverAnimation->setProperty(
"duration", 150);
508 d->hoverAnimation->setProperty(
"startPixmap", d->background->
framePixmap());
511 d->hoverAnimation->setProperty(
"targetPixmap", d->background->
framePixmap());
513 d->hoverAnimation->start();
515 QGraphicsProxyWidget::hoverLeaveEvent(event);
519QSizeF PushButton::sizeHint(Qt::SizeHint which,
const QSizeF & constraint)
const
521 QSizeF hint = QGraphicsProxyWidget::sizeHint(which, constraint);
523 if (hint.isEmpty()) {
531 qreal left, top, right, bottom;
532 d->background->
getMargins(left, top, right, bottom);
533 hint = hint - QSize(nativeMargin, nativeMargin) + QSize(left+right, top+bottom);
539#include <pushbutton.moc>
void setTargetWidget(QGraphicsWidget *widget)
Set the widget on which the animation is to be performed.
static Plasma::Animation * create(Animator::Animation type, QObject *parent=0)
Factory to build new animation objects.
@ PixmapTransitionAnimation
Provides an SVG with borders.
Q_INVOKABLE void paintFrame(QPainter *painter, const QRectF &target, const QRectF &source=QRectF())
Paints the loaded SVG with the elements that represents the border.
Q_INVOKABLE void getMargins(qreal &left, qreal &top, qreal &right, qreal &bottom) const
Convenience method that extracts the size of the four margins in the four output parameters.
Q_INVOKABLE void resizeFrame(const QSizeF &size)
Resize the frame maintaining the same border size.
Q_INVOKABLE void setImagePath(const QString &path)
Loads a new Svg.
Q_INVOKABLE bool hasElementPrefix(const QString &prefix) const
Q_INVOKABLE QPixmap framePixmap()
Returns a pixmap of the SVG represented by this object.
Q_INVOKABLE void setCacheAllRenderedFrames(bool cache)
Sets whether saving all the rendered prefixes in a cache or not.
Q_INVOKABLE void setElementPrefix(Plasma::Location location)
Sets the prefix (.
Q_INVOKABLE bool hasElement(const QString &elementId) const
Check whether an element exists in the loaded SVG.
void setImagePath(const QString &svgFilePath)
Set the SVG file to render.
Q_INVOKABLE void resize(qreal width, qreal height)
Resizes the rendered image.
Q_INVOKABLE QSize elementSize(const QString &elementId) const
Find the size of a given element.
Q_INVOKABLE QPixmap pixmap(const QString &elementID=QString())
Returns a pixmap of the SVG represented by this object.
void setContainsMultipleImages(bool multiple)
Set whether the SVG contains a single image or multiple ones.
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.
Namespace for everything in libplasma.