diff --git a/debian/changelog b/debian/changelog index f14d07b..3822abc 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +libfm-qt (0.11.1-3) unstable; urgency=medium + + * Backported a upstream fix for Icon Emblem Support. + * Added needed Symbols + + -- Alf Gaida Thu, 20 Oct 2016 18:00:38 +0200 + libfm-qt (0.11.1-2) unstable; urgency=medium * Cherry-picking upstream release 0.11.1. diff --git a/debian/libfm-qt3.symbols b/debian/libfm-qt3.symbols index e324472..c608fca 100644 --- a/debian/libfm-qt3.symbols +++ b/debian/libfm-qt3.symbols @@ -382,7 +382,10 @@ libfm-qt.so.3 libfm-qt3 #MINVER# (c++)"Fm::gidToName(unsigned int)@Base" 0.10.0 (c++)"Fm::IconTheme::changed()@Base" 0.10.0 (c++)"Fm::IconTheme::checkChanged()@Base" 0.10.0 - (c++)"Fm::IconTheme::convertFromGIcon(_GIcon*)@Base" 0.10.0 + (c++)"Fm::IconTheme::convertFromGIconWithoutEmblems(_GIcon*)@Base" 0.11.1 + (c++)"Fm::IconTheme::emblems(_FmIcon*)@Base" 0.11.1 + (c++)"Fm::IconTheme::emblems(_GIcon*)@Base" 0.11.1 + (c++)"Fm::IconTheme::ensureCacheData(_FmIcon*)@Base" 0.11.1 (c++)"Fm::IconTheme::eventFilter(QObject*, QEvent*)@Base" 0.10.0 (c++)"Fm::IconTheme::icon(_FmIcon*)@Base" 0.10.0 (c++)"Fm::IconTheme::iconFromNames(char const* const*)@Base" 0.10.0 @@ -435,6 +438,7 @@ libfm-qt.so.3 libfm-qt3 #MINVER# (c++)"Fm::pathListFromQUrls(QList)@Base" 0.10.0 (c++)"Fm::PlacesModelBookmarkItem::PlacesModelBookmarkItem(_FmBookmarkItem*)@Base" 0.10.0 (c++)"Fm::PlacesModel::createTrashItem()@Base" 0.10.0 + (c++)"Fm::PlacesModel::data(QModelIndex const&, int) const@Base" 0.11.1 (c++)"Fm::PlacesModel::dropMimeData(QMimeData const*, Qt::DropAction, int, int, QModelIndex const&)@Base" 0.10.0 (c++)"Fm::PlacesModel::flags(QModelIndex const&) const@Base" 0.10.0 (c++)"Fm::PlacesModelItem::data(int) const@Base" 0.10.0 diff --git a/debian/patches/model-places.patch b/debian/patches/model-places.patch new file mode 100644 index 0000000..70640cb --- /dev/null +++ b/debian/patches/model-places.patch @@ -0,0 +1,344 @@ +Description: Fixed behaviour with icon emblems + Backported a upstream fix for Icon Emblem Support. Only applies to + pcmanfm-qt - no changes in released version needed. +Author: Alf Gaida + +Last-Update: 2016-10-20 + +--- libfm-qt-0.11.1.orig/src/folderitemdelegate.cpp ++++ libfm-qt-0.11.1/src/folderitemdelegate.cpp +@@ -35,7 +35,9 @@ namespace Fm { + FolderItemDelegate::FolderItemDelegate(QAbstractItemView* view, QObject* parent): + QStyledItemDelegate(parent ? parent : view), + view_(view), +- symlinkIcon_(QIcon::fromTheme("emblem-symbolic-link")) { ++ symlinkIcon_(QIcon::fromTheme("emblem-symbolic-link")), ++ fileInfoRole_(Fm::FolderModel::FileInfoRole), ++ fmIconRole_(-1) { + } + + FolderItemDelegate::~FolderItemDelegate() { +@@ -78,9 +80,13 @@ QIcon::Mode FolderItemDelegate::iconMode + // special thanks to Razor-qt developer Alec Moskvin(amoskvin) for providing the fix! + void FolderItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { + Q_ASSERT(index.isValid()); +- FmFileInfo* file = static_cast(index.data(FolderModel::FileInfoRole).value()); ++ FmFileInfo* file = static_cast(index.data(fileInfoRole_).value()); ++ FmIcon* fmicon = static_cast(index.data(fmIconRole_).value()); ++ if(fmicon == nullptr && file != nullptr) { ++ fmicon = fm_file_info_get_icon(file); ++ } ++ QList emblems = fmicon != nullptr ? IconTheme::emblems(fmicon) : QList(); + bool isSymlink = file && fm_file_info_is_symlink(file); +- + if(option.decorationPosition == QStyleOptionViewItem::Top || + option.decorationPosition == QStyleOptionViewItem::Bottom) { + painter->save(); +@@ -100,9 +106,13 @@ void FolderItemDelegate::paint(QPainter* + painter->drawPixmap(iconPos + QPoint(margin.width(), margin.height()), pixmap); + + // draw some emblems for the item if needed +- // we only support symlink emblem at the moment + if(isSymlink) + painter->drawPixmap(iconPos, symlinkIcon_.pixmap(option.decorationSize / 2, iconMode)); ++ if(!emblems.isEmpty()) { ++ QPoint emblemPos(opt.rect.x() + opt.rect.width() / 2, opt.rect.y() + option.decorationSize.height() / 2); ++ QIcon emblem = IconTheme::icon(emblems.first().dataPtr()); ++ painter->drawPixmap(emblemPos, emblem.pixmap(option.decorationSize / 2, iconMode)); ++ } + + // draw the text + // The text rect dimensions should be exactly as they were in sizeHint() +@@ -118,14 +128,20 @@ void FolderItemDelegate::paint(QPainter* + QStyledItemDelegate::paint(painter, option, index); + + // draw emblems if needed +- if(isSymlink) { ++ if(isSymlink || !emblems.isEmpty()) { + QStyleOptionViewItem opt = option; + initStyleOption(&opt, index); + QIcon::Mode iconMode = iconModeFromState(opt.state); +- QPoint iconPos(opt.rect.x(), opt.rect.y() + (opt.rect.height() - option.decorationSize.height()) / 2); + // draw some emblems for the item if needed +- // we only support symlink emblem at the moment +- painter->drawPixmap(iconPos, symlinkIcon_.pixmap(option.decorationSize / 2, iconMode)); ++ if(isSymlink) { ++ QPoint iconPos(opt.rect.x(), opt.rect.y() + (opt.rect.height() - option.decorationSize.height()) / 2); ++ painter->drawPixmap(iconPos, symlinkIcon_.pixmap(option.decorationSize / 2, iconMode)); ++ } ++ else { ++ QPoint iconPos(opt.rect.x() + option.decorationSize.width() / 2, opt.rect.y() + opt.rect.height() / 2); ++ QIcon emblem = IconTheme::icon(emblems.first().dataPtr()); ++ painter->drawPixmap(iconPos, emblem.pixmap(option.decorationSize / 2, iconMode)); ++ } + } + } + } +--- libfm-qt-0.11.1.orig/src/folderitemdelegate.h ++++ libfm-qt-0.11.1/src/folderitemdelegate.h +@@ -41,6 +41,22 @@ public: + return gridSize_; + } + ++ int fileInfoRole() { ++ return fileInfoRole_; ++ } ++ ++ void setFileInfoRole(int role) { ++ fileInfoRole_ = role; ++ } ++ ++ int fmIconRole() { ++ return fmIconRole_; ++ } ++ ++ void setFmIconRole(int role) { ++ fmIconRole_ = role; ++ } ++ + virtual QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const; + virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; + +@@ -52,6 +68,8 @@ private: + QAbstractItemView* view_; + QIcon symlinkIcon_; + QSize gridSize_; ++ int fileInfoRole_; ++ int fmIconRole_; + }; + + } +--- libfm-qt-0.11.1.orig/src/icontheme.cpp ++++ libfm-qt-0.11.1/src/icontheme.cpp +@@ -28,12 +28,18 @@ + + namespace Fm { + ++class IconCacheData { ++public: ++ QIcon qicon; ++ QList emblems; ++}; ++ + 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(data); +- delete picon; ++static void fmIconDataDestroy(gpointer user_data) { ++ IconCacheData* data = reinterpret_cast(user_data); ++ delete data; + } + + IconTheme::IconTheme(): +@@ -88,7 +94,7 @@ QIcon IconTheme::iconFromNames(const cha + return QIcon(); + } + +-QIcon IconTheme::convertFromGIcon(GIcon* gicon) { ++QIcon IconTheme::convertFromGIconWithoutEmblems(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); +@@ -106,20 +112,36 @@ QIcon IconTheme::convertFromGIcon(GIcon* + } + + ++// static ++IconCacheData* IconTheme::ensureCacheData(FmIcon* fmicon) { ++ IconCacheData* data = reinterpret_cast(fm_icon_get_user_data(fmicon)); ++ if(!data) { // we don't have a cache yet ++ data = new IconCacheData(); ++ GIcon* gicon = G_ICON(fmicon); ++ if(G_IS_EMBLEMED_ICON(gicon)) { // special handling for emblemed icon ++ GList* emblems = g_emblemed_icon_get_emblems(G_EMBLEMED_ICON(gicon)); ++ for(GList* l = emblems; l; l = l->next) { ++ GIcon* emblem_gicon = g_emblem_get_icon(G_EMBLEM(l->data)); ++ data->emblems.append(Icon::fromGicon(emblem_gicon)); ++ } ++ gicon = g_emblemed_icon_get_icon(G_EMBLEMED_ICON(gicon)); // get an emblemless GIcon ++ } ++ data->qicon = convertFromGIconWithoutEmblems(gicon); ++ fm_icon_set_user_data(fmicon, data); // store it in FmIcon ++ } ++ return data; ++} ++ + //static + QIcon IconTheme::icon(FmIcon* fmicon) { +- // check if we have a cached version +- QIcon* picon = reinterpret_cast(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; ++ IconCacheData* data = ensureCacheData(fmicon); ++ return data->qicon; + } + + //static + QIcon IconTheme::icon(GIcon* gicon) { ++ if(G_IS_EMBLEMED_ICON(gicon)) // get an emblemless GIcon ++ gicon = g_emblemed_icon_get_icon(G_EMBLEMED_ICON(gicon)); + if(G_IS_THEMED_ICON(gicon)) { + FmIcon* fmicon = fm_icon_from_gicon(gicon); + QIcon qicon = icon(fmicon); +@@ -128,11 +150,26 @@ QIcon IconTheme::icon(GIcon* gicon) { + } + else if(G_IS_FILE_ICON(gicon)) { + // we do not map GFileIcon to FmIcon deliberately. +- return convertFromGIcon(gicon); ++ return convertFromGIconWithoutEmblems(gicon); + } + return theIconTheme->fallbackIcon_; + } + ++// static ++QList IconTheme::emblems(FmIcon* fmicon) { ++ IconCacheData* data = ensureCacheData(fmicon); ++ return data->emblems; ++} ++ ++//static ++QList IconTheme::emblems(GIcon* gicon) { ++ if(G_IS_EMBLEMED_ICON(gicon)) { // if this gicon contains emblems ++ Icon fmicon = Icon::fromGicon(gicon); ++ return emblems(fmicon.dataPtr()); ++ } ++ return QList(); ++} ++ + // 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. +--- libfm-qt-0.11.1.orig/src/icontheme.h ++++ libfm-qt-0.11.1/src/icontheme.h +@@ -25,6 +25,7 @@ + #include + #include + #include "libfm/fm.h" ++#include "icon.h" + + namespace Fm { + +@@ -40,6 +41,8 @@ namespace Fm { + + // Nice article about QPixmap from KDE: http://techbase.kde.org/Development/Tutorials/Graphics/Performance + ++class IconCacheData; ++ + class LIBFM_QT_API IconTheme: public QObject { + Q_OBJECT + public: +@@ -49,6 +52,8 @@ public: + static IconTheme* instance(); + static QIcon icon(FmIcon* fmicon); + static QIcon icon(GIcon* gicon); ++ static QList emblems(FmIcon* fmicon); ++ static QList emblems(GIcon* gicon); + + static void checkChanged(); // check if current icon theme name is changed + Q_SIGNALS: +@@ -56,8 +61,9 @@ Q_SIGNALS: + + protected: + bool eventFilter(QObject *obj, QEvent *event); +- static QIcon convertFromGIcon(GIcon* gicon); ++ static QIcon convertFromGIconWithoutEmblems(GIcon* gicon); + static QIcon iconFromNames(const char * const * names); ++ static IconCacheData* ensureCacheData(FmIcon* fmicon); + + protected: + QIcon fallbackIcon_; +--- libfm-qt-0.11.1.orig/src/placesmodel.cpp ++++ libfm-qt-0.11.1/src/placesmodel.cpp +@@ -35,7 +35,6 @@ PlacesModel::PlacesModel(QObject* parent + showApplications_(true), + showDesktop_(true), + ejectIcon_(QIcon::fromTheme("media-eject")) { +- + setColumnCount(2); + + placesRoot = new QStandardItem(tr("Places")); +@@ -504,6 +503,23 @@ Qt::ItemFlags PlacesModel::flags(const Q + return QStandardItemModel::flags(index); + } + ++ ++QVariant PlacesModel::data(const QModelIndex &index, int role) const { ++ if(index.column() == 0 && index.parent().isValid()) { ++ PlacesModelItem* item = static_cast(QStandardItemModel::itemFromIndex(index)); ++ if(item != nullptr) { ++ switch(role) { ++ case FileInfoRole: ++ return QVariant::fromValue(item->fileInfo()); ++ case FmIconRole: ++ return QVariant::fromValue(item->icon()); ++ } ++ } ++ } ++ return QStandardItemModel::data(index, role); ++} ++ ++ + bool PlacesModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) { + QStandardItem* item = itemFromIndex(parent); + if(data->hasFormat("application/x-bookmark-row")) { // the data being dopped is a bookmark row +--- libfm-qt-0.11.1.orig/src/placesmodel.h ++++ libfm-qt-0.11.1/src/placesmodel.h +@@ -40,6 +40,11 @@ Q_OBJECT + friend class PlacesView; + public: + ++ enum { ++ FileInfoRole = Qt::UserRole, ++ FmIconRole ++ }; ++ + // QAction used for popup menus + class ItemAction : public QAction { + public: +@@ -74,6 +79,8 @@ public: + } + void setShowDesktop(bool show); + ++ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; ++ + public Q_SLOTS: + void updateIcons(); + void updateTrash(); +--- libfm-qt-0.11.1.orig/src/placesmodelitem.cpp ++++ libfm-qt-0.11.1/src/placesmodelitem.cpp +@@ -21,6 +21,7 @@ + #include "placesmodelitem.h" + #include "icontheme.h" + #include ++#include + + namespace Fm { + +--- libfm-qt-0.11.1.orig/src/placesview.cpp ++++ libfm-qt-0.11.1/src/placesview.cpp +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include "folderitemdelegate.h" + + namespace Fm { + +@@ -43,6 +44,11 @@ PlacesView::PlacesView(QWidget* parent): + + setIconSize(QSize(24, 24)); + ++ FolderItemDelegate* delegate = new FolderItemDelegate(this, this); ++ delegate->setFileInfoRole(PlacesModel::FileInfoRole); ++ delegate->setFmIconRole(PlacesModel::FmIconRole); ++ setItemDelegateForColumn(0, delegate); ++ + // FIXME: we may share this model amont all views + model_ = new PlacesModel(this); + setModel(model_); diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000..d7273e0 --- /dev/null +++ b/debian/patches/series @@ -0,0 +1 @@ +model-places.patch