00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "icon.h"
00025 #include "icon_p.h"
00026
00027 #include <QAction>
00028 #include <QApplication>
00029 #include <QPainter>
00030 #include <QGraphicsSceneMouseEvent>
00031 #include <QGraphicsView>
00032 #include <QStyleOptionGraphicsItem>
00033 #include <QTextLayout>
00034
00035
00036
00037 #ifdef BACKINGSTORE_BLUR_HACK
00038 #include <private/qwindowsurface_p.h>
00039 #include "effects/blur.cpp"
00040 #endif
00041
00042 #include <KIconEffect>
00043 #include <KIconLoader>
00044 #include <KIcon>
00045 #include <KUrl>
00046 #include <KRun>
00047 #include <KMimeType>
00048 #include <KDebug>
00049 #include <KColorScheme>
00050 #include <KGlobalSettings>
00051
00052 #include <plasma/theme.h>
00053
00054 #include "phase.h"
00055 #include "svg.h"
00056
00057 namespace Plasma
00058 {
00059
00060 Icon::Private::Private()
00061 : iconSvg(0),
00062 iconSize(48, 48),
00063 states(Private::NoState),
00064 orientation(Qt::Vertical),
00065 invertLayout(false),
00066 drawBg(false)
00067 {
00068 textColor = KColorScheme(QPalette::Active, KColorScheme::Window,
00069 Plasma::Theme::self()->colors()).foreground().color();
00070 shadowColor = KColorScheme(QPalette::Active, KColorScheme::Window,
00071 Plasma::Theme::self()->colors()).background().color();
00072 }
00073
00074 Icon::Private::~Private()
00075 {
00076 qDeleteAll(cornerActions);
00077 delete iconSvg;
00078 }
00079
00080 IconAction::IconAction(Icon* icon, QAction *action)
00081 : m_icon(icon),
00082 m_action(action),
00083 m_hovered(false),
00084 m_pressed(false),
00085 m_visible(false),
00086 m_animationId(-1)
00087 {
00088 }
00089
00090 void IconAction::show()
00091 {
00092 if (m_animationId) {
00093 Phase::self()->stopElementAnimation(m_animationId);
00094 }
00095
00096 rebuildPixmap();
00097
00098 m_animationId = Phase::self()->animateElement(m_icon, Phase::ElementAppear);
00099 Phase::self()->setAnimationPixmap(m_animationId, m_pixmap);
00100 m_visible = true;
00101 }
00102
00103 void IconAction::hide()
00104 {
00105 if (m_animationId) {
00106 Phase::self()->stopElementAnimation(m_animationId);
00107 }
00108
00109 rebuildPixmap();
00110
00111 m_animationId = Phase::self()->animateElement(m_icon, Phase::ElementDisappear);
00112 Phase::self()->setAnimationPixmap(m_animationId, m_pixmap);
00113 m_visible = false;
00114 }
00115
00116 bool IconAction::isVisible() const
00117 {
00118 return m_visible;
00119 }
00120
00121 bool IconAction::isPressed() const
00122 {
00123 return m_pressed;
00124 }
00125
00126 bool IconAction::isHovered() const
00127 {
00128 return m_hovered;
00129 }
00130
00131 void IconAction::setSelected(bool selected)
00132 {
00133 m_selected = selected;
00134 }
00135
00136 bool IconAction::isSelected() const
00137 {
00138 return m_selected;
00139 }
00140
00141 void IconAction::setRect(const QRectF &rect)
00142 {
00143 m_rect = rect;
00144 }
00145
00146 QRectF IconAction::rect() const
00147 {
00148 return m_rect;
00149 }
00150
00151 void IconAction::rebuildPixmap()
00152 {
00153
00154 QIcon::Mode mode = QIcon::Normal;
00155 if (m_selected) {
00156 mode = QIcon::Selected;
00157 }
00158
00159
00160 m_pixmap = QPixmap(26, 26);
00161 m_pixmap.fill(Qt::transparent);
00162
00163 int element = Icon::Private::Minibutton;
00164 if (m_pressed) {
00165 element = Icon::Private::MinibuttonPressed;
00166 } else if (m_hovered) {
00167 element = Icon::Private::MinibuttonHover;
00168 }
00169
00170 QPainter painter(&m_pixmap);
00171 m_icon->drawActionButtonBase(&painter, m_pixmap.size(), element);
00172 m_action->icon().paint(&painter, 2, 2, 22, 22, Qt::AlignCenter, mode);
00173 }
00174
00175 bool IconAction::event(QEvent::Type type, const QPointF &pos)
00176 {
00177 switch (type) {
00178 case QEvent::GraphicsSceneMousePress: {
00179 setSelected(m_rect.contains(pos));
00180 return isSelected();
00181 }
00182 break;
00183
00184 case QEvent::GraphicsSceneMouseMove: {
00185 bool wasSelected = isSelected();
00186 bool active = m_rect.contains(pos);
00187 setSelected(wasSelected && active);
00188 return (wasSelected != isSelected()) || active;
00189 }
00190 break;
00191
00192 case QEvent::GraphicsSceneMouseRelease: {
00193
00194 bool wasSelected = isSelected();
00195 setSelected(false);
00196 if (wasSelected) {
00197 m_action->trigger();
00198 }
00199
00200 return wasSelected;
00201 }
00202 break;
00203
00204 case QEvent::GraphicsSceneHoverEnter:
00205 m_pressed = false;
00206 m_hovered = true;
00207 break;
00208
00209 case QEvent::GraphicsSceneHoverLeave:
00210 m_pressed = false;
00211 m_hovered = false;
00212 break;
00213
00214 default:
00215 break;
00216 }
00217
00218 return false;
00219 }
00220
00221 Phase::AnimId IconAction::animationId() const
00222 {
00223 return m_animationId;
00224 }
00225
00226 QAction* IconAction::action() const
00227 {
00228 return m_action;
00229 }
00230
00231 void IconAction::paint(QPainter *painter) const
00232 {
00233 painter->drawPixmap(m_rect.toRect(), Phase::self()->animationResult(m_animationId));
00234 }
00235
00236 Icon::Icon(QGraphicsItem *parent)
00237 : Plasma::Widget(parent),
00238 d(new Private)
00239 {
00240 init();
00241 }
00242
00243 Icon::Icon(const QString &text, QGraphicsItem *parent)
00244 : Plasma::Widget(parent),
00245 d(new Private)
00246 {
00247 setText(text);
00248 init();
00249 }
00250
00251 Icon::Icon(const QIcon &icon, const QString &text, QGraphicsItem *parent)
00252 : Plasma::Widget(parent),
00253 d(new Private)
00254 {
00255 setText(text);
00256 setIcon(icon);
00257 init();
00258 }
00259
00260 Icon::~Icon()
00261 {
00262 delete d;
00263 }
00264
00265 void Icon::init()
00266 {
00267
00268 setAcceptsHoverEvents(true);
00269
00270 int focusHMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin);
00271 int focusVMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameVMargin);
00272
00273
00274 d->setHorizontalMargin(Private::TextMargin, focusHMargin, focusVMargin);
00275 d->setHorizontalMargin(Private::IconMargin, focusHMargin, focusVMargin);
00276 d->setHorizontalMargin(Private::ItemMargin, 0, 0);
00277
00278
00279 d->setVerticalMargin(Private::TextMargin, 6, 2);
00280 d->setVerticalMargin(Private::IconMargin, focusHMargin, focusVMargin);
00281 d->setVerticalMargin(Private::ItemMargin, 0, 0);
00282
00283 d->setActiveMargins();
00284 d->currentSize = QSizeF(-1, -1);
00285 }
00286
00287 void Icon::addAction(QAction *action)
00288 {
00289 int count = d->cornerActions.count();
00290 if (count > 3) {
00291 kDebug() << "Icon::addAction(QAction*) no more room for more actions!";
00292 }
00293
00294 IconAction* iconAction = new IconAction(this, action);
00295 d->cornerActions.append(iconAction);
00296 connect(action, SIGNAL(destroyed(QObject*)), this, SLOT(actionDestroyed(QObject*)));
00297
00298
00299
00300 switch (count) {
00301 case Private::TopLeft:
00302 iconAction->setRect(QRectF(6, 6, 32, 32));
00303 break;
00304 case Private::TopRight:
00305 iconAction->setRect(QRectF(size().width() - 38, 6, 32, 32));
00306 break;
00307 case Private::BottomLeft:
00308 iconAction->setRect(QRectF(6, size().height() - 38, 32, 32));
00309 break;
00310 case Private::BottomRight:
00311 iconAction->setRect(QRectF(size().width() - 38, size().height() - 38, 32, 32));
00312 break;
00313 }
00314 }
00315
00316 void Icon::actionDestroyed(QObject* action)
00317 {
00318 QList<IconAction*>::iterator it = d->cornerActions.begin();
00319
00320 while (it != d->cornerActions.end()) {
00321 if ((*it)->action() == action) {
00322 d->cornerActions.erase(it);
00323 break;
00324 }
00325 }
00326
00327 update();
00328 }
00329
00330 int Icon::numDisplayLines()
00331 {
00332 return d->numDisplayLines;
00333 }
00334
00335 void Icon::setNumDisplayLines(int numLines)
00336 {
00337 if(numLines > d->maxDisplayLines) {
00338 d->numDisplayLines = d->maxDisplayLines;
00339 }
00340 else {
00341 d->numDisplayLines = numLines;
00342 }
00343 }
00344
00345 void Icon::setDrawBackground(bool draw)
00346 {
00347 if (d->drawBg != draw) {
00348 d->drawBg = draw;
00349 update();
00350 }
00351 }
00352
00353 bool Icon::drawBackground() const
00354 {
00355 return d->drawBg;
00356 }
00357
00358 QSizeF Icon::Private::displaySizeHint(const QStyleOptionGraphicsItem *option, const qreal width) const
00359 {
00360 if (text.isEmpty() && infoText.isEmpty()) {
00361 return QSizeF( .0, .0 );
00362 }
00363 QString label = text;
00364
00365
00366
00367
00368
00369 qreal textWidth = width -
00370 horizontalMargin[Private::TextMargin].left -
00371 horizontalMargin[Private::TextMargin].right;
00372
00373
00374 const qreal maxHeight = numDisplayLines*Plasma::Theme::self()->fontMetrics().lineSpacing();
00375
00376
00377
00378 if (!infoText.isEmpty()) {
00379 label += QString(QChar::LineSeparator) + infoText;
00380 }
00381
00382 QTextLayout layout;
00383 setLayoutOptions(layout, option);
00384 QSizeF size = layoutText(layout, option, label, QSizeF(textWidth, maxHeight));
00385
00386 return addMargin(size, TextMargin);
00387 }
00388
00389 void Icon::layoutIcons(const QStyleOptionGraphicsItem *option)
00390 {
00391 if (size() == d->currentSize) {
00392 return;
00393 }
00394
00395 d->currentSize = size();
00396 d->setActiveMargins();
00397
00398
00399 qreal iconWidth;
00400
00401 if (d->orientation == Qt::Vertical) {
00402 qreal heightAvail;
00403
00404 if (!d->text.isEmpty() || !d->infoText.isEmpty()) {
00405 heightAvail = d->currentSize.height() -
00406 d->displaySizeHint(option, d->currentSize.width()).height() -
00407 d->verticalMargin[Private::TextMargin].top -
00408 d->verticalMargin[Private::TextMargin].bottom;
00409
00410 heightAvail = qMax(heightAvail, d->currentSize.height()/2);
00411 } else {
00412 heightAvail = d->currentSize.height();
00413 }
00414
00415
00416 if (d->currentSize.width() < heightAvail) {
00417 iconWidth = d->currentSize.width() -
00418 d->horizontalMargin[Private::IconMargin].left -
00419 d->horizontalMargin[Private::IconMargin].right;
00420 } else {
00421 iconWidth = heightAvail -
00422 d->verticalMargin[Private::IconMargin].top -
00423 d->verticalMargin[Private::IconMargin].bottom;
00424 }
00425
00426 } else {
00427 qreal widthAvail;
00428 QFontMetricsF fm(font());
00429
00430
00431 qreal textWidth = qMax(fm.width(d->text.left(12)),
00432 fm.width(d->infoText.left(12))) +
00433 fm.width("xx") +
00434 d->horizontalMargin[Private::TextMargin].left +
00435 d->horizontalMargin[Private::TextMargin].right;
00436
00437
00438 if (!d->text.isEmpty() || !d->infoText.isEmpty()) {
00439 widthAvail = d->currentSize.width() -
00440
00441 textWidth -
00442 d->horizontalMargin[Private::TextMargin].left -
00443 d->horizontalMargin[Private::TextMargin].right;
00444 } else {
00445 widthAvail = d->currentSize.width();
00446 }
00447
00448
00449 if (d->currentSize.height() < widthAvail) {
00450 iconWidth = d->currentSize.height() -
00451 d->verticalMargin[Private::IconMargin].top -
00452 d->verticalMargin[Private::IconMargin].bottom;
00453 } else {
00454 iconWidth = widthAvail -
00455 d->horizontalMargin[Private::IconMargin].left -
00456 d->horizontalMargin[Private::IconMargin].right;
00457 }
00458 }
00459
00460 d->iconSize = QSizeF(iconWidth, iconWidth);
00461
00462 int count = 0;
00463 foreach (IconAction* iconAction, d->cornerActions) {
00464
00465
00466 switch (count) {
00467 case Private::TopLeft:
00468
00469
00470 break;
00471 case Private::TopRight:
00472 iconAction->setRect(QRectF(d->currentSize.width() - 38, 6, 32, 32));
00473 break;
00474 case Private::BottomLeft:
00475 iconAction->setRect(QRectF(6, d->currentSize.height() - 38, 32, 32));
00476 break;
00477 case Private::BottomRight:
00478 iconAction->setRect(QRectF(d->currentSize.width() - 38, d->currentSize.height() - 38, 32, 32));
00479 break;
00480 }
00481
00482 ++count;
00483 }
00484
00485 }
00486
00487 void Icon::setSvg(const QString &svgFilePath, const QString &elementId)
00488 {
00489 if (!d->iconSvg) {
00490 d->iconSvg = new Plasma::Svg(svgFilePath);
00491 } else {
00492 d->iconSvg->setFile(svgFilePath);
00493 }
00494
00495 d->iconSvgElement = elementId;
00496 }
00497
00498 void Icon::Private::drawBackground(QPainter *painter, IconState state)
00499 {
00500 if (!drawBg) {
00501 return;
00502 }
00503
00504 bool darkShadow = shadowColor.value() < 128;
00505 QColor shadow = shadowColor;
00506
00507 shadow.setAlphaF(.35);
00508
00509 switch (state) {
00510 case Private::HoverState:
00511 shadow.setHsv(shadow.hue(),
00512 shadow.saturation(),
00513 shadow.value()+(darkShadow?50:-50),
00514 100);
00515 break;
00516 case Private::PressedState:
00517 shadow.setHsv(shadow.hue(),
00518 shadow.saturation(),
00519 shadow.value()+(darkShadow?100:-100),
00520 128);
00521 break;
00522 default:
00523 break;
00524 }
00525
00526 painter->save();
00527 painter->setRenderHint(QPainter::Antialiasing);
00528 painter->setBrush(shadow);
00529 painter->setPen(QPen(shadow, 1.0));
00530 painter->drawPath(roundedRectangle(QRectF(QPointF(0.0, 0.0), currentSize), 10.0));
00531 painter->restore();
00532 }
00533
00534 QPixmap Icon::Private::decoration(const QStyleOptionGraphicsItem *option, bool useHoverEffect)
00535 {
00536 QPixmap result;
00537
00538 QIcon::Mode mode = option->state & QStyle::State_Enabled ? QIcon::Normal : QIcon::Disabled;
00539 QIcon::State state = option->state & QStyle::State_Open ? QIcon::On : QIcon::Off;
00540
00541 if (iconSvg) {
00542 if (iconSvgPixmap.size() != iconSize.toSize()) {
00543 QImage img(iconSize.toSize(), QImage::Format_ARGB32_Premultiplied);
00544 {
00545 img.fill(0);
00546 QPainter p(&img);
00547 iconSvg->resize(iconSize);
00548 iconSvg->paint(&p, img.rect(), iconSvgElement);
00549 }
00550 iconSvgPixmap = QPixmap::fromImage(img);
00551 }
00552 result = iconSvgPixmap;
00553 } else {
00554 const QSize size = icon.actualSize(iconSize.toSize(), mode, state);
00555 result = icon.pixmap(size, mode, state);
00556 }
00557
00558 if (!result.isNull() && useHoverEffect) {
00559 KIconEffect *effect = KIconLoader::global()->iconEffect();
00560
00561
00562
00563
00564 if (effect->hasEffect(KIconLoader::Desktop, KIconLoader::ActiveState)) {
00565 result = effect->apply(result, KIconLoader::Desktop, KIconLoader::ActiveState);
00566 }
00567 }
00568
00569 return result;
00570 }
00571
00572 QPointF Icon::Private::iconPosition(const QStyleOptionGraphicsItem *option, const QPixmap &pixmap) const
00573 {
00574 const QRectF itemRect = subtractMargin(option->rect, Private::ItemMargin);
00575
00576
00577 const QSizeF size = addMargin(iconSize, Private::IconMargin);
00578
00579 Qt::LayoutDirection direction = iconDirection(option);
00580
00581
00582 Qt::Alignment alignment;
00583 if (text.isEmpty() && infoText.isEmpty()) {
00584 alignment = Qt::AlignCenter;
00585 }else if (orientation == Qt::Vertical) {
00586 alignment = Qt::Alignment(Qt::AlignHCenter | Qt::AlignTop);
00587
00588 }else{
00589 alignment = QStyle::visualAlignment(direction, Qt::Alignment(Qt::AlignLeft | Qt::AlignVCenter));
00590 }
00591
00592 const QRect iconRect = QStyle::alignedRect(direction, alignment, size.toSize(), itemRect.toRect());
00593
00594
00595 QRect pixmapRect = pixmap.rect();
00596 pixmapRect.moveCenter(iconRect.center());
00597
00598
00599
00600
00601 return QPointF(pixmapRect.topLeft());
00602 }
00603
00604 QRectF Icon::Private::labelRectangle(const QStyleOptionGraphicsItem *option, const QPixmap &icon,
00605 const QString &string) const
00606 {
00607 Q_UNUSED(string)
00608
00609 if (icon.isNull()) {
00610 return option->rect;
00611 }
00612
00613 const QSizeF decoSize = addMargin(iconSize, Private::IconMargin);
00614
00615 const QRectF itemRect = subtractMargin(option->rect, Private::ItemMargin);
00616 QRectF textArea(QPointF(0, 0), itemRect.size());
00617
00618
00619 if (orientation == Qt::Vertical) {
00620 textArea.setTop(decoSize.height() + 1);
00621
00622 }else{
00623 textArea.setLeft(decoSize.width() + 1);
00624 }
00625
00626 textArea.translate(itemRect.topLeft());
00627
00628 return QRectF(QStyle::visualRect(iconDirection(option), option->rect, textArea.toRect()));
00629 }
00630
00631
00632 QSizeF Icon::Private::layoutText(QTextLayout &layout, const QStyleOptionGraphicsItem *option,
00633 const QString &text, const QSizeF &constraints) const
00634 {
00635 const QSizeF size = layoutText(layout, text, constraints.width());
00636
00637 if (size.width() > constraints.width() || size.height() > constraints.height())
00638 {
00639 const QString elided = elidedText(layout, option, constraints);
00640 return layoutText(layout, elided, constraints.width());
00641 }
00642
00643 return size;
00644 }
00645
00646
00647 QSizeF Icon::Private::layoutText(QTextLayout &layout, const QString &text, qreal maxWidth) const
00648 {
00649 QFontMetricsF metrics(layout.font());
00650 qreal leading = metrics.leading();
00651 qreal height = 0.0;
00652 qreal widthUsed = 0.0;
00653 QTextLine line;
00654
00655 layout.setText(text);
00656
00657 layout.beginLayout();
00658
00659 while ((line = layout.createLine()).isValid())
00660 {
00661 line.setLineWidth(maxWidth);
00662 height += leading;
00663 line.setPosition(QPointF(0.0, height));
00664 height += line.height();
00665 widthUsed = qMax(widthUsed, line.naturalTextWidth());
00666 }
00667 layout.endLayout();
00668
00669 return QSizeF(widthUsed, height);
00670 }
00671
00672
00673
00674
00675
00676 QString Icon::Private::elidedText(QTextLayout &layout, const QStyleOptionGraphicsItem *option,
00677 const QSizeF &size) const
00678 {
00679 Q_UNUSED(option)
00680
00681 QFontMetricsF metrics(layout.font());
00682 const QString text = layout.text();
00683 qreal maxWidth = size.width();
00684 qreal maxHeight = size.height();
00685 qreal height = 0;
00686
00687
00688 QString elided;
00689 elided.reserve(text.length());
00690
00691 for (int i = 0; i < layout.lineCount(); i++)
00692 {
00693 QTextLine line = layout.lineAt(i);
00694 int start = line.textStart();
00695 int length = line.textLength();
00696
00697 height += metrics.leading();
00698 if (height + line.height() + metrics.lineSpacing() > maxHeight)
00699 {
00700
00701
00702 if (line.naturalTextWidth() < maxWidth && start+length > 0 && text[start + length - 1] == QChar::LineSeparator)
00703 elided += text.mid(start, length - 1);
00704 else
00705 elided += metrics.elidedText(text.mid(start), Qt::ElideRight, maxWidth);
00706 break;
00707 }
00708 else if (line.naturalTextWidth() > maxWidth)
00709 elided += metrics.elidedText(text.mid(start, length), Qt::ElideRight, maxWidth);
00710 else
00711 elided += text.mid(start, length);
00712
00713 height += line.height();
00714 }
00715
00716 return elided;
00717 }
00718
00719 void Icon::Private::layoutTextItems(const QStyleOptionGraphicsItem *option,
00720 const QPixmap &icon, QTextLayout *labelLayout,
00721 QTextLayout *infoLayout, QRectF *textBoundingRect) const
00722 {
00723 bool showInformation = false;
00724
00725 setLayoutOptions(*labelLayout, option);
00726
00727 QFontMetricsF fm(labelLayout->font());
00728 const QRectF textArea = labelRectangle(option, icon, text);
00729 QRectF textRect = subtractMargin(textArea, Private::TextMargin);
00730
00731
00732 QSizeF maxLabelSize = textRect.size();
00733 QSizeF maxInfoSize = textRect.size();
00734 QSizeF labelSize;
00735 QSizeF infoSize;
00736
00737
00738
00739 if (!infoText.isEmpty() && textRect.height() >= fm.lineSpacing() * 2)
00740 {
00741 infoLayout->setFont(labelLayout->font());
00742 infoLayout->setTextOption(labelLayout->textOption());
00743
00744 maxLabelSize.rheight() -= fm.lineSpacing();
00745 showInformation = true;
00746 }
00747
00748
00749 labelSize = layoutText(*labelLayout, option, text, maxLabelSize);
00750 maxInfoSize.rheight() -= labelSize.height();
00751
00752
00753 if (showInformation)
00754 infoSize = layoutText(*infoLayout, option, infoText, maxInfoSize);
00755 else
00756 infoSize = QSizeF(0, 0);
00757
00758
00759 const Qt::Alignment alignment = labelLayout->textOption().alignment();
00760 const QSizeF size(qMax(labelSize.width(), infoSize.width()), labelSize.height() + infoSize.height());
00761 *textBoundingRect = QStyle::alignedRect(iconDirection(option), alignment, size.toSize(), textRect.toRect());
00762
00763
00764 labelLayout->setPosition(QPointF(textRect.x(), textBoundingRect->y()));
00765 infoLayout->setPosition(QPointF(textRect.x(), textBoundingRect->y() + labelSize.height()));
00766 }
00767
00768 QBrush Icon::Private::foregroundBrush(const QStyleOptionGraphicsItem *option) const
00769 {
00770 const QPalette::ColorGroup group = option->state & QStyle::State_Enabled ?
00771 QPalette::Normal : QPalette::Disabled;
00772
00773
00774 if (option->state & QStyle::State_Selected)
00775 return option->palette.brush(group, QPalette::HighlightedText);
00776
00777 return option->palette.brush(group, QPalette::Text);
00778 }
00779
00780 QBrush Icon::Private::backgroundBrush(const QStyleOptionGraphicsItem *option) const
00781 {
00782 const QPalette::ColorGroup group = option->state & QStyle::State_Enabled ?
00783 QPalette::Normal : QPalette::Disabled;
00784
00785 QBrush background(Qt::NoBrush);
00786
00787
00788 if (option->state & QStyle::State_Selected)
00789 background = option->palette.brush(group, QPalette::Highlight);
00790
00791 return background;
00792 }
00793
00794 void Icon::Private::drawTextItems(QPainter *painter, const QStyleOptionGraphicsItem *option,
00795 const QTextLayout &labelLayout, const QTextLayout &infoLayout) const
00796 {
00797 Q_UNUSED(option)
00798
00799 painter->setPen(textColor);
00800 labelLayout.draw(painter, QPointF());
00801
00802 if (!infoLayout.text().isEmpty()) {
00803 painter->setPen(textColor);
00804 infoLayout.draw(painter, QPointF());
00805 }
00806 }
00807
00808
00809 void Icon::paintWidget(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
00810 {
00811 Q_UNUSED(option)
00812 Q_UNUSED(widget)
00813
00814 #ifdef BACKINGSTORE_BLUR_HACK
00815 if (d->state == Private::HoverState && scene()) {
00816 QList<QGraphicsView*> views = scene()->views();
00817 if (views.count() > 0) {
00818 QPixmap* pix = static_cast<QPixmap*>(views[0]->windowSurface()->paintDevice());
00819 QImage image(boundingRect().size().toSize(), QImage::Format_ARGB32_Premultiplied);
00820 {
00821 QPainter p(&image);
00822 p.drawPixmap(image.rect(), *pix, sceneBoundingRect());
00823 }
00824 expblur<16,7>(image, 8);
00825 painter->drawImage(0, 0, image);
00826 }
00827 }
00828 #endif
00829
00830
00831 layoutIcons(option);
00832
00833
00834
00835 Private::IconState state = Private::NoState;
00836 if (d->states & Private::ManualPressedState) {
00837 state = Private::PressedState;
00838 } else if (d->states & Private::PressedState) {
00839 if (d->states & Private::HoverState) {
00840 state = Private::PressedState;
00841 }
00842 } else if (d->states & Private::HoverState) {
00843 state = Private::HoverState;
00844 }
00845
00846 QPixmap icon = d->decoration(option, state != Private::NoState);
00847 const QPointF iconPos = d->iconPosition(option, icon);
00848
00849 QTextLayout labelLayout, infoLayout;
00850 QRectF textBoundingRect;
00851 d->layoutTextItems(option, icon, &labelLayout, &infoLayout, &textBoundingRect);
00852
00853 d->drawBackground(painter, state);
00854
00855
00856 painter->drawPixmap(iconPos, icon);
00857
00858
00859 foreach (IconAction *action, d->cornerActions) {
00860 if (action->animationId()) {
00861 action->paint(painter);
00862 }
00863 }
00864
00865
00866 d->drawTextItems(painter, option, labelLayout, infoLayout);
00867 }
00868
00869 void Icon::drawActionButtonBase(QPainter* painter, const QSize &size, int element)
00870 {
00871 qreal radius = size.width()/2;
00872 QRadialGradient gradient(radius, radius, radius, radius, radius);
00873 int alpha;
00874
00875 if (element == Private::MinibuttonPressed) {
00876 alpha = 255;
00877 } else if (element == Private::MinibuttonHover) {
00878 alpha = 200;
00879 } else {
00880 alpha = 160;
00881 }
00882 gradient.setColorAt(0, QColor::fromRgb(d->textColor.red(),
00883 d->textColor.green(),
00884 d->textColor.blue(), alpha));
00885 gradient.setColorAt(1, QColor::fromRgb(d->textColor.red(),
00886 d->textColor.green(),
00887 d->textColor.blue(), 0));
00888
00889 painter->setBrush(gradient);
00890 painter->setPen(Qt::NoPen);
00891 painter->drawEllipse(QRectF(QPointF(.0, .0), size));
00892 }
00893
00894
00895 void Icon::setText(const QString& text)
00896 {
00897 d->text = text;
00898
00899 d->currentSize = QSizeF(-1, -1);
00900 }
00901
00902 QString Icon::text() const
00903 {
00904 return d->text;
00905 }
00906
00907 void Icon::setInfoText(const QString& text)
00908 {
00909 d->infoText = text;
00910
00911 d->currentSize = QSizeF(-1, -1);
00912 }
00913
00914 QString Icon::infoText() const
00915 {
00916 return d->infoText;
00917 }
00918
00919 QIcon Icon::icon() const
00920 {
00921 return d->icon;
00922 }
00923
00924 void Icon::setIcon(const QString& icon)
00925 {
00926 if (icon.isEmpty()) {
00927 setIcon(QIcon());
00928 return;
00929 }
00930
00931 setIcon(KIcon(icon));
00932 }
00933
00934 void Icon::setIcon(const QIcon& icon)
00935 {
00936 d->icon = icon;
00937 }
00938
00939 QSizeF Icon::iconSize() const
00940 {
00941 return d->iconSize;
00942 }
00943
00944 bool Icon::isDown()
00945 {
00946 return d->states & Private::PressedState;
00947 }
00948
00949 void Icon::mousePressEvent(QGraphicsSceneMouseEvent *event)
00950 {
00951 if (event->button() != Qt::LeftButton) {
00952 Widget::mousePressEvent(event);
00953 return;
00954 }
00955
00956 d->states |= Private::PressedState;
00957
00958 bool handled = false;
00959 foreach (IconAction *action, d->cornerActions) {
00960 handled = action->event(event->type(), event->pos());
00961 if (handled) {
00962 break;
00963 }
00964 }
00965
00966 if (!handled) {
00967 emit pressed(true);
00968 }
00969
00970 update();
00971 }
00972
00973 void Icon::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
00974 {
00975 if (~d->states & Private::PressedState) {
00976 Widget::mouseMoveEvent(event);
00977 return;
00978 }
00979
00980 if (boundingRect().contains(event->pos())) {
00981 if (~d->states & Private::HoverState) {
00982 d->states |= Private::HoverState;
00983 update();
00984 }
00985 } else {
00986 if (d->states & Private::HoverState) {
00987 d->states &= ~Private::HoverState;
00988 update();
00989 }
00990 }
00991
00992 d->states |= Private::MovedState;
00993 }
00994
00995 void Icon::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
00996 {
00997 if (~d->states & Private::PressedState) {
00998 Widget::mouseMoveEvent(event);
00999 return;
01000 }
01001
01002 d->states &= ~Private::PressedState;
01003
01004 bool handled = false;
01005 foreach (IconAction *action, d->cornerActions) {
01006 if (action->event(event->type(), event->pos())) {
01007 handled = true;
01008 break;
01009 }
01010 }
01011
01012 if (d->states & Private::MovedState) {
01013 d->states &= ~Private::MovedState;
01014 handled = true;
01015 }
01016
01017 if (!handled) {
01018 if (boundingRect().contains(event->pos())) {
01019 emit clicked();
01020 }
01021 emit pressed(false);
01022 }
01023
01024 update();
01025 }
01026
01027 void Icon::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
01028 {
01029 Q_UNUSED(event)
01030 if (!KGlobalSettings::singleClick()) {
01031 emit doubleClicked();
01032 }
01033 }
01034
01035 void Icon::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
01036 {
01037 foreach (IconAction *action, d->cornerActions) {
01038 action->show();
01039 action->event(event->type(), event->pos());
01040 }
01041
01042 d->states |= Private::HoverState;
01043 update();
01044
01045 Widget::hoverEnterEvent(event);
01046 }
01047
01048 void Icon::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
01049 {
01050 foreach (IconAction *action, d->cornerActions) {
01051 action->hide();
01052 action->event(event->type(), event->pos());
01053 }
01054
01055 d->states &= ~Private::HoverState;
01056 update();
01057
01058 Widget::hoverLeaveEvent(event);
01059 }
01060
01061 void Icon::setPressed(bool pressed)
01062 {
01063 if (pressed) {
01064 d->states |= Private::ManualPressedState;
01065 } else {
01066 d->states &= ~Private::ManualPressedState;
01067 }
01068 update();
01069 }
01070
01071 void Icon::setUnpressed()
01072 {
01073 setPressed(false);
01074 }
01075
01076 void Icon::setOrientation(Qt::Orientation orientation)
01077 {
01078 d->orientation = orientation;
01079 }
01080
01081 void Icon::invertLayout(bool invert)
01082 {
01083 d->invertLayout = invert;
01084 }
01085
01086 bool Icon::invertedLayout() const
01087 {
01088 return d->invertLayout;
01089 }
01090
01091 QSizeF Icon::sizeFromIconSize(const qreal iconWidth) const
01092 {
01093
01094 if (d->text.isEmpty() && d->infoText.isEmpty()) {
01095 return d->addMargin(d->addMargin(QSizeF(iconWidth, iconWidth),
01096 Private::IconMargin),
01097 Private::ItemMargin);
01098 }
01099
01100 QFontMetricsF fm(font());
01101
01102 qreal width = qMax(fm.width(d->text.left(12)),
01103 fm.width(d->infoText.left(12))) +
01104 fm.width("xx") +
01105 d->horizontalMargin[Private::TextMargin].left +
01106 d->horizontalMargin[Private::TextMargin].right;
01107
01108 if (d->orientation == Qt::Vertical) {
01109 width = qMax(width,
01110 iconWidth +
01111 d->horizontalMargin[Private::IconMargin].left +
01112 d->horizontalMargin[Private::IconMargin].right);
01113 }
01114
01115 qreal height;
01116 qreal textHeight;
01117
01118 QStyleOptionGraphicsItem option;
01119 option.state = QStyle::State_None;
01120 option.rect = boundingRect().toRect();
01121 textHeight = d->displaySizeHint(&option, width).height();
01122
01123 if (d->orientation == Qt::Vertical) {
01124 height = iconWidth + textHeight +
01125 d->verticalMargin[Private::TextMargin].top +
01126 d->verticalMargin[Private::TextMargin].bottom +
01127 d->verticalMargin[Private::IconMargin].top +
01128 d->verticalMargin[Private::IconMargin].bottom;
01129
01130 }else{
01131 height = qMax(iconWidth +
01132 d->verticalMargin[Private::IconMargin].top +
01133 d->verticalMargin[Private::IconMargin].bottom,
01134 textHeight +
01135 d->verticalMargin[Private::TextMargin].top +
01136 d->verticalMargin[Private::IconMargin].bottom);
01137 width = width + iconWidth +
01138 d->horizontalMargin[Private::IconMargin].left +
01139 d->horizontalMargin[Private::IconMargin].right;
01140 }
01141
01142 return d->addMargin(QSizeF(width, height), Private::ItemMargin);
01143 }
01144
01145 }
01146
01147 #include "icon.moc"