From e31ebda8db7e8327e88eb363fa6905aa0951275d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9F=B3=E5=8D=9A=E6=96=87?= Date: Tue, 14 Jun 2016 16:01:01 +0800 Subject: [PATCH] add icon Change-Id: I5e6cfb0b57219982d7f0061acbfb485bd949a2e9 --- dbus/dbusdockentry.h | 5 ++ dde-dock.pro | 10 ++- item/appitem.cpp | 23 ++++-- item/appitem.h | 4 + util/themeappicon.cpp | 170 ++++++++++++++++++++++++++++++++++++++++++ util/themeappicon.h | 25 +++++++ 6 files changed, 228 insertions(+), 9 deletions(-) create mode 100644 util/themeappicon.cpp create mode 100644 util/themeappicon.h diff --git a/dbus/dbusdockentry.h b/dbus/dbusdockentry.h index 4797c478f..82cab3c15 100644 --- a/dbus/dbusdockentry.h +++ b/dbus/dbusdockentry.h @@ -73,6 +73,10 @@ public: inline QString title() const { return qvariant_cast< QString >(property("Title")); } + Q_PROPERTY(QString Icon READ icon NOTIFY IconChanged) + inline QString icon() const + { return qvariant_cast< QString >(property("Icon")); } + public Q_SLOTS: // METHODS inline QDBusPendingReply<> Activate() { @@ -94,6 +98,7 @@ void TitlesChanged(); void DataChanged(); void IdChanged(); void TitleChanged(); +void IconChanged(); }; namespace dde { diff --git a/dde-dock.pro b/dde-dock.pro index 6c5eabae6..1a8e31288 100644 --- a/dde-dock.pro +++ b/dde-dock.pro @@ -1,10 +1,10 @@ -QT += core gui widgets dbus x11extras +QT += core gui widgets dbus x11extras svg TARGET = dde-dock TEMPLATE = app CONFIG += c++11 link_pkgconfig -PKGCONFIG += xcb-ewmh +PKGCONFIG += xcb-ewmh gtk+-2.0 SOURCES += main.cpp \ window/mainwindow.cpp \ @@ -19,7 +19,8 @@ SOURCES += main.cpp \ item/placeholderitem.cpp \ dbus/dbusclientmanager.cpp \ dbus/dbusdock.cpp \ - dbus/dbusmenu.cpp + dbus/dbusmenu.cpp \ + util/themeappicon.cpp HEADERS += \ window/mainwindow.h \ @@ -34,4 +35,5 @@ HEADERS += \ item/placeholderitem.h \ dbus/dbusclientmanager.h \ dbus/dbusdock.h \ - dbus/dbusmenu.h + dbus/dbusmenu.h \ + util/themeappicon.h diff --git a/item/appitem.cpp b/item/appitem.cpp index 64303a7a5..c9488c3a6 100644 --- a/item/appitem.cpp +++ b/item/appitem.cpp @@ -1,5 +1,7 @@ #include "appitem.h" +#include "util/themeappicon.h" + #include #include #include @@ -20,11 +22,13 @@ AppItem::AppItem(const QDBusObjectPath &entry, QWidget *parent) { initClientManager(); - m_titles = m_itemEntry->titles(); m_id = m_itemEntry->id(); connect(m_itemEntry, &DBusDockEntry::TitlesChanged, this, &AppItem::titlesChanged); connect(m_itemEntry, &DBusDockEntry::ActiveChanged, this, static_cast(&AppItem::update)); + + titlesChanged(); + iconChanged(); } const QString AppItem::appId() const @@ -49,15 +53,17 @@ void AppItem::paintEvent(QPaintEvent *e) QPainter painter(this); + // draw background + const QRect backgroundRect = rect().marginsRemoved(QMargins(3, 3, 3, 3)); if (m_itemEntry->active()) - painter.fillRect(rect(), Qt::blue); + painter.fillRect(backgroundRect, Qt::blue); else if (!m_titles.isEmpty()) - painter.fillRect(rect(), Qt::cyan); + painter.fillRect(backgroundRect, Qt::cyan); else - painter.fillRect(rect(), Qt::gray); + painter.fillRect(backgroundRect, Qt::gray); // draw icon - painter.fillRect(iconRect, Qt::yellow); + painter.drawPixmap(rect().center() - m_icon.rect().center(), m_icon); // draw text painter.setPen(Qt::red); @@ -130,3 +136,10 @@ void AppItem::titlesChanged() update(); } + +void AppItem::iconChanged() +{ + const QString icon = m_itemEntry->icon(); + + m_icon = ThemeAppIcon::getIcon(icon, 48); +} diff --git a/item/appitem.h b/item/appitem.h index a7a00b13b..1c8f929fa 100644 --- a/item/appitem.h +++ b/item/appitem.h @@ -22,7 +22,10 @@ private: void startDrag(); void initClientManager(); + +private slots: void titlesChanged(); + void iconChanged(); private: DBusDockEntry *m_itemEntry; @@ -31,6 +34,7 @@ private: WindowDict m_titles; QString m_id; + QPixmap m_icon; QPoint m_mousePressPos; diff --git a/util/themeappicon.cpp b/util/themeappicon.cpp new file mode 100644 index 000000000..dfac7234a --- /dev/null +++ b/util/themeappicon.cpp @@ -0,0 +1,170 @@ +#include "themeappicon.h" +#include +#include +#include +#include +#include +#include + +#undef signals +extern "C" { + #include + #include + #include +} +#define signals public + + +static GtkIconTheme* them = NULL; + +inline char* get_icon_theme_name() +{ + GtkSettings* gs = gtk_settings_get_default(); + char* name = NULL; + g_object_get(gs, "gtk-icon-theme-name", &name, NULL); + return name; +} + +ThemeAppIcon::ThemeAppIcon(QObject *parent) : QObject(parent) +{ + +} + +void ThemeAppIcon::gtkInit(){ + gtk_init(NULL, NULL); + gdk_error_trap_push(); +} + +QPixmap ThemeAppIcon::getIconPixmap(QString iconPath, int width, int height){ + Q_ASSERT(false); + if (iconPath.length() == 0){ + iconPath = "application-x-desktop"; + } + QPixmap pixmap(width, height); + // iconPath is an absolute path of the system + if (QFile::exists(iconPath) && iconPath.contains(QDir::separator())) { + pixmap = QPixmap(iconPath); + } else if (iconPath.startsWith("data:image/")){ + // iconPath is a string representing an inline image. + QStringList strs = iconPath.split("base64,"); + if (strs.length() == 2) { + QByteArray data = QByteArray::fromBase64(strs.at(1).toLatin1()); + pixmap.loadFromData(data); + } + }else { + // try to read the iconPath as a icon name. + QString path = getThemeIconPath(iconPath, width); + if (path.length() == 0){ + path = ":/skin/images/application-default-icon.svg"; + } + if (path.endsWith(".svg")) { + QSvgRenderer renderer(path); + pixmap.fill(Qt::transparent); + QPainter painter; + painter.begin(&pixmap); + renderer.render(&painter); + painter.end(); + qDebug() << "path svg:" << path; + } else { + pixmap.load(path); + } + } + + return pixmap; +} + +QString ThemeAppIcon::getThemeIconPath(QString iconName, int size) +{ + QByteArray bytes = iconName.toUtf8(); + char *name = bytes.data(); + + if (g_path_is_absolute(name)) + return g_strdup(name); + + g_return_val_if_fail(name != NULL, NULL); + + int pic_name_len = strlen(name); + char* ext = strrchr(name, '.'); + if (ext != NULL) { + if (g_ascii_strcasecmp(ext+1, "png") == 0 || g_ascii_strcasecmp(ext+1, "svg") == 0 || g_ascii_strcasecmp(ext+1, "jpg") == 0) { + pic_name_len = ext - name; +// qDebug() << "desktop's Icon name should an absoulte path or an basename without extension"; + } + } + + // In pratice, default icon theme may not gets the right icon path when program starting. + if (them == NULL) + them = gtk_icon_theme_new(); + char* icon_theme_name = get_icon_theme_name(); + gtk_icon_theme_set_custom_theme(them, icon_theme_name); + g_free(icon_theme_name); + + char* pic_name = g_strndup(name, pic_name_len); + + GtkIconInfo* info = gtk_icon_theme_lookup_icon(them, pic_name, size, GTK_ICON_LOOKUP_GENERIC_FALLBACK); + if (info == NULL) { + info = gtk_icon_theme_lookup_icon(gtk_icon_theme_get_default(), pic_name, size, GTK_ICON_LOOKUP_GENERIC_FALLBACK); + if (info == NULL) { +// qWarning() << "get gtk icon theme info failed for" << pic_name; + g_free(pic_name); + return ""; + } + } + g_free(pic_name); + + char* path = g_strdup(gtk_icon_info_get_filename(info)); + + #if GTK_MAJOR_VERSION >= 3 + g_object_unref(info); + #elif GTK_MAJOR_VERSION == 2 + gtk_icon_info_free(info); + #endif + g_debug("get icon from icon theme is: %s", path); + return path; +} + +QPixmap ThemeAppIcon::getIcon(const QString iconName, const int size) +{ + const QString fileName = getThemeIconPath(iconName, size); + + QPixmap pixmap; + if (fileName.startsWith("data:image/")) { + //This icon file is an inline image + QStringList strs = fileName.split("base64,"); + if (strs.length() == 2) { + QByteArray data = QByteArray::fromBase64(strs.at(1).toLatin1()); + pixmap.loadFromData(data); + } + + } else if (fileName.endsWith(".svg", Qt::CaseInsensitive)) + pixmap = loadSvg(fileName, size); + else + pixmap = QPixmap(fileName); + + if (pixmap.isNull()) + return pixmap; + + return pixmap.scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); +} + +QPixmap ThemeAppIcon::loadSvg(const QString &fileName, const int size) +{ + QPixmap pixmap(size, size); + QSvgRenderer renderer(fileName); + pixmap.fill(Qt::transparent); + + QPainter painter; + painter.begin(&pixmap); + renderer.render(&painter); + painter.end(); + + return pixmap; +} + + + +ThemeAppIcon::~ThemeAppIcon() +{ + +} + diff --git a/util/themeappicon.h b/util/themeappicon.h new file mode 100644 index 000000000..e7916a5e2 --- /dev/null +++ b/util/themeappicon.h @@ -0,0 +1,25 @@ +#ifndef THEMEAPPICON_H +#define THEMEAPPICON_H + +#include + +class ThemeAppIcon : public QObject +{ + Q_OBJECT +public: + explicit ThemeAppIcon(QObject *parent = 0); + ~ThemeAppIcon(); + + void gtkInit(); + + static QPixmap getIconPixmap(QString iconPath, int width=64, int height=64); + static QString getThemeIconPath(QString iconName, int size=64); + static QPixmap getIcon(const QString iconName, const int size); + static QPixmap loadSvg(const QString &fileName, const int size); + +signals: + +public slots: +}; + +#endif // THEMEAPPICON_H