You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
4.5 KiB
144 lines
4.5 KiB
10 years ago
|
/*
|
||
|
<one line to give the library's name and an idea of what it does.>
|
||
|
Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
||
|
|
||
|
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 "icontheme.h"
|
||
|
#include <libfm/fm.h>
|
||
|
#include <QList>
|
||
|
#include <QIcon>
|
||
|
#include <QtGlobal>
|
||
|
#include <QApplication>
|
||
|
#include <QDesktopWidget>
|
||
|
|
||
|
using namespace Fm;
|
||
|
|
||
|
static IconTheme* theIconTheme = NULL; // the global single instance of IconTheme.
|
||
|
static const char* fallbackNames[] = {"unknown", "application-octet-stream", NULL};
|
||
|
|
||
|
static void fmIconDataDestroy(gpointer data) {
|
||
|
QIcon* picon = reinterpret_cast<QIcon*>(data);
|
||
|
delete picon;
|
||
|
}
|
||
|
|
||
|
IconTheme::IconTheme():
|
||
|
currentThemeName_(QIcon::themeName()) {
|
||
|
// NOTE: only one instance is allowed
|
||
|
Q_ASSERT(theIconTheme == NULL);
|
||
|
Q_ASSERT(qApp != NULL); // QApplication should exists before contructing IconTheme.
|
||
|
|
||
|
theIconTheme = this;
|
||
|
fm_icon_set_user_data_destroy(reinterpret_cast<GDestroyNotify>(fmIconDataDestroy));
|
||
|
fallbackIcon_ = iconFromNames(fallbackNames);
|
||
|
|
||
|
// We need to get notified when there is a QEvent::StyleChange event so
|
||
|
// we can check if the current icon theme name is changed.
|
||
|
// To do this, we can filter QApplication object itself to intercept
|
||
|
// signals of all widgets, but this may be too inefficient.
|
||
|
// So, we only filter the events on QDesktopWidget instead.
|
||
|
qApp->desktop()->installEventFilter(this);
|
||
|
}
|
||
|
|
||
|
IconTheme::~IconTheme() {
|
||
|
}
|
||
|
|
||
|
IconTheme* IconTheme::instance() {
|
||
|
return theIconTheme;
|
||
|
}
|
||
|
|
||
|
// check if the icon theme name is changed and emit "changed()" signal if any change is detected.
|
||
|
void IconTheme::checkChanged() {
|
||
|
if(QIcon::themeName() != theIconTheme->currentThemeName_) {
|
||
|
// if the icon theme is changed
|
||
|
theIconTheme->currentThemeName_ = QIcon::themeName();
|
||
|
// invalidate the cached data
|
||
|
fm_icon_reset_user_data_cache(fm_qdata_id);
|
||
|
|
||
|
theIconTheme->fallbackIcon_ = iconFromNames(fallbackNames);
|
||
|
Q_EMIT theIconTheme->changed();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
QIcon IconTheme::iconFromNames(const char* const* names) {
|
||
|
const gchar* const* name;
|
||
|
// qDebug("names: %p", names);
|
||
|
for(name = names; *name; ++name) {
|
||
|
// qDebug("icon name=%s", *name);
|
||
|
QString qname = *name;
|
||
|
QIcon qicon = QIcon::fromTheme(qname);
|
||
|
if(!qicon.isNull()) {
|
||
|
return qicon;
|
||
|
}
|
||
|
}
|
||
|
return QIcon();
|
||
|
}
|
||
|
|
||
|
QIcon IconTheme::convertFromGIcon(GIcon* gicon) {
|
||
|
if(G_IS_THEMED_ICON(gicon)) {
|
||
|
const gchar * const * names = g_themed_icon_get_names(G_THEMED_ICON(gicon));
|
||
|
QIcon icon = iconFromNames(names);
|
||
|
if(!icon.isNull())
|
||
|
return icon;
|
||
|
}
|
||
|
else if(G_IS_FILE_ICON(gicon)) {
|
||
|
GFile* file = g_file_icon_get_file(G_FILE_ICON(gicon));
|
||
|
char* fpath = g_file_get_path(file);
|
||
|
QString path = fpath;
|
||
|
g_free(fpath);
|
||
|
return QIcon(path);
|
||
|
}
|
||
|
return theIconTheme->fallbackIcon_;
|
||
|
}
|
||
|
|
||
|
|
||
|
//static
|
||
|
QIcon IconTheme::icon(FmIcon* fmicon) {
|
||
|
// check if we have a cached version
|
||
|
QIcon* picon = reinterpret_cast<QIcon*>(fm_icon_get_user_data(fmicon));
|
||
|
if(!picon) { // we don't have a cache yet
|
||
|
picon = new QIcon(); // what a waste!
|
||
|
*picon = convertFromGIcon(G_ICON(fmicon));
|
||
|
fm_icon_set_user_data(fmicon, picon); // store it in FmIcon
|
||
|
}
|
||
|
return *picon;
|
||
|
}
|
||
|
|
||
|
//static
|
||
|
QIcon IconTheme::icon(GIcon* gicon) {
|
||
|
if(G_IS_THEMED_ICON(gicon)) {
|
||
|
FmIcon* fmicon = fm_icon_from_gicon(gicon);
|
||
|
QIcon qicon = icon(fmicon);
|
||
|
fm_icon_unref(fmicon);
|
||
|
return qicon;
|
||
|
}
|
||
|
else if(G_IS_FILE_ICON(gicon)) {
|
||
|
// we do not map GFileIcon to FmIcon deliberately.
|
||
|
return convertFromGIcon(gicon);
|
||
|
}
|
||
|
return theIconTheme->fallbackIcon_;
|
||
|
}
|
||
|
|
||
|
// this method is called whenever there is an event on the QDesktopWidget object.
|
||
|
bool IconTheme::eventFilter(QObject* obj, QEvent* event) {
|
||
|
// we're only interested in the StyleChange event.
|
||
|
if(event->type() == QEvent::StyleChange) {
|
||
|
checkChanged(); // check if the icon theme is changed
|
||
|
}
|
||
|
return QObject::eventFilter(obj, event);
|
||
|
}
|