Cleaned up Plasma::Icon a whole lot, added Fredrik's text drawing code from KFileItemDelegate so we actually draw text correctly.
svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=696698
This commit is contained in:
parent
f33c5ab58b
commit
388d1ca167
576
widgets/icon.cpp
576
widgets/icon.cpp
@ -2,6 +2,7 @@
|
|||||||
* Copyright (C) 2007 by Aaron Seigo <aseigo@kde.org>
|
* Copyright (C) 2007 by Aaron Seigo <aseigo@kde.org>
|
||||||
* Copyright (C) 2007 by Riccardo Iaconelli <riccardo@kde.org>
|
* Copyright (C) 2007 by Riccardo Iaconelli <riccardo@kde.org>
|
||||||
* Copyright (C) 2007 by Matt Broadstone <mbroadst@gmail.com>
|
* Copyright (C) 2007 by Matt Broadstone <mbroadst@gmail.com>
|
||||||
|
* Copyright (C) 2006-2007 Fredrik Höglund <fredrik@kde.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Library General Public License version 2 as
|
* it under the terms of the GNU Library General Public License version 2 as
|
||||||
@ -19,12 +20,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "icon.h"
|
#include "icon.h"
|
||||||
|
#include "icon_p.h"
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QGraphicsSceneMouseEvent>
|
#include <QGraphicsSceneMouseEvent>
|
||||||
#include <QGraphicsView>
|
#include <QGraphicsView>
|
||||||
|
#include <QStyleOptionGraphicsItem>
|
||||||
|
#include <QTextLayout>
|
||||||
|
|
||||||
//#define BACKINGSTORE_BLUR_HACK
|
//#define BACKINGSTORE_BLUR_HACK
|
||||||
|
|
||||||
@ -34,6 +38,9 @@
|
|||||||
|
|
||||||
#include <KIcon>
|
#include <KIcon>
|
||||||
#include <KImageEffect>
|
#include <KImageEffect>
|
||||||
|
#include <KIconEffect>
|
||||||
|
#include <KIconLoader>
|
||||||
|
#include <K3Icon>
|
||||||
#include <KUrl>
|
#include <KUrl>
|
||||||
#include <KRun>
|
#include <KRun>
|
||||||
#include <KMimeType>
|
#include <KMimeType>
|
||||||
@ -46,151 +53,67 @@
|
|||||||
namespace Plasma
|
namespace Plasma
|
||||||
{
|
{
|
||||||
|
|
||||||
class PLASMA_EXPORT IconAction
|
Icon::Private::Private()
|
||||||
|
: svg("widgets/iconbutton"),
|
||||||
|
svgElements(0),
|
||||||
|
size(128*1.1, 128*1.1),
|
||||||
|
iconSize(128, 128),
|
||||||
|
state(Private::NoState),
|
||||||
|
orientation(Qt::Vertical),
|
||||||
|
calculateSizeRequested(true) // First time always true
|
||||||
{
|
{
|
||||||
public:
|
svg.setContentType(Plasma::Svg::ImageSet);
|
||||||
IconAction(Icon* icon, QAction* action);
|
svg.resize(size);
|
||||||
|
|
||||||
void show();
|
//TODO: recheck when svg changes
|
||||||
void hide();
|
checkSvgElements();
|
||||||
bool isVisible() const;
|
}
|
||||||
|
|
||||||
Phase::AnimId animationId() const;
|
Icon::Private::~Private()
|
||||||
QAction* action() const;
|
|
||||||
|
|
||||||
void paint(QPainter *painter) const;
|
|
||||||
bool event(QEvent::Type type, const QPointF &pos);
|
|
||||||
|
|
||||||
void setSelected(bool selected);
|
|
||||||
bool isSelected() const;
|
|
||||||
|
|
||||||
bool isHovered() const;
|
|
||||||
bool isPressed() const;
|
|
||||||
|
|
||||||
void setRect(const QRectF &rect);
|
|
||||||
QRectF rect() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void rebuildPixmap();
|
|
||||||
|
|
||||||
Icon* m_icon;
|
|
||||||
QAction* m_action;
|
|
||||||
QPixmap m_pixmap;
|
|
||||||
QRectF m_rect;
|
|
||||||
|
|
||||||
bool m_hovered;
|
|
||||||
bool m_pressed;
|
|
||||||
bool m_selected;
|
|
||||||
bool m_visible;
|
|
||||||
|
|
||||||
Phase::AnimId m_animationId;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Icon::Private
|
|
||||||
{
|
{
|
||||||
public:
|
qDeleteAll(cornerActions);
|
||||||
Private()
|
}
|
||||||
: svg("widgets/iconbutton"),
|
|
||||||
svgElements(0),
|
|
||||||
size(128*1.1, 128*1.1),
|
|
||||||
iconSize(128, 128),
|
|
||||||
state(Private::NoState)
|
|
||||||
{
|
|
||||||
svg.setContentType(Plasma::Svg::ImageSet);
|
|
||||||
svg.resize(size);
|
|
||||||
|
|
||||||
//TODO: recheck when svg changes
|
void Icon::Private::checkSvgElements()
|
||||||
checkSvgElements();
|
{
|
||||||
}
|
if (svg.elementExists("background")) {
|
||||||
|
svgElements |= SvgBackground;
|
||||||
|
}
|
||||||
|
|
||||||
~Private()
|
if (svg.elementExists("background-hover")) {
|
||||||
{
|
svgElements |= SvgBackgroundHover;
|
||||||
qDeleteAll(cornerActions);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void drawBackground(QPainter *painter);
|
if (svg.elementExists("background-pressed")) {
|
||||||
void drawForeground(QPainter *painter);
|
svgElements |= SvgBackgroundPressed;
|
||||||
void drawIcon(QPainter *painter);
|
}
|
||||||
void drawText(QPainter *painter);
|
|
||||||
|
|
||||||
void checkSvgElements()
|
if (svg.elementExists("foreground")) {
|
||||||
{
|
svgElements |= SvgForeground;
|
||||||
if (svg.elementExists("background")) {
|
}
|
||||||
svgElements |= SvgBackground;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (svg.elementExists("background-hover")) {
|
if (svg.elementExists("foreground-hover")) {
|
||||||
svgElements |= SvgBackgroundHover;
|
svgElements |= SvgForegroundHover;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (svg.elementExists("background-pressed")) {
|
if (svg.elementExists("foreground-pressed")) {
|
||||||
svgElements |= SvgBackgroundPressed;
|
svgElements |= SvgForegroundPressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (svg.elementExists("foreground")) {
|
if (svg.elementExists("minibutton")) {
|
||||||
svgElements |= SvgForeground;
|
svgElements |= SvgMinibutton;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (svg.elementExists("foreground-hover")) {
|
if (svg.elementExists("minibutton-hover")) {
|
||||||
svgElements |= SvgForegroundHover;
|
svgElements |= SvgMinibuttonHover;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (svg.elementExists("foreground-pressed")) {
|
if (svg.elementExists("minibutton-pressed")) {
|
||||||
svgElements |= SvgForegroundPressed;
|
svgElements |= SvgMinibuttonPressed;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (svg.elementExists("minibutton")) {
|
|
||||||
svgElements |= SvgMinibutton;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (svg.elementExists("minibutton-hover")) {
|
|
||||||
svgElements |= SvgMinibuttonHover;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (svg.elementExists("minibutton-pressed")) {
|
|
||||||
svgElements |= SvgMinibuttonPressed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum {
|
|
||||||
NoSvg = 0,
|
|
||||||
SvgBackground = 1,
|
|
||||||
SvgBackgroundHover = 2,
|
|
||||||
SvgBackgroundPressed = 4,
|
|
||||||
SvgForeground = 8,
|
|
||||||
SvgForegroundHover = 16,
|
|
||||||
SvgForegroundPressed = 32,
|
|
||||||
SvgMinibutton = 64,
|
|
||||||
SvgMinibuttonHover = 128,
|
|
||||||
SvgMinibuttonPressed = 256
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ActionPosition {
|
|
||||||
TopLeft = 0,
|
|
||||||
TopRight,
|
|
||||||
BottomLeft,
|
|
||||||
BottomRight,
|
|
||||||
LastIconPosition
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ButtonState
|
|
||||||
{
|
|
||||||
NoState,
|
|
||||||
HoverState,
|
|
||||||
PressedState
|
|
||||||
};
|
|
||||||
|
|
||||||
QString text;
|
|
||||||
QString infoText;
|
|
||||||
Svg svg;
|
|
||||||
int svgElements;
|
|
||||||
QSizeF size;
|
|
||||||
QSizeF iconSize;
|
|
||||||
QIcon icon;
|
|
||||||
ButtonState state;
|
|
||||||
|
|
||||||
QList<IconAction*> cornerActions;
|
|
||||||
};
|
|
||||||
|
|
||||||
IconAction::IconAction(Icon* icon, QAction *action)
|
IconAction::IconAction(Icon* icon, QAction *action)
|
||||||
: m_icon(icon),
|
: m_icon(icon),
|
||||||
@ -349,14 +272,14 @@ void IconAction::paint(QPainter *painter) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
Icon::Icon(QGraphicsItem *parent)
|
Icon::Icon(QGraphicsItem *parent)
|
||||||
: QGraphicsItem(parent),
|
: Plasma::Widget(parent),
|
||||||
d(new Private)
|
d(new Private)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
Icon::Icon(const QString &text, QGraphicsItem *parent)
|
Icon::Icon(const QString &text, QGraphicsItem *parent)
|
||||||
: QGraphicsItem(parent),
|
: Plasma::Widget(parent),
|
||||||
d(new Private)
|
d(new Private)
|
||||||
{
|
{
|
||||||
setText(text);
|
setText(text);
|
||||||
@ -364,7 +287,7 @@ Icon::Icon(const QString &text, QGraphicsItem *parent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Icon::Icon(const QIcon &icon, const QString &text, QGraphicsItem *parent)
|
Icon::Icon(const QIcon &icon, const QString &text, QGraphicsItem *parent)
|
||||||
: QGraphicsItem(parent),
|
: Plasma::Widget(parent),
|
||||||
d(new Private)
|
d(new Private)
|
||||||
{
|
{
|
||||||
setText(text);
|
setText(text);
|
||||||
@ -379,8 +302,21 @@ Icon::~Icon()
|
|||||||
|
|
||||||
void Icon::init()
|
void Icon::init()
|
||||||
{
|
{
|
||||||
setAcceptedMouseButtons(Qt::LeftButton);
|
// setAcceptedMouseButtons(Qt::LeftButton);
|
||||||
setAcceptsHoverEvents(true);
|
setAcceptsHoverEvents(true);
|
||||||
|
|
||||||
|
int focusHMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin);
|
||||||
|
int focusVMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameVMargin);
|
||||||
|
|
||||||
|
// Margins for horizontal mode (list views, tree views, table views)
|
||||||
|
d->setHorizontalMargin(Private::TextMargin, focusHMargin, focusVMargin);
|
||||||
|
d->setHorizontalMargin(Private::IconMargin, focusHMargin, focusVMargin);
|
||||||
|
d->setHorizontalMargin(Private::ItemMargin, 0, 0);
|
||||||
|
|
||||||
|
// Margins for vertical mode (icon views)
|
||||||
|
d->setVerticalMargin(Private::TextMargin, 6, 2);
|
||||||
|
d->setVerticalMargin(Private::IconMargin, focusHMargin, focusVMargin);
|
||||||
|
d->setVerticalMargin(Private::ItemMargin, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Icon::addAction(QAction *action)
|
void Icon::addAction(QAction *action)
|
||||||
@ -426,17 +362,55 @@ void Icon::actionDestroyed(QObject* action)
|
|||||||
update(); // redraw since an action has been deleted.
|
update(); // redraw since an action has been deleted.
|
||||||
}
|
}
|
||||||
|
|
||||||
void Icon::calculateSize()
|
QSizeF Icon::Private::displaySizeHint(const QStyleOptionGraphicsItem *option) const
|
||||||
{
|
{
|
||||||
prepareGeometryChange();
|
QString label = text;
|
||||||
QFontMetrics fm(QApplication::font()); // TODO: get the font somewhere more appropriate
|
const qreal maxWidth = (orientation == Qt::Vertical) ? iconSize.width() + 10 : 32757;
|
||||||
QSizeF fmSize = fm.size(Qt::AlignHCenter | Qt::AlignTop, d->text);
|
kDebug() << "Icon::Private::displaySizeHint maxWidth: " << maxWidth;
|
||||||
|
|
||||||
int margin = 6; // hmmm
|
// To compute the nominal size for the label + info, we'll just append
|
||||||
qreal height = d->iconSize.height() + (margin*2) + fmSize.height();
|
// the information string to the label
|
||||||
qreal width = margin + qMax(fmSize.width(), d->iconSize.width()) + margin;
|
const QString info = infoText;
|
||||||
d->size = QSizeF(width, height);
|
if (!info.isEmpty())
|
||||||
|
label += QString(QChar::LineSeparator) + info;
|
||||||
|
|
||||||
|
QTextLayout layout;
|
||||||
|
setLayoutOptions(layout, option);
|
||||||
|
|
||||||
|
kDebug() << "Icon::Private::displaySizeHint maxWidth: " << maxWidth;
|
||||||
|
QSizeF size = layoutText(layout, option, label, QSizeF(iconSize.width() + 10, 32757));
|
||||||
|
kDebug() << "Icon::Private::displaySizeHint size.width: " << size.width();
|
||||||
|
|
||||||
|
return addMargin(size, TextMargin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Icon::calculateSize(const QStyleOptionGraphicsItem *option)
|
||||||
|
{
|
||||||
|
if (!d->calculateSizeRequested)
|
||||||
|
return;
|
||||||
|
|
||||||
|
prepareGeometryChange();
|
||||||
|
d->setActiveMargins();
|
||||||
|
|
||||||
|
const QSizeF displaySize = d->displaySizeHint(option);
|
||||||
|
const QSizeF decorationSize = d->addMargin(d->iconSize, Private::IconMargin);
|
||||||
|
|
||||||
|
QSizeF newSize;
|
||||||
|
if (d->orientation == Qt::Vertical)
|
||||||
|
{
|
||||||
|
newSize.rwidth() = qMax(decorationSize.width(), displaySize.width());
|
||||||
|
newSize.rheight() = decorationSize.height() + displaySize.height() + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newSize.rwidth() = decorationSize.width() + displaySize.width() + 1;
|
||||||
|
newSize.rheight() = qMax(decorationSize.height(), displaySize.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
kDebug() << "Icon::calculateSize newSize: " << newSize;
|
||||||
|
d->size = d->addMargin(newSize, Private::ItemMargin);
|
||||||
d->svg.resize(d->size);
|
d->svg.resize(d->size);
|
||||||
|
d->calculateSizeRequested = false;
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
foreach (IconAction* iconAction, d->cornerActions) {
|
foreach (IconAction* iconAction, d->cornerActions) {
|
||||||
@ -527,44 +501,266 @@ void Icon::Private::drawForeground(QPainter *painter)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Icon::Private::drawIcon(QPainter *painter)
|
QPixmap Icon::Private::decoration(const QStyleOptionGraphicsItem *option) const
|
||||||
{
|
{
|
||||||
if (!icon.isNull()) {
|
QPixmap result;
|
||||||
qreal iw = iconSize.width();
|
|
||||||
qreal ih = iconSize.height();
|
QIcon::Mode mode = option->state & QStyle::State_Enabled ? QIcon::Normal : QIcon::Disabled;
|
||||||
qreal deltaX = (size.width() - iw) / 2;
|
QIcon::State state = option->state & QStyle::State_Open ? QIcon::On : QIcon::Off;
|
||||||
qreal deltaY = (size.height() - ih) / 2 ;
|
const QSize size = icon.actualSize(iconSize.toSize(), mode, state);
|
||||||
if (state == Private::PressedState) {
|
result = icon.pixmap(size, mode, state);
|
||||||
painter->save();
|
|
||||||
painter->setRenderHint(QPainter::SmoothPixmapTransform);
|
if (!result.isNull())
|
||||||
painter->scale(0.95, 0.95);
|
{
|
||||||
deltaY *= 0.95;
|
// Apply the configured hover effect NOTE: This has no visible effect because we
|
||||||
deltaX *= 0.95;
|
// do drawForeground() -MB
|
||||||
painter->drawPixmap((int)(deltaX + (iw * .025)), (int)(deltaY + (ih * .025)),
|
if (option->state & QStyle::State_MouseOver) {
|
||||||
icon.pixmap(iconSize.toSize()));
|
KIconEffect *effect = KIconLoader::global()->iconEffect();
|
||||||
painter->restore();
|
|
||||||
} else {
|
// Note that in KIconLoader terminology, active = hover.
|
||||||
painter->drawPixmap((int)deltaX, (int)deltaY, icon.pixmap(iconSize.toSize()));
|
// ### We're assuming that the icon group is desktop/filemanager, since this
|
||||||
|
// is KFileItemDelegate.
|
||||||
|
if (effect->hasEffect(K3Icon::Desktop, K3Icon::ActiveState)) {
|
||||||
|
result = effect->apply(result, K3Icon::Desktop, K3Icon::ActiveState);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Icon::Private::drawText(QPainter *painter)
|
QPointF Icon::Private::iconPosition(const QStyleOptionGraphicsItem *option, const QPixmap &pixmap) const
|
||||||
{
|
{
|
||||||
if (!text.isEmpty()) {
|
const QRectF itemRect = subtractMargin(option->rect, Private::ItemMargin);
|
||||||
qreal offset = (iconSize.height() + 12); // TODO this shouldn't be hardcoded?
|
Qt::Alignment alignment = Qt::AlignHCenter | Qt::AlignTop; // NOTE: This assumes always top-center -MB
|
||||||
QRectF textRect(0, offset, size.width(), size.height() - offset);
|
|
||||||
|
|
||||||
QTextOption textOpt;
|
// Compute the nominal decoration rectangle
|
||||||
textOpt.setAlignment(Qt::AlignHCenter | Qt::AlignTop);
|
const QSizeF size = addMargin(iconSize, Private::IconMargin);
|
||||||
textOpt.setWrapMode(QTextOption::WordWrap);
|
const QRect iconRect = QStyle::alignedRect(option->direction, alignment, size.toSize(), itemRect.toRect());
|
||||||
|
|
||||||
painter->setPen(Qt::white);
|
// Position the pixmap in the center of the rectangle
|
||||||
painter->drawText(textRect, text, textOpt);
|
QRect pixmapRect = pixmap.rect();
|
||||||
|
pixmapRect.moveCenter(iconRect.center());
|
||||||
|
|
||||||
|
// add a gimmicky margin of 5px to y, TEMP TEMP TEMP
|
||||||
|
// pixmapRect = pixmapRect.adjusted(0, 5, 0, 0);
|
||||||
|
|
||||||
|
return QPointF(pixmapRect.topLeft());
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF Icon::Private::labelRectangle(const QStyleOptionGraphicsItem *option, const QPixmap &icon,
|
||||||
|
const QString &string) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(string)
|
||||||
|
|
||||||
|
if (icon.isNull())
|
||||||
|
return option->rect;
|
||||||
|
|
||||||
|
const QSizeF decoSize = addMargin(iconSize, Private::IconMargin);
|
||||||
|
|
||||||
|
kDebug() << "Icon::Private::labelRectangle option->rect: " << option->rect;
|
||||||
|
const QRectF itemRect = subtractMargin(option->rect, Private::ItemMargin);
|
||||||
|
QRectF textArea(QPointF(0, 0), itemRect.size());
|
||||||
|
|
||||||
|
textArea.setTop(decoSize.height() + 1);
|
||||||
|
textArea.translate(itemRect.topLeft());
|
||||||
|
return QRectF(QStyle::visualRect(option->direction, option->rect, textArea.toRect()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lays the text out in a rectangle no larger than constraints, eliding it as necessary
|
||||||
|
QSizeF Icon::Private::layoutText(QTextLayout &layout, const QStyleOptionGraphicsItem *option,
|
||||||
|
const QString &text, const QSizeF &constraints) const
|
||||||
|
{
|
||||||
|
const QSizeF size = layoutText(layout, text, constraints.width());
|
||||||
|
|
||||||
|
if (size.width() > constraints.width() || size.height() > constraints.height())
|
||||||
|
{
|
||||||
|
const QString elided = elidedText(layout, option, constraints);
|
||||||
|
return layoutText(layout, elided, constraints.width());
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lays the text out in a rectangle no wider than maxWidth
|
||||||
|
QSizeF Icon::Private::layoutText(QTextLayout &layout, const QString &text, qreal maxWidth) const
|
||||||
|
{
|
||||||
|
QFontMetricsF metrics(layout.font());
|
||||||
|
qreal leading = metrics.leading();
|
||||||
|
qreal height = 0.0;
|
||||||
|
qreal widthUsed = 0.0;
|
||||||
|
QTextLine line;
|
||||||
|
|
||||||
|
layout.setText(text);
|
||||||
|
|
||||||
|
layout.beginLayout();
|
||||||
|
|
||||||
|
// kDebug() << "layoutText called with maxWidth: " << maxWidth;
|
||||||
|
while ((line = layout.createLine()).isValid())
|
||||||
|
{
|
||||||
|
line.setLineWidth(maxWidth);
|
||||||
|
height += leading;
|
||||||
|
line.setPosition(QPointF(0.0, height));
|
||||||
|
height += line.height();
|
||||||
|
widthUsed = qMax(widthUsed, line.naturalTextWidth());
|
||||||
|
}
|
||||||
|
layout.endLayout();
|
||||||
|
|
||||||
|
// return layout.boundingRect().size(); // ARGH!
|
||||||
|
return QSizeF(widthUsed, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Elides the text in the layout, by iterating over each line in the layout, eliding
|
||||||
|
// or word breaking the line if it's wider than the max width, and finally adding an
|
||||||
|
// ellipses at the end of the last line, if there are more lines than will fit within
|
||||||
|
// the vertical size constraints.
|
||||||
|
QString Icon::Private::elidedText(QTextLayout &layout, const QStyleOptionGraphicsItem *option,
|
||||||
|
const QSizeF &size) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(option)
|
||||||
|
|
||||||
|
QFontMetricsF metrics(layout.font());
|
||||||
|
const QString text = layout.text();
|
||||||
|
qreal maxWidth = size.width();
|
||||||
|
qreal maxHeight = size.height();
|
||||||
|
qreal height = 0;
|
||||||
|
|
||||||
|
// If the string contains a single line of text it shouldn't be word wrapped
|
||||||
|
if (text.indexOf(QChar::LineSeparator) == -1)
|
||||||
|
return metrics.elidedText(text, Qt::ElideRight, maxWidth);
|
||||||
|
|
||||||
|
// Elide each line that has already been laid out in the layout.
|
||||||
|
QString elided;
|
||||||
|
elided.reserve(text.length());
|
||||||
|
|
||||||
|
for (int i = 0; i < layout.lineCount(); i++)
|
||||||
|
{
|
||||||
|
QTextLine line = layout.lineAt(i);
|
||||||
|
int start = line.textStart();
|
||||||
|
int length = line.textLength();
|
||||||
|
|
||||||
|
height += metrics.leading();
|
||||||
|
if (height + line.height() + metrics.lineSpacing() > maxHeight)
|
||||||
|
{
|
||||||
|
// Unfortunately, if the line ends because of a line separator, elidedText() will be too
|
||||||
|
// clever and keep adding lines until it finds one that's too wide.
|
||||||
|
if (line.naturalTextWidth() < maxWidth && text[start + length - 1] == QChar::LineSeparator)
|
||||||
|
elided += text.mid(start, length - 1);
|
||||||
|
else
|
||||||
|
elided += metrics.elidedText(text.mid(start), Qt::ElideRight, maxWidth);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (line.naturalTextWidth() > maxWidth)
|
||||||
|
elided += metrics.elidedText(text.mid(start, length), Qt::ElideRight, maxWidth);
|
||||||
|
else
|
||||||
|
elided += text.mid(start, length);
|
||||||
|
|
||||||
|
height += line.height();
|
||||||
|
}
|
||||||
|
|
||||||
|
return elided;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Icon::Private::layoutTextItems(const QStyleOptionGraphicsItem *option,
|
||||||
|
const QPixmap &icon, QTextLayout *labelLayout,
|
||||||
|
QTextLayout *infoLayout, QRectF *textBoundingRect) const
|
||||||
|
{
|
||||||
|
bool showInformation = false;
|
||||||
|
|
||||||
|
setLayoutOptions(*labelLayout, option);
|
||||||
|
|
||||||
|
QFontMetricsF fm(labelLayout->font());
|
||||||
|
const QRectF textArea = labelRectangle(option, icon, text);
|
||||||
|
QRectF textRect = subtractMargin(textArea, Private::TextMargin);
|
||||||
|
|
||||||
|
// Sizes and constraints for the different text parts
|
||||||
|
QSizeF maxLabelSize = textRect.size();
|
||||||
|
QSizeF maxInfoSize = textRect.size();
|
||||||
|
QSizeF labelSize;
|
||||||
|
QSizeF infoSize;
|
||||||
|
|
||||||
|
// If we have additional info text, and there's space for at least two lines of text,
|
||||||
|
// adjust the max label size to make room for at least one line of the info text
|
||||||
|
if (!infoText.isEmpty() && textRect.height() >= fm.lineSpacing() * 2)
|
||||||
|
{
|
||||||
|
infoLayout->setFont(labelLayout->font());
|
||||||
|
infoLayout->setTextOption(labelLayout->textOption());
|
||||||
|
|
||||||
|
maxLabelSize.rheight() -= fm.lineSpacing();
|
||||||
|
showInformation = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lay out the label text, and adjust the max info size based on the label size
|
||||||
|
kDebug() << "Icon::Private::layoutTextItems maxLabelSize: " << maxLabelSize;
|
||||||
|
labelSize = layoutText(*labelLayout, option, text, maxLabelSize);
|
||||||
|
maxInfoSize.rheight() -= labelSize.height();
|
||||||
|
|
||||||
|
// Lay out the info text
|
||||||
|
if (showInformation)
|
||||||
|
infoSize = layoutText(*infoLayout, option, infoText, maxInfoSize);
|
||||||
|
else
|
||||||
|
infoSize = QSizeF(0, 0);
|
||||||
|
|
||||||
|
// Compute the bounding rect of the text
|
||||||
|
const Qt::Alignment alignment = labelLayout->textOption().alignment();
|
||||||
|
const QSizeF size(qMax(labelSize.width(), infoSize.width()), labelSize.height() + infoSize.height());
|
||||||
|
*textBoundingRect = QStyle::alignedRect(option->direction, alignment, size.toSize(), textRect.toRect());
|
||||||
|
|
||||||
|
// Compute the positions where we should draw the layouts
|
||||||
|
labelLayout->setPosition(QPointF(textRect.x(), textBoundingRect->y()));
|
||||||
|
infoLayout->setPosition(QPointF(textRect.x(), textBoundingRect->y() + labelSize.height()));
|
||||||
|
}
|
||||||
|
|
||||||
|
QBrush Icon::Private::foregroundBrush(const QStyleOptionGraphicsItem *option) const
|
||||||
|
{
|
||||||
|
const QPalette::ColorGroup group = option->state & QStyle::State_Enabled ?
|
||||||
|
QPalette::Normal : QPalette::Disabled;
|
||||||
|
|
||||||
|
// Always use the highlight color for selected items
|
||||||
|
if (option->state & QStyle::State_Selected)
|
||||||
|
return option->palette.brush(group, QPalette::HighlightedText);
|
||||||
|
|
||||||
|
return option->palette.brush(group, QPalette::Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
QBrush Icon::Private::backgroundBrush(const QStyleOptionGraphicsItem *option) const
|
||||||
|
{
|
||||||
|
const QPalette::ColorGroup group = option->state & QStyle::State_Enabled ?
|
||||||
|
QPalette::Normal : QPalette::Disabled;
|
||||||
|
|
||||||
|
QBrush background(Qt::NoBrush);
|
||||||
|
|
||||||
|
// Always use the highlight color for selected items
|
||||||
|
if (option->state & QStyle::State_Selected)
|
||||||
|
background = option->palette.brush(group, QPalette::Highlight);
|
||||||
|
|
||||||
|
return background;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Icon::Private::drawTextItems(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||||
|
const QTextLayout &labelLayout, const QTextLayout &infoLayout) const
|
||||||
|
{
|
||||||
|
QPen pen(foregroundBrush(option), 0);
|
||||||
|
painter->setPen(pen);
|
||||||
|
labelLayout.draw(painter, QPointF());
|
||||||
|
|
||||||
|
if (!infoLayout.text().isEmpty())
|
||||||
|
{
|
||||||
|
QColor color;
|
||||||
|
if (option->state & QStyle::State_Selected)
|
||||||
|
{
|
||||||
|
color = option->palette.color(QPalette::HighlightedText);
|
||||||
|
color.setAlphaF(.5);
|
||||||
|
} else
|
||||||
|
color = option->palette.color(QPalette::Highlight);
|
||||||
|
|
||||||
|
painter->setPen(color);
|
||||||
|
infoLayout.draw(painter, QPointF());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Icon::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
|
||||||
|
void Icon::paintWidget(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||||
{
|
{
|
||||||
Q_UNUSED(option)
|
Q_UNUSED(option)
|
||||||
Q_UNUSED(widget)
|
Q_UNUSED(widget)
|
||||||
@ -585,9 +781,23 @@ void Icon::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWid
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
calculateSize(option);
|
||||||
|
d->setActiveMargins();
|
||||||
|
|
||||||
|
// Compute the metrics, and lay out the text items
|
||||||
|
// ========================================================================
|
||||||
|
QPixmap icon = d->decoration(option);
|
||||||
|
const QPointF iconPos = d->iconPosition(option, icon);
|
||||||
|
|
||||||
|
QTextLayout labelLayout, infoLayout;
|
||||||
|
QRectF textBoundingRect;
|
||||||
|
d->layoutTextItems(option, icon, &labelLayout, &infoLayout, &textBoundingRect);
|
||||||
|
|
||||||
d->svg.resize(d->size);
|
d->svg.resize(d->size);
|
||||||
d->drawBackground(painter);
|
d->drawBackground(painter);
|
||||||
d->drawIcon(painter);
|
|
||||||
|
// draw icon
|
||||||
|
painter->drawPixmap(iconPos, icon);
|
||||||
|
|
||||||
d->drawForeground(painter);
|
d->drawForeground(painter);
|
||||||
|
|
||||||
@ -599,7 +809,8 @@ void Icon::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWid
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draw text last because its overlayed
|
// Draw text last because its overlayed
|
||||||
d->drawText(painter);
|
d->drawTextItems(painter, option, labelLayout, infoLayout);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Icon::drawActionButtonBase(QPainter* painter, const QSize &size, int element)
|
void Icon::drawActionButtonBase(QPainter* painter, const QSize &size, int element)
|
||||||
@ -631,7 +842,7 @@ void Icon::drawActionButtonBase(QPainter* painter, const QSize &size, int elemen
|
|||||||
void Icon::setText(const QString& text)
|
void Icon::setText(const QString& text)
|
||||||
{
|
{
|
||||||
d->text = text;
|
d->text = text;
|
||||||
calculateSize();
|
d->calculateSizeRequested = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Icon::text() const
|
QString Icon::text() const
|
||||||
@ -642,7 +853,7 @@ QString Icon::text() const
|
|||||||
void Icon::setInfoText(const QString& text)
|
void Icon::setInfoText(const QString& text)
|
||||||
{
|
{
|
||||||
d->infoText = text;
|
d->infoText = text;
|
||||||
calculateSize();
|
d->calculateSizeRequested = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Icon::infoText() const
|
QString Icon::infoText() const
|
||||||
@ -663,7 +874,7 @@ void Icon::setIcon(const QString& icon)
|
|||||||
void Icon::setIcon(const QIcon& icon)
|
void Icon::setIcon(const QIcon& icon)
|
||||||
{
|
{
|
||||||
d->icon = icon;
|
d->icon = icon;
|
||||||
calculateSize();
|
d->calculateSizeRequested = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSizeF Icon::iconSize() const
|
QSizeF Icon::iconSize() const
|
||||||
@ -674,7 +885,7 @@ QSizeF Icon::iconSize() const
|
|||||||
void Icon::setIconSize(const QSizeF& s)
|
void Icon::setIconSize(const QSizeF& s)
|
||||||
{
|
{
|
||||||
d->iconSize = s;
|
d->iconSize = s;
|
||||||
calculateSize();
|
d->calculateSizeRequested = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Icon::setIconSize(int w, int h)
|
void Icon::setIconSize(int w, int h)
|
||||||
@ -689,22 +900,21 @@ bool Icon::isDown()
|
|||||||
|
|
||||||
void Icon::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
void Icon::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
kDebug() << "Icon::mousePressEvent ";
|
|
||||||
foreach (IconAction *action, d->cornerActions) {
|
foreach (IconAction *action, d->cornerActions) {
|
||||||
action->event(event->type(), event->pos());
|
action->event(event->type(), event->pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
d->state = Private::PressedState;
|
d->state = Private::PressedState;
|
||||||
|
|
||||||
QGraphicsItem::mousePressEvent(event);
|
QGraphicsItem::mousePressEvent(event);
|
||||||
update();
|
update();
|
||||||
event->accept();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Icon::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
void Icon::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
bool inside = boundingRect().contains(event->pos());
|
bool inside = boundingRect().contains(event->pos());
|
||||||
kDebug() << "Icon::mouseReleaseEvent " << inside;
|
|
||||||
Private::ButtonState was = d->state;
|
Private::ButtonState was = d->state;
|
||||||
|
|
||||||
if (inside) {
|
if (inside) {
|
||||||
d->state = Private::HoverState;
|
d->state = Private::HoverState;
|
||||||
|
|
||||||
@ -714,16 +924,17 @@ kDebug() << "Icon::mouseReleaseEvent " << inside;
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
d->state = Private::NoState;
|
|
||||||
}
|
}
|
||||||
|
else if (was == Private::PressedState) {
|
||||||
if (was == Private::PressedState) {
|
|
||||||
emit pressed(false);
|
emit pressed(false);
|
||||||
|
|
||||||
if (inside) {
|
if (inside) {
|
||||||
emit clicked();
|
emit clicked();
|
||||||
}
|
}
|
||||||
|
d->state = Private::NoState;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
d->state = Private::NoState;
|
||||||
}
|
}
|
||||||
|
|
||||||
QGraphicsItem::mouseReleaseEvent(event);
|
QGraphicsItem::mouseReleaseEvent(event);
|
||||||
@ -761,7 +972,6 @@ void Icon::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
QGraphicsItem::mouseMoveEvent(event);
|
QGraphicsItem::mouseMoveEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QSizeF Icon::sizeHint() const
|
QSizeF Icon::sizeHint() const
|
||||||
{
|
{
|
||||||
return d->size;
|
return d->size;
|
||||||
|
243
widgets/icon.h
243
widgets/icon.h
@ -27,10 +27,9 @@
|
|||||||
#include <plasma/dataengine.h>
|
#include <plasma/dataengine.h>
|
||||||
#include <plasma/phase.h>
|
#include <plasma/phase.h>
|
||||||
#include <plasma/plasma_export.h>
|
#include <plasma/plasma_export.h>
|
||||||
#include <plasma/widgets/layoutitem.h>
|
#include <plasma/widgets/widget.h>
|
||||||
|
|
||||||
class QAction;
|
class QAction;
|
||||||
class KUrl;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class provides a generic Icon for the Plasma desktop. An icon, in this
|
* This class provides a generic Icon for the Plasma desktop. An icon, in this
|
||||||
@ -44,162 +43,160 @@ class KUrl;
|
|||||||
namespace Plasma
|
namespace Plasma
|
||||||
{
|
{
|
||||||
|
|
||||||
class PLASMA_EXPORT Icon : public QObject, public QGraphicsItem, public LayoutItem
|
class PLASMA_EXPORT Icon : public Plasma::Widget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY( QString text READ text WRITE setText )
|
Q_PROPERTY( QString text READ text WRITE setText )
|
||||||
Q_PROPERTY( QString infoText READ infoText WRITE setInfoText )
|
Q_PROPERTY( QString infoText READ infoText WRITE setInfoText )
|
||||||
Q_PROPERTY( QSizeF iconSize READ iconSize WRITE setIconSize )
|
Q_PROPERTY( QSizeF iconSize READ iconSize WRITE setIconSize )
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Creates a new Plasma::Icon.
|
||||||
|
* @param parent the QGraphicsItem this icon is parented to.
|
||||||
|
*/
|
||||||
|
explicit Icon(QGraphicsItem *parent = 0);
|
||||||
|
|
||||||
public:
|
/**
|
||||||
/**
|
* Convenience constructor to create a Plasma::Icon with text.
|
||||||
* Creates a new Plasma::Icon.
|
* @param text the text that will be displayed with this icon.
|
||||||
* @param parent the QGraphicsItem this icon is parented to.
|
* @param parent the QGraphicsItem this icon is parented to.
|
||||||
*/
|
*/
|
||||||
explicit Icon(QGraphicsItem *parent = 0);
|
explicit Icon(const QString &text, QGraphicsItem *parent = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience constructor to create a Plasma::Icon with text.
|
* Creates a new Plasma::Icon with text and an icon.
|
||||||
* @param text the text that will be displayed with this icon.
|
* @param icon the icon that will be displayed with this icon.
|
||||||
* @param parent the QGraphicsItem this icon is parented to.
|
* @param text the text that will be displayed with this icon.
|
||||||
*/
|
* @param parent The QGraphicsItem this icon is parented to.
|
||||||
explicit Icon(const QString &text, QGraphicsItem *parent = 0);
|
*/
|
||||||
|
Icon(const QIcon & icon, const QString &text, QGraphicsItem *parent = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Plasma::Icon with text and an icon.
|
* Destroys this Plasma::Icon.
|
||||||
* @param icon the icon that will be displayed with this icon.
|
*/
|
||||||
* @param text the text that will be displayed with this icon.
|
virtual ~Icon();
|
||||||
* @param parent The QGraphicsItem this icon is parented to.
|
|
||||||
*/
|
|
||||||
Icon(const QIcon & icon, const QString &text, QGraphicsItem *parent = 0);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroys this Plasma::Icon.
|
* Returns the text associated with this icon.
|
||||||
*/
|
*/
|
||||||
virtual ~Icon();
|
QString text() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the text associated with this icon.
|
* Sets the text associated with this icon.
|
||||||
*/
|
* @param text the text to associate with this icon.
|
||||||
QString text() const;
|
*/
|
||||||
|
void setText(const QString &text);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the text associated with this icon.
|
* Returns the meta text associated with this icon.
|
||||||
* @param text the text to associate with this icon.
|
*/
|
||||||
*/
|
QString infoText() const;
|
||||||
void setText(const QString &text);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the meta text associated with this icon.
|
* Sets the additional information to be displayed by
|
||||||
*/
|
* this icon.
|
||||||
QString infoText() const;
|
* @param text additional meta text associated with this icon.
|
||||||
|
*/
|
||||||
|
void setInfoText(const QString &text);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the additional information to be displayed by
|
* Sets the graphical icon for this Plasma::Icon.
|
||||||
* this icon.
|
* @param icon the QIcon to associate with this icon.
|
||||||
* @param text additional meta text associated with this icon.
|
*/
|
||||||
*/
|
Q_INVOKABLE void setIcon(const QIcon& icon);
|
||||||
void setInfoText(const QString &text);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the graphical icon for this Plasma::Icon.
|
* Convenience method to set the icon of this Plasma::Icon
|
||||||
* @param icon the QIcon to associate with this icon.
|
* using a QString path to the icon.
|
||||||
*/
|
* @param icon the path to the icon to associate with this Plasma::Icon.
|
||||||
Q_INVOKABLE void setIcon(const QIcon& icon);
|
*/
|
||||||
|
Q_INVOKABLE void setIcon(const QString& icon);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method to set the icon of this Plasma::Icon
|
* Returns the size of this Plasma::Icon's graphical icon.
|
||||||
* using a QString path to the icon.
|
*/
|
||||||
* @param icon the path to the icon to associate with this Plasma::Icon.
|
Q_INVOKABLE QSizeF iconSize() const;
|
||||||
*/
|
|
||||||
Q_INVOKABLE void setIcon(const QString& icon);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the size of this Plasma::Icon's graphical icon.
|
* Sets the size of the graphical icon for this Plasma::Icon.
|
||||||
*/
|
* @param size the size of the icon.
|
||||||
QSizeF iconSize() const;
|
*/
|
||||||
|
Q_INVOKABLE void setIconSize(const QSizeF& size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the size of the graphical icon for this Plasma::Icon.
|
* Convenience method to set the icon size without a QSizeF.
|
||||||
* @param size the size of the icon.
|
* @param height the height of the icon.
|
||||||
*/
|
* @param width the width of the icon.
|
||||||
void setIconSize(const QSizeF& size);
|
*/
|
||||||
|
Q_INVOKABLE void setIconSize(int height, int width);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method to set the icon size without a QSizeF.
|
* Plasma::Icon allows the user to specify a number of actions
|
||||||
* @param height the height of the icon.
|
* (current four) to be displayed around the widget. This method
|
||||||
* @param width the width of the icon.
|
* allows for a created QAction (not a KAction!) to be added to
|
||||||
*/
|
* the Plasma::Icon.
|
||||||
Q_INVOKABLE void setIconSize(int height, int width);
|
* @param action the QAction to associate with this icon.
|
||||||
|
*/
|
||||||
|
void addAction(QAction* action);
|
||||||
|
|
||||||
|
// Layout stuff - no need to document
|
||||||
|
Qt::Orientations expandingDirections() const;
|
||||||
|
|
||||||
/**
|
QSizeF minimumSize() const;
|
||||||
* Plasma::Icon allows the user to specify a number of actions
|
QSizeF maximumSize() const;
|
||||||
* (current four) to be displayed around the widget. This method
|
|
||||||
* allows for a created QAction (not a KAction!) to be added to
|
|
||||||
* the Plasma::Icon.
|
|
||||||
* @param action the QAction to associate with this icon.
|
|
||||||
*/
|
|
||||||
void addAction(QAction* action);
|
|
||||||
|
|
||||||
// Layout stuff - no need to document
|
bool hasHeightForWidth() const;
|
||||||
Qt::Orientations expandingDirections() const;
|
qreal heightForWidth(qreal w) const;
|
||||||
|
|
||||||
QSizeF minimumSize() const;
|
bool hasWidthForHeight() const;
|
||||||
QSizeF maximumSize() const;
|
qreal widthForHeight(qreal h) const;
|
||||||
|
|
||||||
bool hasHeightForWidth() const;
|
QRectF geometry() const;
|
||||||
qreal heightForWidth(qreal w) const;
|
void setGeometry(const QRectF& r);
|
||||||
|
|
||||||
bool hasWidthForHeight() const;
|
QSizeF sizeHint() const;
|
||||||
qreal widthForHeight(qreal h) const;
|
QRectF boundingRect() const;
|
||||||
|
|
||||||
QRectF geometry() const;
|
protected:
|
||||||
void setGeometry(const QRectF& r);
|
void paintWidget(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
|
||||||
|
|
||||||
QSizeF sizeHint() const;
|
Q_SIGNALS:
|
||||||
QRectF boundingRect() const;
|
/**
|
||||||
|
* Indicates when the icon has been pressed.
|
||||||
|
*/
|
||||||
|
void pressed(bool down);
|
||||||
|
|
||||||
protected:
|
/**
|
||||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
|
* Indicates when the icon has been clicked.
|
||||||
|
*/
|
||||||
|
void clicked();
|
||||||
|
|
||||||
Q_SIGNALS:
|
protected:
|
||||||
/**
|
bool isDown();
|
||||||
* Indicates when the icon has been pressed.
|
void mousePressEvent(QGraphicsSceneMouseEvent *event);
|
||||||
*/
|
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
|
||||||
void pressed(bool down);
|
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
|
||||||
|
|
||||||
/**
|
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
|
||||||
* Indicates when the icon has been clicked.
|
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
||||||
*/
|
|
||||||
void clicked();
|
|
||||||
|
|
||||||
protected:
|
public:
|
||||||
bool isDown();
|
class Private;
|
||||||
void mousePressEvent(QGraphicsSceneMouseEvent *event);
|
|
||||||
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
|
|
||||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
|
|
||||||
|
|
||||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
|
/**
|
||||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
* @internal
|
||||||
|
**/
|
||||||
|
void drawActionButtonBase(QPainter* painter, const QSize &size, int element);
|
||||||
|
|
||||||
public:
|
private:
|
||||||
class Private;
|
void init();
|
||||||
|
void calculateSize(const QStyleOptionGraphicsItem *option);
|
||||||
|
|
||||||
/**
|
Private * const d;
|
||||||
* @internal
|
|
||||||
**/
|
|
||||||
void drawActionButtonBase(QPainter* painter, const QSize &size, int element);
|
|
||||||
|
|
||||||
private:
|
private Q_SLOTS:
|
||||||
QPixmap buttonPixmap();
|
void actionDestroyed(QObject* obj);
|
||||||
void init();
|
|
||||||
void calculateSize();
|
|
||||||
|
|
||||||
Private * const d;
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
|
||||||
void actionDestroyed(QObject* obj);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Plasma
|
} // namespace Plasma
|
||||||
|
255
widgets/icon_p.h
Normal file
255
widgets/icon_p.h
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2007 by Aaron Seigo <aseigo@kde.org>
|
||||||
|
* Copyright (C) 2007 by Matt Broadstone <mbroadst@gmail.com>
|
||||||
|
* Copyright (C) 2006-2007 Fredrik Höglund <fredrik@kde.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Library General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this program; if not, write to the
|
||||||
|
* Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef ICON_P_H
|
||||||
|
#define ICON_P_H
|
||||||
|
|
||||||
|
#include <QtCore/QEvent>
|
||||||
|
#include <QtGui/QApplication>
|
||||||
|
#include <QtGui/QStyleOptionGraphicsItem>
|
||||||
|
#include <QtGui/QTextLayout>
|
||||||
|
#include <QtGui/QTextOption>
|
||||||
|
#include <QtGui/QIcon>
|
||||||
|
|
||||||
|
#include <plasma/plasma_export.h>
|
||||||
|
#include <plasma/svg.h>
|
||||||
|
|
||||||
|
#include "icon.h"
|
||||||
|
|
||||||
|
class QAction;
|
||||||
|
class QPainter;
|
||||||
|
class QTextLayout;
|
||||||
|
|
||||||
|
namespace Plasma
|
||||||
|
{
|
||||||
|
|
||||||
|
class PLASMA_EXPORT IconAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IconAction(Icon* icon, QAction* action);
|
||||||
|
|
||||||
|
void show();
|
||||||
|
void hide();
|
||||||
|
bool isVisible() const;
|
||||||
|
|
||||||
|
Phase::AnimId animationId() const;
|
||||||
|
QAction* action() const;
|
||||||
|
|
||||||
|
void paint(QPainter *painter) const;
|
||||||
|
bool event(QEvent::Type type, const QPointF &pos);
|
||||||
|
|
||||||
|
void setSelected(bool selected);
|
||||||
|
bool isSelected() const;
|
||||||
|
|
||||||
|
bool isHovered() const;
|
||||||
|
bool isPressed() const;
|
||||||
|
|
||||||
|
void setRect(const QRectF &rect);
|
||||||
|
QRectF rect() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void rebuildPixmap();
|
||||||
|
|
||||||
|
Icon *m_icon;
|
||||||
|
QAction *m_action;
|
||||||
|
QPixmap m_pixmap;
|
||||||
|
QRectF m_rect;
|
||||||
|
|
||||||
|
bool m_hovered;
|
||||||
|
bool m_pressed;
|
||||||
|
bool m_selected;
|
||||||
|
bool m_visible;
|
||||||
|
|
||||||
|
Phase::AnimId m_animationId;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct Margin
|
||||||
|
{
|
||||||
|
qreal left, right, top, bottom;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Icon::Private
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum MarginType { ItemMargin = 0, TextMargin, IconMargin, NMargins };
|
||||||
|
|
||||||
|
public:
|
||||||
|
Private();
|
||||||
|
~Private();
|
||||||
|
|
||||||
|
void drawBackground(QPainter *painter);
|
||||||
|
void drawForeground(QPainter *painter);
|
||||||
|
void drawText(QPainter *painter);
|
||||||
|
void drawTextItems(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||||
|
const QTextLayout &labelLayout, const QTextLayout &infoLayout) const;
|
||||||
|
|
||||||
|
QPixmap decoration(const QStyleOptionGraphicsItem *option) const;
|
||||||
|
QPointF iconPosition(const QStyleOptionGraphicsItem *option, const QPixmap &pixmap) const;
|
||||||
|
|
||||||
|
QSizeF displaySizeHint(const QStyleOptionGraphicsItem *option) const;
|
||||||
|
|
||||||
|
QBrush foregroundBrush(const QStyleOptionGraphicsItem *option) const;
|
||||||
|
QBrush backgroundBrush(const QStyleOptionGraphicsItem *option) const;
|
||||||
|
|
||||||
|
QString elidedText(QTextLayout &layout, const QStyleOptionGraphicsItem *option,
|
||||||
|
const QSizeF &maxSize) const;
|
||||||
|
QSizeF layoutText(QTextLayout &layout, const QStyleOptionGraphicsItem *option,
|
||||||
|
const QString &text, const QSizeF &constraints) const;
|
||||||
|
QSizeF layoutText(QTextLayout &layout, const QString &text, qreal maxWidth) const;
|
||||||
|
QRectF labelRectangle(const QStyleOptionGraphicsItem *option, const QPixmap &icon,
|
||||||
|
const QString &string) const;
|
||||||
|
void layoutTextItems(const QStyleOptionGraphicsItem *option, const QPixmap &icon,
|
||||||
|
QTextLayout *labelLayout, QTextLayout *infoLayout, QRectF *textBoundingRect) const;
|
||||||
|
|
||||||
|
inline void setLayoutOptions(QTextLayout &layout, const QStyleOptionGraphicsItem *options) const;
|
||||||
|
|
||||||
|
|
||||||
|
// Margin functions
|
||||||
|
inline void setActiveMargins();
|
||||||
|
void setVerticalMargin(MarginType type, qreal left, qreal right, qreal top, qreal bottom);
|
||||||
|
void setHorizontalMargin(MarginType type, qreal left, qreal right, qreal top, qreal bottom);
|
||||||
|
inline void setVerticalMargin(MarginType type, qreal hor, qreal ver);
|
||||||
|
inline void setHorizontalMargin(MarginType type, qreal hor, qreal ver);
|
||||||
|
inline QRectF addMargin(const QRectF &rect, MarginType type) const;
|
||||||
|
inline QRectF subtractMargin(const QRectF &rect, MarginType type) const;
|
||||||
|
inline QSizeF addMargin(const QSizeF &size, MarginType type) const;
|
||||||
|
inline QSizeF subtractMargin(const QSizeF &size, MarginType type) const;
|
||||||
|
|
||||||
|
|
||||||
|
void checkSvgElements();
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NoSvg = 0,
|
||||||
|
SvgBackground = 1,
|
||||||
|
SvgBackgroundHover = 2,
|
||||||
|
SvgBackgroundPressed = 4,
|
||||||
|
SvgForeground = 8,
|
||||||
|
SvgForegroundHover = 16,
|
||||||
|
SvgForegroundPressed = 32,
|
||||||
|
SvgMinibutton = 64,
|
||||||
|
SvgMinibuttonHover = 128,
|
||||||
|
SvgMinibuttonPressed = 256
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ActionPosition {
|
||||||
|
TopLeft = 0,
|
||||||
|
TopRight,
|
||||||
|
BottomLeft,
|
||||||
|
BottomRight,
|
||||||
|
LastIconPosition
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ButtonState
|
||||||
|
{
|
||||||
|
NoState,
|
||||||
|
HoverState,
|
||||||
|
PressedState
|
||||||
|
};
|
||||||
|
|
||||||
|
QString text;
|
||||||
|
QString infoText;
|
||||||
|
Svg svg;
|
||||||
|
int svgElements;
|
||||||
|
QSizeF size;
|
||||||
|
QSizeF iconSize;
|
||||||
|
QIcon icon;
|
||||||
|
ButtonState state;
|
||||||
|
Qt::Orientation orientation;
|
||||||
|
bool calculateSizeRequested;
|
||||||
|
|
||||||
|
QList<IconAction*> cornerActions;
|
||||||
|
|
||||||
|
Margin verticalMargin[NMargins];
|
||||||
|
Margin horizontalMargin[NMargins];
|
||||||
|
Margin *activeMargins;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Inline methods
|
||||||
|
void Icon::Private::setLayoutOptions(QTextLayout &layout, const QStyleOptionGraphicsItem *option) const
|
||||||
|
{
|
||||||
|
QTextOption textoption;
|
||||||
|
textoption.setTextDirection(option->direction);
|
||||||
|
textoption.setAlignment(Qt::AlignCenter); // NOTE: assumption
|
||||||
|
textoption.setWrapMode(QTextOption::WordWrap); // NOTE: assumption as well
|
||||||
|
|
||||||
|
layout.setFont(QApplication::font()); // NOTE: find better ways to get the font
|
||||||
|
layout.setTextOption(textoption);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Icon::Private::setActiveMargins()
|
||||||
|
{
|
||||||
|
activeMargins = (orientation == Qt::Horizontal ?
|
||||||
|
horizontalMargin : verticalMargin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Icon::Private::setVerticalMargin(MarginType type, qreal left, qreal top, qreal right, qreal bottom)
|
||||||
|
{
|
||||||
|
verticalMargin[type].left = left;
|
||||||
|
verticalMargin[type].right = right;
|
||||||
|
verticalMargin[type].top = top;
|
||||||
|
verticalMargin[type].bottom = bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Icon::Private::setHorizontalMargin(MarginType type, qreal left, qreal top, qreal right, qreal bottom)
|
||||||
|
{
|
||||||
|
horizontalMargin[type].left = left;
|
||||||
|
horizontalMargin[type].right = right;
|
||||||
|
horizontalMargin[type].top = top;
|
||||||
|
horizontalMargin[type].bottom = bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Icon::Private::setVerticalMargin(MarginType type, qreal horizontal, qreal vertical)
|
||||||
|
{
|
||||||
|
setVerticalMargin(type, horizontal, vertical, horizontal, vertical);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Icon::Private::setHorizontalMargin(MarginType type, qreal horizontal, qreal vertical)
|
||||||
|
{
|
||||||
|
setHorizontalMargin(type, horizontal, vertical, horizontal, vertical);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF Icon::Private::addMargin(const QRectF &rect, MarginType type) const
|
||||||
|
{
|
||||||
|
const Margin &m = activeMargins[type];
|
||||||
|
return rect.adjusted(-m.left, -m.top, m.right, m.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF Icon::Private::subtractMargin(const QRectF &rect, MarginType type) const
|
||||||
|
{
|
||||||
|
const Margin &m = activeMargins[type];
|
||||||
|
return rect.adjusted(m.left, m.top, -m.right, -m.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSizeF Icon::Private::addMargin(const QSizeF &size, MarginType type) const
|
||||||
|
{
|
||||||
|
const Margin &m = activeMargins[type];
|
||||||
|
return QSizeF(size.width() + m.left + m.right, size.height() + m.top + m.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSizeF Icon::Private::subtractMargin(const QSizeF &size, MarginType type) const
|
||||||
|
{
|
||||||
|
const Margin &m = activeMargins[type];
|
||||||
|
return QSizeF(size.width() - m.left - m.right, size.height() - m.top - m.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Namespace
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user