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) {
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()));
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()));
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;
814 if (iconSvgElementChanged || iconSvgPixmap.size() != iconSize.toSize()) {
815 iconSvg->resize(iconSize);
816 iconSvgPixmap = iconSvg->pixmap(iconSvgElement);
817 iconSvgElementChanged =
false;
819 result = iconSvgPixmap;
821 const QSize size = icon.actualSize(iconSize.toSize(), mode, state);
822 result = icon.pixmap(size, mode, state);
825 if (usePressedEffect) {
826 result = result.scaled(result.size() * 0.9,
Qt::KeepAspectRatio, Qt::SmoothTransformation);
829 if (!result.isNull() && useHoverEffect) {
830 KIconEffect *effect = KIconLoader::global()->iconEffect();
835 if (qFuzzyCompare(qreal(1.0), hoverAnimation->value())) {
841 KIconLoader::ActiveState), hoverAnimation->value());
844 }
else if (!result.isNull() && !oldIcon.isNull()) {
845 if (qFuzzyCompare(qreal(1.0), hoverAnimation->value())) {
849 oldIcon.pixmap(result.size(), mode, state),
850 result, hoverAnimation->value());
858 const QPixmap &pixmap)
const
860 const QRectF itemRect = subtractMargin(option->rect, IconWidgetPrivate::ItemMargin);
863 const QSizeF size = addMargin(iconSize, IconWidgetPrivate::IconMargin);
865 Qt::LayoutDirection direction = iconDirection(option);
868 Qt::Alignment alignment;
869 if (text.isEmpty() && infoText.isEmpty()) {
870 alignment = Qt::AlignCenter;
872 alignment = Qt::Alignment(Qt::AlignHCenter | Qt::AlignTop);
875 alignment = QStyle::visualAlignment(
876 direction, Qt::Alignment(Qt::AlignLeft | Qt::AlignVCenter));
879 const QRect iconRect =
880 QStyle::alignedRect(direction, alignment, size.toSize(), itemRect.toRect());
883 QRect pixmapRect = pixmap.rect();
884 pixmapRect.moveCenter(iconRect.center());
889 return QPointF(pixmapRect.topLeft());
894 const QString &
string)
const
902 const QSizeF decoSize = addMargin(iconSize, IconWidgetPrivate::IconMargin);
903 const QRectF itemRect = subtractMargin(option->rect, IconWidgetPrivate::ItemMargin);
904 QRectF textArea(QPointF(0, 0), itemRect.size());
907 textArea.setTop(decoSize.height() + 1);
910 textArea.setLeft(decoSize.width() + 1);
913 textArea.translate(itemRect.topLeft());
914 return QRectF(QStyle::visualRect(iconDirection(option), option->rect, textArea.toRect()));
918 QSizeF IconWidgetPrivate::layoutText(QTextLayout &layout,
920 const QSizeF &constraints)
const
922 const QSizeF size = layoutText(layout, text, constraints.width());
924 if (size.width() > constraints.width() || size.height() > constraints.height()) {
926 q->setToolTip(action->toolTip());
928 const QString elided = elidedText(layout, constraints);
929 return layoutText(layout, elided, constraints.width());
931 q->setToolTip(QString());
937 QSizeF IconWidgetPrivate::layoutText(QTextLayout &layout,
const QString &text, qreal maxWidth)
const
939 QFontMetricsF metrics(layout.font());
940 qreal leading = metrics.leading();
942 qreal widthUsed = 0.0;
945 layout.setText(text);
947 layout.beginLayout();
949 while ((line = layout.createLine()).isValid()) {
950 line.setLineWidth(maxWidth);
952 line.setPosition(QPointF(0.0, height));
953 height += line.height();
954 widthUsed = qMax(widthUsed, line.naturalTextWidth());
958 return QSizeF(widthUsed, height);
965 QString IconWidgetPrivate::elidedText(QTextLayout &layout,
const QSizeF &size)
const
967 QFontMetricsF metrics(layout.font());
968 const QString text = layout.text();
969 qreal maxWidth = size.width();
970 qreal maxHeight = size.height();
975 elided.reserve(text.length());
977 for (
int i = 0; i < layout.lineCount(); i++) {
978 QTextLine line = layout.lineAt(i);
979 int start = line.textStart();
980 int length = line.textLength();
982 height += metrics.leading();
983 if (height + line.height() + metrics.lineSpacing() > maxHeight) {
987 if (line.naturalTextWidth() < maxWidth &&
988 start + length > 0 &&
989 text[start + length - 1] == QChar::LineSeparator) {
990 elided += text.mid(start, length - 1);
992 elided += metrics.elidedText(text.mid(start), Qt::ElideRight, maxWidth);
995 }
else if (line.naturalTextWidth() > maxWidth) {
996 elided += metrics.elidedText(text.mid(start, length), Qt::ElideRight, maxWidth);
998 elided += text.mid(start, length);
1001 height += line.height();
1008 const QPixmap &icon, QTextLayout *labelLayout,
1009 QTextLayout *infoLayout, QRectF *textBoundingRect)
const
1011 bool showInformation =
false;
1013 setLayoutOptions(*labelLayout, option, q->orientation());
1015 QFontMetricsF fm(labelLayout->font());
1016 const QRectF textArea = labelRectangle(option, icon, text);
1017 QRectF textRect = subtractMargin(textArea, IconWidgetPrivate::TextMargin);
1021 QSizeF maxLabelSize = textRect.size();
1022 QSizeF maxInfoSize = textRect.size();
1028 if (!infoText.isEmpty() && textRect.height() >= fm.lineSpacing() * 2) {
1029 infoLayout->setFont(labelLayout->font());
1030 infoLayout->setTextOption(labelLayout->textOption());
1032 maxLabelSize.rheight() -= fm.lineSpacing();
1033 showInformation =
true;
1037 labelSize = layoutText(*labelLayout, text, maxLabelSize);
1038 maxInfoSize.rheight() -= labelSize.height();
1041 if (showInformation) {
1042 infoSize = layoutText(*infoLayout, infoText, maxInfoSize);
1044 infoSize = QSizeF(0, 0);
1047 const Qt::Alignment alignment = labelLayout->textOption().alignment();
1048 const QSizeF size(qMax(labelSize.width(), infoSize.width()),
1049 labelSize.height() + infoSize.height());
1051 QStyle::alignedRect(iconDirection(option), alignment, size.toSize(), textRect.toRect());
1055 labelLayout->setPosition(QPointF(textRect.x(), textBoundingRect->y()));
1057 for (
int i = 0; i < labelLayout->lineCount(); ++i) {
1058 line = labelLayout->lineAt(i);
1059 haloRects.append(line.naturalTextRect().translated(labelLayout->position().toPoint()).toRect());
1061 infoLayout->setPosition(QPointF(textRect.x(), textBoundingRect->y() + labelSize.height()));
1062 for (
int i = 0; i < infoLayout->lineCount(); ++i) {
1063 line = infoLayout->lineAt(i);
1064 haloRects.append(line.naturalTextRect().translated(infoLayout->position().toPoint()).toRect());
1071 const QPalette::ColorGroup group = option->state & QStyle::State_Enabled ?
1072 QPalette::Normal : QPalette::Disabled;
1075 if (option->state & QStyle::State_Selected) {
1076 return option->palette.brush(group, QPalette::HighlightedText);
1078 return option->palette.brush(group, QPalette::Text);
1083 const QPalette::ColorGroup group = option->state & QStyle::State_Enabled ?
1084 QPalette::Normal : QPalette::Disabled;
1086 QBrush background(Qt::NoBrush);
1089 if (option->state & QStyle::State_Selected) {
1090 background = option->palette.brush(group, QPalette::Highlight);
1095 void IconWidgetPrivate::drawTextItems(QPainter *painter,
1097 const QTextLayout &labelLayout,
1098 const QTextLayout &infoLayout)
const
1103 painter->setPen(textColor);
1107 painter->translate(0.5, 0.5);
1109 labelLayout.draw(painter, QPointF());
1111 if (!infoLayout.text().isEmpty()) {
1112 painter->setPen(textColor);
1113 infoLayout.draw(painter, QPointF());
1123 d->layoutIcons(option);
1127 IconWidgetPrivate::IconWidgetState state = IconWidgetPrivate::NoState;
1128 if (d->states & IconWidgetPrivate::ManualPressedState) {
1129 state = IconWidgetPrivate::PressedState;
1130 }
else if (d->states & IconWidgetPrivate::PressedState) {
1131 if (d->states & IconWidgetPrivate::HoverState) {
1132 state = IconWidgetPrivate::PressedState;
1134 }
else if (d->states & IconWidgetPrivate::HoverState) {
1135 state = IconWidgetPrivate::HoverState;
1138 QPixmap icon = d->decoration(option, state != IconWidgetPrivate::NoState, state & IconWidgetPrivate::PressedState);
1139 const QPointF iconPos = d->iconPosition(option, icon);
1141 d->drawBackground(painter, state);
1144 if (!icon.isNull()) {
1145 painter->drawPixmap(iconPos, icon);
1149 foreach (
const IconAction *action, d->cornerActions) {
1150 if (action->isAnimating()) {
1151 action->paint(painter);
1156 QTextLayout labelLayout, infoLayout;
1157 QRectF textBoundingRect;
1159 d->layoutTextItems(option, icon, &labelLayout, &infoLayout, &textBoundingRect);
1161 if (d->textBgColor != QColor() && d->textBgColor.alpha() > 0 &&
1162 !(d->text.isEmpty() && d->infoText.isEmpty()) &&
1163 !textBoundingRect.isEmpty() &&
1164 !qFuzzyCompare(d->hoverAnimation->value(), (qreal)1.0)) {
1165 QRectF rect = textBoundingRect.adjusted(-2, -2, 4, 4).toAlignedRect();
1166 painter->setPen(Qt::transparent);
1167 QColor color = d->textBgColor;
1168 color.setAlpha(60 * (1.0 - d->hoverAnimation->value()));
1169 QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());
1170 gradient.setColorAt(0, color.lighter(120));
1171 gradient.setColorAt(1, color.darker(120));
1172 painter->setBrush(gradient);
1173 gradient.setColorAt(0, color.lighter(130));
1174 gradient.setColorAt(1, color.darker(130));
1175 painter->setPen(QPen(gradient, 0));
1176 painter->setRenderHint(QPainter::Antialiasing);
1183 if (d->shadowColor.value() < 128) {
1184 shadowPos = QPoint(1, 2);
1186 shadowPos = QPoint(0, 0);
1189 QImage shadow(textBoundingRect.size().toSize() + QSize(4, 4),
1190 QImage::Format_ARGB32_Premultiplied);
1191 shadow.fill(Qt::transparent);
1193 QPainter buffPainter(&shadow);
1194 buffPainter.translate(-textBoundingRect.x(), -textBoundingRect.y());
1195 d->drawTextItems(&buffPainter, option, labelLayout, infoLayout);
1199 painter->drawImage(textBoundingRect.topLeft() + shadowPos, shadow);
1200 }
else if (!(d->text.isEmpty() && d->infoText.isEmpty()) &&
1201 !textBoundingRect.isEmpty()) {
1202 QRect labelRect = d->labelRectangle(option, icon, d->text).toRect();
1204 foreach (
const QRect &rect, d->haloRects) {
1209 d->drawTextItems(painter, option, labelLayout, infoLayout);
1214 d->textBgCustomized =
true;
1215 d->textBgColor = color;
1221 return d->textBgColor;
1226 qreal radius = size.width() / 2;
1227 QRadialGradient gradient(radius, radius, radius, radius, radius);
1230 if (element == IconWidgetPrivate::MinibuttonPressed) {
1232 }
else if (element == IconWidgetPrivate::MinibuttonHover) {
1237 gradient.setColorAt(0, QColor::fromRgb(d->textColor.red(),
1238 d->textColor.green(),
1239 d->textColor.blue(), alpha));
1240 gradient.setColorAt(1, QColor::fromRgb(d->textColor.red(),
1241 d->textColor.green(),
1242 d->textColor.blue(), 0));
1244 painter->setBrush(gradient);
1245 painter->setPen(Qt::NoPen);
1246 painter->drawEllipse(QRectF(QPointF(.0, .0), size));
1251 d->text = KGlobal::locale()->removeAcceleratorMarker(text);
1253 d->currentSize = QSizeF(-1, -1);
1257 d->layoutIcons(&styleoption);
1260 if (!parentWidget() || !parentWidget()->layout()) {
1261 resize(preferredSize());
1274 d->currentSize = QSizeF(-1, -1);
1278 d->layoutIcons(&styleoption);
1281 if (!parentWidget() || !parentWidget()->layout()) {
1282 resize(preferredSize());
1298 if (icon.isEmpty()) {
1314 if (!(d->states & IconWidgetPrivate::HoverState) && !d->iconChangeTimer->isActive() && d->oldIcon.isNull() && !d->icon.isNull() && !icon.isNull()) {
1315 d->oldIcon = d->icon;
1316 d->animateMainIcon(
true, d->states);
1318 d->oldIcon = QIcon();
1320 d->iconChangeTimer->start(300);
1332 d->preferredIconSize = size;
1338 return d->preferredIconSize;
1343 d->minimumIconSize = size;
1349 return d->minimumIconSize;
1354 d->maximumIconSize = size;
1360 return d->maximumIconSize;
1365 return d->states & IconWidgetPrivate::PressedState;
1370 if (event->button() != Qt::LeftButton) {
1375 if (KGlobalSettings::singleClick() || (receivers(SIGNAL(
clicked()))) > 0) {
1376 d->states |= IconWidgetPrivate::PressedState;
1378 d->clickStartPos = scenePos();
1380 bool handled =
false;
1381 foreach (IconAction *action, d->cornerActions) {
1382 handled = action->event(event->type(),
event->pos());
1388 if (!handled && boundingRect().contains(event->pos())) {
1397 if (~d->states & IconWidgetPrivate::PressedState) {
1402 if (boundingRect().contains(event->pos())) {
1403 if (~d->states & IconWidgetPrivate::HoverState) {
1404 d->states |= IconWidgetPrivate::HoverState;
1408 if (d->states & IconWidgetPrivate::HoverState) {
1417 if (~d->states & IconWidgetPrivate::PressedState) {
1425 bool handled = d->clickStartPos != scenePos();
1427 foreach (IconAction *action, d->cornerActions) {
1428 if (action->event(event->type(),
event->pos())) {
1436 if (boundingRect().contains(event->pos())) {
1438 if (KGlobalSettings::singleClick()) {
1442 if (d->action && d->action->menu()) {
1443 d->action->menu()->popup(event->screenPos());
1456 d->states |= IconWidgetPrivate::PressedState;
1459 if (!KGlobalSettings::singleClick()) {
1469 foreach (IconAction *action, d->cornerActions) {
1471 action->event(event->type(),
event->pos());
1474 d->oldIcon = QIcon();
1475 d->animateMainIcon(
true, d->states|IconWidgetPrivate::HoverState);
1483 foreach (IconAction *action, d->cornerActions) {
1485 action->event(event->type(),
event->pos());
1491 d->animateMainIcon(
false, d->states|IconWidgetPrivate::HoverState);
1500 if (event->type() == QEvent::GraphicsSceneDragEnter) {
1501 d->animateMainIcon(
true, d->states|IconWidgetPrivate::HoverState);
1502 }
else if (event->type() == QEvent::GraphicsSceneDragLeave) {
1503 d->animateMainIcon(
false, d->states|IconWidgetPrivate::HoverState);
1512 d->states |= IconWidgetPrivate::ManualPressedState;
1513 d->states |= IconWidgetPrivate::PressedState;
1526 void IconWidgetPrivate::svgChanged()
1528 iconSvgElementChanged =
true;
1540 return d->orientation;
1545 d->invertLayout = invert;
1550 return d->invertLayout;
1555 d->setActiveMargins();
1556 if (d->text.isEmpty() && d->infoText.isEmpty()) {
1558 return d->addMargin(QSizeF(iconWidth, iconWidth), IconWidgetPrivate::ItemMargin);
1561 QFontMetricsF fm(font());
1565 width = qMax(d->maxWordWidth(d->text),
1566 d->maxWordWidth(d->infoText)) +
1568 d->verticalMargin[IconWidgetPrivate::TextMargin].left +
1569 d->verticalMargin[IconWidgetPrivate::TextMargin].right;
1573 d->verticalMargin[IconWidgetPrivate::IconMargin].left +
1574 d->verticalMargin[IconWidgetPrivate::IconMargin].right);
1577 d->horizontalMargin[IconWidgetPrivate::IconMargin].left +
1578 d->horizontalMargin[IconWidgetPrivate::IconMargin].right +
1579 qMax(fm.width(d->text), fm.width(d->infoText)) + fm.width(
"xxx") +
1580 d->horizontalMargin[IconWidgetPrivate::TextMargin].left +
1581 d->horizontalMargin[IconWidgetPrivate::TextMargin].right;
1588 option.state = QStyle::State_None;
1589 option.rect = QRect(0, 0, width, QWIDGETSIZE_MAX);
1590 textHeight = d->displaySizeHint(&option, width).height();
1593 height = iconWidth + textHeight +
1594 d->verticalMargin[IconWidgetPrivate::TextMargin].top +
1595 d->verticalMargin[IconWidgetPrivate::TextMargin].bottom +
1596 d->verticalMargin[IconWidgetPrivate::IconMargin].top +
1597 d->verticalMargin[IconWidgetPrivate::IconMargin].bottom;
1600 height = qMax(iconWidth +
1601 d->verticalMargin[IconWidgetPrivate::IconMargin].top +
1602 d->verticalMargin[IconWidgetPrivate::IconMargin].bottom,
1604 d->verticalMargin[IconWidgetPrivate::TextMargin].top +
1605 d->verticalMargin[IconWidgetPrivate::TextMargin].bottom);
1608 return d->addMargin(QSizeF(width, height), IconWidgetPrivate::ItemMargin);
1613 d->changeEvent(event);
1619 #include "iconwidget.moc"
1620 #include "iconwidget_p.moc"