e3149f9c77
The sizing we get is messed up, and the first pixmap (which we try to use) has size 0x0. Needs fixing.
331 lines
8.8 KiB
C++
331 lines
8.8 KiB
C++
/*
|
|
* Copyright 2012 Marco Martin <mart@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.
|
|
*/
|
|
|
|
#include "iconitem.h"
|
|
|
|
#include <KIconLoader>
|
|
#include <KIconEffect>
|
|
#include <QPainter>
|
|
#include <QPropertyAnimation>
|
|
|
|
#include <plasma/paintutils.h>
|
|
#include <plasma/svg.h>
|
|
|
|
#include <QDebug>
|
|
|
|
IconItem::IconItem(QQuickItem *parent)
|
|
: QQuickPaintedItem(parent),
|
|
m_svgIcon(0),
|
|
m_smooth(false),
|
|
m_active(false),
|
|
m_animValue(0)
|
|
{
|
|
m_animation = new QPropertyAnimation(this);
|
|
connect(m_animation, SIGNAL(valueChanged(QVariant)),
|
|
this, SLOT(valueChanged(QVariant)));
|
|
connect(m_animation, SIGNAL(finished()),
|
|
this, SLOT(animationFinished()));
|
|
m_animation->setTargetObject(this);
|
|
m_animation->setEasingCurve(QEasingCurve::InOutQuad);
|
|
m_animation->setDuration(250);
|
|
|
|
setFlag(ItemHasContents, true);
|
|
|
|
connect(KIconLoader::global(), SIGNAL(iconLoaderSettingsChanged()),
|
|
this, SIGNAL(implicitWidthChanged()));
|
|
connect(KIconLoader::global(), SIGNAL(iconLoaderSettingsChanged()),
|
|
this, SIGNAL(implicitHeightChanged()));
|
|
|
|
|
|
connect(this, SIGNAL(enabledChanged()),
|
|
this, SLOT(loadPixmap()));
|
|
|
|
//initialize implicit size to the Dialog size
|
|
setImplicitWidth(KIconLoader::global()->currentSize(KIconLoader::Dialog));
|
|
setImplicitHeight(KIconLoader::global()->currentSize(KIconLoader::Dialog));
|
|
}
|
|
|
|
|
|
IconItem::~IconItem()
|
|
{
|
|
}
|
|
|
|
void IconItem::setSource(const QVariant &source)
|
|
{
|
|
if (source == m_source) {
|
|
return;
|
|
}
|
|
|
|
m_source = source;
|
|
|
|
if (source.canConvert<QIcon>()) {
|
|
m_icon = source.value<QIcon>();
|
|
m_imageIcon = QImage();
|
|
m_pixmapIcon = QPixmap();
|
|
delete m_svgIcon;
|
|
m_svgIcon = 0;
|
|
|
|
} else if (source.canConvert<QString>()) {
|
|
m_svgIcon = new Plasma::Svg(this);
|
|
//try as a svg toolbar icon
|
|
m_svgIcon->setImagePath("toolbar-icons/" + source.toString().split("-").first());
|
|
|
|
//try as a svg normal icon (like systray)
|
|
if (!m_svgIcon->isValid() || !m_svgIcon->hasElement(m_source.toString())) {
|
|
m_svgIcon->setImagePath("icons/" + source.toString().split("-").first());
|
|
}
|
|
m_svgIcon->setContainsMultipleImages(true);
|
|
|
|
//success?
|
|
if (m_svgIcon->isValid() && m_svgIcon->hasElement(m_source.toString())) {
|
|
m_icon = QIcon();
|
|
|
|
//ok, svg not available
|
|
} else {
|
|
m_icon = QIcon(source.toString());
|
|
delete m_svgIcon;
|
|
m_svgIcon = 0;
|
|
}
|
|
|
|
m_imageIcon = QImage();
|
|
m_pixmapIcon = QPixmap();
|
|
|
|
} else if (source.canConvert<QPixmap>()) {
|
|
m_icon = QIcon();
|
|
m_imageIcon = QImage();
|
|
m_pixmapIcon = source.value<QPixmap>();
|
|
delete m_svgIcon;
|
|
m_svgIcon = 0;
|
|
|
|
} else if (source.canConvert<QImage>()) {
|
|
m_icon = QIcon();
|
|
m_imageIcon = source.value<QImage>();
|
|
m_pixmapIcon = QPixmap();
|
|
delete m_svgIcon;
|
|
m_svgIcon = 0;
|
|
|
|
} else {
|
|
m_icon = QIcon();
|
|
m_imageIcon = QImage();
|
|
m_pixmapIcon = QPixmap();
|
|
delete m_svgIcon;
|
|
m_svgIcon = 0;
|
|
}
|
|
|
|
loadPixmap();
|
|
|
|
emit sourceChanged();
|
|
emit validChanged();
|
|
}
|
|
|
|
QVariant IconItem::source() const
|
|
{
|
|
return m_source;
|
|
}
|
|
|
|
bool IconItem::isActive() const
|
|
{
|
|
return m_active;
|
|
}
|
|
|
|
void IconItem::setActive(bool active)
|
|
{
|
|
if (m_active == active) {
|
|
return;
|
|
}
|
|
|
|
m_active = active;
|
|
loadPixmap();
|
|
emit activeChanged();
|
|
}
|
|
|
|
void IconItem::setImplicitWidth(qreal width)
|
|
{
|
|
if (implicitWidth() == width) {
|
|
return;
|
|
}
|
|
|
|
QQuickItem::setImplicitWidth(width);
|
|
|
|
emit implicitWidthChanged();
|
|
}
|
|
|
|
qreal IconItem::implicitWidth() const
|
|
{
|
|
return QQuickItem::implicitWidth();
|
|
}
|
|
|
|
void IconItem::setImplicitHeight(qreal height)
|
|
{
|
|
if (implicitHeight() == height) {
|
|
return;
|
|
}
|
|
|
|
QQuickItem::setImplicitHeight(height);
|
|
|
|
emit implicitHeightChanged();
|
|
}
|
|
|
|
qreal IconItem::implicitHeight() const
|
|
{
|
|
return QQuickItem::implicitHeight();
|
|
}
|
|
|
|
void IconItem::setSmooth(const bool smooth)
|
|
{
|
|
if (smooth == m_smooth) {
|
|
return;
|
|
}
|
|
m_smooth = smooth;
|
|
update();
|
|
}
|
|
|
|
bool IconItem::smooth() const
|
|
{
|
|
return m_smooth;
|
|
}
|
|
|
|
bool IconItem::isValid() const
|
|
{
|
|
return !m_iconPixmaps.isEmpty();
|
|
}
|
|
|
|
void IconItem::paint(QPainter *painter)
|
|
{
|
|
if (m_iconPixmaps.isEmpty()) {
|
|
qDebug() << "XXXXXXXXXX icons pixmap empty";
|
|
return;
|
|
}
|
|
foreach (QPixmap pix, m_iconPixmaps) {
|
|
qDebug() << "pixmap: " << pix.size();
|
|
}
|
|
|
|
painter->save();
|
|
painter->setRenderHint(QPainter::Antialiasing, m_smooth);
|
|
painter->setRenderHint(QPainter::SmoothPixmapTransform, m_smooth);
|
|
|
|
const QRect destRect(QPointF(boundingRect().center() - QPointF(m_iconPixmaps.first().width()/2, m_iconPixmaps.first().height()/2)).toPoint(),
|
|
m_iconPixmaps.first().size());
|
|
//QSize(32,32));
|
|
qDebug() << "XXXXXXXXXX icons pixmap THERE" << destRect;
|
|
|
|
if (m_animation->state() == QAbstractAnimation::Running) {
|
|
QPixmap result = m_iconPixmaps.first();
|
|
result = Plasma::PaintUtils::transition(result,
|
|
m_iconPixmaps.last(), m_animValue);
|
|
painter->drawPixmap(destRect, result);
|
|
//simpler logic for just paint
|
|
} else {
|
|
painter->drawPixmap(destRect, m_iconPixmaps.first());
|
|
}
|
|
|
|
painter->restore();
|
|
}
|
|
|
|
void IconItem::animationFinished()
|
|
{
|
|
while (m_iconPixmaps.count() > 1) {
|
|
m_iconPixmaps.pop_front();
|
|
}
|
|
}
|
|
|
|
void IconItem::valueChanged(const QVariant &value)
|
|
{
|
|
m_animValue = value.toReal();
|
|
update();
|
|
}
|
|
|
|
void IconItem::loadPixmap()
|
|
{
|
|
int size = qMin(width(), height());
|
|
|
|
//FIXME: Heuristic: allow 24x24 for icons/ that are in the systray(ugly)
|
|
if (m_svgIcon && m_svgIcon->imagePath().contains("icons/") &&
|
|
size > KIconLoader::SizeSmallMedium &&
|
|
size < KIconLoader::SizeMedium) {
|
|
size = 24;
|
|
|
|
//if size is less than 16, leave as is
|
|
} else if (size < KIconLoader::SizeSmall) {
|
|
//do nothing
|
|
} else if (size < KIconLoader::SizeSmallMedium) {
|
|
size = KIconLoader::SizeSmall;
|
|
} else if (size < KIconLoader::SizeMedium) {
|
|
size = KIconLoader::SizeSmallMedium;
|
|
} else if (size < KIconLoader::SizeLarge) {
|
|
size = KIconLoader::SizeMedium;
|
|
} else if (size < KIconLoader::SizeHuge) {
|
|
size = KIconLoader::SizeLarge;
|
|
//if size is more than 64, leave as is
|
|
}
|
|
|
|
//final pixmap to paint
|
|
QPixmap result;
|
|
if (m_svgIcon) {
|
|
m_svgIcon->resize(size, size);
|
|
result = m_svgIcon->pixmap(m_source.toString());
|
|
} else if (!m_source.isNull()) {
|
|
result = m_icon.pixmap(QSize(size, size));
|
|
} else if (!m_pixmapIcon.isNull()) {
|
|
result = m_pixmapIcon;
|
|
} else if (!m_imageIcon.isNull()) {
|
|
result = QPixmap::fromImage(m_imageIcon);
|
|
} else {
|
|
m_iconPixmaps.clear();
|
|
return;
|
|
}
|
|
|
|
if (!isEnabled()) {
|
|
result = KIconLoader::global()->iconEffect()->apply(result, KIconLoader::Desktop, KIconLoader::DisabledState);
|
|
} else if (m_active) {
|
|
result = KIconLoader::global()->iconEffect()->apply(result, KIconLoader::Desktop, KIconLoader::ActiveState);
|
|
}
|
|
|
|
//this happen only when loadPixmap has been called when an anim is running
|
|
while (m_iconPixmaps.count() > 1) {
|
|
m_iconPixmaps.pop_front();
|
|
}
|
|
|
|
m_iconPixmaps << result;
|
|
//if there is only one image, don't animate
|
|
//if an animation was already running, immediate transition, to not overload
|
|
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->setEndValue((qreal)1);
|
|
m_animation->start();
|
|
}
|
|
update();
|
|
}
|
|
|
|
void IconItem::geometryChanged(const QRectF &newGeometry,
|
|
const QRectF &oldGeometry)
|
|
{
|
|
if (newGeometry.size() != oldGeometry.size()) {
|
|
m_iconPixmaps.clear();
|
|
loadPixmap();
|
|
}
|
|
|
|
QQuickItem::geometryChanged(newGeometry, oldGeometry);
|
|
}
|
|
|
|
#include "iconitem.moc"
|