25 #include <QStyleOptionGraphicsItem>
26 #include <QWeakPointer>
29 #include <kiconeffect.h>
30 #include <kmimetype.h>
31 #include <kpushbutton.h>
37 #include "private/actionwidgetinterface_p.h"
38 #include "private/focusindicator_p.h"
39 #include "private/themedwidgetinterface_p.h"
45 class 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) {
76 svg->setImagePath(imagePath);
77 QObject::connect(svg, SIGNAL(repaintNeeded()), q, SLOT(setPixmap()));
78 if (!svgElement.isNull()) {
79 svg->setContainsMultipleImages(
true);
85 if (!svgElement.isEmpty() && svg->hasElement(svgElement)) {
87 QSizeF elementSize = svg->elementSize(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);
118 background->setElementPrefix(
"pressed");
119 background->resizeFrame(q->size());
123 background->setElementPrefix(
"normal");
124 background->resizeFrame(q->size());
125 hoverAnimation->setProperty(
"startPixmap", background->framePixmap());
127 background->setElementPrefix(
"active");
128 background->resizeFrame(activeRect.size());
129 hoverAnimation->setProperty(
"targetPixmap", background->framePixmap());
133 void syncActiveRect();
136 FrameSvg *background;
141 Animation *hoverAnimation;
143 FocusIndicator *focusIndicator;
145 QString absImagePath;
150 void PushButtonPrivate::syncActiveRect()
152 background->setElementPrefix(
"normal");
154 qreal left, top, right, bottom;
155 background->getMargins(left, top, right, bottom);
157 background->setElementPrefix(
"active");
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));
165 background->setElementPrefix(
"normal");
168 void PushButtonPrivate::syncBorders()
171 qreal left, top, right, bottom;
173 background->setElementPrefix(
"normal");
174 background->getMargins(left, top, right, bottom);
175 q->setContentsMargins(left, top, right, bottom);
184 d(new PushButtonPrivate(this))
187 d->background->setImagePath(
"widgets/button");
188 d->background->setCacheAllRenderedFrames(
true);
190 d->background->setElementPrefix(
"normal");
193 d->hoverAnimation->setTargetWidget(
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()));
225 static_cast<KPushButton*
>(widget())->
setText(text);
231 return static_cast<KPushButton*
>(widget())->
text();
236 if (d->imagePath == path) {
244 bool absolutePath = !path.isEmpty() &&
246 !QDir::isRelativePath(path)
248 (path[0] ==
'/' || path.startsWith(QLatin1String(
":/")))
253 d->absImagePath = path;
264 d->svgElement = elementid;
275 d->focusIndicator->setVisible(stylesheet.isEmpty());
276 widget()->setStyleSheet(stylesheet);
281 return widget()->styleSheet();
286 d->setAction(action);
341 return static_cast<KPushButton*
>(widget());
350 QGraphicsProxyWidget::resizeEvent(event);
358 QGraphicsProxyWidget::paint(painter, option, widget);
362 QPixmap bufferPixmap;
367 d->background->setElementPrefix(
"pressed");
369 d->background->setElementPrefix(
"normal");
374 bufferPixmap = QPixmap(rect().size().toSize());
375 bufferPixmap.fill(Qt::transparent);
377 QPainter buffPainter(&bufferPixmap);
378 d->background->paintFrame(&buffPainter);
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()) {
388 d->background->setElementPrefix(
"active");
389 d->background->paintFrame(painter, d->activeRect.topLeft());
392 d->activeRect.topLeft(),
393 d->hoverAnimation->property(
"currentPixmap").value<QPixmap>());
395 }
else if (isEnabled()) {
396 d->background->paintFrame(painter);
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());
480 d->hoverAnimation->setProperty(
"duration", 75);
482 d->background->setElementPrefix(
"normal");
483 d->hoverAnimation->setProperty(
"startPixmap", d->background->framePixmap());
485 d->background->setElementPrefix(
"active");
486 d->hoverAnimation->setProperty(
"targetPixmap", d->background->framePixmap());
488 d->hoverAnimation->start();
490 QGraphicsProxyWidget::hoverEnterEvent(event);
495 d->changeEvent(event);
496 QGraphicsProxyWidget::changeEvent(event);
505 d->hoverAnimation->setProperty(
"duration", 150);
507 d->background->setElementPrefix(
"active");
508 d->hoverAnimation->setProperty(
"startPixmap", d->background->framePixmap());
510 d->background->setElementPrefix(
"normal");
511 d->hoverAnimation->setProperty(
"targetPixmap", d->background->framePixmap());
513 d->hoverAnimation->start();
515 QGraphicsProxyWidget::hoverLeaveEvent(event);
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>
Q_INVOKABLE QString imagePath(const QString &name) const
Retrieve the path for an SVG image in the current theme.
Provides an SVG with borders.
static Theme * defaultTheme()
Singleton pattern accessor.
static Plasma::Animation * create(Animator::Animation type, QObject *parent=0)
Factory to build new animation objects.