Adding upstream version 0.11.2.
Signed-off-by: Alf Gaida <agaida@siduction.org>
This commit is contained in:
parent
4591188e01
commit
932a3bcc26
10
.gitignore
vendored
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
|
||||
*~
|
54
CHANGELOG
54
CHANGELOG
@ -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(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)
|
||||
|
||||
#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
|
||||
)
|
||||
|
||||
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()
|
||||
|
@ -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() {
|
||||
|
295
src/pathbar.cpp
Normal file
295
src/pathbar.cpp
Normal file
@ -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
|
86
src/pathbar.h
Normal file
86
src/pathbar.h
Normal file
@ -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
|
78
src/pathbar_p.h
Normal file
78
src/pathbar_p.h
Normal file
@ -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…
x
Reference in New Issue
Block a user