plasma-framework/widgets/iconwidget_p.h
Stephen Kelly b1b68adb7d Don't use the QtGui module name in includes.
In Qt5, many of them are moved to QtWidgets, so this is the only
way to be source compatible with both Qt 4 and Qt 5.
2012-02-02 10:35:53 +01:00

415 lines
12 KiB
C++

/*
* 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 as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* 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 PLASMA_ICONWIDGET_P_H
#define PLASMA_ICONWIDGET_P_H
#include <QtCore/QEvent>
#include <QtCore/QWeakPointer>
#include <QApplication>
#include <QIcon>
#include <QStyleOptionGraphicsItem>
#include <QTextLayout>
#include <QTextOption>
#include "iconwidget.h"
#include "framesvg.h"
#include "private/actionwidgetinterface_p.h"
#include "theme.h"
class QAction;
class QPainter;
class QTextLayout;
class QPropertyAnimation;
namespace Plasma
{
class Animation;
class IconHoverAnimation;
class IconHoverAnimation : public QObject
{
Q_OBJECT
Q_PROPERTY(qreal value READ value WRITE setValue)
public:
IconHoverAnimation(QObject *parent = 0);
qreal value() const;
bool fadeIn() const;
void setFadeIn(bool fadeIn);
QPropertyAnimation *animation() const;
void setAnimation(QPropertyAnimation *animation);
protected slots:
void setValue(qreal value);
private:
qreal m_value;
bool m_fadeIn;
QWeakPointer<QPropertyAnimation> m_animation;
};
class PLASMA_EXPORT IconAction
{
public:
IconAction(IconWidget *icon, QAction *action);
void show();
void hide();
bool isVisible() const;
bool isAnimating() 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();
IconWidget *m_icon;
QAction *m_action;
QPixmap m_pixmap;
QRectF m_rect;
bool m_hovered;
bool m_pressed;
bool m_selected;
bool m_visible;
QWeakPointer<Animation> m_animation;
};
struct Margin
{
qreal left, right, top, bottom;
};
class IconWidgetPrivate : public ActionWidgetInterface<IconWidget>
{
public:
enum MarginType {
ItemMargin = 0,
TextMargin,
IconMargin,
NMargins
};
enum IconWidgetState {
NoState = 0,
HoverState = 1,
PressedState = 2,
ManualPressedState = 4
};
Q_DECLARE_FLAGS(IconWidgetStates, IconWidgetState)
IconWidgetPrivate(IconWidget *i);
~IconWidgetPrivate();
void changed()
{
emit q->changed();
}
void drawBackground(QPainter *painter, IconWidgetState state);
void drawText(QPainter *painter);
void drawTextItems(QPainter *painter, const QStyleOptionGraphicsItem *option,
const QTextLayout &labelLayout, const QTextLayout &infoLayout) const;
QPixmap decoration(const QStyleOptionGraphicsItem *option, bool useHoverEffect, bool usePressedEffect);
QPointF iconPosition(const QStyleOptionGraphicsItem *option, const QPixmap &pixmap) const;
QSizeF displaySizeHint(const QStyleOptionGraphicsItem *option, const qreal width) const;
QBrush foregroundBrush(const QStyleOptionGraphicsItem *option) const;
QBrush backgroundBrush(const QStyleOptionGraphicsItem *option) const;
QString elidedText(QTextLayout &layout,
const QSizeF &maxSize) const;
QSizeF layoutText(QTextLayout &layout,
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;
int maxWordWidth(const QString text) const;
inline void setLayoutOptions(QTextLayout &layout,
const QStyleOptionGraphicsItem *options,
const Qt::Orientation orientation) const;
inline Qt::LayoutDirection iconDirection(const QStyleOptionGraphicsItem *option) const;
enum {
Minibutton = 64,
MinibuttonHover = 128,
MinibuttonPressed = 256
};
enum ActionPosition {
TopLeft = 0,
TopRight,
BottomLeft,
BottomRight,
LastIconPosition = BottomRight
};
// 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;
inline QRectF actionRect(ActionPosition position) const;
void actionDestroyed(QObject *obj);
void svgChanged();
void readColors();
void colorConfigChanged();
void iconConfigChanged();
void hoverAnimationFinished();
void init();
void layoutIcons(const QStyleOptionGraphicsItem *option);
QSizeF iconSizeForWidgetSize(const QStyleOptionGraphicsItem *option, const QSizeF &widgetSize);
void animateMainIcon(bool, const IconWidgetStates state);
QString text;
QString infoText;
Svg *iconSvg;
FrameSvg *background;
QString iconSvgElement;
QPixmap iconSvgPixmap;
QColor textColor;
QColor textBgColor;
QColor shadowColor;
IconHoverAnimation *hoverAnimation;
QSizeF iconSize;
QSizeF preferredIconSize;
QSizeF minimumIconSize;
QSizeF maximumIconSize;
QIcon icon;
QIcon oldIcon;
IconWidgetStates states;
Qt::Orientation orientation;
int numDisplayLines;
QSizeF currentSize;
QPointF clickStartPos;
mutable QList<QRect> haloRects;
QTimer *iconChangeTimer;
QList<IconAction*> cornerActions;
Margin verticalMargin[NMargins];
Margin horizontalMargin[NMargins];
Margin *activeMargins;
bool iconSvgElementChanged : 1;
bool invertLayout : 1;
bool drawBg : 1;
bool textBgCustomized : 1;
static const int maxDisplayLines = 5;
static const int iconActionSize = 26;
static const int iconActionMargin = 4;
bool customFont;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(IconWidgetPrivate::IconWidgetStates)
// Inline methods
void IconWidgetPrivate::setLayoutOptions(QTextLayout &layout,
const QStyleOptionGraphicsItem *option,
const Qt::Orientation orientation) const
{
QTextOption textoption;
textoption.setTextDirection(option->direction);
if (orientation == Qt::Horizontal) {
textoption.setAlignment(Qt::Alignment(Qt::AlignLeft|Qt::AlignVCenter));
} else {
textoption.setAlignment(Qt::AlignCenter);
}
textoption.setWrapMode(QTextOption::WordWrap); // NOTE: assumption as well
layout.setFont(q->font());
layout.setTextOption(textoption);
}
Qt::LayoutDirection IconWidgetPrivate::iconDirection(const QStyleOptionGraphicsItem *option) const
{
Qt::LayoutDirection direction;
if (invertLayout && orientation == Qt::Horizontal) {
if (option->direction == Qt::LeftToRight) {
direction = Qt::RightToLeft;
} else {
direction = Qt::LeftToRight;
}
} else {
direction = option->direction;
}
return direction;
}
void IconWidgetPrivate::setActiveMargins()
{
//sync here itemmargin with contentsrect, not overly pretty but it's where it's more reliable
qreal left, top, right, bottom;
q->getContentsMargins(&left, &top, &right, &bottom);
if (left || top || right || bottom) {
verticalMargin[ItemMargin].left = horizontalMargin[ItemMargin].left = left;
verticalMargin[ItemMargin].top = horizontalMargin[ItemMargin].top = top;
verticalMargin[ItemMargin].right = horizontalMargin[ItemMargin].right = right;
verticalMargin[ItemMargin].bottom = horizontalMargin[ItemMargin].bottom = bottom;
}
activeMargins = (orientation == Qt::Horizontal ? horizontalMargin : verticalMargin);
}
void IconWidgetPrivate::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 IconWidgetPrivate::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 IconWidgetPrivate::setVerticalMargin(MarginType type, qreal horizontal, qreal vertical)
{
setVerticalMargin(type, horizontal, vertical, horizontal, vertical);
}
void IconWidgetPrivate::setHorizontalMargin(MarginType type, qreal horizontal, qreal vertical)
{
setHorizontalMargin(type, horizontal, vertical, horizontal, vertical);
}
QRectF IconWidgetPrivate::addMargin(const QRectF &rect, MarginType type) const
{
Q_ASSERT(activeMargins);
const Margin &m = activeMargins[type];
return rect.adjusted(-m.left, -m.top, m.right, m.bottom);
}
QRectF IconWidgetPrivate::subtractMargin(const QRectF &rect, MarginType type) const
{
Q_ASSERT(activeMargins);
const Margin &m = activeMargins[type];
return rect.adjusted(m.left, m.top, -m.right, -m.bottom);
}
QSizeF IconWidgetPrivate::addMargin(const QSizeF &size, MarginType type) const
{
Q_ASSERT(activeMargins);
const Margin &m = activeMargins[type];
return QSizeF(size.width() + m.left + m.right, size.height() + m.top + m.bottom);
}
QSizeF IconWidgetPrivate::subtractMargin(const QSizeF &size, MarginType type) const
{
Q_ASSERT(activeMargins);
const Margin &m = activeMargins[type];
return QSizeF(size.width() - m.left - m.right, size.height() - m.top - m.bottom);
}
int IconWidgetPrivate::maxWordWidth(const QString text) const
{
QFontMetricsF fm = Plasma::Theme::defaultTheme()->fontMetrics();
QStringList words = text.split(' ');
qreal maxWidth = 0;
foreach (const QString &word, words) {
maxWidth = qMax(maxWidth, fm.width(word));
}
return maxWidth;
}
QRectF IconWidgetPrivate::actionRect(ActionPosition position) const
{
switch (position) {
case TopLeft:
return QRectF(iconActionMargin,
iconActionMargin,
iconActionSize,
iconActionSize);
case TopRight:
return QRectF(currentSize.width() - iconActionSize - iconActionMargin,
iconActionMargin,
iconActionSize,
iconActionSize);
case BottomLeft:
return QRectF(iconActionMargin,
currentSize.height() - iconActionSize - iconActionMargin,
iconActionSize,
iconActionSize);
//BottomRight
default:
return QRectF(currentSize.width() - iconActionSize - iconActionMargin,
currentSize.height() - iconActionSize - iconActionMargin,
iconActionSize,
iconActionSize);
}
}
} // Namespace
#endif