diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 93d9fe2..4fcaa9b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,6 +12,7 @@ set(SOURCES blurhelper/windowblur.h windowhelper.cpp iconitem.cpp + newiconitem.cpp managedtexturenode.cpp desktop/menupopupwindow.cpp diff --git a/src/fishui.cpp b/src/fishui.cpp index 8218d64..4399c38 100644 --- a/src/fishui.cpp +++ b/src/fishui.cpp @@ -24,6 +24,7 @@ #include "blurhelper/windowblur.h" #include "windowhelper.h" #include "iconitem.h" +#include "newiconitem.h" #include "desktop/menupopupwindow.h" @@ -55,7 +56,7 @@ void FishUI::registerTypes(const char *uri) qmlRegisterType(uri, 1, 0, "WindowShadow"); qmlRegisterType(uri, 1, 0, "WindowBlur"); qmlRegisterType(uri, 1, 0, "WindowHelper"); - qmlRegisterType(uri, 1, 0, "IconItem"); + qmlRegisterType(uri, 1, 0, "IconItem"); qmlRegisterType(uri, 1, 0, "MenuPopupWindow"); qmlRegisterSingletonType(componentUrl(QStringLiteral("Theme.qml")), uri, 1, 0, "Theme"); diff --git a/src/newiconitem.cpp b/src/newiconitem.cpp new file mode 100644 index 0000000..d386734 --- /dev/null +++ b/src/newiconitem.cpp @@ -0,0 +1,137 @@ +#include "newiconitem.h" + +#include +#include +#include +#include +#include + +NewIconItem::NewIconItem(QQuickItem *parent) + : QQuickPaintedItem(parent) +{ + setFlag(ItemHasContents, true); + setSmooth(true); +} + +void NewIconItem::setSource(const QVariant &source) +{ + if (source == m_source) { + return; + } + + m_source = source; + QString sourceString = source.toString(); + + if (source.canConvert() && !source.value().name().isEmpty()) { + sourceString = source.value().name(); + } + + QString localFile; + if (sourceString.startsWith(QLatin1String("file:"))) { + localFile = QUrl(sourceString).toLocalFile(); + } else if (sourceString.startsWith(QLatin1Char('/'))) { + localFile = sourceString; + } else if (sourceString.startsWith("qrc:/")) { + localFile = sourceString.remove(0, 3); + } else if (sourceString.startsWith(":/")) { + localFile = sourceString; + } + + if (!localFile.isEmpty()) { + if (sourceString.endsWith(QLatin1String(".svg")) + || sourceString.endsWith(QLatin1String(".svgz")) + || sourceString.endsWith(QLatin1String(".ico"))) { + m_icon = QIcon(localFile); + m_iconName.clear(); + m_image = QImage(); + } else { + m_image = QImage(localFile); + m_iconName.clear(); + m_icon = QIcon(); + } + } else if (source.canConvert()) { + m_icon = source.value(); + m_iconName.clear(); + m_image = QImage(); + } else if (source.canConvert()) { + m_image = source.value(); + m_iconName.clear(); + m_icon = QIcon(); + } else { + // From icon theme. + m_icon = QIcon(); + m_image = QImage(); + m_iconName = sourceString; + } + + if (width() > 0 && height() > 0) { + loadPixmap(); + } + + emit sourceChanged(); +} + +QVariant NewIconItem::source() const +{ + return m_source; +} + +void NewIconItem::paint(QPainter *painter) +{ + if (m_iconPixmap.isNull()) + return; + + painter->setRenderHints(QPainter::SmoothPixmapTransform); + painter->drawPixmap(contentsBoundingRect().toRect(), m_iconPixmap); +} + +void NewIconItem::updateIcon() +{ + loadPixmap(); +} + +void NewIconItem::loadPixmap() +{ + if (!isComponentComplete()) { + return; + } + + QSize size = QSize(width(), height()); + QPixmap result; + + if (size.width() < 0 || + size.height() < 0) { + m_iconPixmap = QPixmap(); + update(); + return; + } + + if (!m_iconName.isEmpty()) { + QIcon icon = QIcon::fromTheme(m_iconName); + + if (icon.isNull()) + icon = QIcon::fromTheme("application-x-desktop"); + + result = icon.pixmap(size * qApp->devicePixelRatio()); + } else if (!m_icon.isNull()) { + result = m_icon.pixmap(window(), size * qApp->devicePixelRatio()); + } else if (!m_image.isNull()) { + result = QPixmap::fromImage(m_image); + } else { + m_iconPixmap = QPixmap(); + update(); + return; + } + + m_iconPixmap = result; + update(); +} + +void NewIconItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + QQuickPaintedItem::geometryChanged(newGeometry, oldGeometry); + + if (newGeometry.width() > 0 && newGeometry.height() > 0) { + loadPixmap(); + } +} diff --git a/src/newiconitem.h b/src/newiconitem.h new file mode 100644 index 0000000..eaff2c3 --- /dev/null +++ b/src/newiconitem.h @@ -0,0 +1,42 @@ +#ifndef NEWICONITEM_H +#define NEWICONITEM_H + +#include +#include +#include +#include + +class IconItemSource; +class NewIconItem : public QQuickPaintedItem +{ + Q_OBJECT + Q_PROPERTY(QVariant source READ source WRITE setSource NOTIFY sourceChanged) + +public: + NewIconItem(QQuickItem *parent = nullptr); + + void setSource(const QVariant &source); + QVariant source() const; + + void paint(QPainter *painter) override; + + Q_INVOKABLE void updateIcon(); + +signals: + void sourceChanged(); + +protected: + void loadPixmap(); + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; + +private: + QVariant m_source; + + QIcon m_icon; + QImage m_image; + + QString m_iconName; + QPixmap m_iconPixmap; +}; + +#endif // NEWICONITEM_H