26 #include "iconwidget_p.h"
29 #include <QApplication>
30 #include <QGraphicsSceneMouseEvent>
31 #include <QGraphicsView>
34 #include <QStyleOptionGraphicsItem>
35 #include <QTextLayout>
38 #include <kcolorscheme.h>
40 #include <kglobalsettings.h>
42 #include <kiconeffect.h>
43 #include <kiconloader.h>
44 #include <kmimetype.h>
50 #include "private/themedwidgetinterface_p.h"
65 IconHoverAnimation::IconHoverAnimation(
QObject *parent)
66 :
QObject(parent), m_value(0), m_fadeIn(false)
70 qreal IconHoverAnimation::value()
const
75 bool IconHoverAnimation::fadeIn()
const
82 return m_animation.data();
85 void IconHoverAnimation::setValue(qreal value)
92 void IconHoverAnimation::setFadeIn(
bool fadeIn)
97 void IconHoverAnimation::setAnimation(QPropertyAnimation *
animation)
102 IconWidgetPrivate::IconWidgetPrivate(
IconWidget *i)
105 hoverAnimation(new IconHoverAnimation(q)),
107 preferredIconSize(-1, -1),
108 minimumIconSize(-1, -1),
109 maximumIconSize(-1, -1),
110 states(IconWidgetPrivate::NoState),
114 iconSvgElementChanged(false),
117 textBgCustomized(false)
121 IconWidgetPrivate::~IconWidgetPrivate()
123 qDeleteAll(cornerActions);
124 delete hoverAnimation;
127 void IconWidgetPrivate::readColors()
131 if (qGray(textColor.rgb()) > 192) {
132 shadowColor = Qt::black;
134 shadowColor = Qt::white;
137 if (!textBgCustomized) {
138 textBgColor = QColor();
142 void IconWidgetPrivate::colorConfigChanged()
146 qreal left, top, right, bottom;
147 background->getMargins(left, top, right, bottom);
148 setVerticalMargin(IconWidgetPrivate::ItemMargin, left, top, right, bottom);
149 setHorizontalMargin(IconWidgetPrivate::ItemMargin, left, top, right, bottom);
154 void IconWidgetPrivate::iconConfigChanged()
156 if (!icon.isNull()) {
161 IconAction::IconAction(
IconWidget *icon, QAction *action)
171 void IconAction::show()
173 Animation *
animation = m_animation.data();
176 animation->setTargetWidget(m_icon);
178 }
else if (animation->state() == QAbstractAnimation::Running) {
185 animation->setProperty(
"targetPixmap", m_pixmap);
186 animation->setDirection(QAbstractAnimation::Forward);
190 void IconAction::hide()
196 Animation *animation = m_animation.data();
197 if (animation->state() == QAbstractAnimation::Running) {
203 animation->setDirection(QAbstractAnimation::Backward);
204 animation->start(QAbstractAnimation::DeleteWhenStopped);
207 bool IconAction::isVisible()
const
212 bool IconAction::isAnimating()
const
214 return !m_animation.isNull();
217 bool IconAction::isPressed()
const
222 bool IconAction::isHovered()
const
227 void IconAction::setSelected(
bool selected)
229 m_selected = selected;
232 bool IconAction::isSelected()
const
237 void IconAction::setRect(
const QRectF &rect)
242 QRectF IconAction::rect()
const
247 void IconAction::rebuildPixmap()
250 QIcon::Mode mode = m_selected ? QIcon::Selected : QIcon::Normal;
253 m_pixmap = QPixmap(26, 26);
254 m_pixmap.fill(Qt::transparent);
256 int element = IconWidgetPrivate::Minibutton;
258 element = IconWidgetPrivate::MinibuttonPressed;
259 }
else if (m_hovered) {
260 element = IconWidgetPrivate::MinibuttonHover;
263 QPainter painter(&m_pixmap);
264 m_icon->drawActionButtonBase(&painter, m_pixmap.size(), element);
265 m_action->icon().paint(&painter, 2, 2, 22, 22, Qt::AlignCenter, mode);
268 bool IconAction::event(QEvent::Type
type,
const QPointF &pos)
270 if (!m_action->isVisible() || !m_action->isEnabled()) {
274 if (m_icon->size().width() < m_rect.width() * 2.0 ||
275 m_icon->size().height() < m_rect.height() * 2.0) {
280 case QEvent::GraphicsSceneMousePress:
282 setSelected(m_rect.contains(pos));
287 case QEvent::GraphicsSceneMouseMove:
289 bool wasSelected = isSelected();
290 bool active = m_rect.contains(pos);
291 setSelected(wasSelected && active);
292 return (wasSelected != isSelected()) || active;
296 case QEvent::GraphicsSceneMouseRelease:
299 bool wasSelected = isSelected();
309 case QEvent::GraphicsSceneHoverEnter:
314 case QEvent::GraphicsSceneHoverLeave:
326 QAction *IconAction::action()
const
331 void IconAction::paint(QPainter *painter)
const
333 if (!m_action->isVisible() || !m_action->isEnabled()) {
337 if (m_icon->size().width() < m_rect.width() * 2.0 ||
338 m_icon->size().height() < m_rect.height() * 2.0) {
342 Animation *animation = m_animation.data();
343 if (m_visible && !animation) {
344 painter->drawPixmap(m_rect.toRect(), m_pixmap);
346 painter->drawPixmap(m_rect.toRect(),
347 animation->property(
"currentPixmap").value<QPixmap>());
353 d(new IconWidgetPrivate(this))
360 d(new IconWidgetPrivate(this))
368 d(new IconWidgetPrivate(this))
380 void IconWidgetPrivate::init()
384 iconChangeTimer =
new QTimer(q);
385 iconChangeTimer->setSingleShot(
true);
388 QObject::connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()), q, SLOT(colorConfigChanged()));
389 QObject::connect(KGlobalSettings::self(), SIGNAL(iconChanged(
int)), q, SLOT(iconConfigChanged()));
392 q->setAcceptsHoverEvents(
true);
393 q->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
396 background->setImagePath(
"widgets/viewitem");
397 background->setCacheAllRenderedFrames(
true);
398 background->setElementPrefix(
"hover");
401 setHorizontalMargin(IconWidgetPrivate::TextMargin, 1, 1);
402 setHorizontalMargin(IconWidgetPrivate::IconMargin, 1, 1);
403 setHorizontalMargin(IconWidgetPrivate::ItemMargin, 0, 0);
406 setVerticalMargin(IconWidgetPrivate::TextMargin, 6, 2);
407 setVerticalMargin(IconWidgetPrivate::IconMargin, 1, 1);
408 setVerticalMargin(IconWidgetPrivate::ItemMargin, 0, 0);
411 currentSize = QSizeF(-1, -1);
417 int count = d->cornerActions.count();
418 if (count >= IconWidgetPrivate::LastIconPosition) {
419 kDebug() <<
"no more room for more actions!";
423 IconAction *iconAction =
new IconAction(
this, action);
424 d->cornerActions.append(iconAction);
425 connect(action, SIGNAL(destroyed(
QObject*)),
this, SLOT(actionDestroyed(
QObject*)));
427 iconAction->setRect(d->actionRect(qMin((IconWidgetPrivate::ActionPosition)count, IconWidgetPrivate::LastIconPosition)));
436 foreach (IconAction *iconAction, d->cornerActions) {
438 iconAction->setRect(d->actionRect((IconWidgetPrivate::ActionPosition)count));
439 }
else if (!action || iconAction->action() ==
action) {
441 d->cornerActions.removeAll(iconAction);
444 if (count < IconWidgetPrivate::LastIconPosition) {
453 void IconWidgetPrivate::actionDestroyed(
QObject *action)
455 q->removeIconAction(static_cast<QAction*>(action));
460 d->setAction(action);
470 return d->numDisplayLines;
475 if (numLines > d->maxDisplayLines) {
476 d->numDisplayLines = d->maxDisplayLines;
478 d->numDisplayLines = numLines;
484 if (d->drawBg != draw) {
487 QStyle *style = QApplication::style();
488 int focusHMargin = draw ? style->pixelMetric(QStyle::PM_FocusFrameHMargin) : 1;
489 int focusVMargin = draw ? style->pixelMetric(QStyle::PM_FocusFrameVMargin) : 1;
490 d->setHorizontalMargin(IconWidgetPrivate::TextMargin, focusHMargin, focusVMargin);
491 d->setHorizontalMargin(IconWidgetPrivate::IconMargin, focusHMargin, focusVMargin);
492 d->setVerticalMargin(IconWidgetPrivate::IconMargin, focusHMargin, focusVMargin);
493 d->currentSize = QSizeF(-1, -1);
496 qreal left, top, right, bottom;
497 d->background->getMargins(left, top, right, bottom);
498 d->setHorizontalMargin(IconWidgetPrivate::ItemMargin, left, top, right, bottom);
499 d->setVerticalMargin(IconWidgetPrivate::ItemMargin, left, top, right, bottom);
501 d->setHorizontalMargin(IconWidgetPrivate::ItemMargin, 0, 0);
502 d->setVerticalMargin(IconWidgetPrivate::ItemMargin, 0, 0);
517 if (!d->drawBg || d->currentSize.width() < 1) {
518 return QGraphicsItem::shape();
522 QRectF(QPointF(0.0, 0.0), d->currentSize).adjusted(-2, -2, 2, 2), 10.0);
527 if (text.isEmpty() && infoText.isEmpty()) {
528 return QSizeF(.0, .0);
531 QString label = text;
536 qreal textWidth = width -
537 horizontalMargin[IconWidgetPrivate::TextMargin].left -
538 horizontalMargin[IconWidgetPrivate::TextMargin].right;
541 const qreal maxHeight =
542 numDisplayLines * QFontMetrics(q->font()).lineSpacing();
546 if (!infoText.isEmpty()) {
547 label += QString(QChar::LineSeparator) + infoText;
551 setLayoutOptions(layout, option, q->orientation());
552 layout.setFont(q->font());
553 QSizeF size = layoutText(layout, label, QSizeF(textWidth, maxHeight));
555 return addMargin(size, TextMargin);
560 if (option->rect.size() == currentSize) {
564 currentSize = option->rect.size();
565 iconSize = iconSizeForWidgetSize(option, currentSize);
568 foreach (IconAction *iconAction, cornerActions) {
569 iconAction->setRect(actionRect((IconWidgetPrivate::ActionPosition)count));
584 if (text.isEmpty() && infoText.isEmpty()) {
585 heightAvail = rect.height();
587 heightAvail = rect.height() -
588 displaySizeHint(option, rect.width()).height() -
589 verticalMargin[IconWidgetPrivate::TextMargin].top -
590 verticalMargin[IconWidgetPrivate::TextMargin].bottom;
592 heightAvail = qMax(heightAvail, rect.height() / 2);
596 if (!text.isEmpty() || !infoText.isEmpty()) {
597 if (rect.width() < heightAvail) {
598 iconWidth = rect.width() -
599 verticalMargin[IconWidgetPrivate::IconMargin].left -
600 verticalMargin[IconWidgetPrivate::IconMargin].right;
602 iconWidth = heightAvail -
603 verticalMargin[IconWidgetPrivate::IconMargin].top -
604 verticalMargin[IconWidgetPrivate::IconMargin].bottom;
607 iconWidth = qMin(heightAvail, rect.width());
610 iconWidth -= verticalMargin[IconWidgetPrivate::ItemMargin].left + verticalMargin[IconWidgetPrivate::ItemMargin].right;
614 if (text.isEmpty() && infoText.isEmpty()) {
616 iconWidth = qMin(rect.height(), rect.width());
618 iconWidth = rect.height() -
619 horizontalMargin[IconWidgetPrivate::IconMargin].top -
620 horizontalMargin[IconWidgetPrivate::IconMargin].bottom;
622 iconWidth -= horizontalMargin[IconWidgetPrivate::ItemMargin].top + horizontalMargin[IconWidgetPrivate::ItemMargin].bottom;
625 QSizeF iconRect(iconWidth, iconWidth);
627 if (maximumIconSize.isValid()) {
628 iconRect = iconRect.boundedTo(maximumIconSize);
636 if (svgFilePath.isEmpty()) {
638 d->iconSvg->deleteLater();
646 connect(d->iconSvg, SIGNAL(repaintNeeded()),
this, SLOT(svgChanged()));
647 d->oldIcon = d->icon;
649 d->oldIcon = d->iconSvg->pixmap(d->iconSvgElement);
652 d->iconSvg->setImagePath(svgFilePath);
653 d->iconSvg->setContainsMultipleImages(!elementId.isNull());
654 d->iconSvgElement = elementId;
655 d->iconSvgElementChanged =
true;
658 if (!(d->states & IconWidgetPrivate::HoverState) && !d->iconChangeTimer->isActive() && !d->oldIcon.isNull()) {
659 d->animateMainIcon(
true, d->states);
661 d->oldIcon = QIcon();
664 d->iconChangeTimer->start(300);
671 if (d->iconSvg->isValid() && (d->iconSvgElement.isEmpty() || d->iconSvg->hasElement(d->iconSvgElement))) {
672 return d->iconSvg->imagePath();
683 if (which == Qt::PreferredSize) {
686 if (d->preferredIconSize.isValid()) {
687 iconSize = qMax(d->preferredIconSize.height(), d->preferredIconSize.width());
688 }
else if (d->iconSvg) {
689 QSizeF oldSize = d->iconSvg->size();
690 d->iconSvg->resize();
691 if (d->iconSvgElement.isNull()) {
692 iconSize = qMax(d->iconSvg->size().width(), d->iconSvg->size().height());
694 iconSize = qMax(d->iconSvg->elementSize(d->iconSvgElement).width(), d->iconSvg->elementSize(d->iconSvgElement).height());
696 d->iconSvg->resize(oldSize);
698 iconSize = KIconLoader::SizeMedium;
701 if (constraint.width() > 0 || constraint.height() > 0) {
702 QSizeF constrainedWidgetSize(constraint);
703 QSizeF maximumWidgetSize;
705 if (d->maximumIconSize.isValid()) {
707 sizeFromIconSize(qMax(d->maximumIconSize.height(), d->maximumIconSize.width()));
710 QGraphicsWidget::sizeHint(Qt::MaximumSize);
713 if (constrainedWidgetSize.width() <= 0) {
714 constrainedWidgetSize.setWidth(maximumWidgetSize.width());
716 if (constrainedWidgetSize.height() <= 0) {
717 constrainedWidgetSize.setHeight(maximumWidgetSize.height());
722 d->iconSizeForWidgetSize(&option, constrainedWidgetSize);
724 qMin(iconSize, qMax<int>(iconRect.width(), iconRect.height()));
728 }
else if (which == Qt::MinimumSize) {
729 if (d->minimumIconSize.isValid()) {
730 return sizeFromIconSize(qMax(d->minimumIconSize.height(), d->minimumIconSize.width()));
735 if (d->maximumIconSize.isValid()) {
736 return sizeFromIconSize(qMax(d->maximumIconSize.height(), d->maximumIconSize.width()));
739 return QGraphicsWidget::sizeHint(which, constraint);
743 void IconWidgetPrivate::animateMainIcon(
bool show,
const IconWidgetStates state)
749 hoverAnimation->setFadeIn(show);
751 QPropertyAnimation *animation = hoverAnimation->animation();
753 animation =
new QPropertyAnimation(hoverAnimation,
"value");
754 animation->setDuration(150);
755 animation->setEasingCurve(QEasingCurve::OutQuad);
756 animation->setStartValue(0.0);
757 animation->setEndValue(1.0);
758 hoverAnimation->setAnimation(animation);
759 q->connect(animation, SIGNAL(finished()), q, SLOT(hoverAnimationFinished()));
760 }
else if (animation->state() == QAbstractAnimation::Running) {
764 animation->setDirection(show ? QAbstractAnimation::Forward : QAbstractAnimation::Backward);
765 animation->start(show ? QAbstractAnimation::KeepWhenStopped : QAbstractAnimation::DeleteWhenStopped);
769 void IconWidgetPrivate::hoverAnimationFinished()
771 if (!hoverAnimation->fadeIn()) {
772 states &= ~IconWidgetPrivate::HoverState;
776 void IconWidgetPrivate::drawBackground(QPainter *painter, IconWidgetState state)
782 if (!(states & IconWidgetPrivate::HoverState) && !(states & IconWidgetPrivate::PressedState)) {
786 if (state == IconWidgetPrivate::PressedState) {
787 background->setElementPrefix(
"selected");
789 background->setElementPrefix(
"hover");
792 if (qFuzzyCompare(hoverAnimation->value(), 1)) {
793 background->resizeFrame(currentSize);
794 background->paintFrame(painter);
795 }
else if (!qFuzzyCompare(hoverAnimation->value()+1, 1)) {
796 background->resizeFrame(currentSize);
797 QPixmap frame = background->framePixmap();
798 QPainter bufferPainter(&frame);
799 bufferPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
800 bufferPainter.fillRect(frame.rect(), QColor(0,0,0, 255*hoverAnimation->value()));
802 painter->drawPixmap(QPoint(0,0), frame);
806 QPixmap IconWidgetPrivate::decoration(
const QStyleOptionGraphicsItem *option,
bool useHoverEffect,
bool usePressedEffect)
810 QIcon::Mode mode = option->state & QStyle::State_Enabled ? QIcon::Normal : QIcon::Disabled;
811 QIcon::State state = option->state & QStyle::State_Open ? QIcon::On : QIcon::Off;
813 QSize finalSize(iconSize.toSize());
815 if (finalSize.width() < KIconLoader::SizeSmallMedium) {
816 finalSize = QSize(KIconLoader::SizeSmall, KIconLoader::SizeSmall);
817 }
else if (finalSize.width() < KIconLoader::SizeMedium) {
818 finalSize = QSize(KIconLoader::SizeSmallMedium, KIconLoader::SizeSmallMedium);
819 }
else if (finalSize.width() < KIconLoader::SizeLarge) {
820 finalSize = QSize(KIconLoader::SizeMedium, KIconLoader::SizeMedium);
824 if (iconSvgElementChanged || iconSvgPixmap.size() != iconSize.toSize()) {
828 iconSvg->resize(finalSize);
829 iconSvgPixmap = iconSvg->pixmap(iconSvgElement);
830 iconSvgElementChanged =
false;
832 result = iconSvgPixmap;
834 QSize size(iconSize.toSize());
836 if (!icon.availableSizes().isEmpty()) {
837 finalSize = icon.actualSize(iconSize.toSize(), mode, state);
840 result = icon.pixmap(finalSize, mode, state);
843 if (usePressedEffect) {
844 result = result.scaled(result.size() * 0.9,
Qt::KeepAspectRatio, Qt::SmoothTransformation);
847 if (!result.isNull() && useHoverEffect) {
848 KIconEffect *effect = KIconLoader::global()->iconEffect();
853 if (qFuzzyCompare(qreal(1.0), hoverAnimation->value())) {
859 KIconLoader::ActiveState), hoverAnimation->value());
862 }
else if (!result.isNull() && !oldIcon.isNull()) {
863 if (qFuzzyCompare(qreal(1.0), hoverAnimation->value())) {
867 oldIcon.pixmap(result.size(), mode, state),
868 result, hoverAnimation->value());
876 const QPixmap &pixmap)
const
878 const QRectF itemRect = subtractMargin(option->rect, IconWidgetPrivate::ItemMargin);
881 const QSizeF size = addMargin(iconSize, IconWidgetPrivate::IconMargin);
883 Qt::LayoutDirection direction = iconDirection(option);
886 Qt::Alignment alignment;
887 if (text.isEmpty() && infoText.isEmpty()) {
888 alignment = Qt::AlignCenter;
890 alignment = Qt::Alignment(Qt::AlignHCenter | Qt::AlignTop);
893 alignment = QStyle::visualAlignment(
894 direction, Qt::Alignment(Qt::AlignLeft | Qt::AlignVCenter));
897 const QRect iconRect =
898 QStyle::alignedRect(direction, alignment, size.toSize(), itemRect.toRect());
901 QRect pixmapRect = pixmap.rect();
902 pixmapRect.moveCenter(iconRect.center());
907 return QPointF(pixmapRect.topLeft());
912 const QString &
string)
const
920 const QSizeF decoSize = addMargin(iconSize, IconWidgetPrivate::IconMargin);
921 const QRectF itemRect = subtractMargin(option->rect, IconWidgetPrivate::ItemMargin);
922 QRectF textArea(QPointF(0, 0), itemRect.size());
925 textArea.setTop(decoSize.height() + 1);
928 textArea.setLeft(decoSize.width() + 1);
931 textArea.translate(itemRect.topLeft());
932 return QRectF(QStyle::visualRect(iconDirection(option), option->rect, textArea.toRect()));
936 QSizeF IconWidgetPrivate::layoutText(QTextLayout &layout,
938 const QSizeF &constraints)
const
940 const QSizeF size = layoutText(layout, text, constraints.width());
942 if (size.width() > constraints.width() || size.height() > constraints.height()) {
944 q->setToolTip(action->toolTip());
946 const QString elided = elidedText(layout, constraints);
947 return layoutText(layout, elided, constraints.width());
949 q->setToolTip(QString());
955 QSizeF IconWidgetPrivate::layoutText(QTextLayout &layout,
const QString &text, qreal maxWidth)
const
957 QFontMetricsF metrics(layout.font());
958 qreal leading = metrics.leading();
960 qreal widthUsed = 0.0;
963 layout.setText(text);
965 layout.beginLayout();
967 while ((line = layout.createLine()).isValid()) {
968 line.setLineWidth(maxWidth);
970 line.setPosition(QPointF(0.0, height));
971 height += line.height();
972 widthUsed = qMax(widthUsed, line.naturalTextWidth());
976 return QSizeF(widthUsed, height);
983 QString IconWidgetPrivate::elidedText(QTextLayout &layout,
const QSizeF &size)
const
985 QFontMetricsF metrics(layout.font());
986 const QString text = layout.text();
987 qreal maxWidth = size.width();
988 qreal maxHeight = size.height();
993 elided.reserve(text.length());
995 for (
int i = 0; i < layout.lineCount(); i++) {
996 QTextLine line = layout.lineAt(i);
997 int start = line.textStart();
998 int length = line.textLength();
1000 height += metrics.leading();
1001 if (height + line.height() + metrics.lineSpacing() > maxHeight) {
1005 if (line.naturalTextWidth() < maxWidth &&
1006 start + length > 0 &&
1007 text[start + length - 1] == QChar::LineSeparator) {
1008 elided += text.mid(start, length - 1);
1010 elided += metrics.elidedText(text.mid(start), Qt::ElideRight, maxWidth);
1013 }
else if (line.naturalTextWidth() > maxWidth) {
1014 elided += metrics.elidedText(text.mid(start, length), Qt::ElideRight, maxWidth);
1016 elided += text.mid(start, length);
1019 height += line.height();
1026 const QPixmap &icon, QTextLayout *labelLayout,
1027 QTextLayout *infoLayout, QRectF *textBoundingRect)
const
1029 bool showInformation =
false;
1031 setLayoutOptions(*labelLayout, option, q->orientation());
1033 QFontMetricsF fm(labelLayout->font());
1034 const QRectF textArea = labelRectangle(option, icon, text);
1035 QRectF textRect = subtractMargin(textArea, IconWidgetPrivate::TextMargin);
1039 QSizeF maxLabelSize = textRect.size();
1040 QSizeF maxInfoSize = textRect.size();
1046 if (!infoText.isEmpty() && textRect.height() >= fm.lineSpacing() * 2) {
1047 infoLayout->setFont(labelLayout->font());
1048 infoLayout->setTextOption(labelLayout->textOption());
1050 maxLabelSize.rheight() -= fm.lineSpacing();
1051 showInformation =
true;
1055 labelSize = layoutText(*labelLayout, text, maxLabelSize);
1056 maxInfoSize.rheight() -= labelSize.height();
1059 if (showInformation) {
1060 infoSize = layoutText(*infoLayout, infoText, maxInfoSize);
1062 infoSize = QSizeF(0, 0);
1065 const Qt::Alignment alignment = labelLayout->textOption().alignment();
1066 const QSizeF size(qMax(labelSize.width(), infoSize.width()),
1067 labelSize.height() + infoSize.height());
1069 QStyle::alignedRect(iconDirection(option), alignment, size.toSize(), textRect.toRect());
1073 labelLayout->setPosition(QPointF(textRect.x(), textBoundingRect->y()));
1075 for (
int i = 0; i < labelLayout->lineCount(); ++i) {
1076 line = labelLayout->lineAt(i);
1077 haloRects.append(line.naturalTextRect().translated(labelLayout->position().toPoint()).toRect());
1079 infoLayout->setPosition(QPointF(textRect.x(), textBoundingRect->y() + labelSize.height()));
1080 for (
int i = 0; i < infoLayout->lineCount(); ++i) {
1081 line = infoLayout->lineAt(i);
1082 haloRects.append(line.naturalTextRect().translated(infoLayout->position().toPoint()).toRect());
1089 const QPalette::ColorGroup group = option->state & QStyle::State_Enabled ?
1090 QPalette::Normal : QPalette::Disabled;
1093 if (option->state & QStyle::State_Selected) {
1094 return option->palette.brush(group, QPalette::HighlightedText);
1096 return option->palette.brush(group, QPalette::Text);
1101 const QPalette::ColorGroup group = option->state & QStyle::State_Enabled ?
1102 QPalette::Normal : QPalette::Disabled;
1104 QBrush background(Qt::NoBrush);
1107 if (option->state & QStyle::State_Selected) {
1108 background = option->palette.brush(group, QPalette::Highlight);
1113 void IconWidgetPrivate::drawTextItems(QPainter *painter,
1115 const QTextLayout &labelLayout,
1116 const QTextLayout &infoLayout)
const
1121 painter->setPen(textColor);
1125 painter->translate(0.5, 0.5);
1127 labelLayout.draw(painter, QPointF());
1129 if (!infoLayout.text().isEmpty()) {
1130 painter->setPen(textColor);
1131 infoLayout.draw(painter, QPointF());
1141 d->layoutIcons(option);
1145 IconWidgetPrivate::IconWidgetState state = IconWidgetPrivate::NoState;
1146 if (d->states & IconWidgetPrivate::ManualPressedState) {
1147 state = IconWidgetPrivate::PressedState;
1148 }
else if (d->states & IconWidgetPrivate::PressedState) {
1149 if (d->states & IconWidgetPrivate::HoverState) {
1150 state = IconWidgetPrivate::PressedState;
1152 }
else if (d->states & IconWidgetPrivate::HoverState) {
1153 state = IconWidgetPrivate::HoverState;
1156 QPixmap icon = d->decoration(option, state != IconWidgetPrivate::NoState, state & IconWidgetPrivate::PressedState);
1157 const QPointF iconPos = d->iconPosition(option, icon);
1159 d->drawBackground(painter, state);
1162 if (!icon.isNull()) {
1163 painter->drawPixmap(iconPos, icon);
1167 foreach (
const IconAction *action, d->cornerActions) {
1168 if (action->isAnimating()) {
1169 action->paint(painter);
1174 QTextLayout labelLayout, infoLayout;
1175 QRectF textBoundingRect;
1177 d->layoutTextItems(option, icon, &labelLayout, &infoLayout, &textBoundingRect);
1179 if (d->textBgColor != QColor() && d->textBgColor.alpha() > 0 &&
1180 !(d->text.isEmpty() && d->infoText.isEmpty()) &&
1181 !textBoundingRect.isEmpty() &&
1182 !qFuzzyCompare(d->hoverAnimation->value(), (qreal)1.0)) {
1183 QRectF rect = textBoundingRect.adjusted(-2, -2, 4, 4).toAlignedRect();
1184 painter->setPen(Qt::transparent);
1185 QColor color = d->textBgColor;
1186 color.setAlpha(60 * (1.0 - d->hoverAnimation->value()));
1187 QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());
1188 gradient.setColorAt(0, color.lighter(120));
1189 gradient.setColorAt(1, color.darker(120));
1190 painter->setBrush(gradient);
1191 gradient.setColorAt(0, color.lighter(130));
1192 gradient.setColorAt(1, color.darker(130));
1193 painter->setPen(QPen(gradient, 0));
1194 painter->setRenderHint(QPainter::Antialiasing);
1201 if (d->shadowColor.value() < 128) {
1202 shadowPos = QPoint(1, 2);
1204 shadowPos = QPoint(0, 0);
1207 QImage shadow(textBoundingRect.size().toSize() + QSize(4, 4),
1208 QImage::Format_ARGB32_Premultiplied);
1209 shadow.fill(Qt::transparent);
1211 QPainter buffPainter(&shadow);
1212 buffPainter.translate(-textBoundingRect.x(), -textBoundingRect.y());
1213 d->drawTextItems(&buffPainter, option, labelLayout, infoLayout);
1217 painter->drawImage(textBoundingRect.topLeft() + shadowPos, shadow);
1218 }
else if (!(d->text.isEmpty() && d->infoText.isEmpty()) &&
1219 !textBoundingRect.isEmpty()) {
1220 QRect labelRect = d->labelRectangle(option, icon, d->text).toRect();
1222 foreach (
const QRect &rect, d->haloRects) {
1227 d->drawTextItems(painter, option, labelLayout, infoLayout);
1232 d->textBgCustomized =
true;
1233 d->textBgColor = color;
1239 return d->textBgColor;
1244 qreal radius = size.width() / 2;
1245 QRadialGradient gradient(radius, radius, radius, radius, radius);
1248 if (element == IconWidgetPrivate::MinibuttonPressed) {
1250 }
else if (element == IconWidgetPrivate::MinibuttonHover) {
1255 gradient.setColorAt(0, QColor::fromRgb(d->textColor.red(),
1256 d->textColor.green(),
1257 d->textColor.blue(), alpha));
1258 gradient.setColorAt(1, QColor::fromRgb(d->textColor.red(),
1259 d->textColor.green(),
1260 d->textColor.blue(), 0));
1262 painter->setBrush(gradient);
1263 painter->setPen(Qt::NoPen);
1264 painter->drawEllipse(QRectF(QPointF(.0, .0), size));
1269 d->text = KGlobal::locale()->removeAcceleratorMarker(text);
1271 d->currentSize = QSizeF(-1, -1);
1275 d->layoutIcons(&styleoption);
1278 if (!parentWidget() || !parentWidget()->layout()) {
1279 resize(preferredSize());
1292 d->currentSize = QSizeF(-1, -1);
1296 d->layoutIcons(&styleoption);
1299 if (!parentWidget() || !parentWidget()->layout()) {
1300 resize(preferredSize());
1316 if (icon.isEmpty()) {
1332 if (!(d->states & IconWidgetPrivate::HoverState) && !d->iconChangeTimer->isActive() && d->oldIcon.isNull() && !d->icon.isNull() && !icon.isNull()) {
1333 d->oldIcon = d->icon;
1334 d->animateMainIcon(
true, d->states);
1336 d->oldIcon = QIcon();
1338 d->iconChangeTimer->start(300);
1350 d->preferredIconSize = size;
1356 return d->preferredIconSize;
1361 d->minimumIconSize = size;
1367 return d->minimumIconSize;
1372 d->maximumIconSize = size;
1378 return d->maximumIconSize;
1383 return d->states & IconWidgetPrivate::PressedState;
1388 if (event->button() != Qt::LeftButton) {
1389 QGraphicsWidget::mousePressEvent(event);
1393 if (KGlobalSettings::singleClick() || (receivers(SIGNAL(
clicked()))) > 0) {
1394 d->states |= IconWidgetPrivate::PressedState;
1396 d->clickStartPos = scenePos();
1398 bool handled =
false;
1399 foreach (IconAction *action, d->cornerActions) {
1400 handled = action->event(event->type(),
event->pos());
1406 if (!handled && boundingRect().contains(event->pos())) {
1415 if (~d->states & IconWidgetPrivate::PressedState) {
1416 QGraphicsWidget::mouseMoveEvent(event);
1420 if (boundingRect().contains(event->pos())) {
1421 if (~d->states & IconWidgetPrivate::HoverState) {
1422 d->states |= IconWidgetPrivate::HoverState;
1426 if (d->states & IconWidgetPrivate::HoverState) {
1435 if (~d->states & IconWidgetPrivate::PressedState) {
1436 QGraphicsWidget::mouseMoveEvent(event);
1443 bool handled = d->clickStartPos != scenePos();
1445 foreach (IconAction *action, d->cornerActions) {
1446 if (action->event(event->type(),
event->pos())) {
1454 if (boundingRect().contains(event->pos())) {
1456 if (KGlobalSettings::singleClick()) {
1460 if (d->action && d->action->menu()) {
1461 d->action->menu()->popup(event->screenPos());
1474 d->states |= IconWidgetPrivate::PressedState;
1477 if (!KGlobalSettings::singleClick()) {
1487 foreach (IconAction *action, d->cornerActions) {
1489 action->event(event->type(),
event->pos());
1492 d->oldIcon = QIcon();
1493 d->animateMainIcon(
true, d->states|IconWidgetPrivate::HoverState);
1495 QGraphicsWidget::hoverEnterEvent(event);
1501 foreach (IconAction *action, d->cornerActions) {
1503 action->event(event->type(),
event->pos());
1509 d->animateMainIcon(
false, d->states|IconWidgetPrivate::HoverState);
1511 QGraphicsWidget::hoverLeaveEvent(event);
1518 if (event->type() == QEvent::GraphicsSceneDragEnter) {
1519 d->animateMainIcon(
true, d->states|IconWidgetPrivate::HoverState);
1520 }
else if (event->type() == QEvent::GraphicsSceneDragLeave) {
1521 d->animateMainIcon(
false, d->states|IconWidgetPrivate::HoverState);
1530 d->states |= IconWidgetPrivate::ManualPressedState;
1531 d->states |= IconWidgetPrivate::PressedState;
1544 void IconWidgetPrivate::svgChanged()
1546 iconSvgElementChanged =
true;
1558 return d->orientation;
1563 d->invertLayout = invert;
1568 return d->invertLayout;
1573 d->setActiveMargins();
1574 if (d->text.isEmpty() && d->infoText.isEmpty()) {
1576 return d->addMargin(QSizeF(iconWidth, iconWidth), IconWidgetPrivate::ItemMargin);
1579 QFontMetricsF fm(font());
1583 width = qMax(d->maxWordWidth(d->text),
1584 d->maxWordWidth(d->infoText)) +
1586 d->verticalMargin[IconWidgetPrivate::TextMargin].left +
1587 d->verticalMargin[IconWidgetPrivate::TextMargin].right;
1591 d->verticalMargin[IconWidgetPrivate::IconMargin].left +
1592 d->verticalMargin[IconWidgetPrivate::IconMargin].right);
1595 d->horizontalMargin[IconWidgetPrivate::IconMargin].left +
1596 d->horizontalMargin[IconWidgetPrivate::IconMargin].right +
1597 qMax(fm.width(d->text), fm.width(d->infoText)) + fm.width(
"xxx") +
1598 d->horizontalMargin[IconWidgetPrivate::TextMargin].left +
1599 d->horizontalMargin[IconWidgetPrivate::TextMargin].right;
1606 option.state = QStyle::State_None;
1607 option.rect = QRect(0, 0, width, QWIDGETSIZE_MAX);
1608 textHeight = d->displaySizeHint(&option, width).height();
1611 height = iconWidth + textHeight +
1612 d->verticalMargin[IconWidgetPrivate::TextMargin].top +
1613 d->verticalMargin[IconWidgetPrivate::TextMargin].bottom +
1614 d->verticalMargin[IconWidgetPrivate::IconMargin].top +
1615 d->verticalMargin[IconWidgetPrivate::IconMargin].bottom;
1618 height = qMax(iconWidth +
1619 d->verticalMargin[IconWidgetPrivate::IconMargin].top +
1620 d->verticalMargin[IconWidgetPrivate::IconMargin].bottom,
1622 d->verticalMargin[IconWidgetPrivate::TextMargin].top +
1623 d->verticalMargin[IconWidgetPrivate::TextMargin].bottom);
1626 return d->addMargin(QSizeF(width, height), IconWidgetPrivate::ItemMargin);
1631 d->changeEvent(event);
1632 QGraphicsWidget::changeEvent(event);
1637 #include "iconwidget.moc"
1638 #include "iconwidget_p.moc"
The applet is constrained horizontally, but can expand vertically.
On the planar desktop layer, extending across the full screen from edge to edge.
the text color to be used by items resting on the background
void drawHalo(QPainter *painter, const QRectF &rect)
Provides an SVG with borders.
QScriptValue animation(const QString &anim)
QPainterPath roundedRectangle(const QRectF &rect, qreal radius)
Returns a nicely rounded rectanglular path for painting.
The applet keeps a fixed aspect ratio.
void shadowBlur(QImage &image, int radius, const QColor &color)
Creates a blurred shadow of the supplied image.
static QScriptValue type(QScriptContext *ctx, QScriptEngine *eng)
static Theme * defaultTheme()
Singleton pattern accessor.
static Plasma::Animation * create(Animator::Animation type, QObject *parent=0)
Factory to build new animation objects.
QPixmap transition(const QPixmap &from, const QPixmap &to, qreal amount)
Blends a pixmap into another.
Q_INVOKABLE QColor color(ColorRole role) const
Returns the text color to be used by items resting on the background.
A theme aware image-centric SVG class.