Cherry-picking upstream release 0.11.2

* Added new symbols
* Removed build dependencies:
  - cmake
  - liblxqt0-dev
  - libqt5xdg-dev
  - pkg-config
  - qttools5-dev
  - qttools5-dev-tools
* Added build dependency lxqt-build-tools
* Added build dependency libfm-dev to libfm-qt-dev
* Removed models.patch, applied upstream
ubuntu/cosmic debian/0.11.2-1
Alf Gaida 8 years ago
parent 057bb75ee9
commit da03a71631

10
.gitignore vendored

@ -1,10 +0,0 @@
build*/
src/translations/libfm-qt
# Vim.gitignore
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
*.un~
Session.vim
.netrwhist
*~

@ -1,7 +1,59 @@
libfm-qt-0.11.1 / 2016-09-24
libfm-qt-0.11.2 / 2016-12-21
============================
* Fix enabled state of path arrows on starting (#58)
* bump patch version (#56)
* Use QByteArray::constData() where we can (#57)
* Updates lxqt-build-tools required version
* Bump ABI so version numbers preparing for a new release.
* Fix Pathbar Paint on Menu Pop-Up
* Code cleanup and refactor for Fm::PathBar.
* Added another condition
* Added a missing condition (typo)
* Scroll Pathbar with Mouse Wheel
* Reduct flickering of the path bar when creating path buttons.
* Code simplification by removing unnecessary signal/slot usage.
* Path Button Middle Click
* Enable auto-repeat for pathbar scroll buttons.
* Make the path bar buttons aware of style changes.
* Use widget style instead of app style
* Align Path Buttons
* Move FindXCB.cmake to lxqt-build-tools
* Adds superbuild/intree support
* Removes not needed dependency check
* Set CMP0024 policy usage to NEW
* Updates target_include_directories() stuff
* Drops GLib library detection
* Use the new FindMenuCache CMake module
* Use the new FindFm CMake module
* Check for FolderModelItem info (and FmPath)
* Add Fm::PathBar::editingFinished() signal.
* Select the current path when editing the path bar.
* Enable path editing and popup menu for the button-style path bar.
* Properly set styles of path buttons.
* Remove unnecessary debug messages.
* Try to implement the Fm::PathBar which shows a filesystem path as buttons.
* Adds Build PROJECT_NAME with Qt version message
* Move LIBFM_DATA_DIR to pcmanfm repo.
* Refactors CUSTOM_ACTIONS compile definition
* Refactors LIBFM_DATA_DIR compile definition
* Drop add_definitions. Use target_compile_definitions.
* Removes duplicated symbols visibility settings
* README.md: Add build dependency lxqt-build-tools
* Use the new lxqt-build-tools package
* Restore symlink emblem
* Remove empty files
* Try to refactor the emblemed icon support in a more generalized way. Reuse FolderItemDelegate to paint the emblemed icons in Fm::PlacesView to prevent code duplication. APIs changes: * Add Fm::IconTheme::emblems() and cache emblem info in the cache. * Add Fm::FolderItemDelegate::setFileInfoRole() and Fm::FolderItemDelegate::setFmIconRole() * Cache multiple emblems rather than getting the first one only (but only paint the first one now). * Remove icon sizes from Fm::PlacesModel and Fm::PlacesModelItems to maintain MVC design pattern and backward incompatibility. * Expose two role IDs in Fm::PlacesModel: FileInfoRole and FmIconRole so the views can access these data.
* Show File Emblems
* Emblem For (Encrypted) Volume Icons
* Remove cpack (#44)
* Also Consider GEmblemedIcon (#41)
0.11.1 / 2016-09-24
===================
* Release 0.11.1: Add changelog
* Bump version to 0.11.1 (#39)
* Fix Custom Actions Submenu (#38)
* Extend README.md

@ -5,7 +5,7 @@ set(LIBFM_QT_LIBRARY_NAME "fm-qt" CACHE STRING "fm-qt")
set(LIBFM_QT_VERSION_MAJOR 0)
set(LIBFM_QT_VERSION_MINOR 11)
set(LIBFM_QT_VERSION_PATCH 1)
set(LIBFM_QT_VERSION_PATCH 2)
set(LIBFM_QT_VERSION ${LIBFM_QT_VERSION_MAJOR}.${LIBFM_QT_VERSION_MINOR}.${LIBFM_QT_VERSION_PATCH})
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
@ -17,13 +17,14 @@ list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
# Actually, libtool uses different ways on different operating systems. So there is no
# universal way to translate a libtool version-info to a cmake version.
# We use "(current-age).age.revision" as the cmake version.
# current: 3, revision: 0, age: 0 => version: 3.0.0
set(LIBFM_QT_LIB_VERSION "3.0.0")
# current: 4, revision: 0, age: 1 => version: 3.1.0
set(LIBFM_QT_LIB_VERSION "3.1.0")
set(LIBFM_QT_LIB_SOVERSION "3")
set(REQUIRED_QT_VERSION "5.2")
set(REQUIRED_LIBFM_VERSION "1.2.0")
set(REQUIRED_LIBMENUCACHE_VERSION "0.4.0")
set(REQUIRED_LXQT_BUILD_TOOLS_VERSION "0.3.0")
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
@ -32,20 +33,13 @@ endif()
find_package(Qt5Widgets "${REQUIRED_QT_VERSION}" REQUIRED)
find_package(Qt5LinguistTools "${REQUIRED_QT_VERSION}" REQUIRED)
find_package(Qt5X11Extras "${REQUIRED_QT_VERSION}" REQUIRED)
find_package(XCB REQUIRED)
#Note: no run-time dependency on liblxqt, just a build dependency for lxqt_translate_ts/desktop
find_package(lxqt REQUIRED)
find_package(PkgConfig)
pkg_check_modules(SYSTEM_LIBS REQUIRED
glib-2.0
gio-2.0
gio-unix-2.0
)
find_package(lxqt-build-tools "${REQUIRED_LXQT_BUILD_TOOLS_VERSION}" REQUIRED)
find_package(Fm "${REQUIRED_LIBFM_VERSION}" REQUIRED)
find_package(MenuCache "${REQUIRED_LIBMENUCACHE_VERSION}" REQUIRED)
find_package(XCB REQUIRED)
pkg_check_modules(LIBFM REQUIRED libfm>="${REQUIRED_LIBFM_VERSION}")
pkg_check_modules(LIBMENUCACHE REQUIRED libmenu-cache>="${REQUIRED_LIBMENUCACHE_VERSION}")
message(STATUS "Building ${PROJECT_NAME} with Qt ${Qt5Core_VERSION_STRING}")
option(UPDATE_TRANSLATIONS "Update source translation translations/*.ts files" OFF)
include(GNUInstallDirs)
@ -55,13 +49,6 @@ include(LXQtTranslateTs)
include(LXQtTranslateDesktop)
include(LXQtCompilerSettings NO_POLICY_SCOPE)
add_definitions(-DQT_NO_KEYWORDS)
# set visibility to hidden to hide symbols, unless they're exported manually in the code
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
set(CMAKE_AUTOMOC TRUE)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
@ -98,18 +85,3 @@ if(BUILD_DOCUMENTATION)
COMPONENT Devel
)
endif()
# building tarball with CPack -------------------------------------------------
# To create a source distribution, type:
# make package_source
include(InstallRequiredSystemLibraries)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
set(CPACK_PACKAGE_VENDOR "")
set(CPACK_PACKAGE_VERSION_MAJOR ${LIBFM_QT_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${LIBFM_QT_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${LIBFM_QT_VERSION_PATCH})
set(CPACK_GENERATOR TBZ2)
set(CPACK_SOURCE_GENERATOR TBZ2)
set(CPACK_SOURCE_IGNORE_FILES /build/;.gitignore;.*~;.git;.kdev4;temp)
include(CPack)

@ -10,8 +10,8 @@ libfm-qt is licensed under the terms of the [LGPLv2.1](https://www.gnu.org/licen
### Compiling source code
Runtime dependencies are qtx11extras and libfm ≥ 1,2 (not all features are provided by libfm-qt yet).
Additional build dependencies are CMake and optionally Git to pull latest VCS checkouts. The localization files were outsourced to repository [lxqt-l10n](https://github.com/lxde/lxqt-l10n) so the corresponding dependencies are needed, too. Please refer to this repository's `README.md` for further information.
Runtime dependencies are Qt X11 Extras and libfm ≥ 1,2 (not all features are provided by libfm-qt yet).
Additional build dependencies are CMake, [lxqt-build-tools](https://github.com/lxde/lxqt-build-tools) and optionally Git to pull latest VCS checkouts. The localization files were outsourced to repository [lxqt-l10n](https://github.com/lxde/lxqt-l10n) so the corresponding dependencies are needed, too. Please refer to this repository's `README.md` for further information.
Code configuration is handled by CMake. CMake variable `CMAKE_INSTALL_PREFIX` has to be set to `/usr` on most operating systems, depending on the way library paths are dealt with on 64bit systems variables like `CMAKE_INSTALL_LIBDIR` may have to be set as well.

@ -1,53 +0,0 @@
#.rst:
# FindXCB
# -------
#
# Find XCB libraries
#
# Tries to find xcb libraries on unix systems.
#
# - Be sure to set the COMPONENTS to the components you want to link to
# - The XCB_LIBRARIES variable is set ONLY to your COMPONENTS list
# - To use only a specific component check the XCB_LIBRARIES_${COMPONENT} variable
#
# The following values are defined
#
# ::
#
# XCB_FOUND - True if xcb is available
# XCB_INCLUDE_DIRS - Include directories for xcb
# XCB_LIBRARIES - List of libraries for xcb
# XCB_DEFINITIONS - List of definitions for xcb
#
#=============================================================================
# Copyright (c) 2015 Jari Vetoniemi
#
# Distributed under the OSI-approved BSD License (the "License");
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
include(FeatureSummary)
set_package_properties(XCB PROPERTIES
URL "http://xcb.freedesktop.org/"
DESCRIPTION "X protocol C-language Binding")
find_package(PkgConfig)
pkg_check_modules(PC_XCB QUIET xcb ${XCB_FIND_COMPONENTS})
find_library(XCB_LIBRARIES xcb HINTS ${PC_XCB_LIBRARY_DIRS})
find_path(XCB_INCLUDE_DIRS xcb/xcb.h PATH_SUFFIXES xcb HINTS ${PC_XCB_INCLUDE_DIRS})
foreach(COMPONENT ${XCB_FIND_COMPONENTS})
find_library(XCB_LIBRARIES_${COMPONENT} ${COMPONENT} HINTS ${PC_XCB_LIBRARY_DIRS})
list(APPEND XCB_LIBRARIES ${XCB_LIBRARIES_${COMPONENT}})
mark_as_advanced(XCB_LIBRARIES_${COMPONENT})
endforeach(COMPONENT ${XCB_FIND_COMPONENTS})
set(XCB_DEFINITIONS ${PC_XCB_CFLAGS_OTHER})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(XCB DEFAULT_MSG XCB_LIBRARIES XCB_INCLUDE_DIRS)
mark_as_advanced(XCB_INCLUDE_DIRS XCB_LIBRARIES XCB_DEFINITIONS)

@ -33,31 +33,9 @@ endif()
include(CMakeFindDependencyMacro)
find_dependency(Qt5Widgets "@REQUIRED_QT_VERSION@")
find_dependency(Qt5X11Extras "@REQUIRED_QT_VERSION@")
find_package(PkgConfig REQUIRED)
pkg_check_modules(PKG_GLIB glib-2.0)
pkg_check_modules(PKG_GIO
gio-2.0
gio-unix-2.0
)
pkg_check_modules(PKG_FM REQUIRED libfm>=@REQUIRED_LIBFM_VERSION@)
pkg_check_modules(PKG_MENUCACHE REQUIRED libmenu-cache>=@REQUIRED_LIBMENUCACHE_VERSION@)
if (NOT TARGET @LIBFM_QT_LIBRARY_NAME@)
if (POLICY CMP0024)
cmake_policy(SET CMP0024 NEW)
endif()
include("${CMAKE_CURRENT_LIST_DIR}/@LIBFM_QT_LIBRARY_NAME@-targets.cmake")
set_property(TARGET "@LIBFM_QT_LIBRARY_NAME@" APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES
"${PKG_GLIB_INCLUDE_DIRS}"
"${PKG_GIO_INCLUDE_DIRS}"
"${PKG_FM_INCLUDE_DIRS}"
"${PKG_MENUCACHE_INCLUDE_DIRS}"
)
set_property(TARGET "@LIBFM_QT_LIBRARY_NAME@" APPEND PROPERTY
INTERFACE_COMPILE_DEFINITIONS
"QT_NO_KEYWORDS"
"LIBFM_DATA_DIR=\"${PKG_FM_PREFIX}/share/libfm\""
)
endif()

17
debian/changelog vendored

@ -1,3 +1,20 @@
libfm-qt (0.11.2-1) unstable; urgency=medium
* Cherry-picking upstream release 0.11.2
* Added new symbols
* Removed build dependencies:
- cmake
- liblxqt0-dev
- libqt5xdg-dev
- pkg-config
- qttools5-dev
- qttools5-dev-tools
* Added build dependency lxqt-build-tools
* Added build dependency libfm-dev to libfm-qt-dev
* Removed models.patch, applied upstream
-- Alf Gaida <agaida@siduction.org> Thu, 22 Dec 2016 01:32:58 +0100
libfm-qt (0.11.1-3) unstable; urgency=medium
* Backported a upstream fix for Icon Emblem Support.

10
debian/control vendored

@ -7,20 +7,15 @@ Uploaders: Alf Gaida <agaida@siduction.org>,
Section: x11
Priority: optional
Build-Depends: debhelper (>= 10),
cmake (>= 3.0.2),
libfm-dev (>= 1.2.0),
libglib2.0-dev,
libkf5windowsystem-dev,
liblxqt0-dev ( >= 0.11.0),
libmenu-cache-dev,
libqt5svg5-dev,
libqt5x11extras5-dev,
libqt5xdg-dev (>= 2.0.0),
libx11-dev,
pkg-config,
qtbase5-private-dev,
qttools5-dev,
qttools5-dev-tools
lxqt-build-tools (>= 0.3.0),
qtbase5-private-dev
Standards-Version: 3.9.8
Vcs-Browser: https://anonscm.debian.org/cgit/pkg-lxqt/libfm-qt.git/?h=debian/sid
Vcs-Git: https://anonscm.debian.org/git/pkg-lxqt/libfm-qt.git -b debian/sid
@ -52,6 +47,7 @@ Breaks: libfm-qt5-dev
Architecture: any
Section: libdevel
Depends: ${misc:Depends},
libfm-dev (>= 1.2.0),
libfm-qt3 (= ${binary:Version})
Description: file management support library for pcmanfm-qt (development files)
Libfm-Qt is a companion library providing components to build desktop file

@ -421,6 +421,28 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
(c++)"Fm::MountOperation::staticMetaObject@Base" 0.10.0
(c++)"Fm::MountOperation::wait()@Base" 0.10.0
(c++)"Fm::pasteFilesFromClipboard(_FmPath*, QWidget*)@Base" 0.10.0
(c++)"Fm::PathBar::chdir(_FmPath*)@Base" 0.11.2
(c++)"Fm::PathBar::closeEditor()@Base" 0.11.2
(c++)"Fm::PathBar::contextMenuEvent(QContextMenuEvent*)@Base" 0.11.2
(c++)"Fm::PathBar::copyPath()@Base" 0.11.2
(c++)"Fm::PathBar::editingFinished()@Base" 0.11.2
(c++)"Fm::PathBar::metaObject() const@Base" 0.11.2
(c++)"Fm::PathBar::middleClickChdir(_FmPath*)@Base" 0.11.2
(c++)"Fm::PathBar::mousePressEvent(QMouseEvent*)@Base" 0.11.2
(c++)"Fm::PathBar::onButtonToggled(bool)@Base" 0.11.2
(c++)"Fm::PathBar::onReturnPressed()@Base" 0.11.2
(c++)"Fm::PathBar::onScrollButtonClicked()@Base" 0.11.2
(c++)"Fm::PathBar::openEditor()@Base" 0.11.2
(c++)"Fm::PathBar::PathBar(QWidget*)@Base" 0.11.2
(c++)"Fm::PathBar::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.11.2
(c++)"Fm::PathBar::qt_metacast(char const*)@Base" 0.11.2
(c++)"Fm::PathBar::resizeEvent(QResizeEvent*)@Base" 0.11.2
(c++)"Fm::PathBar::setArrowEnabledState(int)@Base" 0.11.2
(c++)"Fm::PathBar::setPath(Fm::Path)@Base" 0.11.2
(c++)"Fm::PathBar::setScrollButtonVisibility()@Base" 0.11.2
(c++)"Fm::PathBar::staticMetaObject@Base" 0.11.2
(c++)"Fm::PathBar::updateScrollButtonVisibility()@Base" 0.11.2
(c++)"Fm::PathBar::wheelEvent(QWheelEvent*)@Base" 0.11.2
(c++)"Fm::PathEdit::autoComplete()@Base" 0.11.0
(c++)"Fm::PathEdit::event(QEvent*)@Base" 0.11.0
(c++)"Fm::PathEdit::focusInEvent(QFocusEvent*)@Base" 0.10.0
@ -630,6 +652,7 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
(c++)"typeinfo for Fm::FontButton@Base" 0.10.0
(c++)"typeinfo for Fm::IconTheme@Base" 0.10.0
(c++)"typeinfo for Fm::MountOperation@Base" 0.10.0
(c++)"typeinfo for Fm::PathBar@Base" 0.11.2
(c++)"typeinfo for Fm::PathEdit@Base" 0.10.0
(c++)"typeinfo for Fm::PlacesModel@Base" 0.10.0
(c++)"typeinfo for Fm::PlacesModelBookmarkItem@Base" 0.10.0
@ -667,6 +690,7 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
(c++)"typeinfo name for Fm::FontButton@Base" 0.10.0
(c++)"typeinfo name for Fm::IconTheme@Base" 0.10.0
(c++)"typeinfo name for Fm::MountOperation@Base" 0.10.0
(c++)"typeinfo name for Fm::PathBar@Base" 0.11.2
(c++)"typeinfo name for Fm::PathEdit@Base" 0.10.0
(c++)"typeinfo name for Fm::PlacesModel@Base" 0.10.0
(c++)"typeinfo name for Fm::PlacesModelBookmarkItem@Base" 0.10.0
@ -704,6 +728,7 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
(c++)"vtable for Fm::FontButton@Base" 0.10.0
(c++)"vtable for Fm::IconTheme@Base" 0.10.0
(c++)"vtable for Fm::MountOperation@Base" 0.10.0
(c++)"vtable for Fm::PathBar@Base" 0.11.2
(c++)"vtable for Fm::PathEdit@Base" 0.10.0
(c++)"vtable for Fm::PlacesModel@Base" 0.10.0
(c++)"vtable for Fm::PlacesModelBookmarkItem@Base" 0.10.0

@ -1,344 +0,0 @@
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 <agaida@siduction.org>
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<FmFileInfo*>(index.data(FolderModel::FileInfoRole).value<void*>());
+ FmFileInfo* file = static_cast<FmFileInfo*>(index.data(fileInfoRole_).value<void*>());
+ FmIcon* fmicon = static_cast<FmIcon*>(index.data(fmIconRole_).value<void*>());
+ if(fmicon == nullptr && file != nullptr) {
+ fmicon = fm_file_info_get_icon(file);
+ }
+ QList<Icon> emblems = fmicon != nullptr ? IconTheme::emblems(fmicon) : QList<Icon>();
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<Icon> 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<QIcon*>(data);
- delete picon;
+static void fmIconDataDestroy(gpointer user_data) {
+ IconCacheData* data = reinterpret_cast<IconCacheData*>(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<IconCacheData*>(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<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;
+ 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<Icon> IconTheme::emblems(FmIcon* fmicon) {
+ IconCacheData* data = ensureCacheData(fmicon);
+ return data->emblems;
+}
+
+//static
+QList<Icon> 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<Icon>();
+}
+
// 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 <QIcon>
#include <QString>
#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<Icon> emblems(FmIcon* fmicon);
+ static QList<Icon> 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<PlacesModelItem*>(QStandardItemModel::itemFromIndex(index));
+ if(item != nullptr) {
+ switch(role) {
+ case FileInfoRole:
+ return QVariant::fromValue<void*>(item->fileInfo());
+ case FmIconRole:
+ return QVariant::fromValue<void*>(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 <gio/gio.h>
+#include <QPainter>
namespace Fm {
--- libfm-qt-0.11.1.orig/src/placesview.cpp
+++ libfm-qt-0.11.1/src/placesview.cpp
@@ -28,6 +28,7 @@
#include <QHeaderView>
#include <QDebug>
#include <QGuiApplication>
+#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_);

@ -1 +0,0 @@
model-places.patch

@ -1,17 +1,3 @@
include_directories(
"${LIBFM_INCLUDE_DIRS}"
"${LIBFM_INCLUDEDIR}/libfm" # to workaround incorrect #include in fm-actions.
"${LIBMENUCACHE_INCLUDE_DIRS}"
"${SYSTEM_LIBS_INCLUDE_DIRS}"
"${XCB_INCLUDE_DIRS}"
)
link_directories(
"${LIBFM_LIBRARY_DIRS}"
"${LIBMENUCACHE_LIBRARY_DIRS}"
"${SYSTEM_LIBS_LIBRARY_DIRS}"
)
set(libfm_SRCS
libfmqt.cpp
bookmarkaction.cpp
@ -43,6 +29,7 @@ set(libfm_SRCS
fileoperationdialog.cpp
renamedialog.cpp
pathedit.cpp
pathbar.cpp
colorbutton.cpp
fontbutton.cpp
browsehistory.cpp
@ -72,11 +59,15 @@ set(libfm_UIS
qt5_wrap_ui(libfm_UIS_H ${libfm_UIS})
set(LIBFM_QT_DATA_DIR "${CMAKE_INSTALL_FULL_DATADIR}/libfm-qt")
set(LIBFM_QT_INTREE_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/include")
# add translation for libfm-qt
lxqt_translate_ts(QM_FILES
UPDATE_TRANSLATIONS ${UPDATE_TRANSLATIONS}
SOURCES ${libfm_SRCS} ${libfm_UIS}
INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/libfm-qt/translations"
INSTALL_DIR "${LIBFM_QT_DATA_DIR}/translations"
PULL_TRANSLATIONS ${PULL_TRANSLATIONS}
CLEAN_TRANSLATIONS ${CLEAN_TRANSLATIONS}
TRANSLATIONS_REPO ${TRANSLATIONS_REPO}
@ -89,15 +80,9 @@ add_library(${LIBFM_QT_LIBRARY_NAME} SHARED
${QM_FILES}
)
set_property(
TARGET ${LIBFM_QT_LIBRARY_NAME} APPEND
PROPERTY COMPILE_DEFINITIONS
LIBFM_DATA_DIR="${CMAKE_INSTALL_FULL_DATADIR}/libfm-qt"
)
# only turn on custom actions support if it is enabled in libfm.
if(EXISTS "${LIBFM_INCLUDEDIR}/libfm/fm-actions.h")
set_property(TARGET ${LIBFM_QT_LIBRARY_NAME} APPEND PROPERTY COMPILE_DEFINITIONS CUSTOM_ACTIONS)
if(EXISTS "${FM_INCLUDE_DIR}/libfm/fm-actions.h")
target_compile_definitions(${LIBFM_QT_LIBRARY_NAME} PRIVATE CUSTOM_ACTIONS)
endif()
install(EXPORT
@ -109,9 +94,8 @@ install(EXPORT
target_link_libraries(${LIBFM_QT_LIBRARY_NAME}
Qt5::Widgets
Qt5::X11Extras
${LIBFM_LIBRARIES}
${LIBMENUCACHE_LIBRARIES}
${SYSTEM_LIBS_LIBRARIES}
${FM_LIBRARIES}
${MENUCACHE_LIBRARIES}
${XCB_LIBRARIES}
)
@ -122,9 +106,20 @@ set_target_properties(${LIBFM_QT_LIBRARY_NAME} PROPERTIES
)
target_include_directories(${LIBFM_QT_LIBRARY_NAME}
PRIVATE "${LIB_XCB_INDLUDE_DIRS}"
PRIVATE "${Qt5Gui_PRIVATE_INCLUDE_DIRS}"
INTERFACE "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
PUBLIC
"${FM_INCLUDE_DIRS}"
"${FM_INCLUDE_DIR}/libfm" # to workaround incorrect #include in fm-actions.
"${MENUCACHE_INCLUDE_DIRS}"
"${XCB_INCLUDE_DIRS}"
INTERFACE
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
"$<BUILD_INTERFACE:${LIBFM_QT_INTREE_INCLUDE_DIR}>"
)
target_compile_definitions(${LIBFM_QT_LIBRARY_NAME}
PRIVATE "LIBFM_QT_DATA_DIR=\"${LIBFM_QT_DATA_DIR}\""
PUBLIC "QT_NO_KEYWORDS"
)
install(FILES
@ -144,14 +139,20 @@ generate_export_header(${LIBFM_QT_LIBRARY_NAME}
EXPORT_MACRO_NAME LIBFM_QT_API
)
# InTree build
file(COPY ${libfm_HS} ${CMAKE_CURRENT_BINARY_DIR}/${LIBFM_QT_LIBRARY_NAME}_export.h
DESTINATION "${LIBFM_QT_INTREE_INCLUDE_DIR}/libfm-qt"
)
configure_package_config_file(
"${PROJECT_SOURCE_DIR}/cmake/fm-qt-config.cmake.in"
"${PROJECT_BINARY_DIR}/install/${LIBFM_QT_LIBRARY_NAME}-config.cmake"
"${CMAKE_BINARY_DIR}/${LIBFM_QT_LIBRARY_NAME}-config.cmake"
INSTALL_DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${LIBFM_QT_LIBRARY_NAME}"
)
install(FILES
"${PROJECT_BINARY_DIR}/install/${LIBFM_QT_LIBRARY_NAME}-config.cmake"
"${CMAKE_BINARY_DIR}/${LIBFM_QT_LIBRARY_NAME}-config.cmake"
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${LIBFM_QT_LIBRARY_NAME}"
COMPONENT Devel
)

@ -439,7 +439,7 @@ void FilePropsDialog::accept() {
FmPath* path = fm_file_info_get_path(fileInfo);
GFile* gf = fm_path_to_gfile(path);
GFile* parent_gf = g_file_get_parent(gf);
GFile* dest = g_file_get_child(G_FILE(parent_gf), new_name.toLocal8Bit().data());
GFile* dest = g_file_get_child(G_FILE(parent_gf), new_name.toLocal8Bit().constData());
g_object_unref(parent_gf);
GError* err = NULL;
if(!g_file_move(gf, dest,

@ -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::iconModeFromState(const QStyle::State state) {
// 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<FmFileInfo*>(index.data(FolderModel::FileInfoRole).value<void*>());
FmFileInfo* file = static_cast<FmFileInfo*>(index.data(fileInfoRole_).value<void*>());
FmIcon* fmicon = static_cast<FmIcon*>(index.data(fmIconRole_).value<void*>());
if(fmicon == nullptr && file != nullptr) {
fmicon = fm_file_info_get_icon(file);
}
QList<Icon> emblems = fmicon != nullptr ? IconTheme::emblems(fmicon) : QList<Icon>();
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, const QStyleOptionViewItem& op
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* painter, const QStyleOptionViewItem& op
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));
}
}
}
}

@ -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_;
};
}

@ -365,12 +365,14 @@ QMimeData* FolderModel::mimeData(const QModelIndexList& indexes) const {
for(const auto &index : indexes) {
FolderModelItem* item = itemFromIndex(index);
if(item) {
if(item && item->info) {
FmPath* path = fm_file_info_get_path(item->info);
char* uri = fm_path_to_uri(path);
urilist.append(uri);
urilist.append('\n');
g_free(uri);
if(path) {
char* uri = fm_path_to_uri(path);
urilist.append(uri);
urilist.append('\n');
g_free(uri);
}
}
}
data->setData("text/uri-list", urilist);
@ -531,7 +533,7 @@ QImage FolderModel::thumbnailFromIndex(const QModelIndex& index, int size) {
FolderModelItem* item = itemFromIndex(index);
if(item) {
FolderModelItem::Thumbnail* thumbnail = item->findThumbnail(size);
// qDebug("FolderModel::thumbnailFromIndex: %d, %s", thumbnail->status, item->displayName.toUtf8().data());
// qDebug("FolderModel::thumbnailFromIndex: %d, %s", thumbnail->status, item->displayName.toUtf8().constData());
switch(thumbnail->status) {
case FolderModelItem::ThumbnailNotChecked: {
// load the thumbnail

@ -28,12 +28,18 @@
namespace Fm {
class IconCacheData {
public:
QIcon qicon;
QList<Icon> 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<QIcon*>(data);
delete picon;
static void fmIconDataDestroy(gpointer user_data) {
IconCacheData* data = reinterpret_cast<IconCacheData*>(user_data);
delete data;
}
IconTheme::IconTheme():
@ -88,7 +94,7 @@ QIcon IconTheme::iconFromNames(const char* const* names) {
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* gicon) {
}
// static
IconCacheData* IconTheme::ensureCacheData(FmIcon* fmicon) {
IconCacheData* data = reinterpret_cast<IconCacheData*>(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<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;
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<Icon> IconTheme::emblems(FmIcon* fmicon) {
IconCacheData* data = ensureCacheData(fmicon);
return data->emblems;
}
//static
QList<Icon> 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<Icon>();
}
// 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.

@ -25,6 +25,7 @@
#include <QIcon>
#include <QString>
#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<Icon> emblems(FmIcon* fmicon);
static QList<Icon> 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_;

@ -49,7 +49,7 @@ LibFmQtData::LibFmQtData(): refCount(1) {
// g_setenv("G_MESSAGES_DEBUG", "all", true);
iconTheme = new IconTheme();
thumbnailLoader = new ThumbnailLoader();
translator.load("libfm-qt_" + QLocale::system().name(), LIBFM_DATA_DIR "/translations");
translator.load("libfm-qt_" + QLocale::system().name(), LIBFM_QT_DATA_DIR "/translations");
}
LibFmQtData::~LibFmQtData() {

@ -0,0 +1,295 @@
/*
* Copyright (C) 2016 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 "pathbar.h"
#include "pathbar_p.h"
#include <QToolButton>
#include <QPushButton>
#include <QScrollArea>
#include <QScrollBar>
#include <QHBoxLayout>
#include <QResizeEvent>
#include <QContextMenuEvent>
#include <QMenu>
#include <QClipboard>
#include <QApplication>
#include <QTimer>
#include <QDebug>
#include "pathedit.h"
namespace Fm {
PathBar::PathBar(QWidget *parent):
QWidget(parent),
tempPathEdit_(nullptr) {
QHBoxLayout* topLayout = new QHBoxLayout(this);
topLayout->setContentsMargins(0, 0, 0, 0);
topLayout->setSpacing(0);
bool rtl(layoutDirection() == Qt::RightToLeft);
// the arrow button used to scroll to start of the path
scrollToStart_ = new QToolButton(this);
scrollToStart_->setArrowType(rtl ? Qt::RightArrow : Qt::LeftArrow);
scrollToStart_->setAutoRepeat(true);
scrollToStart_->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::MinimumExpanding);
connect(scrollToStart_, &QToolButton::clicked, this, &PathBar::onScrollButtonClicked);
topLayout->addWidget(scrollToStart_);
// there might be too many buttons when the path is long, so make it scrollable.
scrollArea_ = new QScrollArea(this);
scrollArea_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
scrollArea_->setFrameShape(QFrame::NoFrame);
scrollArea_->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scrollArea_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scrollArea_->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
scrollArea_->verticalScrollBar()->setDisabled(true);
connect(scrollArea_->horizontalScrollBar(), &QAbstractSlider::valueChanged, this, &PathBar::setArrowEnabledState);
topLayout->addWidget(scrollArea_, 1); // stretch factor=1, make it expandable
// the arrow button used to scroll to end of the path
scrollToEnd_ = new QToolButton(this);
scrollToEnd_->setArrowType(rtl ? Qt::LeftArrow : Qt::RightArrow);
scrollToEnd_->setAutoRepeat(true);
scrollToEnd_->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::MinimumExpanding);
connect(scrollToEnd_, &QToolButton::clicked, this, &PathBar::onScrollButtonClicked);
topLayout->addWidget(scrollToEnd_);
// container widget of the path buttons
buttonsWidget_ = new QWidget(this);
buttonsWidget_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
buttonsLayout_ = new QHBoxLayout(buttonsWidget_);
buttonsLayout_->setContentsMargins(0, 0, 0, 0);
buttonsLayout_->setSpacing(0);
buttonsLayout_->setSizeConstraint(QLayout::SetFixedSize); // required when added to scroll area according to QScrollArea doc.
scrollArea_->setWidget(buttonsWidget_); // make the buttons widget scrollable if the path is too long
}
void PathBar::resizeEvent(QResizeEvent* event) {
QWidget::resizeEvent(event);
updateScrollButtonVisibility();
}
void PathBar::wheelEvent(QWheelEvent* event) {
QWidget::wheelEvent(event);
QAbstractSlider::SliderAction action = QAbstractSlider::SliderNoAction;
int vDelta = event->angleDelta().y();
if(vDelta > 0) {
if(scrollToStart_->isEnabled())
action = QAbstractSlider::SliderSingleStepSub;
}
else if(vDelta < 0) {
if(scrollToEnd_->isEnabled())
action = QAbstractSlider::SliderSingleStepAdd;
}
scrollArea_->horizontalScrollBar()->triggerAction(action);
}
void PathBar::mousePressEvent(QMouseEvent *event) {
QWidget::mousePressEvent(event);
if(event->button() == Qt::LeftButton) {
openEditor();
}
else if(event->button() == Qt::MiddleButton) {
PathButton* btn = qobject_cast<PathButton*>(childAt(event->x(), event->y()));
if(btn != nullptr) {
scrollArea_->ensureWidgetVisible(btn, 0);
Q_EMIT middleClickChdir(btn->pathElement().dataPtr());
}
}
}
void PathBar::contextMenuEvent(QContextMenuEvent *event) {
QMenu* menu = new QMenu(this);
connect(menu, &QMenu::aboutToHide, menu, &QMenu::deleteLater);
QAction* action = menu->addAction(tr("&Edit Path"));
connect(action, &QAction::triggered, this, &PathBar::openEditor);
action = menu->addAction(tr("&Copy Path"));
connect(action, &QAction::triggered, this, &PathBar::copyPath);
menu->popup(mapToGlobal(event->pos()));
}
void PathBar::updateScrollButtonVisibility() {
// Wait for the horizontal scrollbar to be completely shaped.
// Without this, the enabled state of arrow buttons might be
// wrong when the pathbar is created for the first time.
QTimer::singleShot(0, this, SLOT(setScrollButtonVisibility()));
}
void PathBar::setScrollButtonVisibility() {
bool showScrollers;
if(tempPathEdit_ != nullptr) {
showScrollers = false;
}
else {
showScrollers = (buttonsLayout_->sizeHint().width() > width());
}
scrollToStart_->setVisible(showScrollers);
scrollToEnd_->setVisible(showScrollers);
if(showScrollers) {
QScrollBar* sb = scrollArea_->horizontalScrollBar();
int value = sb->value();
scrollToStart_->setEnabled(value != sb->minimum());
scrollToEnd_->setEnabled(value != sb->maximum());
}
}
void PathBar::onButtonToggled(bool checked) {
if(checked) {
PathButton* btn = static_cast<PathButton*>(sender());
scrollArea_->ensureWidgetVisible(btn, 0); // make the button visible
currentPath_ = btn->pathElement();
// qDebug("chdir: %s", currentPath_.displayName(false));
Q_EMIT chdir(currentPath_.dataPtr());
}
}
void PathBar::onScrollButtonClicked() {
QToolButton* btn = static_cast<QToolButton*>(sender());
QAbstractSlider::SliderAction action = QAbstractSlider::SliderNoAction;
if(btn == scrollToEnd_)
action = QAbstractSlider::SliderSingleStepAdd;
else if (btn == scrollToStart_)
action = QAbstractSlider::SliderSingleStepSub;
scrollArea_->horizontalScrollBar()->triggerAction(action);
}
void PathBar::setPath(Path path) {
if(!currentPath_.isNull() && !path.isNull() && currentPath_ == path) // same path, do nothing
return;
currentPath_ = path;
int buttonCount = buttonsLayout_->count() - 1; // the last item is a spacer
// check if we already have a button for this path (FIXME: this loop is inefficient)
for(int i = buttonCount - 1; i >= 0; --i) {
PathButton* btn = static_cast<PathButton*>(buttonsLayout_->itemAt(i)->widget());
if(btn->pathElement() == path) { // we have a button for this path
btn->setChecked(true); // toggle the button
/* we don't need to emit chdir signal here since later
* toggled signal will be triggered on the button, which
* in turns emit chdir. */
return;
}
}
/* FIXME: if the new path is the subdir of our full path, actually
* we can append several new buttons rather than re-create
* all of the buttons. */
setUpdatesEnabled(false);
// we do not have the path in the buttons list
// destroy existing path element buttons and the spacer
QLayoutItem* item;
while((item = buttonsLayout_->takeAt(0)) != nullptr) {
delete item->widget();
delete item;
}
Path pathElement = path;
// create new buttons for the new path
while(!pathElement.isNull()) {
// qDebug("%s", pathElement.displayName(false));
PathButton* btn = new PathButton(pathElement, buttonsWidget_);
btn->show();
connect(btn, &QPushButton::toggled, this, &PathBar::onButtonToggled);
pathElement = pathElement.getParent();
buttonsLayout_->insertWidget(0, btn);
}
buttonCount = buttonsLayout_->count();
if(buttonCount) {
PathButton* lastBtn = static_cast<PathButton*>(buttonsLayout_->itemAt(buttonCount - 1)->widget());
// we don't have to emit the chdir signal since the "onButtonToggled()" slot will be triggered by this.
lastBtn->setChecked(true);
}
buttonsLayout_->addStretch(1);
// we don't want to scroll vertically. make the scroll area fit the height of the buttons
// FIXME: this is a little bit hackish :-(
scrollArea_->setFixedHeight(buttonsLayout_->sizeHint().height());
updateScrollButtonVisibility();
setUpdatesEnabled(true);
}
void PathBar::openEditor() {
if(tempPathEdit_ == nullptr) {
tempPathEdit_ = new PathEdit(this);
layout()->replaceWidget(scrollArea_, tempPathEdit_, Qt::FindDirectChildrenOnly);
scrollArea_->hide();
scrollToStart_->setVisible(false);
scrollToEnd_->setVisible(false);
char* pathStr = currentPath_.toStr();
tempPathEdit_->setText(pathStr);
g_free(pathStr);
connect(tempPathEdit_, &PathEdit::returnPressed, this, &PathBar::onReturnPressed);
connect(tempPathEdit_, &PathEdit::editingFinished, this, &PathBar::closeEditor);
}
tempPathEdit_->setFocus();
tempPathEdit_->selectAll();
}
void PathBar::closeEditor() {
if(tempPathEdit_ == nullptr)
return;
// If a menu has popped up synchronously (with QMenu::exec), the path buttons may be drawn
// but the path-edit may not disappear until the menu is closed. So, we hide it here.
tempPathEdit_->setVisible(false);
layout()->replaceWidget(tempPathEdit_, scrollArea_, Qt::FindDirectChildrenOnly);
scrollArea_->show();
if(buttonsLayout_->sizeHint().width() > width()) {
scrollToStart_->setVisible(true);
scrollToEnd_->setVisible(true);
}
tempPathEdit_->deleteLater();
tempPathEdit_ = nullptr;
updateScrollButtonVisibility();
Q_EMIT editingFinished();
}
void PathBar::copyPath() {
char* pathStr = currentPath_.toStr();
QApplication::clipboard()->setText(pathStr);
g_free(pathStr);
}
void PathBar::onReturnPressed() {
QByteArray pathStr = tempPathEdit_->text().toLocal8Bit();
Path path = Path::newForDisplayName(pathStr.constData());
setPath(path);
}
void PathBar::setArrowEnabledState(int value) {
if(buttonsLayout_->sizeHint().width() > width()) {
QScrollBar* sb = scrollArea_->horizontalScrollBar();
scrollToStart_->setEnabled(value != sb->minimum());
scrollToEnd_->setEnabled(value != sb->maximum());
}
}
} // namespace Fm

@ -0,0 +1,86 @@
/*
* Copyright (C) 2016 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
*
*/
#ifndef FM_PATHBAR_H
#define FM_PATHBAR_H
#include "libfmqtglobals.h"
#include <QWidget>
#include "path.h"
class QToolButton;
class QScrollArea;
class QPushButton;
class QHBoxLayout;
namespace Fm {
class PathEdit;
class LIBFM_QT_API PathBar: public QWidget {
Q_OBJECT
public:
explicit PathBar(QWidget *parent = 0);
Path path() {
return currentPath_;
}
void setPath(Path path);
Q_SIGNALS:
void chdir(FmPath* path);
void middleClickChdir(FmPath* path);
void editingFinished();
public Q_SLOTS:
void openEditor();
void closeEditor();
void copyPath();
private Q_SLOTS:
void onButtonToggled(bool checked);
void onScrollButtonClicked();
void onReturnPressed();
void setArrowEnabledState(int value);
void setScrollButtonVisibility();
protected:
void resizeEvent(QResizeEvent* event);
void wheelEvent (QWheelEvent* event);
void mousePressEvent(QMouseEvent *event);
void contextMenuEvent(QContextMenuEvent *event);
private:
void updateScrollButtonVisibility();
private:
QToolButton* scrollToStart_;
QToolButton* scrollToEnd_;
QScrollArea* scrollArea_;
QWidget* buttonsWidget_;
QHBoxLayout* buttonsLayout_;
PathEdit* tempPathEdit_;
Path currentPath_; // currently active path
};
} // namespace Fm
#endif // FM_PATHBAR_H

@ -0,0 +1,78 @@
/*
* Copyright (C) 2016 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
*
*/
#ifndef FM_PATHBAR_P_H
#define FM_PATHBAR_P_H
#include <QToolButton>
#include <QStyle>
#include <QEvent>
#include <QMouseEvent>
#include "path.h"
namespace Fm {
class PathButton: public QToolButton {
Q_OBJECT
public:
PathButton(Fm::Path pathElement, QWidget* parent = nullptr):
QToolButton(parent),
pathElement_(pathElement) {
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::MinimumExpanding);
setCheckable(true);
setAutoExclusive(true);
setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
/* respect the toolbar icon size (can be set with some styles) */
int icnSize = style()->pixelMetric(QStyle::PM_ToolBarIconSize);
setIconSize(QSize(icnSize, icnSize));
char* label = pathElement.displayBasename();
setText(label);
g_free(label);
if(pathElement.getParent().isNull()) { /* this element is root */
QIcon icon = QIcon::fromTheme("drive-harddisk");
setIcon(icon);
}
}
Path pathElement() {
return pathElement_;
}
void setPathElement(Path pathElement) {
pathElement_ = pathElement;
}
void changeEvent(QEvent* event) override {
QToolButton::changeEvent(event);
if(event->type() == QEvent::StyleChange) {
int icnSize = style()->pixelMetric(QStyle::PM_ToolBarIconSize);
setIconSize(QSize(icnSize, icnSize));
}
}
private:
Path pathElement_;
};
} // namespace Fm
#endif // FM_PATHBAR_P_H

@ -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 QModelIndex& index) const {
return QStandardItemModel::flags(index);
}
QVariant PlacesModel::data(const QModelIndex &index, int role) const {
if(index.column() == 0 && index.parent().isValid()) {
PlacesModelItem* item = static_cast<PlacesModelItem*>(QStandardItemModel::itemFromIndex(index));
if(item != nullptr) {
switch(role) {
case FileInfoRole:
return QVariant::fromValue<void*>(item->fileInfo());
case FmIconRole:
return QVariant::fromValue<void*>(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

@ -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();

@ -21,6 +21,7 @@
#include "placesmodelitem.h"
#include "icontheme.h"
#include <gio/gio.h>
#include <QPainter>
namespace Fm {

@ -28,6 +28,7 @@
#include <QHeaderView>
#include <QDebug>
#include <QGuiApplication>
#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_);

@ -234,7 +234,7 @@ QVariant ProxyFolderModel::data(const QModelIndex& index, int role) const {
void ProxyFolderModel::onThumbnailLoaded(const QModelIndex& srcIndex, int size) {
// FolderModel* srcModel = static_cast<FolderModel*>(sourceModel());
// FolderModelItem* item = srcModel->itemFromIndex(srcIndex);
// qDebug("ProxyFolderModel::onThumbnailLoaded: %d, %s", size, item->displayName.toUtf8().data());
// qDebug("ProxyFolderModel::onThumbnailLoaded: %d, %s", size, item->displayName.toUtf8().constData());
if(size == thumbnailSize_) { // if a thumbnail of the size we want is loaded
QModelIndex index = mapFromSource(srcIndex);

@ -136,7 +136,7 @@ void renameFile(FmFileInfo *file, QWidget *parent) {
GFile* gf = fm_path_to_gfile(path);
GFile* parent_gf = g_file_get_parent(gf);
GFile* dest = g_file_get_child(G_FILE(parent_gf), new_name.toLocal8Bit().data());
GFile* dest = g_file_get_child(G_FILE(parent_gf), new_name.toLocal8Bit().constData());
g_object_unref(parent_gf);
GError* err = NULL;
@ -193,7 +193,7 @@ _retry:
return;
GFile* parent_gf = fm_path_to_gfile(parentDir);
GFile* dest_gf = g_file_get_child(G_FILE(parent_gf), new_name.toLocal8Bit().data());
GFile* dest_gf = g_file_get_child(G_FILE(parent_gf), new_name.toLocal8Bit().constData());
g_object_unref(parent_gf);
GError* err = NULL;

Loading…
Cancel
Save