Fix handling of click/hover events and add methods to allow callers to
make the icon appear clicked. Getting it in now so that it doesn't block other work. I believe all discussed issues have been fixed with this patch, but I'll stay around to fix any issues that remain. ;) svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=749016
This commit is contained in:
parent
419f8db838
commit
4fb7cbc2d6
145
widgets/icon.cpp
145
widgets/icon.cpp
|
@ -56,7 +56,7 @@ Icon::Private::Private()
|
|||
: svg("widgets/iconbutton"),
|
||||
svgElements(0),
|
||||
iconSize(48, 48),
|
||||
state(Private::NoState),
|
||||
states(Private::NoState),
|
||||
orientation(Qt::Vertical),
|
||||
alignment(Qt::AlignHCenter | Qt::AlignTop),
|
||||
calculateSizeRequested(true) // First time always true
|
||||
|
@ -452,7 +452,7 @@ void Icon::calculateSize(const QStyleOptionGraphicsItem *option)
|
|||
update();
|
||||
}
|
||||
|
||||
void Icon::Private::drawBackground(QPainter *painter)
|
||||
void Icon::Private::drawBackground(QPainter *painter, IconState state)
|
||||
{
|
||||
QString element;
|
||||
if (svgElements & Private::SvgBackground) {
|
||||
|
@ -460,8 +460,6 @@ void Icon::Private::drawBackground(QPainter *painter)
|
|||
}
|
||||
|
||||
switch (state) {
|
||||
case Private::NoState:
|
||||
break;
|
||||
case Private::HoverState:
|
||||
if (svgElements & Private::SvgBackgroundHover) {
|
||||
element = "background-hover";
|
||||
|
@ -474,6 +472,8 @@ void Icon::Private::drawBackground(QPainter *painter)
|
|||
element = "background-hover";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!element.isEmpty()) {
|
||||
|
@ -481,7 +481,7 @@ void Icon::Private::drawBackground(QPainter *painter)
|
|||
}
|
||||
}
|
||||
|
||||
void Icon::Private::drawForeground(QPainter *painter)
|
||||
void Icon::Private::drawForeground(QPainter *painter, IconState state)
|
||||
{
|
||||
QString element;
|
||||
if (svgElements & Private::SvgForeground) {
|
||||
|
@ -489,8 +489,6 @@ void Icon::Private::drawForeground(QPainter *painter)
|
|||
}
|
||||
|
||||
switch (state) {
|
||||
case Private::NoState:
|
||||
break;
|
||||
case Private::HoverState:
|
||||
if (svgElements & Private::SvgForegroundHover) {
|
||||
element = "foreground-hover";
|
||||
|
@ -503,6 +501,8 @@ void Icon::Private::drawForeground(QPainter *painter)
|
|||
element = "foreground-hover";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!element.isEmpty()) {
|
||||
|
@ -510,7 +510,7 @@ void Icon::Private::drawForeground(QPainter *painter)
|
|||
}
|
||||
}
|
||||
|
||||
QPixmap Icon::Private::decoration(const QStyleOptionGraphicsItem *option) const
|
||||
QPixmap Icon::Private::decoration(const QStyleOptionGraphicsItem *option, bool useHoverEffect) const
|
||||
{
|
||||
QPixmap result;
|
||||
|
||||
|
@ -519,19 +519,15 @@ QPixmap Icon::Private::decoration(const QStyleOptionGraphicsItem *option) const
|
|||
const QSize size = icon.actualSize(iconSize.toSize(), mode, state);
|
||||
result = icon.pixmap(size, mode, state);
|
||||
|
||||
if (!result.isNull())
|
||||
if (!result.isNull() && useHoverEffect)
|
||||
{
|
||||
// Apply the configured hover effect NOTE: This has no visible effect because we
|
||||
// do drawForeground() -MB
|
||||
if (option->state & QStyle::State_MouseOver) {
|
||||
KIconEffect *effect = KIconLoader::global()->iconEffect();
|
||||
KIconEffect *effect = KIconLoader::global()->iconEffect();
|
||||
|
||||
// Note that in KIconLoader terminology, active = hover.
|
||||
// ### We're assuming that the icon group is desktop/filemanager, since this
|
||||
// is KFileItemDelegate.
|
||||
if (effect->hasEffect(KIconLoader::Desktop, KIconLoader::ActiveState)) {
|
||||
result = effect->apply(result, KIconLoader::Desktop, KIconLoader::ActiveState);
|
||||
}
|
||||
// Note that in KIconLoader terminology, active = hover.
|
||||
// ### We're assuming that the icon group is desktop/filemanager, since this
|
||||
// is KFileItemDelegate.
|
||||
if (effect->hasEffect(KIconLoader::Desktop, KIconLoader::ActiveState)) {
|
||||
result = effect->apply(result, KIconLoader::Desktop, KIconLoader::ActiveState);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -791,7 +787,18 @@ void Icon::paintWidget(QPainter *painter, const QStyleOptionGraphicsItem *option
|
|||
|
||||
// Compute the metrics, and lay out the text items
|
||||
// ========================================================================
|
||||
QPixmap icon = d->decoration(option);
|
||||
Private::IconState state = Private::NoState;
|
||||
if (d->states & Private::ManualPressedState) {
|
||||
state = Private::PressedState;
|
||||
} else if (d->states & Private::PressedState) {
|
||||
if (d->states & Private::HoverState) {
|
||||
state = Private::PressedState;
|
||||
}
|
||||
} else if (d->states & Private::HoverState) {
|
||||
state = Private::HoverState;
|
||||
}
|
||||
|
||||
QPixmap icon = d->decoration(option, state != Private::NoState);
|
||||
const QPointF iconPos = d->iconPosition(option, icon);
|
||||
|
||||
QTextLayout labelLayout, infoLayout;
|
||||
|
@ -799,12 +806,12 @@ void Icon::paintWidget(QPainter *painter, const QStyleOptionGraphicsItem *option
|
|||
d->layoutTextItems(option, icon, &labelLayout, &infoLayout, &textBoundingRect);
|
||||
|
||||
d->svg.resize(size());
|
||||
d->drawBackground(painter);
|
||||
d->drawBackground(painter, state);
|
||||
|
||||
// draw icon
|
||||
painter->drawPixmap(iconPos, icon);
|
||||
|
||||
d->drawForeground(painter);
|
||||
d->drawForeground(painter, state);
|
||||
|
||||
// Draw corner actions
|
||||
foreach (IconAction *action, d->cornerActions) {
|
||||
|
@ -905,7 +912,7 @@ void Icon::setIconSize(int w, int h)
|
|||
|
||||
bool Icon::isDown()
|
||||
{
|
||||
return d->state == Private::PressedState;
|
||||
return d->states & Private::PressedState;
|
||||
}
|
||||
|
||||
void Icon::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
|
@ -915,47 +922,67 @@ void Icon::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|||
return;
|
||||
}
|
||||
|
||||
//kDebug();
|
||||
d->states |= Private::PressedState;
|
||||
|
||||
bool handled = false;
|
||||
foreach (IconAction *action, d->cornerActions) {
|
||||
action->event(event->type(), event->pos());
|
||||
handled = action->event(event->type(), event->pos());
|
||||
if (handled) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
d->state = Private::PressedState;
|
||||
emit pressed(true);
|
||||
if (!handled) {
|
||||
emit pressed(true);
|
||||
}
|
||||
|
||||
event->accept();
|
||||
update();
|
||||
}
|
||||
|
||||
void Icon::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
if (~d->states & Private::PressedState) {
|
||||
Widget::mouseMoveEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (boundingRect().contains(event->pos())) {
|
||||
if (~d->states & Private::HoverState) {
|
||||
d->states |= Private::HoverState;
|
||||
update();
|
||||
}
|
||||
} else {
|
||||
if (d->states & Private::HoverState) {
|
||||
d->states &= ~Private::HoverState;
|
||||
update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Icon::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
//kDebug();
|
||||
bool inside = boundingRect().contains(event->pos());
|
||||
Private::ButtonState was = d->state;
|
||||
|
||||
if (inside) {
|
||||
d->state = Private::HoverState;
|
||||
|
||||
foreach (IconAction *action, d->cornerActions) {
|
||||
if (action->event(event->type(), event->pos())) {
|
||||
inside = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
d->state = Private::NoState;
|
||||
if (~d->states & Private::PressedState) {
|
||||
Widget::mouseMoveEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (was == Private::PressedState) {
|
||||
emit pressed(false);
|
||||
d->states &= ~Private::PressedState;
|
||||
|
||||
if (inside) {
|
||||
bool handled = false;
|
||||
foreach (IconAction *action, d->cornerActions) {
|
||||
if (action->event(event->type(), event->pos())) {
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!handled) {
|
||||
if (boundingRect().contains(event->pos())) {
|
||||
emit clicked();
|
||||
}
|
||||
d->state = Private::NoState;
|
||||
emit pressed(false);
|
||||
}
|
||||
|
||||
event->ignore();
|
||||
update();
|
||||
}
|
||||
|
||||
|
@ -966,7 +993,9 @@ void Icon::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
|
|||
action->event(event->type(), event->pos());
|
||||
}
|
||||
|
||||
d->state = Private::HoverState;
|
||||
d->states |= Private::HoverState;
|
||||
update();
|
||||
|
||||
Widget::hoverEnterEvent(event);
|
||||
}
|
||||
|
||||
|
@ -977,17 +1006,25 @@ void Icon::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
|
|||
action->event(event->type(), event->pos());
|
||||
}
|
||||
|
||||
d->state = Private::NoState;
|
||||
d->states &= ~Private::HoverState;
|
||||
update();
|
||||
|
||||
Widget::hoverLeaveEvent(event);
|
||||
}
|
||||
|
||||
void Icon::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
void Icon::setPressed(bool pressed)
|
||||
{
|
||||
if (d->state == Private::PressedState) {
|
||||
d->state = Private::HoverState;
|
||||
if (pressed) {
|
||||
d->states |= Private::ManualPressedState;
|
||||
} else {
|
||||
d->states &= ~Private::ManualPressedState;
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
Widget::mouseMoveEvent(event);
|
||||
void Icon::setUnpressed()
|
||||
{
|
||||
setPressed(false);
|
||||
}
|
||||
|
||||
void Icon::setAlignment(Qt::Alignment alignment)
|
||||
|
|
|
@ -155,6 +155,19 @@ public:
|
|||
|
||||
Qt::Orientations expandingDirections() const;
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* Sets the appearance of the icon to pressed or restores the appearance
|
||||
* to normal. This does not simulate a mouse button press.
|
||||
* @param pressed whether to appear as pressed (true) or as normal (false)
|
||||
*/
|
||||
void setPressed(bool pressed=true);
|
||||
|
||||
/**
|
||||
* Shortcut for setPressed(false)
|
||||
*/
|
||||
void setUnpressed();
|
||||
|
||||
protected:
|
||||
void paintWidget(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
|
||||
|
||||
|
|
|
@ -92,17 +92,26 @@ class Icon::Private
|
|||
public:
|
||||
enum MarginType { ItemMargin = 0, TextMargin, IconMargin, NMargins };
|
||||
|
||||
enum IconState
|
||||
{
|
||||
NoState = 0,
|
||||
HoverState = 1,
|
||||
PressedState = 2,
|
||||
ManualPressedState = 4
|
||||
};
|
||||
Q_DECLARE_FLAGS(IconStates, IconState);
|
||||
|
||||
public:
|
||||
Private();
|
||||
~Private();
|
||||
|
||||
void drawBackground(QPainter *painter);
|
||||
void drawForeground(QPainter *painter);
|
||||
void drawBackground(QPainter *painter, IconState state);
|
||||
void drawForeground(QPainter *painter, IconState state);
|
||||
void drawText(QPainter *painter);
|
||||
void drawTextItems(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||
const QTextLayout &labelLayout, const QTextLayout &infoLayout) const;
|
||||
|
||||
QPixmap decoration(const QStyleOptionGraphicsItem *option) const;
|
||||
QPixmap decoration(const QStyleOptionGraphicsItem *option, bool useHoverEffect) const;
|
||||
QPointF iconPosition(const QStyleOptionGraphicsItem *option, const QPixmap &pixmap) const;
|
||||
|
||||
QSizeF displaySizeHint(const QStyleOptionGraphicsItem *option) const;
|
||||
|
@ -158,13 +167,6 @@ public:
|
|||
LastIconPosition
|
||||
};
|
||||
|
||||
enum ButtonState
|
||||
{
|
||||
NoState,
|
||||
HoverState,
|
||||
PressedState
|
||||
};
|
||||
|
||||
QString text;
|
||||
QString infoText;
|
||||
Svg svg;
|
||||
|
@ -172,7 +174,7 @@ public:
|
|||
QSizeF size;
|
||||
QSizeF iconSize;
|
||||
QIcon icon;
|
||||
ButtonState state;
|
||||
IconStates states;
|
||||
Qt::Orientation orientation;
|
||||
Qt::Alignment alignment;
|
||||
bool calculateSizeRequested;
|
||||
|
@ -184,6 +186,8 @@ public:
|
|||
Margin *activeMargins;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(Icon::Private::IconStates);
|
||||
|
||||
// Inline methods
|
||||
void Icon::Private::setLayoutOptions(QTextLayout &layout, const QStyleOptionGraphicsItem *option) const
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue
Block a user