Port IconItem to native QSGTexture
Port IconItem to native QSGTexture including the animation. This will save constantly uploading a new texture to OpenGL throughout the animation. REVIEW: 116024
This commit is contained in:
parent
5600cb0fea
commit
096c6d247b
@ -21,6 +21,7 @@ set(corebindings_SRCS
|
|||||||
datasource.cpp
|
datasource.cpp
|
||||||
# runnermodel.cpp
|
# runnermodel.cpp
|
||||||
svgitem.cpp
|
svgitem.cpp
|
||||||
|
fadingnode.cpp
|
||||||
framesvgitem.cpp
|
framesvgitem.cpp
|
||||||
tooltip.cpp
|
tooltip.cpp
|
||||||
tooltipdialog.cpp
|
tooltipdialog.cpp
|
||||||
|
145
src/declarativeimports/core/fadingnode.cpp
Normal file
145
src/declarativeimports/core/fadingnode.cpp
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 David Edmundson <davidedmundson@kde.org>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "fadingnode_p.h"
|
||||||
|
|
||||||
|
#include <QSGSimpleMaterialShader>
|
||||||
|
#include <QtOpenGL/QGLContext>
|
||||||
|
#include <QtOpenGL/QGLFunctions>
|
||||||
|
|
||||||
|
struct FadingMaterialState
|
||||||
|
{
|
||||||
|
QSGTexture *source;
|
||||||
|
QSGTexture *target;
|
||||||
|
qreal progress;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FadingMaterialShader : public QSGSimpleMaterialShader<FadingMaterialState>
|
||||||
|
{
|
||||||
|
QSG_DECLARE_SIMPLE_SHADER(FadingMaterialShader, FadingMaterialState)
|
||||||
|
public:
|
||||||
|
virtual const char* fragmentShader() const;
|
||||||
|
virtual const char* vertexShader() const;
|
||||||
|
|
||||||
|
virtual void updateState(const FadingMaterialState* newState, const FadingMaterialState* oldState);
|
||||||
|
virtual QList<QByteArray> attributes() const;
|
||||||
|
|
||||||
|
virtual void initialize();
|
||||||
|
private:
|
||||||
|
QOpenGLFunctions *glFuncs;
|
||||||
|
int m_progressId;
|
||||||
|
};
|
||||||
|
|
||||||
|
QList<QByteArray> FadingMaterialShader::attributes() const
|
||||||
|
{
|
||||||
|
return QList<QByteArray>() << "qt_Vertex" << "qt_MultiTexCoord0";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* FadingMaterialShader::vertexShader() const
|
||||||
|
{
|
||||||
|
return "uniform highp mat4 qt_Matrix;"
|
||||||
|
"attribute highp vec4 qt_Vertex;"
|
||||||
|
"attribute highp vec2 qt_MultiTexCoord0;"
|
||||||
|
"varying highp vec2 v_coord;"
|
||||||
|
"void main() {"
|
||||||
|
" v_coord = qt_MultiTexCoord0;"
|
||||||
|
" gl_Position = qt_Matrix * qt_Vertex;"
|
||||||
|
" }";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* FadingMaterialShader::fragmentShader() const
|
||||||
|
{
|
||||||
|
return "varying highp vec2 v_coord;"
|
||||||
|
"uniform sampler2D u_src;"
|
||||||
|
"uniform sampler2D u_target;"
|
||||||
|
"uniform highp float u_transitionProgress;"
|
||||||
|
"uniform lowp float qt_Opacity;"
|
||||||
|
"void main() {"
|
||||||
|
"lowp vec4 tex1 = texture2D(u_target, v_coord);"
|
||||||
|
"lowp vec4 tex2 = texture2D(u_src, v_coord);"
|
||||||
|
"gl_FragColor.rgb = mix(tex1.rgb, tex2.rgb, u_transitionProgress);"
|
||||||
|
"gl_FragColor.a = mix(tex1.a, tex2.a, u_transitionProgress) * qt_Opacity;"
|
||||||
|
"}";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FadingMaterialShader::updateState(const FadingMaterialState* newState, const FadingMaterialState* oldState)
|
||||||
|
{
|
||||||
|
if (!oldState || oldState->source != newState->source) {
|
||||||
|
glFuncs->glActiveTexture(GL_TEXTURE1);
|
||||||
|
newState->target->bind();
|
||||||
|
// reset the active texture back to 0 after we changed it to something else
|
||||||
|
glFuncs->glActiveTexture(GL_TEXTURE0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!oldState || oldState->target != newState->target) {
|
||||||
|
glFuncs->glActiveTexture(GL_TEXTURE0);
|
||||||
|
newState->source->bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!oldState || oldState->progress != newState->progress) {
|
||||||
|
program()->setUniformValue(m_progressId, (GLfloat) newState->progress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadingMaterialShader::initialize()
|
||||||
|
{
|
||||||
|
QSGSimpleMaterialShader< FadingMaterialState >::initialize();
|
||||||
|
glFuncs = QOpenGLContext::currentContext()->functions();
|
||||||
|
program()->bind();
|
||||||
|
program()->setUniformValue("u_src", 0);
|
||||||
|
program()->setUniformValue("u_target", 1);
|
||||||
|
m_progressId = program()->uniformLocation("u_transitionProgress");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FadingNode::FadingNode(QSGTexture *source, QSGTexture *target):
|
||||||
|
m_source(source),
|
||||||
|
m_target(target)
|
||||||
|
{
|
||||||
|
QSGSimpleMaterial<FadingMaterialState> *m = FadingMaterialShader::createMaterial();
|
||||||
|
m->setFlag(QSGMaterial::Blending);
|
||||||
|
setMaterial(m);
|
||||||
|
setFlag(OwnsMaterial, true);
|
||||||
|
setProgress(1.0);
|
||||||
|
|
||||||
|
QSGGeometry *g = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4);
|
||||||
|
QSGGeometry::updateTexturedRectGeometry(g, QRect(), QRect());
|
||||||
|
setGeometry(g);
|
||||||
|
setFlag(QSGNode::OwnsGeometry, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
FadingNode::~FadingNode()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadingNode::setRect(const QRectF &bounds)
|
||||||
|
{
|
||||||
|
QSGGeometry::updateTexturedRectGeometry(geometry(), bounds, QRectF(0, 0, 1, 1));
|
||||||
|
markDirty(QSGNode::DirtyGeometry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadingNode::setProgress(qreal progress)
|
||||||
|
{
|
||||||
|
QSGSimpleMaterial<FadingMaterialState> *m = static_cast<QSGSimpleMaterial<FadingMaterialState>*>(material());
|
||||||
|
m->state()->source = m_source.data();
|
||||||
|
m->state()->target = m_target.data();
|
||||||
|
m->state()->progress = progress;
|
||||||
|
markDirty(QSGNode::DirtyMaterial);
|
||||||
|
}
|
50
src/declarativeimports/core/fadingnode_p.h
Normal file
50
src/declarativeimports/core/fadingnode_p.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 David Edmundson <davidedmundson@kde.org>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FADINGNODE_H
|
||||||
|
#define FADINGNODE_H
|
||||||
|
|
||||||
|
#include <QSGGeometryNode>
|
||||||
|
#include <QSGTexture>
|
||||||
|
#include <QRectF>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This node fades between two textures using a shader
|
||||||
|
*/
|
||||||
|
|
||||||
|
class FadingNode : public QSGGeometryNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Ownership of the textures is transferred to the node
|
||||||
|
*/
|
||||||
|
FadingNode(QSGTexture *source, QSGTexture *target);
|
||||||
|
~FadingNode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the progress fading between source and target
|
||||||
|
*/
|
||||||
|
void setProgress(qreal progress);
|
||||||
|
void setRect(const QRectF &bounds);
|
||||||
|
private:
|
||||||
|
QScopedPointer<QSGTexture> m_source;
|
||||||
|
QScopedPointer<QSGTexture> m_target;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PLASMAFADINGNODE_H
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012 Marco Martin <mart@kde.org>
|
* Copyright 2012 Marco Martin <mart@kde.org>
|
||||||
|
* Copyright 2014 David Edmundson <davidedmudnson@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 as
|
* it under the terms of the GNU Library General Public License as
|
||||||
@ -23,138 +24,21 @@
|
|||||||
#include <QPaintEngine>
|
#include <QPaintEngine>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QPropertyAnimation>
|
#include <QPropertyAnimation>
|
||||||
|
#include <QPixmap>
|
||||||
|
#include <QSGSimpleTextureNode>
|
||||||
|
#include <QQuickWindow>
|
||||||
|
#include <QPixmap>
|
||||||
|
|
||||||
#include <kiconloader.h>
|
#include <kiconloader.h>
|
||||||
#include <kiconeffect.h>
|
#include <kiconeffect.h>
|
||||||
|
|
||||||
#include <plasma/svg.h>
|
#include <plasma/svg.h>
|
||||||
|
|
||||||
QPixmap transition(const QPixmap &from, const QPixmap &to, qreal amount)
|
#include "fadingnode_p.h"
|
||||||
{
|
#include "svgtexturenode.h"
|
||||||
if (from.isNull() && to.isNull()) {
|
|
||||||
return from;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qFuzzyCompare(amount + 1, qreal(1.0))) {
|
|
||||||
return from;
|
|
||||||
}
|
|
||||||
|
|
||||||
QRect startRect(from.rect());
|
|
||||||
QRect targetRect(to.rect());
|
|
||||||
QSize pixmapSize = startRect.size().expandedTo(targetRect.size());
|
|
||||||
QRect toRect = QRect(QPoint(0, 0), pixmapSize);
|
|
||||||
targetRect.moveCenter(toRect.center());
|
|
||||||
startRect.moveCenter(toRect.center());
|
|
||||||
|
|
||||||
//paint to in the center of from
|
|
||||||
QColor color;
|
|
||||||
color.setAlphaF(amount);
|
|
||||||
|
|
||||||
// If the native paint engine supports Porter/Duff compositing and CompositionMode_Plus
|
|
||||||
QPaintEngine *paintEngine = from.paintEngine();
|
|
||||||
if (paintEngine &&
|
|
||||||
paintEngine->hasFeature(QPaintEngine::PorterDuff) &&
|
|
||||||
paintEngine->hasFeature(QPaintEngine::BlendModes)) {
|
|
||||||
QPixmap startPixmap(pixmapSize);
|
|
||||||
startPixmap.fill(Qt::transparent);
|
|
||||||
|
|
||||||
QPixmap targetPixmap(pixmapSize);
|
|
||||||
targetPixmap.fill(Qt::transparent);
|
|
||||||
|
|
||||||
QPainter p;
|
|
||||||
p.begin(&targetPixmap);
|
|
||||||
p.drawPixmap(targetRect, to);
|
|
||||||
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
|
||||||
p.fillRect(targetRect, color);
|
|
||||||
p.end();
|
|
||||||
|
|
||||||
p.begin(&startPixmap);
|
|
||||||
p.drawPixmap(startRect, from);
|
|
||||||
p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
|
|
||||||
p.fillRect(startRect, color);
|
|
||||||
p.setCompositionMode(QPainter::CompositionMode_Plus);
|
|
||||||
p.drawPixmap(targetRect, targetPixmap);
|
|
||||||
p.end();
|
|
||||||
|
|
||||||
return startPixmap;
|
|
||||||
}
|
|
||||||
#warning Cannot use XRender with QPixmap anymore. Find equivalent with Qt API.
|
|
||||||
#if 0 // HAVE_X11 && defined(HAVE_XRENDER)
|
|
||||||
// We have Xrender support
|
|
||||||
else if (paintEngine && paintEngine->hasFeature(QPaintEngine::PorterDuff)) {
|
|
||||||
// QX11PaintEngine doesn't implement CompositionMode_Plus in Qt 4.3,
|
|
||||||
// which we need to be able to do a transition from one pixmap to
|
|
||||||
// another.
|
|
||||||
//
|
|
||||||
// In order to avoid the overhead of converting the pixmaps to images
|
|
||||||
// and doing the operation entirely in software, this function has a
|
|
||||||
// specialized path for X11 that uses Xrender directly to do the
|
|
||||||
// transition. This operation can be fully accelerated in HW.
|
|
||||||
//
|
|
||||||
// This specialization can be removed when QX11PaintEngine supports
|
|
||||||
// CompositionMode_Plus.
|
|
||||||
QPixmap source(targetPixmap), destination(startPixmap);
|
|
||||||
|
|
||||||
source.detach();
|
|
||||||
destination.detach();
|
|
||||||
|
|
||||||
Display *dpy = QX11Info::display();
|
|
||||||
|
|
||||||
XRenderPictFormat *format = XRenderFindStandardFormat(dpy, PictStandardA8);
|
|
||||||
XRenderPictureAttributes pa;
|
|
||||||
pa.repeat = 1; // RepeatNormal
|
|
||||||
|
|
||||||
// Create a 1x1 8 bit repeating alpha picture
|
|
||||||
Pixmap pixmap = XCreatePixmap(dpy, destination.handle(), 1, 1, 8);
|
|
||||||
Picture alpha = XRenderCreatePicture(dpy, pixmap, format, CPRepeat, &pa);
|
|
||||||
XFreePixmap(dpy, pixmap);
|
|
||||||
|
|
||||||
// Fill the alpha picture with the opacity value
|
|
||||||
XRenderColor xcolor;
|
|
||||||
xcolor.alpha = quint16(0xffff * amount);
|
|
||||||
XRenderFillRectangle(dpy, PictOpSrc, alpha, &xcolor, 0, 0, 1, 1);
|
|
||||||
|
|
||||||
// Reduce the alpha of the destination with 1 - opacity
|
|
||||||
XRenderComposite(dpy, PictOpOutReverse, alpha, None, destination.x11PictureHandle(),
|
|
||||||
0, 0, 0, 0, 0, 0, destination.width(), destination.height());
|
|
||||||
|
|
||||||
// Add source * opacity to the destination
|
|
||||||
XRenderComposite(dpy, PictOpAdd, source.x11PictureHandle(), alpha,
|
|
||||||
destination.x11PictureHandle(),
|
|
||||||
toRect.x(), toRect.y(), 0, 0, 0, 0, destination.width(), destination.height());
|
|
||||||
|
|
||||||
XRenderFreePicture(dpy, alpha);
|
|
||||||
return destination;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else {
|
|
||||||
// Fall back to using QRasterPaintEngine to do the transition.
|
|
||||||
QImage under(pixmapSize, QImage::Format_ARGB32_Premultiplied);
|
|
||||||
under.fill(Qt::transparent);
|
|
||||||
QImage over(pixmapSize, QImage::Format_ARGB32_Premultiplied);
|
|
||||||
over.fill(Qt::transparent);
|
|
||||||
|
|
||||||
QPainter p;
|
|
||||||
p.begin(&over);
|
|
||||||
p.drawPixmap(targetRect, to);
|
|
||||||
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
|
||||||
p.fillRect(over.rect(), color);
|
|
||||||
p.end();
|
|
||||||
|
|
||||||
p.begin(&under);
|
|
||||||
p.drawPixmap(startRect, from);
|
|
||||||
p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
|
|
||||||
p.fillRect(startRect, color);
|
|
||||||
p.setCompositionMode(QPainter::CompositionMode_Plus);
|
|
||||||
p.drawImage(toRect.topLeft(), over);
|
|
||||||
p.end();
|
|
||||||
|
|
||||||
return QPixmap::fromImage(under);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IconItem::IconItem(QQuickItem *parent)
|
IconItem::IconItem(QQuickItem *parent)
|
||||||
: QQuickPaintedItem(parent),
|
: QQuickItem(parent),
|
||||||
m_svgIcon(0),
|
m_svgIcon(0),
|
||||||
m_smooth(false),
|
m_smooth(false),
|
||||||
m_active(false),
|
m_active(false),
|
||||||
@ -173,7 +57,7 @@ IconItem::IconItem(QQuickItem *parent)
|
|||||||
this, SLOT(animationFinished()));
|
this, SLOT(animationFinished()));
|
||||||
m_animation->setTargetObject(this);
|
m_animation->setTargetObject(this);
|
||||||
m_animation->setEasingCurve(QEasingCurve::InOutQuad);
|
m_animation->setEasingCurve(QEasingCurve::InOutQuad);
|
||||||
m_animation->setDuration(250);
|
m_animation->setDuration(250); //FIXME from theme
|
||||||
|
|
||||||
setFlag(ItemHasContents, true);
|
setFlag(ItemHasContents, true);
|
||||||
|
|
||||||
@ -303,38 +187,60 @@ bool IconItem::isValid() const
|
|||||||
return !m_icon.isNull() || m_svgIcon || !m_pixmapIcon.isNull() || !m_imageIcon.isNull();
|
return !m_icon.isNull() || m_svgIcon || !m_pixmapIcon.isNull() || !m_imageIcon.isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IconItem::paint(QPainter *painter)
|
QSGNode* IconItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData)
|
||||||
{
|
{
|
||||||
if (m_iconPixmaps.isEmpty()) {
|
Q_UNUSED(updatePaintNodeData)
|
||||||
return;
|
|
||||||
|
if (m_iconPixmap.isNull()) {
|
||||||
|
delete oldNode;
|
||||||
|
return Q_NULLPTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
painter->save();
|
|
||||||
painter->setRenderHint(QPainter::Antialiasing, m_smooth);
|
|
||||||
painter->setRenderHint(QPainter::SmoothPixmapTransform, m_smooth);
|
|
||||||
|
|
||||||
const int iconSize = adjustedSize(qMin(boundingRect().size().width(), boundingRect().size().height()));
|
|
||||||
|
|
||||||
const QRect destRect(QPointF(boundingRect().center() - QPointF(iconSize / 2, iconSize / 2)).toPoint(),
|
|
||||||
QSize(iconSize, iconSize));
|
|
||||||
|
|
||||||
if (m_animation->state() == QAbstractAnimation::Running) {
|
if (m_animation->state() == QAbstractAnimation::Running) {
|
||||||
QPixmap result = m_iconPixmaps.first();
|
FadingNode *animatingNode = static_cast<FadingNode*>(oldNode);
|
||||||
result = transition(result,
|
|
||||||
m_iconPixmaps.last(), m_animValue);
|
if (!animatingNode || m_textureChanged) {
|
||||||
painter->drawPixmap(destRect, result);
|
delete oldNode;
|
||||||
//simpler logic for just paint
|
|
||||||
} else {
|
QSGTexture *source = window()->createTextureFromImage(m_iconPixmap.toImage());
|
||||||
painter->drawPixmap(destRect, m_iconPixmaps.first());
|
QSGTexture *target = window()->createTextureFromImage(m_oldIconPixmap.toImage());
|
||||||
|
animatingNode = new FadingNode(source, target);
|
||||||
|
m_sizeChanged = true;
|
||||||
|
m_textureChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
painter->restore();
|
animatingNode->setProgress(m_animValue);
|
||||||
}
|
|
||||||
|
|
||||||
void IconItem::animationFinished()
|
if (m_sizeChanged) {
|
||||||
{
|
const int iconSize = adjustedSize(qMin(boundingRect().size().width(), boundingRect().size().height()));
|
||||||
while (m_iconPixmaps.count() > 1) {
|
const QRect destRect(QPointF(boundingRect().center() - QPointF(iconSize/2, iconSize/2)).toPoint(),
|
||||||
m_iconPixmaps.pop_front();
|
QSize(iconSize, iconSize));
|
||||||
|
|
||||||
|
animatingNode->setRect(destRect);
|
||||||
|
m_sizeChanged = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return animatingNode;
|
||||||
|
} else {
|
||||||
|
Plasma::SVGTextureNode *textureNode = static_cast<Plasma::SVGTextureNode*>(oldNode);
|
||||||
|
|
||||||
|
if (!textureNode || m_textureChanged) {
|
||||||
|
delete oldNode;
|
||||||
|
textureNode = new Plasma::SVGTextureNode;
|
||||||
|
textureNode->setTexture(window()->createTextureFromImage(m_iconPixmap.toImage()));
|
||||||
|
m_sizeChanged = true;
|
||||||
|
m_textureChanged = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_sizeChanged) {
|
||||||
|
const int iconSize = adjustedSize(qMin(boundingRect().size().width(), boundingRect().size().height()));
|
||||||
|
const QRect destRect(QPointF(boundingRect().center() - QPointF(iconSize/2, iconSize/2)).toPoint(),
|
||||||
|
QSize(iconSize, iconSize));
|
||||||
|
|
||||||
|
textureNode->setRect(destRect);
|
||||||
|
m_sizeChanged = false;
|
||||||
|
}
|
||||||
|
return textureNode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,6 +250,12 @@ void IconItem::valueChanged(const QVariant &value)
|
|||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IconItem::animationFinished()
|
||||||
|
{
|
||||||
|
m_oldIconPixmap = QPixmap();
|
||||||
|
m_textureChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
int IconItem::adjustedSize(int size)
|
int IconItem::adjustedSize(int size)
|
||||||
{
|
{
|
||||||
//FIXME: Heuristic: allow 24x24 for icons/ that are in the systray(ugly)
|
//FIXME: Heuristic: allow 24x24 for icons/ that are in the systray(ugly)
|
||||||
@ -390,7 +302,7 @@ void IconItem::loadPixmap()
|
|||||||
} else if (!m_imageIcon.isNull()) {
|
} else if (!m_imageIcon.isNull()) {
|
||||||
result = QPixmap::fromImage(m_imageIcon);
|
result = QPixmap::fromImage(m_imageIcon);
|
||||||
} else {
|
} else {
|
||||||
m_iconPixmaps.clear();
|
m_iconPixmap = QPixmap();
|
||||||
m_animation->stop();
|
m_animation->stop();
|
||||||
update();
|
update();
|
||||||
return;
|
return;
|
||||||
@ -402,28 +314,17 @@ void IconItem::loadPixmap()
|
|||||||
result = KIconLoader::global()->iconEffect()->apply(result, KIconLoader::Desktop, KIconLoader::ActiveState);
|
result = KIconLoader::global()->iconEffect()->apply(result, KIconLoader::Desktop, KIconLoader::ActiveState);
|
||||||
}
|
}
|
||||||
|
|
||||||
//this happen only when loadPixmap has been called when an anim is running
|
m_oldIconPixmap = m_iconPixmap;
|
||||||
while (m_iconPixmaps.count() > 1) {
|
m_iconPixmap = result;
|
||||||
m_iconPixmaps.pop_front();
|
m_textureChanged = true;
|
||||||
}
|
|
||||||
|
|
||||||
m_iconPixmaps << result;
|
//don't animate initial setting
|
||||||
//if there is only one image, don't animate
|
if (!m_oldIconPixmap.isNull()) {
|
||||||
//if an animation was already running, immediate transition, to not overload
|
|
||||||
if (m_iconPixmaps.first().size() != result.size()) {
|
|
||||||
m_animation->stop();
|
|
||||||
if (m_iconPixmaps.count() > 1) {
|
|
||||||
m_iconPixmaps.pop_front();
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (m_animation->state() == QAbstractAnimation::Running) {
|
|
||||||
m_animation->stop();
|
|
||||||
m_iconPixmaps.pop_front();
|
|
||||||
|
|
||||||
} else if (m_iconPixmaps.count() > 1) {
|
|
||||||
m_animation->setStartValue((qreal)0);
|
m_animation->setStartValue((qreal)0);
|
||||||
m_animation->setEndValue((qreal)1);
|
m_animation->setEndValue((qreal)1);
|
||||||
m_animation->start();
|
m_animation->start();
|
||||||
|
} else {
|
||||||
|
m_animValue = 1.0;
|
||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
@ -433,7 +334,10 @@ void IconItem::geometryChanged(const QRectF &newGeometry,
|
|||||||
{
|
{
|
||||||
if (newGeometry.size() != oldGeometry.size()) {
|
if (newGeometry.size() != oldGeometry.size()) {
|
||||||
if (newGeometry.width() > 0 && newGeometry.height() > 0) {
|
if (newGeometry.width() > 0 && newGeometry.height() > 0) {
|
||||||
|
m_sizeChanged = true;
|
||||||
|
if (!m_loadPixmapTimer.isActive()) {
|
||||||
m_loadPixmapTimer.start();
|
m_loadPixmapTimer.start();
|
||||||
|
}
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012 Marco Martin <mart@kde.org>
|
* Copyright 2012 Marco Martin <mart@kde.org>
|
||||||
|
* Copyright 2014 David Edmundson <davidedmudnson@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 as
|
* it under the terms of the GNU Library General Public License as
|
||||||
@ -21,7 +22,7 @@
|
|||||||
#define ICONITEM_H
|
#define ICONITEM_H
|
||||||
|
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QQuickPaintedItem>
|
#include <QQuickItem>
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
@ -33,7 +34,7 @@ namespace Plasma
|
|||||||
class Svg;
|
class Svg;
|
||||||
}
|
}
|
||||||
|
|
||||||
class IconItem : public QQuickPaintedItem
|
class IconItem : public QQuickItem
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -58,7 +59,7 @@ public:
|
|||||||
|
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
|
|
||||||
void paint(QPainter *painter);
|
QSGNode* updatePaintNode(QSGNode * oldNode, UpdatePaintNodeData * updatePaintNodeData);
|
||||||
|
|
||||||
void geometryChanged(const QRectF &newGeometry,
|
void geometryChanged(const QRectF &newGeometry,
|
||||||
const QRectF &oldGeometry);
|
const QRectF &oldGeometry);
|
||||||
@ -90,9 +91,12 @@ private:
|
|||||||
bool m_smooth;
|
bool m_smooth;
|
||||||
bool m_active;
|
bool m_active;
|
||||||
|
|
||||||
//This list contains at most 2 sources, when a pixmap transition is due,
|
bool m_textureChanged;
|
||||||
//a new pixmap is queued, the old one is removed when the animation finishes
|
bool m_sizeChanged;
|
||||||
QList<QPixmap> m_iconPixmaps;
|
|
||||||
|
QPixmap m_iconPixmap;
|
||||||
|
QPixmap m_oldIconPixmap;
|
||||||
|
|
||||||
|
|
||||||
//animation on pixmap change
|
//animation on pixmap change
|
||||||
QPropertyAnimation *m_animation;
|
QPropertyAnimation *m_animation;
|
||||||
|
Loading…
Reference in New Issue
Block a user