00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "toolbutton.h"
00021
00022 #include <QStyleOptionGraphicsItem>
00023 #include <QPainter>
00024 #include <QDir>
00025 #include <QToolButton>
00026 #include <QApplication>
00027
00028 #include <kicon.h>
00029 #include <kiconeffect.h>
00030 #include <kmimetype.h>
00031 #include <kcolorutils.h>
00032
00033 #include "theme.h"
00034 #include "svg.h"
00035 #include "framesvg.h"
00036 #include "animator.h"
00037 #include "paintutils.h"
00038
00039 namespace Plasma
00040 {
00041
00042 class ToolButtonPrivate
00043 {
00044 public:
00045 ToolButtonPrivate(ToolButton *toolButton)
00046 : q(toolButton),
00047 background(0),
00048 animId(0),
00049 fadeIn(false),
00050 svg(0)
00051 {
00052 }
00053
00054 ~ToolButtonPrivate()
00055 {
00056 delete svg;
00057 }
00058
00059 void setPixmap(ToolButton *q)
00060 {
00061 if (imagePath.isEmpty()) {
00062 return;
00063 }
00064
00065 KMimeType::Ptr mime = KMimeType::findByPath(absImagePath);
00066 QPixmap pm(q->size().toSize());
00067
00068 if (mime->is("image/svg+xml")) {
00069 svg = new Svg();
00070 QPainter p(&pm);
00071 svg->paint(&p, pm.rect());
00072 } else {
00073 pm = QPixmap(absImagePath);
00074 }
00075
00076 static_cast<QToolButton*>(q->widget())->setIcon(KIcon(pm));
00077 }
00078
00079 void syncActiveRect();
00080 void syncBorders();
00081 void animationUpdate(qreal progress);
00082
00083 ToolButton *q;
00084
00085 FrameSvg *background;
00086 int animId;
00087 bool fadeIn;
00088 qreal opacity;
00089 QRectF activeRect;
00090
00091 QString imagePath;
00092 QString absImagePath;
00093 Svg *svg;
00094 };
00095
00096 void ToolButtonPrivate::syncActiveRect()
00097 {
00098 background->setElementPrefix("normal");
00099
00100 qreal left, top, right, bottom;
00101 background->getMargins(left, top, right, bottom);
00102
00103 background->setElementPrefix("active");
00104 qreal activeLeft, activeTop, activeRight, activeBottom;
00105 background->getMargins(activeLeft, activeTop, activeRight, activeBottom);
00106
00107 activeRect = QRectF(QPointF(0, 0), q->size());
00108 activeRect.adjust(left - activeLeft, top - activeTop,
00109 -(right - activeRight), -(bottom - activeBottom));
00110
00111 background->setElementPrefix("normal");
00112 }
00113
00114 void ToolButtonPrivate::syncBorders()
00115 {
00116
00117 qreal left, top, right, bottom;
00118
00119 background->setElementPrefix("normal");
00120 background->getMargins(left, top, right, bottom);
00121 q->setContentsMargins(left, top, right, bottom);
00122
00123
00124 syncActiveRect();
00125 }
00126
00127 void ToolButtonPrivate::animationUpdate(qreal progress)
00128 {
00129 if (progress == 1) {
00130 animId = 0;
00131 fadeIn = true;
00132 }
00133
00134 opacity = fadeIn ? progress : 1 - progress;
00135
00136
00137 q->update();
00138 }
00139
00140 ToolButton::ToolButton(QGraphicsWidget *parent)
00141 : QGraphicsProxyWidget(parent),
00142 d(new ToolButtonPrivate(this))
00143 {
00144 QToolButton *native = new QToolButton;
00145 connect(native, SIGNAL(clicked()), this, SIGNAL(clicked()));
00146 setWidget(native);
00147 native->setAttribute(Qt::WA_NoSystemBackground);
00148 native->setAutoRaise(true);
00149
00150 d->background = new FrameSvg(this);
00151 d->background->setImagePath("widgets/button");
00152 d->background->setCacheAllRenderedFrames(true);
00153 d->background->setElementPrefix("normal");
00154 d->syncBorders();
00155 setAcceptHoverEvents(true);
00156 connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), SLOT(syncBorders()));
00157 }
00158
00159 ToolButton::~ToolButton()
00160 {
00161 delete d;
00162 }
00163
00164 void ToolButton::setAutoRaise(bool raise)
00165 {
00166 nativeWidget()->setAutoRaise(raise);
00167 }
00168
00169 bool ToolButton::autoRaise() const
00170 {
00171 return nativeWidget()->autoRaise();
00172 }
00173
00174 void ToolButton::setText(const QString &text)
00175 {
00176 static_cast<QToolButton*>(widget())->setText(text);
00177 }
00178
00179 QString ToolButton::text() const
00180 {
00181 return static_cast<QToolButton*>(widget())->text();
00182 }
00183
00184 void ToolButton::setImage(const QString &path)
00185 {
00186 if (d->imagePath == path) {
00187 return;
00188 }
00189
00190 delete d->svg;
00191 d->svg = 0;
00192 d->imagePath = path;
00193
00194 bool absolutePath = !path.isEmpty() &&
00195 #ifdef Q_WS_WIN
00196 !QDir::isRelativePath(path)
00197 #else
00198 (path[0] == '/' || path.startsWith(":/"))
00199 #endif
00200 ;
00201
00202 if (absolutePath) {
00203 d->absImagePath = path;
00204 } else {
00205
00206 d->absImagePath = Theme::defaultTheme()->imagePath(path);
00207 }
00208
00209 d->setPixmap(this);
00210 }
00211
00212 QString ToolButton::image() const
00213 {
00214 return d->imagePath;
00215 }
00216
00217 void ToolButton::setStyleSheet(const QString &stylesheet)
00218 {
00219 widget()->setStyleSheet(stylesheet);
00220 }
00221
00222 QString ToolButton::styleSheet()
00223 {
00224 return widget()->styleSheet();
00225 }
00226
00227 QToolButton *ToolButton::nativeWidget() const
00228 {
00229 return static_cast<QToolButton*>(widget());
00230 }
00231
00232 void ToolButton::resizeEvent(QGraphicsSceneResizeEvent *event)
00233 {
00234 d->setPixmap(this);
00235
00236 if (d->background) {
00237
00238 d->background->setElementPrefix("pressed");
00239 d->background->resizeFrame(size());
00240 d->background->setElementPrefix("focus");
00241 d->background->resizeFrame(size());
00242
00243 d->syncActiveRect();
00244
00245 d->background->setElementPrefix("active");
00246 d->background->resizeFrame(d->activeRect.size());
00247
00248 d->background->setElementPrefix("normal");
00249 d->background->resizeFrame(size());
00250 }
00251
00252 QGraphicsProxyWidget::resizeEvent(event);
00253 }
00254
00255 void ToolButton::paint(QPainter *painter,
00256 const QStyleOptionGraphicsItem *option,
00257 QWidget *widget)
00258 {
00259 if (!styleSheet().isNull()) {
00260 QGraphicsProxyWidget::paint(painter, option, widget);
00261 return;
00262 }
00263
00264 QToolButton *button = nativeWidget();
00265
00266 QStyleOptionToolButton buttonOpt;
00267 buttonOpt.initFrom(button);
00268 buttonOpt.icon = button->icon();
00269 buttonOpt.text = button->text();
00270 buttonOpt.iconSize = button->iconSize();
00271 buttonOpt.toolButtonStyle = button->toolButtonStyle();
00272
00273
00274 if (d->animId || !button->autoRaise() || (buttonOpt.state & QStyle::State_MouseOver) || (buttonOpt.state & QStyle::State_On)) {
00275 if (button->isDown() || (buttonOpt.state & QStyle::State_On)) {
00276 d->background->setElementPrefix("pressed");
00277 } else {
00278 d->background->setElementPrefix("normal");
00279 }
00280 d->background->resizeFrame(size());
00281
00282 if (d->animId) {
00283 QPixmap buffer = d->background->framePixmap();
00284
00285 QPainter bufferPainter(&buffer);
00286 bufferPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
00287 QColor alphaColor(Qt::black);
00288 alphaColor.setAlphaF(qMin(qreal(0.95), d->opacity));
00289 bufferPainter.fillRect(buffer.rect(), alphaColor);
00290 bufferPainter.end();
00291
00292 painter->drawPixmap(QPoint(0,0), buffer);
00293
00294 buttonOpt.palette.setColor(QPalette::ButtonText, KColorUtils::mix(Plasma::Theme::defaultTheme()->color(Plasma::Theme::ButtonTextColor), Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor), 1-d->opacity));
00295 } else {
00296 d->background->paintFrame(painter);
00297 buttonOpt.palette.setColor(QPalette::ButtonText, Plasma::Theme::defaultTheme()->color(Plasma::Theme::ButtonTextColor));
00298 }
00299
00300 } else {
00301 buttonOpt.palette.setColor(QPalette::ButtonText, Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor));
00302 }
00303
00304 painter->setFont(Plasma::Theme::defaultTheme()->font(Plasma::Theme::DefaultFont));
00305
00306 button->style()->drawControl(QStyle::CE_ToolButtonLabel, &buttonOpt, painter, button);
00307 }
00308
00309 void ToolButton::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
00310 {
00311 if (nativeWidget()->isDown() || !nativeWidget()->autoRaise()) {
00312 return;
00313 }
00314
00315 const int FadeInDuration = 75;
00316
00317 if (d->animId) {
00318 Plasma::Animator::self()->stopCustomAnimation(d->animId);
00319 }
00320 d->animId = Plasma::Animator::self()->customAnimation(
00321 40 / (1000 / FadeInDuration), FadeInDuration,
00322 Plasma::Animator::LinearCurve, this, "animationUpdate");
00323
00324 d->background->setElementPrefix("active");
00325
00326 QGraphicsProxyWidget::hoverEnterEvent(event);
00327 }
00328
00329 void ToolButton::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
00330 {
00331 if (nativeWidget()->isDown() || !nativeWidget()->autoRaise()) {
00332 return;
00333 }
00334
00335 const int FadeOutDuration = 150;
00336
00337 if (d->animId) {
00338 Plasma::Animator::self()->stopCustomAnimation(d->animId);
00339 }
00340
00341 d->fadeIn = false;
00342 d->animId = Plasma::Animator::self()->customAnimation(
00343 40 / (1000 / FadeOutDuration), FadeOutDuration,
00344 Plasma::Animator::LinearCurve, this, "animationUpdate");
00345
00346 d->background->setElementPrefix("active");
00347
00348 QGraphicsProxyWidget::hoverLeaveEvent(event);
00349 }
00350
00351 }
00352
00353 #include <toolbutton.moc>
00354