Added new versions, mangled some symbols
This commit is contained in:
parent
f95b471116
commit
0829311d25
4
AUTHORS
4
AUTHORS
@ -1,6 +1,6 @@
|
|||||||
Upstream Authors:
|
Upstream Authors:
|
||||||
LXQt team: http://lxqt.org
|
LXQt team: https://lxqt.org
|
||||||
Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
||||||
|
|
||||||
Copyright:
|
Copyright:
|
||||||
Copyright (c) 2013-2017 LXQt team
|
Copyright (c) 2013-2018 LXQt team
|
||||||
|
81
CHANGELOG
81
CHANGELOG
@ -1,7 +1,86 @@
|
|||||||
|
|
||||||
libfm-qt-0.12.0 / 2017-10-21
|
libfm-qt-0.13.0 / 2018-05-21
|
||||||
============================
|
============================
|
||||||
|
|
||||||
|
* Bumped minor version to 13
|
||||||
|
* Fixed shortcut detection
|
||||||
|
* Delete CachedFolderModel immediately on unreffing it
|
||||||
|
* Fix crashes in new templates code
|
||||||
|
* Remove the C++ wrapper for the old FmPath struct in libfm.
|
||||||
|
* Avoid using FmPath from libfm in FmSearch.
|
||||||
|
* Removed redundant code
|
||||||
|
* Modify Fm::BasicFileLauncher APIs to use Fm::FileInfoPtr consistently.
|
||||||
|
* Add typedef FileInfoPtr for std::shared_ptr<const FileInfo> since it's so frequently used.
|
||||||
|
* Correctly handle the mounting of mountable paths and correctly parse the target URIs of shortcuts.
|
||||||
|
* Add new APIs Fm::MountOperation::mountEnclosingVolume() and Fm::MountOperation::mountMountable() and deprecate Fm::MountOperation::mount().
|
||||||
|
* Also cover local shortcuts
|
||||||
|
* Added "reject" to exec dialog
|
||||||
|
* Delete some libfm compatibility wrappers.
|
||||||
|
* Delete the unused old FmTemplate wrapper.
|
||||||
|
* Create the template items in the "Create New" menu with the new C++ file template APIs.
|
||||||
|
* Port template support to C++ (Fm::Templates class).
|
||||||
|
* Add convinient functions in Fm::FileOperation to set dest paths for file transfer jobs.
|
||||||
|
* Made job async again
|
||||||
|
* Fixed launching of desktop files
|
||||||
|
* Cleanup
|
||||||
|
* CMake: Prevent in-source builds
|
||||||
|
* Fix Fm::FileInfo::isDir() and isExecutableType() to make its behavior consistent with libfm.
|
||||||
|
* Port file lancher to C++ and Implement Fm::BasicFileLauncher base class. * Migrate Fm::FileLauncher to the new C++ implementation.
|
||||||
|
* Port archiver integration to C++ (#182)
|
||||||
|
* Fully port all file operations to C++ 11 (#181)
|
||||||
|
* Add kitty to terminals.list
|
||||||
|
* Italic font for hidden items
|
||||||
|
* Select multiple files
|
||||||
|
* No visible cursor in File Properties labels
|
||||||
|
* Just corrected a misspelling
|
||||||
|
* Elided labels for file operation dialog
|
||||||
|
* fix namespace, fixes lxqt/libfm-qt/issues/174
|
||||||
|
* Misc link fixes
|
||||||
|
* Fixes some pathes after repo move
|
||||||
|
* Fix a cause of crash in `AppChooserComboBox`
|
||||||
|
* build: Bump version
|
||||||
|
* Drop Fm::IconTheme
|
||||||
|
* iconinfo: Properly handle multiple names
|
||||||
|
* Some code cleanup
|
||||||
|
* Fixed custom action execution mode
|
||||||
|
* Don't drop on files
|
||||||
|
* Prevent possible c++11 range-loop container detach
|
||||||
|
* See `.bak` and `.old` as backup extensions; also follow GLib
|
||||||
|
* Ensure that rename editor has opaque background
|
||||||
|
* Use special/custom folder icons for bookmarks
|
||||||
|
* Added two missing cases of `mapFromSource()`
|
||||||
|
* Support hiding items in Places side-pane
|
||||||
|
* Fixed sorting by type/owner
|
||||||
|
* Fix lambda connections in filedialog (#159)
|
||||||
|
* Drop Q_FOREACH
|
||||||
|
* Fix memory leak in thumbnail loading (#150)
|
||||||
|
* Be more tolerant
|
||||||
|
* Fix the "Folders" key in custom actions
|
||||||
|
* Add Group column and don't use owner's full name
|
||||||
|
* Fix comparison of integers of different signs
|
||||||
|
* Guarantee 64-bit time attributes (#148)
|
||||||
|
* Added a proxy setting for backup as hidden (#145)
|
||||||
|
* Fixed the logic of queued deletion
|
||||||
|
* Track folders containing cut files only with QString
|
||||||
|
* Copy selected pathbar text to selection clipboard
|
||||||
|
* Smooth scrolling for icon and thumbnail views
|
||||||
|
* cmake: Handle CMP0071
|
||||||
|
* Prepare libfm-qt for bulk rename
|
||||||
|
* No change queue of files in the deletion queue
|
||||||
|
* FileInfo: Fix potential SEGFAULT
|
||||||
|
* Fix two devices for one mount
|
||||||
|
* Always wait for the folder to load before selecting
|
||||||
|
* Really cancel multiple renaming on cancelling
|
||||||
|
* Prevent a potential crash in xdndworkaround
|
||||||
|
* Fix wrong gray-out of cut files
|
||||||
|
* Merge side-pane with its surroundings
|
||||||
|
* Prompt dialog specifically for desktop files
|
||||||
|
* Remove unnecessary noise
|
||||||
|
|
||||||
|
0.12.0 / 2017-10-21
|
||||||
|
===================
|
||||||
|
|
||||||
|
* Release 0.12.0: Update changelog
|
||||||
* Add data transferred to file operation dialog.
|
* Add data transferred to file operation dialog.
|
||||||
* Bump versions
|
* Bump versions
|
||||||
* Disable context-menu actions that cannot be used
|
* Disable context-menu actions that cannot be used
|
||||||
|
@ -4,27 +4,27 @@ project(libfm-qt)
|
|||||||
set(LIBFM_QT_LIBRARY_NAME "fm-qt" CACHE STRING "fm-qt")
|
set(LIBFM_QT_LIBRARY_NAME "fm-qt" CACHE STRING "fm-qt")
|
||||||
|
|
||||||
set(LIBFM_QT_VERSION_MAJOR 0)
|
set(LIBFM_QT_VERSION_MAJOR 0)
|
||||||
set(LIBFM_QT_VERSION_MINOR 12)
|
set(LIBFM_QT_VERSION_MINOR 13)
|
||||||
set(LIBFM_QT_VERSION_PATCH 0)
|
set(LIBFM_QT_VERSION_PATCH 0)
|
||||||
set(LIBFM_QT_VERSION ${LIBFM_QT_VERSION_MAJOR}.${LIBFM_QT_VERSION_MINOR}.${LIBFM_QT_VERSION_PATCH})
|
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")
|
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
# We use the libtool versioning scheme for the internal so name, "current:revision:age"
|
# We use the libtool versioning scheme for the internal so name, "current:revision:age"
|
||||||
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info
|
# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info
|
||||||
# https://www.sourceware.org/autobook/autobook/autobook_91.html
|
# https://www.sourceware.org/autobook/autobook/autobook_91.html
|
||||||
# http://pusling.com/blog/?p=352
|
# http://pusling.com/blog/?p=352
|
||||||
# Actually, libtool uses different ways on different operating systems. So there is no
|
# 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.
|
# universal way to translate a libtool version-info to a cmake version.
|
||||||
# We use "(current-age).age.revision" as the cmake version.
|
# We use "(current-age).age.revision" as the cmake version.
|
||||||
# current: 4, revision: 0, age: 1 => version: 3.1.0
|
# current: 5, revision: 0, age: 0 => version: 5.0.0
|
||||||
set(LIBFM_QT_LIB_VERSION "3.1.0")
|
set(LIBFM_QT_LIB_VERSION "5.0.0")
|
||||||
set(LIBFM_QT_LIB_SOVERSION "3")
|
set(LIBFM_QT_LIB_SOVERSION "5")
|
||||||
|
|
||||||
set(REQUIRED_QT_VERSION "5.2")
|
set(REQUIRED_QT_VERSION "5.7.1")
|
||||||
set(REQUIRED_LIBFM_VERSION "1.2.0")
|
set(REQUIRED_LIBFM_VERSION "1.2.0")
|
||||||
set(REQUIRED_LIBMENUCACHE_VERSION "0.4.0")
|
set(REQUIRED_LIBMENUCACHE_VERSION "0.4.0")
|
||||||
set(REQUIRED_LXQT_BUILD_TOOLS_VERSION "0.4.0")
|
set(REQUIRED_LXQT_BUILD_TOOLS_VERSION "0.5.0")
|
||||||
|
|
||||||
if (NOT CMAKE_BUILD_TYPE)
|
if (NOT CMAKE_BUILD_TYPE)
|
||||||
set(CMAKE_BUILD_TYPE Release)
|
set(CMAKE_BUILD_TYPE Release)
|
||||||
@ -46,11 +46,13 @@ option(UPDATE_TRANSLATIONS "Update source translation translations/*.ts files" O
|
|||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
include(GenerateExportHeader)
|
include(GenerateExportHeader)
|
||||||
include(CMakePackageConfigHelpers)
|
include(CMakePackageConfigHelpers)
|
||||||
|
include(LXQtPreventInSourceBuilds)
|
||||||
include(LXQtTranslateTs)
|
include(LXQtTranslateTs)
|
||||||
include(LXQtTranslateDesktop)
|
include(LXQtTranslateDesktop)
|
||||||
include(LXQtCompilerSettings NO_POLICY_SCOPE)
|
include(LXQtCompilerSettings NO_POLICY_SCOPE)
|
||||||
|
|
||||||
set(CMAKE_AUTOMOC TRUE)
|
set(CMAKE_AUTOMOC TRUE)
|
||||||
|
set(CMAKE_AUTOUIC ON)
|
||||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
|
|
||||||
write_basic_package_version_file(
|
write_basic_package_version_file(
|
||||||
@ -70,8 +72,7 @@ add_subdirectory(data)
|
|||||||
|
|
||||||
# add Doxygen support to generate API docs
|
# add Doxygen support to generate API docs
|
||||||
# References:
|
# References:
|
||||||
# http://majewsky.wordpress.com/2010/08/14/tip-of-the-day-cmake-and-doxygen/
|
# https://majewsky.wordpress.com/2010/08/14/tip-of-the-day-cmake-and-doxygen/
|
||||||
# http://www.bluequartz.net/projects/EIM_Segmentation/SoftwareDocumentation/html/usewithcmakeproject.html
|
|
||||||
option(BUILD_DOCUMENTATION "Use Doxygen to create the HTML based API documentation" OFF)
|
option(BUILD_DOCUMENTATION "Use Doxygen to create the HTML based API documentation" OFF)
|
||||||
if(BUILD_DOCUMENTATION)
|
if(BUILD_DOCUMENTATION)
|
||||||
find_package(Doxygen REQUIRED)
|
find_package(Doxygen REQUIRED)
|
||||||
|
12
Doxyfile.in
12
Doxyfile.in
@ -20,7 +20,7 @@
|
|||||||
# that follow. The default is UTF-8 which is also the encoding used for all
|
# that follow. The default is UTF-8 which is also the encoding used for all
|
||||||
# text before the first occurrence of this tag. Doxygen uses libiconv (or the
|
# text before the first occurrence of this tag. Doxygen uses libiconv (or the
|
||||||
# iconv built into libc) for the transcoding. See
|
# iconv built into libc) for the transcoding. See
|
||||||
# http://www.gnu.org/software/libiconv for the list of possible encodings.
|
# https://www.gnu.org/software/libiconv for the list of possible encodings.
|
||||||
|
|
||||||
DOXYFILE_ENCODING = UTF-8
|
DOXYFILE_ENCODING = UTF-8
|
||||||
|
|
||||||
@ -247,7 +247,7 @@ EXTENSION_MAPPING =
|
|||||||
|
|
||||||
# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
|
# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
|
||||||
# comments according to the Markdown format, which allows for more readable
|
# comments according to the Markdown format, which allows for more readable
|
||||||
# documentation. See http://daringfireball.net/projects/markdown/ for details.
|
# documentation. See https://daringfireball.net/projects/markdown/ for details.
|
||||||
# The output of markdown processing is further processed by doxygen, so you
|
# The output of markdown processing is further processed by doxygen, so you
|
||||||
# can mix doxygen, HTML, and XML commands with Markdown formatting.
|
# can mix doxygen, HTML, and XML commands with Markdown formatting.
|
||||||
# Disable only in case of backward compatibilities issues.
|
# Disable only in case of backward compatibilities issues.
|
||||||
@ -587,7 +587,7 @@ LAYOUT_FILE =
|
|||||||
# containing the references data. This must be a list of .bib files. The
|
# containing the references data. This must be a list of .bib files. The
|
||||||
# .bib extension is automatically appended if omitted. Using this command
|
# .bib extension is automatically appended if omitted. Using this command
|
||||||
# requires the bibtex tool to be installed. See also
|
# requires the bibtex tool to be installed. See also
|
||||||
# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
|
# https://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
|
||||||
# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
|
# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
|
||||||
# feature you need bibtex and perl available in the search path. Do not use
|
# feature you need bibtex and perl available in the search path. Do not use
|
||||||
# file names with spaces, bibtex cannot handle them.
|
# file names with spaces, bibtex cannot handle them.
|
||||||
@ -659,7 +659,7 @@ INPUT = "@PROJECT_SOURCE_DIR@/src"
|
|||||||
# This tag can be used to specify the character encoding of the source files
|
# This tag can be used to specify the character encoding of the source files
|
||||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
|
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
|
||||||
# also the default input encoding. Doxygen uses libiconv (or the iconv built
|
# also the default input encoding. Doxygen uses libiconv (or the iconv built
|
||||||
# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
|
# into libc) for the transcoding. See https://www.gnu.org/software/libiconv for
|
||||||
# the list of possible encodings.
|
# the list of possible encodings.
|
||||||
|
|
||||||
INPUT_ENCODING = UTF-8
|
INPUT_ENCODING = UTF-8
|
||||||
@ -931,7 +931,7 @@ HTML_EXTRA_FILES =
|
|||||||
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
|
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
|
||||||
# Doxygen will adjust the colors in the style sheet and background images
|
# Doxygen will adjust the colors in the style sheet and background images
|
||||||
# according to this color. Hue is specified as an angle on a colorwheel,
|
# according to this color. Hue is specified as an angle on a colorwheel,
|
||||||
# see http://en.wikipedia.org/wiki/Hue for more information.
|
# see https://en.wikipedia.org/wiki/Hue for more information.
|
||||||
# For instance the value 0 represents red, 60 is yellow, 120 is green,
|
# For instance the value 0 represents red, 60 is yellow, 120 is green,
|
||||||
# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
|
# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
|
||||||
# The allowed range is 0 to 359.
|
# The allowed range is 0 to 359.
|
||||||
@ -984,7 +984,7 @@ HTML_INDEX_NUM_ENTRIES = 100
|
|||||||
# directory and running "make install" will install the docset in
|
# directory and running "make install" will install the docset in
|
||||||
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
|
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
|
||||||
# it at startup.
|
# it at startup.
|
||||||
# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
|
# See https://developer.apple.com/tools/creatingdocsetswithdoxygen.html
|
||||||
# for more information.
|
# for more information.
|
||||||
|
|
||||||
GENERATE_DOCSET = NO
|
GENERATE_DOCSET = NO
|
||||||
|
36
README.md
36
README.md
@ -2,26 +2,44 @@
|
|||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
libfm-qt is the Qt port of libfm, a library providing components to build desktop file managers which belongs to [LXDE](http://lxde.org).
|
libfm-qt is the Qt port of libfm, a library providing components to build
|
||||||
|
desktop file managers which belongs to [LXDE](https://lxde.org).
|
||||||
|
|
||||||
libfm-qt is licensed under the terms of the [LGPLv2.1](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) or any later version. See file LICENSE for its full text.
|
libfm-qt is licensed under the terms of the
|
||||||
|
[LGPLv2.1](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html)
|
||||||
|
or any later version. See file LICENSE for its full text.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
### Compiling source code
|
### Compiling source code
|
||||||
|
|
||||||
Runtime dependencies are Qt X11 Extras and libfm ≥ 1,2 (not all features are provided by libfm-qt yet).
|
Runtime dependencies are Qt X11 Extras and libfm ≥ 1.2
|
||||||
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.
|
(not all features are provided by libfm-qt yet).
|
||||||
|
Additional build dependencies are CMake,
|
||||||
|
[lxqt-build-tools](https://github.com/lxqt/lxqt-build-tools) and optionally Git
|
||||||
|
to pull latest VCS checkouts. The localization files were outsourced to
|
||||||
|
repository [lxqt-l10n](https://github.com/lxqt/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.
|
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.
|
||||||
|
|
||||||
To build run `make`, to install `make install` which accepts variable `DESTDIR` as usual.
|
To build run `make`, to install `make install` which accepts variable `DESTDIR`
|
||||||
|
as usual.
|
||||||
|
|
||||||
### Binary packages
|
### Binary packages
|
||||||
|
|
||||||
Official binary packages are available in Arch Linux, Debian (as of Debian stretch) and openSUSE (Leap 42.1 and Tumbleweed).
|
Official binary packages are available in Arch Linux, Debian (as of Debian
|
||||||
The library is still missing in Fedora which is providing version 0.10.0 of PCManFM-Qt only so far. This version was still including the code outsourced into libfm-qt later so libfm-qt will have to be provided by Fedora, too, as soon as the distribution upgrades to PCManFM-Qt ≥ 0.10.1.
|
stretch) and openSUSE (Leap 42.1 and Tumbleweed).
|
||||||
|
The library is still missing in Fedora which is providing version 0.10.0 of
|
||||||
|
PCManFM-Qt only so far. This version was still including the code outsourced
|
||||||
|
into libfm-qt later so libfm-qt will have to be provided by Fedora, too,
|
||||||
|
as soon as the distribution upgrades to PCManFM-Qt ≥ 0.10.1.
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
Issues should go to the tracker of PCManFM-Qt at https://github.com/lxde/pcmanfm-qt/issues.
|
Issues should go to the tracker of PCManFM-Qt at
|
||||||
|
https://github.com/lxqt/pcmanfm-qt/issues.
|
||||||
|
@ -75,3 +75,6 @@ desktop_id=terminology.desktop
|
|||||||
open_arg=-e
|
open_arg=-e
|
||||||
noclose_arg=--hold -e
|
noclose_arg=--hold -e
|
||||||
desktop_id=termite.desktop
|
desktop_id=termite.desktop
|
||||||
|
|
||||||
|
[kitty]
|
||||||
|
desktop_id=kitty.desktop
|
||||||
|
11
debian/changelog
vendored
11
debian/changelog
vendored
@ -1,8 +1,15 @@
|
|||||||
libfm-qt (0.13.0-1) experimental; urgency=medium
|
libfm-qt (0.13.0-1) experimental; urgency=medium
|
||||||
|
|
||||||
*
|
* Cherry-picking upstream release 0.13.0.
|
||||||
|
* Removed build dependency libglib2.0-dev, thrown in via lxqt-build-tools
|
||||||
|
* Bumped build dependency lxqt-build-tools to >= 0.5.0~
|
||||||
|
* Renamed libfm-qt3 -> libfm-qt5. soname bumped
|
||||||
|
* Added Breaks and replaces for libfm-qt3
|
||||||
|
* Bumped years in copyright
|
||||||
|
* Added symbols and removed two not used old (internal) ones, no soname bump
|
||||||
|
needed.
|
||||||
|
|
||||||
-- Alf Gaida <agaida@siduction.org> Mon, 21 May 2018 16:44:53 +0200
|
-- Alf Gaida <agaida@siduction.org> Wed, 23 May 2018 20:58:31 +0200
|
||||||
|
|
||||||
libfm-qt (0.12.0-17) unstable; urgency=medium
|
libfm-qt (0.12.0-17) unstable; urgency=medium
|
||||||
|
|
||||||
|
402
debian/libfm-qt3.symbols → debian/libfm-qt5.symbols
vendored
402
debian/libfm-qt3.symbols → debian/libfm-qt5.symbols
vendored
@ -1,4 +1,4 @@
|
|||||||
libfm-qt.so.3 libfm-qt3 #MINVER#
|
libfm-qt.so.5 libfm-qt5 #MINVER#
|
||||||
(c++)"Fm::AppChooserComboBox::AppChooserComboBox(QWidget*)@Base" 0.10.0
|
(c++)"Fm::AppChooserComboBox::AppChooserComboBox(QWidget*)@Base" 0.10.0
|
||||||
(c++)"Fm::AppChooserComboBox::isChanged() const@Base" 0.12.0
|
(c++)"Fm::AppChooserComboBox::isChanged() const@Base" 0.12.0
|
||||||
(c++)"Fm::AppChooserComboBox::metaObject() const@Base" 0.10.0
|
(c++)"Fm::AppChooserComboBox::metaObject() const@Base" 0.10.0
|
||||||
@ -37,7 +37,35 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::AppMenuView::selectionChanged(QItemSelection const&, QItemSelection const&)@Base" 0.12.0
|
(c++)"Fm::AppMenuView::selectionChanged(QItemSelection const&, QItemSelection const&)@Base" 0.12.0
|
||||||
(c++)"Fm::AppMenuView::staticMetaObject@Base" 0.10.0
|
(c++)"Fm::AppMenuView::staticMetaObject@Base" 0.10.0
|
||||||
(c++)"Fm::AppMenuView::~AppMenuView()@Base" 0.10.0
|
(c++)"Fm::AppMenuView::~AppMenuView()@Base" 0.10.0
|
||||||
|
(c++)"Fm::Archiver::Archiver()@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Archiver::allArchivers()@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Archiver::allArchivers_@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Archiver::createArchive(_GAppLaunchContext*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > const&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Archiver::defaultArchiver()@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Archiver::defaultArchiver_@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Archiver::extractArchives(_GAppLaunchContext*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > const&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Archiver::extractArchivesTo(_GAppLaunchContext*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > const&, Fm::FilePath const&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Archiver::isMimeTypeSupported(char const*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Archiver::launchProgram(_GAppLaunchContext*, char const*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > const&, Fm::FilePath const&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Archiver::setDefaultArchiver(Fm::Archiver*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Archiver::setDefaultArchiverByName(char const*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::BasicFileLauncher::BasicFileLauncher()@Base" 0.13.0~
|
||||||
|
(c++)"Fm::BasicFileLauncher::ask(char const*, char* const*, int)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::BasicFileLauncher::askExecFile(std::shared_ptr<Fm::FileInfo const> const&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::BasicFileLauncher::chooseApp(Fm::FileInfoList const&, char const*, Fm::GErrorPtr&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::BasicFileLauncher::handleShortcut(std::shared_ptr<Fm::FileInfo const> const&, _GAppLaunchContext*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::BasicFileLauncher::launchDesktopEntry(char const*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > const&, _GAppLaunchContext*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::BasicFileLauncher::launchDesktopEntry(std::shared_ptr<Fm::FileInfo const> const&, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > const&, _GAppLaunchContext*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::BasicFileLauncher::launchExecutable(std::shared_ptr<Fm::FileInfo const> const&, _GAppLaunchContext*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::BasicFileLauncher::launchFiles(Fm::FileInfoList const&, _GAppLaunchContext*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::BasicFileLauncher::launchPaths(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, _GAppLaunchContext*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::BasicFileLauncher::launchWithApp(_GAppInfo*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > const&, _GAppLaunchContext*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::BasicFileLauncher::launchWithDefaultApp(std::shared_ptr<Fm::FileInfo const> const&, _GAppLaunchContext*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::BasicFileLauncher::openFolder(_GAppLaunchContext*, Fm::FileInfoList const&, Fm::GErrorPtr&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::BasicFileLauncher::showError(_GAppLaunchContext*, Fm::GErrorPtr&, Fm::FilePath const&, std::shared_ptr<Fm::FileInfo const> const&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::BasicFileLauncher::~BasicFileLauncher()@Base" 0.13.0~
|
||||||
(c++)"Fm::BookmarkAction::BookmarkAction(std::shared_ptr<Fm::BookmarkItem const>, QObject*)@Base" 0.12.0
|
(c++)"Fm::BookmarkAction::BookmarkAction(std::shared_ptr<Fm::BookmarkItem const>, QObject*)@Base" 0.12.0
|
||||||
|
(c++)"Fm::BookmarkItem::BookmarkItem(Fm::FilePath const&, QString)@Base" 0.13.0~
|
||||||
(c++)"Fm::Bookmarks::Bookmarks(QObject*)@Base" 0.12.0
|
(c++)"Fm::Bookmarks::Bookmarks(QObject*)@Base" 0.12.0
|
||||||
(c++)"Fm::Bookmarks::changed()@Base" 0.12.0
|
(c++)"Fm::Bookmarks::changed()@Base" 0.12.0
|
||||||
(c++)"Fm::Bookmarks::globalInstance()@Base" 0.12.0
|
(c++)"Fm::Bookmarks::globalInstance()@Base" 0.12.0
|
||||||
@ -82,30 +110,20 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::ColorButton::setColor(QColor const&)@Base" 0.10.0
|
(c++)"Fm::ColorButton::setColor(QColor const&)@Base" 0.10.0
|
||||||
(c++)"Fm::ColorButton::staticMetaObject@Base" 0.10.0
|
(c++)"Fm::ColorButton::staticMetaObject@Base" 0.10.0
|
||||||
(c++)"Fm::ColorButton::~ColorButton()@Base" 0.10.0
|
(c++)"Fm::ColorButton::~ColorButton()@Base" 0.10.0
|
||||||
(c++)"Fm::CopyJob::CopyJob(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > const&&, Fm::FilePath const&&, Fm::CopyJob::Mode)@Base" 0.12.0
|
|
||||||
(c++)"Fm::CopyJob::CopyJob(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > const&, Fm::FilePath const&, Fm::CopyJob::Mode)@Base" 0.12.0
|
|
||||||
(c++)"Fm::CopyJob::copyDir(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo>, Fm::FilePath const&)@Base" 0.12.0
|
|
||||||
(c++)"Fm::CopyJob::copyPath(Fm::FilePath const&, Fm::FilePath const&, char const*)@Base" 0.12.0
|
|
||||||
(c++)"Fm::CopyJob::copyPath(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo> const&, Fm::FilePath const&, char const*)@Base" 0.12.0
|
|
||||||
(c++)"Fm::CopyJob::copyRegularFile(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo>, Fm::FilePath const&)@Base" 0.12.0
|
|
||||||
(c++)"Fm::CopyJob::copySpecialFile(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo>, Fm::FilePath const&)@Base" 0.12.0
|
|
||||||
(c++)"Fm::CopyJob::exec()@Base" 0.12.0
|
|
||||||
(c++|arch= !armel !armhf !i386 !mips !mipsel !hppa !hurd-i386 !kfreebsd-i386 !m68k !powerpc !sh4 !x32 )"Fm::CopyJob::gfileProgressCallback(long, long, Fm::CopyJob*)@Base" 0.12.0
|
|
||||||
(c++|arch= !amd64 !arm64 !mips64el !ppc64el !s390x !alpha !ia64 !kfreebsd-amd64 !ppc64 !riscv64 !sparc64 )"Fm::CopyJob::gfileProgressCallback(long long, long long, Fm::CopyJob*)@Base" 0.12.0
|
|
||||||
(c++)"Fm::CopyJob::makeDir(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo>, Fm::FilePath const&)@Base" 0.12.0
|
|
||||||
(c++)"Fm::CopyJob::metaObject() const@Base" 0.12.0
|
|
||||||
(c++)"Fm::CopyJob::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.12.0
|
|
||||||
(c++)"Fm::CopyJob::qt_metacast(char const*)@Base" 0.12.0
|
|
||||||
(c++)"Fm::CopyJob::staticMetaObject@Base" 0.12.0
|
|
||||||
(c++)"Fm::CreateNewMenu::CreateNewMenu(QWidget*, Fm::FilePath, QWidget*)@Base" 0.12.0
|
(c++)"Fm::CreateNewMenu::CreateNewMenu(QWidget*, Fm::FilePath, QWidget*)@Base" 0.12.0
|
||||||
|
(c++)"Fm::CreateNewMenu::addTemplateItem(std::shared_ptr<Fm::TemplateItem const> const&)@Base" 0.13.0~
|
||||||
(c++)"Fm::CreateNewMenu::metaObject() const@Base" 0.10.0
|
(c++)"Fm::CreateNewMenu::metaObject() const@Base" 0.10.0
|
||||||
(c++)"Fm::CreateNewMenu::onCreateNew()@Base" 0.10.0
|
(c++)"Fm::CreateNewMenu::onCreateNew()@Base" 0.10.0
|
||||||
(c++)"Fm::CreateNewMenu::onCreateNewFile()@Base" 0.10.0
|
(c++)"Fm::CreateNewMenu::onCreateNewFile()@Base" 0.10.0
|
||||||
(c++)"Fm::CreateNewMenu::onCreateNewFolder()@Base" 0.10.0
|
(c++)"Fm::CreateNewMenu::onCreateNewFolder()@Base" 0.10.0
|
||||||
(c++)"Fm::CreateNewMenu::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.10.0
|
(c++)"Fm::CreateNewMenu::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.10.0
|
||||||
(c++)"Fm::CreateNewMenu::qt_metacast(char const*)@Base" 0.10.0
|
(c++)"Fm::CreateNewMenu::qt_metacast(char const*)@Base" 0.10.0
|
||||||
|
(c++)"Fm::CreateNewMenu::removeTemplateItem(std::shared_ptr<Fm::TemplateItem const> const&)@Base" 0.13.0~
|
||||||
(c++)"Fm::CreateNewMenu::staticMetaObject@Base" 0.10.0
|
(c++)"Fm::CreateNewMenu::staticMetaObject@Base" 0.10.0
|
||||||
|
(c++)"Fm::CreateNewMenu::updateTemplateItem(std::shared_ptr<Fm::TemplateItem const> const&, std::shared_ptr<Fm::TemplateItem const> const&)@Base" 0.13.0~
|
||||||
(c++)"Fm::CreateNewMenu::~CreateNewMenu()@Base" 0.10.0
|
(c++)"Fm::CreateNewMenu::~CreateNewMenu()@Base" 0.10.0
|
||||||
|
(c++)"Fm::DeleteJob::DeleteJob(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > const&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::DeleteJob::DeleteJob(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >&&)@Base" 0.13.0~
|
||||||
(c++)"Fm::DeleteJob::deleteDirContent(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo>)@Base" 0.12.0
|
(c++)"Fm::DeleteJob::deleteDirContent(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo>)@Base" 0.12.0
|
||||||
(c++)"Fm::DeleteJob::deleteFile(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo>)@Base" 0.12.0
|
(c++)"Fm::DeleteJob::deleteFile(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo>)@Base" 0.12.0
|
||||||
(c++)"Fm::DeleteJob::exec()@Base" 0.12.0
|
(c++)"Fm::DeleteJob::exec()@Base" 0.12.0
|
||||||
@ -113,6 +131,7 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::DeleteJob::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.12.0
|
(c++)"Fm::DeleteJob::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.12.0
|
||||||
(c++)"Fm::DeleteJob::qt_metacast(char const*)@Base" 0.12.0
|
(c++)"Fm::DeleteJob::qt_metacast(char const*)@Base" 0.12.0
|
||||||
(c++)"Fm::DeleteJob::staticMetaObject@Base" 0.12.0
|
(c++)"Fm::DeleteJob::staticMetaObject@Base" 0.12.0
|
||||||
|
(c++)"Fm::DeleteJob::~DeleteJob()@Base" 0.13.0~
|
||||||
(c++)"Fm::DirListJob::DirListJob(Fm::FilePath const&, Fm::DirListJob::Flags, std::shared_ptr<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > const> const&)@Base" 0.12.0
|
(c++)"Fm::DirListJob::DirListJob(Fm::FilePath const&, Fm::DirListJob::Flags, std::shared_ptr<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > const> const&)@Base" 0.12.0
|
||||||
(c++)"Fm::DirListJob::exec()@Base" 0.12.0
|
(c++)"Fm::DirListJob::exec()@Base" 0.12.0
|
||||||
(c++)"Fm::DirListJob::filesFound(Fm::FileInfoList&)@Base" 0.12.0
|
(c++)"Fm::DirListJob::filesFound(Fm::FileInfoList&)@Base" 0.12.0
|
||||||
@ -206,8 +225,18 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::EditBookmarksDialog::qt_metacast(char const*)@Base" 0.10.0
|
(c++)"Fm::EditBookmarksDialog::qt_metacast(char const*)@Base" 0.10.0
|
||||||
(c++)"Fm::EditBookmarksDialog::staticMetaObject@Base" 0.10.0
|
(c++)"Fm::EditBookmarksDialog::staticMetaObject@Base" 0.10.0
|
||||||
(c++)"Fm::EditBookmarksDialog::~EditBookmarksDialog()@Base" 0.10.0
|
(c++)"Fm::EditBookmarksDialog::~EditBookmarksDialog()@Base" 0.10.0
|
||||||
(c++)"Fm::FileChangeAttrJob::FileChangeAttrJob()@Base" 0.12.0
|
(c++)"Fm::FileChangeAttrJob::FileChangeAttrJob(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileChangeAttrJob::changeFileDisplayName(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo> const&, char const*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileChangeAttrJob::changeFileGroup(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo> const&, unsigned int)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileChangeAttrJob::changeFileHidden(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo> const&, bool)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileChangeAttrJob::changeFileIcon(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo> const&, Fm::GObjectPtr<_GIcon>&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileChangeAttrJob::changeFileMode(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo> const&, unsigned int, unsigned int)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileChangeAttrJob::changeFileOwner(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo> const&, unsigned int)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileChangeAttrJob::changeFileTargetUri(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo> const&, char const*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileChangeAttrJob::exec()@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileChangeAttrJob::handleError(Fm::GErrorPtr&, Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo> const&, Fm::Job::ErrorSeverity)@Base" 0.13.0~
|
||||||
(c++)"Fm::FileChangeAttrJob::metaObject() const@Base" 0.12.0
|
(c++)"Fm::FileChangeAttrJob::metaObject() const@Base" 0.12.0
|
||||||
|
(c++)"Fm::FileChangeAttrJob::processFile(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo> const&)@Base" 0.13.0~
|
||||||
(c++)"Fm::FileChangeAttrJob::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.12.0
|
(c++)"Fm::FileChangeAttrJob::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.12.0
|
||||||
(c++)"Fm::FileChangeAttrJob::qt_metacast(char const*)@Base" 0.12.0
|
(c++)"Fm::FileChangeAttrJob::qt_metacast(char const*)@Base" 0.12.0
|
||||||
(c++)"Fm::FileChangeAttrJob::staticMetaObject@Base" 0.12.0
|
(c++)"Fm::FileChangeAttrJob::staticMetaObject@Base" 0.12.0
|
||||||
@ -270,7 +299,7 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::FileInfo::isExecutableType() const@Base" 0.12.0
|
(c++)"Fm::FileInfo::isExecutableType() const@Base" 0.12.0
|
||||||
(c++)"Fm::FileInfo::setFromGFileInfo(Fm::GObjectPtr<_GFileInfo> const&, Fm::FilePath const&)@Base" 0.12.0
|
(c++)"Fm::FileInfo::setFromGFileInfo(Fm::GObjectPtr<_GFileInfo> const&, Fm::FilePath const&)@Base" 0.12.0
|
||||||
(c++)"Fm::FileInfo::~FileInfo()@Base" 0.12.0
|
(c++)"Fm::FileInfo::~FileInfo()@Base" 0.12.0
|
||||||
(c++)"Fm::FileInfoJob::FileInfoJob(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, Fm::FilePath, std::shared_ptr<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > const> const&)@Base" 0.12.0
|
(c++)"Fm::FileInfoJob::FileInfoJob(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, Fm::FilePath, std::shared_ptr<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > const> const&)@Base" 0.13.0~
|
||||||
(c++)"Fm::FileInfoJob::exec()@Base" 0.12.0
|
(c++)"Fm::FileInfoJob::exec()@Base" 0.12.0
|
||||||
(c++)"Fm::FileInfoJob::gotInfo(Fm::FilePath const&, std::shared_ptr<Fm::FileInfo const>&)@Base" 0.12.0
|
(c++)"Fm::FileInfoJob::gotInfo(Fm::FilePath const&, std::shared_ptr<Fm::FileInfo const>&)@Base" 0.12.0
|
||||||
(c++)"Fm::FileInfoJob::metaObject() const@Base" 0.12.0
|
(c++)"Fm::FileInfoJob::metaObject() const@Base" 0.12.0
|
||||||
@ -281,15 +310,12 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::FileInfoList::isSameType() const@Base" 0.12.0
|
(c++)"Fm::FileInfoList::isSameType() const@Base" 0.12.0
|
||||||
(c++)"Fm::FileLauncher::FileLauncher()@Base" 0.10.0
|
(c++)"Fm::FileLauncher::FileLauncher()@Base" 0.10.0
|
||||||
(c++)"Fm::FileLauncher::ask(char const*, char* const*, int)@Base" 0.10.0
|
(c++)"Fm::FileLauncher::ask(char const*, char* const*, int)@Base" 0.10.0
|
||||||
(c++)"Fm::FileLauncher::error(_GAppLaunchContext*, _GError*, _FmPath*)@Base" 0.10.0
|
(c++)"Fm::FileLauncher::askExecFile(std::shared_ptr<Fm::FileInfo const> const&)@Base" 0.13.0~
|
||||||
(c++)"Fm::FileLauncher::execFile(_FmFileInfo*)@Base" 0.10.0
|
(c++)"Fm::FileLauncher::chooseApp(Fm::FileInfoList const&, char const*, Fm::GErrorPtr&)@Base" 0.13.0~
|
||||||
(c++)"Fm::FileLauncher::funcs@Base" 0.10.0
|
(c++)"Fm::FileLauncher::launchFiles(QWidget*, Fm::FileInfoList const&)@Base" 0.13.0~
|
||||||
(c++)"Fm::FileLauncher::getApp(_GList*, _FmMimeType*, _GError**)@Base" 0.10.0
|
(c++)"Fm::FileLauncher::launchPaths(QWidget*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > const&)@Base" 0.13.0~
|
||||||
(c++)"Fm::FileLauncher::launchFiles(QWidget*, Fm::FileInfoList)@Base" 0.12.0
|
(c++)"Fm::FileLauncher::openFolder(_GAppLaunchContext*, Fm::FileInfoList const&, Fm::GErrorPtr&)@Base" 0.13.0~
|
||||||
(c++)"Fm::FileLauncher::launchFiles(QWidget*, _GList*)@Base" 0.10.0
|
(c++)"Fm::FileLauncher::showError(_GAppLaunchContext*, Fm::GErrorPtr&, Fm::FilePath const&, std::shared_ptr<Fm::FileInfo const> const&)@Base" 0.13.0~
|
||||||
(c++)"Fm::FileLauncher::launchPaths(QWidget*, _GList*)@Base" 0.10.0
|
|
||||||
(c++)"Fm::FileLauncher::launchPaths(QWidget*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >)@Base" 0.12.0
|
|
||||||
(c++)"Fm::FileLauncher::openFolder(_GAppLaunchContext*, _GList*, _GError**)@Base" 0.10.0
|
|
||||||
(c++)"Fm::FileLauncher::~FileLauncher()@Base" 0.12.0
|
(c++)"Fm::FileLauncher::~FileLauncher()@Base" 0.12.0
|
||||||
(c++)"Fm::FileLinkJob::FileLinkJob()@Base" 0.12.0
|
(c++)"Fm::FileLinkJob::FileLinkJob()@Base" 0.12.0
|
||||||
(c++)"Fm::FileMenu::FileMenu(Fm::FileInfoList, std::shared_ptr<Fm::FileInfo const>, Fm::FilePath, bool, QString const&, QWidget*)@Base" 0.12.0
|
(c++)"Fm::FileMenu::FileMenu(Fm::FileInfoList, std::shared_ptr<Fm::FileInfo const>, Fm::FilePath, bool, QString const&, QWidget*)@Base" 0.12.0
|
||||||
@ -321,37 +347,41 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::FileMonitor::qt_metacast(char const*)@Base" 0.12.0
|
(c++)"Fm::FileMonitor::qt_metacast(char const*)@Base" 0.12.0
|
||||||
(c++)"Fm::FileMonitor::staticMetaObject@Base" 0.12.0
|
(c++)"Fm::FileMonitor::staticMetaObject@Base" 0.12.0
|
||||||
(c++)"Fm::FileOperation::FileOperation(Fm::FileOperation::Type, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, QObject*)@Base" 0.12.0
|
(c++)"Fm::FileOperation::FileOperation(Fm::FileOperation::Type, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, QObject*)@Base" 0.12.0
|
||||||
|
(c++)"Fm::FileOperation::cancel()@Base" 0.13.0~
|
||||||
(c++)"Fm::FileOperation::changeAttrFiles(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, QWidget*)@Base" 0.12.0
|
(c++)"Fm::FileOperation::changeAttrFiles(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, QWidget*)@Base" 0.12.0
|
||||||
(c++)"Fm::FileOperation::copyFiles(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, Fm::FilePath, QWidget*)@Base" 0.12.0
|
(c++)"Fm::FileOperation::copyFiles(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, Fm::FilePath, QWidget*)@Base" 0.12.0
|
||||||
|
(c++)"Fm::FileOperation::copyFiles(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, QWidget*)@Base" 0.13.0~
|
||||||
(c++)"Fm::FileOperation::deleteFiles(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, bool, QWidget*)@Base" 0.12.0
|
(c++)"Fm::FileOperation::deleteFiles(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, bool, QWidget*)@Base" 0.12.0
|
||||||
(c++)"Fm::FileOperation::disconnectJob()@Base" 0.10.0
|
(c++)"Fm::FileOperation::disconnectJob()@Base" 0.10.0
|
||||||
(c++)"Fm::FileOperation::finished()@Base" 0.10.0
|
(c++)"Fm::FileOperation::finished()@Base" 0.10.0
|
||||||
(c++)"Fm::FileOperation::handleFinish()@Base" 0.10.0
|
|
||||||
(c++)"Fm::FileOperation::metaObject() const@Base" 0.10.0
|
(c++)"Fm::FileOperation::metaObject() const@Base" 0.10.0
|
||||||
(c++)"Fm::FileOperation::moveFiles(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, Fm::FilePath, QWidget*)@Base" 0.12.0
|
(c++)"Fm::FileOperation::moveFiles(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, Fm::FilePath, QWidget*)@Base" 0.12.0
|
||||||
(c++)"Fm::FileOperation::onFileOpsJobAsk(_FmFileOpsJob*, char const*, char* const*, Fm::FileOperation*)@Base" 0.10.0
|
(c++)"Fm::FileOperation::moveFiles(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, QWidget*)@Base" 0.13.0~
|
||||||
(c++)"Fm::FileOperation::onFileOpsJobAskRename(_FmFileOpsJob*, _FmFileInfo*, _FmFileInfo*, char**, Fm::FileOperation*)@Base" 0.10.0
|
(c++)"Fm::FileOperation::onJobCancalled()@Base" 0.13.0~
|
||||||
(c++)"Fm::FileOperation::onFileOpsJobCancelled(_FmFileOpsJob*, Fm::FileOperation*)@Base" 0.10.0
|
(c++)"Fm::FileOperation::onJobError(Fm::GErrorPtr const&, Fm::Job::ErrorSeverity, Fm::Job::ErrorAction&)@Base" 0.13.0~
|
||||||
(c++)"Fm::FileOperation::onFileOpsJobCurFile(_FmFileOpsJob*, char const*, Fm::FileOperation*)@Base" 0.10.0
|
(c++)"Fm::FileOperation::onJobFileExists(Fm::FileInfo const&, Fm::FileInfo const&, Fm::FileOperationJob::FileExistsAction&, Fm::FilePath&)@Base" 0.13.0~
|
||||||
(c++)"Fm::FileOperation::onFileOpsJobError(_FmFileOpsJob*, _GError*, FmJobErrorSeverity, Fm::FileOperation*)@Base" 0.10.0
|
(c++)"Fm::FileOperation::onJobFinish()@Base" 0.13.0~
|
||||||
(c++)"Fm::FileOperation::onFileOpsJobFinished(_FmFileOpsJob*, Fm::FileOperation*)@Base" 0.10.0
|
(c++)"Fm::FileOperation::onJobPrepared()@Base" 0.13.0~
|
||||||
(c++)"Fm::FileOperation::onFileOpsJobPercent(_FmFileOpsJob*, unsigned int, Fm::FileOperation*)@Base" 0.10.0
|
|
||||||
(c++)"Fm::FileOperation::onFileOpsJobPrepared(_FmFileOpsJob*, Fm::FileOperation*)@Base" 0.10.0
|
|
||||||
(c++)"Fm::FileOperation::onUiTimeout()@Base" 0.10.0
|
(c++)"Fm::FileOperation::onUiTimeout()@Base" 0.10.0
|
||||||
(c++)"Fm::FileOperation::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.10.0
|
(c++)"Fm::FileOperation::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.10.0
|
||||||
(c++)"Fm::FileOperation::qt_metacast(char const*)@Base" 0.10.0
|
(c++)"Fm::FileOperation::qt_metacast(char const*)@Base" 0.10.0
|
||||||
(c++)"Fm::FileOperation::run()@Base" 0.10.0
|
(c++)"Fm::FileOperation::run()@Base" 0.10.0
|
||||||
|
(c++)"Fm::FileOperation::setChmod(unsigned int, unsigned int)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileOperation::setChown(unsigned int, unsigned int)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileOperation::setDestFiles(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >)@Base" 0.13.0~
|
||||||
(c++)"Fm::FileOperation::setDestination(Fm::FilePath)@Base" 0.12.0
|
(c++)"Fm::FileOperation::setDestination(Fm::FilePath)@Base" 0.12.0
|
||||||
|
(c++)"Fm::FileOperation::setRecursiveChattr(bool)@Base" 0.13.0~
|
||||||
(c++)"Fm::FileOperation::showDialog()@Base" 0.10.0
|
(c++)"Fm::FileOperation::showDialog()@Base" 0.10.0
|
||||||
(c++)"Fm::FileOperation::staticMetaObject@Base" 0.10.0
|
(c++)"Fm::FileOperation::staticMetaObject@Base" 0.10.0
|
||||||
(c++)"Fm::FileOperation::symlinkFiles(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, Fm::FilePath, QWidget*)@Base" 0.12.0
|
(c++)"Fm::FileOperation::symlinkFiles(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, Fm::FilePath, QWidget*)@Base" 0.12.0
|
||||||
|
(c++)"Fm::FileOperation::symlinkFiles(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, QWidget*)@Base" 0.13.0~
|
||||||
(c++)"Fm::FileOperation::trashFiles(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, bool, QWidget*)@Base" 0.12.0
|
(c++)"Fm::FileOperation::trashFiles(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, bool, QWidget*)@Base" 0.12.0
|
||||||
(c++)"Fm::FileOperation::unTrashFiles(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, QWidget*)@Base" 0.12.0
|
(c++)"Fm::FileOperation::unTrashFiles(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, QWidget*)@Base" 0.12.0
|
||||||
(c++)"Fm::FileOperation::~FileOperation()@Base" 0.10.0
|
(c++)"Fm::FileOperation::~FileOperation()@Base" 0.10.0
|
||||||
(c++)"Fm::FileOperationDialog::FileOperationDialog(Fm::FileOperation*)@Base" 0.10.0
|
(c++)"Fm::FileOperationDialog::FileOperationDialog(Fm::FileOperation*)@Base" 0.10.0
|
||||||
(c++)"Fm::FileOperationDialog::ask(QString, char* const*)@Base" 0.10.0
|
(c++)"Fm::FileOperationDialog::ask(QString, char* const*)@Base" 0.10.0
|
||||||
(c++)"Fm::FileOperationDialog::askRename(_FmFileInfo*, _FmFileInfo*, QString&)@Base" 0.10.0
|
(c++)"Fm::FileOperationDialog::askRename(Fm::FileInfo const&, Fm::FileInfo const&, Fm::FilePath&)@Base" 0.13.0~
|
||||||
(c++)"Fm::FileOperationDialog::error(_GError*, FmJobErrorSeverity)@Base" 0.10.0
|
(c++)"Fm::FileOperationDialog::error(_GError*, Fm::Job::ErrorSeverity)@Base" 0.13.0~
|
||||||
(c++)"Fm::FileOperationDialog::metaObject() const@Base" 0.10.0
|
(c++)"Fm::FileOperationDialog::metaObject() const@Base" 0.10.0
|
||||||
(c++)"Fm::FileOperationDialog::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.10.0
|
(c++)"Fm::FileOperationDialog::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.10.0
|
||||||
(c++)"Fm::FileOperationDialog::qt_metacast(char const*)@Base" 0.10.0
|
(c++)"Fm::FileOperationDialog::qt_metacast(char const*)@Base" 0.10.0
|
||||||
@ -360,6 +390,7 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++|arch= !armel !armhf !i386 !mips !mipsel !hppa !hurd-i386 !kfreebsd-i386 !m68k !powerpc !sh4 !x32 )"Fm::FileOperationDialog::setDataTransferred(unsigned long, unsigned long)@Base" 0.12.0
|
(c++|arch= !armel !armhf !i386 !mips !mipsel !hppa !hurd-i386 !kfreebsd-i386 !m68k !powerpc !sh4 !x32 )"Fm::FileOperationDialog::setDataTransferred(unsigned long, unsigned long)@Base" 0.12.0
|
||||||
(c++|arch= !amd64 !arm64 !mips64el !ppc64el !s390x !alpha !ia64 !kfreebsd-amd64 !ppc64 !ppc64 !riscv64 !sparc64 )"Fm::FileOperationDialog::setDataTransferred(unsigned long long, unsigned long long)@Base" 0.12.0
|
(c++|arch= !amd64 !arm64 !mips64el !ppc64el !s390x !alpha !ia64 !kfreebsd-amd64 !ppc64 !ppc64 !riscv64 !sparc64 )"Fm::FileOperationDialog::setDataTransferred(unsigned long long, unsigned long long)@Base" 0.12.0
|
||||||
(c++)"Fm::FileOperationDialog::setDestPath(Fm::FilePath const&)@Base" 0.12.0
|
(c++)"Fm::FileOperationDialog::setDestPath(Fm::FilePath const&)@Base" 0.12.0
|
||||||
|
(optional|c++|arch= !i386 )"Fm::FileOperationDialog::setFilesProcessed(unsigned long, unsigned long)@Base" 0.13.0~
|
||||||
(c++)"Fm::FileOperationDialog::setPercent(unsigned int)@Base" 0.10.0
|
(c++)"Fm::FileOperationDialog::setPercent(unsigned int)@Base" 0.10.0
|
||||||
(c++)"Fm::FileOperationDialog::setPrepared()@Base" 0.10.0
|
(c++)"Fm::FileOperationDialog::setPrepared()@Base" 0.10.0
|
||||||
(c++)"Fm::FileOperationDialog::setRemainingTime(unsigned int)@Base" 0.10.0
|
(c++)"Fm::FileOperationDialog::setRemainingTime(unsigned int)@Base" 0.10.0
|
||||||
@ -370,6 +401,7 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++|arch= !armel !armhf !i386 !mips !mipsel !hppa !hurd-i386 !kfreebsd-i386 !m68k !powerpc !sh4 !x32 )"Fm::FileOperationJob::addFinishedAmount(unsigned long, unsigned long)@Base" 0.12.0
|
(c++|arch= !armel !armhf !i386 !mips !mipsel !hppa !hurd-i386 !kfreebsd-i386 !m68k !powerpc !sh4 !x32 )"Fm::FileOperationJob::addFinishedAmount(unsigned long, unsigned long)@Base" 0.12.0
|
||||||
(c++|arch= !amd64 !arm64 !mips64el !ppc64el !s390x !alpha !ia64 !kfreebsd-amd64 !ppc64 !riscv64 !sparc64 )"Fm::FileOperationJob::addFinishedAmount(unsigned long long, unsigned long long)@Base" 0.12.0
|
(c++|arch= !amd64 !arm64 !mips64el !ppc64el !s390x !alpha !ia64 !kfreebsd-amd64 !ppc64 !riscv64 !sparc64 )"Fm::FileOperationJob::addFinishedAmount(unsigned long long, unsigned long long)@Base" 0.12.0
|
||||||
(c++)"Fm::FileOperationJob::askRename(Fm::FileInfo const&, Fm::FileInfo const&, Fm::FilePath&)@Base" 0.12.0
|
(c++)"Fm::FileOperationJob::askRename(Fm::FileInfo const&, Fm::FileInfo const&, Fm::FilePath&)@Base" 0.12.0
|
||||||
|
(c++)"Fm::FileOperationJob::currentFile() const@Base" 0.13.0~
|
||||||
(c++|arch= !armel !armhf !i386 !mips !mipsel !hppa !hurd-i386 !kfreebsd-i386 !m68k !powerpc !sh4 !x32 )"Fm::FileOperationJob::currentFileProgress(Fm::FilePath&, unsigned long&, unsigned long&) const@Base" 0.12.0
|
(c++|arch= !armel !armhf !i386 !mips !mipsel !hppa !hurd-i386 !kfreebsd-i386 !m68k !powerpc !sh4 !x32 )"Fm::FileOperationJob::currentFileProgress(Fm::FilePath&, unsigned long&, unsigned long&) const@Base" 0.12.0
|
||||||
(c++|arch= !amd64 !arm64 !mips64el !ppc64el !s390x !alpha !ia64 !kfreebsd-amd64 !ppc64 !riscv64 !sparc64 )"Fm::FileOperationJob::currentFileProgress(Fm::FilePath&, unsigned long long&, unsigned long long&) const@Base" 0.12.0
|
(c++|arch= !amd64 !arm64 !mips64el !ppc64el !s390x !alpha !ia64 !kfreebsd-amd64 !ppc64 !riscv64 !sparc64 )"Fm::FileOperationJob::currentFileProgress(Fm::FilePath&, unsigned long long&, unsigned long long&) const@Base" 0.12.0
|
||||||
(c++)"Fm::FileOperationJob::fileExists(Fm::FileInfo const&, Fm::FileInfo const&, Fm::FileOperationJob::FileExistsAction&, Fm::FilePath&)@Base" 0.12.0
|
(c++)"Fm::FileOperationJob::fileExists(Fm::FileInfo const&, Fm::FileInfo const&, Fm::FileOperationJob::FileExistsAction&, Fm::FilePath&)@Base" 0.12.0
|
||||||
@ -377,6 +409,7 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++|arch= !amd64 !arm64 !mips64el !ppc64el !s390x !alpha !ia64 !kfreebsd-amd64 !ppc64 !riscv64 !sparc64 )"Fm::FileOperationJob::finishedAmount(unsigned long long&, unsigned long long&) const@Base" 0.12.0
|
(c++|arch= !amd64 !arm64 !mips64el !ppc64el !s390x !alpha !ia64 !kfreebsd-amd64 !ppc64 !riscv64 !sparc64 )"Fm::FileOperationJob::finishedAmount(unsigned long long&, unsigned long long&) const@Base" 0.12.0
|
||||||
(c++)"Fm::FileOperationJob::metaObject() const@Base" 0.12.0
|
(c++)"Fm::FileOperationJob::metaObject() const@Base" 0.12.0
|
||||||
(c++)"Fm::FileOperationJob::preparedToRun()@Base" 0.12.0
|
(c++)"Fm::FileOperationJob::preparedToRun()@Base" 0.12.0
|
||||||
|
(c++)"Fm::FileOperationJob::progress() const@Base" 0.13.0~
|
||||||
(c++)"Fm::FileOperationJob::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.12.0
|
(c++)"Fm::FileOperationJob::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.12.0
|
||||||
(c++)"Fm::FileOperationJob::qt_metacast(char const*)@Base" 0.12.0
|
(c++)"Fm::FileOperationJob::qt_metacast(char const*)@Base" 0.12.0
|
||||||
(c++)"Fm::FileOperationJob::setCurrentFile(Fm::FilePath const&)@Base" 0.12.0
|
(c++)"Fm::FileOperationJob::setCurrentFile(Fm::FilePath const&)@Base" 0.12.0
|
||||||
@ -427,6 +460,30 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::FileSystemInfoJob::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.12.0
|
(c++)"Fm::FileSystemInfoJob::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.12.0
|
||||||
(c++)"Fm::FileSystemInfoJob::qt_metacast(char const*)@Base" 0.12.0
|
(c++)"Fm::FileSystemInfoJob::qt_metacast(char const*)@Base" 0.12.0
|
||||||
(c++)"Fm::FileSystemInfoJob::staticMetaObject@Base" 0.12.0
|
(c++)"Fm::FileSystemInfoJob::staticMetaObject@Base" 0.12.0
|
||||||
|
(c++)"Fm::FileTransferJob::FileTransferJob(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, Fm::FilePath const&, Fm::FileTransferJob::Mode)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::FileTransferJob(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, Fm::FileTransferJob::Mode)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::FileTransferJob(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >, Fm::FileTransferJob::Mode)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::copyDirContent(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo>, Fm::FilePath&, bool)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::copyFile(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo> const&, Fm::FilePath const&, char const*, bool)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::copyRegularFile(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo> const&, Fm::FilePath&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::copySpecialFile(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo> const&, Fm::FilePath&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::createShortcut(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo> const&, Fm::FilePath&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::createSymlink(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo> const&, Fm::FilePath&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::exec()@Base" 0.13.0~
|
||||||
|
(optional|c++|arch= !i386 )"Fm::FileTransferJob::gfileCopyProgressCallback(long, long, Fm::FileTransferJob*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::handleError(Fm::GErrorPtr&, Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo> const&, Fm::FilePath&, int&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::linkFile(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo> const&, Fm::FilePath const&, char const*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::makeDir(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo>, Fm::FilePath&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::metaObject() const@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::moveFile(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo> const&, Fm::FilePath const&, char const*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::moveFileSameFs(Fm::FilePath const&, Fm::GObjectPtr<_GFileInfo> const&, Fm::FilePath&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::processPath(Fm::FilePath const&, Fm::FilePath const&, char const*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::qt_metacast(char const*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::setDestDirPath(Fm::FilePath const&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::setDestPaths(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::setSrcPaths(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::FileTransferJob::staticMetaObject@Base" 0.13.0~
|
||||||
(c++)"Fm::Folder::Folder()@Base" 0.12.0
|
(c++)"Fm::Folder::Folder()@Base" 0.12.0
|
||||||
(c++)"Fm::Folder::Folder(Fm::FilePath const&)@Base" 0.12.0
|
(c++)"Fm::Folder::Folder(Fm::FilePath const&)@Base" 0.12.0
|
||||||
(c++)"Fm::Folder::cache_@Base" 0.12.0
|
(c++)"Fm::Folder::cache_@Base" 0.12.0
|
||||||
@ -522,6 +579,7 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::FolderModel::dropMimeData(QMimeData const*, Qt::DropAction, int, int, QModelIndex const&)@Base" 0.10.0
|
(c++)"Fm::FolderModel::dropMimeData(QMimeData const*, Qt::DropAction, int, int, QModelIndex const&)@Base" 0.10.0
|
||||||
(c++)"Fm::FolderModel::fileInfoFromIndex(QModelIndex const&) const@Base" 0.10.0
|
(c++)"Fm::FolderModel::fileInfoFromIndex(QModelIndex const&) const@Base" 0.10.0
|
||||||
(c++)"Fm::FolderModel::fileSizeChanged(QModelIndex const&)@Base" 0.12.0
|
(c++)"Fm::FolderModel::fileSizeChanged(QModelIndex const&)@Base" 0.12.0
|
||||||
|
(c++)"Fm::FolderModel::filesAdded(Fm::FileInfoList)@Base" 0.13.0~
|
||||||
(c++)"Fm::FolderModel::findItemByFileInfo(Fm::FileInfo const*, int*)@Base" 0.12.0
|
(c++)"Fm::FolderModel::findItemByFileInfo(Fm::FileInfo const*, int*)@Base" 0.12.0
|
||||||
(c++)"Fm::FolderModel::findItemByName(char const*, int*)@Base" 0.10.0
|
(c++)"Fm::FolderModel::findItemByName(char const*, int*)@Base" 0.10.0
|
||||||
(c++)"Fm::FolderModel::findItemByPath(Fm::FilePath const&, int*)@Base" 0.12.0
|
(c++)"Fm::FolderModel::findItemByPath(Fm::FilePath const&, int*)@Base" 0.12.0
|
||||||
@ -597,8 +655,10 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::FolderView::prepareFolderMenu(Fm::FolderMenu*)@Base" 0.10.0
|
(c++)"Fm::FolderView::prepareFolderMenu(Fm::FolderMenu*)@Base" 0.10.0
|
||||||
(c++)"Fm::FolderView::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.10.0
|
(c++)"Fm::FolderView::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.10.0
|
||||||
(c++)"Fm::FolderView::qt_metacast(char const*)@Base" 0.10.0
|
(c++)"Fm::FolderView::qt_metacast(char const*)@Base" 0.10.0
|
||||||
|
(c++)"Fm::FolderView::scrollSmoothly()@Base" 0.13.0~
|
||||||
(c++)"Fm::FolderView::selChanged()@Base" 0.12.0
|
(c++)"Fm::FolderView::selChanged()@Base" 0.12.0
|
||||||
(c++)"Fm::FolderView::selectAll()@Base" 0.10.0
|
(c++)"Fm::FolderView::selectAll()@Base" 0.10.0
|
||||||
|
(c++)"Fm::FolderView::selectFiles(Fm::FileInfoList const&, bool)@Base" 0.13.0~
|
||||||
(c++)"Fm::FolderView::selectedFilePaths() const@Base" 0.10.0
|
(c++)"Fm::FolderView::selectedFilePaths() const@Base" 0.10.0
|
||||||
(c++)"Fm::FolderView::selectedFiles() const@Base" 0.10.0
|
(c++)"Fm::FolderView::selectedFiles() const@Base" 0.10.0
|
||||||
(c++)"Fm::FolderView::selectedIndexes() const@Base" 0.10.0
|
(c++)"Fm::FolderView::selectedIndexes() const@Base" 0.10.0
|
||||||
@ -627,25 +687,15 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::IconInfo::IconInfo(char const*)@Base" 0.12.0
|
(c++)"Fm::IconInfo::IconInfo(char const*)@Base" 0.12.0
|
||||||
(c++)"Fm::IconInfo::cache_@Base" 0.12.0
|
(c++)"Fm::IconInfo::cache_@Base" 0.12.0
|
||||||
(c++)"Fm::IconInfo::emblems() const@Base" 0.12.0
|
(c++)"Fm::IconInfo::emblems() const@Base" 0.12.0
|
||||||
(c++)"Fm::IconInfo::fallbackQicon_@Base" 0.12.0
|
(c++)"Fm::IconInfo::fallbackQicons_@Base" 0.13.0~
|
||||||
(c++)"Fm::IconInfo::fromGIcon(Fm::GObjectPtr<_GIcon>)@Base" 0.12.0
|
(c++)"Fm::IconInfo::fromGIcon(Fm::GObjectPtr<_GIcon>)@Base" 0.12.0
|
||||||
(c++)"Fm::IconInfo::fromName(char const*)@Base" 0.12.0
|
(c++)"Fm::IconInfo::fromName(char const*)@Base" 0.12.0
|
||||||
(c++)"Fm::IconInfo::internalQicon() const@Base" 0.12.0
|
(c++)"Fm::IconInfo::internalQicon() const@Base" 0.12.0
|
||||||
(c++)"Fm::IconInfo::mutex_@Base" 0.12.0
|
(c++)"Fm::IconInfo::mutex_@Base" 0.12.0
|
||||||
(c++)"Fm::IconInfo::qicon(bool const&) const@Base" 0.12.0
|
(c++)"Fm::IconInfo::qicon(bool const&) const@Base" 0.12.0
|
||||||
(c++)"Fm::IconInfo::qiconFromNames(char const* const*)@Base" 0.12.0
|
(c++)"Fm::IconInfo::qiconsFromNames(char const* const*)@Base" 0.13.0~
|
||||||
(c++)"Fm::IconInfo::updateQIcons()@Base" 0.12.0
|
(c++)"Fm::IconInfo::updateQIcons()@Base" 0.12.0
|
||||||
(c++)"Fm::IconInfo::~IconInfo()@Base" 0.12.0
|
(c++)"Fm::IconInfo::~IconInfo()@Base" 0.12.0
|
||||||
(c++)"Fm::IconTheme::IconTheme()@Base" 0.10.0
|
|
||||||
(c++)"Fm::IconTheme::changed()@Base" 0.10.0
|
|
||||||
(c++)"Fm::IconTheme::checkChanged()@Base" 0.10.0
|
|
||||||
(c++)"Fm::IconTheme::eventFilter(QObject*, QEvent*)@Base" 0.10.0
|
|
||||||
(c++)"Fm::IconTheme::instance()@Base" 0.10.0
|
|
||||||
(c++)"Fm::IconTheme::metaObject() const@Base" 0.10.0
|
|
||||||
(c++)"Fm::IconTheme::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.10.0
|
|
||||||
(c++)"Fm::IconTheme::qt_metacast(char const*)@Base" 0.10.0
|
|
||||||
(c++)"Fm::IconTheme::staticMetaObject@Base" 0.10.0
|
|
||||||
(c++)"Fm::IconTheme::~IconTheme()@Base" 0.12.0
|
|
||||||
(c++)"Fm::Job::Job()@Base" 0.12.0
|
(c++)"Fm::Job::Job()@Base" 0.12.0
|
||||||
(c++)"Fm::Job::cancel()@Base" 0.12.0
|
(c++)"Fm::Job::cancel()@Base" 0.12.0
|
||||||
(c++)"Fm::Job::cancelled()@Base" 0.12.0
|
(c++)"Fm::Job::cancelled()@Base" 0.12.0
|
||||||
@ -676,12 +726,15 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::MountOperation::finished(_GError*)@Base" 0.10.0
|
(c++)"Fm::MountOperation::finished(_GError*)@Base" 0.10.0
|
||||||
(c++)"Fm::MountOperation::handleFinish(_GError*)@Base" 0.10.0
|
(c++)"Fm::MountOperation::handleFinish(_GError*)@Base" 0.10.0
|
||||||
(c++)"Fm::MountOperation::metaObject() const@Base" 0.10.0
|
(c++)"Fm::MountOperation::metaObject() const@Base" 0.10.0
|
||||||
|
(c++)"Fm::MountOperation::mountEnclosingVolume(Fm::FilePath const&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::MountOperation::mountMountable(Fm::FilePath const&)@Base" 0.13.0~
|
||||||
(c++)"Fm::MountOperation::onAbort(_GMountOperation*, Fm::MountOperation*)@Base" 0.10.0
|
(c++)"Fm::MountOperation::onAbort(_GMountOperation*, Fm::MountOperation*)@Base" 0.10.0
|
||||||
(c++)"Fm::MountOperation::onAskPassword(_GMountOperation*, char*, char*, char*, GAskPasswordFlags, Fm::MountOperation*)@Base" 0.10.0
|
(c++)"Fm::MountOperation::onAskPassword(_GMountOperation*, char*, char*, char*, GAskPasswordFlags, Fm::MountOperation*)@Base" 0.10.0
|
||||||
(c++)"Fm::MountOperation::onAskQuestion(_GMountOperation*, char*, char**, Fm::MountOperation*)@Base" 0.10.0
|
(c++)"Fm::MountOperation::onAskQuestion(_GMountOperation*, char*, char**, Fm::MountOperation*)@Base" 0.10.0
|
||||||
(c++)"Fm::MountOperation::onEjectMountFinished(_GMount*, _GAsyncResult*, QPointer<Fm::MountOperation>*)@Base" 0.10.0
|
(c++)"Fm::MountOperation::onEjectMountFinished(_GMount*, _GAsyncResult*, QPointer<Fm::MountOperation>*)@Base" 0.10.0
|
||||||
(c++)"Fm::MountOperation::onEjectVolumeFinished(_GVolume*, _GAsyncResult*, QPointer<Fm::MountOperation>*)@Base" 0.10.0
|
(c++)"Fm::MountOperation::onEjectVolumeFinished(_GVolume*, _GAsyncResult*, QPointer<Fm::MountOperation>*)@Base" 0.10.0
|
||||||
(c++)"Fm::MountOperation::onMountFileFinished(_GFile*, _GAsyncResult*, QPointer<Fm::MountOperation>*)@Base" 0.10.0
|
(c++)"Fm::MountOperation::onMountFileFinished(_GFile*, _GAsyncResult*, QPointer<Fm::MountOperation>*)@Base" 0.10.0
|
||||||
|
(c++)"Fm::MountOperation::onMountMountableFinished(_GFile*, _GAsyncResult*, QPointer<Fm::MountOperation>*)@Base" 0.13.0~
|
||||||
(c++)"Fm::MountOperation::onMountVolumeFinished(_GVolume*, _GAsyncResult*, QPointer<Fm::MountOperation>*)@Base" 0.10.0
|
(c++)"Fm::MountOperation::onMountVolumeFinished(_GVolume*, _GAsyncResult*, QPointer<Fm::MountOperation>*)@Base" 0.10.0
|
||||||
(c++)"Fm::MountOperation::onShowProcesses(_GMountOperation*, char*, _GArray*, char**, Fm::MountOperation*)@Base" 0.10.0
|
(c++)"Fm::MountOperation::onShowProcesses(_GMountOperation*, char*, _GArray*, char**, Fm::MountOperation*)@Base" 0.10.0
|
||||||
(c++|arch= !armel !armhf !i386 !mips !mipsel !hppa !hurd-i386 !kfreebsd-i386 !m68k !powerpc !sh4 !x32 )"Fm::MountOperation::onShowUnmountProgress(_GMountOperation*, char*, long, long, Fm::MountOperation*)@Base" 0.12.0
|
(c++|arch= !armel !armhf !i386 !mips !mipsel !hppa !hurd-i386 !kfreebsd-i386 !m68k !powerpc !sh4 !x32 )"Fm::MountOperation::onShowUnmountProgress(_GMountOperation*, char*, long, long, Fm::MountOperation*)@Base" 0.12.0
|
||||||
@ -780,6 +833,16 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::PlacesModelVolumeItem::PlacesModelVolumeItem(_GVolume*)@Base" 0.10.0
|
(c++)"Fm::PlacesModelVolumeItem::PlacesModelVolumeItem(_GVolume*)@Base" 0.10.0
|
||||||
(c++)"Fm::PlacesModelVolumeItem::isMounted()@Base" 0.10.0
|
(c++)"Fm::PlacesModelVolumeItem::isMounted()@Base" 0.10.0
|
||||||
(c++)"Fm::PlacesModelVolumeItem::update()@Base" 0.10.0
|
(c++)"Fm::PlacesModelVolumeItem::update()@Base" 0.10.0
|
||||||
|
(c++)"Fm::PlacesProxyModel::PlacesProxyModel(QObject*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::PlacesProxyModel::filterAcceptsRow(int, QModelIndex const&) const@Base" 0.13.0~
|
||||||
|
(c++)"Fm::PlacesProxyModel::metaObject() const@Base" 0.13.0~
|
||||||
|
(c++)"Fm::PlacesProxyModel::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::PlacesProxyModel::qt_metacast(char const*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::PlacesProxyModel::restoreHiddenItems(QSet<QString> const&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::PlacesProxyModel::setHidden(QString const&, bool)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::PlacesProxyModel::showAll(bool)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::PlacesProxyModel::staticMetaObject@Base" 0.13.0~
|
||||||
|
(c++)"Fm::PlacesProxyModel::~PlacesProxyModel()@Base" 0.13.0~
|
||||||
(c++)"Fm::PlacesView::PlacesView(QWidget*)@Base" 0.10.0
|
(c++)"Fm::PlacesView::PlacesView(QWidget*)@Base" 0.10.0
|
||||||
(c++)"Fm::PlacesView::activateRow(int, QModelIndex const&)@Base" 0.10.0
|
(c++)"Fm::PlacesView::activateRow(int, QModelIndex const&)@Base" 0.10.0
|
||||||
(c++)"Fm::PlacesView::chdirRequested(int, Fm::FilePath const&)@Base" 0.12.0
|
(c++)"Fm::PlacesView::chdirRequested(int, Fm::FilePath const&)@Base" 0.12.0
|
||||||
@ -787,6 +850,7 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::PlacesView::contextMenuEvent(QContextMenuEvent*)@Base" 0.10.0
|
(c++)"Fm::PlacesView::contextMenuEvent(QContextMenuEvent*)@Base" 0.10.0
|
||||||
(c++)"Fm::PlacesView::dragMoveEvent(QDragMoveEvent*)@Base" 0.10.0
|
(c++)"Fm::PlacesView::dragMoveEvent(QDragMoveEvent*)@Base" 0.10.0
|
||||||
(c++)"Fm::PlacesView::dropEvent(QDropEvent*)@Base" 0.10.0
|
(c++)"Fm::PlacesView::dropEvent(QDropEvent*)@Base" 0.10.0
|
||||||
|
(c++)"Fm::PlacesView::hiddenItemSet(QString const&, bool)@Base" 0.13.0~
|
||||||
(c++)"Fm::PlacesView::metaObject() const@Base" 0.10.0
|
(c++)"Fm::PlacesView::metaObject() const@Base" 0.10.0
|
||||||
(c++)"Fm::PlacesView::onClicked(QModelIndex const&)@Base" 0.10.0
|
(c++)"Fm::PlacesView::onClicked(QModelIndex const&)@Base" 0.10.0
|
||||||
(c++)"Fm::PlacesView::onDeleteBookmark()@Base" 0.10.0
|
(c++)"Fm::PlacesView::onDeleteBookmark()@Base" 0.10.0
|
||||||
@ -803,9 +867,12 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::PlacesView::onRenameBookmark()@Base" 0.10.0
|
(c++)"Fm::PlacesView::onRenameBookmark()@Base" 0.10.0
|
||||||
(c++)"Fm::PlacesView::onUnmountMount()@Base" 0.10.0
|
(c++)"Fm::PlacesView::onUnmountMount()@Base" 0.10.0
|
||||||
(c++)"Fm::PlacesView::onUnmountVolume()@Base" 0.10.0
|
(c++)"Fm::PlacesView::onUnmountVolume()@Base" 0.10.0
|
||||||
|
(c++)"Fm::PlacesView::proxyModel_@Base" 0.13.0~
|
||||||
(c++)"Fm::PlacesView::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.10.0
|
(c++)"Fm::PlacesView::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.10.0
|
||||||
(c++)"Fm::PlacesView::qt_metacast(char const*)@Base" 0.10.0
|
(c++)"Fm::PlacesView::qt_metacast(char const*)@Base" 0.10.0
|
||||||
|
(c++)"Fm::PlacesView::restoreHiddenItems(QSet<QString> const&)@Base" 0.13.0~
|
||||||
(c++)"Fm::PlacesView::setCurrentPath(Fm::FilePath)@Base" 0.12.0
|
(c++)"Fm::PlacesView::setCurrentPath(Fm::FilePath)@Base" 0.12.0
|
||||||
|
(c++)"Fm::PlacesView::showAll(bool)@Base" 0.13.0~
|
||||||
(c++)"Fm::PlacesView::staticMetaObject@Base" 0.10.0
|
(c++)"Fm::PlacesView::staticMetaObject@Base" 0.10.0
|
||||||
(c++)"Fm::PlacesView::~PlacesView()@Base" 0.10.0
|
(c++)"Fm::PlacesView::~PlacesView()@Base" 0.10.0
|
||||||
(c++)"Fm::ProxyFolderModel::ProxyFolderModel(QObject*)@Base" 0.10.0
|
(c++)"Fm::ProxyFolderModel::ProxyFolderModel(QObject*)@Base" 0.10.0
|
||||||
@ -821,6 +888,7 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::ProxyFolderModel::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.10.0
|
(c++)"Fm::ProxyFolderModel::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.10.0
|
||||||
(c++)"Fm::ProxyFolderModel::qt_metacast(char const*)@Base" 0.10.0
|
(c++)"Fm::ProxyFolderModel::qt_metacast(char const*)@Base" 0.10.0
|
||||||
(c++)"Fm::ProxyFolderModel::removeFilter(Fm::ProxyFolderModelFilter*)@Base" 0.10.0
|
(c++)"Fm::ProxyFolderModel::removeFilter(Fm::ProxyFolderModelFilter*)@Base" 0.10.0
|
||||||
|
(c++)"Fm::ProxyFolderModel::setBackupAsHidden(bool)@Base" 0.13.0~
|
||||||
(c++)"Fm::ProxyFolderModel::setCutFiles(QItemSelection const&)@Base" 0.12.0
|
(c++)"Fm::ProxyFolderModel::setCutFiles(QItemSelection const&)@Base" 0.12.0
|
||||||
(c++)"Fm::ProxyFolderModel::setFolderFirst(bool)@Base" 0.10.0
|
(c++)"Fm::ProxyFolderModel::setFolderFirst(bool)@Base" 0.10.0
|
||||||
(c++)"Fm::ProxyFolderModel::setShowHidden(bool)@Base" 0.10.0
|
(c++)"Fm::ProxyFolderModel::setShowHidden(bool)@Base" 0.10.0
|
||||||
@ -833,7 +901,7 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::ProxyFolderModel::staticMetaObject@Base" 0.10.0
|
(c++)"Fm::ProxyFolderModel::staticMetaObject@Base" 0.10.0
|
||||||
(c++)"Fm::ProxyFolderModel::updateFilters()@Base" 0.10.0
|
(c++)"Fm::ProxyFolderModel::updateFilters()@Base" 0.10.0
|
||||||
(c++)"Fm::ProxyFolderModel::~ProxyFolderModel()@Base" 0.10.0
|
(c++)"Fm::ProxyFolderModel::~ProxyFolderModel()@Base" 0.10.0
|
||||||
(c++)"Fm::RenameDialog::RenameDialog(_FmFileInfo*, _FmFileInfo*, QWidget*, QFlags<Qt::WindowType>)@Base" 0.10.0
|
(c++)"Fm::RenameDialog::RenameDialog(Fm::FileInfo const&, Fm::FileInfo const&, QWidget*, QFlags<Qt::WindowType>)@Base" 0.13.0~
|
||||||
(c++)"Fm::RenameDialog::accept()@Base" 0.10.0
|
(c++)"Fm::RenameDialog::accept()@Base" 0.10.0
|
||||||
(c++)"Fm::RenameDialog::metaObject() const@Base" 0.10.0
|
(c++)"Fm::RenameDialog::metaObject() const@Base" 0.10.0
|
||||||
(c++)"Fm::RenameDialog::onFileNameChanged(QString)@Base" 0.10.0
|
(c++)"Fm::RenameDialog::onFileNameChanged(QString)@Base" 0.10.0
|
||||||
@ -847,6 +915,7 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::SidePane::SidePane(QWidget*)@Base" 0.10.0
|
(c++)"Fm::SidePane::SidePane(QWidget*)@Base" 0.10.0
|
||||||
(c++)"Fm::SidePane::chdirRequested(int, Fm::FilePath const&)@Base" 0.12.0
|
(c++)"Fm::SidePane::chdirRequested(int, Fm::FilePath const&)@Base" 0.12.0
|
||||||
(c++)"Fm::SidePane::createNewFolderRequested(Fm::FilePath const&)@Base" 0.12.0
|
(c++)"Fm::SidePane::createNewFolderRequested(Fm::FilePath const&)@Base" 0.12.0
|
||||||
|
(c++)"Fm::SidePane::hiddenPlaceSet(QString const&, bool)@Base" 0.13.0~
|
||||||
(c++)"Fm::SidePane::initDirTree()@Base" 0.10.0
|
(c++)"Fm::SidePane::initDirTree()@Base" 0.10.0
|
||||||
(c++)"Fm::SidePane::metaObject() const@Base" 0.10.0
|
(c++)"Fm::SidePane::metaObject() const@Base" 0.10.0
|
||||||
(c++)"Fm::SidePane::modeByName(char const*)@Base" 0.10.0
|
(c++)"Fm::SidePane::modeByName(char const*)@Base" 0.10.0
|
||||||
@ -859,6 +928,7 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::SidePane::prepareFileMenu(Fm::FileMenu*)@Base" 0.10.0
|
(c++)"Fm::SidePane::prepareFileMenu(Fm::FileMenu*)@Base" 0.10.0
|
||||||
(c++)"Fm::SidePane::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.10.0
|
(c++)"Fm::SidePane::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.10.0
|
||||||
(c++)"Fm::SidePane::qt_metacast(char const*)@Base" 0.10.0
|
(c++)"Fm::SidePane::qt_metacast(char const*)@Base" 0.10.0
|
||||||
|
(c++)"Fm::SidePane::restoreHiddenPlaces(QSet<QString> const&)@Base" 0.13.0~
|
||||||
(c++)"Fm::SidePane::setCurrentPath(Fm::FilePath)@Base" 0.12.0
|
(c++)"Fm::SidePane::setCurrentPath(Fm::FilePath)@Base" 0.12.0
|
||||||
(c++)"Fm::SidePane::setHomeDir(char const*)@Base" 0.10.0
|
(c++)"Fm::SidePane::setHomeDir(char const*)@Base" 0.10.0
|
||||||
(c++)"Fm::SidePane::setIconSize(QSize)@Base" 0.10.0
|
(c++)"Fm::SidePane::setIconSize(QSize)@Base" 0.10.0
|
||||||
@ -866,6 +936,23 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::SidePane::setShowHidden(bool)@Base" 0.10.0
|
(c++)"Fm::SidePane::setShowHidden(bool)@Base" 0.10.0
|
||||||
(c++)"Fm::SidePane::staticMetaObject@Base" 0.10.0
|
(c++)"Fm::SidePane::staticMetaObject@Base" 0.10.0
|
||||||
(c++)"Fm::SidePane::~SidePane()@Base" 0.10.0
|
(c++)"Fm::SidePane::~SidePane()@Base" 0.10.0
|
||||||
|
(c++)"Fm::TemplateItem::TemplateItem(std::shared_ptr<Fm::FileInfo const>)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::TemplateItem::filePath() const@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Templates::Templates()@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Templates::addTemplateDir(char const*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Templates::globalInstance()@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Templates::globalInstance_@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Templates::itemAdded(std::shared_ptr<Fm::TemplateItem const> const&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Templates::itemChanged(std::shared_ptr<Fm::TemplateItem const> const&, std::shared_ptr<Fm::TemplateItem const> const&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Templates::itemRemoved(std::shared_ptr<Fm::TemplateItem const> const&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Templates::metaObject() const@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Templates::onFilesAdded(Fm::FileInfoList&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Templates::onFilesChanged(std::vector<std::pair<std::shared_ptr<Fm::FileInfo const>, std::shared_ptr<Fm::FileInfo const> >, std::allocator<std::pair<std::shared_ptr<Fm::FileInfo const>, std::shared_ptr<Fm::FileInfo const> > > >&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Templates::onFilesRemoved(Fm::FileInfoList&)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Templates::onTemplateDirRemoved()@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Templates::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Templates::qt_metacast(char const*)@Base" 0.13.0~
|
||||||
|
(c++)"Fm::Templates::staticMetaObject@Base" 0.13.0~
|
||||||
(c++)"Fm::ThumbnailJob::ThumbnailJob(Fm::FileInfoList, int)@Base" 0.12.0
|
(c++)"Fm::ThumbnailJob::ThumbnailJob(Fm::FileInfoList, int)@Base" 0.12.0
|
||||||
(c++)"Fm::ThumbnailJob::exec()@Base" 0.12.0
|
(c++)"Fm::ThumbnailJob::exec()@Base" 0.12.0
|
||||||
(c++)"Fm::ThumbnailJob::generateThumbnail(std::shared_ptr<Fm::FileInfo const> const&, Fm::FilePath const&, char const*, QString const&)@Base" 0.12.0
|
(c++)"Fm::ThumbnailJob::generateThumbnail(std::shared_ptr<Fm::FileInfo const> const&, Fm::FilePath const&, char const*, QString const&)@Base" 0.12.0
|
||||||
@ -898,15 +985,13 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::TotalSizeJob::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.12.0
|
(c++)"Fm::TotalSizeJob::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.12.0
|
||||||
(c++)"Fm::TotalSizeJob::qt_metacast(char const*)@Base" 0.12.0
|
(c++)"Fm::TotalSizeJob::qt_metacast(char const*)@Base" 0.12.0
|
||||||
(c++)"Fm::TotalSizeJob::staticMetaObject@Base" 0.12.0
|
(c++)"Fm::TotalSizeJob::staticMetaObject@Base" 0.12.0
|
||||||
(c++)"Fm::TrashJob::TrashJob(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > const&&)@Base" 0.12.0
|
(c++)"Fm::TrashJob::TrashJob(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >)@Base" 0.13.0~
|
||||||
(c++)"Fm::TrashJob::TrashJob(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > const&)@Base" 0.12.0
|
|
||||||
(c++)"Fm::TrashJob::exec()@Base" 0.12.0
|
(c++)"Fm::TrashJob::exec()@Base" 0.12.0
|
||||||
(c++)"Fm::TrashJob::metaObject() const@Base" 0.12.0
|
(c++)"Fm::TrashJob::metaObject() const@Base" 0.12.0
|
||||||
(c++)"Fm::TrashJob::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.12.0
|
(c++)"Fm::TrashJob::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.12.0
|
||||||
(c++)"Fm::TrashJob::qt_metacast(char const*)@Base" 0.12.0
|
(c++)"Fm::TrashJob::qt_metacast(char const*)@Base" 0.12.0
|
||||||
(c++)"Fm::TrashJob::staticMetaObject@Base" 0.12.0
|
(c++)"Fm::TrashJob::staticMetaObject@Base" 0.12.0
|
||||||
(c++)"Fm::UntrashJob::UntrashJob()@Base" 0.12.0
|
(c++)"Fm::UntrashJob::UntrashJob(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >)@Base" 0.13.0~
|
||||||
(c++)"Fm::UntrashJob::ensure_parent_dir(_GFile*)@Base" 0.12.0
|
|
||||||
(c++)"Fm::UntrashJob::exec()@Base" 0.12.0
|
(c++)"Fm::UntrashJob::exec()@Base" 0.12.0
|
||||||
(c++)"Fm::UserInfoCache::UserInfoCache()@Base" 0.12.0
|
(c++)"Fm::UserInfoCache::UserInfoCache()@Base" 0.12.0
|
||||||
(c++)"Fm::UserInfoCache::changed()@Base" 0.12.0
|
(c++)"Fm::UserInfoCache::changed()@Base" 0.12.0
|
||||||
@ -943,9 +1028,9 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"Fm::VolumeManager::volumeRemoved(Fm::Volume const&)@Base" 0.12.0
|
(c++)"Fm::VolumeManager::volumeRemoved(Fm::Volume const&)@Base" 0.12.0
|
||||||
(c++)"Fm::VolumeManager::~VolumeManager()@Base" 0.12.0
|
(c++)"Fm::VolumeManager::~VolumeManager()@Base" 0.12.0
|
||||||
(c++)"Fm::allKnownTerminals()@Base" 0.12.0
|
(c++)"Fm::allKnownTerminals()@Base" 0.12.0
|
||||||
(c++)"Fm::changeFileName(Fm::FilePath const&, QString const&, QWidget*)@Base" 0.12.0
|
(c++)"Fm::changeFileName(Fm::FilePath const&, QString const&, QWidget*, bool)@Base" 0.13.0~
|
||||||
(c++)"Fm::copyFilesToClipboard(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > const&)@Base" 0.12.0
|
(c++)"Fm::copyFilesToClipboard(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > const&)@Base" 0.12.0
|
||||||
(c++)"Fm::createFileOrFolder(Fm::CreateFileType, Fm::FilePath, _FmTemplate*, QWidget*)@Base" 0.12.0
|
(c++)"Fm::createFileOrFolder(Fm::CreateFileType, Fm::FilePath, Fm::TemplateItem const*, QWidget*)@Base" 0.13.0~
|
||||||
(c++)"Fm::cutFilesToClipboard(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > const&)@Base" 0.12.0
|
(c++)"Fm::cutFilesToClipboard(std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > const&)@Base" 0.12.0
|
||||||
(c++)"Fm::execModelessDialog(QDialog*)@Base" 0.10.0
|
(c++)"Fm::execModelessDialog(QDialog*)@Base" 0.10.0
|
||||||
(c++|arch= !armel !armhf !i386 !mips !mipsel !hppa !hurd-i386 !kfreebsd-i386 !m68k !powerpc !sh4 !x32 )"Fm::formatFileSize(unsigned long, bool)@Base" 0.12.0
|
(c++|arch= !armel !armhf !i386 !mips !mipsel !hppa !hurd-i386 !kfreebsd-i386 !m68k !powerpc !sh4 !x32 )"Fm::formatFileSize(unsigned long, bool)@Base" 0.12.0
|
||||||
@ -969,6 +1054,7 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"non-virtual thunk to Fm::AppMenuView::~AppMenuView()@Base" 0.10.0
|
(c++)"non-virtual thunk to Fm::AppMenuView::~AppMenuView()@Base" 0.10.0
|
||||||
(c++)"non-virtual thunk to Fm::ColorButton::~ColorButton()@Base" 0.10.0
|
(c++)"non-virtual thunk to Fm::ColorButton::~ColorButton()@Base" 0.10.0
|
||||||
(c++)"non-virtual thunk to Fm::CreateNewMenu::~CreateNewMenu()@Base" 0.10.0
|
(c++)"non-virtual thunk to Fm::CreateNewMenu::~CreateNewMenu()@Base" 0.10.0
|
||||||
|
(c++)"non-virtual thunk to Fm::DeleteJob::~DeleteJob()@Base" 0.13.0~
|
||||||
(c++)"non-virtual thunk to Fm::DirTreeView::~DirTreeView()@Base" 0.10.0
|
(c++)"non-virtual thunk to Fm::DirTreeView::~DirTreeView()@Base" 0.10.0
|
||||||
(c++)"non-virtual thunk to Fm::EditBookmarksDialog::~EditBookmarksDialog()@Base" 0.10.0
|
(c++)"non-virtual thunk to Fm::EditBookmarksDialog::~EditBookmarksDialog()@Base" 0.10.0
|
||||||
(c++)"non-virtual thunk to Fm::FileDialog::~FileDialog()@Base" 0.12.0
|
(c++)"non-virtual thunk to Fm::FileDialog::~FileDialog()@Base" 0.12.0
|
||||||
@ -988,14 +1074,15 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"non-virtual thunk to Fm::ThumbnailJob::~ThumbnailJob()@Base" 0.12.0
|
(c++)"non-virtual thunk to Fm::ThumbnailJob::~ThumbnailJob()@Base" 0.12.0
|
||||||
(c++|arch= !armel !armhf !i386 !mips !mipsel !hppa !hurd-i386 !kfreebsd-i386 !m68k !powerpc !sh4 !x32 )"std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> > >, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const>, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::_M_find_before_node(unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long) const@Base" 0.12.0
|
(c++|arch= !armel !armhf !i386 !mips !mipsel !hppa !hurd-i386 !kfreebsd-i386 !m68k !powerpc !sh4 !x32 )"std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> > >, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const>, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::_M_find_before_node(unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long) const@Base" 0.12.0
|
||||||
(c++|arch= !amd64 !arm64 !mips64el !ppc64el !s390x !alpha !ia64 !kfreebsd-amd64 !ppc64 !riscv64 !sparc64 )"std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> > >, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const>, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::_M_find_before_node(unsigned int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int) const@Base" 0.12.0
|
(c++|arch= !amd64 !arm64 !mips64el !ppc64el !s390x !alpha !ia64 !kfreebsd-amd64 !ppc64 !riscv64 !sparc64 )"std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> > >, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const>, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::_M_find_before_node(unsigned int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int) const@Base" 0.12.0
|
||||||
(c++|arch= !armel !armhf !i386 !mips !mipsel !hppa !hurd-i386 !kfreebsd-i386 !m68k !powerpc !sh4 !x32 )"std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> > >, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const>, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::_M_insert_unique_node(unsigned long, unsigned long, std::__detail::_Hash_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> >, true>*)@Base" 0.12.0
|
|
||||||
(c++|arch= !amd64 !arm64 !mips64el !ppc64el !s390x !alpha !ia64 !kfreebsd-amd64 !ppc64 !riscv64 !sparc64 )"std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> > >, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const>, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::_M_insert_unique_node(unsigned int, unsigned int, std::__detail::_Hash_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> >, true>*)@Base" 0.12.0
|
|
||||||
(c++)"std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> > >, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const>, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::clear()@Base" 0.12.0
|
(c++)"std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> > >, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const>, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::clear()@Base" 0.12.0
|
||||||
|
(optional=gcc8|c++|arch= !i386 )"std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> > >, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const>, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::erase(std::__detail::_Node_const_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> >, false, true>)@Base" 0.13.0~
|
||||||
(c++)"std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> > >, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const>, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::find(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.12.0
|
(c++)"std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> > >, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const>, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::find(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.12.0
|
||||||
(c++|arch= !armel !armhf !i386 !mips !mipsel !hppa !hurd-i386 !kfreebsd-i386 !m68k !powerpc !sh4 !x32 )"std::_Hashtable<unsigned int, std::pair<unsigned int const, std::shared_ptr<Fm::GroupInfo const> >, std::allocator<std::pair<unsigned int const, std::shared_ptr<Fm::GroupInfo const> > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_insert_unique_node(unsigned long, unsigned long, std::__detail::_Hash_node<std::pair<unsigned int const, std::shared_ptr<Fm::GroupInfo const> >, false>*)@Base" 0.12.0
|
(optional=gcc8|c++|arch= !i386 )"std::_Hashtable<unsigned int, std::pair<unsigned int const, std::shared_ptr<Fm::GroupInfo const> >, std::allocator<std::pair<unsigned int const, std::shared_ptr<Fm::GroupInfo const> > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_insert_unique_node(unsigned long, unsigned long, std::__detail::_Hash_node<std::pair<unsigned int const, std::shared_ptr<Fm::GroupInfo const> >, false>*, unsigned long)@Base" 0.13.0~
|
||||||
(c++|arch= !amd64 !arm64 !mips64el !ppc64el !s390x !alpha !ia64 !kfreebsd-amd64 !ppc64 !riscv64 !sparc64 )"std::_Hashtable<unsigned int, std::pair<unsigned int const, std::shared_ptr<Fm::GroupInfo const> >, std::allocator<std::pair<unsigned int const, std::shared_ptr<Fm::GroupInfo const> > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_insert_unique_node(unsigned int, unsigned int, std::__detail::_Hash_node<std::pair<unsigned int const, std::shared_ptr<Fm::GroupInfo const> >, false>*)@Base" 0.12.0
|
(optional=gcc8|c++)"std::_Hashtable<unsigned int, std::pair<unsigned int const, std::shared_ptr<Fm::UserInfo const> >, std::allocator<std::pair<unsigned int const, std::shared_ptr<Fm::UserInfo const> > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_insert_unique_node(unsigned long, unsigned long, std::__detail::_Hash_node<std::pair<unsigned int const, std::shared_ptr<Fm::UserInfo const> >, false>*, unsigned long)@Base" 0.13.0~
|
||||||
(c++|arch= !armel !armhf !i386 !mips !mipsel !hppa !hurd-i386 !kfreebsd-i386 !m68k !powerpc !sh4 !x32 )"std::_Hashtable<unsigned int, std::pair<unsigned int const, std::shared_ptr<Fm::UserInfo const> >, std::allocator<std::pair<unsigned int const, std::shared_ptr<Fm::UserInfo const> > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_insert_unique_node(unsigned long, unsigned long, std::__detail::_Hash_node<std::pair<unsigned int const, std::shared_ptr<Fm::UserInfo const> >, false>*)@Base" 0.12.0
|
(optional=gcc7|c++|arch= !armel !armhf !i386 !mips !mipsel !hppa !hurd-i386 !kfreebsd-i386 !m68k !powerpc !sh4 !x32 )"std::_Hashtable<unsigned int, std::pair<unsigned int const, std::shared_ptr<Fm::GroupInfo const> >, std::allocator<std::pair<unsigned int const, std::shared_ptr<Fm::GroupInfo const> > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_insert_unique_node(unsigned long, unsigned long, std::__detail::_Hash_node<std::pair<unsigned int const, std::shared_ptr<Fm::GroupInfo const> >, false>*)@Base" 0.12.0
|
||||||
(c++|arch= !amd64 !arm64 !mips64el !ppc64el !s390x !alpha !ia64 !kfreebsd-amd64 !ppc64 !riscv64 !sparc64 )"std::_Hashtable<unsigned int, std::pair<unsigned int const, std::shared_ptr<Fm::UserInfo const> >, std::allocator<std::pair<unsigned int const, std::shared_ptr<Fm::UserInfo const> > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_insert_unique_node(unsigned int, unsigned int, std::__detail::_Hash_node<std::pair<unsigned int const, std::shared_ptr<Fm::UserInfo const> >, false>*)@Base" 0.12.0
|
(optional=gcc7|c++|arch= !amd64 !arm64 !mips64el !ppc64el !s390x !alpha !ia64 !kfreebsd-amd64 !ppc64 !riscv64 !sparc64 )"std::_Hashtable<unsigned int, std::pair<unsigned int const, std::shared_ptr<Fm::GroupInfo const> >, std::allocator<std::pair<unsigned int const, std::shared_ptr<Fm::GroupInfo const> > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_insert_unique_node(unsigned int, unsigned int, std::__detail::_Hash_node<std::pair<unsigned int const, std::shared_ptr<Fm::GroupInfo const> >, false>*)@Base" 0.12.0
|
||||||
|
(optional=gcc7|c++|arch= !armel !armhf !i386 !mips !mipsel !hppa !hurd-i386 !kfreebsd-i386 !m68k !powerpc !sh4 !x32 )"std::_Hashtable<unsigned int, std::pair<unsigned int const, std::shared_ptr<Fm::UserInfo const> >, std::allocator<std::pair<unsigned int const, std::shared_ptr<Fm::UserInfo const> > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_insert_unique_node(unsigned long, unsigned long, std::__detail::_Hash_node<std::pair<unsigned int const, std::shared_ptr<Fm::UserInfo const> >, false>*)@Base" 0.12.0
|
||||||
|
(optional=gcc7|c++|arch= !amd64 !arm64 !mips64el !ppc64el !s390x !alpha !ia64 !kfreebsd-amd64 !ppc64 !riscv64 !sparc64 )"std::_Hashtable<unsigned int, std::pair<unsigned int const, std::shared_ptr<Fm::UserInfo const> >, std::allocator<std::pair<unsigned int const, std::shared_ptr<Fm::UserInfo const> > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_insert_unique_node(unsigned int, unsigned int, std::__detail::_Hash_node<std::pair<unsigned int const, std::shared_ptr<Fm::UserInfo const> >, false>*)@Base" 0.12.0
|
||||||
(c++)"std::_Rb_tree<unsigned int, unsigned int, std::_Identity<unsigned int>, std::less<unsigned int>, std::allocator<unsigned int> >::_M_erase(std::_Rb_tree_node<unsigned int>*)@Base" 0.12.0
|
(c++)"std::_Rb_tree<unsigned int, unsigned int, std::_Identity<unsigned int>, std::less<unsigned int>, std::allocator<unsigned int> >::_M_erase(std::_Rb_tree_node<unsigned int>*)@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_destroy()@Base" 0.12.0
|
(c++|arch= !armel !riscv64 )"std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_destroy()@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)1>::_M_destroy()@Base" 0.12.0
|
(c++|arch= armel riscv64 )"std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)1>::_M_destroy()@Base" 0.12.0
|
||||||
@ -1074,78 +1161,62 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<Fm::MimeType, std::allocator<Fm::MimeType>, (__gnu_cxx::_Lock_policy)2>::_M_get_deleter(std::type_info const&)@Base" 0.12.0
|
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<Fm::MimeType, std::allocator<Fm::MimeType>, (__gnu_cxx::_Lock_policy)2>::_M_get_deleter(std::type_info const&)@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<Fm::MimeType, std::allocator<Fm::MimeType>, (__gnu_cxx::_Lock_policy)1>::_M_get_deleter(std::type_info const&)@Base" 0.12.0
|
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<Fm::MimeType, std::allocator<Fm::MimeType>, (__gnu_cxx::_Lock_policy)1>::_M_get_deleter(std::type_info const&)@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<Fm::MimeType, std::allocator<Fm::MimeType>, (__gnu_cxx::_Lock_policy)2>::~_Sp_counted_ptr_inplace()@Base" 0.12.0
|
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<Fm::MimeType, std::allocator<Fm::MimeType>, (__gnu_cxx::_Lock_policy)2>::~_Sp_counted_ptr_inplace()@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<Fm::MimeType, std::allocator<Fm::MimeType>, (__gnu_cxx::_Lock_policy)1>::~_Sp_counted_ptr_inplace()@Base" 0.12.0
|
(c++)"std::_Sp_counted_ptr_inplace<Fm::PlacesModel, std::allocator<Fm::PlacesModel>, (__gnu_cxx::_Lock_policy)2>::_M_destroy()@Base" 0.13.0~
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<Fm::PlacesModel, std::allocator<Fm::PlacesModel>, (__gnu_cxx::_Lock_policy)2>::_M_destroy()@Base" 0.12.0
|
(c++)"std::_Sp_counted_ptr_inplace<Fm::PlacesModel, std::allocator<Fm::PlacesModel>, (__gnu_cxx::_Lock_policy)2>::_M_dispose()@Base" 0.13.0~
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<Fm::PlacesModel, std::allocator<Fm::PlacesModel>, (__gnu_cxx::_Lock_policy)1>::_M_destroy()@Base" 0.12.0
|
(c++)"std::_Sp_counted_ptr_inplace<Fm::PlacesModel, std::allocator<Fm::PlacesModel>, (__gnu_cxx::_Lock_policy)2>::_M_get_deleter(std::type_info const&)@Base" 0.13.0~
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<Fm::PlacesModel, std::allocator<Fm::PlacesModel>, (__gnu_cxx::_Lock_policy)2>::_M_dispose()@Base" 0.12.0
|
(c++)"std::_Sp_counted_ptr_inplace<Fm::PlacesModel, std::allocator<Fm::PlacesModel>, (__gnu_cxx::_Lock_policy)2>::~_Sp_counted_ptr_inplace()@Base" 0.13.0~
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<Fm::PlacesModel, std::allocator<Fm::PlacesModel>, (__gnu_cxx::_Lock_policy)1>::_M_dispose()@Base" 0.12.0
|
(optional|c++)"std::_Sp_counted_ptr_inplace<Fm::PlacesProxyModel, std::allocator<Fm::PlacesProxyModel>, (__gnu_cxx::_Lock_policy)2>::_M_destroy()@Base" 0.13.0~
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<Fm::PlacesModel, std::allocator<Fm::PlacesModel>, (__gnu_cxx::_Lock_policy)2>::_M_get_deleter(std::type_info const&)@Base" 0.12.0
|
(optional|c++)"std::_Sp_counted_ptr_inplace<Fm::PlacesProxyModel, std::allocator<Fm::PlacesProxyModel>, (__gnu_cxx::_Lock_policy)2>::_M_dispose()@Base" 0.13.0~
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<Fm::PlacesModel, std::allocator<Fm::PlacesModel>, (__gnu_cxx::_Lock_policy)1>::_M_get_deleter(std::type_info const&)@Base" 0.12.0
|
(optional|c++)"std::_Sp_counted_ptr_inplace<Fm::PlacesProxyModel, std::allocator<Fm::PlacesProxyModel>, (__gnu_cxx::_Lock_policy)2>::_M_get_deleter(std::type_info const&)@Base" 0.13.0~
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<Fm::PlacesModel, std::allocator<Fm::PlacesModel>, (__gnu_cxx::_Lock_policy)2>::~_Sp_counted_ptr_inplace()@Base" 0.12.0
|
(optional|c++)"std::_Sp_counted_ptr_inplace<Fm::PlacesProxyModel, std::allocator<Fm::PlacesProxyModel>, (__gnu_cxx::_Lock_policy)2>::~_Sp_counted_ptr_inplace()@Base" 0.13.0~
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<Fm::PlacesModel, std::allocator<Fm::PlacesModel>, (__gnu_cxx::_Lock_policy)1>::~_Sp_counted_ptr_inplace()@Base" 0.12.0
|
(optional|c++)"std::_Sp_counted_ptr_inplace<Fm::TemplateItem, std::allocator<Fm::TemplateItem>, (__gnu_cxx::_Lock_policy)2>::_M_destroy()@Base" 0.13.0~
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<Fm::Thumbnailer, std::allocator<Fm::Thumbnailer>, (__gnu_cxx::_Lock_policy)2>::_M_destroy()@Base" 0.12.0
|
(optional|c++)"std::_Sp_counted_ptr_inplace<Fm::TemplateItem, std::allocator<Fm::TemplateItem>, (__gnu_cxx::_Lock_policy)2>::_M_dispose()@Base" 0.13.0~
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<Fm::Thumbnailer, std::allocator<Fm::Thumbnailer>, (__gnu_cxx::_Lock_policy)1>::_M_destroy()@Base" 0.12.0
|
(optional|c++)"std::_Sp_counted_ptr_inplace<Fm::TemplateItem, std::allocator<Fm::TemplateItem>, (__gnu_cxx::_Lock_policy)2>::_M_get_deleter(std::type_info const&)@Base" 0.13.0~
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<Fm::Thumbnailer, std::allocator<Fm::Thumbnailer>, (__gnu_cxx::_Lock_policy)2>::_M_dispose()@Base" 0.12.0
|
(optional|c++)"std::_Sp_counted_ptr_inplace<Fm::TemplateItem, std::allocator<Fm::TemplateItem>, (__gnu_cxx::_Lock_policy)2>::~_Sp_counted_ptr_inplace()@Base" 0.13.0~
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<Fm::Thumbnailer, std::allocator<Fm::Thumbnailer>, (__gnu_cxx::_Lock_policy)1>::_M_dispose()@Base" 0.12.0
|
(optional|c++)"std::_Sp_counted_ptr_inplace<Fm::Templates, std::allocator<Fm::Templates>, (__gnu_cxx::_Lock_policy)2>::_M_destroy()@Base" 0.13.0~
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<Fm::Thumbnailer, std::allocator<Fm::Thumbnailer>, (__gnu_cxx::_Lock_policy)2>::_M_get_deleter(std::type_info const&)@Base" 0.12.0
|
(optional|c++)"std::_Sp_counted_ptr_inplace<Fm::Templates, std::allocator<Fm::Templates>, (__gnu_cxx::_Lock_policy)2>::_M_dispose()@Base" 0.13.0~
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<Fm::Thumbnailer, std::allocator<Fm::Thumbnailer>, (__gnu_cxx::_Lock_policy)1>::_M_get_deleter(std::type_info const&)@Base" 0.12.0
|
(optional|c++)"std::_Sp_counted_ptr_inplace<Fm::Templates, std::allocator<Fm::Templates>, (__gnu_cxx::_Lock_policy)2>::_M_get_deleter(std::type_info const&)@Base" 0.13.0~
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<Fm::Thumbnailer, std::allocator<Fm::Thumbnailer>, (__gnu_cxx::_Lock_policy)2>::~_Sp_counted_ptr_inplace()@Base" 0.12.0
|
(optional|c++)"std::_Sp_counted_ptr_inplace<Fm::Templates, std::allocator<Fm::Templates>, (__gnu_cxx::_Lock_policy)2>::~_Sp_counted_ptr_inplace()@Base" 0.13.0~
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<Fm::Thumbnailer, std::allocator<Fm::Thumbnailer>, (__gnu_cxx::_Lock_policy)1>::~_Sp_counted_ptr_inplace()@Base" 0.12.0
|
(c++)"std::_Sp_counted_ptr_inplace<Fm::Thumbnailer, std::allocator<Fm::Thumbnailer>, (__gnu_cxx::_Lock_policy)2>::_M_destroy()@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)2>::_M_destroy()@Base" 0.12.0
|
(c++)"std::_Sp_counted_ptr_inplace<Fm::Thumbnailer, std::allocator<Fm::Thumbnailer>, (__gnu_cxx::_Lock_policy)2>::_M_dispose()@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)1>::_M_destroy()@Base" 0.12.0
|
(c++)"std::_Sp_counted_ptr_inplace<Fm::Thumbnailer, std::allocator<Fm::Thumbnailer>, (__gnu_cxx::_Lock_policy)2>::_M_get_deleter(std::type_info const&)@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)2>::_M_dispose()@Base" 0.12.0
|
(c++)"std::_Sp_counted_ptr_inplace<Fm::Thumbnailer, std::allocator<Fm::Thumbnailer>, (__gnu_cxx::_Lock_policy)2>::~_Sp_counted_ptr_inplace()@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)1>::_M_dispose()@Base" 0.12.0
|
(c++)"std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)2>::_M_destroy()@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)2>::_M_get_deleter(std::type_info const&)@Base" 0.12.0
|
(c++)"std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)2>::_M_dispose()@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)1>::_M_get_deleter(std::type_info const&)@Base" 0.12.0
|
(c++)"std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)2>::_M_get_deleter(std::type_info const&)@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)2>::~_Sp_counted_ptr_inplace()@Base" 0.12.0
|
(c++)"std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)2>::~_Sp_counted_ptr_inplace()@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)1>::~_Sp_counted_ptr_inplace()@Base" 0.12.0
|
(c++)"std::_Sp_counted_ptr_inplace<Fm::VolumeManager, std::allocator<Fm::VolumeManager>, (__gnu_cxx::_Lock_policy)2>::_M_destroy()@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<Fm::VolumeManager, std::allocator<Fm::VolumeManager>, (__gnu_cxx::_Lock_policy)2>::_M_destroy()@Base" 0.12.0
|
(c++)"std::_Sp_counted_ptr_inplace<Fm::VolumeManager, std::allocator<Fm::VolumeManager>, (__gnu_cxx::_Lock_policy)2>::_M_dispose()@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<Fm::VolumeManager, std::allocator<Fm::VolumeManager>, (__gnu_cxx::_Lock_policy)1>::_M_destroy()@Base" 0.12.0
|
(c++)"std::_Sp_counted_ptr_inplace<Fm::VolumeManager, std::allocator<Fm::VolumeManager>, (__gnu_cxx::_Lock_policy)2>::_M_get_deleter(std::type_info const&)@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<Fm::VolumeManager, std::allocator<Fm::VolumeManager>, (__gnu_cxx::_Lock_policy)2>::_M_dispose()@Base" 0.12.0
|
(c++)"std::_Sp_counted_ptr_inplace<Fm::VolumeManager, std::allocator<Fm::VolumeManager>, (__gnu_cxx::_Lock_policy)2>::~_Sp_counted_ptr_inplace()@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<Fm::VolumeManager, std::allocator<Fm::VolumeManager>, (__gnu_cxx::_Lock_policy)1>::_M_dispose()@Base" 0.12.0
|
(c++)"std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)2>::_M_destroy()@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<Fm::VolumeManager, std::allocator<Fm::VolumeManager>, (__gnu_cxx::_Lock_policy)2>::_M_get_deleter(std::type_info const&)@Base" 0.12.0
|
(c++)"std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)2>::_M_dispose()@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<Fm::VolumeManager, std::allocator<Fm::VolumeManager>, (__gnu_cxx::_Lock_policy)1>::_M_get_deleter(std::type_info const&)@Base" 0.12.0
|
(c++)"std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)2>::_M_get_deleter(std::type_info const&)@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<Fm::VolumeManager, std::allocator<Fm::VolumeManager>, (__gnu_cxx::_Lock_policy)2>::~_Sp_counted_ptr_inplace()@Base" 0.12.0
|
(c++)"std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)2>::~_Sp_counted_ptr_inplace()@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<Fm::VolumeManager, std::allocator<Fm::VolumeManager>, (__gnu_cxx::_Lock_policy)1>::~_Sp_counted_ptr_inplace()@Base" 0.12.0
|
(c++)"std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > __gnu_cxx::__to_xstring<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char>(int (*)(char*, unsigned long, char const*, __va_list_tag*), unsigned long, char const*, ...)@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)2>::_M_destroy()@Base" 0.12.0
|
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)1>::_M_destroy()@Base" 0.12.0
|
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)2>::_M_dispose()@Base" 0.12.0
|
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)1>::_M_dispose()@Base" 0.12.0
|
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)2>::_M_get_deleter(std::type_info const&)@Base" 0.12.0
|
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)1>::_M_get_deleter(std::type_info const&)@Base" 0.12.0
|
|
||||||
(c++|arch= !armel !riscv64 )"std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)2>::~_Sp_counted_ptr_inplace()@Base" 0.12.0
|
|
||||||
(c++|arch= armel riscv64 )"std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)1>::~_Sp_counted_ptr_inplace()@Base" 0.12.0
|
|
||||||
(c++|arch= !arm64 !armel !armhf !i386 !mips !mipsel !mips64el !ppc64el !alpha !hppa !hurd-i386 !ia64 !kfreebsd-i386 !m68k !powerpc !ppc64 !riscv64 !sh4 !sparc64 !x32 )"std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > __gnu_cxx::__to_xstring<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char>(int (*)(char*, unsigned long, char const*, __va_list_tag*), unsigned long, char const*, ...)@Base" 0.12.0
|
|
||||||
(optional|c++|arch= !amd64 !arm64 !armel !armhf !i386 !mips !mips64el !mipsel !ppc64el !s390x !hppa !ia64 !kfreebsd-amd64 !kfreebsd-i386 !m68k !powerpc !ppc64 !riscv64 !sh4 !x32 )"std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > __gnu_cxx::__to_xstring<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char>(int (*)(char*, unsigned long, char const*, __va_list_tag), unsigned long, char const*, ...)@Base" 0.12.0
|
|
||||||
(optional|c++|arch= !amd64 !arm64 !i386 !mips !mips64el !mipsel !ppc64el !s390x !alpha !hppa !hurd-i386 !ia64 !kfreebsd-amd64 !kfreebsd-i386 !m68k !powerpc !ppc64 !riscv64 !sh4 !x32 )"std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > __gnu_cxx::__to_xstring<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char>(int (*)(char*, unsigned int, char const*, std::__va_list), unsigned int, char const*, ...)@Base" 0.12.0
|
|
||||||
(optional|c++|arch= !amd64 !arm64 !armel !armhf !i386 !mips64el !ppc64el !s390x !alpha !hurd-i386 !ia64 !kfreebsd-amd64 !kfreebsd-i386 !powerpc !ppc64 !riscv64 !sh4 !x32 )"std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > __gnu_cxx::__to_xstring<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char>(int (*)(char*, unsigned int, char const*, void*), unsigned int, char const*, ...)@Base" 0.12.0
|
|
||||||
(optional|c++|arch= !amd64 !arm64 !armel !armhf !i386 !mips !mips64el !mipsel !s390x !alpha !hppa !ia64 !kfreebsd-amd64 !kfreebsd-i386 !m68k !powerpc !riscv64 !sh4 !x32 )"std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > __gnu_cxx::__to_xstring<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char>(int (*)(char*, unsigned long, char const*, char*), unsigned long, char const*, ...)@Base" 0.12.0
|
|
||||||
(optional|c++|arch= !amd64 !arm64 !armel !armhf !mips !mipsel !mips64el !ppc64el !s390x !alpha !ia64 !kfreebsd-amd64 !hppa !m68k !powerpc !ppc64 !riscv64 !sh4 !sparc64 !x32 )"std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > __gnu_cxx::__to_xstring<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char>(int (*)(char*, unsigned int, char const*, char*), unsigned int, char const*, ...)@Base" 0.12.0
|
|
||||||
(optional|c++|arch= !amd64 !arm64 !armel !armhf !i386 !mips !mips64el !mipsel !ppc64el !s390x !alpha !hppa !ia64 !kfreebsd-amd64 !kfreebsd-i386 !m68k !ppc64 !riscv64 !sh4 )"std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > __gnu_cxx::__to_xstring<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char>(int (*)(char*, unsigned int, char const*, __va_list_tag*), unsigned int, char const*, ...)@Base" 0.12.0
|
|
||||||
(optional|c++|arch= !amd64 !arm64 !armel !armhf !i386 !mips !mips64el !mipsel !ppc64el !s390x !alpha !hppa !ia64 !kfreebsd-amd64 !kfreebsd-i386 !m68k !powerpc !ppc64 !riscv64 !x32)"std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > __gnu_cxx::__to_xstring<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char>(int (*)(char*, unsigned int, char const*, __va_list_tag), unsigned int, char const*, ...)@Base" 0.12.0
|
|
||||||
(optional|c++|arch= !amd64 !arm64 !armel !armhf !i386 !mips !mipsel !ppc64el !s390x !alpha !hppa !kfreebsd-amd64 !kfreebsd-i386 !m68k !powerpc !ppc64 !sh4 !x32 )"std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > __gnu_cxx::__to_xstring<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char>(int (*)(char*, unsigned long, char const*, void*), unsigned long, char const*, ...)@Base" 0.12.0
|
|
||||||
(optional|c++|arch= !amd64 !armel !armhf !i386 !mips !mipsel !mips64el !ppc64el !s390x !alpha !hppa !hurd-i386 !ia64 !kfreebsd-amd64 !kfreebsd-i386 !m68k !powerpc !ppc64 !riscv64 !sh4 !sparc64 !x32 )"std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > __gnu_cxx::__to_xstring<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char>(int (*)(char*, unsigned long, char const*, std::__va_list), unsigned long, char const*, ...)@Base" 0.12.0
|
|
||||||
(c++)"std::__detail::_Map_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> > >, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const>, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>, true>::operator[](std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.12.0
|
(c++)"std::__detail::_Map_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Fm::FileInfo const> > >, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const>, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>, true>::operator[](std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.12.0
|
||||||
|
(c++)"std::__detail::_Map_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, Fm::FileInfoList>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, Fm::FileInfoList> >, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>, true>::operator[](std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&)@Base" 0.13.0~
|
||||||
(c++)"std::pair<std::_Rb_tree_iterator<unsigned int>, bool> std::_Rb_tree<unsigned int, unsigned int, std::_Identity<unsigned int>, std::less<unsigned int>, std::allocator<unsigned int> >::_M_insert_unique<unsigned int>(unsigned int&&)@Base" 0.12.0
|
(c++)"std::pair<std::_Rb_tree_iterator<unsigned int>, bool> std::_Rb_tree<unsigned int, unsigned int, std::_Identity<unsigned int>, std::less<unsigned int>, std::allocator<unsigned int> >::_M_insert_unique<unsigned int>(unsigned int&&)@Base" 0.12.0
|
||||||
|
(optional=gcc8|c++)"std::pair<std::__detail::_Node_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, char const*>, false, true>, bool> std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, char const*>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, char const*> >, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::_M_emplace<std::pair<char const*, char const*> >(std::integral_constant<bool, true>, std::pair<char const*, char const*>&&)@Base" 0.13.0~
|
||||||
(c++)"std::vector<Fm::BrowseHistoryItem, std::allocator<Fm::BrowseHistoryItem> >::_M_erase(__gnu_cxx::__normal_iterator<Fm::BrowseHistoryItem*, std::vector<Fm::BrowseHistoryItem, std::allocator<Fm::BrowseHistoryItem> > >)@Base" 0.12.0
|
(c++)"std::vector<Fm::BrowseHistoryItem, std::allocator<Fm::BrowseHistoryItem> >::_M_erase(__gnu_cxx::__normal_iterator<Fm::BrowseHistoryItem*, std::vector<Fm::BrowseHistoryItem, std::allocator<Fm::BrowseHistoryItem> > >)@Base" 0.12.0
|
||||||
(c++)"std::vector<Fm::DirTreeModelItem*, std::allocator<Fm::DirTreeModelItem*> >::_M_erase(__gnu_cxx::__normal_iterator<Fm::DirTreeModelItem**, std::vector<Fm::DirTreeModelItem*, std::allocator<Fm::DirTreeModelItem*> > >)@Base" 0.12.0
|
(c++)"std::vector<Fm::DirTreeModelItem*, std::allocator<Fm::DirTreeModelItem*> >::_M_erase(__gnu_cxx::__normal_iterator<Fm::DirTreeModelItem**, std::vector<Fm::DirTreeModelItem*, std::allocator<Fm::DirTreeModelItem*> > >)@Base" 0.12.0
|
||||||
(c++)"std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >::_M_erase(__gnu_cxx::__normal_iterator<Fm::FilePath*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > >, __gnu_cxx::__normal_iterator<Fm::FilePath*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > >)@Base" 0.12.0
|
(c++)"std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >::_M_erase(__gnu_cxx::__normal_iterator<Fm::FilePath*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > >, __gnu_cxx::__normal_iterator<Fm::FilePath*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > >)@Base" 0.12.0
|
||||||
(c++|arch= !i386 !mips !mipsel !s390x !alpha !hurd-i386 !kfreebsd-i386 !powerpc !ppc64 )"std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >::insert(__gnu_cxx::__normal_iterator<Fm::FilePath const*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > >, Fm::FilePath const&)@Base" 0.12.0
|
(optional=gcc8|c++)"std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >::reserve(unsigned long)@Base" 0.13.0~
|
||||||
(c++)"std::vector<std::shared_ptr<Fm::BookmarkItem const>, std::allocator<std::shared_ptr<Fm::BookmarkItem const> > >::_M_erase(__gnu_cxx::__normal_iterator<std::shared_ptr<Fm::BookmarkItem const>*, std::vector<std::shared_ptr<Fm::BookmarkItem const>, std::allocator<std::shared_ptr<Fm::BookmarkItem const> > > >)@Base" 0.12.0
|
(c++)"std::vector<std::shared_ptr<Fm::BookmarkItem const>, std::allocator<std::shared_ptr<Fm::BookmarkItem const> > >::_M_erase(__gnu_cxx::__normal_iterator<std::shared_ptr<Fm::BookmarkItem const>*, std::vector<std::shared_ptr<Fm::BookmarkItem const>, std::allocator<std::shared_ptr<Fm::BookmarkItem const> > > >)@Base" 0.12.0
|
||||||
(c++)"std::vector<std::shared_ptr<Fm::BookmarkItem const>, std::allocator<std::shared_ptr<Fm::BookmarkItem const> > >::_M_insert_rval(__gnu_cxx::__normal_iterator<std::shared_ptr<Fm::BookmarkItem const> const*, std::vector<std::shared_ptr<Fm::BookmarkItem const>, std::allocator<std::shared_ptr<Fm::BookmarkItem const> > > >, std::shared_ptr<Fm::BookmarkItem const>&&)@Base" 0.12.0
|
(c++)"std::vector<std::shared_ptr<Fm::BookmarkItem const>, std::allocator<std::shared_ptr<Fm::BookmarkItem const> > >::_M_insert_rval(__gnu_cxx::__normal_iterator<std::shared_ptr<Fm::BookmarkItem const> const*, std::vector<std::shared_ptr<Fm::BookmarkItem const>, std::allocator<std::shared_ptr<Fm::BookmarkItem const> > > >, std::shared_ptr<Fm::BookmarkItem const>&&)@Base" 0.12.0
|
||||||
(c++)"std::vector<std::shared_ptr<Fm::FileInfo const>, std::allocator<std::shared_ptr<Fm::FileInfo const> > >::operator=(std::vector<std::shared_ptr<Fm::FileInfo const>, std::allocator<std::shared_ptr<Fm::FileInfo const> > > const&)@Base" 0.12.0
|
(c++)"std::vector<std::shared_ptr<Fm::FileInfo const>, std::allocator<std::shared_ptr<Fm::FileInfo const> > >::operator=(std::vector<std::shared_ptr<Fm::FileInfo const>, std::allocator<std::shared_ptr<Fm::FileInfo const> > > const&)@Base" 0.12.0
|
||||||
(c++|arch= !armel !armhf !i386 !mips !mipsel !hppa !hurd-i386 !kfreebsd-i386 !m68k !powerpc !sh4 !x32 )"std::vector<std::shared_ptr<Fm::FileInfo const>, std::allocator<std::shared_ptr<Fm::FileInfo const> > >::reserve(unsigned long)@Base" 0.12.0
|
(c++)"std::vector<std::shared_ptr<Fm::TemplateItem>, std::allocator<std::shared_ptr<Fm::TemplateItem> > >::_M_erase(__gnu_cxx::__normal_iterator<std::shared_ptr<Fm::TemplateItem>*, std::vector<std::shared_ptr<Fm::TemplateItem>, std::allocator<std::shared_ptr<Fm::TemplateItem> > > >, __gnu_cxx::__normal_iterator<std::shared_ptr<Fm::TemplateItem>*, std::vector<std::shared_ptr<Fm::TemplateItem>, std::allocator<std::shared_ptr<Fm::TemplateItem> > > >)@Base" 0.13.0~
|
||||||
(optional|c++|arch= !amd64 !arm64 !mips64el !ppc64el !s390x !ia64 !kfreebsd-amd64 !alpha !ppc64 !riscv64 !sparc64 )"std::vector<std::shared_ptr<Fm::FileInfo const>, std::allocator<std::shared_ptr<Fm::FileInfo const> > >::reserve(unsigned int)@Base" 0.12.0
|
|
||||||
(c++)"std::vector<std::shared_ptr<Fm::Thumbnailer>, std::allocator<std::shared_ptr<Fm::Thumbnailer> > >::~vector()@Base" 0.12.0
|
(c++)"std::vector<std::shared_ptr<Fm::Thumbnailer>, std::allocator<std::shared_ptr<Fm::Thumbnailer> > >::~vector()@Base" 0.12.0
|
||||||
|
(c++)"std::vector<std::unique_ptr<Fm::Archiver, std::default_delete<Fm::Archiver> >, std::allocator<std::unique_ptr<Fm::Archiver, std::default_delete<Fm::Archiver> > > >::~vector()@Base" 0.13.0~
|
||||||
(c++)"typeinfo for Fm::AppChooserComboBox@Base" 0.10.0
|
(c++)"typeinfo for Fm::AppChooserComboBox@Base" 0.10.0
|
||||||
(c++)"typeinfo for Fm::AppChooserDialog@Base" 0.10.0
|
(c++)"typeinfo for Fm::AppChooserDialog@Base" 0.10.0
|
||||||
(c++)"typeinfo for Fm::AppMenuView@Base" 0.10.0
|
(c++)"typeinfo for Fm::AppMenuView@Base" 0.10.0
|
||||||
|
(c++)"typeinfo for Fm::BasicFileLauncher@Base" 0.13.0~
|
||||||
(c++)"typeinfo for Fm::BookmarkAction@Base" 0.10.0
|
(c++)"typeinfo for Fm::BookmarkAction@Base" 0.10.0
|
||||||
(c++)"typeinfo for Fm::Bookmarks@Base" 0.12.0
|
(c++)"typeinfo for Fm::Bookmarks@Base" 0.12.0
|
||||||
(c++)"typeinfo for Fm::BrowseHistory@Base" 0.10.0
|
(c++)"typeinfo for Fm::BrowseHistory@Base" 0.10.0
|
||||||
(c++)"typeinfo for Fm::CachedFolderModel@Base" 0.10.0
|
(c++)"typeinfo for Fm::CachedFolderModel@Base" 0.10.0
|
||||||
(c++)"typeinfo for Fm::ColorButton@Base" 0.10.0
|
(c++)"typeinfo for Fm::ColorButton@Base" 0.10.0
|
||||||
(c++)"typeinfo for Fm::CopyJob@Base" 0.12.0
|
|
||||||
(c++)"typeinfo for Fm::CreateNewMenu@Base" 0.10.0
|
(c++)"typeinfo for Fm::CreateNewMenu@Base" 0.10.0
|
||||||
(c++)"typeinfo for Fm::DeleteJob@Base" 0.12.0
|
(c++)"typeinfo for Fm::DeleteJob@Base" 0.12.0
|
||||||
(c++)"typeinfo for Fm::DirListJob@Base" 0.12.0
|
(c++)"typeinfo for Fm::DirListJob@Base" 0.12.0
|
||||||
@ -1167,6 +1238,7 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"typeinfo for Fm::FilePropsDialog@Base" 0.10.0
|
(c++)"typeinfo for Fm::FilePropsDialog@Base" 0.10.0
|
||||||
(c++)"typeinfo for Fm::FileSearchDialog@Base" 0.10.0
|
(c++)"typeinfo for Fm::FileSearchDialog@Base" 0.10.0
|
||||||
(c++)"typeinfo for Fm::FileSystemInfoJob@Base" 0.12.0
|
(c++)"typeinfo for Fm::FileSystemInfoJob@Base" 0.12.0
|
||||||
|
(c++)"typeinfo for Fm::FileTransferJob@Base" 0.13.0~
|
||||||
(c++)"typeinfo for Fm::Folder@Base" 0.12.0
|
(c++)"typeinfo for Fm::Folder@Base" 0.12.0
|
||||||
(c++)"typeinfo for Fm::FolderItemDelegate@Base" 0.10.0
|
(c++)"typeinfo for Fm::FolderItemDelegate@Base" 0.10.0
|
||||||
(c++)"typeinfo for Fm::FolderMenu@Base" 0.10.0
|
(c++)"typeinfo for Fm::FolderMenu@Base" 0.10.0
|
||||||
@ -1174,7 +1246,6 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"typeinfo for Fm::FolderModelItem@Base" 0.10.0
|
(c++)"typeinfo for Fm::FolderModelItem@Base" 0.10.0
|
||||||
(c++)"typeinfo for Fm::FolderView@Base" 0.10.0
|
(c++)"typeinfo for Fm::FolderView@Base" 0.10.0
|
||||||
(c++)"typeinfo for Fm::FontButton@Base" 0.10.0
|
(c++)"typeinfo for Fm::FontButton@Base" 0.10.0
|
||||||
(c++)"typeinfo for Fm::IconTheme@Base" 0.10.0
|
|
||||||
(c++)"typeinfo for Fm::Job@Base" 0.12.0
|
(c++)"typeinfo for Fm::Job@Base" 0.12.0
|
||||||
(c++)"typeinfo for Fm::MountOperation@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::PathBar@Base" 0.11.2
|
||||||
@ -1185,11 +1256,13 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"typeinfo for Fm::PlacesModelItem@Base" 0.10.0
|
(c++)"typeinfo for Fm::PlacesModelItem@Base" 0.10.0
|
||||||
(c++)"typeinfo for Fm::PlacesModelMountItem@Base" 0.10.0
|
(c++)"typeinfo for Fm::PlacesModelMountItem@Base" 0.10.0
|
||||||
(c++)"typeinfo for Fm::PlacesModelVolumeItem@Base" 0.10.0
|
(c++)"typeinfo for Fm::PlacesModelVolumeItem@Base" 0.10.0
|
||||||
|
(c++)"typeinfo for Fm::PlacesProxyModel@Base" 0.13.0~
|
||||||
(c++)"typeinfo for Fm::PlacesView@Base" 0.10.0
|
(c++)"typeinfo for Fm::PlacesView@Base" 0.10.0
|
||||||
(c++)"typeinfo for Fm::ProxyFolderModel@Base" 0.10.0
|
(c++)"typeinfo for Fm::ProxyFolderModel@Base" 0.10.0
|
||||||
(c++)"typeinfo for Fm::ProxyFolderModelFilter@Base" 0.12.0
|
(c++)"typeinfo for Fm::ProxyFolderModelFilter@Base" 0.12.0
|
||||||
(c++)"typeinfo for Fm::RenameDialog@Base" 0.10.0
|
(c++)"typeinfo for Fm::RenameDialog@Base" 0.10.0
|
||||||
(c++)"typeinfo for Fm::SidePane@Base" 0.10.0
|
(c++)"typeinfo for Fm::SidePane@Base" 0.10.0
|
||||||
|
(c++)"typeinfo for Fm::Templates@Base" 0.13.0~
|
||||||
(c++)"typeinfo for Fm::ThumbnailJob@Base" 0.12.0
|
(c++)"typeinfo for Fm::ThumbnailJob@Base" 0.12.0
|
||||||
(c++)"typeinfo for Fm::TotalSizeJob@Base" 0.12.0
|
(c++)"typeinfo for Fm::TotalSizeJob@Base" 0.12.0
|
||||||
(c++)"typeinfo for Fm::TrashJob@Base" 0.12.0
|
(c++)"typeinfo for Fm::TrashJob@Base" 0.12.0
|
||||||
@ -1219,28 +1292,24 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++|arch= armel riscv64 )"typeinfo for std::_Sp_counted_ptr_inplace<Fm::IconInfo, std::allocator<Fm::IconInfo>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
(c++|arch= armel riscv64 )"typeinfo for std::_Sp_counted_ptr_inplace<Fm::IconInfo, std::allocator<Fm::IconInfo>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"typeinfo for std::_Sp_counted_ptr_inplace<Fm::MimeType, std::allocator<Fm::MimeType>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
(c++|arch= !armel !riscv64 )"typeinfo for std::_Sp_counted_ptr_inplace<Fm::MimeType, std::allocator<Fm::MimeType>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"typeinfo for std::_Sp_counted_ptr_inplace<Fm::MimeType, std::allocator<Fm::MimeType>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
(c++|arch= armel riscv64 )"typeinfo for std::_Sp_counted_ptr_inplace<Fm::MimeType, std::allocator<Fm::MimeType>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"typeinfo for std::_Sp_counted_ptr_inplace<Fm::PlacesModel, std::allocator<Fm::PlacesModel>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
(c++)"typeinfo for std::_Sp_counted_ptr_inplace<Fm::PlacesModel, std::allocator<Fm::PlacesModel>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"typeinfo for std::_Sp_counted_ptr_inplace<Fm::PlacesModel, std::allocator<Fm::PlacesModel>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
(c++)"typeinfo for std::_Sp_counted_ptr_inplace<Fm::PlacesProxyModel, std::allocator<Fm::PlacesProxyModel>, (__gnu_cxx::_Lock_policy)2>@Base" 0.13.0~
|
||||||
(c++|arch= !armel !riscv64 )"typeinfo for std::_Sp_counted_ptr_inplace<Fm::Thumbnailer, std::allocator<Fm::Thumbnailer>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
(c++)"typeinfo for std::_Sp_counted_ptr_inplace<Fm::TemplateItem, std::allocator<Fm::TemplateItem>, (__gnu_cxx::_Lock_policy)2>@Base" 0.13.0~
|
||||||
(c++|arch= armel riscv64 )"typeinfo for std::_Sp_counted_ptr_inplace<Fm::Thumbnailer, std::allocator<Fm::Thumbnailer>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
(c++)"typeinfo for std::_Sp_counted_ptr_inplace<Fm::Templates, std::allocator<Fm::Templates>, (__gnu_cxx::_Lock_policy)2>@Base" 0.13.0~
|
||||||
(c++|arch= !armel !riscv64 )"typeinfo for std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
(c++)"typeinfo for std::_Sp_counted_ptr_inplace<Fm::Thumbnailer, std::allocator<Fm::Thumbnailer>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"typeinfo for std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
(c++)"typeinfo for std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"typeinfo for std::_Sp_counted_ptr_inplace<Fm::VolumeManager, std::allocator<Fm::VolumeManager>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
(c++)"typeinfo for std::_Sp_counted_ptr_inplace<Fm::VolumeManager, std::allocator<Fm::VolumeManager>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"typeinfo for std::_Sp_counted_ptr_inplace<Fm::VolumeManager, std::allocator<Fm::VolumeManager>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
(c++)"typeinfo for std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"typeinfo for std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
|
||||||
(c++|arch= armel riscv64 )"typeinfo for std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
|
||||||
(optional|c++|arch=armel riscv64 )"typeinfo for __gnu_cxx::__mutex@Base" 0.12.0
|
|
||||||
(optional|c++|arch=armel riscv64 )"typeinfo name for __gnu_cxx::__mutex@Base" 0.12.0
|
|
||||||
(c++)"typeinfo for std::_Sp_make_shared_tag@Base" 0.12.0
|
(c++)"typeinfo for std::_Sp_make_shared_tag@Base" 0.12.0
|
||||||
(c++)"typeinfo name for Fm::AppChooserComboBox@Base" 0.10.0
|
(c++)"typeinfo name for Fm::AppChooserComboBox@Base" 0.10.0
|
||||||
(c++)"typeinfo name for Fm::AppChooserDialog@Base" 0.10.0
|
(c++)"typeinfo name for Fm::AppChooserDialog@Base" 0.10.0
|
||||||
(c++)"typeinfo name for Fm::AppMenuView@Base" 0.10.0
|
(c++)"typeinfo name for Fm::AppMenuView@Base" 0.10.0
|
||||||
|
(c++)"typeinfo name for Fm::BasicFileLauncher@Base" 0.13.0~
|
||||||
(c++)"typeinfo name for Fm::BookmarkAction@Base" 0.10.0
|
(c++)"typeinfo name for Fm::BookmarkAction@Base" 0.10.0
|
||||||
(c++)"typeinfo name for Fm::Bookmarks@Base" 0.12.0
|
(c++)"typeinfo name for Fm::Bookmarks@Base" 0.12.0
|
||||||
(c++)"typeinfo name for Fm::BrowseHistory@Base" 0.10.0
|
(c++)"typeinfo name for Fm::BrowseHistory@Base" 0.10.0
|
||||||
(c++)"typeinfo name for Fm::CachedFolderModel@Base" 0.10.0
|
(c++)"typeinfo name for Fm::CachedFolderModel@Base" 0.10.0
|
||||||
(c++)"typeinfo name for Fm::ColorButton@Base" 0.10.0
|
(c++)"typeinfo name for Fm::ColorButton@Base" 0.10.0
|
||||||
(c++)"typeinfo name for Fm::CopyJob@Base" 0.12.0
|
|
||||||
(c++)"typeinfo name for Fm::CreateNewMenu@Base" 0.10.0
|
(c++)"typeinfo name for Fm::CreateNewMenu@Base" 0.10.0
|
||||||
(c++)"typeinfo name for Fm::DeleteJob@Base" 0.12.0
|
(c++)"typeinfo name for Fm::DeleteJob@Base" 0.12.0
|
||||||
(c++)"typeinfo name for Fm::DirListJob@Base" 0.12.0
|
(c++)"typeinfo name for Fm::DirListJob@Base" 0.12.0
|
||||||
@ -1262,6 +1331,7 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"typeinfo name for Fm::FilePropsDialog@Base" 0.10.0
|
(c++)"typeinfo name for Fm::FilePropsDialog@Base" 0.10.0
|
||||||
(c++)"typeinfo name for Fm::FileSearchDialog@Base" 0.10.0
|
(c++)"typeinfo name for Fm::FileSearchDialog@Base" 0.10.0
|
||||||
(c++)"typeinfo name for Fm::FileSystemInfoJob@Base" 0.12.0
|
(c++)"typeinfo name for Fm::FileSystemInfoJob@Base" 0.12.0
|
||||||
|
(c++)"typeinfo name for Fm::FileTransferJob@Base" 0.13.0~
|
||||||
(c++)"typeinfo name for Fm::Folder@Base" 0.12.0
|
(c++)"typeinfo name for Fm::Folder@Base" 0.12.0
|
||||||
(c++)"typeinfo name for Fm::FolderItemDelegate@Base" 0.10.0
|
(c++)"typeinfo name for Fm::FolderItemDelegate@Base" 0.10.0
|
||||||
(c++)"typeinfo name for Fm::FolderMenu@Base" 0.10.0
|
(c++)"typeinfo name for Fm::FolderMenu@Base" 0.10.0
|
||||||
@ -1269,7 +1339,6 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"typeinfo name for Fm::FolderModelItem@Base" 0.10.0
|
(c++)"typeinfo name for Fm::FolderModelItem@Base" 0.10.0
|
||||||
(c++)"typeinfo name for Fm::FolderView@Base" 0.10.0
|
(c++)"typeinfo name for Fm::FolderView@Base" 0.10.0
|
||||||
(c++)"typeinfo name for Fm::FontButton@Base" 0.10.0
|
(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::Job@Base" 0.12.0
|
(c++)"typeinfo name for Fm::Job@Base" 0.12.0
|
||||||
(c++)"typeinfo name for Fm::MountOperation@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::PathBar@Base" 0.11.2
|
||||||
@ -1280,11 +1349,13 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"typeinfo name for Fm::PlacesModelItem@Base" 0.10.0
|
(c++)"typeinfo name for Fm::PlacesModelItem@Base" 0.10.0
|
||||||
(c++)"typeinfo name for Fm::PlacesModelMountItem@Base" 0.10.0
|
(c++)"typeinfo name for Fm::PlacesModelMountItem@Base" 0.10.0
|
||||||
(c++)"typeinfo name for Fm::PlacesModelVolumeItem@Base" 0.10.0
|
(c++)"typeinfo name for Fm::PlacesModelVolumeItem@Base" 0.10.0
|
||||||
|
(c++)"typeinfo name for Fm::PlacesProxyModel@Base" 0.13.0~
|
||||||
(c++)"typeinfo name for Fm::PlacesView@Base" 0.10.0
|
(c++)"typeinfo name for Fm::PlacesView@Base" 0.10.0
|
||||||
(c++)"typeinfo name for Fm::ProxyFolderModel@Base" 0.10.0
|
(c++)"typeinfo name for Fm::ProxyFolderModel@Base" 0.10.0
|
||||||
(c++)"typeinfo name for Fm::ProxyFolderModelFilter@Base" 0.12.0
|
(c++)"typeinfo name for Fm::ProxyFolderModelFilter@Base" 0.12.0
|
||||||
(c++)"typeinfo name for Fm::RenameDialog@Base" 0.10.0
|
(c++)"typeinfo name for Fm::RenameDialog@Base" 0.10.0
|
||||||
(c++)"typeinfo name for Fm::SidePane@Base" 0.10.0
|
(c++)"typeinfo name for Fm::SidePane@Base" 0.10.0
|
||||||
|
(c++)"typeinfo name for Fm::Templates@Base" 0.13.0~
|
||||||
(c++)"typeinfo name for Fm::ThumbnailJob@Base" 0.12.0
|
(c++)"typeinfo name for Fm::ThumbnailJob@Base" 0.12.0
|
||||||
(c++)"typeinfo name for Fm::TotalSizeJob@Base" 0.12.0
|
(c++)"typeinfo name for Fm::TotalSizeJob@Base" 0.12.0
|
||||||
(c++)"typeinfo name for Fm::TrashJob@Base" 0.12.0
|
(c++)"typeinfo name for Fm::TrashJob@Base" 0.12.0
|
||||||
@ -1315,9 +1386,10 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++|arch= !armel !riscv64 )"typeinfo name for std::_Sp_counted_ptr_inplace<Fm::MimeType, std::allocator<Fm::MimeType>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
(c++|arch= !armel !riscv64 )"typeinfo name for std::_Sp_counted_ptr_inplace<Fm::MimeType, std::allocator<Fm::MimeType>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"typeinfo name for std::_Sp_counted_ptr_inplace<Fm::MimeType, std::allocator<Fm::MimeType>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
(c++|arch= armel riscv64 )"typeinfo name for std::_Sp_counted_ptr_inplace<Fm::MimeType, std::allocator<Fm::MimeType>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"typeinfo name for std::_Sp_counted_ptr_inplace<Fm::PlacesModel, std::allocator<Fm::PlacesModel>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
(c++|arch= !armel !riscv64 )"typeinfo name for std::_Sp_counted_ptr_inplace<Fm::PlacesModel, std::allocator<Fm::PlacesModel>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"typeinfo name for std::_Sp_counted_ptr_inplace<Fm::PlacesModel, std::allocator<Fm::PlacesModel>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
(c++)"typeinfo name for std::_Sp_counted_ptr_inplace<Fm::PlacesProxyModel, std::allocator<Fm::PlacesProxyModel>, (__gnu_cxx::_Lock_policy)2>@Base" 0.13.0~
|
||||||
(c++|arch= !armel !riscv64 )"typeinfo name for std::_Sp_counted_ptr_inplace<Fm::Thumbnailer, std::allocator<Fm::Thumbnailer>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
(c++)"typeinfo name for std::_Sp_counted_ptr_inplace<Fm::TemplateItem, std::allocator<Fm::TemplateItem>, (__gnu_cxx::_Lock_policy)2>@Base" 0.13.0~
|
||||||
(c++|arch= armel riscv64 )"typeinfo name for std::_Sp_counted_ptr_inplace<Fm::Thumbnailer, std::allocator<Fm::Thumbnailer>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
(c++)"typeinfo name for std::_Sp_counted_ptr_inplace<Fm::Templates, std::allocator<Fm::Templates>, (__gnu_cxx::_Lock_policy)2>@Base" 0.13.0~
|
||||||
|
(c++)"typeinfo name for std::_Sp_counted_ptr_inplace<Fm::Thumbnailer, std::allocator<Fm::Thumbnailer>, (__gnu_cxx::_Lock_policy)2>@Base" 0.13.0~
|
||||||
(c++|arch= !armel !riscv64 )"typeinfo name for std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
(c++|arch= !armel !riscv64 )"typeinfo name for std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"typeinfo name for std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
(c++|arch= armel riscv64 )"typeinfo name for std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"typeinfo name for std::_Sp_counted_ptr_inplace<Fm::VolumeManager, std::allocator<Fm::VolumeManager>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
(c++|arch= !armel !riscv64 )"typeinfo name for std::_Sp_counted_ptr_inplace<Fm::VolumeManager, std::allocator<Fm::VolumeManager>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
||||||
@ -1325,11 +1397,15 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++|arch= !armel !riscv64 )"typeinfo name for std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
(c++|arch= !armel !riscv64 )"typeinfo name for std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"typeinfo name for std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
(c++|arch= armel riscv64 )"typeinfo name for std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
||||||
(c++)"typeinfo name for std::_Sp_make_shared_tag@Base" 0.12.0
|
(c++)"typeinfo name for std::_Sp_make_shared_tag@Base" 0.12.0
|
||||||
|
(optional=gcc8|c++)"void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char const*>(char const*, char const*, std::forward_iterator_tag)@Base" 0.13.0~
|
||||||
|
(optional=gcc8|c++)"void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char*>(char*, char*, std::forward_iterator_tag)@Base" 0.13.0~
|
||||||
(c++)"void std::vector<Fm::BrowseHistoryItem, std::allocator<Fm::BrowseHistoryItem> >::_M_realloc_insert<Fm::BrowseHistoryItem>(__gnu_cxx::__normal_iterator<Fm::BrowseHistoryItem*, std::vector<Fm::BrowseHistoryItem, std::allocator<Fm::BrowseHistoryItem> > >, Fm::BrowseHistoryItem&&)@Base" 0.12.0
|
(c++)"void std::vector<Fm::BrowseHistoryItem, std::allocator<Fm::BrowseHistoryItem> >::_M_realloc_insert<Fm::BrowseHistoryItem>(__gnu_cxx::__normal_iterator<Fm::BrowseHistoryItem*, std::vector<Fm::BrowseHistoryItem, std::allocator<Fm::BrowseHistoryItem> > >, Fm::BrowseHistoryItem&&)@Base" 0.12.0
|
||||||
(optional|c++)"void std::vector<Fm::DirTreeModelItem*, std::allocator<Fm::DirTreeModelItem*> >::_M_realloc_insert<Fm::DirTreeModelItem*>(__gnu_cxx::__normal_iterator<Fm::DirTreeModelItem**, std::vector<Fm::DirTreeModelItem*, std::allocator<Fm::DirTreeModelItem*> > >, Fm::DirTreeModelItem*&&)@Base" 0.12.0
|
(optional=gcc8|c++)"void std::vector<Fm::DirTreeModelItem*, std::allocator<Fm::DirTreeModelItem*> >::emplace_back<Fm::DirTreeModelItem*>(Fm::DirTreeModelItem*&&)@Base" 0.13.0~
|
||||||
(c++)"void std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >::_M_range_insert<__gnu_cxx::__normal_iterator<Fm::FilePath const*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > > >(__gnu_cxx::__normal_iterator<Fm::FilePath*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > >, __gnu_cxx::__normal_iterator<Fm::FilePath const*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > >, __gnu_cxx::__normal_iterator<Fm::FilePath const*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > >, std::forward_iterator_tag)@Base" 0.12.0
|
(c++)"void std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >::_M_range_insert<__gnu_cxx::__normal_iterator<Fm::FilePath const*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > > >(__gnu_cxx::__normal_iterator<Fm::FilePath*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > >, __gnu_cxx::__normal_iterator<Fm::FilePath const*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > >, __gnu_cxx::__normal_iterator<Fm::FilePath const*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > >, std::forward_iterator_tag)@Base" 0.12.0
|
||||||
(c++)"void std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >::_M_realloc_insert<Fm::FilePath const&>(__gnu_cxx::__normal_iterator<Fm::FilePath*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > >, Fm::FilePath const&)@Base" 0.12.0
|
(c++)"void std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >::_M_realloc_insert<Fm::FilePath const&>(__gnu_cxx::__normal_iterator<Fm::FilePath*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > >, Fm::FilePath const&)@Base" 0.12.0
|
||||||
|
(c++)"void std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >::_M_realloc_insert<Fm::FilePath&>(__gnu_cxx::__normal_iterator<Fm::FilePath*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > >, Fm::FilePath&)@Base" 0.13.0~
|
||||||
(c++)"void std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >::_M_realloc_insert<Fm::FilePath>(__gnu_cxx::__normal_iterator<Fm::FilePath*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > >, Fm::FilePath&&)@Base" 0.12.0
|
(c++)"void std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >::_M_realloc_insert<Fm::FilePath>(__gnu_cxx::__normal_iterator<Fm::FilePath*, std::vector<Fm::FilePath, std::allocator<Fm::FilePath> > >, Fm::FilePath&&)@Base" 0.12.0
|
||||||
|
(c++)"void std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >::emplace_back<Fm::FilePath&>(Fm::FilePath&)@Base" 0.13.0~
|
||||||
(c++)"void std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >::emplace_back<Fm::FilePath>(Fm::FilePath&&)@Base" 0.12.0
|
(c++)"void std::vector<Fm::FilePath, std::allocator<Fm::FilePath> >::emplace_back<Fm::FilePath>(Fm::FilePath&&)@Base" 0.12.0
|
||||||
(c++)"void std::vector<Fm::Mount, std::allocator<Fm::Mount> >::_M_realloc_insert<Fm::Mount>(__gnu_cxx::__normal_iterator<Fm::Mount*, std::vector<Fm::Mount, std::allocator<Fm::Mount> > >, Fm::Mount&&)@Base" 0.12.0
|
(c++)"void std::vector<Fm::Mount, std::allocator<Fm::Mount> >::_M_realloc_insert<Fm::Mount>(__gnu_cxx::__normal_iterator<Fm::Mount*, std::vector<Fm::Mount, std::allocator<Fm::Mount> > >, Fm::Mount&&)@Base" 0.12.0
|
||||||
(c++)"void std::vector<Fm::Mount, std::allocator<Fm::Mount> >::emplace_back<Fm::Mount>(Fm::Mount&&)@Base" 0.12.0
|
(c++)"void std::vector<Fm::Mount, std::allocator<Fm::Mount> >::emplace_back<Fm::Mount>(Fm::Mount&&)@Base" 0.12.0
|
||||||
@ -1343,16 +1419,20 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"void std::vector<std::shared_ptr<Fm::BookmarkItem const>, std::allocator<std::shared_ptr<Fm::BookmarkItem const> > >::_M_realloc_insert<std::shared_ptr<Fm::BookmarkItem const> >(__gnu_cxx::__normal_iterator<std::shared_ptr<Fm::BookmarkItem const>*, std::vector<std::shared_ptr<Fm::BookmarkItem const>, std::allocator<std::shared_ptr<Fm::BookmarkItem const> > > >, std::shared_ptr<Fm::BookmarkItem const>&&)@Base" 0.12.0
|
(c++)"void std::vector<std::shared_ptr<Fm::BookmarkItem const>, std::allocator<std::shared_ptr<Fm::BookmarkItem const> > >::_M_realloc_insert<std::shared_ptr<Fm::BookmarkItem const> >(__gnu_cxx::__normal_iterator<std::shared_ptr<Fm::BookmarkItem const>*, std::vector<std::shared_ptr<Fm::BookmarkItem const>, std::allocator<std::shared_ptr<Fm::BookmarkItem const> > > >, std::shared_ptr<Fm::BookmarkItem const>&&)@Base" 0.12.0
|
||||||
(c++)"void std::vector<std::shared_ptr<Fm::FileInfo const>, std::allocator<std::shared_ptr<Fm::FileInfo const> > >::_M_realloc_insert<std::shared_ptr<Fm::FileInfo const> >(__gnu_cxx::__normal_iterator<std::shared_ptr<Fm::FileInfo const>*, std::vector<std::shared_ptr<Fm::FileInfo const>, std::allocator<std::shared_ptr<Fm::FileInfo const> > > >, std::shared_ptr<Fm::FileInfo const>&&)@Base" 0.12.0
|
(c++)"void std::vector<std::shared_ptr<Fm::FileInfo const>, std::allocator<std::shared_ptr<Fm::FileInfo const> > >::_M_realloc_insert<std::shared_ptr<Fm::FileInfo const> >(__gnu_cxx::__normal_iterator<std::shared_ptr<Fm::FileInfo const>*, std::vector<std::shared_ptr<Fm::FileInfo const>, std::allocator<std::shared_ptr<Fm::FileInfo const> > > >, std::shared_ptr<Fm::FileInfo const>&&)@Base" 0.12.0
|
||||||
(c++)"void std::vector<std::shared_ptr<Fm::FileInfo const>, std::allocator<std::shared_ptr<Fm::FileInfo const> > >::_M_realloc_insert<std::shared_ptr<Fm::FileInfo const> const&>(__gnu_cxx::__normal_iterator<std::shared_ptr<Fm::FileInfo const>*, std::vector<std::shared_ptr<Fm::FileInfo const>, std::allocator<std::shared_ptr<Fm::FileInfo const> > > >, std::shared_ptr<Fm::FileInfo const> const&)@Base" 0.12.0
|
(c++)"void std::vector<std::shared_ptr<Fm::FileInfo const>, std::allocator<std::shared_ptr<Fm::FileInfo const> > >::_M_realloc_insert<std::shared_ptr<Fm::FileInfo const> const&>(__gnu_cxx::__normal_iterator<std::shared_ptr<Fm::FileInfo const>*, std::vector<std::shared_ptr<Fm::FileInfo const>, std::allocator<std::shared_ptr<Fm::FileInfo const> > > >, std::shared_ptr<Fm::FileInfo const> const&)@Base" 0.12.0
|
||||||
|
(c++)"void std::vector<std::shared_ptr<Fm::FileInfo const>, std::allocator<std::shared_ptr<Fm::FileInfo const> > >::emplace_back<std::shared_ptr<Fm::FileInfo const> const&>(std::shared_ptr<Fm::FileInfo const> const&)@Base" 0.13.0~
|
||||||
|
(c++)"void std::vector<std::shared_ptr<Fm::Folder>, std::allocator<std::shared_ptr<Fm::Folder> > >::_M_realloc_insert<std::shared_ptr<Fm::Folder> >(__gnu_cxx::__normal_iterator<std::shared_ptr<Fm::Folder>*, std::vector<std::shared_ptr<Fm::Folder>, std::allocator<std::shared_ptr<Fm::Folder> > > >, std::shared_ptr<Fm::Folder>&&)@Base" 0.13.0~
|
||||||
|
(c++)"void std::vector<std::shared_ptr<Fm::TemplateItem>, std::allocator<std::shared_ptr<Fm::TemplateItem> > >::_M_realloc_insert<std::shared_ptr<Fm::TemplateItem> >(__gnu_cxx::__normal_iterator<std::shared_ptr<Fm::TemplateItem>*, std::vector<std::shared_ptr<Fm::TemplateItem>, std::allocator<std::shared_ptr<Fm::TemplateItem> > > >, std::shared_ptr<Fm::TemplateItem>&&)@Base" 0.13.0~
|
||||||
(c++)"void std::vector<std::shared_ptr<Fm::Thumbnailer>, std::allocator<std::shared_ptr<Fm::Thumbnailer> > >::_M_realloc_insert<std::shared_ptr<Fm::Thumbnailer> >(__gnu_cxx::__normal_iterator<std::shared_ptr<Fm::Thumbnailer>*, std::vector<std::shared_ptr<Fm::Thumbnailer>, std::allocator<std::shared_ptr<Fm::Thumbnailer> > > >, std::shared_ptr<Fm::Thumbnailer>&&)@Base" 0.12.0
|
(c++)"void std::vector<std::shared_ptr<Fm::Thumbnailer>, std::allocator<std::shared_ptr<Fm::Thumbnailer> > >::_M_realloc_insert<std::shared_ptr<Fm::Thumbnailer> >(__gnu_cxx::__normal_iterator<std::shared_ptr<Fm::Thumbnailer>*, std::vector<std::shared_ptr<Fm::Thumbnailer>, std::allocator<std::shared_ptr<Fm::Thumbnailer> > > >, std::shared_ptr<Fm::Thumbnailer>&&)@Base" 0.12.0
|
||||||
|
(c++)"void std::vector<std::unique_ptr<Fm::Archiver, std::default_delete<Fm::Archiver> >, std::allocator<std::unique_ptr<Fm::Archiver, std::default_delete<Fm::Archiver> > > >::_M_realloc_insert<std::unique_ptr<Fm::Archiver, std::default_delete<Fm::Archiver> > >(__gnu_cxx::__normal_iterator<std::unique_ptr<Fm::Archiver, std::default_delete<Fm::Archiver> >*, std::vector<std::unique_ptr<Fm::Archiver, std::default_delete<Fm::Archiver> >, std::allocator<std::unique_ptr<Fm::Archiver, std::default_delete<Fm::Archiver> > > > >, std::unique_ptr<Fm::Archiver, std::default_delete<Fm::Archiver> >&&)@Base" 0.13.0~
|
||||||
(c++)"vtable for Fm::AppChooserComboBox@Base" 0.10.0
|
(c++)"vtable for Fm::AppChooserComboBox@Base" 0.10.0
|
||||||
(c++)"vtable for Fm::AppChooserDialog@Base" 0.10.0
|
(c++)"vtable for Fm::AppChooserDialog@Base" 0.10.0
|
||||||
(c++)"vtable for Fm::AppMenuView@Base" 0.10.0
|
(c++)"vtable for Fm::AppMenuView@Base" 0.10.0
|
||||||
|
(c++)"vtable for Fm::BasicFileLauncher@Base" 0.13.0~
|
||||||
(c++)"vtable for Fm::BookmarkAction@Base" 0.10.0
|
(c++)"vtable for Fm::BookmarkAction@Base" 0.10.0
|
||||||
(c++)"vtable for Fm::Bookmarks@Base" 0.12.0
|
(c++)"vtable for Fm::Bookmarks@Base" 0.12.0
|
||||||
(c++)"vtable for Fm::BrowseHistory@Base" 0.10.0
|
(c++)"vtable for Fm::BrowseHistory@Base" 0.10.0
|
||||||
(c++)"vtable for Fm::CachedFolderModel@Base" 0.10.0
|
(c++)"vtable for Fm::CachedFolderModel@Base" 0.10.0
|
||||||
(c++)"vtable for Fm::ColorButton@Base" 0.10.0
|
(c++)"vtable for Fm::ColorButton@Base" 0.10.0
|
||||||
(c++)"vtable for Fm::CopyJob@Base" 0.12.0
|
|
||||||
(c++)"vtable for Fm::CreateNewMenu@Base" 0.10.0
|
(c++)"vtable for Fm::CreateNewMenu@Base" 0.10.0
|
||||||
(c++)"vtable for Fm::DeleteJob@Base" 0.12.0
|
(c++)"vtable for Fm::DeleteJob@Base" 0.12.0
|
||||||
(c++)"vtable for Fm::DirListJob@Base" 0.12.0
|
(c++)"vtable for Fm::DirListJob@Base" 0.12.0
|
||||||
@ -1374,6 +1454,7 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"vtable for Fm::FilePropsDialog@Base" 0.10.0
|
(c++)"vtable for Fm::FilePropsDialog@Base" 0.10.0
|
||||||
(c++)"vtable for Fm::FileSearchDialog@Base" 0.10.0
|
(c++)"vtable for Fm::FileSearchDialog@Base" 0.10.0
|
||||||
(c++)"vtable for Fm::FileSystemInfoJob@Base" 0.12.0
|
(c++)"vtable for Fm::FileSystemInfoJob@Base" 0.12.0
|
||||||
|
(c++)"vtable for Fm::FileTransferJob@Base" 0.13.0~
|
||||||
(c++)"vtable for Fm::Folder@Base" 0.12.0
|
(c++)"vtable for Fm::Folder@Base" 0.12.0
|
||||||
(c++)"vtable for Fm::FolderItemDelegate@Base" 0.10.0
|
(c++)"vtable for Fm::FolderItemDelegate@Base" 0.10.0
|
||||||
(c++)"vtable for Fm::FolderMenu@Base" 0.10.0
|
(c++)"vtable for Fm::FolderMenu@Base" 0.10.0
|
||||||
@ -1381,7 +1462,6 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"vtable for Fm::FolderModelItem@Base" 0.10.0
|
(c++)"vtable for Fm::FolderModelItem@Base" 0.10.0
|
||||||
(c++)"vtable for Fm::FolderView@Base" 0.10.0
|
(c++)"vtable for Fm::FolderView@Base" 0.10.0
|
||||||
(c++)"vtable for Fm::FontButton@Base" 0.10.0
|
(c++)"vtable for Fm::FontButton@Base" 0.10.0
|
||||||
(c++)"vtable for Fm::IconTheme@Base" 0.10.0
|
|
||||||
(c++)"vtable for Fm::Job@Base" 0.12.0
|
(c++)"vtable for Fm::Job@Base" 0.12.0
|
||||||
(c++)"vtable for Fm::MountOperation@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::PathBar@Base" 0.11.2
|
||||||
@ -1392,10 +1472,12 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"vtable for Fm::PlacesModelItem@Base" 0.10.0
|
(c++)"vtable for Fm::PlacesModelItem@Base" 0.10.0
|
||||||
(c++)"vtable for Fm::PlacesModelMountItem@Base" 0.10.0
|
(c++)"vtable for Fm::PlacesModelMountItem@Base" 0.10.0
|
||||||
(c++)"vtable for Fm::PlacesModelVolumeItem@Base" 0.10.0
|
(c++)"vtable for Fm::PlacesModelVolumeItem@Base" 0.10.0
|
||||||
|
(c++)"vtable for Fm::PlacesProxyModel@Base" 0.13.0~
|
||||||
(c++)"vtable for Fm::PlacesView@Base" 0.10.0
|
(c++)"vtable for Fm::PlacesView@Base" 0.10.0
|
||||||
(c++)"vtable for Fm::ProxyFolderModel@Base" 0.10.0
|
(c++)"vtable for Fm::ProxyFolderModel@Base" 0.10.0
|
||||||
(c++)"vtable for Fm::RenameDialog@Base" 0.10.0
|
(c++)"vtable for Fm::RenameDialog@Base" 0.10.0
|
||||||
(c++)"vtable for Fm::SidePane@Base" 0.10.0
|
(c++)"vtable for Fm::SidePane@Base" 0.10.0
|
||||||
|
(c++)"vtable for Fm::Templates@Base" 0.13.0~
|
||||||
(c++)"vtable for Fm::ThumbnailJob@Base" 0.12.0
|
(c++)"vtable for Fm::ThumbnailJob@Base" 0.12.0
|
||||||
(c++)"vtable for Fm::TotalSizeJob@Base" 0.12.0
|
(c++)"vtable for Fm::TotalSizeJob@Base" 0.12.0
|
||||||
(c++)"vtable for Fm::TrashJob@Base" 0.12.0
|
(c++)"vtable for Fm::TrashJob@Base" 0.12.0
|
||||||
@ -1403,7 +1485,7 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++)"vtable for Fm::UserInfoCache@Base" 0.12.0
|
(c++)"vtable for Fm::UserInfoCache@Base" 0.12.0
|
||||||
(c++)"vtable for Fm::VolumeManager::GetGVolumeMonitorJob@Base" 0.12.0
|
(c++)"vtable for Fm::VolumeManager::GetGVolumeMonitorJob@Base" 0.12.0
|
||||||
(c++)"vtable for Fm::VolumeManager@Base" 0.12.0
|
(c++)"vtable for Fm::VolumeManager@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::BookmarkItem const, std::allocator<Fm::BookmarkItem>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
(optional|c++|arch= !armel !riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::BookmarkItem const, std::allocator<Fm::BookmarkItem>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::BookmarkItem const, std::allocator<Fm::BookmarkItem>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
(c++|arch= armel riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::BookmarkItem const, std::allocator<Fm::BookmarkItem>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::BookmarkItem, std::allocator<Fm::BookmarkItem>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
(c++|arch= !armel !riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::BookmarkItem, std::allocator<Fm::BookmarkItem>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::BookmarkItem, std::allocator<Fm::BookmarkItem>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
(c++|arch= armel riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::BookmarkItem, std::allocator<Fm::BookmarkItem>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
||||||
@ -1422,45 +1504,13 @@ libfm-qt.so.3 libfm-qt3 #MINVER#
|
|||||||
(c++|arch= !armel !riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::MimeType, std::allocator<Fm::MimeType>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
(c++|arch= !armel !riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::MimeType, std::allocator<Fm::MimeType>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::MimeType, std::allocator<Fm::MimeType>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
(c++|arch= armel riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::MimeType, std::allocator<Fm::MimeType>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::PlacesModel, std::allocator<Fm::PlacesModel>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
(c++|arch= !armel !riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::PlacesModel, std::allocator<Fm::PlacesModel>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::PlacesModel, std::allocator<Fm::PlacesModel>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
(c++)"vtable for std::_Sp_counted_ptr_inplace<Fm::PlacesProxyModel, std::allocator<Fm::PlacesProxyModel>, (__gnu_cxx::_Lock_policy)2>@Base" 0.13.0~
|
||||||
(c++|arch= !armel !riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::Thumbnailer, std::allocator<Fm::Thumbnailer>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
(c++)"vtable for std::_Sp_counted_ptr_inplace<Fm::TemplateItem, std::allocator<Fm::TemplateItem>, (__gnu_cxx::_Lock_policy)2>@Base" 0.13.0~
|
||||||
(c++|arch= armel riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::Thumbnailer, std::allocator<Fm::Thumbnailer>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
(c++)"vtable for std::_Sp_counted_ptr_inplace<Fm::Templates, std::allocator<Fm::Templates>, (__gnu_cxx::_Lock_policy)2>@Base" 0.13.0~
|
||||||
|
(c++)"vtable for std::_Sp_counted_ptr_inplace<Fm::Thumbnailer, std::allocator<Fm::Thumbnailer>, (__gnu_cxx::_Lock_policy)2>@Base" 0.13.0~
|
||||||
(c++|arch= !armel !riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
(c++|arch= !armel !riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
(c++|arch= armel riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::UserInfo, std::allocator<Fm::UserInfo>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::VolumeManager, std::allocator<Fm::VolumeManager>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
(c++|arch= !armel !riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::VolumeManager, std::allocator<Fm::VolumeManager>, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::VolumeManager, std::allocator<Fm::VolumeManager>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
(c++|arch= armel riscv64 )"vtable for std::_Sp_counted_ptr_inplace<Fm::VolumeManager, std::allocator<Fm::VolumeManager>, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
||||||
(c++|arch= !armel !riscv64 )"vtable for std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
(c++|arch= !armel !riscv64 )"vtable for std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)2>@Base" 0.12.0
|
||||||
(c++|arch= armel riscv64 )"vtable for std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
(c++|arch= armel riscv64 )"vtable for std::_Sp_counted_ptr_inplace<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >, std::allocator<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >, (__gnu_cxx::_Lock_policy)1>@Base" 0.12.0
|
||||||
fm_search_add_dir@Base 0.10.0
|
|
||||||
fm_search_add_mime_type@Base 0.10.0
|
|
||||||
fm_search_dup_path@Base 0.10.0
|
|
||||||
fm_search_free@Base 0.10.0
|
|
||||||
fm_search_get_content_ci@Base 0.10.0
|
|
||||||
fm_search_get_content_pattern@Base 0.10.0
|
|
||||||
fm_search_get_content_regex@Base 0.10.0
|
|
||||||
fm_search_get_dirs@Base 0.10.0
|
|
||||||
fm_search_get_max_mtime@Base 0.10.0
|
|
||||||
fm_search_get_max_size@Base 0.10.0
|
|
||||||
fm_search_get_mime_types@Base 0.10.0
|
|
||||||
fm_search_get_min_mtime@Base 0.10.0
|
|
||||||
fm_search_get_min_size@Base 0.10.0
|
|
||||||
fm_search_get_name_ci@Base 0.10.0
|
|
||||||
fm_search_get_name_patterns@Base 0.10.0
|
|
||||||
fm_search_get_name_regex@Base 0.10.0
|
|
||||||
fm_search_get_recursive@Base 0.10.0
|
|
||||||
fm_search_get_show_hidden@Base 0.10.0
|
|
||||||
fm_search_new@Base 0.10.0
|
|
||||||
fm_search_remove_dir@Base 0.10.0
|
|
||||||
fm_search_remove_mime_type@Base 0.10.0
|
|
||||||
fm_search_set_content_ci@Base 0.10.0
|
|
||||||
fm_search_set_content_pattern@Base 0.10.0
|
|
||||||
fm_search_set_content_regex@Base 0.10.0
|
|
||||||
fm_search_set_max_mtime@Base 0.10.0
|
|
||||||
fm_search_set_max_size@Base 0.10.0
|
|
||||||
fm_search_set_min_mtime@Base 0.10.0
|
|
||||||
fm_search_set_min_size@Base 0.10.0
|
|
||||||
fm_search_set_name_ci@Base 0.10.0
|
|
||||||
fm_search_set_name_patterns@Base 0.10.0
|
|
||||||
fm_search_set_name_regex@Base 0.10.0
|
|
||||||
fm_search_set_recursive@Base 0.10.0
|
|
||||||
fm_search_set_show_hidden@Base 0.10.0
|
|
@ -9,7 +9,7 @@ set(libfm_core_SRCS
|
|||||||
core/filemonitor.cpp
|
core/filemonitor.cpp
|
||||||
# i/o jobs
|
# i/o jobs
|
||||||
core/job.cpp
|
core/job.cpp
|
||||||
core/copyjob.cpp
|
core/filetransferjob.cpp
|
||||||
core/deletejob.cpp
|
core/deletejob.cpp
|
||||||
core/dirlistjob.cpp
|
core/dirlistjob.cpp
|
||||||
core/filechangeattrjob.cpp
|
core/filechangeattrjob.cpp
|
||||||
@ -24,10 +24,13 @@ set(libfm_core_SRCS
|
|||||||
core/thumbnailjob.cpp
|
core/thumbnailjob.cpp
|
||||||
# extra desktop services
|
# extra desktop services
|
||||||
core/bookmarks.cpp
|
core/bookmarks.cpp
|
||||||
|
core/basicfilelauncher.cpp
|
||||||
core/volumemanager.cpp
|
core/volumemanager.cpp
|
||||||
core/userinfocache.cpp
|
core/userinfocache.cpp
|
||||||
core/thumbnailer.cpp
|
core/thumbnailer.cpp
|
||||||
core/terminal.cpp
|
core/terminal.cpp
|
||||||
|
core/archiver.cpp
|
||||||
|
core/templates.cpp
|
||||||
# custom actions
|
# custom actions
|
||||||
customactions/fileaction.cpp
|
customactions/fileaction.cpp
|
||||||
customactions/fileactionprofile.cpp
|
customactions/fileactionprofile.cpp
|
||||||
@ -39,7 +42,6 @@ set(libfm_SRCS
|
|||||||
libfmqt.cpp
|
libfmqt.cpp
|
||||||
bookmarkaction.cpp
|
bookmarkaction.cpp
|
||||||
sidepane.cpp
|
sidepane.cpp
|
||||||
icontheme.cpp
|
|
||||||
filelauncher.cpp
|
filelauncher.cpp
|
||||||
foldermodel.cpp
|
foldermodel.cpp
|
||||||
foldermodelitem.cpp
|
foldermodelitem.cpp
|
||||||
@ -95,9 +97,6 @@ set(libfm_UIS
|
|||||||
filedialog.ui
|
filedialog.ui
|
||||||
)
|
)
|
||||||
|
|
||||||
qt5_wrap_ui(libfm_UIS_H ${libfm_UIS})
|
|
||||||
|
|
||||||
|
|
||||||
set(LIBFM_QT_DATA_DIR "${CMAKE_INSTALL_FULL_DATADIR}/libfm-qt")
|
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")
|
set(LIBFM_QT_INTREE_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/include")
|
||||||
|
|
||||||
@ -114,7 +113,7 @@ lxqt_translate_ts(QM_FILES
|
|||||||
|
|
||||||
add_library(${LIBFM_QT_LIBRARY_NAME} SHARED
|
add_library(${LIBFM_QT_LIBRARY_NAME} SHARED
|
||||||
${libfm_SRCS}
|
${libfm_SRCS}
|
||||||
${libfm_UIS_H}
|
${libfm_UIS}
|
||||||
${QM_FILES}
|
${QM_FILES}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -154,6 +153,7 @@ target_include_directories(${LIBFM_QT_LIBRARY_NAME}
|
|||||||
|
|
||||||
target_compile_definitions(${LIBFM_QT_LIBRARY_NAME}
|
target_compile_definitions(${LIBFM_QT_LIBRARY_NAME}
|
||||||
PRIVATE "LIBFM_QT_DATA_DIR=\"${LIBFM_QT_DATA_DIR}\""
|
PRIVATE "LIBFM_QT_DATA_DIR=\"${LIBFM_QT_DATA_DIR}\""
|
||||||
|
"QT_NO_FOREACH"
|
||||||
PUBLIC "QT_NO_KEYWORDS"
|
PUBLIC "QT_NO_KEYWORDS"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -216,7 +216,7 @@ export(TARGETS ${LIBFM_QT_LIBRARY_NAME}
|
|||||||
set(REQUIRED_QT "Qt5Widgets >= ${REQUIRED_QT_VERSION} Qt5X11Extras >= ${REQUIRED_QT_VERSION}")
|
set(REQUIRED_QT "Qt5Widgets >= ${REQUIRED_QT_VERSION} Qt5X11Extras >= ${REQUIRED_QT_VERSION}")
|
||||||
configure_file(libfm-qt.pc.in lib${LIBFM_QT_LIBRARY_NAME}.pc @ONLY)
|
configure_file(libfm-qt.pc.in lib${LIBFM_QT_LIBRARY_NAME}.pc @ONLY)
|
||||||
# FreeBSD loves to install files to different locations
|
# FreeBSD loves to install files to different locations
|
||||||
# http://www.freebsd.org/doc/handbook/dirstructure.html
|
# https://www.freebsd.org/doc/handbook/dirstructure.html
|
||||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||||
install(FILES
|
install(FILES
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/lib${LIBFM_QT_LIBRARY_NAME}.pc"
|
"${CMAKE_CURRENT_BINARY_DIR}/lib${LIBFM_QT_LIBRARY_NAME}.pc"
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "appchoosercombobox.h"
|
#include "appchoosercombobox.h"
|
||||||
#include "icontheme.h"
|
|
||||||
#include "appchooserdialog.h"
|
#include "appchooserdialog.h"
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
#include "core/iconinfo.h"
|
#include "core/iconinfo.h"
|
||||||
@ -33,7 +32,7 @@ AppChooserComboBox::AppChooserComboBox(QWidget* parent):
|
|||||||
|
|
||||||
// the new Qt5 signal/slot syntax cannot handle overloaded methods by default
|
// the new Qt5 signal/slot syntax cannot handle overloaded methods by default
|
||||||
// hence a type-casting is needed here. really ugly!
|
// hence a type-casting is needed here. really ugly!
|
||||||
// reference: http://qt-project.org/forums/viewthread/21513
|
// reference: https://forum.qt.io/topic/20998/qt5-new-signals-slots-syntax-does-not-work-solved
|
||||||
connect((QComboBox*)this, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &AppChooserComboBox::onCurrentIndexChanged);
|
connect((QComboBox*)this, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &AppChooserComboBox::onCurrentIndexChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,8 +71,10 @@ void AppChooserComboBox::setMimeType(std::shared_ptr<const Fm::MimeType> mimeTyp
|
|||||||
|
|
||||||
// returns the currently selected app.
|
// returns the currently selected app.
|
||||||
Fm::GAppInfoPtr AppChooserComboBox::selectedApp() const {
|
Fm::GAppInfoPtr AppChooserComboBox::selectedApp() const {
|
||||||
|
// the elements of appInfos_ and the combo indexes before "Customize"
|
||||||
|
// always have a one-to-one correspondence
|
||||||
int idx = currentIndex();
|
int idx = currentIndex();
|
||||||
return idx >= 0 ? appInfos_[idx] : Fm::GAppInfoPtr{};
|
return idx >= 0 && !appInfos_.empty() ? appInfos_[idx] : Fm::GAppInfoPtr{};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AppChooserComboBox::isChanged() const {
|
bool AppChooserComboBox::isChanged() const {
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "appmenuview.h"
|
#include "appmenuview.h"
|
||||||
#include <QStandardItemModel>
|
#include <QStandardItemModel>
|
||||||
#include "icontheme.h"
|
|
||||||
#include "appmenuview_p.h"
|
#include "appmenuview_p.h"
|
||||||
#include <gio/gdesktopappinfo.h>
|
#include <gio/gdesktopappinfo.h>
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
#include <QStandardItem>
|
#include <QStandardItem>
|
||||||
#include <menu-cache/menu-cache.h>
|
#include <menu-cache/menu-cache.h>
|
||||||
#include "icontheme.h"
|
|
||||||
#include "core/iconinfo.h"
|
#include "core/iconinfo.h"
|
||||||
|
|
||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
143
src/archiver.h
143
src/archiver.h
@ -1,143 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 __LIBFM_QT_FM_ARCHIVER_H__
|
|
||||||
#define __LIBFM_QT_FM_ARCHIVER_H__
|
|
||||||
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
#include <QObject>
|
|
||||||
#include <QtGlobal>
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
|
|
||||||
class LIBFM_QT_API Archiver {
|
|
||||||
public:
|
|
||||||
|
|
||||||
|
|
||||||
// default constructor
|
|
||||||
Archiver() {
|
|
||||||
dataPtr_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// move constructor
|
|
||||||
Archiver(Archiver&& other) noexcept {
|
|
||||||
dataPtr_ = reinterpret_cast<FmArchiver*>(other.takeDataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// destructor
|
|
||||||
~Archiver() {
|
|
||||||
if(dataPtr_ != nullptr) {
|
|
||||||
(dataPtr_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// create a wrapper for the data pointer without increasing the reference count
|
|
||||||
static Archiver wrapPtr(FmArchiver* dataPtr) {
|
|
||||||
Archiver obj;
|
|
||||||
obj.dataPtr_ = reinterpret_cast<FmArchiver*>(dataPtr);
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
// disown the managed data pointer
|
|
||||||
FmArchiver* takeDataPtr() {
|
|
||||||
FmArchiver* data = reinterpret_cast<FmArchiver*>(dataPtr_);
|
|
||||||
dataPtr_ = nullptr;
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the raw pointer wrapped
|
|
||||||
FmArchiver* dataPtr() {
|
|
||||||
return reinterpret_cast<FmArchiver*>(dataPtr_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// automatic type casting
|
|
||||||
operator FmArchiver*() {
|
|
||||||
return dataPtr();
|
|
||||||
}
|
|
||||||
|
|
||||||
// automatic type casting
|
|
||||||
operator void*() {
|
|
||||||
return dataPtr();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// move assignment
|
|
||||||
Archiver& operator=(Archiver&& other) noexcept {
|
|
||||||
dataPtr_ = reinterpret_cast<FmArchiver*>(other.takeDataPtr());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isNull() {
|
|
||||||
return (dataPtr_ == nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// methods
|
|
||||||
|
|
||||||
void setDefault(void) {
|
|
||||||
fm_archiver_set_default(dataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Archiver getDefault( ) {
|
|
||||||
return wrapPtr(fm_archiver_get_default());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool extractArchivesTo(GAppLaunchContext* ctx, FmPathList* files, FmPath* dest_dir) {
|
|
||||||
return fm_archiver_extract_archives_to(dataPtr(), ctx, files, dest_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool extractArchives(GAppLaunchContext* ctx, FmPathList* files) {
|
|
||||||
return fm_archiver_extract_archives(dataPtr(), ctx, files);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool createArchive(GAppLaunchContext* ctx, FmPathList* files) {
|
|
||||||
return fm_archiver_create_archive(dataPtr(), ctx, files);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool isMimeTypeSupported(const char* type) {
|
|
||||||
return fm_archiver_is_mime_type_supported(dataPtr(), type);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// the wrapped object cannot be copied.
|
|
||||||
private:
|
|
||||||
Archiver(const Archiver& other) = delete;
|
|
||||||
Archiver& operator=(const Archiver& other) = delete;
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
FmArchiver* dataPtr_; // data pointer for the underlying C struct
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // __LIBFM_QT_FM_ARCHIVER_H__
|
|
@ -59,7 +59,7 @@ void CachedFolderModel::unref() {
|
|||||||
--refCount;
|
--refCount;
|
||||||
if(refCount <= 0) {
|
if(refCount <= 0) {
|
||||||
folder()->setProperty(cacheKey, QVariant());
|
folder()->setProperty(cacheKey, QVariant());
|
||||||
deleteLater();
|
delete(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
174
src/core/archiver.cpp
Normal file
174
src/core/archiver.cpp
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
#include "libfmqtglobals.h"
|
||||||
|
#include "archiver.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include <gio/gdesktopappinfo.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Fm {
|
||||||
|
|
||||||
|
Archiver* Archiver::defaultArchiver_ = nullptr; // static
|
||||||
|
std::vector<std::unique_ptr<Archiver>> Archiver::allArchivers_; // static
|
||||||
|
|
||||||
|
Archiver::Archiver() {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Archiver::isMimeTypeSupported(const char* type) {
|
||||||
|
char** p;
|
||||||
|
if(G_UNLIKELY(!type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for(p = mimeTypes_.get(); *p; ++p) {
|
||||||
|
if(strcmp(*p, type) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Archiver::launchProgram(GAppLaunchContext* ctx, const char* cmd, const FilePathList& files, const FilePath& dir) {
|
||||||
|
char* _cmd = NULL;
|
||||||
|
const char* dir_place_holder;
|
||||||
|
GKeyFile* dummy;
|
||||||
|
|
||||||
|
if(dir.isValid() && (dir_place_holder = strstr(cmd, "%d"))) {
|
||||||
|
CStrPtr dir_str;
|
||||||
|
int len;
|
||||||
|
if(strstr(cmd, "%U") || strstr(cmd, "%u")) { /* supports URI */
|
||||||
|
dir_str = dir.uri();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dir_str = dir.localPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: remove libfm dependency here
|
||||||
|
/* replace all % with %% so encoded URI can be handled correctly when parsing Exec key. */
|
||||||
|
std::string percentEscapedDir;
|
||||||
|
for(auto p = dir_str.get(); *p; ++p) {
|
||||||
|
percentEscapedDir += *p;
|
||||||
|
if(*p == '%') {
|
||||||
|
percentEscapedDir += '%';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* quote the path or URI */
|
||||||
|
dir_str = CStrPtr{g_shell_quote(percentEscapedDir.c_str())};
|
||||||
|
|
||||||
|
len = strlen(cmd) - 2 + strlen(dir_str.get()) + 1;
|
||||||
|
_cmd = (char*)g_malloc(len);
|
||||||
|
len = (dir_place_holder - cmd);
|
||||||
|
strncpy(_cmd, cmd, len);
|
||||||
|
strcpy(_cmd + len, dir_str.get());
|
||||||
|
strcat(_cmd, dir_place_holder + 2);
|
||||||
|
cmd = _cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create a fake key file to cheat GDesktopAppInfo */
|
||||||
|
dummy = g_key_file_new();
|
||||||
|
g_key_file_set_string(dummy, G_KEY_FILE_DESKTOP_GROUP, "Type", "Application");
|
||||||
|
g_key_file_set_string(dummy, G_KEY_FILE_DESKTOP_GROUP, "Name", program_.get());
|
||||||
|
|
||||||
|
/* replace all % with %% so encoded URI can be handled correctly when parsing Exec key. */
|
||||||
|
g_key_file_set_string(dummy, G_KEY_FILE_DESKTOP_GROUP, "Exec", cmd);
|
||||||
|
GAppInfoPtr app{reinterpret_cast<GAppInfo*>(g_desktop_app_info_new_from_keyfile(dummy)), false};
|
||||||
|
|
||||||
|
g_key_file_free(dummy);
|
||||||
|
g_debug("cmd = %s", cmd);
|
||||||
|
if(app) {
|
||||||
|
GList* uris = NULL;
|
||||||
|
for(auto& file: files) {
|
||||||
|
uris = g_list_prepend(uris, g_strdup(file.uri().get()));
|
||||||
|
}
|
||||||
|
g_app_info_launch_uris(app.get(), uris, ctx, NULL);
|
||||||
|
g_list_foreach(uris, (GFunc)g_free, NULL);
|
||||||
|
g_list_free(uris);
|
||||||
|
}
|
||||||
|
g_free(_cmd);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Archiver::createArchive(GAppLaunchContext* ctx, const FilePathList& files) {
|
||||||
|
if(createCmd_ && !files.empty()) {
|
||||||
|
launchProgram(ctx, createCmd_.get(), files, FilePath{});
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Archiver::extractArchives(GAppLaunchContext* ctx, const FilePathList& files) {
|
||||||
|
if(extractCmd_ && !files.empty()) {
|
||||||
|
launchProgram(ctx, extractCmd_.get(), files, FilePath{});
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Archiver::extractArchivesTo(GAppLaunchContext* ctx, const FilePathList& files, const FilePath& dest_dir) {
|
||||||
|
if(extractToCmd_ && !files.empty()) {
|
||||||
|
launchProgram(ctx, extractToCmd_.get(), files, dest_dir);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
Archiver* Archiver::defaultArchiver() {
|
||||||
|
allArchivers(); // to have a preliminary default archiver
|
||||||
|
return defaultArchiver_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Archiver::setDefaultArchiverByName(const char *name) {
|
||||||
|
if(name) {
|
||||||
|
auto& all = allArchivers();
|
||||||
|
for(auto& archiver: all) {
|
||||||
|
if(archiver->program_ && strcmp(archiver->program_.get(), name) == 0) {
|
||||||
|
defaultArchiver_ = archiver.get();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void Archiver::setDefaultArchiver(Archiver* archiver) {
|
||||||
|
if(archiver) {
|
||||||
|
defaultArchiver_ = archiver;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
const std::vector<std::unique_ptr<Archiver> >& Archiver::allArchivers() {
|
||||||
|
// load all archivers on demand
|
||||||
|
if(allArchivers_.empty()) {
|
||||||
|
GKeyFile* kf = g_key_file_new();
|
||||||
|
if(g_key_file_load_from_file(kf, LIBFM_QT_DATA_DIR "/archivers.list", G_KEY_FILE_NONE, NULL)) {
|
||||||
|
gsize n_archivers;
|
||||||
|
CStrArrayPtr programs{g_key_file_get_groups(kf, &n_archivers)};
|
||||||
|
if(programs) {
|
||||||
|
gsize i;
|
||||||
|
for(i = 0; i < n_archivers; ++i) {
|
||||||
|
auto program = programs[i];
|
||||||
|
std::unique_ptr<Archiver> archiver{new Archiver{}};
|
||||||
|
archiver->createCmd_ = CStrPtr{g_key_file_get_string(kf, program, "create", NULL)};
|
||||||
|
archiver->extractCmd_ = CStrPtr{g_key_file_get_string(kf, program, "extract", NULL)};
|
||||||
|
archiver->extractToCmd_ = CStrPtr{g_key_file_get_string(kf, program, "extract_to", NULL)};
|
||||||
|
archiver->mimeTypes_ = CStrArrayPtr{g_key_file_get_string_list(kf, program, "mime_types", NULL, NULL)};
|
||||||
|
archiver->program_ = CStrPtr{g_strdup(program)};
|
||||||
|
|
||||||
|
// if default archiver is not set, find the first program existing in the current system.
|
||||||
|
if(!defaultArchiver_) {
|
||||||
|
CStrPtr fullPath{g_find_program_in_path(program)};
|
||||||
|
if(fullPath) {
|
||||||
|
defaultArchiver_ = archiver.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allArchivers_.emplace_back(std::move(archiver));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_key_file_free(kf);
|
||||||
|
}
|
||||||
|
return allArchivers_;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Fm
|
69
src/core/archiver.h
Normal file
69
src/core/archiver.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#ifndef ARCHIVER_H
|
||||||
|
#define ARCHIVER_H
|
||||||
|
|
||||||
|
#include "../libfmqtglobals.h"
|
||||||
|
#include "filepath.h"
|
||||||
|
#include "gioptrs.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace Fm {
|
||||||
|
|
||||||
|
class LIBFM_QT_API Archiver {
|
||||||
|
public:
|
||||||
|
Archiver();
|
||||||
|
|
||||||
|
bool isMimeTypeSupported(const char* type);
|
||||||
|
|
||||||
|
bool canCreateArchive() const {
|
||||||
|
return createCmd_ != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool createArchive(GAppLaunchContext* ctx, const FilePathList& files);
|
||||||
|
|
||||||
|
bool canExtractArchives() const {
|
||||||
|
return extractCmd_ != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool extractArchives(GAppLaunchContext* ctx, const FilePathList& files);
|
||||||
|
|
||||||
|
bool canExtractArchivesTo() const {
|
||||||
|
return extractToCmd_ != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool extractArchivesTo(GAppLaunchContext* ctx, const FilePathList& files, const FilePath& dest_dir);
|
||||||
|
|
||||||
|
/* get default GUI archivers used by libfm */
|
||||||
|
static Archiver* defaultArchiver();
|
||||||
|
|
||||||
|
/* set default GUI archivers used by libfm */
|
||||||
|
static void setDefaultArchiverByName(const char* name);
|
||||||
|
|
||||||
|
/* set default GUI archivers used by libfm */
|
||||||
|
static void setDefaultArchiver(Archiver* archiver);
|
||||||
|
|
||||||
|
/* get a list of FmArchiver* of all GUI archivers known to libfm */
|
||||||
|
static const std::vector<std::unique_ptr<Archiver>>& allArchivers();
|
||||||
|
|
||||||
|
const char* program() const {
|
||||||
|
return program_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool launchProgram(GAppLaunchContext* ctx, const char* cmd, const FilePathList& files, const FilePath &dir);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CStrPtr program_;
|
||||||
|
CStrPtr createCmd_;
|
||||||
|
CStrPtr extractCmd_;
|
||||||
|
CStrPtr extractToCmd_;
|
||||||
|
CStrArrayPtr mimeTypes_;
|
||||||
|
|
||||||
|
static Archiver* defaultArchiver_;
|
||||||
|
static std::vector<std::unique_ptr<Archiver>> allArchivers_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Fm
|
||||||
|
|
||||||
|
#endif // ARCHIVER_H
|
345
src/core/basicfilelauncher.cpp
Normal file
345
src/core/basicfilelauncher.cpp
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
#include "basicfilelauncher.h"
|
||||||
|
#include "fileinfojob.h"
|
||||||
|
#include "mountoperation.h"
|
||||||
|
|
||||||
|
#include <gio/gdesktopappinfo.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QEventLoop>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
namespace Fm {
|
||||||
|
|
||||||
|
BasicFileLauncher::BasicFileLauncher():
|
||||||
|
quickExec_{false} {
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicFileLauncher::~BasicFileLauncher() {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicFileLauncher::launchFiles(const FileInfoList& fileInfos, GAppLaunchContext* ctx) {
|
||||||
|
std::unordered_map<std::string, FileInfoList> mimeTypeToFiles;
|
||||||
|
FileInfoList folderInfos;
|
||||||
|
FilePathList pathsToLaunch;
|
||||||
|
// classify files according to different mimetypes
|
||||||
|
for(auto& fileInfo : fileInfos) {
|
||||||
|
// qDebug("path: %s, target: %s", fileInfo->path().toString().get(), fileInfo->target().c_str());
|
||||||
|
if(fileInfo->isDir()) {
|
||||||
|
folderInfos.emplace_back(fileInfo);
|
||||||
|
}
|
||||||
|
else if(fileInfo->isMountable()) {
|
||||||
|
if(fileInfo->target().empty()) {
|
||||||
|
// the mountable is not yet mounted so we have no target URI.
|
||||||
|
GErrorPtr err{G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED,
|
||||||
|
QObject::tr("The path is not mounted.")};
|
||||||
|
if(!showError(ctx, err, fileInfo->path(), fileInfo)) {
|
||||||
|
// the user fail to handle the error, skip this file.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we do not have the target path in the FileInfo object.
|
||||||
|
// try to launch our path again to query the new file info later so we can get the mounted target URI.
|
||||||
|
pathsToLaunch.emplace_back(fileInfo->path());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// we have the target path, launch it later
|
||||||
|
pathsToLaunch.emplace_back(FilePath::fromPathStr(fileInfo->target().c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(fileInfo->isDesktopEntry()) {
|
||||||
|
// launch the desktop entry
|
||||||
|
launchDesktopEntry(fileInfo, FilePathList{}, ctx);
|
||||||
|
}
|
||||||
|
else if(fileInfo->isExecutableType()) {
|
||||||
|
// directly execute the file
|
||||||
|
launchExecutable(fileInfo, ctx);
|
||||||
|
}
|
||||||
|
else if(fileInfo->isShortcut()) {
|
||||||
|
// for shortcuts, launch their targets instead
|
||||||
|
auto path = handleShortcut(fileInfo, ctx);
|
||||||
|
if(path.isValid()) {
|
||||||
|
pathsToLaunch.emplace_back(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto& mimeType = fileInfo->mimeType();
|
||||||
|
mimeTypeToFiles[mimeType->name()].emplace_back(fileInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// open folders
|
||||||
|
if(!folderInfos.empty()) {
|
||||||
|
GErrorPtr err;
|
||||||
|
openFolder(ctx, folderInfos, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// open files of different mime-types with their default app
|
||||||
|
for(auto& typeFiles : mimeTypeToFiles) {
|
||||||
|
auto& mimeType = typeFiles.first;
|
||||||
|
auto& files = typeFiles.second;
|
||||||
|
GErrorPtr err;
|
||||||
|
GAppInfoPtr app{g_app_info_get_default_for_type(mimeType.c_str(), false), false};
|
||||||
|
if(!app) {
|
||||||
|
app = chooseApp(files, mimeType.c_str(), err);
|
||||||
|
}
|
||||||
|
if(app) {
|
||||||
|
launchWithApp(app.get(), files.paths(), ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!pathsToLaunch.empty()) {
|
||||||
|
launchPaths(pathsToLaunch, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicFileLauncher::launchPaths(FilePathList paths, GAppLaunchContext* ctx) {
|
||||||
|
// FIXME: blocking with an event loop is not a good design :-(
|
||||||
|
QEventLoop eventLoop;
|
||||||
|
|
||||||
|
auto job = new FileInfoJob{paths};
|
||||||
|
job->setAutoDelete(false); // do not automatically delete the job since we want its results later.
|
||||||
|
|
||||||
|
GObjectPtr<GAppLaunchContext> ctxPtr{ctx};
|
||||||
|
QObject::connect(job, &FileInfoJob::finished,
|
||||||
|
[&eventLoop]() {
|
||||||
|
// exit the event loop when the job is done
|
||||||
|
eventLoop.exit();
|
||||||
|
});
|
||||||
|
// run the job in another thread to not block the UI
|
||||||
|
job->runAsync();
|
||||||
|
|
||||||
|
// blocking until the job is done with a event loop
|
||||||
|
eventLoop.exec();
|
||||||
|
|
||||||
|
// launch the file info
|
||||||
|
launchFiles(job->files(), ctx);
|
||||||
|
|
||||||
|
delete job;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GAppInfoPtr BasicFileLauncher::chooseApp(const FileInfoList& /* fileInfos */, const char* /*mimeType*/, GErrorPtr& /* err */) {
|
||||||
|
return GAppInfoPtr{};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicFileLauncher::openFolder(GAppLaunchContext* ctx, const FileInfoList& folderInfos, GErrorPtr& err) {
|
||||||
|
auto app = chooseApp(folderInfos, "inode/directory", err);
|
||||||
|
if(app) {
|
||||||
|
launchWithApp(app.get(), folderInfos.paths(), ctx);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
showError(ctx, err);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicFileLauncher::ExecAction BasicFileLauncher::askExecFile(const FileInfoPtr & /* file */) {
|
||||||
|
return ExecAction::DIRECT_EXEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicFileLauncher::showError(GAppLaunchContext* /* ctx */, GErrorPtr& /* err */, const FilePath& /* path */, const FileInfoPtr& /* info */) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BasicFileLauncher::ask(const char* /* msg */, char* const* /* btn_labels */, int default_btn) {
|
||||||
|
return default_btn;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicFileLauncher::launchWithApp(GAppInfo* app, const FilePathList& paths, GAppLaunchContext* ctx) {
|
||||||
|
GList* uris = nullptr;
|
||||||
|
for(auto& path : paths) {
|
||||||
|
auto uri = path.uri();
|
||||||
|
uris = g_list_prepend(uris, uri.release());
|
||||||
|
}
|
||||||
|
GErrorPtr err;
|
||||||
|
bool ret = bool(g_app_info_launch_uris(app, uris, ctx, &err));
|
||||||
|
g_list_foreach(uris, reinterpret_cast<GFunc>(g_free), nullptr);
|
||||||
|
g_list_free(uris);
|
||||||
|
if(!ret) {
|
||||||
|
// FIXME: show error for all files
|
||||||
|
showError(ctx, err, paths[0]);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool BasicFileLauncher::launchDesktopEntry(const FileInfoPtr &fileInfo, const FilePathList &paths, GAppLaunchContext* ctx) {
|
||||||
|
/* treat desktop entries as executables */
|
||||||
|
auto target = fileInfo->target();
|
||||||
|
CStrPtr filename;
|
||||||
|
const char* desktopEntryName = nullptr;
|
||||||
|
FilePathList shortcutTargetPaths;
|
||||||
|
if(fileInfo->isExecutableType()) {
|
||||||
|
auto act = quickExec_ ? ExecAction::DIRECT_EXEC : askExecFile(fileInfo);
|
||||||
|
switch(act) {
|
||||||
|
case ExecAction::EXEC_IN_TERMINAL:
|
||||||
|
case ExecAction::DIRECT_EXEC: {
|
||||||
|
if(fileInfo->isShortcut()) {
|
||||||
|
auto path = handleShortcut(fileInfo, ctx);
|
||||||
|
if(path.isValid()) {
|
||||||
|
shortcutTargetPaths.emplace_back(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(target.empty()) {
|
||||||
|
filename = fileInfo->path().localPath();
|
||||||
|
}
|
||||||
|
desktopEntryName = !target.empty() ? target.c_str() : filename.get();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ExecAction::OPEN_WITH_DEFAULT_APP:
|
||||||
|
return launchWithDefaultApp(fileInfo, ctx);
|
||||||
|
case ExecAction::CANCEL:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* make exception for desktop entries under menu */
|
||||||
|
else if(fileInfo->isNative() /* an exception */ ||
|
||||||
|
fileInfo->path().hasUriScheme("menu")) {
|
||||||
|
if(target.empty()) {
|
||||||
|
filename = fileInfo->path().localPath();
|
||||||
|
}
|
||||||
|
desktopEntryName = !target.empty() ? target.c_str() : filename.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(desktopEntryName) {
|
||||||
|
return launchDesktopEntry(desktopEntryName, paths, ctx);
|
||||||
|
}
|
||||||
|
if(!shortcutTargetPaths.empty()) {
|
||||||
|
launchPaths(shortcutTargetPaths, ctx);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicFileLauncher::launchDesktopEntry(const char *desktopEntryName, const FilePathList &paths, GAppLaunchContext *ctx) {
|
||||||
|
bool ret = false;
|
||||||
|
GAppInfo* app;
|
||||||
|
|
||||||
|
/* Let GDesktopAppInfo try first. */
|
||||||
|
if(g_path_is_absolute(desktopEntryName)) {
|
||||||
|
app = G_APP_INFO(g_desktop_app_info_new_from_filename(desktopEntryName));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
app = G_APP_INFO(g_desktop_app_info_new(desktopEntryName));
|
||||||
|
}
|
||||||
|
/* we handle Type=Link in FmFileInfo so if GIO failed then
|
||||||
|
it cannot be launched in fact */
|
||||||
|
|
||||||
|
if(app) {
|
||||||
|
return launchWithApp(app, paths, ctx);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QString msg = QObject::tr("Invalid desktop entry file: '%1'").arg(desktopEntryName);
|
||||||
|
GErrorPtr err{G_IO_ERROR, G_IO_ERROR_FAILED, msg};
|
||||||
|
showError(ctx, err);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePath BasicFileLauncher::handleShortcut(const FileInfoPtr& fileInfo, GAppLaunchContext* ctx) {
|
||||||
|
auto target = fileInfo->target();
|
||||||
|
auto scheme = CStrPtr{g_uri_parse_scheme(target.c_str())};
|
||||||
|
if(scheme) {
|
||||||
|
// collect the uri schemes we support
|
||||||
|
if(strcmp(scheme.get(), "file") == 0
|
||||||
|
|| strcmp(scheme.get(), "trash") == 0
|
||||||
|
|| strcmp(scheme.get(), "network") == 0
|
||||||
|
|| strcmp(scheme.get(), "computer") == 0) {
|
||||||
|
return FilePath::fromUri(fileInfo->target().c_str());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// ask gio to launch the default handler for the uri scheme
|
||||||
|
GAppInfoPtr app{g_app_info_get_default_for_uri_scheme(scheme.get()), false};
|
||||||
|
FilePathList uris{FilePath::fromUri(fileInfo->target().c_str())};
|
||||||
|
launchWithApp(app.get(), uris, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// see it as a local path
|
||||||
|
return FilePath::fromLocalPath(fileInfo->target().c_str());
|
||||||
|
}
|
||||||
|
return FilePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicFileLauncher::launchExecutable(const FileInfoPtr &fileInfo, GAppLaunchContext* ctx) {
|
||||||
|
/* if it's an executable file, directly execute it. */
|
||||||
|
auto filename = fileInfo->path().localPath();
|
||||||
|
/* FIXME: we need to use eaccess/euidaccess here. */
|
||||||
|
if(g_file_test(filename.get(), G_FILE_TEST_IS_EXECUTABLE)) {
|
||||||
|
auto act = quickExec_ ? ExecAction::DIRECT_EXEC : askExecFile(fileInfo);
|
||||||
|
int flags = G_APP_INFO_CREATE_NONE;
|
||||||
|
switch(act) {
|
||||||
|
case ExecAction::EXEC_IN_TERMINAL:
|
||||||
|
flags |= G_APP_INFO_CREATE_NEEDS_TERMINAL;
|
||||||
|
/* Falls through. */
|
||||||
|
case ExecAction::DIRECT_EXEC: {
|
||||||
|
/* filename may contain spaces. Fix #3143296 */
|
||||||
|
CStrPtr quoted{g_shell_quote(filename.get())};
|
||||||
|
// FIXME: remove libfm dependency
|
||||||
|
GAppInfoPtr app{fm_app_info_create_from_commandline(quoted.get(), nullptr, GAppInfoCreateFlags(flags), nullptr)};
|
||||||
|
if(app) {
|
||||||
|
CStrPtr run_path{g_path_get_dirname(filename.get())};
|
||||||
|
CStrPtr cwd;
|
||||||
|
/* bug #3589641: scripts are ran from $HOME.
|
||||||
|
since GIO launcher is kinda ugly - it has
|
||||||
|
no means to set running directory so we
|
||||||
|
do workaround - change directory to it */
|
||||||
|
if(run_path && strcmp(run_path.get(), ".")) {
|
||||||
|
cwd = CStrPtr{g_get_current_dir()};
|
||||||
|
if(chdir(run_path.get()) != 0) {
|
||||||
|
cwd.reset();
|
||||||
|
// show errors
|
||||||
|
QString msg = QObject::tr("Cannot set working directory to '%1': %2").arg(run_path.get()).arg(g_strerror(errno));
|
||||||
|
GErrorPtr err{G_IO_ERROR, g_io_error_from_errno(errno), msg};
|
||||||
|
showError(ctx, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: remove libfm dependency
|
||||||
|
GErrorPtr err;
|
||||||
|
if(!fm_app_info_launch(app.get(), nullptr, ctx, &err)) {
|
||||||
|
showError(ctx, err);
|
||||||
|
}
|
||||||
|
if(cwd) { /* return back */
|
||||||
|
if(chdir(cwd.get()) != 0) {
|
||||||
|
g_warning("fm_launch_files(): chdir() failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ExecAction::OPEN_WITH_DEFAULT_APP:
|
||||||
|
return launchWithDefaultApp(fileInfo, ctx);
|
||||||
|
case ExecAction::CANCEL:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicFileLauncher::launchWithDefaultApp(const FileInfoPtr &fileInfo, GAppLaunchContext* ctx) {
|
||||||
|
FileInfoList files;
|
||||||
|
files.emplace_back(fileInfo);
|
||||||
|
GErrorPtr err;
|
||||||
|
GAppInfoPtr app{g_app_info_get_default_for_type(fileInfo->mimeType()->name(), false), false};
|
||||||
|
if(app) {
|
||||||
|
return launchWithApp(app.get(), files.paths(), ctx);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
showError(ctx, err, fileInfo->path());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Fm
|
72
src/core/basicfilelauncher.h
Normal file
72
src/core/basicfilelauncher.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#ifndef BASICFILELAUNCHER_H
|
||||||
|
#define BASICFILELAUNCHER_H
|
||||||
|
|
||||||
|
#include "../libfmqtglobals.h"
|
||||||
|
|
||||||
|
#include "fileinfo.h"
|
||||||
|
#include "filepath.h"
|
||||||
|
#include "mimetype.h"
|
||||||
|
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
namespace Fm {
|
||||||
|
|
||||||
|
class LIBFM_QT_API BasicFileLauncher {
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum class ExecAction {
|
||||||
|
NONE,
|
||||||
|
DIRECT_EXEC,
|
||||||
|
EXEC_IN_TERMINAL,
|
||||||
|
OPEN_WITH_DEFAULT_APP,
|
||||||
|
CANCEL
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit BasicFileLauncher();
|
||||||
|
virtual ~BasicFileLauncher();
|
||||||
|
|
||||||
|
bool launchFiles(const FileInfoList &fileInfos, GAppLaunchContext* ctx = nullptr);
|
||||||
|
|
||||||
|
bool launchPaths(FilePathList paths, GAppLaunchContext* ctx = nullptr);
|
||||||
|
|
||||||
|
bool launchDesktopEntry(const FileInfoPtr &fileInfo, const FilePathList& paths = FilePathList{}, GAppLaunchContext* ctx = nullptr);
|
||||||
|
|
||||||
|
bool launchDesktopEntry(const char* desktopEntryName, const FilePathList& paths = FilePathList{}, GAppLaunchContext* ctx = nullptr);
|
||||||
|
|
||||||
|
bool launchWithDefaultApp(const FileInfoPtr& fileInfo, GAppLaunchContext* ctx = nullptr);
|
||||||
|
|
||||||
|
bool launchWithApp(GAppInfo* app, const FilePathList& paths, GAppLaunchContext* ctx = nullptr);
|
||||||
|
|
||||||
|
bool launchExecutable(const FileInfoPtr &fileInfo, GAppLaunchContext* ctx = nullptr);
|
||||||
|
|
||||||
|
bool quickExec() const {
|
||||||
|
return quickExec_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setQuickExec(bool value) {
|
||||||
|
quickExec_ = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual GAppInfoPtr chooseApp(const FileInfoList& fileInfos, const char* mimeType, GErrorPtr& err);
|
||||||
|
|
||||||
|
virtual bool openFolder(GAppLaunchContext* ctx, const FileInfoList& folderInfos, GErrorPtr& err);
|
||||||
|
|
||||||
|
virtual bool showError(GAppLaunchContext* ctx, GErrorPtr& err, const FilePath& path = FilePath{}, const FileInfoPtr& info = FileInfoPtr{});
|
||||||
|
|
||||||
|
virtual ExecAction askExecFile(const FileInfoPtr& file);
|
||||||
|
|
||||||
|
virtual int ask(const char* msg, char* const* btn_labels, int default_btn);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
FilePath handleShortcut(const FileInfoPtr &fileInfo, GAppLaunchContext* ctx = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool quickExec_; // Don't ask options on launch executable file
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Fm
|
||||||
|
|
||||||
|
#endif // BASICFILELAUNCHER_H
|
@ -2,6 +2,7 @@
|
|||||||
#include "cstrptr.h"
|
#include "cstrptr.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
|
||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
|
||||||
@ -15,6 +16,60 @@ static inline CStrPtr get_new_bookmarks_file(void) {
|
|||||||
return CStrPtr{g_build_filename(g_get_user_config_dir(), "gtk-3.0", "bookmarks", nullptr)};
|
return CStrPtr{g_build_filename(g_get_user_config_dir(), "gtk-3.0", "bookmarks", nullptr)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BookmarkItem::BookmarkItem(const FilePath& path, const QString name):
|
||||||
|
path_{path},
|
||||||
|
name_{name} {
|
||||||
|
if(name_.isEmpty()) { // if the name is not specified, use basename of the path
|
||||||
|
name_ = path_.baseName().get();
|
||||||
|
}
|
||||||
|
// We cannot rely on FileInfos to set bookmark icons because there is no guarantee
|
||||||
|
// that FileInfos already exist, while their creation is costly. Therefore, we have
|
||||||
|
// to get folder icons directly, as is done at `FileInfo::setFromGFileInfo` and more.
|
||||||
|
auto local_path = path.localPath();
|
||||||
|
auto dot_dir = CStrPtr{g_build_filename(local_path.get(), ".directory", nullptr)};
|
||||||
|
if(g_file_test(dot_dir.get(), G_FILE_TEST_IS_REGULAR)) {
|
||||||
|
GKeyFile* kf = g_key_file_new();
|
||||||
|
if(g_key_file_load_from_file(kf, dot_dir.get(), G_KEY_FILE_NONE, nullptr)) {
|
||||||
|
CStrPtr icon_name{g_key_file_get_string(kf, "Desktop Entry", "Icon", nullptr)};
|
||||||
|
if(icon_name) {
|
||||||
|
icon_ = IconInfo::fromName(icon_name.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_key_file_free(kf);
|
||||||
|
}
|
||||||
|
if(!icon_ || !icon_->isValid()) {
|
||||||
|
// first check some standard folders that are shared by Qt and GLib
|
||||||
|
if(path_ == FilePath::homeDir()) {
|
||||||
|
icon_ = IconInfo::fromName("user-home");
|
||||||
|
}
|
||||||
|
else if (path_.parent() == FilePath::homeDir()) {
|
||||||
|
QString folderPath = QString::fromUtf8(path_.toString().get());
|
||||||
|
if(folderPath == QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)) {
|
||||||
|
icon_ = IconInfo::fromName("user-desktop");
|
||||||
|
}
|
||||||
|
else if(folderPath == QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)) {
|
||||||
|
icon_ = IconInfo::fromName("folder-documents");
|
||||||
|
}
|
||||||
|
else if(folderPath == QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)) {
|
||||||
|
icon_ = IconInfo::fromName("folder-download");
|
||||||
|
}
|
||||||
|
else if(folderPath == QStandardPaths::writableLocation(QStandardPaths::MusicLocation)) {
|
||||||
|
icon_ = IconInfo::fromName("folder-music");
|
||||||
|
}
|
||||||
|
else if(folderPath == QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)) {
|
||||||
|
icon_ = IconInfo::fromName("folder-pictures");
|
||||||
|
}
|
||||||
|
else if(folderPath == QStandardPaths::writableLocation(QStandardPaths::MoviesLocation)) {
|
||||||
|
icon_ = IconInfo::fromName("folder-videos");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fall back to the default folder icon
|
||||||
|
if(!icon_ || !icon_->isValid()) {
|
||||||
|
icon_ = IconInfo::fromName("folder");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Bookmarks::Bookmarks(QObject* parent):
|
Bookmarks::Bookmarks(QObject* parent):
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
idle_handler{false} {
|
idle_handler{false} {
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
#ifndef FM2_BOOKMARKS_H
|
#ifndef FM2_BOOKMARKS_H
|
||||||
#define FM2_BOOKMARKS_H
|
#define FM2_BOOKMARKS_H
|
||||||
|
|
||||||
#include "../libfmqtglobals.h"
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include "gobjectptr.h"
|
#include "gobjectptr.h"
|
||||||
#include "fileinfo.h"
|
#include "filepath.h"
|
||||||
|
#include "iconinfo.h"
|
||||||
|
|
||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
|
||||||
@ -13,11 +12,7 @@ class LIBFM_QT_API BookmarkItem {
|
|||||||
public:
|
public:
|
||||||
friend class Bookmarks;
|
friend class Bookmarks;
|
||||||
|
|
||||||
explicit BookmarkItem(const FilePath& path, const QString name): path_{path}, name_{name} {
|
explicit BookmarkItem(const FilePath& path, const QString name);
|
||||||
if(name_.isEmpty()) { // if the name is not specified, use basename of the path
|
|
||||||
name_ = path_.baseName().get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString& name() const {
|
const QString& name() const {
|
||||||
return name_;
|
return name_;
|
||||||
@ -27,15 +22,11 @@ public:
|
|||||||
return path_;
|
return path_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::shared_ptr<const FmFileInfo>& info() const {
|
const std::shared_ptr<const IconInfo>& icon() const {
|
||||||
return info_;
|
return icon_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setInfo(const std::shared_ptr<const FmFileInfo>& info) {
|
|
||||||
info_ = info;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setName(const QString& name) {
|
void setName(const QString& name) {
|
||||||
name_ = name;
|
name_ = name;
|
||||||
}
|
}
|
||||||
@ -43,7 +34,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
FilePath path_;
|
FilePath path_;
|
||||||
QString name_;
|
QString name_;
|
||||||
std::shared_ptr<const FmFileInfo> info_;
|
std::shared_ptr<const IconInfo> icon_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
#ifndef LIBFM_QT_COMPAT_P_H
|
|
||||||
#define LIBFM_QT_COMPAT_P_H
|
|
||||||
|
|
||||||
#include "../libfmqtglobals.h"
|
|
||||||
#include "core/filepath.h"
|
|
||||||
#include "core/fileinfo.h"
|
|
||||||
#include "core/gioptrs.h"
|
|
||||||
|
|
||||||
// deprecated
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
#include "path.h"
|
|
||||||
|
|
||||||
// compatibility functions bridging the old libfm C APIs and new C++ APIs.
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
inline FM_QT_DEPRECATED Fm::Path _convertPath(const Fm::FilePath& path) {
|
|
||||||
return Fm::Path::newForGfile(path.gfile().get());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline FM_QT_DEPRECATED Fm::PathList _convertPathList(const Fm::FilePathList& srcFiles) {
|
|
||||||
Fm::PathList ret;
|
|
||||||
for(auto& file: srcFiles) {
|
|
||||||
ret.pushTail(_convertPath(file));
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline FM_QT_DEPRECATED FmFileInfo* _convertFileInfo(const std::shared_ptr<const Fm::FileInfo>& info) {
|
|
||||||
// conver to GFileInfo first
|
|
||||||
GFileInfoPtr ginfo{g_file_info_new(), false};
|
|
||||||
g_file_info_set_name(ginfo.get(), info->name().c_str());
|
|
||||||
g_file_info_set_display_name(ginfo.get(), info->displayName().toUtf8().constData());
|
|
||||||
g_file_info_set_content_type(ginfo.get(), info->mimeType()->name());
|
|
||||||
|
|
||||||
auto mode = info->mode();
|
|
||||||
g_file_info_set_attribute_uint32(ginfo.get(), G_FILE_ATTRIBUTE_UNIX_MODE, mode);
|
|
||||||
GFileType ftype = info->isDir() ? G_FILE_TYPE_DIRECTORY : G_FILE_TYPE_REGULAR; // FIXME: generate more accurate type
|
|
||||||
g_file_info_set_file_type(ginfo.get(), ftype);
|
|
||||||
g_file_info_set_size(ginfo.get(), info->size());
|
|
||||||
g_file_info_set_icon(ginfo.get(), info->icon()->gicon().get());
|
|
||||||
|
|
||||||
g_file_info_set_attribute_uint64(ginfo.get(), G_FILE_ATTRIBUTE_TIME_MODIFIED, info->mtime());
|
|
||||||
g_file_info_set_attribute_uint64(ginfo.get(), G_FILE_ATTRIBUTE_TIME_ACCESS, info->atime());
|
|
||||||
g_file_info_set_attribute_uint64(ginfo.get(), G_FILE_ATTRIBUTE_TIME_CHANGED, info->ctime());
|
|
||||||
|
|
||||||
auto gf = info->path().gfile();
|
|
||||||
return fm_file_info_new_from_g_file_data(gf.get(), ginfo.get(), nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // LIBFM_QT_COMPAT_P_H
|
|
@ -1,453 +0,0 @@
|
|||||||
#include "copyjob.h"
|
|
||||||
#include "totalsizejob.h"
|
|
||||||
#include "fileinfo_p.h"
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
CopyJob::CopyJob(const FilePathList& paths, const FilePath& destDirPath, Mode mode):
|
|
||||||
FileOperationJob{},
|
|
||||||
srcPaths_{paths},
|
|
||||||
destDirPath_{destDirPath},
|
|
||||||
mode_{mode},
|
|
||||||
skip_dir_content{false} {
|
|
||||||
}
|
|
||||||
|
|
||||||
CopyJob::CopyJob(const FilePathList &&paths, const FilePath &&destDirPath, Mode mode):
|
|
||||||
FileOperationJob{},
|
|
||||||
srcPaths_{paths},
|
|
||||||
destDirPath_{destDirPath},
|
|
||||||
mode_{mode},
|
|
||||||
skip_dir_content{false} {
|
|
||||||
}
|
|
||||||
|
|
||||||
void CopyJob::gfileProgressCallback(goffset current_num_bytes, goffset total_num_bytes, CopyJob* _this) {
|
|
||||||
_this->setCurrentFileProgress(total_num_bytes, current_num_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CopyJob::copyRegularFile(const FilePath& srcPath, GFileInfoPtr /*srcFile*/, const FilePath& destPath) {
|
|
||||||
int flags = G_FILE_COPY_ALL_METADATA | G_FILE_COPY_NOFOLLOW_SYMLINKS;
|
|
||||||
GErrorPtr err;
|
|
||||||
_retry_copy:
|
|
||||||
if(!g_file_copy(srcPath.gfile().get(), destPath.gfile().get(), GFileCopyFlags(flags), cancellable().get(),
|
|
||||||
GFileProgressCallback(gfileProgressCallback), this, &err)) {
|
|
||||||
flags &= ~G_FILE_COPY_OVERWRITE;
|
|
||||||
/* handle existing files or file name conflict */
|
|
||||||
if(err.domain() == G_IO_ERROR && (err.code() == G_IO_ERROR_EXISTS ||
|
|
||||||
err.code() == G_IO_ERROR_INVALID_FILENAME ||
|
|
||||||
err.code() == G_IO_ERROR_FILENAME_TOO_LONG)) {
|
|
||||||
#if 0
|
|
||||||
GFile* dest_cp = new_dest;
|
|
||||||
bool dest_exists = (err->code == G_IO_ERROR_EXISTS);
|
|
||||||
FmFileOpOption opt = 0;
|
|
||||||
g_error_free(err);
|
|
||||||
err = nullptr;
|
|
||||||
|
|
||||||
new_dest = nullptr;
|
|
||||||
opt = _fm_file_ops_job_ask_new_name(job, src, dest, &new_dest, dest_exists);
|
|
||||||
if(!new_dest) { /* restoring status quo */
|
|
||||||
new_dest = dest_cp;
|
|
||||||
}
|
|
||||||
else if(dest_cp) { /* we got new new_dest, forget old one */
|
|
||||||
g_object_unref(dest_cp);
|
|
||||||
}
|
|
||||||
switch(opt) {
|
|
||||||
case FM_FILE_OP_RENAME:
|
|
||||||
dest = new_dest;
|
|
||||||
goto _retry_copy;
|
|
||||||
break;
|
|
||||||
case FM_FILE_OP_OVERWRITE:
|
|
||||||
flags |= G_FILE_COPY_OVERWRITE;
|
|
||||||
goto _retry_copy;
|
|
||||||
break;
|
|
||||||
case FM_FILE_OP_CANCEL:
|
|
||||||
fm_job_cancel(fmjob);
|
|
||||||
break;
|
|
||||||
case FM_FILE_OP_SKIP:
|
|
||||||
ret = true;
|
|
||||||
delete_src = false; /* don't delete source file. */
|
|
||||||
break;
|
|
||||||
case FM_FILE_OP_SKIP_ERROR: ; /* FIXME */
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ErrorAction act = emitError( err, ErrorSeverity::MODERATE);
|
|
||||||
err.reset();
|
|
||||||
if(act == ErrorAction::RETRY) {
|
|
||||||
// FIXME: job->current_file_finished = 0;
|
|
||||||
goto _retry_copy;
|
|
||||||
}
|
|
||||||
# if 0
|
|
||||||
const bool is_no_space = (err.domain() == G_IO_ERROR &&
|
|
||||||
err.code() == G_IO_ERROR_NO_SPACE);
|
|
||||||
/* FIXME: ask to leave partial content? */
|
|
||||||
if(is_no_space) {
|
|
||||||
g_file_delete(dest, fm_job_get_cancellable(fmjob), nullptr);
|
|
||||||
}
|
|
||||||
ret = false;
|
|
||||||
delete_src = false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
err.reset();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CopyJob::copySpecialFile(const FilePath& srcPath, GFileInfoPtr srcFile, const FilePath& destPath) {
|
|
||||||
bool ret = false;
|
|
||||||
GError* err = nullptr;
|
|
||||||
/* only handle FIFO for local files */
|
|
||||||
if(srcPath.isNative() && destPath.isNative()) {
|
|
||||||
auto src_path = srcPath.localPath();
|
|
||||||
struct stat src_st;
|
|
||||||
int r;
|
|
||||||
r = lstat(src_path.get(), &src_st);
|
|
||||||
if(r == 0) {
|
|
||||||
/* Handle FIFO on native file systems. */
|
|
||||||
if(S_ISFIFO(src_st.st_mode)) {
|
|
||||||
auto dest_path = destPath.localPath();
|
|
||||||
if(mkfifo(dest_path.get(), src_st.st_mode) == 0) {
|
|
||||||
ret = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* FIXME: how about block device, char device, and socket? */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!ret) {
|
|
||||||
g_set_error(&err, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
||||||
("Cannot copy file '%s': not supported"),
|
|
||||||
g_file_info_get_display_name(srcFile.get()));
|
|
||||||
// emitError( err, ErrorSeverity::MODERATE);
|
|
||||||
g_clear_error(&err);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CopyJob::copyDir(const FilePath& srcPath, GFileInfoPtr srcFile, const FilePath& destPath) {
|
|
||||||
bool ret = false;
|
|
||||||
if(makeDir(srcPath, srcFile, destPath)) {
|
|
||||||
GError* err = nullptr;
|
|
||||||
auto enu = GFileEnumeratorPtr{
|
|
||||||
g_file_enumerate_children(srcPath.gfile().get(),
|
|
||||||
gfile_info_query_attribs,
|
|
||||||
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
|
||||||
cancellable().get(), &err),
|
|
||||||
false};
|
|
||||||
if(enu) {
|
|
||||||
int n_children = 0;
|
|
||||||
int n_copied = 0;
|
|
||||||
ret = true;
|
|
||||||
while(!isCancelled()) {
|
|
||||||
auto inf = GFileInfoPtr{g_file_enumerator_next_file(enu.get(), cancellable().get(), &err), false};
|
|
||||||
if(inf) {
|
|
||||||
++n_children;
|
|
||||||
/* don't overwrite dir content, only calculate progress. */
|
|
||||||
if(Q_UNLIKELY(skip_dir_content)) {
|
|
||||||
/* FIXME: this is incorrect as we don't do the calculation recursively. */
|
|
||||||
addFinishedAmount(g_file_info_get_size(inf.get()), 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const char* name = g_file_info_get_name(inf.get());
|
|
||||||
FilePath childPath = srcPath.child(name);
|
|
||||||
bool child_ret = copyPath(childPath, inf, destPath, name);
|
|
||||||
if(child_ret) {
|
|
||||||
++n_copied;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ret = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(err) {
|
|
||||||
// FIXME: emitError( err, ErrorSeverity::MODERATE);
|
|
||||||
g_error_free(err);
|
|
||||||
err = nullptr;
|
|
||||||
/* ErrorAction::RETRY is not supported here */
|
|
||||||
ret = false;
|
|
||||||
}
|
|
||||||
else { /* EOF is reached */
|
|
||||||
/* all files are successfully copied. */
|
|
||||||
if(isCancelled()) {
|
|
||||||
ret = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* some files are not copied */
|
|
||||||
if(n_children != n_copied) {
|
|
||||||
/* if the copy actions are skipped deliberately, it's ok */
|
|
||||||
if(!skip_dir_content) {
|
|
||||||
ret = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* else job->skip_dir_content is true */
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_file_enumerator_close(enu.get(), nullptr, &err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CopyJob::makeDir(const FilePath& srcPath, GFileInfoPtr srcFile, const FilePath& dirPath) {
|
|
||||||
GError* err = nullptr;
|
|
||||||
if(isCancelled())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
FilePath destPath = dirPath;
|
|
||||||
bool mkdir_done = false;
|
|
||||||
do {
|
|
||||||
mkdir_done = g_file_make_directory(destPath.gfile().get(), cancellable().get(), &err);
|
|
||||||
if(err->domain == G_IO_ERROR && (err->code == G_IO_ERROR_EXISTS ||
|
|
||||||
err->code == G_IO_ERROR_INVALID_FILENAME ||
|
|
||||||
err->code == G_IO_ERROR_FILENAME_TOO_LONG)) {
|
|
||||||
GFileInfoPtr destFile;
|
|
||||||
// FIXME: query its info
|
|
||||||
FilePath newDestPath;
|
|
||||||
FileExistsAction opt = askRename(FileInfo{srcFile, srcPath.parent()}, FileInfo{destFile, dirPath.parent()}, newDestPath);
|
|
||||||
g_error_free(err);
|
|
||||||
err = nullptr;
|
|
||||||
|
|
||||||
switch(opt) {
|
|
||||||
case FileOperationJob::RENAME:
|
|
||||||
destPath = newDestPath;
|
|
||||||
break;
|
|
||||||
case FileOperationJob::SKIP:
|
|
||||||
/* when a dir is skipped, we need to know its total size to calculate correct progress */
|
|
||||||
// job->finished += size;
|
|
||||||
// fm_file_ops_job_emit_percent(job);
|
|
||||||
// job->skip_dir_content = skip_dir_content = true;
|
|
||||||
mkdir_done = true; /* pretend that dir creation succeeded */
|
|
||||||
break;
|
|
||||||
case FileOperationJob::OVERWRITE:
|
|
||||||
mkdir_done = true; /* pretend that dir creation succeeded */
|
|
||||||
break;
|
|
||||||
case FileOperationJob::CANCEL:
|
|
||||||
cancel();
|
|
||||||
break;
|
|
||||||
case FileOperationJob::SKIP_ERROR: ; /* FIXME */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
#if 0
|
|
||||||
ErrorAction act = emitError( err, ErrorSeverity::MODERATE);
|
|
||||||
g_error_free(err);
|
|
||||||
err = nullptr;
|
|
||||||
if(act == ErrorAction::RETRY) {
|
|
||||||
goto _retry_mkdir;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// job->finished += size;
|
|
||||||
} while(!mkdir_done && !isCancelled());
|
|
||||||
|
|
||||||
if(mkdir_done && !isCancelled()) {
|
|
||||||
bool chmod_done = false;
|
|
||||||
mode_t mode = g_file_info_get_attribute_uint32(srcFile.get(), G_FILE_ATTRIBUTE_UNIX_MODE);
|
|
||||||
if(mode) {
|
|
||||||
mode |= (S_IRUSR | S_IWUSR); /* ensure we have rw permission to this file. */
|
|
||||||
do {
|
|
||||||
/* chmod the newly created dir properly */
|
|
||||||
// if(!fm_job_is_cancelled(fmjob) && !job->skip_dir_content)
|
|
||||||
chmod_done = g_file_set_attribute_uint32(destPath.gfile().get(),
|
|
||||||
G_FILE_ATTRIBUTE_UNIX_MODE,
|
|
||||||
mode, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
|
||||||
cancellable().get(), &err);
|
|
||||||
if(!chmod_done) {
|
|
||||||
/*
|
|
||||||
ErrorAction act = emitError( err, ErrorSeverity::MODERATE);
|
|
||||||
g_error_free(err);
|
|
||||||
err = nullptr;
|
|
||||||
if(act == ErrorAction::RETRY) {
|
|
||||||
goto _retry_chmod_for_dir;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/* FIXME: some filesystems may not support this. */
|
|
||||||
}
|
|
||||||
} while(!chmod_done && !isCancelled());
|
|
||||||
// finished += size;
|
|
||||||
// fm_file_ops_job_emit_percent(job);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CopyJob::copyPath(const FilePath& srcPath, const FilePath& destDirPath, const char* destFileName) {
|
|
||||||
GErrorPtr err;
|
|
||||||
GFileInfoPtr srcInfo = GFileInfoPtr {
|
|
||||||
g_file_query_info(srcPath.gfile().get(),
|
|
||||||
gfile_info_query_attribs,
|
|
||||||
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
|
||||||
cancellable().get(), &err),
|
|
||||||
false
|
|
||||||
};
|
|
||||||
if(!srcInfo || isCancelled()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return copyPath(srcPath, srcInfo, destDirPath, destFileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CopyJob::copyPath(const FilePath& srcPath, const GFileInfoPtr& srcInfo, const FilePath& destDirPath, const char* destFileName) {
|
|
||||||
setCurrentFile(srcPath);
|
|
||||||
GErrorPtr err;
|
|
||||||
GFileInfoPtr destDirInfo = GFileInfoPtr {
|
|
||||||
g_file_query_info(destDirPath.gfile().get(),
|
|
||||||
"id::filesystem",
|
|
||||||
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
|
||||||
cancellable().get(), &err),
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
if(!destDirInfo || isCancelled()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto size = g_file_info_get_size(srcInfo.get());
|
|
||||||
setCurrentFileProgress(size, 0);
|
|
||||||
|
|
||||||
auto destPath = destDirPath.child(destFileName);
|
|
||||||
bool success = false;
|
|
||||||
switch(g_file_info_get_file_type(srcInfo.get())) {
|
|
||||||
case G_FILE_TYPE_DIRECTORY:
|
|
||||||
success = copyDir(srcPath, srcInfo, destPath);
|
|
||||||
break;
|
|
||||||
case G_FILE_TYPE_SPECIAL:
|
|
||||||
success = copySpecialFile(srcPath, srcInfo, destPath);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
success = copyRegularFile(srcPath, srcInfo, destPath);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(success) {
|
|
||||||
addFinishedAmount(size, 1);
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
if(ret && dest_folder) {
|
|
||||||
fm_dest = fm_path_new_for_gfile(dest);
|
|
||||||
if(!_fm_folder_event_file_added(dest_folder, fm_dest)) {
|
|
||||||
fm_path_unref(fm_dest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
bool _fm_file_ops_job_copy_run(FmFileOpsJob* job) {
|
|
||||||
bool ret = true;
|
|
||||||
GFile* dest_dir;
|
|
||||||
GList* l;
|
|
||||||
FmJob* fmjob = FM_JOB(job);
|
|
||||||
/* prepare the job, count total work needed with FmDeepCountJob */
|
|
||||||
FmDeepCountJob* dc = fm_deep_count_job_new(job->srcs, FM_DC_JOB_DEFAULT);
|
|
||||||
FmFolder* df;
|
|
||||||
|
|
||||||
/* let the deep count job share the same cancellable object. */
|
|
||||||
fm_job_set_cancellable(FM_JOB(dc), fm_job_get_cancellable(fmjob));
|
|
||||||
fm_job_run_sync(FM_JOB(dc));
|
|
||||||
job->total = dc->total_size;
|
|
||||||
if(fm_job_is_cancelled(fmjob)) {
|
|
||||||
g_object_unref(dc);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
g_object_unref(dc);
|
|
||||||
g_debug("total size to copy: %llu", (long long unsigned int)job->total);
|
|
||||||
|
|
||||||
dest_dir = fm_path_to_gfile(job->dest);
|
|
||||||
/* suspend updates for destination */
|
|
||||||
df = fm_folder_find_by_path(job->dest);
|
|
||||||
if(df) {
|
|
||||||
fm_folder_block_updates(df);
|
|
||||||
}
|
|
||||||
|
|
||||||
fm_file_ops_job_emit_prepared(job);
|
|
||||||
|
|
||||||
for(l = fm_path_list_peek_head_link(job->srcs); !fm_job_is_cancelled(fmjob) && l; l = l->next) {
|
|
||||||
FmPath* path = FM_PATH(l->data);
|
|
||||||
GFile* src = fm_path_to_gfile(path);
|
|
||||||
GFile* dest;
|
|
||||||
char* tmp_basename;
|
|
||||||
|
|
||||||
if(g_file_is_native(src) && g_file_is_native(dest_dir))
|
|
||||||
/* both are native */
|
|
||||||
{
|
|
||||||
tmp_basename = nullptr;
|
|
||||||
}
|
|
||||||
else if(g_file_is_native(src)) /* copy from native to virtual */
|
|
||||||
tmp_basename = g_filename_to_utf8(fm_path_get_basename(path),
|
|
||||||
-1, nullptr, nullptr, nullptr);
|
|
||||||
/* gvfs escapes it itself */
|
|
||||||
else { /* copy from virtual to native/virtual */
|
|
||||||
/* if we drop URI query onto native filesystem, omit query part */
|
|
||||||
const char* basename = fm_path_get_basename(path);
|
|
||||||
char* sub_name;
|
|
||||||
|
|
||||||
sub_name = strchr(basename, '?');
|
|
||||||
if(sub_name) {
|
|
||||||
sub_name = g_strndup(basename, sub_name - basename);
|
|
||||||
basename = strrchr(sub_name, G_DIR_SEPARATOR);
|
|
||||||
if(basename) {
|
|
||||||
basename++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
basename = sub_name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tmp_basename = fm_uri_subpath_to_native_subpath(basename, nullptr);
|
|
||||||
g_free(sub_name);
|
|
||||||
}
|
|
||||||
dest = g_file_get_child(dest_dir,
|
|
||||||
tmp_basename ? tmp_basename : fm_path_get_basename(path));
|
|
||||||
g_free(tmp_basename);
|
|
||||||
if(!_fm_file_ops_job_copy_file(job, src, nullptr, dest, nullptr, df)) {
|
|
||||||
ret = false;
|
|
||||||
}
|
|
||||||
g_object_unref(src);
|
|
||||||
g_object_unref(dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* g_debug("finished: %llu, total: %llu", job->finished, job->total); */
|
|
||||||
fm_file_ops_job_emit_percent(job);
|
|
||||||
|
|
||||||
/* restore updates for destination */
|
|
||||||
if(df) {
|
|
||||||
fm_folder_unblock_updates(df);
|
|
||||||
g_object_unref(df);
|
|
||||||
}
|
|
||||||
g_object_unref(dest_dir);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void CopyJob::exec() {
|
|
||||||
TotalSizeJob totalSizeJob{srcPaths_};
|
|
||||||
connect(&totalSizeJob, &TotalSizeJob::error, this, &CopyJob::error);
|
|
||||||
connect(this, &CopyJob::cancelled, &totalSizeJob, &TotalSizeJob::cancel);
|
|
||||||
totalSizeJob.run();
|
|
||||||
if(isCancelled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setTotalAmount(totalSizeJob.totalSize(), totalSizeJob.fileCount());
|
|
||||||
Q_EMIT preparedToRun();
|
|
||||||
|
|
||||||
for(auto& srcPath : srcPaths_) {
|
|
||||||
if(isCancelled()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
copyPath(srcPath, destDirPath_, srcPath.baseName().get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Fm
|
|
@ -1,46 +0,0 @@
|
|||||||
#ifndef FM2_COPYJOB_H
|
|
||||||
#define FM2_COPYJOB_H
|
|
||||||
|
|
||||||
#include "../libfmqtglobals.h"
|
|
||||||
#include "fileoperationjob.h"
|
|
||||||
#include "gioptrs.h"
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class LIBFM_QT_API CopyJob : public Fm::FileOperationJob {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum class Mode {
|
|
||||||
COPY,
|
|
||||||
MOVE
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit CopyJob(const FilePathList& paths, const FilePath& destDirPath, Mode mode = Mode::COPY);
|
|
||||||
|
|
||||||
explicit CopyJob(const FilePathList&& paths, const FilePath&& destDirPath, Mode mode = Mode::COPY);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void exec() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool copyPath(const FilePath& srcPath, const FilePath& destPath, const char *destFileName);
|
|
||||||
bool copyPath(const FilePath &srcPath, const GFileInfoPtr &srcInfo, const FilePath &destDirPath, const char *destFileName);
|
|
||||||
bool copyRegularFile(const FilePath &srcPath, GFileInfoPtr srcFile, const FilePath& destPath);
|
|
||||||
bool copySpecialFile(const FilePath &srcPath, GFileInfoPtr srcFile, const FilePath& destPath);
|
|
||||||
bool copyDir(const FilePath &srcPath, GFileInfoPtr srcFile, const FilePath& destPath);
|
|
||||||
bool makeDir(const FilePath &srcPath, GFileInfoPtr srcFile, const FilePath& dirPath);
|
|
||||||
|
|
||||||
static void gfileProgressCallback(goffset current_num_bytes, goffset total_num_bytes, CopyJob* _this);
|
|
||||||
|
|
||||||
private:
|
|
||||||
FilePathList srcPaths_;
|
|
||||||
FilePath destDirPath_;
|
|
||||||
Mode mode_;
|
|
||||||
bool skip_dir_content;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Fm
|
|
||||||
|
|
||||||
#endif // FM2_COPYJOB_H
|
|
@ -25,6 +25,9 @@ bool DeleteJob::deleteFile(const FilePath& path, GFileInfoPtr inf) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: get parent dir of the current path.
|
||||||
|
// if there is a Fm::Folder object created for it, block the update for the folder temporarily.
|
||||||
|
|
||||||
/* currently processed file. */
|
/* currently processed file. */
|
||||||
setCurrentFile(path);
|
setCurrentFile(path);
|
||||||
|
|
||||||
@ -33,11 +36,21 @@ bool DeleteJob::deleteFile(const FilePath& path, GFileInfoPtr inf) {
|
|||||||
deleteDirContent(path, inf);
|
deleteDirContent(path, inf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isTrashRoot = false;
|
||||||
|
// special handling for trash:///
|
||||||
|
if(!path.isNative() && g_strcmp0(path.uriScheme().get(), "trash") == 0) {
|
||||||
|
// little trick: basename of trash root is /
|
||||||
|
auto basename = path.baseName();
|
||||||
|
if(basename && basename[0] == G_DIR_SEPARATOR) {
|
||||||
|
isTrashRoot = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool hasError = false;
|
bool hasError = false;
|
||||||
while(!isCancelled()) {
|
while(!isCancelled()) {
|
||||||
GErrorPtr err;
|
GErrorPtr err;
|
||||||
// try to delete the path directly
|
// try to delete the path directly (but don't delete if it's trash:///)
|
||||||
if(g_file_delete(path.gfile().get(), cancellable().get(), &err)) {
|
if(isTrashRoot || g_file_delete(path.gfile().get(), cancellable().get(), &err)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(err) {
|
if(err) {
|
||||||
@ -69,26 +82,9 @@ bool DeleteJob::deleteFile(const FilePath& path, GFileInfoPtr inf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool DeleteJob::deleteDirContent(const FilePath& path, GFileInfoPtr inf) {
|
bool DeleteJob::deleteDirContent(const FilePath& path, GFileInfoPtr inf) {
|
||||||
#if 0
|
|
||||||
FmFolder* sub_folder;
|
|
||||||
/* special handling for trash:/// */
|
|
||||||
if(!g_file_is_native(gf)) {
|
|
||||||
char* scheme = g_file_get_uri_scheme(gf);
|
|
||||||
if(g_strcmp0(scheme, "trash") == 0) {
|
|
||||||
/* little trick: basename of trash root is /. */
|
|
||||||
char* basename = g_file_get_basename(gf);
|
|
||||||
if(basename && basename[0] == G_DIR_SEPARATOR) {
|
|
||||||
is_trash_root = true;
|
|
||||||
}
|
|
||||||
g_free(basename);
|
|
||||||
}
|
|
||||||
g_free(scheme);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
GErrorPtr err;
|
GErrorPtr err;
|
||||||
GFileEnumeratorPtr enu {
|
GFileEnumeratorPtr enu {
|
||||||
g_file_enumerate_children(path.gfile().get(), gfile_info_query_attribs,
|
g_file_enumerate_children(path.gfile().get(), defaultGFileInfoQueryAttribs,
|
||||||
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||||
cancellable().get(), &err),
|
cancellable().get(), &err),
|
||||||
false
|
false
|
||||||
@ -126,6 +122,17 @@ bool DeleteJob::deleteDirContent(const FilePath& path, GFileInfoPtr inf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DeleteJob::DeleteJob(const FilePathList &paths): paths_{paths} {
|
||||||
|
setCalcProgressUsingSize(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteJob::DeleteJob(FilePathList &&paths): paths_{paths} {
|
||||||
|
setCalcProgressUsingSize(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteJob::~DeleteJob() {
|
||||||
|
}
|
||||||
|
|
||||||
void DeleteJob::exec() {
|
void DeleteJob::exec() {
|
||||||
/* prepare the job, count total work needed with FmDeepCountJob */
|
/* prepare the job, count total work needed with FmDeepCountJob */
|
||||||
TotalSizeJob totalSizeJob{paths_, TotalSizeJob::Flags::PREPARE_DELETE};
|
TotalSizeJob totalSizeJob{paths_, TotalSizeJob::Flags::PREPARE_DELETE};
|
||||||
|
@ -11,14 +11,11 @@ namespace Fm {
|
|||||||
class LIBFM_QT_API DeleteJob : public Fm::FileOperationJob {
|
class LIBFM_QT_API DeleteJob : public Fm::FileOperationJob {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit DeleteJob(const FilePathList& paths): paths_{paths} {
|
explicit DeleteJob(const FilePathList& paths);
|
||||||
}
|
|
||||||
|
|
||||||
explicit DeleteJob(FilePathList&& paths): paths_{paths} {
|
explicit DeleteJob(FilePathList&& paths);
|
||||||
}
|
|
||||||
|
|
||||||
~DeleteJob() {
|
~DeleteJob();
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void exec() override;
|
void exec() override;
|
||||||
|
@ -25,7 +25,7 @@ void DirListJob::exec() {
|
|||||||
_retry:
|
_retry:
|
||||||
err.reset();
|
err.reset();
|
||||||
dir_inf = GFileInfoPtr{
|
dir_inf = GFileInfoPtr{
|
||||||
g_file_query_info(dir_gfile.get(), gfile_info_query_attribs,
|
g_file_query_info(dir_gfile.get(), defaultGFileInfoQueryAttribs,
|
||||||
G_FILE_QUERY_INFO_NONE, cancellable().get(), &err),
|
G_FILE_QUERY_INFO_NONE, cancellable().get(), &err),
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
@ -58,7 +58,7 @@ _retry:
|
|||||||
// FIXME: _fm_file_info_job_update_fs_readonly(gf, inf, nullptr, nullptr);
|
// FIXME: _fm_file_info_job_update_fs_readonly(gf, inf, nullptr, nullptr);
|
||||||
err.reset();
|
err.reset();
|
||||||
GFileEnumeratorPtr enu = GFileEnumeratorPtr{
|
GFileEnumeratorPtr enu = GFileEnumeratorPtr{
|
||||||
g_file_enumerate_children(dir_gfile.get(), gfile_info_query_attribs,
|
g_file_enumerate_children(dir_gfile.get(), defaultGFileInfoQueryAttribs,
|
||||||
G_FILE_QUERY_INFO_NONE, cancellable().get(), &err),
|
G_FILE_QUERY_INFO_NONE, cancellable().get(), &err),
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
@ -1,9 +1,324 @@
|
|||||||
#include "filechangeattrjob.h"
|
#include "filechangeattrjob.h"
|
||||||
|
#include "totalsizejob.h"
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
|
||||||
FileChangeAttrJob::FileChangeAttrJob() {
|
static const char query[] = G_FILE_ATTRIBUTE_STANDARD_TYPE","
|
||||||
|
G_FILE_ATTRIBUTE_STANDARD_NAME","
|
||||||
|
G_FILE_ATTRIBUTE_UNIX_GID","
|
||||||
|
G_FILE_ATTRIBUTE_UNIX_UID","
|
||||||
|
G_FILE_ATTRIBUTE_UNIX_MODE","
|
||||||
|
G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME;
|
||||||
|
|
||||||
|
FileChangeAttrJob::FileChangeAttrJob(FilePathList paths):
|
||||||
|
paths_{std::move(paths)},
|
||||||
|
recursive_{false},
|
||||||
|
// chmod
|
||||||
|
fileModeEnabled_{false},
|
||||||
|
newMode_{0},
|
||||||
|
newModeMask_{0},
|
||||||
|
// chown
|
||||||
|
ownerEnabled_{false},
|
||||||
|
uid_{0},
|
||||||
|
groupEnabled_{false},
|
||||||
|
gid_{0},
|
||||||
|
// Display name
|
||||||
|
displayNameEnabled_{false},
|
||||||
|
// icon
|
||||||
|
iconEnabled_{false},
|
||||||
|
// hidden
|
||||||
|
hiddenEnabled_{false},
|
||||||
|
hidden_{false},
|
||||||
|
// target uri
|
||||||
|
targetUriEnabled_{false} {
|
||||||
|
|
||||||
|
// the progress of chmod/chown is not related to file size
|
||||||
|
setCalcProgressUsingSize(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileChangeAttrJob::exec() {
|
||||||
|
// count total amount of the work
|
||||||
|
if(recursive_) {
|
||||||
|
TotalSizeJob totalSizeJob{paths_};
|
||||||
|
connect(&totalSizeJob, &TotalSizeJob::error, this, &FileChangeAttrJob::error);
|
||||||
|
connect(this, &FileChangeAttrJob::cancelled, &totalSizeJob, &TotalSizeJob::cancel);
|
||||||
|
totalSizeJob.run();
|
||||||
|
std::uint64_t totalSize, totalCount;
|
||||||
|
totalSizeJob.totalAmount(totalSize, totalCount);
|
||||||
|
setTotalAmount(totalSize, totalCount);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setTotalAmount(paths_.size(), paths_.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ready to start
|
||||||
|
Q_EMIT preparedToRun();
|
||||||
|
|
||||||
|
// do the actual change attrs job
|
||||||
|
for(auto& path : paths_) {
|
||||||
|
if(isCancelled()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
GErrorPtr err;
|
||||||
|
GFileInfoPtr info{
|
||||||
|
g_file_query_info(path.gfile().get(), query,
|
||||||
|
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||||
|
cancellable().get(), &err),
|
||||||
|
false
|
||||||
|
};
|
||||||
|
if(info) {
|
||||||
|
processFile(path, info);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
handleError(err, path, info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileChangeAttrJob::processFile(const FilePath& path, const GFileInfoPtr& info) {
|
||||||
|
setCurrentFile(path);
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
|
if(ownerEnabled_) {
|
||||||
|
changeFileOwner(path, info, uid_);
|
||||||
|
}
|
||||||
|
if(groupEnabled_) {
|
||||||
|
changeFileGroup(path, info, gid_);
|
||||||
|
}
|
||||||
|
if(fileModeEnabled_) {
|
||||||
|
changeFileMode(path, info, newMode_, newModeMask_);
|
||||||
|
}
|
||||||
|
/* change display name, icon, hidden, target */
|
||||||
|
if(displayNameEnabled_ && !displayName().empty()) {
|
||||||
|
changeFileDisplayName(path, info, displayName_.c_str());
|
||||||
|
}
|
||||||
|
if(iconEnabled_ && icon_) {
|
||||||
|
changeFileIcon(path, info, icon_);
|
||||||
|
}
|
||||||
|
if(hiddenEnabled_) {
|
||||||
|
changeFileHidden(path, info, hidden_);
|
||||||
|
}
|
||||||
|
if(targetUriEnabled_ && !targetUri_.empty()) {
|
||||||
|
changeFileTargetUri(path, info, targetUri_.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: do not use size 1 here.
|
||||||
|
addFinishedAmount(1, 1);
|
||||||
|
|
||||||
|
// recursively apply to subfolders
|
||||||
|
auto type = g_file_info_get_file_type(info.get());
|
||||||
|
if(!isCancelled() && recursive_ && type == G_FILE_TYPE_DIRECTORY) {
|
||||||
|
bool retry;
|
||||||
|
do {
|
||||||
|
retry = false;
|
||||||
|
GErrorPtr err;
|
||||||
|
GFileEnumeratorPtr enu{
|
||||||
|
g_file_enumerate_children(path.gfile().get(), query,
|
||||||
|
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||||
|
cancellable().get(), &err),
|
||||||
|
false
|
||||||
|
};
|
||||||
|
if(enu) {
|
||||||
|
while(!isCancelled()) {
|
||||||
|
err.reset();
|
||||||
|
GFileInfoPtr childInfo{g_file_enumerator_next_file(enu.get(), cancellable().get(), &err), false};
|
||||||
|
if(childInfo) {
|
||||||
|
auto childPath = path.child(g_file_info_get_name(childInfo.get()));
|
||||||
|
ret = processFile(childPath, childInfo);
|
||||||
|
if(!ret) { /* _fm_file_ops_job_change_attr_file() failed */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(err) {
|
||||||
|
handleError(err, path, info, ErrorSeverity::MILD);
|
||||||
|
retry = false;
|
||||||
|
/* FM_JOB_RETRY is not supported here */
|
||||||
|
}
|
||||||
|
else { /* EOF */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_file_enumerator_close(enu.get(), cancellable().get(), nullptr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
retry = handleError(err, path, info);
|
||||||
|
}
|
||||||
|
} while(!isCancelled() && retry);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileChangeAttrJob::handleError(GErrorPtr &err, const FilePath &path, const GFileInfoPtr &info, ErrorSeverity severity) {
|
||||||
|
auto act = emitError(err, severity);
|
||||||
|
if (act == ErrorAction::RETRY) {
|
||||||
|
err.reset();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileChangeAttrJob::changeFileOwner(const FilePath& path, const GFileInfoPtr& info, uid_t uid) {
|
||||||
|
/* change owner */
|
||||||
|
bool ret = false;
|
||||||
|
bool retry;
|
||||||
|
do {
|
||||||
|
GErrorPtr err;
|
||||||
|
if(!g_file_set_attribute_uint32(path.gfile().get(), G_FILE_ATTRIBUTE_UNIX_UID,
|
||||||
|
uid, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||||
|
cancellable().get(), &err)) {
|
||||||
|
retry = handleError(err, path, info, ErrorSeverity::MILD);
|
||||||
|
err.reset();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = true;
|
||||||
|
retry = false;
|
||||||
|
}
|
||||||
|
} while(retry && !isCancelled());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileChangeAttrJob::changeFileGroup(const FilePath& path, const GFileInfoPtr& info, gid_t gid) {
|
||||||
|
/* change group */
|
||||||
|
bool ret = false;
|
||||||
|
bool retry;
|
||||||
|
do {
|
||||||
|
GErrorPtr err;
|
||||||
|
if(!g_file_set_attribute_uint32(path.gfile().get(), G_FILE_ATTRIBUTE_UNIX_GID,
|
||||||
|
gid, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||||
|
cancellable().get(), &err)) {
|
||||||
|
retry = handleError(err, path, info, ErrorSeverity::MILD);
|
||||||
|
err.reset();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = true;
|
||||||
|
retry = false;
|
||||||
|
}
|
||||||
|
} while(retry && !isCancelled());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileChangeAttrJob::changeFileMode(const FilePath& path, const GFileInfoPtr& info, mode_t newMode, mode_t newModeMask) {
|
||||||
|
bool ret = false;
|
||||||
|
/* change mode */
|
||||||
|
if(newModeMask) {
|
||||||
|
guint32 mode = g_file_info_get_attribute_uint32(info.get(), G_FILE_ATTRIBUTE_UNIX_MODE);
|
||||||
|
mode &= ~newModeMask;
|
||||||
|
mode |= (newMode & newModeMask);
|
||||||
|
|
||||||
|
auto type = g_file_info_get_file_type(info.get());
|
||||||
|
/* FIXME: this behavior should be optional. */
|
||||||
|
/* treat dirs with 'r' as 'rx' */
|
||||||
|
if(type == G_FILE_TYPE_DIRECTORY) {
|
||||||
|
if((newModeMask & S_IRUSR) && (mode & S_IRUSR)) {
|
||||||
|
mode |= S_IXUSR;
|
||||||
|
}
|
||||||
|
if((newModeMask & S_IRGRP) && (mode & S_IRGRP)) {
|
||||||
|
mode |= S_IXGRP;
|
||||||
|
}
|
||||||
|
if((newModeMask & S_IROTH) && (mode & S_IROTH)) {
|
||||||
|
mode |= S_IXOTH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* new mode */
|
||||||
|
bool retry;
|
||||||
|
do {
|
||||||
|
GErrorPtr err;
|
||||||
|
if(!g_file_set_attribute_uint32(path.gfile().get(), G_FILE_ATTRIBUTE_UNIX_MODE,
|
||||||
|
mode, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||||
|
cancellable().get(), &err)) {
|
||||||
|
retry = handleError(err, path, info, ErrorSeverity::MILD);
|
||||||
|
err.reset();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = true;
|
||||||
|
retry = false;
|
||||||
|
}
|
||||||
|
} while(retry && !isCancelled());
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FileChangeAttrJob::changeFileDisplayName(const FilePath& path, const GFileInfoPtr& info, const char* displayName) {
|
||||||
|
bool ret = false;
|
||||||
|
bool retry;
|
||||||
|
do {
|
||||||
|
GErrorPtr err;
|
||||||
|
if(!g_file_set_display_name(path.gfile().get(), displayName, cancellable().get(), &err)) {
|
||||||
|
retry = handleError(err, path, info, ErrorSeverity::MILD);
|
||||||
|
err.reset();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = true;
|
||||||
|
retry = false;
|
||||||
|
}
|
||||||
|
} while(retry && !isCancelled());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileChangeAttrJob::changeFileIcon(const FilePath& path, const GFileInfoPtr& info, GIconPtr& icon) {
|
||||||
|
bool ret = false;
|
||||||
|
bool retry;
|
||||||
|
do {
|
||||||
|
GErrorPtr err;
|
||||||
|
if(!g_file_set_attribute(path.gfile().get(), G_FILE_ATTRIBUTE_STANDARD_ICON,
|
||||||
|
G_FILE_ATTRIBUTE_TYPE_OBJECT, icon.get(),
|
||||||
|
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||||
|
cancellable().get(), &err)) {
|
||||||
|
retry = handleError(err, path, info, ErrorSeverity::MILD);
|
||||||
|
err.reset();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = true;
|
||||||
|
retry = false;
|
||||||
|
}
|
||||||
|
} while(retry && !isCancelled());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileChangeAttrJob::changeFileHidden(const FilePath& path, const GFileInfoPtr& info, bool hidden) {
|
||||||
|
bool ret = false;
|
||||||
|
bool retry;
|
||||||
|
do {
|
||||||
|
GErrorPtr err;
|
||||||
|
gboolean g_hidden = hidden;
|
||||||
|
if(!g_file_set_attribute(path.gfile().get(), G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN,
|
||||||
|
G_FILE_ATTRIBUTE_TYPE_BOOLEAN, &g_hidden,
|
||||||
|
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||||
|
cancellable().get(), &err)) {
|
||||||
|
retry = handleError(err, path, info, ErrorSeverity::MILD);
|
||||||
|
err.reset();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = true;
|
||||||
|
retry = false;
|
||||||
|
}
|
||||||
|
} while(retry && !isCancelled());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileChangeAttrJob::changeFileTargetUri(const FilePath& path, const GFileInfoPtr& info, const char* targetUri) {
|
||||||
|
bool ret = false;
|
||||||
|
bool retry;
|
||||||
|
do {
|
||||||
|
GErrorPtr err;
|
||||||
|
if(!g_file_set_attribute_string(path.gfile().get(), G_FILE_ATTRIBUTE_STANDARD_TARGET_URI,
|
||||||
|
targetUri, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||||
|
cancellable().get(), &err)) {
|
||||||
|
retry = handleError(err, path, info, ErrorSeverity::MILD);
|
||||||
|
err.reset();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = true;
|
||||||
|
retry = false;
|
||||||
|
}
|
||||||
|
} while(retry && !isCancelled());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Fm
|
} // namespace Fm
|
||||||
|
@ -3,13 +3,141 @@
|
|||||||
|
|
||||||
#include "../libfmqtglobals.h"
|
#include "../libfmqtglobals.h"
|
||||||
#include "fileoperationjob.h"
|
#include "fileoperationjob.h"
|
||||||
|
#include "gioptrs.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
|
||||||
class LIBFM_QT_API FileChangeAttrJob : public Fm::FileOperationJob {
|
class LIBFM_QT_API FileChangeAttrJob : public Fm::FileOperationJob {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit FileChangeAttrJob();
|
explicit FileChangeAttrJob(FilePathList paths);
|
||||||
|
|
||||||
|
void setFileModeEnabled(bool enabled) {
|
||||||
|
fileModeEnabled_ = enabled;
|
||||||
|
}
|
||||||
|
void setFileMode(mode_t newMode, mode_t newModeMask) {
|
||||||
|
newMode_ = newMode;
|
||||||
|
newModeMask_ = newModeMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ownerEnabled() const {
|
||||||
|
return ownerEnabled_;
|
||||||
|
}
|
||||||
|
void setOwnerEnabled(bool enabled) {
|
||||||
|
ownerEnabled_ = enabled;
|
||||||
|
}
|
||||||
|
void setOwner(uid_t uid) {
|
||||||
|
uid_ = uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool groupEnabled() const {
|
||||||
|
return groupEnabled_;
|
||||||
|
}
|
||||||
|
void setGroupEnabled(bool groupEnabled) {
|
||||||
|
groupEnabled_ = groupEnabled;
|
||||||
|
}
|
||||||
|
void setGroup(gid_t gid) {
|
||||||
|
gid_ = gid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This only work for change attr jobs.
|
||||||
|
void setRecursive(bool recursive) {
|
||||||
|
recursive_ = recursive;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setHiddenEnabled(bool enabled) {
|
||||||
|
hiddenEnabled_ = enabled;
|
||||||
|
}
|
||||||
|
void setHidden(bool hidden) {
|
||||||
|
hidden_ = hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool iconEnabled() const {
|
||||||
|
return iconEnabled_;
|
||||||
|
}
|
||||||
|
void setIconEnabled(bool iconEnabled) {
|
||||||
|
iconEnabled_ = iconEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool displayNameEnabled() const {
|
||||||
|
return displayNameEnabled_;
|
||||||
|
}
|
||||||
|
void setDisplayNameEnabled(bool displayNameEnabled) {
|
||||||
|
displayNameEnabled_ = displayNameEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& displayName() const {
|
||||||
|
return displayName_;
|
||||||
|
}
|
||||||
|
void setDisplayName(const std::string& displayName) {
|
||||||
|
displayName_ = displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool targetUriEnabled() const {
|
||||||
|
return targetUriEnabled_;
|
||||||
|
}
|
||||||
|
void setTargetUriEnabled(bool targetUriEnabled) {
|
||||||
|
targetUriEnabled_ = targetUriEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& targetUri() const {
|
||||||
|
return targetUri_;
|
||||||
|
}
|
||||||
|
void setTargetUri(const std::string& value) {
|
||||||
|
targetUri_ = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void exec() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool processFile(const FilePath& path, const GFileInfoPtr& info);
|
||||||
|
bool handleError(GErrorPtr& err, const FilePath& path, const GFileInfoPtr& info, ErrorSeverity severity = ErrorSeverity::MODERATE);
|
||||||
|
|
||||||
|
bool changeFileOwner(const FilePath& path, const GFileInfoPtr& info, uid_t uid);
|
||||||
|
bool changeFileGroup(const FilePath& path, const GFileInfoPtr& info, gid_t gid);
|
||||||
|
bool changeFileMode(const FilePath& path, const GFileInfoPtr& info, mode_t newMode, mode_t newModeMask);
|
||||||
|
bool changeFileDisplayName(const FilePath& path, const GFileInfoPtr& info, const char* displayName);
|
||||||
|
bool changeFileIcon(const FilePath& path, const GFileInfoPtr& info, GIconPtr& icon);
|
||||||
|
bool changeFileHidden(const FilePath& path, const GFileInfoPtr& info, bool hidden);
|
||||||
|
bool changeFileTargetUri(const FilePath& path, const GFileInfoPtr& info, const char* targetUri_);
|
||||||
|
|
||||||
|
private:
|
||||||
|
FilePathList paths_;
|
||||||
|
bool recursive_;
|
||||||
|
|
||||||
|
// chmod
|
||||||
|
bool fileModeEnabled_;
|
||||||
|
mode_t newMode_;
|
||||||
|
mode_t newModeMask_;
|
||||||
|
|
||||||
|
// chown
|
||||||
|
bool ownerEnabled_;
|
||||||
|
uid_t uid_;
|
||||||
|
|
||||||
|
bool groupEnabled_;
|
||||||
|
gid_t gid_;
|
||||||
|
|
||||||
|
// Display name
|
||||||
|
bool displayNameEnabled_;
|
||||||
|
std::string displayName_;
|
||||||
|
|
||||||
|
// icon
|
||||||
|
bool iconEnabled_;
|
||||||
|
GIconPtr icon_;
|
||||||
|
|
||||||
|
// hidden
|
||||||
|
bool hiddenEnabled_;
|
||||||
|
bool hidden_;
|
||||||
|
|
||||||
|
// target uri
|
||||||
|
bool targetUriEnabled_;
|
||||||
|
std::string targetUri_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Fm
|
} // namespace Fm
|
||||||
|
@ -4,12 +4,12 @@
|
|||||||
|
|
||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
|
||||||
const char gfile_info_query_attribs[] = "standard::*,"
|
const char defaultGFileInfoQueryAttribs[] = "standard::*,"
|
||||||
"unix::*,"
|
"unix::*,"
|
||||||
"time::*,"
|
"time::*,"
|
||||||
"access::*,"
|
"access::*,"
|
||||||
"id::filesystem,"
|
"id::filesystem,"
|
||||||
"metadata::emblems";
|
"metadata::emblems";
|
||||||
|
|
||||||
FileInfo::FileInfo() {
|
FileInfo::FileInfo() {
|
||||||
// FIXME: initialize numeric data members
|
// FIXME: initialize numeric data members
|
||||||
@ -28,7 +28,8 @@ void FileInfo::setFromGFileInfo(const GObjectPtr<GFileInfo>& inf, const FilePath
|
|||||||
GIcon* gicon;
|
GIcon* gicon;
|
||||||
GFileType type;
|
GFileType type;
|
||||||
|
|
||||||
name_ = g_file_info_get_name(inf.get());
|
if (const char * name = g_file_info_get_name(inf.get()))
|
||||||
|
name_ = name;
|
||||||
|
|
||||||
dispName_ = g_file_info_get_display_name(inf.get());
|
dispName_ = g_file_info_get_display_name(inf.get());
|
||||||
|
|
||||||
@ -118,6 +119,8 @@ void FileInfo::setFromGFileInfo(const GObjectPtr<GFileInfo>& inf, const FilePath
|
|||||||
isDeletable_ = true;
|
isDeletable_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isShortcut_ = false;
|
||||||
|
|
||||||
/* special handling for symlinks */
|
/* special handling for symlinks */
|
||||||
if(g_file_info_get_is_symlink(inf.get())) {
|
if(g_file_info_get_is_symlink(inf.get())) {
|
||||||
mode_ &= ~S_IFMT; /* reset type */
|
mode_ &= ~S_IFMT; /* reset type */
|
||||||
@ -125,11 +128,10 @@ void FileInfo::setFromGFileInfo(const GObjectPtr<GFileInfo>& inf, const FilePath
|
|||||||
goto _file_is_symlink;
|
goto _file_is_symlink;
|
||||||
}
|
}
|
||||||
|
|
||||||
isShortcut_ = false;
|
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case G_FILE_TYPE_SHORTCUT:
|
case G_FILE_TYPE_SHORTCUT:
|
||||||
isShortcut_ = true;
|
isShortcut_ = true;
|
||||||
|
/* Falls through. */
|
||||||
case G_FILE_TYPE_MOUNTABLE:
|
case G_FILE_TYPE_MOUNTABLE:
|
||||||
uri = g_file_info_get_attribute_string(inf.get(), G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);
|
uri = g_file_info_get_attribute_string(inf.get(), G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);
|
||||||
if(uri) {
|
if(uri) {
|
||||||
@ -184,6 +186,7 @@ _file_is_symlink:
|
|||||||
mimeType_ = MimeType::guessFromFileName(target_.c_str());
|
mimeType_ = MimeType::guessFromFileName(target_.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Falls through. */
|
||||||
/* continue with absent mime type */
|
/* continue with absent mime type */
|
||||||
default: /* G_FILE_TYPE_UNKNOWN G_FILE_TYPE_REGULAR G_FILE_TYPE_SPECIAL */
|
default: /* G_FILE_TYPE_UNKNOWN G_FILE_TYPE_REGULAR G_FILE_TYPE_SPECIAL */
|
||||||
if(G_UNLIKELY(!mimeType_)) {
|
if(G_UNLIKELY(!mimeType_)) {
|
||||||
@ -211,7 +214,7 @@ _file_is_symlink:
|
|||||||
g_key_file_free(kf);
|
g_key_file_free(kf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!icon_) {
|
if(!icon_) {
|
||||||
/* try file-specific icon first */
|
/* try file-specific icon first */
|
||||||
gicon = g_file_info_get_icon(inf.get());
|
gicon = g_file_info_get_icon(inf.get());
|
||||||
@ -246,7 +249,11 @@ _file_is_symlink:
|
|||||||
atime_ = g_file_info_get_attribute_uint64(inf.get(), G_FILE_ATTRIBUTE_TIME_ACCESS);
|
atime_ = g_file_info_get_attribute_uint64(inf.get(), G_FILE_ATTRIBUTE_TIME_ACCESS);
|
||||||
ctime_ = g_file_info_get_attribute_uint64(inf.get(), G_FILE_ATTRIBUTE_TIME_CHANGED);
|
ctime_ = g_file_info_get_attribute_uint64(inf.get(), G_FILE_ATTRIBUTE_TIME_CHANGED);
|
||||||
isHidden_ = g_file_info_get_is_hidden(inf.get());
|
isHidden_ = g_file_info_get_is_hidden(inf.get());
|
||||||
isBackup_ = g_file_info_get_is_backup(inf.get());
|
// g_file_info_get_is_backup() does not cover ".bak" and ".old".
|
||||||
|
// NOTE: Here, dispName_ is not modified for desktop entries yet.
|
||||||
|
isBackup_ = g_file_info_get_is_backup(inf.get())
|
||||||
|
|| dispName_.endsWith(QLatin1String(".bak"))
|
||||||
|
|| dispName_.endsWith(QLatin1String(".old"));
|
||||||
isNameChangeable_ = true; /* GVFS tends to ignore this attribute */
|
isNameChangeable_ = true; /* GVFS tends to ignore this attribute */
|
||||||
isIconChangeable_ = isHiddenChangeable_ = false;
|
isIconChangeable_ = isHiddenChangeable_ = false;
|
||||||
if(g_file_info_has_attribute(inf.get(), G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME)) {
|
if(g_file_info_has_attribute(inf.get(), G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME)) {
|
||||||
@ -326,7 +333,31 @@ bool FileInfo::canThumbnail() const {
|
|||||||
|
|
||||||
/* full path of the file is required by this function */
|
/* full path of the file is required by this function */
|
||||||
bool FileInfo::isExecutableType() const {
|
bool FileInfo::isExecutableType() const {
|
||||||
if(isText()) { /* g_content_type_can_be_executable reports text files as executables too */
|
if(isDesktopEntry()) {
|
||||||
|
/* treat desktop entries as executables if
|
||||||
|
they are native and have read permission */
|
||||||
|
if(isNative() && (mode_ & (S_IRUSR|S_IRGRP|S_IROTH))) {
|
||||||
|
if(isShortcut() && !target_.empty()) {
|
||||||
|
/* handle shortcuts from desktop to menu entries:
|
||||||
|
first check for entries in /usr/share/applications and such
|
||||||
|
which may be considered as a safe desktop entry path
|
||||||
|
then check if that is a shortcut to a native file
|
||||||
|
otherwise it is a link to a file under menu:// */
|
||||||
|
if (!g_str_has_prefix(target_.c_str(), "/usr/share/")) {
|
||||||
|
auto target = FilePath::fromPathStr(target_.c_str());
|
||||||
|
bool is_native = target.isNative();
|
||||||
|
if (is_native) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if(isText()) { /* g_content_type_can_be_executable reports text files as executables too */
|
||||||
/* We don't execute remote files nor files in trash */
|
/* We don't execute remote files nor files in trash */
|
||||||
if(isNative() && (mode_ & (S_IXOTH | S_IXGRP | S_IXUSR))) {
|
if(isNative() && (mode_ & (S_IXOTH | S_IXGRP | S_IXUSR))) {
|
||||||
/* it has executable bits so lets check shell-bang */
|
/* it has executable bits so lets check shell-bang */
|
||||||
|
@ -90,16 +90,16 @@ public:
|
|||||||
return mimeType_;
|
return mimeType_;
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t ctime() const {
|
quint64 ctime() const {
|
||||||
return ctime_;
|
return ctime_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
time_t atime() const {
|
quint64 atime() const {
|
||||||
return atime_;
|
return atime_;
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t mtime() const {
|
quint64 mtime() const {
|
||||||
return mtime_;
|
return mtime_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,7 +163,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isDir() const {
|
bool isDir() const {
|
||||||
return mimeType_->isDir();
|
return S_ISDIR(mode_) || mimeType_->isDir();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNative() const {
|
bool isNative() const {
|
||||||
@ -194,6 +194,10 @@ public:
|
|||||||
return dispName_;
|
return dispName_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString description() const {
|
||||||
|
return QString::fromUtf8(mimeType_ ? mimeType_->desc() : "");
|
||||||
|
}
|
||||||
|
|
||||||
FilePath path() const {
|
FilePath path() const {
|
||||||
return dirPath_ ? dirPath_.child(name_.c_str()) : FilePath::fromPathStr(name_.c_str());
|
return dirPath_ ? dirPath_.child(name_.c_str()) : FilePath::fromPathStr(name_.c_str());
|
||||||
}
|
}
|
||||||
@ -221,9 +225,9 @@ private:
|
|||||||
uid_t uid_;
|
uid_t uid_;
|
||||||
gid_t gid_;
|
gid_t gid_;
|
||||||
uint64_t size_;
|
uint64_t size_;
|
||||||
time_t mtime_;
|
quint64 mtime_;
|
||||||
time_t atime_;
|
quint64 atime_;
|
||||||
time_t ctime_;
|
quint64 ctime_;
|
||||||
|
|
||||||
uint64_t blksize_;
|
uint64_t blksize_;
|
||||||
uint64_t blocks_;
|
uint64_t blocks_;
|
||||||
@ -266,9 +270,10 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// smart pointer to FileInfo objects (once created, FileInfo objects should stay immutable so const is needed here)
|
||||||
|
typedef std::shared_ptr<const FileInfo> FileInfoPtr;
|
||||||
|
|
||||||
typedef std::pair<std::shared_ptr<const FileInfo>, std::shared_ptr<const FileInfo>> FileInfoPair;
|
typedef std::pair<FileInfoPtr, FileInfoPtr> FileInfoPair;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
|
||||||
extern const char gfile_info_query_attribs[];
|
extern const char defaultGFileInfoQueryAttribs[];
|
||||||
|
|
||||||
} // namespace Fm
|
} // namespace Fm
|
||||||
|
|
||||||
|
@ -3,9 +3,10 @@
|
|||||||
|
|
||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
|
||||||
FileInfoJob::FileInfoJob(FilePathList paths, FilePath commonDirPath, const std::shared_ptr<const HashSet>& cutFilesHashSet):
|
FileInfoJob::FileInfoJob(FilePathList paths, FilePathList deletionPaths, FilePath commonDirPath, const std::shared_ptr<const HashSet>& cutFilesHashSet):
|
||||||
Job(),
|
Job(),
|
||||||
paths_{std::move(paths)},
|
paths_{std::move(paths)},
|
||||||
|
deletionPaths_{std::move(deletionPaths)},
|
||||||
commonDirPath_{std::move(commonDirPath)},
|
commonDirPath_{std::move(commonDirPath)},
|
||||||
cutFilesHashSet_{cutFilesHashSet} {
|
cutFilesHashSet_{cutFilesHashSet} {
|
||||||
}
|
}
|
||||||
@ -15,12 +16,13 @@ void FileInfoJob::exec() {
|
|||||||
if(!isCancelled()) {
|
if(!isCancelled()) {
|
||||||
GErrorPtr err;
|
GErrorPtr err;
|
||||||
GFileInfoPtr inf{
|
GFileInfoPtr inf{
|
||||||
g_file_query_info(path.gfile().get(), gfile_info_query_attribs,
|
g_file_query_info(path.gfile().get(), defaultGFileInfoQueryAttribs,
|
||||||
G_FILE_QUERY_INFO_NONE, cancellable().get(), &err),
|
G_FILE_QUERY_INFO_NONE, cancellable().get(), &err),
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
if(!inf)
|
if(!inf) {
|
||||||
return;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Reuse the same dirPath object when the path remains the same (optimize for files in the same dir)
|
// Reuse the same dirPath object when the path remains the same (optimize for files in the same dir)
|
||||||
auto dirPath = commonDirPath_.isValid() ? commonDirPath_ : path.parent();
|
auto dirPath = commonDirPath_.isValid() ? commonDirPath_ : path.parent();
|
||||||
|
@ -13,12 +13,16 @@ class LIBFM_QT_API FileInfoJob : public Job {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit FileInfoJob(FilePathList paths, FilePath commonDirPath = FilePath(), const std::shared_ptr<const HashSet>& cutFilesHashSet = nullptr);
|
explicit FileInfoJob(FilePathList paths, FilePathList deletionPaths = FilePathList(), FilePath commonDirPath = FilePath(), const std::shared_ptr<const HashSet>& cutFilesHashSet = nullptr);
|
||||||
|
|
||||||
const FilePathList& paths() const {
|
const FilePathList& paths() const {
|
||||||
return paths_;
|
return paths_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const FilePathList& deletionPaths() const {
|
||||||
|
return deletionPaths_;
|
||||||
|
}
|
||||||
|
|
||||||
const FileInfoList& files() const {
|
const FileInfoList& files() const {
|
||||||
return results_;
|
return results_;
|
||||||
}
|
}
|
||||||
@ -31,6 +35,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
FilePathList paths_;
|
FilePathList paths_;
|
||||||
|
FilePathList deletionPaths_;
|
||||||
FileInfoList results_;
|
FileInfoList results_;
|
||||||
FilePath commonDirPath_;
|
FilePath commonDirPath_;
|
||||||
const std::shared_ptr<const HashSet> cutFilesHashSet_;
|
const std::shared_ptr<const HashSet> cutFilesHashSet_;
|
||||||
|
@ -4,6 +4,7 @@ namespace Fm {
|
|||||||
|
|
||||||
FileOperationJob::FileOperationJob():
|
FileOperationJob::FileOperationJob():
|
||||||
hasTotalAmount_{false},
|
hasTotalAmount_{false},
|
||||||
|
calcProgressUsingSize_{true},
|
||||||
totalSize_{0},
|
totalSize_{0},
|
||||||
totalCount_{0},
|
totalCount_{0},
|
||||||
finishedSize_{0},
|
finishedSize_{0},
|
||||||
@ -31,6 +32,22 @@ bool FileOperationJob::currentFileProgress(FilePath& path, uint64_t& totalSize,
|
|||||||
return currentFile_.isValid();
|
return currentFile_.isValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double FileOperationJob::progress() const {
|
||||||
|
std::lock_guard<std::mutex> lock{mutex_};
|
||||||
|
double finishedRatio;
|
||||||
|
if(calcProgressUsingSize_) {
|
||||||
|
finishedRatio = totalSize_ > 0 ? double(finishedSize_ + currentFileFinished_) / totalSize_ : 0.0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
finishedRatio = totalCount_ > 0 ? double(finishedCount_) / totalCount_ : 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(finishedRatio > 1.0) {
|
||||||
|
finishedRatio = 1.0;
|
||||||
|
}
|
||||||
|
return finishedRatio;
|
||||||
|
}
|
||||||
|
|
||||||
FileOperationJob::FileExistsAction FileOperationJob::askRename(const FileInfo &src, const FileInfo &dest, FilePath &newDest) {
|
FileOperationJob::FileExistsAction FileOperationJob::askRename(const FileInfo &src, const FileInfo &dest, FilePath &newDest) {
|
||||||
FileExistsAction action = SKIP;
|
FileExistsAction action = SKIP;
|
||||||
Q_EMIT fileExists(src, dest, action, newDest);
|
Q_EMIT fileExists(src, dest, action, newDest);
|
||||||
@ -47,31 +64,37 @@ bool FileOperationJob::finishedAmount(uint64_t& finishedSize, uint64_t& finished
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FileOperationJob::setTotalAmount(uint64_t fileSize, uint64_t fileCount) {
|
void FileOperationJob::setTotalAmount(uint64_t fileSize, uint64_t fileCount) {
|
||||||
std::lock_guard<std::mutex> locl{mutex_};
|
std::lock_guard<std::mutex> lock{mutex_};
|
||||||
hasTotalAmount_ = true;
|
hasTotalAmount_ = true;
|
||||||
totalSize_ = fileSize;
|
totalSize_ = fileSize;
|
||||||
totalCount_ = fileCount;
|
totalCount_ = fileCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileOperationJob::setFinishedAmount(uint64_t finishedSize, uint64_t finishedCount) {
|
void FileOperationJob::setFinishedAmount(uint64_t finishedSize, uint64_t finishedCount) {
|
||||||
std::lock_guard<std::mutex> locl{mutex_};
|
std::lock_guard<std::mutex> lock{mutex_};
|
||||||
finishedSize_ = finishedSize;
|
finishedSize_ = finishedSize;
|
||||||
finishedCount_ = finishedCount;
|
finishedCount_ = finishedCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileOperationJob::addFinishedAmount(uint64_t finishedSize, uint64_t finishedCount) {
|
void FileOperationJob::addFinishedAmount(uint64_t finishedSize, uint64_t finishedCount) {
|
||||||
std::lock_guard<std::mutex> locl{mutex_};
|
std::lock_guard<std::mutex> lock{mutex_};
|
||||||
finishedSize_ += finishedSize;
|
finishedSize_ += finishedSize;
|
||||||
finishedCount_ += finishedCount;
|
finishedCount_ += finishedCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FilePath FileOperationJob::currentFile() const {
|
||||||
|
std::lock_guard<std::mutex> lock{mutex_};
|
||||||
|
auto ret = currentFile_;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void FileOperationJob::setCurrentFile(const FilePath& path) {
|
void FileOperationJob::setCurrentFile(const FilePath& path) {
|
||||||
std::lock_guard<std::mutex> locl{mutex_};
|
std::lock_guard<std::mutex> lock{mutex_};
|
||||||
currentFile_ = path;
|
currentFile_ = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileOperationJob::setCurrentFileProgress(uint64_t totalSize, uint64_t finishedSize) {
|
void FileOperationJob::setCurrentFileProgress(uint64_t totalSize, uint64_t finishedSize) {
|
||||||
std::lock_guard<std::mutex> locl{mutex_};
|
std::lock_guard<std::mutex> lock{mutex_};
|
||||||
currentFileSize_ = totalSize;
|
currentFileSize_ = totalSize;
|
||||||
currentFileFinished_ = finishedSize;
|
currentFileFinished_ = finishedSize;
|
||||||
}
|
}
|
||||||
|
@ -24,12 +24,26 @@ public:
|
|||||||
|
|
||||||
explicit FileOperationJob();
|
explicit FileOperationJob();
|
||||||
|
|
||||||
|
// get total amount of work to do
|
||||||
bool totalAmount(std::uint64_t& fileSize, std::uint64_t& fileCount) const;
|
bool totalAmount(std::uint64_t& fileSize, std::uint64_t& fileCount) const;
|
||||||
|
|
||||||
|
// get currently finished job amount
|
||||||
bool finishedAmount(std::uint64_t& finishedSize, std::uint64_t& finishedCount) const;
|
bool finishedAmount(std::uint64_t& finishedSize, std::uint64_t& finishedCount) const;
|
||||||
|
|
||||||
|
// get the current file
|
||||||
|
FilePath currentFile() const;
|
||||||
|
|
||||||
|
// get progress of the current file
|
||||||
bool currentFileProgress(FilePath& path, std::uint64_t& totalSize, std::uint64_t& finishedSize) const;
|
bool currentFileProgress(FilePath& path, std::uint64_t& totalSize, std::uint64_t& finishedSize) const;
|
||||||
|
|
||||||
|
// is the job calculate progress based on file size or file counts
|
||||||
|
bool calcProgressUsingSize() const {
|
||||||
|
return calcProgressUsingSize_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get currently finished amount (0.0 to 1.0)
|
||||||
|
virtual double progress() const;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
|
||||||
void preparedToRun();
|
void preparedToRun();
|
||||||
@ -55,8 +69,17 @@ protected:
|
|||||||
|
|
||||||
void setCurrentFileProgress(uint64_t totalSize, uint64_t finishedSize);
|
void setCurrentFileProgress(uint64_t totalSize, uint64_t finishedSize);
|
||||||
|
|
||||||
|
void setCalcProgressUsingSize(bool value) {
|
||||||
|
calcProgressUsingSize_ = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::mutex& mutex() {
|
||||||
|
return mutex_;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool hasTotalAmount_;
|
bool hasTotalAmount_;
|
||||||
|
bool calcProgressUsingSize_;
|
||||||
std::uint64_t totalSize_;
|
std::uint64_t totalSize_;
|
||||||
std::uint64_t totalCount_;
|
std::uint64_t totalCount_;
|
||||||
std::uint64_t finishedSize_;
|
std::uint64_t finishedSize_;
|
||||||
|
641
src/core/filetransferjob.cpp
Normal file
641
src/core/filetransferjob.cpp
Normal file
@ -0,0 +1,641 @@
|
|||||||
|
#include "filetransferjob.h"
|
||||||
|
#include "totalsizejob.h"
|
||||||
|
#include "fileinfo_p.h"
|
||||||
|
|
||||||
|
namespace Fm {
|
||||||
|
|
||||||
|
FileTransferJob::FileTransferJob(FilePathList srcPaths, Mode mode):
|
||||||
|
FileOperationJob{},
|
||||||
|
srcPaths_{std::move(srcPaths)},
|
||||||
|
mode_{mode} {
|
||||||
|
}
|
||||||
|
|
||||||
|
FileTransferJob::FileTransferJob(FilePathList srcPaths, FilePathList destPaths, Mode mode):
|
||||||
|
FileTransferJob{std::move(srcPaths), mode} {
|
||||||
|
destPaths_ = std::move(destPaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
FileTransferJob::FileTransferJob(FilePathList srcPaths, const FilePath& destDirPath, Mode mode):
|
||||||
|
FileTransferJob{std::move(srcPaths), mode} {
|
||||||
|
setDestDirPath(destDirPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileTransferJob::setSrcPaths(FilePathList srcPaths) {
|
||||||
|
srcPaths_ = std::move(srcPaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileTransferJob::setDestPaths(FilePathList destPaths) {
|
||||||
|
destPaths_ = std::move(destPaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileTransferJob::setDestDirPath(const FilePath& destDirPath) {
|
||||||
|
destPaths_.clear();
|
||||||
|
destPaths_.reserve(srcPaths_.size());
|
||||||
|
for(const auto& srcPath: srcPaths_) {
|
||||||
|
FilePath destPath;
|
||||||
|
if(mode_ == Mode::LINK && !srcPath.isNative()) {
|
||||||
|
// special handling for URLs
|
||||||
|
auto fullBasename = srcPath.baseName();
|
||||||
|
char* basename = fullBasename.get();
|
||||||
|
char* dname = nullptr;
|
||||||
|
// if we drop URI query onto native filesystem, omit query part
|
||||||
|
if(!srcPath.isNative()) {
|
||||||
|
dname = strchr(basename, '?');
|
||||||
|
}
|
||||||
|
// if basename consist only from query then use first part of it
|
||||||
|
if(dname == basename) {
|
||||||
|
basename++;
|
||||||
|
dname = strchr(basename, '&');
|
||||||
|
}
|
||||||
|
|
||||||
|
CStrPtr _basename;
|
||||||
|
if(dname) {
|
||||||
|
_basename = CStrPtr{g_strndup(basename, dname - basename)};
|
||||||
|
dname = strrchr(_basename.get(), G_DIR_SEPARATOR);
|
||||||
|
g_debug("cutting '%s' to '%s'", basename, dname ? &dname[1] : _basename.get());
|
||||||
|
if(dname) {
|
||||||
|
basename = &dname[1];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
basename = _basename.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
destPath = destDirPath.child(basename);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
destPath = destDirPath.child(srcPath.baseName().get());
|
||||||
|
}
|
||||||
|
destPaths_.emplace_back(std::move(destPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileTransferJob::gfileCopyProgressCallback(goffset current_num_bytes, goffset total_num_bytes, FileTransferJob* _this) {
|
||||||
|
_this->setCurrentFileProgress(total_num_bytes, current_num_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileTransferJob::moveFileSameFs(const FilePath& srcPath, const GFileInfoPtr& srcInfo, FilePath& destPath) {
|
||||||
|
int flags = G_FILE_COPY_ALL_METADATA | G_FILE_COPY_NOFOLLOW_SYMLINKS;
|
||||||
|
GErrorPtr err;
|
||||||
|
bool retry;
|
||||||
|
do {
|
||||||
|
retry = false;
|
||||||
|
err.reset();
|
||||||
|
// do the file operation
|
||||||
|
if(!g_file_move(srcPath.gfile().get(), destPath.gfile().get(), GFileCopyFlags(flags), cancellable().get(),
|
||||||
|
nullptr, this, &err)) {
|
||||||
|
retry = handleError(err, srcPath, srcInfo, destPath, flags);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} while(retry && !isCancelled());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileTransferJob::copyRegularFile(const FilePath& srcPath, const GFileInfoPtr& srcInfo, FilePath& destPath) {
|
||||||
|
int flags = G_FILE_COPY_ALL_METADATA | G_FILE_COPY_NOFOLLOW_SYMLINKS;
|
||||||
|
GErrorPtr err;
|
||||||
|
bool retry;
|
||||||
|
do {
|
||||||
|
retry = false;
|
||||||
|
err.reset();
|
||||||
|
|
||||||
|
// reset progress of the current file (only for copy)
|
||||||
|
auto size = g_file_info_get_size(srcInfo.get());
|
||||||
|
setCurrentFileProgress(size, 0);
|
||||||
|
|
||||||
|
// do the file operation
|
||||||
|
if(!g_file_copy(srcPath.gfile().get(), destPath.gfile().get(), GFileCopyFlags(flags), cancellable().get(),
|
||||||
|
(GFileProgressCallback)&gfileCopyProgressCallback, this, &err)) {
|
||||||
|
retry = handleError(err, srcPath, srcInfo, destPath, flags);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} while(retry && !isCancelled());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileTransferJob::copySpecialFile(const FilePath& srcPath, const GFileInfoPtr& srcInfo, FilePath &destPath) {
|
||||||
|
bool ret = false;
|
||||||
|
// only handle FIFO for local files
|
||||||
|
if(srcPath.isNative() && destPath.isNative()) {
|
||||||
|
auto src_path = srcPath.localPath();
|
||||||
|
struct stat src_st;
|
||||||
|
int r;
|
||||||
|
r = lstat(src_path.get(), &src_st);
|
||||||
|
if(r == 0) {
|
||||||
|
// Handle FIFO on native file systems.
|
||||||
|
if(S_ISFIFO(src_st.st_mode)) {
|
||||||
|
auto dest_path = destPath.localPath();
|
||||||
|
if(mkfifo(dest_path.get(), src_st.st_mode) == 0) {
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// FIXME: how about block device, char device, and socket?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!ret) {
|
||||||
|
GErrorPtr err;
|
||||||
|
g_set_error(&err, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
("Cannot copy file '%s': not supported"),
|
||||||
|
g_file_info_get_display_name(srcInfo.get()));
|
||||||
|
emitError(err, ErrorSeverity::MODERATE);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileTransferJob::copyDirContent(const FilePath& srcPath, GFileInfoPtr srcInfo, FilePath& destPath, bool skip) {
|
||||||
|
bool ret = false;
|
||||||
|
// copy dir content
|
||||||
|
GErrorPtr err;
|
||||||
|
auto enu = GFileEnumeratorPtr{
|
||||||
|
g_file_enumerate_children(srcPath.gfile().get(),
|
||||||
|
defaultGFileInfoQueryAttribs,
|
||||||
|
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||||
|
cancellable().get(), &err),
|
||||||
|
false};
|
||||||
|
if(enu) {
|
||||||
|
int n_children = 0;
|
||||||
|
int n_copied = 0;
|
||||||
|
ret = true;
|
||||||
|
while(!isCancelled()) {
|
||||||
|
err.reset();
|
||||||
|
GFileInfoPtr inf{g_file_enumerator_next_file(enu.get(), cancellable().get(), &err), false};
|
||||||
|
if(inf) {
|
||||||
|
++n_children;
|
||||||
|
const char* name = g_file_info_get_name(inf.get());
|
||||||
|
FilePath childPath = srcPath.child(name);
|
||||||
|
bool child_ret = copyFile(childPath, inf, destPath, name, skip);
|
||||||
|
if(child_ret) {
|
||||||
|
++n_copied;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(err) {
|
||||||
|
// fail to read directory content
|
||||||
|
// NOTE: since we cannot read the source dir, we cannot calculate the progress correctly, either.
|
||||||
|
emitError(err, ErrorSeverity::MODERATE);
|
||||||
|
err.reset();
|
||||||
|
/* ErrorAction::RETRY is not supported here */
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
else { /* EOF is reached */
|
||||||
|
/* all files are successfully copied. */
|
||||||
|
if(isCancelled()) {
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* some files are not copied */
|
||||||
|
if(n_children != n_copied) {
|
||||||
|
/* if the copy actions are skipped deliberately, it's ok */
|
||||||
|
if(!skip) {
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* else job->skip_dir_content is true */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_file_enumerator_close(enu.get(), nullptr, &err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(err) {
|
||||||
|
emitError(err, ErrorSeverity::MODERATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileTransferJob::makeDir(const FilePath& srcPath, GFileInfoPtr srcInfo, FilePath& destPath) {
|
||||||
|
if(isCancelled()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mkdir_done = false;
|
||||||
|
do {
|
||||||
|
GErrorPtr err;
|
||||||
|
mkdir_done = g_file_make_directory_with_parents(destPath.gfile().get(), cancellable().get(), &err);
|
||||||
|
if(!mkdir_done) {
|
||||||
|
if(err->domain == G_IO_ERROR && (err->code == G_IO_ERROR_EXISTS ||
|
||||||
|
err->code == G_IO_ERROR_INVALID_FILENAME ||
|
||||||
|
err->code == G_IO_ERROR_FILENAME_TOO_LONG)) {
|
||||||
|
GFileInfoPtr destInfo = GFileInfoPtr {
|
||||||
|
g_file_query_info(destPath.gfile().get(),
|
||||||
|
defaultGFileInfoQueryAttribs,
|
||||||
|
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||||
|
cancellable().get(), nullptr),
|
||||||
|
false
|
||||||
|
};
|
||||||
|
if(!destInfo) {
|
||||||
|
// FIXME: error handling
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePath newDestPath;
|
||||||
|
FileExistsAction opt = askRename(FileInfo{srcInfo, srcPath.parent()}, FileInfo{destInfo, destPath.parent()}, newDestPath);
|
||||||
|
switch(opt) {
|
||||||
|
case FileOperationJob::RENAME:
|
||||||
|
destPath = std::move(newDestPath);
|
||||||
|
break;
|
||||||
|
case FileOperationJob::SKIP:
|
||||||
|
/* when a dir is skipped, we need to know its total size to calculate correct progress */
|
||||||
|
mkdir_done = true; /* pretend that dir creation succeeded */
|
||||||
|
break;
|
||||||
|
case FileOperationJob::OVERWRITE:
|
||||||
|
mkdir_done = true; /* pretend that dir creation succeeded */
|
||||||
|
break;
|
||||||
|
case FileOperationJob::CANCEL:
|
||||||
|
cancel();
|
||||||
|
return false;
|
||||||
|
case FileOperationJob::SKIP_ERROR: ; /* FIXME */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ErrorAction act = emitError(err, ErrorSeverity::MODERATE);
|
||||||
|
if(act != ErrorAction::RETRY) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while(!mkdir_done && !isCancelled());
|
||||||
|
|
||||||
|
bool chmod_done = false;
|
||||||
|
if(mkdir_done && !isCancelled()) {
|
||||||
|
mode_t mode = g_file_info_get_attribute_uint32(srcInfo.get(), G_FILE_ATTRIBUTE_UNIX_MODE);
|
||||||
|
if(mode) {
|
||||||
|
mode |= (S_IRUSR | S_IWUSR); /* ensure we have rw permission to this file. */
|
||||||
|
do {
|
||||||
|
GErrorPtr err;
|
||||||
|
// chmod the newly created dir properly
|
||||||
|
// if(!fm_job_is_cancelled(fmjob) && !job->skip_dir_content)
|
||||||
|
chmod_done = g_file_set_attribute_uint32(destPath.gfile().get(),
|
||||||
|
G_FILE_ATTRIBUTE_UNIX_MODE,
|
||||||
|
mode, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||||
|
cancellable().get(), &err);
|
||||||
|
if(!chmod_done) {
|
||||||
|
ErrorAction act = emitError(err, ErrorSeverity::MODERATE);
|
||||||
|
if(act != ErrorAction::RETRY) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* FIXME: some filesystems may not support this. */
|
||||||
|
}
|
||||||
|
} while(!chmod_done && !isCancelled());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mkdir_done && chmod_done;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileTransferJob::handleError(GErrorPtr &err, const FilePath &srcPath, const GFileInfoPtr &srcInfo, FilePath &destPath, int& flags) {
|
||||||
|
bool retry = false;
|
||||||
|
/* handle existing files or file name conflict */
|
||||||
|
if(err.domain() == G_IO_ERROR && (err.code() == G_IO_ERROR_EXISTS ||
|
||||||
|
err.code() == G_IO_ERROR_INVALID_FILENAME ||
|
||||||
|
err.code() == G_IO_ERROR_FILENAME_TOO_LONG)) {
|
||||||
|
flags &= ~G_FILE_COPY_OVERWRITE;
|
||||||
|
|
||||||
|
// get info of the existing file
|
||||||
|
GFileInfoPtr destInfo = GFileInfoPtr {
|
||||||
|
g_file_query_info(destPath.gfile().get(),
|
||||||
|
defaultGFileInfoQueryAttribs,
|
||||||
|
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||||
|
cancellable().get(), nullptr),
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
// ask the user to rename or overwrite the existing file
|
||||||
|
if(!isCancelled() && destInfo) {
|
||||||
|
FilePath newDestPath;
|
||||||
|
FileExistsAction opt = askRename(FileInfo{srcInfo, srcPath.parent()},
|
||||||
|
FileInfo{destInfo, destPath.parent()},
|
||||||
|
newDestPath);
|
||||||
|
switch(opt) {
|
||||||
|
case FileOperationJob::RENAME:
|
||||||
|
// try a new file name
|
||||||
|
if(newDestPath.isValid()) {
|
||||||
|
destPath = std::move(newDestPath);
|
||||||
|
// FIXME: handle the error when newDestPath is invalid.
|
||||||
|
}
|
||||||
|
retry = true;
|
||||||
|
break;
|
||||||
|
case FileOperationJob::OVERWRITE:
|
||||||
|
// overwrite existing file
|
||||||
|
flags |= G_FILE_COPY_OVERWRITE;
|
||||||
|
retry = true;
|
||||||
|
err.reset();
|
||||||
|
break;
|
||||||
|
case FileOperationJob::CANCEL:
|
||||||
|
// cancel the whole job.
|
||||||
|
cancel();
|
||||||
|
break;
|
||||||
|
case FileOperationJob::SKIP:
|
||||||
|
// skip current file and don't copy it
|
||||||
|
case FileOperationJob::SKIP_ERROR: ; /* FIXME */
|
||||||
|
retry = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
err.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// show error message
|
||||||
|
if(!isCancelled() && err) {
|
||||||
|
ErrorAction act = emitError(err, ErrorSeverity::MODERATE);
|
||||||
|
err.reset();
|
||||||
|
if(act == ErrorAction::RETRY) {
|
||||||
|
// the user wants retry the operation again
|
||||||
|
retry = true;
|
||||||
|
}
|
||||||
|
const bool is_no_space = (err.domain() == G_IO_ERROR && err.code() == G_IO_ERROR_NO_SPACE);
|
||||||
|
/* FIXME: ask to leave partial content? */
|
||||||
|
if(is_no_space) {
|
||||||
|
// run out of disk space. delete the partial content we copied.
|
||||||
|
g_file_delete(destPath.gfile().get(), cancellable().get(), nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileTransferJob::processPath(const FilePath& srcPath, const FilePath& destDirPath, const char* destFileName) {
|
||||||
|
GErrorPtr err;
|
||||||
|
GFileInfoPtr srcInfo = GFileInfoPtr {
|
||||||
|
g_file_query_info(srcPath.gfile().get(),
|
||||||
|
defaultGFileInfoQueryAttribs,
|
||||||
|
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||||
|
cancellable().get(), &err),
|
||||||
|
false
|
||||||
|
};
|
||||||
|
if(!srcInfo || isCancelled()) {
|
||||||
|
// FIXME: report error
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ret;
|
||||||
|
switch(mode_) {
|
||||||
|
case Mode::MOVE:
|
||||||
|
ret = moveFile(srcPath, srcInfo, destDirPath, destFileName);
|
||||||
|
break;
|
||||||
|
case Mode::COPY: {
|
||||||
|
bool deleteSrc = false;
|
||||||
|
ret = copyFile(srcPath, srcInfo, destDirPath, destFileName, deleteSrc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Mode::LINK:
|
||||||
|
ret = linkFile(srcPath, srcInfo, destDirPath, destFileName);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileTransferJob::moveFile(const FilePath &srcPath, const GFileInfoPtr &srcInfo, const FilePath &destDirPath, const char *destFileName) {
|
||||||
|
setCurrentFile(srcPath);
|
||||||
|
|
||||||
|
GErrorPtr err;
|
||||||
|
GFileInfoPtr destDirInfo = GFileInfoPtr {
|
||||||
|
g_file_query_info(destDirPath.gfile().get(),
|
||||||
|
"id::filesystem",
|
||||||
|
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||||
|
cancellable().get(), &err),
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
if(!destDirInfo || isCancelled()) {
|
||||||
|
// FIXME: report errors
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If src and dest are on the same filesystem, do move.
|
||||||
|
// Exception: if src FS is trash:///, we always do move
|
||||||
|
// Otherwise, do copy & delete src files.
|
||||||
|
auto src_fs = g_file_info_get_attribute_string(srcInfo.get(), "id::filesystem");
|
||||||
|
auto dest_fs = g_file_info_get_attribute_string(destDirInfo.get(), "id::filesystem");
|
||||||
|
bool ret;
|
||||||
|
if(src_fs && dest_fs && (strcmp(src_fs, dest_fs) == 0 || g_str_has_prefix(src_fs, "trash"))) {
|
||||||
|
// src and dest are on the same filesystem
|
||||||
|
auto destPath = destDirPath.child(destFileName);
|
||||||
|
ret = moveFileSameFs(srcPath, srcInfo, destPath);
|
||||||
|
|
||||||
|
// increase current progress
|
||||||
|
// FIXME: it's not appropriate to calculate the progress of move operations using file size
|
||||||
|
// since the time required to move a file is not related to it's file size.
|
||||||
|
auto size = g_file_info_get_size(srcInfo.get());
|
||||||
|
addFinishedAmount(size, 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// cross device/filesystem move: copy & delete
|
||||||
|
ret = copyFile(srcPath, srcInfo, destDirPath, destFileName);
|
||||||
|
// NOTE: do not need to increase progress here since it's done by copyPath().
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileTransferJob::copyFile(const FilePath& srcPath, const GFileInfoPtr& srcInfo, const FilePath& destDirPath, const char* destFileName, bool skip) {
|
||||||
|
setCurrentFile(srcPath);
|
||||||
|
|
||||||
|
auto size = g_file_info_get_size(srcInfo.get());
|
||||||
|
bool success = false;
|
||||||
|
setCurrentFileProgress(size, 0);
|
||||||
|
|
||||||
|
auto destPath = destDirPath.child(destFileName);
|
||||||
|
auto file_type = g_file_info_get_file_type(srcInfo.get());
|
||||||
|
if(!skip) {
|
||||||
|
switch(file_type) {
|
||||||
|
case G_FILE_TYPE_DIRECTORY:
|
||||||
|
success = makeDir(srcPath, srcInfo, destPath);
|
||||||
|
break;
|
||||||
|
case G_FILE_TYPE_SPECIAL:
|
||||||
|
success = copySpecialFile(srcPath, srcInfo, destPath);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
success = copyRegularFile(srcPath, srcInfo, destPath);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // skip the file
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(success) {
|
||||||
|
// finish copying the file
|
||||||
|
addFinishedAmount(size, 1);
|
||||||
|
setCurrentFileProgress(0, 0);
|
||||||
|
|
||||||
|
// recursively copy dir content
|
||||||
|
if(file_type == G_FILE_TYPE_DIRECTORY) {
|
||||||
|
success = copyDirContent(srcPath, srcInfo, destPath, skip);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!skip && success && mode_ == Mode::MOVE) {
|
||||||
|
// delete the source file for cross-filesystem move
|
||||||
|
GErrorPtr err;
|
||||||
|
if(g_file_delete(srcPath.gfile().get(), cancellable().get(), &err)) {
|
||||||
|
// FIXME: add some file size to represent the amount of work need to delete a file
|
||||||
|
addFinishedAmount(1, 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileTransferJob::linkFile(const FilePath &srcPath, const GFileInfoPtr &srcInfo, const FilePath &destDirPath, const char *destFileName) {
|
||||||
|
setCurrentFile(srcPath);
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
|
// cannot create links on non-native filesystems
|
||||||
|
if(!destDirPath.isNative()) {
|
||||||
|
auto msg = tr("Cannot create a link on non-native filesystem");
|
||||||
|
GErrorPtr err{g_error_new_literal(G_IO_ERROR, G_IO_ERROR_FAILED, msg.toUtf8().constData())};
|
||||||
|
emitError(err, ErrorSeverity::CRITICAL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(srcPath.isNative()) {
|
||||||
|
// create symlinks for native files
|
||||||
|
auto destPath = destDirPath.child(destFileName);
|
||||||
|
ret = createSymlink(srcPath, srcInfo, destPath);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// ensure that the dest file has *.desktop filename extension.
|
||||||
|
CStrPtr desktopEntryFileName{g_strconcat(destFileName, ".desktop", nullptr)};
|
||||||
|
auto destPath = destDirPath.child(desktopEntryFileName.get());
|
||||||
|
ret = createShortcut(srcPath, srcInfo, destPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update progress
|
||||||
|
// FIXME: increase the progress by 1 byte is not appropriate
|
||||||
|
addFinishedAmount(1, 1);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileTransferJob::createSymlink(const FilePath &srcPath, const GFileInfoPtr &srcInfo, FilePath &destPath) {
|
||||||
|
bool ret = false;
|
||||||
|
auto src = srcPath.localPath();
|
||||||
|
int flags = 0;
|
||||||
|
GErrorPtr err;
|
||||||
|
bool retry;
|
||||||
|
do {
|
||||||
|
retry = false;
|
||||||
|
if(flags & G_FILE_COPY_OVERWRITE) { // overwrite existing file
|
||||||
|
// creating symlink cannot overwrite existing files directly, so we delete the existing file first.
|
||||||
|
g_file_delete(destPath.gfile().get(), cancellable().get(), nullptr);
|
||||||
|
}
|
||||||
|
if(!g_file_make_symbolic_link(destPath.gfile().get(), src.get(), cancellable().get(), &err)) {
|
||||||
|
retry = handleError(err, srcPath, srcInfo, destPath, flags);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while(!isCancelled() && retry);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileTransferJob::createShortcut(const FilePath &srcPath, const GFileInfoPtr &srcInfo, FilePath &destPath) {
|
||||||
|
bool ret = false;
|
||||||
|
const char* iconName = nullptr;
|
||||||
|
GIcon* icon = g_file_info_get_icon(srcInfo.get());
|
||||||
|
if(icon && G_IS_THEMED_ICON(icon)) {
|
||||||
|
auto iconNames = g_themed_icon_get_names(G_THEMED_ICON(icon));
|
||||||
|
if(iconNames && iconNames[0]) {
|
||||||
|
iconName = iconNames[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CStrPtr srcPathUri;
|
||||||
|
auto uri = g_file_info_get_attribute_string(srcInfo.get(), G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);
|
||||||
|
if(!uri) {
|
||||||
|
srcPathUri = srcPath.uri();
|
||||||
|
uri = srcPathUri.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
CStrPtr srcPathDispName;
|
||||||
|
auto name = g_file_info_get_display_name(srcInfo.get());
|
||||||
|
if(!name) {
|
||||||
|
srcPathDispName = srcPath.displayName();
|
||||||
|
name = srcPathDispName.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
GKeyFile* kf = g_key_file_new();
|
||||||
|
if(kf) {
|
||||||
|
g_key_file_set_string(kf, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_TYPE, "Link");
|
||||||
|
g_key_file_set_string(kf, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NAME, name);
|
||||||
|
if(iconName) {
|
||||||
|
g_key_file_set_string(kf, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_ICON, iconName);
|
||||||
|
}
|
||||||
|
if(uri) {
|
||||||
|
g_key_file_set_string(kf, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_URL, uri);
|
||||||
|
}
|
||||||
|
gsize contentLen;
|
||||||
|
CStrPtr content{g_key_file_to_data(kf, &contentLen, nullptr)};
|
||||||
|
g_key_file_free(kf);
|
||||||
|
|
||||||
|
int flags = 0;
|
||||||
|
if(content) {
|
||||||
|
bool retry;
|
||||||
|
GErrorPtr err;
|
||||||
|
do {
|
||||||
|
retry = false;
|
||||||
|
if(flags & G_FILE_COPY_OVERWRITE) { // overwrite existing file
|
||||||
|
g_file_delete(destPath.gfile().get(), cancellable().get(), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!g_file_replace_contents(destPath.gfile().get(), content.get(), contentLen, nullptr, false, G_FILE_CREATE_NONE, nullptr, cancellable().get(), &err)) {
|
||||||
|
retry = handleError(err, srcPath, srcInfo, destPath, flags);
|
||||||
|
err.reset();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
} while(!isCancelled() && retry);
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FileTransferJob::exec() {
|
||||||
|
// calculate the total size of files to copy
|
||||||
|
auto totalSizeFlags = (mode_ == Mode::COPY ? TotalSizeJob::DEFAULT : TotalSizeJob::PREPARE_MOVE);
|
||||||
|
TotalSizeJob totalSizeJob{srcPaths_, totalSizeFlags};
|
||||||
|
connect(&totalSizeJob, &TotalSizeJob::error, this, &FileTransferJob::error);
|
||||||
|
connect(this, &FileTransferJob::cancelled, &totalSizeJob, &TotalSizeJob::cancel);
|
||||||
|
totalSizeJob.run();
|
||||||
|
if(isCancelled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ready to start
|
||||||
|
setTotalAmount(totalSizeJob.totalSize(), totalSizeJob.fileCount());
|
||||||
|
Q_EMIT preparedToRun();
|
||||||
|
|
||||||
|
if(srcPaths_.size() != destPaths_.size()) {
|
||||||
|
qWarning("error: srcPaths.size() != destPaths.size() when copying files");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy the files
|
||||||
|
for(size_t i = 0; i < srcPaths_.size(); ++i) {
|
||||||
|
if(isCancelled()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const auto& srcPath = srcPaths_[i];
|
||||||
|
const auto& destPath = destPaths_[i];
|
||||||
|
auto destDirPath = destPath.parent();
|
||||||
|
processPath(srcPath, destDirPath, destPath.baseName().get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace Fm
|
58
src/core/filetransferjob.h
Normal file
58
src/core/filetransferjob.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#ifndef FM2_COPYJOB_H
|
||||||
|
#define FM2_COPYJOB_H
|
||||||
|
|
||||||
|
#include "../libfmqtglobals.h"
|
||||||
|
#include "fileoperationjob.h"
|
||||||
|
#include "gioptrs.h"
|
||||||
|
|
||||||
|
namespace Fm {
|
||||||
|
|
||||||
|
class LIBFM_QT_API FileTransferJob : public Fm::FileOperationJob {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum class Mode {
|
||||||
|
COPY,
|
||||||
|
MOVE,
|
||||||
|
LINK
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit FileTransferJob(FilePathList srcPaths, Mode mode = Mode::COPY);
|
||||||
|
explicit FileTransferJob(FilePathList srcPaths, FilePathList destPaths, Mode mode = Mode::COPY);
|
||||||
|
explicit FileTransferJob(FilePathList srcPaths, const FilePath &destDirPath, Mode mode = Mode::COPY);
|
||||||
|
|
||||||
|
void setSrcPaths(FilePathList srcPaths);
|
||||||
|
void setDestPaths(FilePathList destPaths);
|
||||||
|
void setDestDirPath(const FilePath &destDirPath);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void exec() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool processPath(const FilePath& srcPath, const FilePath& destPath, const char *destFileName);
|
||||||
|
bool moveFile(const FilePath &srcPath, const GFileInfoPtr &srcInfo, const FilePath &destDirPath, const char *destFileName);
|
||||||
|
bool copyFile(const FilePath &srcPath, const GFileInfoPtr &srcInfo, const FilePath &destDirPath, const char *destFileName, bool skip = false);
|
||||||
|
bool linkFile(const FilePath &srcPath, const GFileInfoPtr &srcInfo, const FilePath &destDirPath, const char *destFileName);
|
||||||
|
|
||||||
|
bool moveFileSameFs(const FilePath &srcPath, const GFileInfoPtr& srcInfo, FilePath &destPath);
|
||||||
|
bool copyRegularFile(const FilePath &srcPath, const GFileInfoPtr& srcInfo, FilePath &destPath);
|
||||||
|
bool copySpecialFile(const FilePath &srcPath, const GFileInfoPtr& srcInfo, FilePath& destPath);
|
||||||
|
bool copyDirContent(const FilePath &srcPath, GFileInfoPtr srcInfo, FilePath &destPath, bool skip = false);
|
||||||
|
bool makeDir(const FilePath &srcPath, GFileInfoPtr srcInfo, FilePath &destPath);
|
||||||
|
bool createSymlink(const FilePath &srcPath, const GFileInfoPtr& srcInfo, FilePath& destPath);
|
||||||
|
bool createShortcut(const FilePath &srcPath, const GFileInfoPtr& srcInfo, FilePath& destPath);
|
||||||
|
|
||||||
|
bool handleError(GErrorPtr& err, const FilePath &srcPath, const GFileInfoPtr &srcInfo, FilePath &destPath, int& flags);
|
||||||
|
|
||||||
|
static void gfileCopyProgressCallback(goffset current_num_bytes, goffset total_num_bytes, FileTransferJob* _this);
|
||||||
|
|
||||||
|
private:
|
||||||
|
FilePathList srcPaths_;
|
||||||
|
FilePathList destPaths_;
|
||||||
|
Mode mode_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace Fm
|
||||||
|
|
||||||
|
#endif // FM2_COPYJOB_H
|
@ -34,8 +34,8 @@
|
|||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
|
||||||
std::unordered_map<FilePath, std::weak_ptr<Folder>, FilePathHash> Folder::cache_;
|
std::unordered_map<FilePath, std::weak_ptr<Folder>, FilePathHash> Folder::cache_;
|
||||||
FilePath Folder::cutFilesDirPath_;
|
QString Folder::cutFilesDirPath_;
|
||||||
FilePath Folder::lastCutFilesDirPath_;
|
QString Folder::lastCutFilesDirPath_;
|
||||||
std::shared_ptr<const HashSet> Folder::cutFilesHashSet_;
|
std::shared_ptr<const HashSet> Folder::cutFilesHashSet_;
|
||||||
std::mutex Folder::mutex_;
|
std::mutex Folder::mutex_;
|
||||||
|
|
||||||
@ -205,9 +205,11 @@ void Folder::onFileInfoFinished() {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
FileInfoList files_to_add;
|
FileInfoList files_to_add;
|
||||||
|
FileInfoList files_to_delete;
|
||||||
std::vector<FileInfoPair> files_to_update;
|
std::vector<FileInfoPair> files_to_update;
|
||||||
|
|
||||||
const auto& paths = job->paths();
|
const auto& paths = job->paths();
|
||||||
|
const auto& deletionPaths = job->deletionPaths();
|
||||||
const auto& infos = job->files();
|
const auto& infos = job->files();
|
||||||
auto path_it = paths.cbegin();
|
auto path_it = paths.cbegin();
|
||||||
auto info_it = infos.cbegin();
|
auto info_it = infos.cbegin();
|
||||||
@ -218,7 +220,8 @@ void Folder::onFileInfoFinished() {
|
|||||||
if(path == dirPath_) { // got the info for the folder itself.
|
if(path == dirPath_) { // got the info for the folder itself.
|
||||||
dirInfo_ = info;
|
dirInfo_ = info;
|
||||||
}
|
}
|
||||||
else {
|
// add/update the file only if it isn't going to be deleted
|
||||||
|
else if(std::find(deletionPaths.cbegin(), deletionPaths.cend(), path) == deletionPaths.cend()) {
|
||||||
auto it = files_.find(info->name());
|
auto it = files_.find(info->name());
|
||||||
if(it != files_.end()) { // the file already exists, update
|
if(it != files_.end()) { // the file already exists, update
|
||||||
files_to_update.push_back(std::make_pair(it->second, info));
|
files_to_update.push_back(std::make_pair(it->second, info));
|
||||||
@ -235,6 +238,18 @@ void Folder::onFileInfoFinished() {
|
|||||||
if(!files_to_update.empty()) {
|
if(!files_to_update.empty()) {
|
||||||
Q_EMIT filesChanged(files_to_update);
|
Q_EMIT filesChanged(files_to_update);
|
||||||
}
|
}
|
||||||
|
// deletion should be done now, after the info job is processed
|
||||||
|
for(const auto &path: deletionPaths) {
|
||||||
|
auto name = path.baseName();
|
||||||
|
auto it = files_.find(name.get());
|
||||||
|
if(it != files_.end()) {
|
||||||
|
files_to_delete.push_back(it->second);
|
||||||
|
files_.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!files_to_delete.empty()) {
|
||||||
|
Q_EMIT filesRemoved(files_to_delete);
|
||||||
|
}
|
||||||
Q_EMIT contentChanged();
|
Q_EMIT contentChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,14 +265,16 @@ void Folder::processPendingChanges() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FileInfoJob* info_job = nullptr;
|
FileInfoJob* info_job = nullptr;
|
||||||
if(!paths_to_update.empty() || !paths_to_add.empty()) {
|
if(!paths_to_update.empty() || !paths_to_add.empty() || !paths_to_del.empty()) {
|
||||||
FilePathList paths;
|
FilePathList paths, deletionPaths;
|
||||||
paths.insert(paths.end(), paths_to_add.cbegin(), paths_to_add.cend());
|
paths.insert(paths.end(), paths_to_add.cbegin(), paths_to_add.cend());
|
||||||
paths.insert(paths.end(), paths_to_update.cbegin(), paths_to_update.cend());
|
paths.insert(paths.end(), paths_to_update.cbegin(), paths_to_update.cend());
|
||||||
info_job = new FileInfoJob{paths, dirPath_,
|
deletionPaths.insert(deletionPaths.end(), paths_to_del.cbegin(), paths_to_del.cend());
|
||||||
hasCutFiles() ? cutFilesHashSet_ : nullptr};
|
info_job = new FileInfoJob{paths, deletionPaths, dirPath_,
|
||||||
|
hasCutFiles() ? cutFilesHashSet_ : nullptr};
|
||||||
paths_to_update.clear();
|
paths_to_update.clear();
|
||||||
paths_to_add.clear();
|
paths_to_add.clear();
|
||||||
|
paths_to_del.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(info_job) {
|
if(info_job) {
|
||||||
@ -275,21 +292,6 @@ void Folder::processPendingChanges() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!paths_to_del.empty()) {
|
|
||||||
FileInfoList deleted_files;
|
|
||||||
for(const auto &path: paths_to_del) {
|
|
||||||
auto name = path.baseName();
|
|
||||||
auto it = files_.find(name.get());
|
|
||||||
if(it != files_.end()) {
|
|
||||||
deleted_files.push_back(it->second);
|
|
||||||
files_.erase(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Q_EMIT filesRemoved(deleted_files);
|
|
||||||
Q_EMIT contentChanged();
|
|
||||||
paths_to_del.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(pending_change_notify) {
|
if(pending_change_notify) {
|
||||||
Q_EMIT changed();
|
Q_EMIT changed();
|
||||||
/* update volume info */
|
/* update volume info */
|
||||||
@ -346,10 +348,10 @@ bool Folder::eventFileAdded(const FilePath &path) {
|
|||||||
bool Folder::eventFileChanged(const FilePath &path) {
|
bool Folder::eventFileChanged(const FilePath &path) {
|
||||||
bool added;
|
bool added;
|
||||||
// G_LOCK(lists);
|
// G_LOCK(lists);
|
||||||
/* make sure that the file is not already queued for changes or
|
/* make sure that the file is not already queued for changes, addition or deletion */
|
||||||
* it's already queued for addition. */
|
|
||||||
if(std::find(paths_to_update.cbegin(), paths_to_update.cend(), path) == paths_to_update.cend()
|
if(std::find(paths_to_update.cbegin(), paths_to_update.cend(), path) == paths_to_update.cend()
|
||||||
&& std::find(paths_to_add.cbegin(), paths_to_add.cend(), path) == paths_to_add.cend()) {
|
&& std::find(paths_to_add.cbegin(), paths_to_add.cend(), path) == paths_to_add.cend()
|
||||||
|
&& std::find(paths_to_del.cbegin(), paths_to_del.cend(), path) == paths_to_del.cend()) {
|
||||||
/* Since this function is called only when a file already exists, even if that file
|
/* Since this function is called only when a file already exists, even if that file
|
||||||
isn't included in "files_" yet, it will be soon due to a previous call to queueUpdate().
|
isn't included in "files_" yet, it will be soon due to a previous call to queueUpdate().
|
||||||
So, here, we should queue it for changes regardless of what "files_" may contain. */
|
So, here, we should queue it for changes regardless of what "files_" may contain. */
|
||||||
@ -367,14 +369,19 @@ bool Folder::eventFileChanged(const FilePath &path) {
|
|||||||
void Folder::eventFileDeleted(const FilePath& path) {
|
void Folder::eventFileDeleted(const FilePath& path) {
|
||||||
// qDebug() << "delete " << path.baseName().get();
|
// qDebug() << "delete " << path.baseName().get();
|
||||||
// G_LOCK(lists);
|
// G_LOCK(lists);
|
||||||
if(files_.find(path.baseName().get()) != files_.cend()) {
|
/* Queue the file for deletion only if it is not in the addition queue but
|
||||||
|
if it is, remove it from that queue instead of queueing it for deletion.
|
||||||
|
Moreover, as was the case with eventFileChanged(), here too queueing
|
||||||
|
should be done regardless of what "files_" may contain. */
|
||||||
|
if(std::find(paths_to_add.cbegin(), paths_to_add.cend(), path) == paths_to_add.cend()) {
|
||||||
if(std::find(paths_to_del.cbegin(), paths_to_del.cend(), path) == paths_to_del.cend()) {
|
if(std::find(paths_to_del.cbegin(), paths_to_del.cend(), path) == paths_to_del.cend()) {
|
||||||
paths_to_del.push_back(path);
|
paths_to_del.push_back(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* if the file is already queued for addition or update, that operation
|
else {
|
||||||
will be just a waste, therefore cancel it right now */
|
paths_to_add.erase(std::remove(paths_to_add.begin(), paths_to_add.end(), path), paths_to_add.cend());
|
||||||
paths_to_add.erase(std::remove(paths_to_add.begin(), paths_to_add.end(), path), paths_to_add.cend());
|
}
|
||||||
|
/* the update queue should be canceled for a file that is going to be deleted */
|
||||||
paths_to_update.erase(std::remove(paths_to_update.begin(), paths_to_update.end(), path), paths_to_update.cend());
|
paths_to_update.erase(std::remove(paths_to_update.begin(), paths_to_update.end(), path), paths_to_update.cend());
|
||||||
queueUpdate();
|
queueUpdate();
|
||||||
// G_UNLOCK(lists);
|
// G_UNLOCK(lists);
|
||||||
@ -451,17 +458,16 @@ void Folder::onFileChangeEvents(GFileMonitor* /*monitor*/, GFile* gf, GFile* /*o
|
|||||||
eventFileDeleted(path);
|
eventFileDeleted(path);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
queueUpdate();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// checks whether there were cut files here
|
// checks whether there were cut files here
|
||||||
// and if there were, invalidates this last cut path
|
// and if there were, invalidates this last cut path
|
||||||
bool Folder::hadCutFilesUnset() {
|
bool Folder::hadCutFilesUnset() {
|
||||||
if(lastCutFilesDirPath_ == dirPath_) {
|
if(lastCutFilesDirPath_ == dirPath_.toString().get()) {
|
||||||
lastCutFilesDirPath_ = FilePath();
|
lastCutFilesDirPath_ = QString();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -470,14 +476,14 @@ bool Folder::hadCutFilesUnset() {
|
|||||||
bool Folder::hasCutFiles() {
|
bool Folder::hasCutFiles() {
|
||||||
return cutFilesHashSet_
|
return cutFilesHashSet_
|
||||||
&& !cutFilesHashSet_->empty()
|
&& !cutFilesHashSet_->empty()
|
||||||
&& cutFilesDirPath_ == dirPath_;
|
&& cutFilesDirPath_ == dirPath_.toString().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Folder::setCutFiles(const std::shared_ptr<const HashSet>& cutFilesHashSet) {
|
void Folder::setCutFiles(const std::shared_ptr<const HashSet>& cutFilesHashSet) {
|
||||||
if(cutFilesHashSet_ && !cutFilesHashSet_->empty()) {
|
if(cutFilesHashSet_ && !cutFilesHashSet_->empty()) {
|
||||||
lastCutFilesDirPath_ = cutFilesDirPath_;
|
lastCutFilesDirPath_ = cutFilesDirPath_;
|
||||||
}
|
}
|
||||||
cutFilesDirPath_ = dirPath_;
|
cutFilesDirPath_ = dirPath_.toString().get();
|
||||||
cutFilesHashSet_ = cutFilesHashSet;
|
cutFilesHashSet_ = cutFilesHashSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,8 +185,8 @@ private:
|
|||||||
bool defer_content_test : 1;
|
bool defer_content_test : 1;
|
||||||
|
|
||||||
static std::unordered_map<FilePath, std::weak_ptr<Folder>, FilePathHash> cache_;
|
static std::unordered_map<FilePath, std::weak_ptr<Folder>, FilePathHash> cache_;
|
||||||
static FilePath cutFilesDirPath_;
|
static QString cutFilesDirPath_;
|
||||||
static FilePath lastCutFilesDirPath_;
|
static QString lastCutFilesDirPath_;
|
||||||
static std::shared_ptr<const HashSet> cutFilesHashSet_;
|
static std::shared_ptr<const HashSet> cutFilesHashSet_;
|
||||||
static std::mutex mutex_;
|
static std::mutex mutex_;
|
||||||
};
|
};
|
||||||
|
@ -5,7 +5,7 @@ namespace Fm {
|
|||||||
|
|
||||||
std::unordered_map<GIcon*, std::shared_ptr<IconInfo>, IconInfo::GIconHash, IconInfo::GIconEqual> IconInfo::cache_;
|
std::unordered_map<GIcon*, std::shared_ptr<IconInfo>, IconInfo::GIconHash, IconInfo::GIconEqual> IconInfo::cache_;
|
||||||
std::mutex IconInfo::mutex_;
|
std::mutex IconInfo::mutex_;
|
||||||
QIcon IconInfo::fallbackQicon_;
|
QList<QIcon> IconInfo::fallbackQicons_;
|
||||||
|
|
||||||
static const char* fallbackIconNames[] = {
|
static const char* fallbackIconNames[] = {
|
||||||
"unknown",
|
"unknown",
|
||||||
@ -15,6 +15,15 @@ static const char* fallbackIconNames[] = {
|
|||||||
nullptr
|
nullptr
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static QIcon getFirst(const QList<QIcon> & icons)
|
||||||
|
{
|
||||||
|
for (const auto & icon : icons) {
|
||||||
|
if (!icon.isNull())
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
return QIcon{};
|
||||||
|
}
|
||||||
|
|
||||||
IconInfo::IconInfo(const char* name):
|
IconInfo::IconInfo(const char* name):
|
||||||
gicon_{g_themed_icon_new(name), false} {
|
gicon_{g_themed_icon_new(name), false} {
|
||||||
}
|
}
|
||||||
@ -50,10 +59,9 @@ std::shared_ptr<const IconInfo> IconInfo::fromGIcon(GIconPtr gicon) {
|
|||||||
|
|
||||||
void IconInfo::updateQIcons() {
|
void IconInfo::updateQIcons() {
|
||||||
std::lock_guard<std::mutex> lock{mutex_};
|
std::lock_guard<std::mutex> lock{mutex_};
|
||||||
fallbackQicon_ = QIcon();
|
|
||||||
for(auto& elem: cache_) {
|
for(auto& elem: cache_) {
|
||||||
auto& info = elem.second;
|
auto& info = elem.second;
|
||||||
info->internalQicon_ = QIcon();
|
info->internalQicons_.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +72,7 @@ QIcon IconInfo::qicon(const bool& transparent) const {
|
|||||||
qicon_ = QIcon(new IconEngine{shared_from_this()});
|
qicon_ = QIcon(new IconEngine{shared_from_this()});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
qicon_ = internalQicon_;
|
qicon_ = getFirst(internalQicons_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,24 +82,21 @@ QIcon IconInfo::qicon(const bool& transparent) const {
|
|||||||
qiconTransparent_ = QIcon(new IconEngine{shared_from_this(), transparent});
|
qiconTransparent_ = QIcon(new IconEngine{shared_from_this(), transparent});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
qiconTransparent_ = internalQicon_;
|
qiconTransparent_ = getFirst(internalQicons_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return !transparent ? qicon_ : qiconTransparent_;
|
return !transparent ? qicon_ : qiconTransparent_;
|
||||||
}
|
}
|
||||||
|
|
||||||
QIcon IconInfo::qiconFromNames(const char* const* names) {
|
QList<QIcon> IconInfo::qiconsFromNames(const char* const* names) {
|
||||||
const gchar* const* name;
|
QList<QIcon> icons;
|
||||||
// qDebug("names: %p", names);
|
// qDebug("names: %p", names);
|
||||||
for(name = names; *name; ++name) {
|
for(const gchar* const* name = names; *name; ++name) {
|
||||||
// qDebug("icon name=%s", *name);
|
// qDebug("icon name=%s", *name);
|
||||||
QIcon qicon = QIcon::fromTheme(*name);
|
icons.push_back(QIcon::fromTheme(*name));
|
||||||
if(!qicon.isNull()) {
|
|
||||||
return qicon;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return QIcon();
|
return icons;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::forward_list<std::shared_ptr<const IconInfo>> IconInfo::emblems() const {
|
std::forward_list<std::shared_ptr<const IconInfo>> IconInfo::emblems() const {
|
||||||
@ -109,30 +114,34 @@ std::forward_list<std::shared_ptr<const IconInfo>> IconInfo::emblems() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QIcon IconInfo::internalQicon() const {
|
QIcon IconInfo::internalQicon() const {
|
||||||
if(Q_UNLIKELY(internalQicon_.isNull())) {
|
QIcon ret_icon;
|
||||||
|
if(Q_UNLIKELY(internalQicons_.isEmpty())) {
|
||||||
GIcon* gicon = gicon_.get();
|
GIcon* gicon = gicon_.get();
|
||||||
if(G_IS_EMBLEMED_ICON(gicon_.get())) {
|
if(G_IS_EMBLEMED_ICON(gicon_.get())) {
|
||||||
gicon = g_emblemed_icon_get_icon(G_EMBLEMED_ICON(gicon));
|
gicon = g_emblemed_icon_get_icon(G_EMBLEMED_ICON(gicon));
|
||||||
}
|
}
|
||||||
if(G_IS_THEMED_ICON(gicon)) {
|
if(G_IS_THEMED_ICON(gicon)) {
|
||||||
const gchar* const* names = g_themed_icon_get_names(G_THEMED_ICON(gicon));
|
const gchar* const* names = g_themed_icon_get_names(G_THEMED_ICON(gicon));
|
||||||
internalQicon_ = qiconFromNames(names);
|
internalQicons_ = qiconsFromNames(names);
|
||||||
}
|
}
|
||||||
else if(G_IS_FILE_ICON(gicon)) {
|
else if(G_IS_FILE_ICON(gicon)) {
|
||||||
GFile* file = g_file_icon_get_file(G_FILE_ICON(gicon));
|
GFile* file = g_file_icon_get_file(G_FILE_ICON(gicon));
|
||||||
CStrPtr fpath{g_file_get_path(file)};
|
CStrPtr fpath{g_file_get_path(file)};
|
||||||
internalQicon_ = QIcon(fpath.get());
|
internalQicons_.push_back(QIcon(fpath.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// fallback to default icon
|
|
||||||
if(Q_UNLIKELY(internalQicon_.isNull())) {
|
|
||||||
if(Q_UNLIKELY(fallbackQicon_.isNull())) {
|
|
||||||
fallbackQicon_ = qiconFromNames(fallbackIconNames);
|
|
||||||
}
|
|
||||||
internalQicon_ = fallbackQicon_;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return internalQicon_;
|
|
||||||
|
ret_icon = getFirst(internalQicons_);
|
||||||
|
|
||||||
|
// fallback to default icon
|
||||||
|
if(Q_UNLIKELY(ret_icon.isNull())) {
|
||||||
|
if(Q_UNLIKELY(fallbackQicons_.isEmpty())) {
|
||||||
|
fallbackQicons_ = qiconsFromNames(fallbackIconNames);
|
||||||
|
}
|
||||||
|
ret_icon = getFirst(fallbackQicons_);
|
||||||
|
}
|
||||||
|
return ret_icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Fm
|
} // namespace Fm
|
||||||
|
@ -77,7 +77,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static QIcon qiconFromNames(const char* const* names);
|
static QList<QIcon> qiconsFromNames(const char* const* names);
|
||||||
|
|
||||||
// actual QIcon loaded by QIcon::fromTheme
|
// actual QIcon loaded by QIcon::fromTheme
|
||||||
QIcon internalQicon() const;
|
QIcon internalQicon() const;
|
||||||
@ -98,11 +98,11 @@ private:
|
|||||||
GIconPtr gicon_;
|
GIconPtr gicon_;
|
||||||
mutable QIcon qicon_;
|
mutable QIcon qicon_;
|
||||||
mutable QIcon qiconTransparent_;
|
mutable QIcon qiconTransparent_;
|
||||||
mutable QIcon internalQicon_;
|
mutable QList<QIcon> internalQicons_;
|
||||||
|
|
||||||
static std::unordered_map<GIcon*, std::shared_ptr<IconInfo>, GIconHash, GIconEqual> cache_;
|
static std::unordered_map<GIcon*, std::shared_ptr<IconInfo>, GIconHash, GIconEqual> cache_;
|
||||||
static std::mutex mutex_;
|
static std::mutex mutex_;
|
||||||
static QIcon fallbackQicon_;
|
static QList<QIcon> fallbackQicons_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Fm
|
} // namespace Fm
|
||||||
|
130
src/core/templates.cpp
Normal file
130
src/core/templates.cpp
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
#include "templates.h"
|
||||||
|
#include "gioptrs.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace Fm {
|
||||||
|
|
||||||
|
std::weak_ptr<Templates> Templates::globalInstance_;
|
||||||
|
|
||||||
|
TemplateItem::TemplateItem(std::shared_ptr<const FileInfo> file): fileInfo_{file} {
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePath TemplateItem::filePath() const {
|
||||||
|
auto& target = fileInfo_->target();
|
||||||
|
if(fileInfo_->isDesktopEntry() && !target.empty()) {
|
||||||
|
if(target[0] == '/') { // target is an absolute path
|
||||||
|
return FilePath::fromLocalPath(target.c_str());
|
||||||
|
}
|
||||||
|
else { // resolve relative path
|
||||||
|
return fileInfo_->dirPath().relativePath(target.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fileInfo_->path();
|
||||||
|
}
|
||||||
|
|
||||||
|
Templates::Templates() : QObject() {
|
||||||
|
auto* data_dirs = g_get_system_data_dirs();
|
||||||
|
// system-wide template dirs
|
||||||
|
for(auto data_dir = data_dirs; *data_dir; ++data_dir) {
|
||||||
|
CStrPtr dir_name{g_build_filename(*data_dir, "templates", nullptr)};
|
||||||
|
addTemplateDir(dir_name.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
// user-specific template dir
|
||||||
|
CStrPtr dir_name{g_build_filename(g_get_user_data_dir(), "templates", nullptr)};
|
||||||
|
addTemplateDir(dir_name.get());
|
||||||
|
|
||||||
|
// $XDG_TEMPLATES_DIR (FIXME: this might change at runtime)
|
||||||
|
const gchar *special_dir = g_get_user_special_dir(G_USER_DIRECTORY_TEMPLATES);
|
||||||
|
if (special_dir) {
|
||||||
|
addTemplateDir(special_dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<Templates> Templates::globalInstance() {
|
||||||
|
auto templates = globalInstance_.lock();
|
||||||
|
if(!templates) {
|
||||||
|
templates = make_shared<Templates>();
|
||||||
|
globalInstance_ = templates;
|
||||||
|
}
|
||||||
|
return templates;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Templates::addTemplateDir(const char* dirPathName) {
|
||||||
|
auto dir_path = FilePath::fromLocalPath(dirPathName);
|
||||||
|
if(dir_path.isValid()) {
|
||||||
|
auto folder = Folder::fromPath(dir_path);
|
||||||
|
connect(folder.get(), &Folder::filesAdded, this, &Templates::onFilesAdded);
|
||||||
|
connect(folder.get(), &Folder::filesChanged, this, &Templates::onFilesChanged);
|
||||||
|
connect(folder.get(), &Folder::filesRemoved, this, &Templates::onFilesRemoved);
|
||||||
|
connect(folder.get(), &Folder::removed, this, &Templates::onTemplateDirRemoved);
|
||||||
|
templateFolders_.emplace_back(std::move(folder));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Templates::onFilesAdded(FileInfoList& addedFiles) {
|
||||||
|
for(auto& file : addedFiles) {
|
||||||
|
// FIXME: we do not support subdirs right now (only XFCE supports this)
|
||||||
|
if(file->isHidden() || file->isDir()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
items_.emplace_back(std::make_shared<TemplateItem>(file));
|
||||||
|
// emit a signal for the addition
|
||||||
|
Q_EMIT itemAdded(items_.back());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Templates::onFilesChanged(std::vector<FileInfoPair>& changePairs) {
|
||||||
|
for(auto& change: changePairs) {
|
||||||
|
auto& old_file = change.first;
|
||||||
|
auto& new_file = change.second;
|
||||||
|
auto it = std::find_if(items_.begin(), items_.end(), [&](const std::shared_ptr<TemplateItem>& item) {
|
||||||
|
return item->fileInfo() == old_file;
|
||||||
|
});
|
||||||
|
if(it != items_.end()) {
|
||||||
|
// emit a signal for the change
|
||||||
|
auto old = *it;
|
||||||
|
*it = std::make_shared<TemplateItem>(new_file);
|
||||||
|
Q_EMIT itemChanged(old, *it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Templates::onFilesRemoved(FileInfoList& removedFiles) {
|
||||||
|
for(auto& file : removedFiles) {
|
||||||
|
auto filePath = file->path();
|
||||||
|
auto it = std::remove_if(items_.begin(), items_.end(), [&](const std::shared_ptr<TemplateItem>& item) {
|
||||||
|
return item->fileInfo() == file;
|
||||||
|
});
|
||||||
|
for(auto removed_it = it; it != items_.end(); ++it) {
|
||||||
|
// emit a signal for the removal
|
||||||
|
Q_EMIT itemRemoved(*removed_it);
|
||||||
|
}
|
||||||
|
items_.erase(it, items_.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Templates::onTemplateDirRemoved() {
|
||||||
|
// the whole template dir is removed
|
||||||
|
auto folder = static_cast<Folder*>(sender());
|
||||||
|
if(!folder) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto dirPath = folder->path();
|
||||||
|
|
||||||
|
// remote all files under this dir
|
||||||
|
auto it = std::remove_if(items_.begin(), items_.end(), [&](const std::shared_ptr<TemplateItem>& item) {
|
||||||
|
return dirPath.isPrefixOf(item->filePath());
|
||||||
|
});
|
||||||
|
for(auto removed_it = it; it != items_.end(); ++it) {
|
||||||
|
// emit a signal for the removal
|
||||||
|
Q_EMIT itemRemoved(*removed_it);
|
||||||
|
}
|
||||||
|
items_.erase(it, items_.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Fm
|
100
src/core/templates.h
Normal file
100
src/core/templates.h
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#ifndef TEMPLATES_H
|
||||||
|
#define TEMPLATES_H
|
||||||
|
|
||||||
|
#include "../libfmqtglobals.h"
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include "folder.h"
|
||||||
|
#include "fileinfo.h"
|
||||||
|
#include "mimetype.h"
|
||||||
|
#include "iconinfo.h"
|
||||||
|
|
||||||
|
namespace Fm {
|
||||||
|
|
||||||
|
class LIBFM_QT_API TemplateItem {
|
||||||
|
public:
|
||||||
|
explicit TemplateItem(std::shared_ptr<const FileInfo> fileInfo);
|
||||||
|
|
||||||
|
QString displayName() const {
|
||||||
|
return fileInfo_->displayName();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& name() const {
|
||||||
|
return fileInfo_->name();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const IconInfo> icon() const {
|
||||||
|
return fileInfo_->icon();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const FileInfo> fileInfo() const {
|
||||||
|
return fileInfo_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const MimeType> mimeType() const {
|
||||||
|
return fileInfo_->mimeType();
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePath filePath() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<const FileInfo> fileInfo_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class LIBFM_QT_API Templates : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit Templates();
|
||||||
|
|
||||||
|
// FIXME: the first call to this method will get no templates since dir loading is in progress.
|
||||||
|
static std::shared_ptr<Templates> globalInstance();
|
||||||
|
|
||||||
|
void forEachItem(std::function<void (const std::shared_ptr<const TemplateItem>&)> func) const {
|
||||||
|
for(const auto& item : items_) {
|
||||||
|
func(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<const TemplateItem>> items() const {
|
||||||
|
std::vector<std::shared_ptr<const TemplateItem>> tmp_items;
|
||||||
|
for(auto& item: items_) {
|
||||||
|
tmp_items.emplace_back(item);
|
||||||
|
}
|
||||||
|
return tmp_items;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasTemplates() const {
|
||||||
|
return !items_.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void itemAdded(const std::shared_ptr<const TemplateItem>& item);
|
||||||
|
|
||||||
|
void itemChanged(const std::shared_ptr<const TemplateItem>& oldItem, const std::shared_ptr<const TemplateItem>& newItem);
|
||||||
|
|
||||||
|
void itemRemoved(const std::shared_ptr<const TemplateItem>& item);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void addTemplateDir(const char* dirPathName);
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void onFilesAdded(FileInfoList& addedFiles);
|
||||||
|
|
||||||
|
void onFilesChanged(std::vector<FileInfoPair>& changePairs);
|
||||||
|
|
||||||
|
void onFilesRemoved(FileInfoList& removedFiles);
|
||||||
|
|
||||||
|
void onTemplateDirRemoved();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::shared_ptr<TemplateItem>> items_;
|
||||||
|
std::vector<std::shared_ptr<Folder>> templateFolders_;
|
||||||
|
static std::weak_ptr<Templates> globalInstance_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Fm
|
||||||
|
|
||||||
|
#endif // TEMPLATES_H
|
@ -21,7 +21,7 @@ CStrPtr Thumbnailer::commandForUri(const char* uri, const char* output_file, gui
|
|||||||
/* FIXME: how to handle TryExec? */
|
/* FIXME: how to handle TryExec? */
|
||||||
|
|
||||||
/* parse the command line and do required substitutions according to:
|
/* parse the command line and do required substitutions according to:
|
||||||
* http://developer.gnome.org/integration-guide/stable/thumbnailer.html.en
|
* https://developer.gnome.org/integration-guide/stable/thumbnailer.html.en
|
||||||
*/
|
*/
|
||||||
GString* cmd_line = g_string_sized_new(1024);
|
GString* cmd_line = g_string_sized_new(1024);
|
||||||
const char* p;
|
const char* p;
|
||||||
@ -119,16 +119,17 @@ void Thumbnailer::loadAll() {
|
|||||||
CStrPtr file_path{g_build_filename(dir_path, "thumbnailers", base_name.c_str(), nullptr)};
|
CStrPtr file_path{g_build_filename(dir_path, "thumbnailers", base_name.c_str(), nullptr)};
|
||||||
if(g_key_file_load_from_file(kf, file_path.get(), G_KEY_FILE_NONE, nullptr)) {
|
if(g_key_file_load_from_file(kf, file_path.get(), G_KEY_FILE_NONE, nullptr)) {
|
||||||
auto thumbnailer = std::make_shared<Thumbnailer>(base_name.c_str(), kf);
|
auto thumbnailer = std::make_shared<Thumbnailer>(base_name.c_str(), kf);
|
||||||
char** mime_types = g_key_file_get_string_list(kf, "Thumbnailer Entry", "MimeType", nullptr, nullptr);
|
if(thumbnailer->exec_) {
|
||||||
if(mime_types && thumbnailer->exec_) {
|
char** mime_types = g_key_file_get_string_list(kf, "Thumbnailer Entry", "MimeType", nullptr, nullptr);
|
||||||
for(char** name = mime_types; *name; ++name) {
|
if(mime_types) {
|
||||||
auto mime_type = MimeType::fromName(*name);
|
for(char** name = mime_types; *name; ++name) {
|
||||||
if(mime_type) {
|
auto mime_type = MimeType::fromName(*name);
|
||||||
thumbnailer->mimeTypes_.push_back(mime_type);
|
if(mime_type) {
|
||||||
std::const_pointer_cast<MimeType>(mime_type)->addThumbnailer(thumbnailer);
|
std::const_pointer_cast<MimeType>(mime_type)->addThumbnailer(thumbnailer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
g_strfreev(mime_types);
|
||||||
}
|
}
|
||||||
g_strfreev(mime_types);
|
|
||||||
}
|
}
|
||||||
allThumbnailers_.push_back(std::move(thumbnailer));
|
allThumbnailers_.push_back(std::move(thumbnailer));
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ private:
|
|||||||
CStrPtr id_;
|
CStrPtr id_;
|
||||||
CStrPtr try_exec_; /* FIXME: is this useful? */
|
CStrPtr try_exec_; /* FIXME: is this useful? */
|
||||||
CStrPtr exec_;
|
CStrPtr exec_;
|
||||||
std::vector<std::shared_ptr<const MimeType>> mimeTypes_;
|
//std::vector<std::shared_ptr<const MimeType>> mimeTypes_;
|
||||||
|
|
||||||
static std::mutex mutex_;
|
static std::mutex mutex_;
|
||||||
static std::vector<std::shared_ptr<Thumbnailer>> allThumbnailers_;
|
static std::vector<std::shared_ptr<Thumbnailer>> allThumbnailers_;
|
||||||
|
@ -120,7 +120,7 @@ bool ThumbnailJob::isSupportedImageType(const std::shared_ptr<const MimeType>& m
|
|||||||
|
|
||||||
bool ThumbnailJob::isThumbnailOutdated(const std::shared_ptr<const FileInfo>& file, const QImage &thumbnail) const {
|
bool ThumbnailJob::isThumbnailOutdated(const std::shared_ptr<const FileInfo>& file, const QImage &thumbnail) const {
|
||||||
QString thumb_mtime = thumbnail.text("Thumb::MTime");
|
QString thumb_mtime = thumbnail.text("Thumb::MTime");
|
||||||
return (thumb_mtime.isEmpty() || thumb_mtime.toInt() != file->mtime());
|
return (thumb_mtime.isEmpty() || thumb_mtime.toULongLong() != file->mtime());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ThumbnailJob::readJpegExif(GInputStream *stream, QImage& thumbnail, int& rotate_degrees) {
|
bool ThumbnailJob::readJpegExif(GInputStream *stream, QImage& thumbnail, int& rotate_degrees) {
|
||||||
@ -140,7 +140,7 @@ bool ThumbnailJob::readJpegExif(GInputStream *stream, QImage& thumbnail, int& ro
|
|||||||
exif_loader_unref(exif_loader);
|
exif_loader_unref(exif_loader);
|
||||||
if(exif_data) {
|
if(exif_data) {
|
||||||
/* reference for EXIF orientation tag:
|
/* reference for EXIF orientation tag:
|
||||||
* http://www.impulseadventure.com/photo/exif-orientation.html */
|
* https://www.impulseadventure.com/photo/exif-orientation.html */
|
||||||
ExifEntry* orient_ent = exif_data_get_entry(exif_data, EXIF_TAG_ORIENTATION);
|
ExifEntry* orient_ent = exif_data_get_entry(exif_data, EXIF_TAG_ORIENTATION);
|
||||||
if(orient_ent) { /* orientation flag found in EXIF */
|
if(orient_ent) { /* orientation flag found in EXIF */
|
||||||
gushort orient;
|
gushort orient;
|
||||||
|
@ -61,37 +61,34 @@ _retry_query_info:
|
|||||||
/* prepare for moving across different devices */
|
/* prepare for moving across different devices */
|
||||||
if(flags_ & PREPARE_MOVE) {
|
if(flags_ & PREPARE_MOVE) {
|
||||||
fs_id = g_file_info_get_attribute_string(inf.get(), G_FILE_ATTRIBUTE_ID_FILESYSTEM);
|
fs_id = g_file_info_get_attribute_string(inf.get(), G_FILE_ATTRIBUTE_ID_FILESYSTEM);
|
||||||
fs_id = g_intern_string(fs_id);
|
if(fs_id && dest_fs_id && (strcmp(fs_id, dest_fs_id) == 0 || g_str_has_prefix(fs_id, "trash"))) {
|
||||||
if(g_strcmp0(fs_id, dest_fs_id) != 0) {
|
// same filesystem or move from trash:///
|
||||||
|
descend = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
/* files on different device requires an additional 'delete' for the source file. */
|
/* files on different device requires an additional 'delete' for the source file. */
|
||||||
++totalSize_; /* this is for the additional delete */
|
++totalSize_; /* this is for the additional delete */
|
||||||
++totalOndiskSize_;
|
++totalOndiskSize_;
|
||||||
++fileCount_;
|
++fileCount_;
|
||||||
}
|
descend = true;
|
||||||
else {
|
|
||||||
descend = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type == G_FILE_TYPE_DIRECTORY) {
|
if(type == G_FILE_TYPE_DIRECTORY) {
|
||||||
#if 0
|
|
||||||
FmPath* fm_path = fm_path_new_for_gfile(gf);
|
|
||||||
/* check if we need to decends into the dir. */
|
/* check if we need to decends into the dir. */
|
||||||
/* trash:/// doesn't support deleting files recursively */
|
/* trash:/// doesn't support deleting files recursively (but we want to descend into trash root "trash:///" */
|
||||||
if(flags & PREPARE_DELETE && fm_path_is_trash(fm_path) && ! fm_path_is_trash_root(fm_path)) {
|
if(flags_ & PREPARE_DELETE && path.hasUriScheme("trash") && path.baseName()[0] != '/') {
|
||||||
descend = false;
|
descend = false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* only descends into files on the same filesystem */
|
/* only descends into files on the same filesystem */
|
||||||
if(flags & FM_DC_JOB_SAME_FS) {
|
if(flags_ & SAME_FS) {
|
||||||
fs_id = g_file_info_get_attribute_string(inf, G_FILE_ATTRIBUTE_ID_FILESYSTEM);
|
fs_id = g_file_info_get_attribute_string(inf.get(), G_FILE_ATTRIBUTE_ID_FILESYSTEM);
|
||||||
descend = (g_strcmp0(fs_id, dest_fs_id) == 0);
|
descend = (g_strcmp0(fs_id, dest_fs_id) == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fm_path_unref(fm_path);
|
|
||||||
#endif
|
|
||||||
inf = nullptr;
|
|
||||||
|
|
||||||
|
inf = nullptr;
|
||||||
if(descend) {
|
if(descend) {
|
||||||
_retry_enum_children:
|
_retry_enum_children:
|
||||||
GErrorPtr err;
|
GErrorPtr err;
|
||||||
|
@ -2,10 +2,9 @@
|
|||||||
|
|
||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
|
||||||
TrashJob::TrashJob(const FilePathList& paths): paths_{paths} {
|
TrashJob::TrashJob(FilePathList paths): paths_{std::move(paths)} {
|
||||||
}
|
// calculate progress using finished file counts rather than their sizes
|
||||||
|
setCalcProgressUsingSize(false);
|
||||||
TrashJob::TrashJob(const FilePathList&& paths): paths_{paths} {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrashJob::exec() {
|
void TrashJob::exec() {
|
||||||
@ -20,33 +19,32 @@ void TrashJob::exec() {
|
|||||||
|
|
||||||
setCurrentFile(path);
|
setCurrentFile(path);
|
||||||
|
|
||||||
for(;;) {
|
// TODO: get parent dir of the current path.
|
||||||
GErrorPtr err;
|
// if there is a Fm::Folder object created for it, block the update for the folder temporarily.
|
||||||
GFile* gf = path.gfile().get();
|
|
||||||
GFileInfoPtr inf{
|
|
||||||
g_file_query_info(gf, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, G_FILE_QUERY_INFO_NONE,
|
|
||||||
cancellable().get(), &err),
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
bool ret = FALSE;
|
for(;;) { // retry the i/o operation on errors
|
||||||
|
auto gf = path.gfile();
|
||||||
|
bool ret = false;
|
||||||
|
// FIXME: do not depend on fm_config
|
||||||
if(fm_config->no_usb_trash) {
|
if(fm_config->no_usb_trash) {
|
||||||
err.reset();
|
GMountPtr mnt{g_file_find_enclosing_mount(gf.get(), nullptr, nullptr), false};
|
||||||
GMountPtr mnt{g_file_find_enclosing_mount(gf, nullptr, &err), false};
|
|
||||||
if(mnt) {
|
if(mnt) {
|
||||||
ret = g_mount_can_unmount(mnt.get()); /* TRUE if it's removable media */
|
ret = g_mount_can_unmount(mnt.get()); /* TRUE if it's removable media */
|
||||||
if(ret) {
|
if(ret) {
|
||||||
unsupportedFiles_.push_back(path);
|
unsupportedFiles_.push_back(path);
|
||||||
|
break; // don't trash the file
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ret) {
|
// move the file to trash
|
||||||
err.reset();
|
GErrorPtr err;
|
||||||
ret = g_file_trash(gf, cancellable().get(), &err);
|
ret = g_file_trash(gf.get(), cancellable().get(), &err);
|
||||||
|
if(ret) { // trash operation succeeded
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if(!ret) {
|
else { // failed
|
||||||
/* if trashing is not supported by the file system */
|
// if trashing is not supported by the file system
|
||||||
if(err.domain() == G_IO_ERROR && err.code() == G_IO_ERROR_NOT_SUPPORTED) {
|
if(err.domain() == G_IO_ERROR && err.code() == G_IO_ERROR_NOT_SUPPORTED) {
|
||||||
unsupportedFiles_.push_back(path);
|
unsupportedFiles_.push_back(path);
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,7 @@ namespace Fm {
|
|||||||
class LIBFM_QT_API TrashJob : public Fm::FileOperationJob {
|
class LIBFM_QT_API TrashJob : public Fm::FileOperationJob {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit TrashJob(const FilePathList& paths);
|
explicit TrashJob(FilePathList paths);
|
||||||
explicit TrashJob(const FilePathList&& paths);
|
|
||||||
|
|
||||||
FilePathList unsupportedFiles() const {
|
FilePathList unsupportedFiles() const {
|
||||||
return unsupportedFiles_;
|
return unsupportedFiles_;
|
||||||
|
@ -1,132 +1,76 @@
|
|||||||
#include "untrashjob.h"
|
#include "untrashjob.h"
|
||||||
|
#include "filetransferjob.h"
|
||||||
|
|
||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
|
||||||
UntrashJob::UntrashJob() {
|
UntrashJob::UntrashJob(FilePathList srcPaths):
|
||||||
|
srcPaths_{std::move(srcPaths)} {
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char trash_query[] =
|
|
||||||
G_FILE_ATTRIBUTE_STANDARD_TYPE","
|
|
||||||
G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME","
|
|
||||||
G_FILE_ATTRIBUTE_STANDARD_NAME","
|
|
||||||
G_FILE_ATTRIBUTE_STANDARD_IS_VIRTUAL","
|
|
||||||
G_FILE_ATTRIBUTE_STANDARD_SIZE","
|
|
||||||
G_FILE_ATTRIBUTE_UNIX_BLOCKS","
|
|
||||||
G_FILE_ATTRIBUTE_UNIX_BLOCK_SIZE","
|
|
||||||
G_FILE_ATTRIBUTE_ID_FILESYSTEM","
|
|
||||||
"trash::orig-path";
|
|
||||||
|
|
||||||
bool UntrashJob::ensure_parent_dir(GFile* orig_path) {
|
|
||||||
GFile* parent = g_file_get_parent(orig_path);
|
|
||||||
gboolean ret = g_file_query_exists(parent, cancellable().get());
|
|
||||||
if(!ret) {
|
|
||||||
GErrorPtr err;
|
|
||||||
_retry_mkdir:
|
|
||||||
if(!g_file_make_directory_with_parents(parent, cancellable().get(), &err)) {
|
|
||||||
if(!isCancelled()) {
|
|
||||||
ErrorAction act = emitError(err, ErrorSeverity::MODERATE);
|
|
||||||
err = nullptr;
|
|
||||||
if(act == ErrorAction::RETRY) {
|
|
||||||
goto _retry_mkdir;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ret = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_object_unref(parent);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void UntrashJob::exec() {
|
void UntrashJob::exec() {
|
||||||
#if 0
|
// preparing for the job
|
||||||
gboolean ret = TRUE;
|
FilePathList validSrcPaths;
|
||||||
GList* l;
|
FilePathList origPaths;
|
||||||
GError* err = nullptr;
|
for(auto& srcPath: srcPaths_) {
|
||||||
FmJob* fmjob = FM_JOB(job);
|
if(isCancelled()) {
|
||||||
job->total = fm_path_list_get_length(job->srcs);
|
break;
|
||||||
fm_file_ops_job_emit_prepared(job);
|
|
||||||
|
|
||||||
l = fm_path_list_peek_head_link(job->srcs);
|
|
||||||
for(; !fm_job_is_cancelled(fmjob) && l; l = l->next) {
|
|
||||||
GFile* gf;
|
|
||||||
GFileInfo* inf;
|
|
||||||
FmPath* path = FM_PATH(l->data);
|
|
||||||
if(!fm_path_is_trash(path)) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
gf = fm_path_to_gfile(path);
|
GErrorPtr err;
|
||||||
_retry_get_orig_path:
|
GFileInfoPtr srcInfo{
|
||||||
inf = g_file_query_info(gf, trash_query, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, fm_job_get_cancellable(fmjob), &err);
|
g_file_query_info(srcPath.gfile().get(),
|
||||||
if(inf) {
|
"trash::orig-path",
|
||||||
const char* orig_path_str = g_file_info_get_attribute_byte_string(inf, "trash::orig-path");
|
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||||
fm_file_ops_job_emit_cur_file(job, g_file_info_get_display_name(inf));
|
cancellable().get(),
|
||||||
|
&err),
|
||||||
|
false
|
||||||
|
};
|
||||||
|
if(srcInfo) {
|
||||||
|
const char* orig_path_str = g_file_info_get_attribute_byte_string(srcInfo.get(), "trash::orig-path");
|
||||||
if(orig_path_str) {
|
if(orig_path_str) {
|
||||||
/* FIXME: what if orig_path_str is a relative path?
|
validSrcPaths.emplace_back(srcPath);
|
||||||
* This is actually allowed by the horrible trash spec. */
|
origPaths.emplace_back(FilePath::fromPathStr(orig_path_str));
|
||||||
GFile* orig_path = fm_file_new_for_commandline_arg(orig_path_str);
|
|
||||||
FmFolder* src_folder = fm_folder_find_by_path(fm_path_get_parent(path));
|
|
||||||
FmPath* orig_fm_path = fm_path_new_for_gfile(orig_path);
|
|
||||||
FmFolder* dst_folder = fm_folder_find_by_path(fm_path_get_parent(orig_fm_path));
|
|
||||||
fm_path_unref(orig_fm_path);
|
|
||||||
/* ensure the existence of parent folder. */
|
|
||||||
if(ensure_parent_dir(fmjob, orig_path)) {
|
|
||||||
ret = _fm_file_ops_job_move_file(job, gf, inf, orig_path, path, src_folder, dst_folder);
|
|
||||||
}
|
|
||||||
if(src_folder) {
|
|
||||||
g_object_unref(src_folder);
|
|
||||||
}
|
|
||||||
if(dst_folder) {
|
|
||||||
g_object_unref(dst_folder);
|
|
||||||
}
|
|
||||||
g_object_unref(orig_path);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ErrorAction act;
|
ErrorAction act;
|
||||||
|
|
||||||
g_set_error(&err, G_IO_ERROR, G_IO_ERROR_FAILED,
|
g_set_error(&err, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
_("Cannot untrash file '%s': original path not known"),
|
tr("Cannot untrash file '%s': original path not known").toUtf8().constData(),
|
||||||
g_file_info_get_display_name(inf));
|
g_file_info_get_display_name(srcInfo.get()));
|
||||||
act = emitError( err, ErrorSeverity::MODERATE);
|
// FIXME: do we need to retry here?
|
||||||
g_clear_error(&err);
|
emitError(err, ErrorSeverity::MODERATE);
|
||||||
if(act == ErrorAction::ABORT) {
|
|
||||||
g_object_unref(inf);
|
|
||||||
g_object_unref(gf);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
g_object_unref(inf);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
char* basename = g_file_get_basename(gf);
|
// FIXME: do we need to retry here?
|
||||||
char* disp = basename ? g_filename_display_name(basename) : nullptr;
|
emitError(err);
|
||||||
g_free(basename);
|
|
||||||
/* FIXME: translate it */
|
|
||||||
fm_file_ops_job_emit_cur_file(job, disp ? disp : "(invalid file)");
|
|
||||||
g_free(disp);
|
|
||||||
|
|
||||||
if(err) {
|
|
||||||
ErrorAction act = emitError( err, ErrorSeverity::MODERATE);
|
|
||||||
g_error_free(err);
|
|
||||||
err = nullptr;
|
|
||||||
if(act == ErrorAction::RETRY) {
|
|
||||||
goto _retry_get_orig_path;
|
|
||||||
}
|
|
||||||
else if(act == ErrorAction::ABORT) {
|
|
||||||
g_object_unref(gf);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
g_object_unref(gf);
|
|
||||||
++job->finished;
|
|
||||||
fm_file_ops_job_emit_percent(job);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
// collected original paths of the trashed files
|
||||||
|
// use the file transfer job to handle the actual file move
|
||||||
|
FileTransferJob fileTransferJob{std::move(validSrcPaths), std::move(origPaths), FileTransferJob::Mode::MOVE};
|
||||||
|
// FIXME:
|
||||||
|
// I'm not sure why specifying Qt::DirectConnection is needed here since the caller & receiver are in the same thread. :-(
|
||||||
|
// However without this, the signals/slots here will cause deadlocks.
|
||||||
|
connect(&fileTransferJob, &FileTransferJob::preparedToRun, this, &UntrashJob::preparedToRun, Qt::DirectConnection);
|
||||||
|
connect(&fileTransferJob, &FileTransferJob::error, this, &UntrashJob::error, Qt::DirectConnection);
|
||||||
|
connect(&fileTransferJob, &FileTransferJob::fileExists, this, &UntrashJob::fileExists, Qt::DirectConnection);
|
||||||
|
|
||||||
|
// cancel the file transfer subjob if the parent job is cancelled
|
||||||
|
connect(this, &UntrashJob::cancelled, &fileTransferJob,
|
||||||
|
[&fileTransferJob]() {
|
||||||
|
if(!fileTransferJob.isCancelled()) {
|
||||||
|
fileTransferJob.cancel();
|
||||||
|
}
|
||||||
|
}, Qt::DirectConnection);
|
||||||
|
|
||||||
|
// cancel the parent job if the file transfer subjob is cancelled
|
||||||
|
connect(&fileTransferJob, &FileTransferJob::cancelled, this,
|
||||||
|
[this]() {
|
||||||
|
if(!isCancelled()) {
|
||||||
|
cancel();
|
||||||
|
}
|
||||||
|
}, Qt::DirectConnection);
|
||||||
|
fileTransferJob.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Fm
|
} // namespace Fm
|
||||||
|
@ -6,15 +6,15 @@
|
|||||||
|
|
||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
|
||||||
class LIBFM_QT_API UntrashJob : public Fm::FileOperationJob {
|
class LIBFM_QT_API UntrashJob : public FileOperationJob {
|
||||||
public:
|
public:
|
||||||
explicit UntrashJob();
|
explicit UntrashJob(FilePathList srcPaths);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void exec() override;
|
void exec() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool ensure_parent_dir(GFile *orig_path);
|
FilePathList srcPaths_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Fm
|
} // namespace Fm
|
||||||
|
@ -19,14 +19,45 @@
|
|||||||
|
|
||||||
#include "createnewmenu.h"
|
#include "createnewmenu.h"
|
||||||
#include "folderview.h"
|
#include "folderview.h"
|
||||||
#include "icontheme.h"
|
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
#include "core/iconinfo.h"
|
#include "core/iconinfo.h"
|
||||||
|
#include "core/templates.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateAction: public QAction {
|
||||||
|
public:
|
||||||
|
TemplateAction(std::shared_ptr<const TemplateItem> item, QObject* parent):
|
||||||
|
QAction(parent) {
|
||||||
|
setTemplateItem(std::move(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::shared_ptr<const TemplateItem> templateItem() const {
|
||||||
|
return templateItem_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTemplateItem(std::shared_ptr<const TemplateItem> item) {
|
||||||
|
templateItem_ = std::move(item);
|
||||||
|
auto mimeType = templateItem_->mimeType();
|
||||||
|
setText(QString("%1 (%2)").arg(templateItem_->displayName()).arg(mimeType->desc()));
|
||||||
|
setIcon(templateItem_->icon()->qicon());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<const TemplateItem> templateItem_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
CreateNewMenu::CreateNewMenu(QWidget* dialogParent, Fm::FilePath dirPath, QWidget* parent):
|
CreateNewMenu::CreateNewMenu(QWidget* dialogParent, Fm::FilePath dirPath, QWidget* parent):
|
||||||
QMenu(parent), dialogParent_(dialogParent), dirPath_(std::move(dirPath)) {
|
QMenu(parent),
|
||||||
|
dialogParent_(dialogParent),
|
||||||
|
dirPath_(std::move(dirPath)),
|
||||||
|
templateSeparator_{nullptr},
|
||||||
|
templates_{Templates::globalInstance()} {
|
||||||
|
|
||||||
QAction* action = new QAction(QIcon::fromTheme("folder-new"), tr("Folder"), this);
|
QAction* action = new QAction(QIcon::fromTheme("folder-new"), tr("Folder"), this);
|
||||||
connect(action, &QAction::triggered, this, &CreateNewMenu::onCreateNewFolder);
|
connect(action, &QAction::triggered, this, &CreateNewMenu::onCreateNewFolder);
|
||||||
addAction(action);
|
addAction(action);
|
||||||
@ -36,27 +67,12 @@ CreateNewMenu::CreateNewMenu(QWidget* dialogParent, Fm::FilePath dirPath, QWidge
|
|||||||
addAction(action);
|
addAction(action);
|
||||||
|
|
||||||
// add more items to "Create New" menu from templates
|
// add more items to "Create New" menu from templates
|
||||||
GList* templates = fm_template_list_all(fm_config->only_user_templates);
|
connect(templates_.get(), &Templates::itemAdded, this, &CreateNewMenu::addTemplateItem);
|
||||||
if(templates) {
|
connect(templates_.get(), &Templates::itemChanged, this, &CreateNewMenu::updateTemplateItem);
|
||||||
addSeparator();
|
connect(templates_.get(), &Templates::itemRemoved, this, &CreateNewMenu::removeTemplateItem);
|
||||||
for(GList* l = templates; l; l = l->next) {
|
templates_->forEachItem([this](const std::shared_ptr<const TemplateItem>& item) {
|
||||||
FmTemplate* templ = (FmTemplate*)l->data;
|
addTemplateItem(item);
|
||||||
/* we support directories differently */
|
});
|
||||||
if(fm_template_is_directory(templ)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
FmMimeType* mime_type = fm_template_get_mime_type(templ);
|
|
||||||
const char* label = fm_template_get_label(templ);
|
|
||||||
QString text = QString("%1 (%2)").arg(QString::fromUtf8(label)).arg(QString::fromUtf8(fm_mime_type_get_desc(mime_type)));
|
|
||||||
FmIcon* icon = fm_template_get_icon(templ);
|
|
||||||
if(!icon) {
|
|
||||||
icon = fm_mime_type_get_icon(mime_type);
|
|
||||||
}
|
|
||||||
QAction* action = addAction(Fm::IconInfo::fromGIcon(G_ICON(icon))->qicon(), text);
|
|
||||||
action->setObjectName(QString::fromUtf8(fm_template_get_name(templ, nullptr)));
|
|
||||||
connect(action, &QAction::triggered, this, &CreateNewMenu::onCreateNew);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateNewMenu::~CreateNewMenu() {
|
CreateNewMenu::~CreateNewMenu() {
|
||||||
@ -75,22 +91,62 @@ void CreateNewMenu::onCreateNewFolder() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CreateNewMenu::onCreateNew() {
|
void CreateNewMenu::onCreateNew() {
|
||||||
QAction* action = static_cast<QAction*>(sender());
|
TemplateAction* action = static_cast<TemplateAction*>(sender());
|
||||||
QByteArray name = action->objectName().toUtf8();
|
if(dirPath_) {
|
||||||
GList* templates = fm_template_list_all(fm_config->only_user_templates);
|
createFileOrFolder(CreateWithTemplate, dirPath_, action->templateItem().get(), dialogParent_);
|
||||||
FmTemplate* templ = nullptr;
|
|
||||||
for(GList* l = templates; l; l = l->next) {
|
|
||||||
FmTemplate* t = (FmTemplate*)l->data;
|
|
||||||
if(name == fm_template_get_name(t, nullptr)) {
|
|
||||||
templ = t;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(templ) { // template found
|
}
|
||||||
if(dirPath_) {
|
|
||||||
createFileOrFolder(CreateWithTemplate, dirPath_, templ, dialogParent_);
|
void CreateNewMenu::addTemplateItem(const std::shared_ptr<const TemplateItem> &item) {
|
||||||
|
if(!templateSeparator_) {
|
||||||
|
templateSeparator_= addSeparator();
|
||||||
|
}
|
||||||
|
auto mimeType = item->mimeType();
|
||||||
|
/* we support directories differently */
|
||||||
|
if(mimeType->isDir()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QAction* action = new TemplateAction{item, this};
|
||||||
|
connect(action, &QAction::triggered, this, &CreateNewMenu::onCreateNew);
|
||||||
|
addAction(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateNewMenu::updateTemplateItem(const std::shared_ptr<const TemplateItem> &oldItem, const std::shared_ptr<const TemplateItem> &newItem) {
|
||||||
|
auto allActions = actions();
|
||||||
|
auto separatorPos = allActions.indexOf(templateSeparator_);
|
||||||
|
// all items after the separator are templates
|
||||||
|
for(auto i = separatorPos + 1; i < allActions.size(); ++i) {
|
||||||
|
auto action = static_cast<TemplateAction*>(allActions[i]);
|
||||||
|
if(action->templateItem() == oldItem) {
|
||||||
|
// update the menu item
|
||||||
|
action->setTemplateItem(newItem);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CreateNewMenu::removeTemplateItem(const std::shared_ptr<const TemplateItem> &item) {
|
||||||
|
if(!templateSeparator_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto allActions = actions();
|
||||||
|
auto separatorPos = allActions.indexOf(templateSeparator_);
|
||||||
|
// all items after the separator are templates
|
||||||
|
for(auto i = separatorPos + 1; i < allActions.size(); ++i) {
|
||||||
|
auto action = static_cast<TemplateAction*>(allActions[i]);
|
||||||
|
if(action->templateItem() == item) {
|
||||||
|
// delete the action from the menu
|
||||||
|
removeAction(action);
|
||||||
|
allActions.removeAt(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no more template items. remove the separator
|
||||||
|
if(separatorPos == allActions.size() - 1) {
|
||||||
|
removeAction(templateSeparator_);
|
||||||
|
templateSeparator_ = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Fm
|
} // namespace Fm
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2012 - 2015 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
* Copyright (C) 2012 - 2015 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
@ -29,6 +29,8 @@
|
|||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
|
||||||
class FolderView;
|
class FolderView;
|
||||||
|
class Templates;
|
||||||
|
class TemplateItem;
|
||||||
|
|
||||||
class LIBFM_QT_API CreateNewMenu : public QMenu {
|
class LIBFM_QT_API CreateNewMenu : public QMenu {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -39,12 +41,23 @@ public:
|
|||||||
|
|
||||||
protected Q_SLOTS:
|
protected Q_SLOTS:
|
||||||
void onCreateNewFolder();
|
void onCreateNewFolder();
|
||||||
|
|
||||||
void onCreateNewFile();
|
void onCreateNewFile();
|
||||||
|
|
||||||
void onCreateNew();
|
void onCreateNew();
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void addTemplateItem(const std::shared_ptr<const TemplateItem>& item);
|
||||||
|
|
||||||
|
void updateTemplateItem(const std::shared_ptr<const TemplateItem>& oldItem, const std::shared_ptr<const TemplateItem>& newItem);
|
||||||
|
|
||||||
|
void removeTemplateItem(const std::shared_ptr<const TemplateItem>& item);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QWidget* dialogParent_;
|
QWidget* dialogParent_;
|
||||||
Fm::FilePath dirPath_;
|
Fm::FilePath dirPath_;
|
||||||
|
QAction* templateSeparator_;
|
||||||
|
std::shared_ptr<Templates> templates_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -373,12 +373,17 @@ bool FileActionCondition::match_folder(const FileInfoList& files, const char* fo
|
|||||||
pattern = g_pattern_spec_new(folder);
|
pattern = g_pattern_spec_new(folder);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto pat_str = string(folder) + "/*";
|
auto pat_str = g_str_has_suffix(folder, "/") ? string(folder) + "*" // be tolerant
|
||||||
|
: string(folder) + "/*";
|
||||||
pattern = g_pattern_spec_new(pat_str.c_str());
|
pattern = g_pattern_spec_new(pat_str.c_str());
|
||||||
}
|
}
|
||||||
for(auto& fi: files) {
|
for(auto& fi: files) {
|
||||||
auto dirname = fi->dirPath().toString();
|
auto dirname = fi->isDir() ? fi->path().toString() // also match "folder" itself
|
||||||
if(g_pattern_match_string(pattern, dirname.get())) { // at least 1 file is in the folder
|
: fi->dirPath().toString();
|
||||||
|
// Since the pattern ends with "/*", if the directory path is equal to "folder",
|
||||||
|
// it should end with "/" to be found as a match. Adding "/" is always harmless.
|
||||||
|
auto path_str = string(dirname.get()) + "/";
|
||||||
|
if(g_pattern_match_string(pattern, path_str.c_str())) { // at least 1 file is in the folder
|
||||||
if(negated) {
|
if(negated) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,9 @@ FileActionProfile::FileActionProfile(GKeyFile *kf, const char* profile_name) {
|
|||||||
exec_mode = FileActionExecMode::NORMAL;
|
exec_mode = FileActionExecMode::NORMAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
exec_mode = FileActionExecMode::NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
startup_notify = g_key_file_get_boolean(kf, group_name.c_str(), "StartupNotify", nullptr);
|
startup_notify = g_key_file_get_boolean(kf, group_name.c_str(), "StartupNotify", nullptr);
|
||||||
startup_wm_class = CStrPtr{g_key_file_get_string(kf, group_name.c_str(), "StartupWMClass", nullptr)};
|
startup_wm_class = CStrPtr{g_key_file_get_string(kf, group_name.c_str(), "StartupWMClass", nullptr)};
|
||||||
|
@ -167,7 +167,7 @@ QModelIndex DirTreeModel::indexFromPath(const Fm::FilePath &path) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DirTreeModelItem* DirTreeModel::itemFromPath(const Fm::FilePath &path) const {
|
DirTreeModelItem* DirTreeModel::itemFromPath(const Fm::FilePath &path) const {
|
||||||
Q_FOREACH(DirTreeModelItem* item, rootItems_) {
|
for(DirTreeModelItem* const item : qAsConst(rootItems_)) {
|
||||||
if(item->fileInfo_ && path == item->fileInfo_->path()) {
|
if(item->fileInfo_ && path == item->fileInfo_->path()) {
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
@ -224,7 +224,7 @@ QString DirTreeModel::dispName(const QModelIndex& index) {
|
|||||||
|
|
||||||
void DirTreeModel::setShowHidden(bool show_hidden) {
|
void DirTreeModel::setShowHidden(bool show_hidden) {
|
||||||
showHidden_ = show_hidden;
|
showHidden_ = show_hidden;
|
||||||
Q_FOREACH(DirTreeModelItem* item, rootItems_) {
|
for(DirTreeModelItem* const item : qAsConst(rootItems_)) {
|
||||||
item->setShowHidden(show_hidden);
|
item->setShowHidden(show_hidden);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "dirtreemodelitem.h"
|
#include "dirtreemodelitem.h"
|
||||||
#include "dirtreemodel.h"
|
#include "dirtreemodel.h"
|
||||||
#include "icontheme.h"
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
namespace Fm {
|
namespace Fm {
|
||||||
@ -55,12 +54,12 @@ DirTreeModelItem::~DirTreeModelItem() {
|
|||||||
freeFolder();
|
freeFolder();
|
||||||
// delete child items if needed
|
// delete child items if needed
|
||||||
if(!children_.empty()) {
|
if(!children_.empty()) {
|
||||||
Q_FOREACH(DirTreeModelItem* item, children_) {
|
for(DirTreeModelItem* const item : qAsConst(children_)) {
|
||||||
delete item;
|
delete item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!hiddenChildren_.empty()) {
|
if(!hiddenChildren_.empty()) {
|
||||||
Q_FOREACH(DirTreeModelItem* item, hiddenChildren_) {
|
for(DirTreeModelItem* const item : qAsConst(hiddenChildren_)) {
|
||||||
delete item;
|
delete item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,7 +123,7 @@ void DirTreeModelItem::unloadFolder() {
|
|||||||
// delete all visible child items
|
// delete all visible child items
|
||||||
model_->beginRemoveRows(index(), 0, children_.size() - 1);
|
model_->beginRemoveRows(index(), 0, children_.size() - 1);
|
||||||
if(!children_.empty()) {
|
if(!children_.empty()) {
|
||||||
Q_FOREACH(DirTreeModelItem* item, children_) {
|
for(DirTreeModelItem* const item : qAsConst(children_)) {
|
||||||
delete item;
|
delete item;
|
||||||
}
|
}
|
||||||
children_.clear();
|
children_.clear();
|
||||||
@ -133,7 +132,7 @@ void DirTreeModelItem::unloadFolder() {
|
|||||||
|
|
||||||
// remove hidden children
|
// remove hidden children
|
||||||
if(!hiddenChildren_.empty()) {
|
if(!hiddenChildren_.empty()) {
|
||||||
Q_FOREACH(DirTreeModelItem* item, hiddenChildren_) {
|
for(DirTreeModelItem* const item : qAsConst(hiddenChildren_)) {
|
||||||
delete item;
|
delete item;
|
||||||
}
|
}
|
||||||
hiddenChildren_.clear();
|
hiddenChildren_.clear();
|
||||||
@ -343,7 +342,7 @@ DirTreeModelItem* DirTreeModelItem::childFromName(const char* utf8_name, int* po
|
|||||||
DirTreeModelItem* DirTreeModelItem::childFromPath(Fm::FilePath path, bool recursive) const {
|
DirTreeModelItem* DirTreeModelItem::childFromPath(Fm::FilePath path, bool recursive) const {
|
||||||
Q_ASSERT(path != nullptr);
|
Q_ASSERT(path != nullptr);
|
||||||
|
|
||||||
Q_FOREACH(DirTreeModelItem* item, children_) {
|
for(DirTreeModelItem* const item : qAsConst(children_)) {
|
||||||
// if(item->fileInfo_)
|
// if(item->fileInfo_)
|
||||||
// qDebug() << "child: " << QString::fromUtf8(fm_file_info_get_disp_name(item->fileInfo_));
|
// qDebug() << "child: " << QString::fromUtf8(fm_file_info_get_disp_name(item->fileInfo_));
|
||||||
if(item->fileInfo_ && item->fileInfo_->path() == path) {
|
if(item->fileInfo_ && item->fileInfo_->path() == path) {
|
||||||
|
@ -306,7 +306,7 @@ void DirTreeView::rowsRemoved(const QModelIndex& parent, int start, int end) {
|
|||||||
|
|
||||||
void DirTreeView::doQueuedDeletions() {
|
void DirTreeView::doQueuedDeletions() {
|
||||||
if(!queuedForDeletion_.empty()) {
|
if(!queuedForDeletion_.empty()) {
|
||||||
Q_FOREACH(DirTreeModelItem* item, queuedForDeletion_) {
|
for(DirTreeModelItem* const item : qAsConst(queuedForDeletion_)) {
|
||||||
delete item;
|
delete item;
|
||||||
}
|
}
|
||||||
queuedForDeletion_.clear();
|
queuedForDeletion_.clear();
|
||||||
|
@ -51,6 +51,7 @@ bool DndDest::dropMimeData(const QMimeData* data, Qt::DropAction action) {
|
|||||||
break;
|
break;
|
||||||
case Qt::LinkAction:
|
case Qt::LinkAction:
|
||||||
FileOperation::symlinkFiles(srcPaths, destPath_);
|
FileOperation::symlinkFiles(srcPaths, destPath_);
|
||||||
|
/* Falls through. */
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -102,8 +102,8 @@ void EditBookmarksDialog::onAddItem() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EditBookmarksDialog::onRemoveItem() {
|
void EditBookmarksDialog::onRemoveItem() {
|
||||||
QList<QTreeWidgetItem*> sels = ui->treeWidget->selectedItems();
|
const QList<QTreeWidgetItem*> sels = ui->treeWidget->selectedItems();
|
||||||
Q_FOREACH(QTreeWidgetItem* item, sels) {
|
for(QTreeWidgetItem* const item : sels) {
|
||||||
delete item;
|
delete item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,31 +19,37 @@
|
|||||||
|
|
||||||
#include "execfiledialog_p.h"
|
#include "execfiledialog_p.h"
|
||||||
#include "ui_exec-file.h"
|
#include "ui_exec-file.h"
|
||||||
#include "icontheme.h"
|
|
||||||
#include "core/iconinfo.h"
|
#include "core/iconinfo.h"
|
||||||
|
|
||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
|
||||||
ExecFileDialog::ExecFileDialog(FmFileInfo* file, QWidget* parent, Qt::WindowFlags f):
|
ExecFileDialog::ExecFileDialog(const FileInfo &fileInfo, QWidget* parent, Qt::WindowFlags f):
|
||||||
QDialog(parent, f),
|
QDialog(parent, f),
|
||||||
ui(new Ui::ExecFileDialog()),
|
ui(new Ui::ExecFileDialog()),
|
||||||
fileInfo_(fm_file_info_ref(file)),
|
result_(BasicFileLauncher::ExecAction::DIRECT_EXEC) {
|
||||||
result_(FM_FILE_LAUNCHER_EXEC_CANCEL) {
|
|
||||||
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
// show file icon
|
// show file icon
|
||||||
GIcon* gicon = G_ICON(fm_file_info_get_icon(fileInfo_));
|
auto gicon = fileInfo.icon();
|
||||||
ui->icon->setPixmap(Fm::IconInfo::fromGIcon(gicon)->qicon().pixmap(QSize(48, 48)));
|
if(gicon) {
|
||||||
|
ui->icon->setPixmap(gicon->qicon().pixmap(QSize(48, 48)));
|
||||||
|
}
|
||||||
|
|
||||||
QString msg;
|
QString msg;
|
||||||
if(fm_file_info_is_text(file)) {
|
if(fileInfo.isDesktopEntry()) {
|
||||||
|
msg = tr("This file '%1' seems to be a desktop entry.\nWhat do you want to do with it?")
|
||||||
|
.arg(fileInfo.displayName());
|
||||||
|
ui->exec->setDefault(true);
|
||||||
|
ui->execTerm->hide();
|
||||||
|
}
|
||||||
|
else if(fileInfo.isText()) {
|
||||||
msg = tr("This text file '%1' seems to be an executable script.\nWhat do you want to do with it?")
|
msg = tr("This text file '%1' seems to be an executable script.\nWhat do you want to do with it?")
|
||||||
.arg(QString::fromUtf8(fm_file_info_get_disp_name(file)));
|
.arg(fileInfo.displayName());
|
||||||
ui->execTerm->setDefault(true);
|
ui->execTerm->setDefault(true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
msg = tr("This file '%1' is executable. Do you want to execute it?")
|
msg = tr("This file '%1' is executable. Do you want to execute it?")
|
||||||
.arg(QString::fromUtf8(fm_file_info_get_disp_name(file)));
|
.arg(fileInfo.displayName());
|
||||||
ui->exec->setDefault(true);
|
ui->exec->setDefault(true);
|
||||||
ui->open->hide();
|
ui->open->hide();
|
||||||
}
|
}
|
||||||
@ -52,23 +58,28 @@ ExecFileDialog::ExecFileDialog(FmFileInfo* file, QWidget* parent, Qt::WindowFlag
|
|||||||
|
|
||||||
ExecFileDialog::~ExecFileDialog() {
|
ExecFileDialog::~ExecFileDialog() {
|
||||||
delete ui;
|
delete ui;
|
||||||
if(fileInfo_) {
|
|
||||||
fm_file_info_unref(fileInfo_);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecFileDialog::accept() {
|
void ExecFileDialog::accept() {
|
||||||
QObject* _sender = sender();
|
QObject* _sender = sender();
|
||||||
if(_sender == ui->exec) {
|
if(_sender == ui->exec) {
|
||||||
result_ = FM_FILE_LAUNCHER_EXEC;
|
result_ = BasicFileLauncher::ExecAction::DIRECT_EXEC;
|
||||||
}
|
}
|
||||||
else if(_sender == ui->execTerm) {
|
else if(_sender == ui->execTerm) {
|
||||||
result_ = FM_FILE_LAUNCHER_EXEC_IN_TERMINAL;
|
result_ = BasicFileLauncher::ExecAction::EXEC_IN_TERMINAL;
|
||||||
}
|
}
|
||||||
else if(_sender == ui->open) {
|
else if(_sender == ui->open) {
|
||||||
result_ = FM_FILE_LAUNCHER_EXEC_OPEN;
|
result_ = BasicFileLauncher::ExecAction::OPEN_WITH_DEFAULT_APP;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result_ = BasicFileLauncher::ExecAction::CANCEL;
|
||||||
}
|
}
|
||||||
QDialog::accept();
|
QDialog::accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExecFileDialog::reject() {
|
||||||
|
result_ = BasicFileLauncher::ExecAction::CANCEL;
|
||||||
|
QDialog::reject();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Fm
|
} // namespace Fm
|
||||||
|
@ -20,8 +20,12 @@
|
|||||||
#ifndef FM_EXECFILEDIALOG_H
|
#ifndef FM_EXECFILEDIALOG_H
|
||||||
#define FM_EXECFILEDIALOG_H
|
#define FM_EXECFILEDIALOG_H
|
||||||
|
|
||||||
|
#include "core/basicfilelauncher.h"
|
||||||
|
#include "core/fileinfo.h"
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <libfm/fm.h>
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class ExecFileDialog;
|
class ExecFileDialog;
|
||||||
@ -33,19 +37,19 @@ class ExecFileDialog : public QDialog {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
~ExecFileDialog();
|
~ExecFileDialog();
|
||||||
ExecFileDialog(FmFileInfo* fileInfo, QWidget* parent = 0, Qt::WindowFlags f = 0);
|
ExecFileDialog(const FileInfo& fileInfo, QWidget* parent = 0, Qt::WindowFlags f = 0);
|
||||||
|
|
||||||
FmFileLauncherExecAction result() {
|
BasicFileLauncher::ExecAction result() {
|
||||||
return result_;
|
return result_;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void accept();
|
virtual void accept() override;
|
||||||
|
virtual void reject() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::ExecFileDialog* ui;
|
Ui::ExecFileDialog* ui;
|
||||||
FmFileInfo* fileInfo_;
|
BasicFileLauncher::ExecAction result_;
|
||||||
FmFileLauncherExecAction result_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>450</width>
|
<width>450</width>
|
||||||
<height>246</height>
|
<height>297</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -34,7 +34,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QLabel" name="dest">
|
<widget class="Fm::ElidedLabel" name="dest">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@ -57,7 +57,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QLabel" name="curFile">
|
<widget class="Fm::ElidedLabel" name="curFile">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@ -122,12 +122,12 @@
|
|||||||
<item row="4" column="0">
|
<item row="4" column="0">
|
||||||
<widget class="QLabel" name="label_6">
|
<widget class="QLabel" name="label_6">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Data transferred:</string>
|
<string>Files processed:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="4" column="1">
|
||||||
<widget class="QLabel" name="dataTransferred">
|
<widget class="QLabel" name="filesProcessed">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
@ -147,6 +147,13 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>Fm::ElidedLabel</class>
|
||||||
|
<extends>QLabel</extends>
|
||||||
|
<header>fileoperationdialog_p.h</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
|
@ -96,7 +96,7 @@
|
|||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="textInteractionFlags">
|
<property name="textInteractionFlags">
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -119,7 +119,7 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="textInteractionFlags">
|
<property name="textInteractionFlags">
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -142,7 +142,7 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="textInteractionFlags">
|
<property name="textInteractionFlags">
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -165,7 +165,7 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="textInteractionFlags">
|
<property name="textInteractionFlags">
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -188,7 +188,7 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="textInteractionFlags">
|
<property name="textInteractionFlags">
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -211,7 +211,7 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="textInteractionFlags">
|
<property name="textInteractionFlags">
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -237,7 +237,7 @@
|
|||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="textInteractionFlags">
|
<property name="textInteractionFlags">
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -246,9 +246,6 @@
|
|||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Open With:</string>
|
<string>Open With:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="1">
|
<item row="5" column="1">
|
||||||
@ -274,7 +271,7 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="textInteractionFlags">
|
<property name="textInteractionFlags">
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -346,41 +346,43 @@ void FileDialog::goHome() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FileDialog::setDirectoryPath(FilePath directory, FilePath selectedPath, bool addHistory) {
|
void FileDialog::setDirectoryPath(FilePath directory, FilePath selectedPath, bool addHistory) {
|
||||||
if(!directory.isValid() || directoryPath_ == directory) {
|
if(!directory.isValid()) {
|
||||||
updateAcceptButtonState(); // FIXME: is this needed?
|
updateAcceptButtonState(); // FIXME: is this needed?
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(folder_) {
|
if(directoryPath_ != directory) {
|
||||||
if(folderModel_) {
|
if(folder_) {
|
||||||
proxyModel_->setSourceModel(nullptr);
|
if(folderModel_) {
|
||||||
folderModel_->unref(); // unref the cached model
|
proxyModel_->setSourceModel(nullptr);
|
||||||
folderModel_ = nullptr;
|
folderModel_->unref(); // unref the cached model
|
||||||
|
folderModel_ = nullptr;
|
||||||
|
}
|
||||||
|
freeFolder();
|
||||||
|
}
|
||||||
|
|
||||||
|
directoryPath_ = std::move(directory);
|
||||||
|
|
||||||
|
ui->location->setPath(directoryPath_);
|
||||||
|
ui->sidePane->chdir(directoryPath_);
|
||||||
|
if(addHistory) {
|
||||||
|
history_.add(directoryPath_);
|
||||||
}
|
}
|
||||||
freeFolder();
|
backAction_->setEnabled(history_.canBackward());
|
||||||
|
forwardAction_->setEnabled(history_.canForward());
|
||||||
|
|
||||||
|
folder_ = Fm::Folder::fromPath(directoryPath_);
|
||||||
|
folderModel_ = CachedFolderModel::modelFromFolder(folder_);
|
||||||
|
proxyModel_->setSourceModel(folderModel_);
|
||||||
|
|
||||||
|
// no lambda in these connections for easy disconnection
|
||||||
|
connect(folder_.get(), &Fm::Folder::removed, this, &FileDialog::goHome);
|
||||||
|
connect(folder_.get(), &Fm::Folder::unmount, this, &FileDialog::goHome);
|
||||||
|
|
||||||
|
QUrl uri = QUrl::fromEncoded(directory.uri().get());
|
||||||
|
Q_EMIT directoryEntered(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
directoryPath_ = std::move(directory);
|
|
||||||
|
|
||||||
ui->location->setPath(directoryPath_);
|
|
||||||
ui->sidePane->chdir(directoryPath_);
|
|
||||||
if(addHistory) {
|
|
||||||
history_.add(directoryPath_);
|
|
||||||
}
|
|
||||||
backAction_->setEnabled(history_.canBackward());
|
|
||||||
forwardAction_->setEnabled(history_.canForward());
|
|
||||||
|
|
||||||
folder_ = Fm::Folder::fromPath(directoryPath_);
|
|
||||||
folderModel_ = CachedFolderModel::modelFromFolder(folder_);
|
|
||||||
proxyModel_->setSourceModel(folderModel_);
|
|
||||||
|
|
||||||
// no lambda in these connections for easy disconnection
|
|
||||||
connect(folder_.get(), &Fm::Folder::removed, this, &FileDialog::goHome);
|
|
||||||
connect(folder_.get(), &Fm::Folder::unmount, this, &FileDialog::goHome);
|
|
||||||
|
|
||||||
QUrl uri = QUrl::fromEncoded(directory.uri().get());
|
|
||||||
Q_EMIT directoryEntered(uri);
|
|
||||||
|
|
||||||
// select the path if valid
|
// select the path if valid
|
||||||
if(selectedPath.isValid()) {
|
if(selectedPath.isValid()) {
|
||||||
if(folder_->isLoaded()) {
|
if(folder_->isLoaded()) {
|
||||||
@ -415,13 +417,13 @@ void FileDialog::selectFilePath(const FilePath &path) {
|
|||||||
QItemSelectionModel* selModel = ui->folderView->selectionModel();
|
QItemSelectionModel* selModel = ui->folderView->selectionModel();
|
||||||
selModel->select(idx, flags);
|
selModel->select(idx, flags);
|
||||||
selModel->setCurrentIndex(idx, QItemSelectionModel::Current);
|
selModel->setCurrentIndex(idx, QItemSelectionModel::Current);
|
||||||
QTimer::singleShot(0, [this, idx]() {
|
QTimer::singleShot(0, this, [this, idx]() {
|
||||||
ui->folderView->childView()->scrollTo(idx, QAbstractItemView::PositionAtCenter);
|
ui->folderView->childView()->scrollTo(idx, QAbstractItemView::PositionAtCenter);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileDialog::selectFilePathWithDelay(const FilePath &path) {
|
void FileDialog::selectFilePathWithDelay(const FilePath &path) {
|
||||||
QTimer::singleShot(0, [this, path]() {
|
QTimer::singleShot(0, this, [this, path]() {
|
||||||
if(acceptMode_ == QFileDialog::AcceptSave) {
|
if(acceptMode_ == QFileDialog::AcceptSave) {
|
||||||
// with a save dialog, always put the base name in line-edit, regardless of selection
|
// with a save dialog, always put the base name in line-edit, regardless of selection
|
||||||
ui->fileName->setText(path.baseName().get());
|
ui->fileName->setText(path.baseName().get());
|
||||||
@ -436,7 +438,7 @@ void FileDialog::selectFilePathWithDelay(const FilePath &path) {
|
|||||||
|
|
||||||
void FileDialog::selectFilesOnReload(const Fm::FileInfoList& infos) {
|
void FileDialog::selectFilesOnReload(const Fm::FileInfoList& infos) {
|
||||||
QObject::disconnect(lambdaConnection_);
|
QObject::disconnect(lambdaConnection_);
|
||||||
QTimer::singleShot(0, [this, infos]() {
|
QTimer::singleShot(0, this, [this, infos]() {
|
||||||
for(auto& fileInfo: infos) {
|
for(auto& fileInfo: infos) {
|
||||||
selectFilePath(fileInfo->path());
|
selectFilePath(fileInfo->path());
|
||||||
}
|
}
|
||||||
@ -635,13 +637,8 @@ void FileDialog::selectFile(const QUrl& filename) {
|
|||||||
auto urlStr = filename.toEncoded();
|
auto urlStr = filename.toEncoded();
|
||||||
auto path = FilePath::fromUri(urlStr.constData());
|
auto path = FilePath::fromUri(urlStr.constData());
|
||||||
auto parent = path.parent();
|
auto parent = path.parent();
|
||||||
if(parent.isValid() && parent != directoryPath_) {
|
// chdir into file's parent if needed and select the file
|
||||||
// chdir into file's parent if it isn't the current directory
|
setDirectoryPath(parent, path);
|
||||||
setDirectoryPath(parent, path);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
selectFilePathWithDelay(path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QUrl> FileDialog::selectedFiles() {
|
QList<QUrl> FileDialog::selectedFiles() {
|
||||||
@ -770,7 +767,8 @@ void FileDialog::setMimeTypeFilters(const QStringList& filters) {
|
|||||||
auto nameFilter = mimeType.comment();
|
auto nameFilter = mimeType.comment();
|
||||||
if(!mimeType.suffixes().empty()) {
|
if(!mimeType.suffixes().empty()) {
|
||||||
nameFilter + " (";
|
nameFilter + " (";
|
||||||
for(const auto& suffix: mimeType.suffixes()) {
|
const auto suffixes = mimeType.suffixes();
|
||||||
|
for(const auto& suffix: suffixes) {
|
||||||
nameFilter += "*.";
|
nameFilter += "*.";
|
||||||
nameFilter += suffix;
|
nameFilter += suffix;
|
||||||
nameFilter += ' ';
|
nameFilter += ' ';
|
||||||
|
@ -26,111 +26,73 @@
|
|||||||
#include "appchooserdialog.h"
|
#include "appchooserdialog.h"
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
|
|
||||||
|
#include "core/fileinfojob.h"
|
||||||
|
#include "mountoperation.h"
|
||||||
|
|
||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
|
||||||
FmFileLauncher FileLauncher::funcs = {
|
FileLauncher::FileLauncher() {
|
||||||
FileLauncher::_getApp,
|
|
||||||
/* gboolean (*before_open)(GAppLaunchContext* ctx, GList* folder_infos, gpointer user_data); */
|
|
||||||
(FmLaunchFolderFunc)FileLauncher::_openFolder,
|
|
||||||
FileLauncher::_execFile,
|
|
||||||
FileLauncher::_error,
|
|
||||||
FileLauncher::_ask,
|
|
||||||
nullptr
|
|
||||||
};
|
|
||||||
|
|
||||||
FileLauncher::FileLauncher():
|
|
||||||
quickExec_(false) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FileLauncher::~FileLauncher() {
|
FileLauncher::~FileLauncher() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileLauncher::launchFiles(QWidget *parent, Fm::FileInfoList file_infos) {
|
|
||||||
// FIXME: rewrite
|
|
||||||
return launchPaths(parent, file_infos.paths());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileLauncher::launchPaths(QWidget *parent, Fm::FilePathList paths) {
|
bool FileLauncher::launchFiles(QWidget* parent, const FileInfoList &file_infos) {
|
||||||
// FIXME: rewrite, port to new api
|
GObjectPtr<FmAppLaunchContext> context{fm_app_launch_context_new_for_widget(parent), false};
|
||||||
GList* tmp = nullptr;
|
bool ret = BasicFileLauncher::launchFiles(file_infos, G_APP_LAUNCH_CONTEXT(context.get()));
|
||||||
for(auto& path: paths) {
|
|
||||||
auto fmpath = fm_path_new_for_gfile(path.gfile().get());
|
|
||||||
tmp = g_list_prepend(tmp, fmpath);
|
|
||||||
}
|
|
||||||
tmp = g_list_reverse(tmp);
|
|
||||||
bool ret = launchPaths(parent, tmp);
|
|
||||||
g_list_free(tmp);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileLauncher::launchFiles(QWidget* parent, GList* file_infos) {
|
bool FileLauncher::launchPaths(QWidget* parent, const FilePathList& paths) {
|
||||||
FmAppLaunchContext* context = fm_app_launch_context_new_for_widget(parent);
|
GObjectPtr<FmAppLaunchContext> context{fm_app_launch_context_new_for_widget(parent), false};
|
||||||
bool ret = fm_launch_files(G_APP_LAUNCH_CONTEXT(context), file_infos, &funcs, this);
|
bool ret = BasicFileLauncher::launchPaths(paths, G_APP_LAUNCH_CONTEXT(context.get()));
|
||||||
g_object_unref(context);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileLauncher::launchPaths(QWidget* parent, GList* paths) {
|
|
||||||
FmAppLaunchContext* context = fm_app_launch_context_new_for_widget(parent);
|
|
||||||
bool ret = fm_launch_paths(G_APP_LAUNCH_CONTEXT(context), paths, &funcs, this);
|
|
||||||
g_object_unref(context);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
GAppInfo* FileLauncher::getApp(GList* /*file_infos*/, FmMimeType* mime_type, GError** /*err*/) {
|
|
||||||
AppChooserDialog dlg(nullptr);
|
|
||||||
if(mime_type) {
|
|
||||||
dlg.setMimeType(Fm::MimeType::fromName(fm_mime_type_get_type(mime_type)));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
dlg.setCanSetDefault(false);
|
|
||||||
}
|
|
||||||
// FIXME: show error properly?
|
|
||||||
if(execModelessDialog(&dlg) == QDialog::Accepted) {
|
|
||||||
auto app = dlg.selectedApp();
|
|
||||||
return app.release();
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileLauncher::openFolder(GAppLaunchContext* /*ctx*/, GList* folder_infos, GError** /*err*/) {
|
|
||||||
for(GList* l = folder_infos; l; l = l->next) {
|
|
||||||
FmFileInfo* fi = FM_FILE_INFO(l->data);
|
|
||||||
qDebug() << " folder:" << QString::fromUtf8(fm_file_info_get_disp_name(fi));
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
FmFileLauncherExecAction FileLauncher::execFile(FmFileInfo* file) {
|
|
||||||
if(quickExec_) {
|
|
||||||
/* SF bug#838: open terminal for each script may be just a waste.
|
|
||||||
User should open a terminal and start the script there
|
|
||||||
in case if user wants to see the script output anyway.
|
|
||||||
if (fm_file_info_is_text(file))
|
|
||||||
return FM_FILE_LAUNCHER_EXEC_IN_TERMINAL; */
|
|
||||||
return FM_FILE_LAUNCHER_EXEC;
|
|
||||||
}
|
|
||||||
|
|
||||||
FmFileLauncherExecAction res = FM_FILE_LAUNCHER_EXEC_CANCEL;
|
|
||||||
ExecFileDialog dlg(file);
|
|
||||||
if(execModelessDialog(&dlg) == QDialog::Accepted) {
|
|
||||||
res = dlg.result();
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FileLauncher::ask(const char* /*msg*/, char* const* /*btn_labels*/, int /*default_btn*/) {
|
int FileLauncher::ask(const char* /*msg*/, char* const* /*btn_labels*/, int /*default_btn*/) {
|
||||||
/* FIXME: set default button properly */
|
/* FIXME: set default button properly */
|
||||||
// return fm_askv(data->parent, nullptr, msg, btn_labels);
|
// return fm_askv(data->parent, nullptr, msg, btn_labels);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileLauncher::error(GAppLaunchContext* /*ctx*/, GError* err, FmPath* path) {
|
GAppInfoPtr FileLauncher::chooseApp(const FileInfoList& /*fileInfos*/, const char *mimeType, GErrorPtr& /*err*/) {
|
||||||
|
AppChooserDialog dlg(nullptr);
|
||||||
|
GAppInfoPtr app;
|
||||||
|
if(mimeType) {
|
||||||
|
dlg.setMimeType(Fm::MimeType::fromName(mimeType));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dlg.setCanSetDefault(false);
|
||||||
|
}
|
||||||
|
// FIXME: show error properly?
|
||||||
|
if(execModelessDialog(&dlg) == QDialog::Accepted) {
|
||||||
|
app = dlg.selectedApp();
|
||||||
|
}
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileLauncher::openFolder(GAppLaunchContext *ctx, const FileInfoList &folderInfos, GErrorPtr &err) {
|
||||||
|
return BasicFileLauncher::openFolder(ctx, folderInfos, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileLauncher::showError(GAppLaunchContext* /*ctx*/, GErrorPtr &err, const FilePath &path, const FileInfoPtr &info) {
|
||||||
/* ask for mount if trying to launch unmounted path */
|
/* ask for mount if trying to launch unmounted path */
|
||||||
if(err->domain == G_IO_ERROR) {
|
if(err->domain == G_IO_ERROR) {
|
||||||
if(path && err->code == G_IO_ERROR_NOT_MOUNTED) {
|
if(path && err->code == G_IO_ERROR_NOT_MOUNTED) {
|
||||||
//if(fm_mount_path(data->parent, path, TRUE))
|
MountOperation* op = new MountOperation(true);
|
||||||
// return FALSE; /* ask to retry */
|
op->setAutoDestroy(true);
|
||||||
|
if(info && info->isMountable()) {
|
||||||
|
// this is a mountable shortcut (such as computer:///xxxx.drive)
|
||||||
|
op->mountMountable(path);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
op->mountEnclosingVolume(path);
|
||||||
|
}
|
||||||
|
if(op->wait()) {
|
||||||
|
// if the mount operation succeeds, we can ignore the error and continue
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(err->code == G_IO_ERROR_FAILED_HANDLED) {
|
else if(err->code == G_IO_ERROR_FAILED_HANDLED) {
|
||||||
return true; /* don't show error message */
|
return true; /* don't show error message */
|
||||||
@ -138,7 +100,16 @@ bool FileLauncher::error(GAppLaunchContext* /*ctx*/, GError* err, FmPath* path)
|
|||||||
}
|
}
|
||||||
QMessageBox dlg(QMessageBox::Critical, QObject::tr("Error"), QString::fromUtf8(err->message), QMessageBox::Ok);
|
QMessageBox dlg(QMessageBox::Critical, QObject::tr("Error"), QString::fromUtf8(err->message), QMessageBox::Ok);
|
||||||
execModelessDialog(&dlg);
|
execModelessDialog(&dlg);
|
||||||
return true;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicFileLauncher::ExecAction FileLauncher::askExecFile(const FileInfoPtr &file) {
|
||||||
|
auto res = BasicFileLauncher::ExecAction::CANCEL;
|
||||||
|
ExecFileDialog dlg(*file);
|
||||||
|
if(execModelessDialog(&dlg) == QDialog::Accepted) {
|
||||||
|
res = dlg.result();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,60 +23,31 @@
|
|||||||
|
|
||||||
#include "libfmqtglobals.h"
|
#include "libfmqtglobals.h"
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <libfm/fm.h>
|
|
||||||
#include "core/fileinfo.h"
|
#include "core/fileinfo.h"
|
||||||
|
#include "core/basicfilelauncher.h"
|
||||||
|
|
||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
|
||||||
class LIBFM_QT_API FileLauncher {
|
class LIBFM_QT_API FileLauncher: public BasicFileLauncher {
|
||||||
public:
|
public:
|
||||||
explicit FileLauncher();
|
explicit FileLauncher();
|
||||||
virtual ~FileLauncher();
|
virtual ~FileLauncher();
|
||||||
|
|
||||||
bool launchFiles(QWidget* parent, Fm::FileInfoList file_infos);
|
bool launchFiles(QWidget* parent, const FileInfoList& file_infos);
|
||||||
|
|
||||||
bool launchPaths(QWidget* parent, Fm::FilePathList paths);
|
bool launchPaths(QWidget* parent, const FilePathList &paths);
|
||||||
|
|
||||||
bool quickExec() const {
|
|
||||||
return quickExec_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setQuickExec(bool value) {
|
|
||||||
quickExec_ = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual GAppInfo* getApp(GList* file_infos, FmMimeType* mime_type, GError** err);
|
GAppInfoPtr chooseApp(const FileInfoList& fileInfos, const char* mimeType, GErrorPtr& err) override;
|
||||||
virtual bool openFolder(GAppLaunchContext* ctx, GList* folder_infos, GError** err);
|
|
||||||
virtual FmFileLauncherExecAction execFile(FmFileInfo* file);
|
|
||||||
virtual bool error(GAppLaunchContext* ctx, GError* err, FmPath* path);
|
|
||||||
virtual int ask(const char* msg, char* const* btn_labels, int default_btn);
|
|
||||||
|
|
||||||
private:
|
bool openFolder(GAppLaunchContext* ctx, const FileInfoList& folderInfos, GErrorPtr& err) override;
|
||||||
bool launchFiles(QWidget* parent, GList* file_infos);
|
|
||||||
|
|
||||||
bool launchPaths(QWidget* parent, GList* paths);
|
bool showError(GAppLaunchContext* ctx, GErrorPtr& err, const FilePath& path = FilePath{}, const FileInfoPtr& info = FileInfoPtr{}) override;
|
||||||
|
|
||||||
static GAppInfo* _getApp(GList* file_infos, FmMimeType* mime_type, gpointer user_data, GError** err) {
|
ExecAction askExecFile(const FileInfoPtr& file) override;
|
||||||
return reinterpret_cast<FileLauncher*>(user_data)->getApp(file_infos, mime_type, err);
|
|
||||||
}
|
|
||||||
static gboolean _openFolder(GAppLaunchContext* ctx, GList* folder_infos, gpointer user_data, GError** err) {
|
|
||||||
return reinterpret_cast<FileLauncher*>(user_data)->openFolder(ctx, folder_infos, err);
|
|
||||||
}
|
|
||||||
static FmFileLauncherExecAction _execFile(FmFileInfo* file, gpointer user_data) {
|
|
||||||
return reinterpret_cast<FileLauncher*>(user_data)->execFile(file);
|
|
||||||
}
|
|
||||||
static gboolean _error(GAppLaunchContext* ctx, GError* err, FmPath* file, gpointer user_data) {
|
|
||||||
return reinterpret_cast<FileLauncher*>(user_data)->error(ctx, err, file);
|
|
||||||
}
|
|
||||||
static int _ask(const char* msg, char* const* btn_labels, int default_btn, gpointer user_data) {
|
|
||||||
return reinterpret_cast<FileLauncher*>(user_data)->ask(msg, btn_labels, default_btn);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
int ask(const char* msg, char* const* btn_labels, int default_btn) override;
|
||||||
static FmFileLauncher funcs;
|
|
||||||
bool quickExec_; // Don't ask options on launch executable file
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
#include "filemenu.h"
|
#include "filemenu.h"
|
||||||
#include "createnewmenu.h"
|
#include "createnewmenu.h"
|
||||||
#include "icontheme.h"
|
|
||||||
#include "filepropsdialog.h"
|
#include "filepropsdialog.h"
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
#include "fileoperation.h"
|
#include "fileoperation.h"
|
||||||
@ -35,7 +34,7 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include "filemenu_p.h"
|
#include "filemenu_p.h"
|
||||||
|
|
||||||
#include "core/compat_p.h"
|
#include "core/archiver.h"
|
||||||
|
|
||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
|
||||||
@ -207,18 +206,17 @@ FileMenu::FileMenu(Fm::FileInfoList files, std::shared_ptr<const Fm::FileInfo> i
|
|||||||
// FIXME: we need to modify upstream libfm to include some Qt-based archiver programs.
|
// FIXME: we need to modify upstream libfm to include some Qt-based archiver programs.
|
||||||
if(!allVirtual_) {
|
if(!allVirtual_) {
|
||||||
if(sameType_) {
|
if(sameType_) {
|
||||||
// FIXME: port these parts to Fm API
|
auto archiver = Archiver::defaultArchiver();
|
||||||
FmArchiver* archiver = fm_archiver_get_default();
|
|
||||||
if(archiver) {
|
if(archiver) {
|
||||||
if(fm_archiver_is_mime_type_supported(archiver, mime_type->name())) {
|
if(archiver->isMimeTypeSupported(mime_type->name())) {
|
||||||
QAction* archiverSeparator = nullptr;
|
QAction* archiverSeparator = nullptr;
|
||||||
if(cwd_ && archiver->extract_to_cmd) {
|
if(cwd_ && archiver->canExtractArchivesTo()) {
|
||||||
archiverSeparator = addSeparator();
|
archiverSeparator = addSeparator();
|
||||||
QAction* action = new QAction(tr("Extract to..."), this);
|
QAction* action = new QAction(tr("Extract to..."), this);
|
||||||
connect(action, &QAction::triggered, this, &FileMenu::onExtract);
|
connect(action, &QAction::triggered, this, &FileMenu::onExtract);
|
||||||
addAction(action);
|
addAction(action);
|
||||||
}
|
}
|
||||||
if(archiver->extract_cmd) {
|
if(archiver->canExtractArchives()) {
|
||||||
if(!archiverSeparator) {
|
if(!archiverSeparator) {
|
||||||
addSeparator();
|
addSeparator();
|
||||||
}
|
}
|
||||||
@ -227,7 +225,7 @@ FileMenu::FileMenu(Fm::FileInfoList files, std::shared_ptr<const Fm::FileInfo> i
|
|||||||
addAction(action);
|
addAction(action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else if(archiver->canCreateArchive()){
|
||||||
addSeparator();
|
addSeparator();
|
||||||
QAction* action = new QAction(tr("Compress"), this);
|
QAction* action = new QAction(tr("Compress"), this);
|
||||||
connect(action, &QAction::triggered, this, &FileMenu::onCompress);
|
connect(action, &QAction::triggered, this, &FileMenu::onCompress);
|
||||||
@ -376,7 +374,9 @@ void FileMenu::onRenameTriggered() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(auto& info: files_) {
|
for(auto& info: files_) {
|
||||||
Fm::renameFile(info, nullptr);
|
if(!Fm::renameFile(info, nullptr)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,27 +391,23 @@ void FileMenu::setUseTrash(bool trash) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FileMenu::onCompress() {
|
void FileMenu::onCompress() {
|
||||||
FmArchiver* archiver = fm_archiver_get_default();
|
auto archiver = Archiver::defaultArchiver();
|
||||||
if(archiver) {
|
if(archiver) {
|
||||||
auto paths = Fm::_convertPathList(files_.paths());
|
archiver->createArchive(nullptr, files_.paths());
|
||||||
fm_archiver_create_archive(archiver, nullptr, paths.dataPtr());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileMenu::onExtract() {
|
void FileMenu::onExtract() {
|
||||||
FmArchiver* archiver = fm_archiver_get_default();
|
auto archiver = Archiver::defaultArchiver();
|
||||||
if(archiver) {
|
if(archiver) {
|
||||||
auto paths = Fm::_convertPathList(files_.paths());
|
archiver->extractArchives(nullptr, files_.paths());
|
||||||
fm_archiver_extract_archives(archiver, nullptr, paths.dataPtr());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileMenu::onExtractHere() {
|
void FileMenu::onExtractHere() {
|
||||||
FmArchiver* archiver = fm_archiver_get_default();
|
auto archiver = Archiver::defaultArchiver();
|
||||||
if(archiver) {
|
if(archiver) {
|
||||||
auto paths = Fm::_convertPathList(files_.paths());
|
archiver->extractArchivesTo(nullptr, files_.paths(), cwd_);
|
||||||
auto cwd = Fm::_convertPath(cwd_);
|
|
||||||
fm_archiver_extract_archives_to(archiver, nullptr, paths.dataPtr(), cwd);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
#ifndef FM_FILEMENU_P_H
|
#ifndef FM_FILEMENU_P_H
|
||||||
#define FM_FILEMENU_P_H
|
#define FM_FILEMENU_P_H
|
||||||
|
|
||||||
#include "icontheme.h"
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include "core/gioptrs.h"
|
#include "core/gioptrs.h"
|
||||||
#include "core/iconinfo.h"
|
#include "core/iconinfo.h"
|
||||||
|
@ -24,87 +24,207 @@
|
|||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include "path.h"
|
|
||||||
|
|
||||||
#include "core/compat_p.h"
|
#include "core/deletejob.h"
|
||||||
|
#include "core/trashjob.h"
|
||||||
|
#include "core/untrashjob.h"
|
||||||
|
#include "core/filetransferjob.h"
|
||||||
|
#include "core/filechangeattrjob.h"
|
||||||
|
#include "utilities.h"
|
||||||
|
|
||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
|
||||||
#define SHOW_DLG_DELAY 1000
|
#define SHOW_DLG_DELAY 1000
|
||||||
|
|
||||||
FileOperation::FileOperation(Type type, Fm::FilePathList srcFiles, QObject* parent):
|
FileOperation::FileOperation(Type type, Fm::FilePathList srcPaths, QObject* parent):
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
job_{fm_file_ops_job_new((FmFileOpType)type, Fm::_convertPathList(srcFiles))},
|
type_{type},
|
||||||
dlg{nullptr},
|
job_{nullptr},
|
||||||
srcPaths{std::move(srcFiles)},
|
dlg_{nullptr},
|
||||||
uiTimer(nullptr),
|
srcPaths_{std::move(srcPaths)},
|
||||||
|
uiTimer_(nullptr),
|
||||||
elapsedTimer_(nullptr),
|
elapsedTimer_(nullptr),
|
||||||
lastElapsed_(0),
|
lastElapsed_(0),
|
||||||
updateRemainingTime_(true),
|
updateRemainingTime_(true),
|
||||||
autoDestroy_(true) {
|
autoDestroy_(true) {
|
||||||
|
|
||||||
g_signal_connect(job_, "ask", G_CALLBACK(onFileOpsJobAsk), this);
|
switch(type_) {
|
||||||
g_signal_connect(job_, "ask-rename", G_CALLBACK(onFileOpsJobAskRename), this);
|
case Copy:
|
||||||
g_signal_connect(job_, "error", G_CALLBACK(onFileOpsJobError), this);
|
job_ = new FileTransferJob(srcPaths_, FileTransferJob::Mode::COPY);
|
||||||
g_signal_connect(job_, "prepared", G_CALLBACK(onFileOpsJobPrepared), this);
|
break;
|
||||||
g_signal_connect(job_, "cur-file", G_CALLBACK(onFileOpsJobCurFile), this);
|
case Move:
|
||||||
g_signal_connect(job_, "percent", G_CALLBACK(onFileOpsJobPercent), this);
|
job_ = new FileTransferJob(srcPaths_, FileTransferJob::Mode::MOVE);
|
||||||
g_signal_connect(job_, "finished", G_CALLBACK(onFileOpsJobFinished), this);
|
break;
|
||||||
g_signal_connect(job_, "cancelled", G_CALLBACK(onFileOpsJobCancelled), this);
|
case Link:
|
||||||
|
job_ = new FileTransferJob(srcPaths_, FileTransferJob::Mode::LINK);
|
||||||
|
break;
|
||||||
|
case Delete:
|
||||||
|
job_ = new Fm::DeleteJob(srcPaths_);
|
||||||
|
break;
|
||||||
|
case Trash:
|
||||||
|
job_ = new Fm::TrashJob(srcPaths_);
|
||||||
|
break;
|
||||||
|
case UnTrash:
|
||||||
|
job_ = new Fm::UntrashJob(srcPaths_);
|
||||||
|
break;
|
||||||
|
case ChangeAttr:
|
||||||
|
job_ = new Fm::FileChangeAttrJob(srcPaths_);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(job_) {
|
||||||
|
// automatically delete the job object when it's finished.
|
||||||
|
job_->setAutoDelete(true);
|
||||||
|
|
||||||
|
// new C++ jobs
|
||||||
|
connect(job_, &Fm::Job::finished, this, &Fm::FileOperation::onJobFinish);
|
||||||
|
connect(job_, &Fm::Job::cancelled, this, &Fm::FileOperation::onJobCancalled);
|
||||||
|
connect(job_, &Fm::Job::error, this, &Fm::FileOperation::onJobError, Qt::BlockingQueuedConnection);
|
||||||
|
connect(job_, &Fm::FileOperationJob::fileExists, this, &Fm::FileOperation::onJobFileExists, Qt::BlockingQueuedConnection);
|
||||||
|
|
||||||
|
// we block the job deliberately until we prepare to start (initiailize the timer) so we can calculate elapsed time correctly.
|
||||||
|
connect(job_, &Fm::FileOperationJob::preparedToRun, this, &Fm::FileOperation::onJobPrepared, Qt::BlockingQueuedConnection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileOperation::disconnectJob() {
|
void FileOperation::disconnectJob() {
|
||||||
g_signal_handlers_disconnect_by_func(job_, (gpointer)G_CALLBACK(onFileOpsJobAsk), this);
|
if(job_) {
|
||||||
g_signal_handlers_disconnect_by_func(job_, (gpointer)G_CALLBACK(onFileOpsJobAskRename), this);
|
disconnect(job_, &Fm::Job::finished, this, &Fm::FileOperation::onJobFinish);
|
||||||
g_signal_handlers_disconnect_by_func(job_, (gpointer)G_CALLBACK(onFileOpsJobError), this);
|
disconnect(job_, &Fm::Job::cancelled, this, &Fm::FileOperation::onJobCancalled);
|
||||||
g_signal_handlers_disconnect_by_func(job_, (gpointer)G_CALLBACK(onFileOpsJobPrepared), this);
|
disconnect(job_, &Fm::Job::error, this, &Fm::FileOperation::onJobError);
|
||||||
g_signal_handlers_disconnect_by_func(job_, (gpointer)G_CALLBACK(onFileOpsJobCurFile), this);
|
disconnect(job_, &Fm::FileOperationJob::fileExists, this, &Fm::FileOperation::onJobFileExists);
|
||||||
g_signal_handlers_disconnect_by_func(job_, (gpointer)G_CALLBACK(onFileOpsJobPercent), this);
|
disconnect(job_, &Fm::FileOperationJob::preparedToRun, this, &Fm::FileOperation::onJobPrepared);
|
||||||
g_signal_handlers_disconnect_by_func(job_, (gpointer)G_CALLBACK(onFileOpsJobFinished), this);
|
}
|
||||||
g_signal_handlers_disconnect_by_func(job_, (gpointer)G_CALLBACK(onFileOpsJobCancelled), this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FileOperation::~FileOperation() {
|
FileOperation::~FileOperation() {
|
||||||
if(uiTimer) {
|
if(uiTimer_) {
|
||||||
uiTimer->stop();
|
uiTimer_->stop();
|
||||||
delete uiTimer;
|
delete uiTimer_;
|
||||||
uiTimer = nullptr;
|
uiTimer_ = nullptr;
|
||||||
}
|
}
|
||||||
if(elapsedTimer_) {
|
if(elapsedTimer_) {
|
||||||
delete elapsedTimer_;
|
delete elapsedTimer_;
|
||||||
elapsedTimer_ = nullptr;
|
elapsedTimer_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(job_) {
|
|
||||||
disconnectJob();
|
|
||||||
g_object_unref(job_);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileOperation::setDestination(Fm::FilePath dest) {
|
void FileOperation::setDestination(Fm::FilePath dest) {
|
||||||
destPath = std::move(dest);
|
destPath_ = std::move(dest);
|
||||||
auto tmp = Fm::Path::newForGfile(dest.gfile().get());
|
switch(type_) {
|
||||||
fm_file_ops_job_set_dest(job_, tmp.dataPtr());
|
case Copy:
|
||||||
|
case Move:
|
||||||
|
case Link:
|
||||||
|
if(job_) {
|
||||||
|
static_cast<FileTransferJob*>(job_)->setDestDirPath(destPath_);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileOperation::setDestFiles(FilePathList destFiles) {
|
||||||
|
switch(type_) {
|
||||||
|
case Copy:
|
||||||
|
case Move:
|
||||||
|
case Link:
|
||||||
|
if(job_) {
|
||||||
|
static_cast<FileTransferJob*>(job_)->setDestPaths(std::move(destFiles));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileOperation::setChmod(mode_t newMode, mode_t newModeMask) {
|
||||||
|
if(job_) {
|
||||||
|
auto job = static_cast<FileChangeAttrJob*>(job_);
|
||||||
|
job->setFileModeEnabled(true);
|
||||||
|
job->setFileMode(newMode, newModeMask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileOperation::setChown(uid_t uid, gid_t gid) {
|
||||||
|
if(job_) {
|
||||||
|
auto job = static_cast<FileChangeAttrJob*>(job_);
|
||||||
|
if(uid != INVALID_UID) {
|
||||||
|
job->setOwnerEnabled(true);
|
||||||
|
job->setOwner(uid);
|
||||||
|
}
|
||||||
|
if(gid != INVALID_GID) {
|
||||||
|
job->setGroupEnabled(true);
|
||||||
|
job->setGroup(gid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileOperation::setRecursiveChattr(bool recursive) {
|
||||||
|
if(job_) {
|
||||||
|
auto job = static_cast<FileChangeAttrJob*>(job_);
|
||||||
|
job->setRecursive(recursive);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileOperation::run() {
|
bool FileOperation::run() {
|
||||||
delete uiTimer;
|
delete uiTimer_;
|
||||||
// run the job
|
// run the job
|
||||||
uiTimer = new QTimer();
|
uiTimer_ = new QTimer();
|
||||||
uiTimer->start(SHOW_DLG_DELAY);
|
uiTimer_->start(SHOW_DLG_DELAY);
|
||||||
connect(uiTimer, &QTimer::timeout, this, &FileOperation::onUiTimeout);
|
connect(uiTimer_, &QTimer::timeout, this, &FileOperation::onUiTimeout);
|
||||||
|
|
||||||
return fm_job_run_async(FM_JOB(job_));
|
if(job_) {
|
||||||
|
job_->runAsync();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileOperation::cancel() {
|
||||||
|
if(job_) {
|
||||||
|
job_->cancel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileOperation::onUiTimeout() {
|
void FileOperation::onUiTimeout() {
|
||||||
if(dlg) {
|
if(dlg_) {
|
||||||
dlg->setCurFile(curFile);
|
|
||||||
// estimate remaining time based on past history
|
// estimate remaining time based on past history
|
||||||
// FIXME: avoid directly access data member of FmFileOpsJob
|
if(job_) {
|
||||||
if(Q_LIKELY(job_->percent > 0 && updateRemainingTime_)) {
|
Fm::FilePath curFilePath = job_->currentFile();
|
||||||
gint64 remaining = elapsedTime() * ((double(100 - job_->percent) / job_->percent) / 1000);
|
// update progress bar
|
||||||
dlg->setRemainingTime(remaining);
|
double finishedRatio = job_->progress();
|
||||||
|
if(finishedRatio > 0.0 && updateRemainingTime_) {
|
||||||
|
dlg_->setPercent(int(finishedRatio * 100));
|
||||||
|
|
||||||
|
std::uint64_t totalSize, totalCount, finishedSize, finishedCount;
|
||||||
|
job_->totalAmount(totalSize, totalCount);
|
||||||
|
job_->finishedAmount(finishedSize, finishedCount);
|
||||||
|
|
||||||
|
// only show data transferred if the job progress can be calculated by file size.
|
||||||
|
// for jobs not related to data transfer (for example: change attr, delete,...), hide the UI
|
||||||
|
if(job_->calcProgressUsingSize()) {
|
||||||
|
dlg_->setDataTransferred(finishedSize, totalSize);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dlg_->setFilesProcessed(finishedCount, totalCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
double remainRatio = 1.0 - finishedRatio;
|
||||||
|
gint64 remaining = elapsedTime() * (remainRatio / finishedRatio) / 1000;
|
||||||
|
// qDebug("etime: %llu, finished: %lf, remain:%lf, remaining secs: %llu",
|
||||||
|
// elapsedTime(), finishedRatio, remainRatio, remaining);
|
||||||
|
dlg_->setRemainingTime(remaining);
|
||||||
|
}
|
||||||
|
// update currently processed file
|
||||||
|
if(curFilePath_ != curFilePath) {
|
||||||
|
curFilePath_ = std::move(curFilePath);
|
||||||
|
// FIXME: make this cleaner
|
||||||
|
curFile = QString::fromUtf8(curFilePath_.toString().get());
|
||||||
|
dlg_->setCurFile(curFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// this timeout slot is called every 0.5 second.
|
// this timeout slot is called every 0.5 second.
|
||||||
// by adding this flag, we can update remaining time every 1 second.
|
// by adding this flag, we can update remaining time every 1 second.
|
||||||
@ -116,125 +236,84 @@ void FileOperation::onUiTimeout() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FileOperation::showDialog() {
|
void FileOperation::showDialog() {
|
||||||
if(!dlg) {
|
if(!dlg_) {
|
||||||
dlg = new FileOperationDialog(this);
|
dlg_ = new FileOperationDialog(this);
|
||||||
dlg->setSourceFiles(srcPaths);
|
dlg_->setSourceFiles(srcPaths_);
|
||||||
|
|
||||||
if(destPath) {
|
if(destPath_) {
|
||||||
dlg->setDestPath(destPath);
|
dlg_->setDestPath(destPath_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(curFile.isEmpty()) {
|
if(curFile.isEmpty()) {
|
||||||
dlg->setPrepared();
|
dlg_->setPrepared();
|
||||||
dlg->setCurFile(curFile);
|
dlg_->setCurFile(curFile);
|
||||||
}
|
}
|
||||||
uiTimer->setInterval(500); // change the interval of the timer
|
uiTimer_->setInterval(500); // change the interval of the timer
|
||||||
// now the timer is used to update current file display
|
// now the timer is used to update current file display
|
||||||
dlg->show();
|
dlg_->show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gint FileOperation::onFileOpsJobAsk(FmFileOpsJob* /*job*/, const char* question, char* const* options, FileOperation* pThis) {
|
void FileOperation::onJobFileExists(const FileInfo& src, const FileInfo& dest, Fm::FileOperationJob::FileExistsAction& response, FilePath& newDest) {
|
||||||
pThis->pauseElapsedTimer();
|
pauseElapsedTimer();
|
||||||
pThis->showDialog();
|
showDialog();
|
||||||
int ret = pThis->dlg->ask(QString::fromUtf8(question), options);
|
response = dlg_->askRename(src, dest, newDest);
|
||||||
pThis->resumeElapsedTimer();
|
resumeElapsedTimer();
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gint FileOperation::onFileOpsJobAskRename(FmFileOpsJob* /*job*/, FmFileInfo* src, FmFileInfo* dest, char** new_name, FileOperation* pThis) {
|
void FileOperation::onJobCancalled() {
|
||||||
pThis->pauseElapsedTimer();
|
|
||||||
pThis->showDialog();
|
|
||||||
QString newName;
|
|
||||||
int ret = pThis->dlg->askRename(src, dest, newName);
|
|
||||||
if(!newName.isEmpty()) {
|
|
||||||
*new_name = g_strdup(newName.toUtf8().constData());
|
|
||||||
}
|
|
||||||
pThis->resumeElapsedTimer();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileOperation::onFileOpsJobCancelled(FmFileOpsJob* /*job*/, FileOperation* /*pThis*/) {
|
|
||||||
qDebug("file operation is cancelled!");
|
qDebug("file operation is cancelled!");
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileOperation::onFileOpsJobCurFile(FmFileOpsJob* /*job*/, const char* cur_file, FileOperation* pThis) {
|
void FileOperation::onJobError(const GErrorPtr& err, Fm::Job::ErrorSeverity severity, Fm::Job::ErrorAction& response) {
|
||||||
pThis->curFile = QString::fromUtf8(cur_file);
|
pauseElapsedTimer();
|
||||||
|
showDialog();
|
||||||
// We update the current file name in a timeout slot because drawing a string
|
response = Fm::Job::ErrorAction(dlg_->error(err.get(), severity));
|
||||||
// in the UI is expansive. Updating the label text too often cause
|
resumeElapsedTimer();
|
||||||
// significant impact on performance.
|
|
||||||
// if(pThis->dlg)
|
|
||||||
// pThis->dlg->setCurFile(pThis->curFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FmJobErrorAction FileOperation::onFileOpsJobError(FmFileOpsJob* /*job*/, GError* err, FmJobErrorSeverity severity, FileOperation* pThis) {
|
void FileOperation::onJobPrepared() {
|
||||||
pThis->pauseElapsedTimer();
|
if(!elapsedTimer_) {
|
||||||
pThis->showDialog();
|
elapsedTimer_ = new QElapsedTimer();
|
||||||
FmJobErrorAction act = pThis->dlg->error(err, severity);
|
elapsedTimer_->start();
|
||||||
pThis->resumeElapsedTimer();
|
}
|
||||||
return act;
|
if(dlg_) {
|
||||||
}
|
dlg_->setPrepared();
|
||||||
|
|
||||||
void FileOperation::onFileOpsJobFinished(FmFileOpsJob* /*job*/, FileOperation* pThis) {
|
|
||||||
pThis->handleFinish();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileOperation::onFileOpsJobPercent(FmFileOpsJob* job, guint percent, FileOperation* pThis) {
|
|
||||||
if(pThis->dlg) {
|
|
||||||
pThis->dlg->setPercent(percent);
|
|
||||||
pThis->dlg->setDataTransferred(job->finished, job->total);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileOperation::onFileOpsJobPrepared(FmFileOpsJob* /*job*/, FileOperation* pThis) {
|
void FileOperation::onJobFinish() {
|
||||||
if(!pThis->elapsedTimer_) {
|
|
||||||
pThis->elapsedTimer_ = new QElapsedTimer();
|
|
||||||
pThis->elapsedTimer_->start();
|
|
||||||
}
|
|
||||||
if(pThis->dlg) {
|
|
||||||
pThis->dlg->setPrepared();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileOperation::handleFinish() {
|
|
||||||
disconnectJob();
|
disconnectJob();
|
||||||
|
|
||||||
if(uiTimer) {
|
if(uiTimer_) {
|
||||||
uiTimer->stop();
|
uiTimer_->stop();
|
||||||
delete uiTimer;
|
delete uiTimer_;
|
||||||
uiTimer = nullptr;
|
uiTimer_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dlg) {
|
if(dlg_) {
|
||||||
dlg->done(QDialog::Accepted);
|
dlg_->done(QDialog::Accepted);
|
||||||
delete dlg;
|
delete dlg_;
|
||||||
dlg = nullptr;
|
dlg_ = nullptr;
|
||||||
}
|
}
|
||||||
Q_EMIT finished();
|
Q_EMIT finished();
|
||||||
|
|
||||||
/* sepcial handling for trash
|
// special handling for trash job
|
||||||
* FIXME: need to refactor this to use a more elegant way later. */
|
if(type_ == Trash && !job_->isCancelled()) {
|
||||||
if(job_->type == FM_FILE_OP_TRASH) { /* FIXME: direct access to job struct! */
|
auto trashJob = static_cast<Fm::TrashJob*>(job_);
|
||||||
auto unable_to_trash = static_cast<FmPathList*>(g_object_get_data(G_OBJECT(job_), "trash-unsupported"));
|
|
||||||
/* some files cannot be trashed because underlying filesystems don't support it. */
|
/* some files cannot be trashed because underlying filesystems don't support it. */
|
||||||
if(unable_to_trash) { /* delete them instead */
|
auto unsupportedFiles = trashJob->unsupportedFiles();
|
||||||
Fm::FilePathList filesToDel;
|
if(!unsupportedFiles.empty()) { /* delete them instead */
|
||||||
for(GList* l = fm_path_list_peek_head_link(unable_to_trash); l; l = l->next) {
|
|
||||||
filesToDel.push_back(Fm::FilePath{fm_path_to_gfile(FM_PATH(l->data)), false});
|
|
||||||
}
|
|
||||||
/* FIXME: parent window might be already destroyed! */
|
/* FIXME: parent window might be already destroyed! */
|
||||||
QWidget* parent = nullptr; // FIXME: currently, parent window is not set
|
QWidget* parent = nullptr; // FIXME: currently, parent window is not set
|
||||||
if(QMessageBox::question(parent, tr("Error"),
|
if(QMessageBox::question(parent, tr("Error"),
|
||||||
tr("Some files cannot be moved to trash can because "
|
tr("Some files cannot be moved to trash can because "
|
||||||
"the underlying file systems don't support this operation.\n"
|
"the underlying file systems don't support this operation.\n"
|
||||||
"Do you want to delete them instead?")) == QMessageBox::Yes) {
|
"Do you want to delete them instead?")) == QMessageBox::Yes) {
|
||||||
deleteFiles(std::move(filesToDel), false);
|
deleteFiles(std::move(unsupportedFiles), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_object_unref(job_);
|
|
||||||
job_ = nullptr;
|
|
||||||
|
|
||||||
if(autoDestroy_) {
|
if(autoDestroy_) {
|
||||||
delete this;
|
delete this;
|
||||||
@ -249,6 +328,15 @@ FileOperation* FileOperation::copyFiles(Fm::FilePathList srcFiles, Fm::FilePath
|
|||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
FileOperation *FileOperation::copyFiles(FilePathList srcFiles, FilePathList destFiles, QWidget *parent) {
|
||||||
|
qDebug("copy: %s -> %s", srcFiles[0].toString().get(), destFiles[0].toString().get());
|
||||||
|
FileOperation* op = new FileOperation(FileOperation::Copy, std::move(srcFiles), parent);
|
||||||
|
op->setDestFiles(std::move(destFiles));
|
||||||
|
op->run();
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
FileOperation* FileOperation::moveFiles(Fm::FilePathList srcFiles, Fm::FilePath dest, QWidget* parent) {
|
FileOperation* FileOperation::moveFiles(Fm::FilePathList srcFiles, Fm::FilePath dest, QWidget* parent) {
|
||||||
FileOperation* op = new FileOperation(FileOperation::Move, std::move(srcFiles), parent);
|
FileOperation* op = new FileOperation(FileOperation::Move, std::move(srcFiles), parent);
|
||||||
@ -257,6 +345,14 @@ FileOperation* FileOperation::moveFiles(Fm::FilePathList srcFiles, Fm::FilePath
|
|||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
FileOperation *FileOperation::moveFiles(FilePathList srcFiles, FilePathList destFiles, QWidget *parent) {
|
||||||
|
FileOperation* op = new FileOperation(FileOperation::Move, std::move(srcFiles), parent);
|
||||||
|
op->setDestFiles(std::move(destFiles));
|
||||||
|
op->run();
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
//static
|
//static
|
||||||
FileOperation* FileOperation::symlinkFiles(Fm::FilePathList srcFiles, Fm::FilePath dest, QWidget* parent) {
|
FileOperation* FileOperation::symlinkFiles(Fm::FilePathList srcFiles, Fm::FilePath dest, QWidget* parent) {
|
||||||
FileOperation* op = new FileOperation(FileOperation::Link, std::move(srcFiles), parent);
|
FileOperation* op = new FileOperation(FileOperation::Link, std::move(srcFiles), parent);
|
||||||
@ -265,6 +361,14 @@ FileOperation* FileOperation::symlinkFiles(Fm::FilePathList srcFiles, Fm::FilePa
|
|||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
FileOperation *FileOperation::symlinkFiles(FilePathList srcFiles, FilePathList destFiles, QWidget *parent) {
|
||||||
|
FileOperation* op = new FileOperation(FileOperation::Link, std::move(srcFiles), parent);
|
||||||
|
op->setDestFiles(std::move(destFiles));
|
||||||
|
op->run();
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
//static
|
//static
|
||||||
FileOperation* FileOperation::deleteFiles(Fm::FilePathList srcFiles, bool prompt, QWidget* parent) {
|
FileOperation* FileOperation::deleteFiles(Fm::FilePathList srcFiles, bool prompt, QWidget* parent) {
|
||||||
if(prompt) {
|
if(prompt) {
|
||||||
|
@ -24,8 +24,8 @@
|
|||||||
#include "libfmqtglobals.h"
|
#include "libfmqtglobals.h"
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
#include <libfm/fm.h>
|
|
||||||
#include "core/filepath.h"
|
#include "core/filepath.h"
|
||||||
|
#include "core/fileoperationjob.h"
|
||||||
|
|
||||||
class QTimer;
|
class QTimer;
|
||||||
|
|
||||||
@ -37,51 +37,47 @@ class LIBFM_QT_API FileOperation : public QObject {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
enum Type {
|
enum Type {
|
||||||
Copy = FM_FILE_OP_COPY,
|
Copy,
|
||||||
Move = FM_FILE_OP_MOVE,
|
Move,
|
||||||
Link = FM_FILE_OP_LINK,
|
Link,
|
||||||
Delete = FM_FILE_OP_DELETE,
|
Delete,
|
||||||
Trash = FM_FILE_OP_TRASH,
|
Trash,
|
||||||
UnTrash = FM_FILE_OP_UNTRASH,
|
UnTrash,
|
||||||
ChangeAttr = FM_FILE_OP_CHANGE_ATTR
|
ChangeAttr
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FileOperation(Type type, Fm::FilePathList srcFiles, QObject* parent = 0);
|
explicit FileOperation(Type type, Fm::FilePathList srcFiles, QObject* parent = 0);
|
||||||
|
|
||||||
virtual ~FileOperation();
|
virtual ~FileOperation();
|
||||||
|
|
||||||
void setDestination(Fm::FilePath dest);
|
void setDestination(Fm::FilePath dest);
|
||||||
|
|
||||||
void setChmod(mode_t newMode, mode_t newModeMask) {
|
void setDestFiles(FilePathList destFiles);
|
||||||
fm_file_ops_job_set_chmod(job_, newMode, newModeMask);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setChown(gint uid, gint gid) {
|
void setChmod(mode_t newMode, mode_t newModeMask);
|
||||||
fm_file_ops_job_set_chown(job_, uid, gid);
|
|
||||||
}
|
void setChown(uid_t uid, gid_t gid);
|
||||||
|
|
||||||
// This only work for change attr jobs.
|
// This only work for change attr jobs.
|
||||||
void setRecursiveChattr(bool recursive) {
|
void setRecursiveChattr(bool recursive);
|
||||||
fm_file_ops_job_set_recursive(job_, (gboolean)recursive);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool run();
|
bool run();
|
||||||
|
|
||||||
void cancel() {
|
void cancel();
|
||||||
if(job_) {
|
|
||||||
fm_job_cancel(FM_JOB(job_));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isRunning() const {
|
bool isRunning() const {
|
||||||
return job_ ? fm_job_is_running(FM_JOB(job_)) : false;
|
return job_ && !isCancelled();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isCancelled() const {
|
bool isCancelled() const {
|
||||||
return job_ ? fm_job_is_cancelled(FM_JOB(job_)) : false;
|
if(job_) {
|
||||||
|
return job_->isCancelled();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FmFileOpsJob* job() {
|
Fm::FileOperationJob* job() {
|
||||||
return job_;
|
return job_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,32 +89,54 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Type type() {
|
Type type() {
|
||||||
return (Type)job_->type;
|
return type_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// convinient static functions
|
// convinient static functions
|
||||||
static FileOperation* copyFiles(Fm::FilePathList srcFiles, Fm::FilePath dest, QWidget* parent = 0);
|
static FileOperation* copyFiles(Fm::FilePathList srcFiles, Fm::FilePath dest, QWidget* parent = 0);
|
||||||
|
|
||||||
|
static FileOperation* copyFiles(Fm::FilePathList srcFiles, Fm::FilePathList destFiles, QWidget* parent = 0);
|
||||||
|
|
||||||
|
static FileOperation* copyFile(Fm::FilePath srcFile, Fm::FilePath destFile, QWidget* parent = 0) {
|
||||||
|
return copyFiles(FilePathList{std::move(srcFile)}, FilePathList{std::move(destFile)}, parent);
|
||||||
|
}
|
||||||
|
|
||||||
static FileOperation* moveFiles(Fm::FilePathList srcFiles, Fm::FilePath dest, QWidget* parent = 0);
|
static FileOperation* moveFiles(Fm::FilePathList srcFiles, Fm::FilePath dest, QWidget* parent = 0);
|
||||||
|
|
||||||
|
static FileOperation* moveFiles(Fm::FilePathList srcFiles, Fm::FilePathList destFiles, QWidget* parent = 0);
|
||||||
|
|
||||||
|
static FileOperation* moveFile(Fm::FilePath srcFile, Fm::FilePath destFile, QWidget* parent = 0) {
|
||||||
|
return moveFiles(FilePathList{std::move(srcFile)}, FilePathList{std::move(destFile)}, parent);
|
||||||
|
}
|
||||||
|
|
||||||
static FileOperation* symlinkFiles(Fm::FilePathList srcFiles, Fm::FilePath dest, QWidget* parent = 0);
|
static FileOperation* symlinkFiles(Fm::FilePathList srcFiles, Fm::FilePath dest, QWidget* parent = 0);
|
||||||
|
|
||||||
|
static FileOperation* symlinkFiles(Fm::FilePathList srcFiles, Fm::FilePathList destFiles, QWidget* parent = 0);
|
||||||
|
|
||||||
|
static FileOperation* symlinkFile(Fm::FilePath srcFile, Fm::FilePath destFile, QWidget* parent = 0) {
|
||||||
|
return symlinkFiles(FilePathList{std::move(srcFile)}, FilePathList{std::move(destFile)}, parent);
|
||||||
|
}
|
||||||
|
|
||||||
static FileOperation* deleteFiles(Fm::FilePathList srcFiles, bool promp = true, QWidget* parent = 0);
|
static FileOperation* deleteFiles(Fm::FilePathList srcFiles, bool promp = true, QWidget* parent = 0);
|
||||||
|
|
||||||
static FileOperation* trashFiles(Fm::FilePathList srcFiles, bool promp = true, QWidget* parent = 0);
|
static FileOperation* trashFiles(Fm::FilePathList srcFiles, bool promp = true, QWidget* parent = 0);
|
||||||
|
|
||||||
static FileOperation* unTrashFiles(Fm::FilePathList srcFiles, QWidget* parent = 0);
|
static FileOperation* unTrashFiles(Fm::FilePathList srcFiles, QWidget* parent = 0);
|
||||||
|
|
||||||
static FileOperation* changeAttrFiles(Fm::FilePathList srcFiles, QWidget* parent = 0);
|
static FileOperation* changeAttrFiles(Fm::FilePathList srcFiles, QWidget* parent = 0);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void finished();
|
void finished();
|
||||||
|
|
||||||
private:
|
private Q_SLOTS:
|
||||||
static gint onFileOpsJobAsk(FmFileOpsJob* job, const char* question, char* const* options, FileOperation* pThis);
|
void onJobPrepared();
|
||||||
static gint onFileOpsJobAskRename(FmFileOpsJob* job, FmFileInfo* src, FmFileInfo* dest, char** new_name, FileOperation* pThis);
|
void onJobFinish();
|
||||||
static FmJobErrorAction onFileOpsJobError(FmFileOpsJob* job, GError* err, FmJobErrorSeverity severity, FileOperation* pThis);
|
void onJobCancalled();
|
||||||
static void onFileOpsJobPrepared(FmFileOpsJob* job, FileOperation* pThis);
|
void onJobError(const GErrorPtr& err, Fm::Job::ErrorSeverity severity, Fm::Job::ErrorAction& response);
|
||||||
static void onFileOpsJobCurFile(FmFileOpsJob* job, const char* cur_file, FileOperation* pThis);
|
void onJobFileExists(const FileInfo& src, const FileInfo& dest, Fm::FileOperationJob::FileExistsAction& response, FilePath& newDest);
|
||||||
static void onFileOpsJobPercent(FmFileOpsJob* job, guint percent, FileOperation* pThis);
|
|
||||||
static void onFileOpsJobFinished(FmFileOpsJob* job, FileOperation* pThis);
|
private:
|
||||||
static void onFileOpsJobCancelled(FmFileOpsJob* job, FileOperation* pThis);
|
|
||||||
|
|
||||||
void handleFinish();
|
|
||||||
void disconnectJob();
|
void disconnectJob();
|
||||||
void showDialog();
|
void showDialog();
|
||||||
|
|
||||||
@ -146,11 +164,13 @@ private Q_SLOTS:
|
|||||||
void onUiTimeout();
|
void onUiTimeout();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FmFileOpsJob* job_;
|
Type type_;
|
||||||
FileOperationDialog* dlg;
|
FileOperationJob* job_;
|
||||||
Fm::FilePath destPath;
|
FileOperationDialog* dlg_;
|
||||||
Fm::FilePathList srcPaths;
|
FilePath destPath_;
|
||||||
QTimer* uiTimer;
|
FilePath curFilePath_;
|
||||||
|
FilePathList srcPaths_;
|
||||||
|
QTimer* uiTimer_;
|
||||||
QElapsedTimer* elapsedTimer_;
|
QElapsedTimer* elapsedTimer_;
|
||||||
qint64 lastElapsed_;
|
qint64 lastElapsed_;
|
||||||
bool updateRemainingTime_;
|
bool updateRemainingTime_;
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
#include "ui_file-operation-dialog.h"
|
#include "ui_file-operation-dialog.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
|
||||||
FileOperationDialog::FileOperationDialog(FileOperation* _operation):
|
FileOperationDialog::FileOperationDialog(FileOperation* _operation):
|
||||||
@ -41,35 +42,35 @@ FileOperationDialog::FileOperationDialog(FileOperation* _operation):
|
|||||||
QString title;
|
QString title;
|
||||||
QString message;
|
QString message;
|
||||||
switch(_operation->type()) {
|
switch(_operation->type()) {
|
||||||
case FM_FILE_OP_MOVE:
|
case FileOperation::Move:
|
||||||
title = tr("Move files");
|
title = tr("Move files");
|
||||||
message = tr("Moving the following files to destination folder:");
|
message = tr("Moving the following files to destination folder:");
|
||||||
break;
|
break;
|
||||||
case FM_FILE_OP_COPY:
|
case FileOperation::Copy:
|
||||||
title = tr("Copy Files");
|
title = tr("Copy Files");
|
||||||
message = tr("Copying the following files to destination folder:");
|
message = tr("Copying the following files to destination folder:");
|
||||||
break;
|
break;
|
||||||
case FM_FILE_OP_TRASH:
|
case FileOperation::Trash:
|
||||||
title = tr("Trash Files");
|
title = tr("Trash Files");
|
||||||
message = tr("Moving the following files to trash can:");
|
message = tr("Moving the following files to trash can:");
|
||||||
break;
|
break;
|
||||||
case FM_FILE_OP_DELETE:
|
case FileOperation::Delete:
|
||||||
title = tr("Delete Files");
|
title = tr("Delete Files");
|
||||||
message = tr("Deleting the following files:");
|
message = tr("Deleting the following files:");
|
||||||
ui->dest->hide();
|
ui->dest->hide();
|
||||||
ui->destLabel->hide();
|
ui->destLabel->hide();
|
||||||
break;
|
break;
|
||||||
case FM_FILE_OP_LINK:
|
case FileOperation::Link:
|
||||||
title = tr("Create Symlinks");
|
title = tr("Create Symlinks");
|
||||||
message = tr("Creating symlinks for the following files:");
|
message = tr("Creating symlinks for the following files:");
|
||||||
break;
|
break;
|
||||||
case FM_FILE_OP_CHANGE_ATTR:
|
case FileOperation::ChangeAttr:
|
||||||
title = tr("Change Attributes");
|
title = tr("Change Attributes");
|
||||||
message = tr("Changing attributes of the following files:");
|
message = tr("Changing attributes of the following files:");
|
||||||
ui->dest->hide();
|
ui->dest->hide();
|
||||||
ui->destLabel->hide();
|
ui->destLabel->hide();
|
||||||
break;
|
break;
|
||||||
case FM_FILE_OP_UNTRASH:
|
case FileOperation::UnTrash:
|
||||||
title = tr("Restore Trashed Files");
|
title = tr("Restore Trashed Files");
|
||||||
message = tr("Restoring the following files from trash can:");
|
message = tr("Restoring the following files from trash can:");
|
||||||
ui->dest->hide();
|
ui->dest->hide();
|
||||||
@ -100,47 +101,53 @@ int FileOperationDialog::ask(QString /*question*/, char* const* /*options*/) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FileOperationDialog::askRename(FmFileInfo* src, FmFileInfo* dest, QString& new_name) {
|
|
||||||
int ret;
|
FileOperationJob::FileExistsAction FileOperationDialog::askRename(const FileInfo &src, const FileInfo &dest, FilePath &newDest) {
|
||||||
|
FileOperationJob::FileExistsAction ret;
|
||||||
if(defaultOption == -1) { // default action is not set, ask the user
|
if(defaultOption == -1) { // default action is not set, ask the user
|
||||||
RenameDialog dlg(src, dest, this);
|
RenameDialog dlg(src, dest, this);
|
||||||
dlg.exec();
|
dlg.exec();
|
||||||
switch(dlg.action()) {
|
switch(dlg.action()) {
|
||||||
case RenameDialog::ActionOverwrite:
|
case RenameDialog::ActionOverwrite:
|
||||||
ret = FM_FILE_OP_OVERWRITE;
|
ret = FileOperationJob::OVERWRITE;
|
||||||
if(dlg.applyToAll()) {
|
if(dlg.applyToAll()) {
|
||||||
defaultOption = ret;
|
defaultOption = ret;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RenameDialog::ActionRename:
|
case RenameDialog::ActionRename: {
|
||||||
ret = FM_FILE_OP_RENAME;
|
ret = FileOperationJob::RENAME;
|
||||||
new_name = dlg.newName();
|
auto newName = dlg.newName();
|
||||||
|
if(!newName.isEmpty()) {
|
||||||
|
auto destDirPath = dest.path().parent();
|
||||||
|
newDest = destDirPath.child(newName.toUtf8().constData());
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case RenameDialog::ActionIgnore:
|
case RenameDialog::ActionIgnore:
|
||||||
ret = FM_FILE_OP_SKIP;
|
ret = FileOperationJob::SKIP;
|
||||||
if(dlg.applyToAll()) {
|
if(dlg.applyToAll()) {
|
||||||
defaultOption = ret;
|
defaultOption = ret;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = FM_FILE_OP_CANCEL;
|
ret = FileOperationJob::CANCEL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ret = defaultOption;
|
ret = (FileOperationJob::FileExistsAction)defaultOption;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
FmJobErrorAction FileOperationDialog::error(GError* err, FmJobErrorSeverity severity) {
|
Job::ErrorAction FileOperationDialog::error(GError* err, Job::ErrorSeverity severity) {
|
||||||
if(severity >= FM_JOB_ERROR_MODERATE) {
|
if(severity >= Job::ErrorSeverity::MODERATE) {
|
||||||
if(severity == FM_JOB_ERROR_CRITICAL) {
|
if(severity == Job::ErrorSeverity::CRITICAL) {
|
||||||
QMessageBox::critical(this, tr("Error"), QString::fromUtf8(err->message));
|
QMessageBox::critical(this, tr("Error"), QString::fromUtf8(err->message));
|
||||||
return FM_JOB_ABORT;
|
return Job::ErrorAction::ABORT;
|
||||||
}
|
}
|
||||||
if (ignoreNonCriticalErrors_) {
|
if (ignoreNonCriticalErrors_) {
|
||||||
return FM_JOB_CONTINUE;
|
return Job::ErrorAction::CONTINUE;
|
||||||
}
|
}
|
||||||
QMessageBox::StandardButton stb = QMessageBox::critical(this, tr("Error"), QString::fromUtf8(err->message),
|
QMessageBox::StandardButton stb = QMessageBox::critical(this, tr("Error"), QString::fromUtf8(err->message),
|
||||||
QMessageBox::Ok | QMessageBox::Ignore);
|
QMessageBox::Ok | QMessageBox::Ignore);
|
||||||
@ -148,7 +155,7 @@ FmJobErrorAction FileOperationDialog::error(GError* err, FmJobErrorSeverity seve
|
|||||||
ignoreNonCriticalErrors_ = true;
|
ignoreNonCriticalErrors_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return FM_JOB_CONTINUE;
|
return Job::ErrorAction::CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileOperationDialog::setCurFile(QString cur_file) {
|
void FileOperationDialog::setCurFile(QString cur_file) {
|
||||||
@ -156,15 +163,22 @@ void FileOperationDialog::setCurFile(QString cur_file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FileOperationDialog::setDataTransferred(uint64_t finishedSize, std::uint64_t totalSize) {
|
void FileOperationDialog::setDataTransferred(uint64_t finishedSize, std::uint64_t totalSize) {
|
||||||
ui->dataTransferred->setText(QString("%1 / %2")
|
ui->filesProcessed->setText(QString("%1 / %2")
|
||||||
.arg(formatFileSize(finishedSize, fm_config->si_unit))
|
.arg(formatFileSize(finishedSize, fm_config->si_unit))
|
||||||
.arg(formatFileSize(totalSize, fm_config->si_unit)));
|
.arg(formatFileSize(totalSize, fm_config->si_unit)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileOperationDialog::setFilesProcessed(uint64_t finishedCount, uint64_t totalCount) {
|
||||||
|
ui->filesProcessed->setText(QString("%1 / %2")
|
||||||
|
.arg(finishedCount)
|
||||||
|
.arg(totalCount));
|
||||||
|
}
|
||||||
|
|
||||||
void FileOperationDialog::setPercent(unsigned int percent) {
|
void FileOperationDialog::setPercent(unsigned int percent) {
|
||||||
ui->progressBar->setValue(percent);
|
ui->progressBar->setValue(percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FileOperationDialog::setRemainingTime(unsigned int sec) {
|
void FileOperationDialog::setRemainingTime(unsigned int sec) {
|
||||||
unsigned int min = 0;
|
unsigned int min = 0;
|
||||||
unsigned int hr = 0;
|
unsigned int hr = 0;
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <libfm/fm.h>
|
#include <libfm/fm.h>
|
||||||
#include "core/filepath.h"
|
#include "core/filepath.h"
|
||||||
#include "core/fileinfo.h"
|
#include "core/fileinfo.h"
|
||||||
|
#include "core/fileoperationjob.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class FileOperationDialog;
|
class FileOperationDialog;
|
||||||
@ -46,12 +47,15 @@ public:
|
|||||||
void setDestPath(const Fm::FilePath& dest);
|
void setDestPath(const Fm::FilePath& dest);
|
||||||
|
|
||||||
int ask(QString question, char* const* options);
|
int ask(QString question, char* const* options);
|
||||||
int askRename(FmFileInfo* src, FmFileInfo* dest, QString& new_name);
|
|
||||||
FmJobErrorAction error(GError* err, FmJobErrorSeverity severity);
|
FileOperationJob::FileExistsAction askRename(const FileInfo& src, const FileInfo& dest, FilePath& newDest);
|
||||||
|
|
||||||
|
Job::ErrorAction error(GError* err, Job::ErrorSeverity severity);
|
||||||
void setPrepared();
|
void setPrepared();
|
||||||
void setCurFile(QString cur_file);
|
void setCurFile(QString cur_file);
|
||||||
void setPercent(unsigned int percent);
|
void setPercent(unsigned int percent);
|
||||||
void setDataTransferred(std::uint64_t finishedSize, std::uint64_t totalSize);
|
void setDataTransferred(std::uint64_t finishedSize, std::uint64_t totalSize);
|
||||||
|
void setFilesProcessed(std::uint64_t finishedCount, std::uint64_t totalCount);
|
||||||
void setRemainingTime(unsigned int sec);
|
void setRemainingTime(unsigned int sec);
|
||||||
|
|
||||||
virtual void reject();
|
virtual void reject();
|
||||||
|
69
src/fileoperationdialog_p.h
Normal file
69
src/fileoperationdialog_p.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* 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_FILEOPERATIONDIALOG_P_H
|
||||||
|
#define FM_FILEOPERATIONDIALOG_P_H
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QStyleOption>
|
||||||
|
#include <QLabel>
|
||||||
|
|
||||||
|
namespace Fm {
|
||||||
|
|
||||||
|
class ElidedLabel : public QLabel {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ElidedLabel(QWidget *parent = 0, Qt::WindowFlags f = Qt::WindowFlags()):
|
||||||
|
QLabel(parent, f),
|
||||||
|
lastWidth_(0) {
|
||||||
|
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||||
|
// set a min width to prevent the window from widening with long texts
|
||||||
|
setMinimumWidth(fontMetrics().averageCharWidth() * 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// A simplified version of QLabel::paintEvent() without pixmap or shortcut but with eliding.
|
||||||
|
void paintEvent(QPaintEvent* /*event*/) override {
|
||||||
|
QRect cr = contentsRect().adjusted(margin(), margin(), -margin(), -margin());
|
||||||
|
QString txt = text();
|
||||||
|
// if the text is changed or its rect is resized (due to window resizing),
|
||||||
|
// find whether it needs to be elided...
|
||||||
|
if (txt != lastText_ || cr.width() != lastWidth_) {
|
||||||
|
lastText_ = txt;
|
||||||
|
lastWidth_ = cr.width();
|
||||||
|
elidedText_ = fontMetrics().elidedText(txt, Qt::ElideMiddle, cr.width());
|
||||||
|
}
|
||||||
|
// ... then, draw the (elided) text
|
||||||
|
if(!elidedText_.isEmpty()) {
|
||||||
|
QPainter painter(this);
|
||||||
|
QStyleOption opt;
|
||||||
|
opt.initFrom(this);
|
||||||
|
style()->drawItemText(&painter, cr, alignment(), opt.palette, isEnabled(), elidedText_, foregroundRole());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString elidedText_;
|
||||||
|
QString lastText_;
|
||||||
|
int lastWidth_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FM_FILEOPERATIONDIALOG_P_H
|
@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
#include "filepropsdialog.h"
|
#include "filepropsdialog.h"
|
||||||
#include "ui_file-props.h"
|
#include "ui_file-props.h"
|
||||||
#include "icontheme.h"
|
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
#include "fileoperation.h"
|
#include "fileoperation.h"
|
||||||
#include <QStringBuilder>
|
#include <QStringBuilder>
|
||||||
@ -403,9 +402,9 @@ void FilePropsDialog::accept() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check if chown or chmod is needed
|
// check if chown or chmod is needed
|
||||||
gint32 newUid = uidFromName(ui->owner->text());
|
uid_t newUid = uidFromName(ui->owner->text());
|
||||||
gint32 newGid = gidFromName(ui->ownerGroup->text());
|
gid_t newGid = gidFromName(ui->ownerGroup->text());
|
||||||
bool needChown = (newUid != -1 && newUid != uid) || (newGid != -1 && newGid != gid);
|
bool needChown = (newUid != INVALID_UID && newUid != uid) || (newGid != INVALID_GID && newGid != gid);
|
||||||
|
|
||||||
int newOwnerPermSel = ui->ownerPerm->currentIndex();
|
int newOwnerPermSel = ui->ownerPerm->currentIndex();
|
||||||
int newGroupPermSel = ui->groupPerm->currentIndex();
|
int newGroupPermSel = ui->groupPerm->currentIndex();
|
||||||
@ -421,10 +420,10 @@ void FilePropsDialog::accept() {
|
|||||||
if(needChown) {
|
if(needChown) {
|
||||||
// don't do chown if new uid/gid and the original ones are actually the same.
|
// don't do chown if new uid/gid and the original ones are actually the same.
|
||||||
if(newUid == uid) {
|
if(newUid == uid) {
|
||||||
newUid = -1;
|
newUid = INVALID_UID;
|
||||||
}
|
}
|
||||||
if(newGid == gid) {
|
if(newGid == gid) {
|
||||||
newGid = -1;
|
newGid = INVALID_GID;
|
||||||
}
|
}
|
||||||
op->setChown(newUid, newGid);
|
op->setChown(newUid, newGid);
|
||||||
}
|
}
|
||||||
|
@ -80,8 +80,8 @@ private:
|
|||||||
|
|
||||||
std::shared_ptr<const Fm::MimeType> mimeType; // mime type of the files
|
std::shared_ptr<const Fm::MimeType> mimeType; // mime type of the files
|
||||||
|
|
||||||
gint32 uid; // owner uid of the files, -1 means all files do not have the same uid
|
uid_t uid; // owner uid of the files, INVALID_UID means all files do not have the same uid
|
||||||
gint32 gid; // owner gid of the files, -1 means all files do not have the same uid
|
gid_t gid; // owner gid of the files, INVALID_GID means all files do not have the same uid
|
||||||
mode_t ownerPerm; // read permission of the files, -1 means not all files have the same value
|
mode_t ownerPerm; // read permission of the files, -1 means not all files have the same value
|
||||||
int ownerPermSel;
|
int ownerPermSel;
|
||||||
mode_t groupPerm; // read permission of the files, -1 means not all files have the same value
|
mode_t groupPerm; // read permission of the files, -1 means not all files have the same value
|
||||||
|
@ -33,7 +33,7 @@ FileSearchDialog::FileSearchDialog(QStringList paths, QWidget* parent, Qt::Windo
|
|||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
ui->minSize->setMaximum(std::numeric_limits<int>().max());
|
ui->minSize->setMaximum(std::numeric_limits<int>().max());
|
||||||
ui->maxSize->setMaximum(std::numeric_limits<int>().max());
|
ui->maxSize->setMaximum(std::numeric_limits<int>().max());
|
||||||
Q_FOREACH(const QString& path, paths) {
|
for(const QString& path : qAsConst(paths)) {
|
||||||
ui->listView->addItem(path);
|
ui->listView->addItem(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ void FileSearchDialog::accept() {
|
|||||||
fm_search_set_min_mtime(search, ui->minTime->date().toString(QStringLiteral("yyyy-MM-dd")).toUtf8().constData());
|
fm_search_set_min_mtime(search, ui->minTime->date().toString(QStringLiteral("yyyy-MM-dd")).toUtf8().constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
searchUri_ = Path::wrapPtr(fm_search_dup_path(search));
|
searchUri_ = FilePath{fm_search_to_gfile(search), false};
|
||||||
|
|
||||||
fm_search_free(search);
|
fm_search_free(search);
|
||||||
}
|
}
|
||||||
@ -144,7 +144,8 @@ void FileSearchDialog::onAddPath() {
|
|||||||
|
|
||||||
void FileSearchDialog::onRemovePath() {
|
void FileSearchDialog::onRemovePath() {
|
||||||
// remove selected items
|
// remove selected items
|
||||||
Q_FOREACH(QListWidgetItem* item, ui->listView->selectedItems()) {
|
const auto itemList = ui->listView->selectedItems();
|
||||||
|
for(QListWidgetItem* const item : itemList) {
|
||||||
delete item;
|
delete item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "libfmqtglobals.h"
|
#include "libfmqtglobals.h"
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include "path.h"
|
#include "core/filepath.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class SearchDialog;
|
class SearchDialog;
|
||||||
@ -35,7 +35,7 @@ public:
|
|||||||
explicit FileSearchDialog(QStringList paths = QStringList(), QWidget* parent = 0, Qt::WindowFlags f = 0);
|
explicit FileSearchDialog(QStringList paths = QStringList(), QWidget* parent = 0, Qt::WindowFlags f = 0);
|
||||||
~FileSearchDialog();
|
~FileSearchDialog();
|
||||||
|
|
||||||
Path searchUri() const {
|
const FilePath& searchUri() const {
|
||||||
return searchUri_;
|
return searchUri_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ private Q_SLOTS:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::SearchDialog* ui;
|
Ui::SearchDialog* ui;
|
||||||
Path searchUri_;
|
FilePath searchUri_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -229,9 +229,9 @@ void fm_search_set_min_mtime(FmSearch* search, const char* mtime)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* really build the path */
|
/* really build the path */
|
||||||
FmPath* fm_search_dup_path(FmSearch* search)
|
GFile* fm_search_to_gfile(FmSearch* search)
|
||||||
{
|
{
|
||||||
FmPath* search_path = NULL;
|
GFile* search_path = NULL;
|
||||||
GString* search_str = g_string_sized_new(1024);
|
GString* search_str = g_string_sized_new(1024);
|
||||||
/* build the search:// URI to perform the search */
|
/* build the search:// URI to perform the search */
|
||||||
g_string_append(search_str, "search://");
|
g_string_append(search_str, "search://");
|
||||||
@ -310,7 +310,7 @@ FmPath* fm_search_dup_path(FmSearch* search)
|
|||||||
if(search->max_mtime)
|
if(search->max_mtime)
|
||||||
g_string_append_printf(search_str, "&max_mtime=%s", search->max_mtime);
|
g_string_append_printf(search_str, "&max_mtime=%s", search->max_mtime);
|
||||||
|
|
||||||
search_path = fm_path_new_for_uri(search_str->str);
|
search_path = g_file_new_for_uri(search_str->str);
|
||||||
g_string_free(search_str, TRUE);
|
g_string_free(search_str, TRUE);
|
||||||
}
|
}
|
||||||
return search_path;
|
return search_path;
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
#ifndef _FM_SEARCH_H_
|
#ifndef _FM_SEARCH_H_
|
||||||
#define _FM_SEARCH_H_
|
#define _FM_SEARCH_H_
|
||||||
|
|
||||||
#include <libfm/fm.h>
|
#include <gio/gio.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ typedef struct _FmSearch FmSearch;
|
|||||||
FmSearch* fm_search_new(void);
|
FmSearch* fm_search_new(void);
|
||||||
void fm_search_free(FmSearch* search);
|
void fm_search_free(FmSearch* search);
|
||||||
|
|
||||||
FmPath* fm_search_dup_path(FmSearch* search);
|
GFile* fm_search_to_gfile(FmSearch* search);
|
||||||
|
|
||||||
gboolean fm_search_get_recursive(FmSearch* search);
|
gboolean fm_search_get_recursive(FmSearch* search);
|
||||||
void fm_search_set_recursive(FmSearch* search, gboolean recursive);
|
void fm_search_set_recursive(FmSearch* search, gboolean recursive);
|
||||||
|
@ -111,6 +111,16 @@ void FolderItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& op
|
|||||||
auto file = index.data(fileInfoRole_).value<std::shared_ptr<const Fm::FileInfo>>();
|
auto file = index.data(fileInfoRole_).value<std::shared_ptr<const Fm::FileInfo>>();
|
||||||
const auto& emblems = file ? file->emblems() : icon_emblems;
|
const auto& emblems = file ? file->emblems() : icon_emblems;
|
||||||
|
|
||||||
|
QStyleOptionViewItem opt = option;
|
||||||
|
initStyleOption(&opt, index);
|
||||||
|
|
||||||
|
// distinguish the hidden items visually by making their texts italic
|
||||||
|
if(file && file->isHidden()) {
|
||||||
|
QFont f(opt.font);
|
||||||
|
f.setItalic(true);
|
||||||
|
opt.font = f;
|
||||||
|
}
|
||||||
|
|
||||||
bool isSymlink = file && file->isSymlink();
|
bool isSymlink = file && file->isSymlink();
|
||||||
// vertical layout (icon mode, thumbnail mode)
|
// vertical layout (icon mode, thumbnail mode)
|
||||||
if(option.decorationPosition == QStyleOptionViewItem::Top ||
|
if(option.decorationPosition == QStyleOptionViewItem::Top ||
|
||||||
@ -118,8 +128,6 @@ void FolderItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& op
|
|||||||
painter->save();
|
painter->save();
|
||||||
painter->setClipRect(option.rect);
|
painter->setClipRect(option.rect);
|
||||||
|
|
||||||
QStyleOptionViewItem opt = option;
|
|
||||||
initStyleOption(&opt, index);
|
|
||||||
opt.decorationAlignment = Qt::AlignHCenter | Qt::AlignTop;
|
opt.decorationAlignment = Qt::AlignHCenter | Qt::AlignTop;
|
||||||
opt.displayAlignment = Qt::AlignTop | Qt::AlignHCenter;
|
opt.displayAlignment = Qt::AlignTop | Qt::AlignHCenter;
|
||||||
|
|
||||||
@ -168,12 +176,10 @@ void FolderItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& op
|
|||||||
// let QStyledItemDelegate does its default painting
|
// let QStyledItemDelegate does its default painting
|
||||||
// FIXME: For better text alignment, here we should increase
|
// FIXME: For better text alignment, here we should increase
|
||||||
// the icon width if it's smaller that the requested size
|
// the icon width if it's smaller that the requested size
|
||||||
QStyledItemDelegate::paint(painter, option, index);
|
QStyledItemDelegate::paint(painter, opt, index);
|
||||||
|
|
||||||
// draw emblems if needed
|
// draw emblems if needed
|
||||||
if(isSymlink || !emblems.empty()) {
|
if(isSymlink || !emblems.empty()) {
|
||||||
QStyleOptionViewItem opt = option;
|
|
||||||
initStyleOption(&opt, index);
|
|
||||||
QIcon::Mode iconMode = iconModeFromState(opt.state);
|
QIcon::Mode iconMode = iconModeFromState(opt.state);
|
||||||
// draw some emblems for the item if needed
|
// draw some emblems for the item if needed
|
||||||
if(isSymlink) {
|
if(isSymlink) {
|
||||||
@ -249,7 +255,8 @@ void FolderItemDelegate::drawText(QPainter* painter, QStyleOptionViewItem& opt,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ?????
|
// Respect the active and inactive palettes (some styles can use different colors for them).
|
||||||
|
// Also, take into account a probable disabled palette.
|
||||||
QPalette::ColorGroup cg = (opt.state & QStyle::State_Enabled)
|
QPalette::ColorGroup cg = (opt.state & QStyle::State_Enabled)
|
||||||
? (opt.state & QStyle::State_Active)
|
? (opt.state & QStyle::State_Active)
|
||||||
? QPalette::Active
|
? QPalette::Active
|
||||||
@ -350,8 +357,13 @@ QWidget* FolderItemDelegate::createEditor(QWidget* parent, const QStyleOptionVie
|
|||||||
return textEdit;
|
return textEdit;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// return the default line-edit in compact view
|
// return the default line-edit in other views and
|
||||||
return QStyledItemDelegate::createEditor(parent, option, index);
|
// ensure that its background isn't transparent (on the side-pane)
|
||||||
|
QWidget* editor = QStyledItemDelegate::createEditor(parent, option, index);
|
||||||
|
QPalette p = editor->palette();
|
||||||
|
p.setColor(QPalette::Base, QApplication::palette().color(QPalette::Base));
|
||||||
|
editor->setPalette(p);
|
||||||
|
return editor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "foldermodel.h"
|
#include "foldermodel.h"
|
||||||
#include "icontheme.h"
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <QtAlgorithms>
|
#include <QtAlgorithms>
|
||||||
@ -40,7 +39,6 @@ FolderModel::FolderModel():
|
|||||||
}
|
}
|
||||||
|
|
||||||
FolderModel::~FolderModel() {
|
FolderModel::~FolderModel() {
|
||||||
qDebug("delete FolderModel");
|
|
||||||
// if the thumbnail requests list is not empty, cancel them
|
// if the thumbnail requests list is not empty, cancel them
|
||||||
for(auto job: pendingThumbnailJobs_) {
|
for(auto job: pendingThumbnailJobs_) {
|
||||||
job->cancel();
|
job->cancel();
|
||||||
@ -87,6 +85,7 @@ void FolderModel::onFilesAdded(const Fm::FileInfoList& files) {
|
|||||||
items.append(item);
|
items.append(item);
|
||||||
}
|
}
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
|
Q_EMIT filesAdded(files);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FolderModel::onFilesChanged(std::vector<Fm::FileInfoPair>& files) {
|
void FolderModel::onFilesChanged(std::vector<Fm::FileInfoPair>& files) {
|
||||||
@ -161,7 +160,8 @@ void FolderModel::setCutFiles(const QItemSelection& selection) {
|
|||||||
if(!selection.isEmpty()) {
|
if(!selection.isEmpty()) {
|
||||||
auto cutFilesHashSet = std::make_shared<HashSet>();
|
auto cutFilesHashSet = std::make_shared<HashSet>();
|
||||||
folder_->setCutFiles(cutFilesHashSet);
|
folder_->setCutFiles(cutFilesHashSet);
|
||||||
for(const auto& index : selection.indexes()) {
|
const auto indexes = selection.indexes();
|
||||||
|
for(const auto& index : indexes) {
|
||||||
auto item = itemFromIndex(index);
|
auto item = itemFromIndex(index);
|
||||||
item->bindCutFiles(cutFilesHashSet);
|
item->bindCutFiles(cutFilesHashSet);
|
||||||
cutFilesHashSet->insert(item->info->path().hash());
|
cutFilesHashSet->insert(item->info->path().hash());
|
||||||
@ -230,6 +230,8 @@ QVariant FolderModel::data(const QModelIndex& index, int role/* = Qt::DisplayRol
|
|||||||
return item->displaySize();
|
return item->displaySize();
|
||||||
case ColumnFileOwner:
|
case ColumnFileOwner:
|
||||||
return item->ownerName();
|
return item->ownerName();
|
||||||
|
case ColumnFileGroup:
|
||||||
|
return item->ownerGroup();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -275,6 +277,9 @@ QVariant FolderModel::headerData(int section, Qt::Orientation orientation, int r
|
|||||||
case ColumnFileOwner:
|
case ColumnFileOwner:
|
||||||
title = tr("Owner");
|
title = tr("Owner");
|
||||||
break;
|
break;
|
||||||
|
case ColumnFileGroup:
|
||||||
|
title = tr("Group");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return QVariant(title);
|
return QVariant(title);
|
||||||
}
|
}
|
||||||
@ -361,12 +366,12 @@ QList< FolderModelItem >::iterator FolderModel::findItemByFileInfo(const Fm::Fil
|
|||||||
}
|
}
|
||||||
|
|
||||||
QStringList FolderModel::mimeTypes() const {
|
QStringList FolderModel::mimeTypes() const {
|
||||||
qDebug("FolderModel::mimeTypes");
|
//qDebug("FolderModel::mimeTypes");
|
||||||
QStringList types = QAbstractItemModel::mimeTypes();
|
QStringList types = QAbstractItemModel::mimeTypes();
|
||||||
// now types contains "application/x-qabstractitemmodeldatalist"
|
// now types contains "application/x-qabstractitemmodeldatalist"
|
||||||
|
|
||||||
// add support for freedesktop Xdnd direct save (XDS) protocol.
|
// add support for freedesktop Xdnd direct save (XDS) protocol.
|
||||||
// http://www.freedesktop.org/wiki/Specifications/XDS/#index4h2
|
// https://www.freedesktop.org/wiki/Specifications/XDS/#index4h2
|
||||||
// the real implementation is in FolderView::childDropEvent().
|
// the real implementation is in FolderView::childDropEvent().
|
||||||
types << "XdndDirectSave0";
|
types << "XdndDirectSave0";
|
||||||
types << "text/uri-list";
|
types << "text/uri-list";
|
||||||
@ -376,7 +381,7 @@ QStringList FolderModel::mimeTypes() const {
|
|||||||
|
|
||||||
QMimeData* FolderModel::mimeData(const QModelIndexList& indexes) const {
|
QMimeData* FolderModel::mimeData(const QModelIndexList& indexes) const {
|
||||||
QMimeData* data = QAbstractItemModel::mimeData(indexes);
|
QMimeData* data = QAbstractItemModel::mimeData(indexes);
|
||||||
qDebug("FolderModel::mimeData");
|
//qDebug("FolderModel::mimeData");
|
||||||
// build a uri list
|
// build a uri list
|
||||||
QByteArray urilist;
|
QByteArray urilist;
|
||||||
urilist.reserve(4096);
|
urilist.reserve(4096);
|
||||||
@ -398,7 +403,7 @@ QMimeData* FolderModel::mimeData(const QModelIndexList& indexes) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool FolderModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) {
|
bool FolderModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) {
|
||||||
qDebug("FolderModel::dropMimeData");
|
//qDebug("FolderModel::dropMimeData");
|
||||||
if(!folder_ || !data) {
|
if(!folder_ || !data) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -413,7 +418,12 @@ bool FolderModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int
|
|||||||
info = fileInfoFromIndex(itemIndex);
|
info = fileInfoFromIndex(itemIndex);
|
||||||
}
|
}
|
||||||
if(info) {
|
if(info) {
|
||||||
destPath = info->path();
|
if (info->isDir()) {
|
||||||
|
destPath = info->path();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
destPath = path(); // don't drop on file
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
@ -425,7 +435,7 @@ bool FolderModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int
|
|||||||
|
|
||||||
// FIXME: should we put this in dropEvent handler of FolderView instead?
|
// FIXME: should we put this in dropEvent handler of FolderView instead?
|
||||||
if(data->hasUrls()) {
|
if(data->hasUrls()) {
|
||||||
qDebug("drop action: %d", action);
|
//qDebug("drop action: %d", action);
|
||||||
auto srcPaths = pathListFromQUrls(data->urls());
|
auto srcPaths = pathListFromQUrls(data->urls());
|
||||||
switch(action) {
|
switch(action) {
|
||||||
case Qt::CopyAction:
|
case Qt::CopyAction:
|
||||||
@ -436,6 +446,7 @@ bool FolderModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int
|
|||||||
break;
|
break;
|
||||||
case Qt::LinkAction:
|
case Qt::LinkAction:
|
||||||
FileOperation::symlinkFiles(srcPaths, destPath);
|
FileOperation::symlinkFiles(srcPaths, destPath);
|
||||||
|
/* Falls through. */
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -448,7 +459,7 @@ bool FolderModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
Qt::DropActions FolderModel::supportedDropActions() const {
|
Qt::DropActions FolderModel::supportedDropActions() const {
|
||||||
qDebug("FolderModel::supportedDropActions");
|
//qDebug("FolderModel::supportedDropActions");
|
||||||
return Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
|
return Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@ public:
|
|||||||
ColumnFileSize,
|
ColumnFileSize,
|
||||||
ColumnFileMTime,
|
ColumnFileMTime,
|
||||||
ColumnFileOwner,
|
ColumnFileOwner,
|
||||||
|
ColumnFileGroup,
|
||||||
NumOfColumns
|
NumOfColumns
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -98,6 +99,7 @@ public:
|
|||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void thumbnailLoaded(const QModelIndex& index, int size);
|
void thumbnailLoaded(const QModelIndex& index, int size);
|
||||||
void fileSizeChanged(const QModelIndex& index);
|
void fileSizeChanged(const QModelIndex& index);
|
||||||
|
void filesAdded(FileInfoList infoList);
|
||||||
|
|
||||||
protected Q_SLOTS:
|
protected Q_SLOTS:
|
||||||
|
|
||||||
|
@ -43,10 +43,7 @@ QString FolderModelItem::ownerName() const {
|
|||||||
QString name;
|
QString name;
|
||||||
auto user = Fm::UserInfoCache::globalInstance()->userFromId(info->uid());
|
auto user = Fm::UserInfoCache::globalInstance()->userFromId(info->uid());
|
||||||
if(user) {
|
if(user) {
|
||||||
name = user->realName();
|
name = user->name();
|
||||||
if(name.isEmpty()) {
|
|
||||||
name = user->name();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include "icontheme.h"
|
|
||||||
|
|
||||||
#include "core/folder.h"
|
#include "core/folder.h"
|
||||||
|
|
||||||
|
@ -45,12 +45,16 @@
|
|||||||
#include <QX11Info> // for XDS support
|
#include <QX11Info> // for XDS support
|
||||||
#include <xcb/xcb.h> // for XDS support
|
#include <xcb/xcb.h> // for XDS support
|
||||||
#include "xdndworkaround.h" // for XDS support
|
#include "xdndworkaround.h" // for XDS support
|
||||||
#include "path.h"
|
|
||||||
#include "folderview_p.h"
|
#include "folderview_p.h"
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
|
|
||||||
Q_DECLARE_OPAQUE_POINTER(FmFileInfo*)
|
Q_DECLARE_OPAQUE_POINTER(FmFileInfo*)
|
||||||
|
|
||||||
|
#define SCROLL_FRAMES_PER_SEC 50
|
||||||
|
#define SCROLL_DURATION 300 // in ms
|
||||||
|
|
||||||
|
static const int scrollAnimFrames = SCROLL_FRAMES_PER_SEC * SCROLL_DURATION / 1000;
|
||||||
|
|
||||||
using namespace Fm;
|
using namespace Fm;
|
||||||
|
|
||||||
FolderViewListView::FolderViewListView(QWidget* parent):
|
FolderViewListView::FolderViewListView(QWidget* parent):
|
||||||
@ -144,7 +148,7 @@ void FolderViewListView::dragEnterEvent(QDragEnterEvent* event) {
|
|||||||
else {
|
else {
|
||||||
QAbstractItemView::dragEnterEvent(event);
|
QAbstractItemView::dragEnterEvent(event);
|
||||||
}
|
}
|
||||||
qDebug("dragEnterEvent");
|
//qDebug("dragEnterEvent");
|
||||||
//static_cast<FolderView*>(parent())->childDragEnterEvent(event);
|
//static_cast<FolderView*>(parent())->childDragEnterEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -410,7 +414,7 @@ void FolderViewTreeView::reset() {
|
|||||||
// This is for performance reason so in this case rowsInserted() and rowsAboutToBeRemoved()
|
// This is for performance reason so in this case rowsInserted() and rowsAboutToBeRemoved()
|
||||||
// might not be called. Hence we also have to re-layout the columns when the model is reset.
|
// might not be called. Hence we also have to re-layout the columns when the model is reset.
|
||||||
// This fixes bug #190
|
// This fixes bug #190
|
||||||
// https://github.com/lxde/pcmanfm-qt/issues/190
|
// https://github.com/lxqt/pcmanfm-qt/issues/190
|
||||||
QTreeView::reset();
|
QTreeView::reset();
|
||||||
queueLayoutColumns();
|
queueLayoutColumns();
|
||||||
}
|
}
|
||||||
@ -476,7 +480,9 @@ FolderView::FolderView(FolderView::ViewMode _mode, QWidget *parent):
|
|||||||
autoSelectionDelay_(600),
|
autoSelectionDelay_(600),
|
||||||
autoSelectionTimer_(nullptr),
|
autoSelectionTimer_(nullptr),
|
||||||
selChangedTimer_(nullptr),
|
selChangedTimer_(nullptr),
|
||||||
itemDelegateMargins_(QSize(3, 3)) {
|
itemDelegateMargins_(QSize(3, 3)),
|
||||||
|
smoothScrollTimer_(nullptr),
|
||||||
|
wheelEvent_(nullptr) {
|
||||||
|
|
||||||
iconSize_[IconMode - FirstViewMode] = QSize(48, 48);
|
iconSize_[IconMode - FirstViewMode] = QSize(48, 48);
|
||||||
iconSize_[CompactMode - FirstViewMode] = QSize(24, 24);
|
iconSize_[CompactMode - FirstViewMode] = QSize(24, 24);
|
||||||
@ -495,6 +501,11 @@ FolderView::FolderView(FolderView::ViewMode _mode, QWidget *parent):
|
|||||||
}
|
}
|
||||||
|
|
||||||
FolderView::~FolderView() {
|
FolderView::~FolderView() {
|
||||||
|
if(smoothScrollTimer_) {
|
||||||
|
disconnect(smoothScrollTimer_, &QTimer::timeout, this, &FolderView::scrollSmoothly);
|
||||||
|
smoothScrollTimer_->stop();
|
||||||
|
delete smoothScrollTimer_;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FolderView::onItemActivated(QModelIndex index) {
|
void FolderView::onItemActivated(QModelIndex index) {
|
||||||
@ -567,6 +578,13 @@ void FolderView::setViewMode(ViewMode _mode) {
|
|||||||
if(_mode == mode) { // if it's the same more, ignore
|
if(_mode == mode) { // if it's the same more, ignore
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// smooth scrolling is only for icon and thumbnail modes
|
||||||
|
if(smoothScrollTimer_ && (_mode == DetailedListMode || _mode == CompactMode)) {
|
||||||
|
disconnect(smoothScrollTimer_, &QTimer::timeout, this, &FolderView::scrollSmoothly);
|
||||||
|
smoothScrollTimer_->stop();
|
||||||
|
delete smoothScrollTimer_;
|
||||||
|
smoothScrollTimer_ = nullptr;
|
||||||
|
}
|
||||||
// FIXME: retain old selection
|
// FIXME: retain old selection
|
||||||
|
|
||||||
// since only detailed list mode uses QTreeView, and others
|
// since only detailed list mode uses QTreeView, and others
|
||||||
@ -656,11 +674,10 @@ void FolderView::setViewMode(ViewMode _mode) {
|
|||||||
view->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
view->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
layout()->addWidget(view);
|
layout()->addWidget(view);
|
||||||
|
|
||||||
// enable dnd
|
// enable dnd (the drop indicator is set at "FolderView::childDragMoveEvent()")
|
||||||
view->setDragEnabled(true);
|
view->setDragEnabled(true);
|
||||||
view->setAcceptDrops(true);
|
view->setAcceptDrops(true);
|
||||||
view->setDragDropMode(QAbstractItemView::DragDrop);
|
view->setDragDropMode(QAbstractItemView::DragDrop);
|
||||||
view->setDropIndicatorShown(true);
|
|
||||||
|
|
||||||
// inline renaming
|
// inline renaming
|
||||||
if(delegate) {
|
if(delegate) {
|
||||||
@ -891,6 +908,43 @@ QModelIndex FolderView::indexFromFolderPath(const Fm::FilePath& folderPath) cons
|
|||||||
return QModelIndex();
|
return QModelIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FolderView::selectFiles(const Fm::FileInfoList& files, bool add) {
|
||||||
|
if(!model_ || files.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!add) {
|
||||||
|
selectionModel()->clear();
|
||||||
|
}
|
||||||
|
QModelIndex index, firstIndex;
|
||||||
|
int count = model_->rowCount();
|
||||||
|
Fm::FileInfoList list = files;
|
||||||
|
bool singleFile(files.size() == 1);
|
||||||
|
for(int row = 0; row < count; ++row) {
|
||||||
|
if (list.empty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index = model_->index(row, 0);
|
||||||
|
auto info = model_->fileInfoFromIndex(index);
|
||||||
|
for(auto it = list.cbegin(); it != list.cend(); ++it) {
|
||||||
|
auto& item = *it;
|
||||||
|
if(item == info) {
|
||||||
|
selectionModel()->select(index, QItemSelectionModel::Select);
|
||||||
|
if (!firstIndex.isValid()) {
|
||||||
|
firstIndex = index;
|
||||||
|
}
|
||||||
|
list.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (firstIndex.isValid()) {
|
||||||
|
view->scrollTo(firstIndex, QAbstractItemView::EnsureVisible);
|
||||||
|
if (singleFile) { // give focus to the single file
|
||||||
|
selectionModel()->setCurrentIndex(firstIndex, QItemSelectionModel::Current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Fm::FileInfoList FolderView::selectedFiles() const {
|
Fm::FileInfoList FolderView::selectedFiles() const {
|
||||||
if(model_) {
|
if(model_) {
|
||||||
QModelIndexList selIndexes = mode == DetailedListMode ? selectedRows() : selectedIndexes();
|
QModelIndexList selIndexes = mode == DetailedListMode ? selectedRows() : selectedIndexes();
|
||||||
@ -941,7 +995,7 @@ void FolderView::invertSelection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FolderView::childDragEnterEvent(QDragEnterEvent* event) {
|
void FolderView::childDragEnterEvent(QDragEnterEvent* event) {
|
||||||
qDebug("drag enter");
|
//qDebug("drag enter");
|
||||||
if(event->mimeData()->hasFormat("text/uri-list")) {
|
if(event->mimeData()->hasFormat("text/uri-list")) {
|
||||||
event->accept();
|
event->accept();
|
||||||
}
|
}
|
||||||
@ -951,12 +1005,23 @@ void FolderView::childDragEnterEvent(QDragEnterEvent* event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FolderView::childDragLeaveEvent(QDragLeaveEvent* e) {
|
void FolderView::childDragLeaveEvent(QDragLeaveEvent* e) {
|
||||||
qDebug("drag leave");
|
//qDebug("drag leave");
|
||||||
e->accept();
|
e->accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FolderView::childDragMoveEvent(QDragMoveEvent* /*e*/) {
|
void FolderView::childDragMoveEvent(QDragMoveEvent* e) {
|
||||||
qDebug("drag move");
|
// Since it isn't possible to drop on a file (see "FolderModel::dropMimeData()"),
|
||||||
|
// we enable the drop indicator only when the cursor is on a folder.
|
||||||
|
QModelIndex index = view->indexAt(e->pos());
|
||||||
|
if(index.isValid() && index.model()) {
|
||||||
|
QVariant data = index.model()->data(index, FolderModel::FileInfoRole);
|
||||||
|
auto info = data.value<std::shared_ptr<const Fm::FileInfo>>();
|
||||||
|
if(info && !info->isDir()) {
|
||||||
|
view->setDropIndicatorShown(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
view->setDropIndicatorShown(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FolderView::childDropEvent(QDropEvent* e) {
|
void FolderView::childDropEvent(QDropEvent* e) {
|
||||||
@ -1049,8 +1114,8 @@ bool FolderView::eventFilter(QObject* watched, QEvent* event) {
|
|||||||
}
|
}
|
||||||
autoSelectionTimer_->start(autoSelectionDelay_);
|
autoSelectionTimer_->start(autoSelectionDelay_);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
case QEvent::HoverLeave:
|
case QEvent::HoverLeave:
|
||||||
if(style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick)) {
|
if(style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick)) {
|
||||||
setCursor(Qt::ArrowCursor);
|
setCursor(Qt::ArrowCursor);
|
||||||
@ -1086,6 +1151,42 @@ bool FolderView::eventFilter(QObject* watched, QEvent* event) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Smooth Scrolling
|
||||||
|
// Some tricks are adapted from <https://github.com/zhou13/qsmoothscrollarea>.
|
||||||
|
else if(mode != DetailedListMode
|
||||||
|
&& event->spontaneous()
|
||||||
|
&& !(QApplication::keyboardModifiers() & (Qt::ShiftModifier | Qt::AltModifier))) {
|
||||||
|
if(QScrollBar* vbar = view->verticalScrollBar()) {
|
||||||
|
// keep track of the wheel event for smooth scrolling
|
||||||
|
wheelEvent_ = static_cast<QWheelEvent*>(event);
|
||||||
|
int delta = wheelEvent_->angleDelta().y();
|
||||||
|
if((delta > 0 && vbar->value() == vbar->minimum()) || (delta < 0 && vbar->value() == vbar->maximum())) {
|
||||||
|
break; // the scrollbar can't move
|
||||||
|
}
|
||||||
|
// get a rough estimation of the wheel speed and disable animation if it's too high
|
||||||
|
static QList<qint64> wheelEvents;
|
||||||
|
wheelEvents << QDateTime::currentMSecsSinceEpoch();
|
||||||
|
while(wheelEvents.last() - wheelEvents.first() > 500) {
|
||||||
|
wheelEvents.removeFirst();
|
||||||
|
}
|
||||||
|
if(wheelEvents.size() > 10) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!smoothScrollTimer_) {
|
||||||
|
smoothScrollTimer_ = new QTimer();
|
||||||
|
connect(smoothScrollTimer_, &QTimer::timeout, this, &FolderView::scrollSmoothly);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the data for smooth scrolling
|
||||||
|
scollData data;
|
||||||
|
data.delta = delta;
|
||||||
|
data.leftFrames = scrollAnimFrames;
|
||||||
|
queuedScrollSteps_.append(data);
|
||||||
|
smoothScrollTimer_->start(1000 / SCROLL_FRAMES_PER_SEC);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -1094,6 +1195,36 @@ bool FolderView::eventFilter(QObject* watched, QEvent* event) {
|
|||||||
return QObject::eventFilter(watched, event);
|
return QObject::eventFilter(watched, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FolderView::scrollSmoothly() {
|
||||||
|
if(!wheelEvent_ || !view->verticalScrollBar()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int totalDelta = 0;
|
||||||
|
QList<scollData>::iterator it = queuedScrollSteps_.begin();
|
||||||
|
while(it != queuedScrollSteps_.end()) {
|
||||||
|
if(it->leftFrames == 1) { // find the exact delta for the last frame
|
||||||
|
totalDelta += it->delta - (scrollAnimFrames - 1) * qRound((qreal)it->delta / (qreal)scrollAnimFrames);
|
||||||
|
it = queuedScrollSteps_.erase(it);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
totalDelta += qRound((qreal)it->delta / (qreal)scrollAnimFrames);
|
||||||
|
-- it->leftFrames;
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(totalDelta != 0) {
|
||||||
|
// as in qevent.cpp -> QWheelEvent::QWheelEvent()
|
||||||
|
QWheelEvent e(wheelEvent_->pos(), wheelEvent_->globalPos(),
|
||||||
|
totalDelta,
|
||||||
|
wheelEvent_->buttons(), Qt::NoModifier, Qt::Vertical);
|
||||||
|
QApplication::sendEvent(view->verticalScrollBar(), &e);
|
||||||
|
}
|
||||||
|
if(queuedScrollSteps_.empty()) {
|
||||||
|
smoothScrollTimer_->stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// this slot handles auto-selection of items.
|
// this slot handles auto-selection of items.
|
||||||
void FolderView::onAutoSelectionTimeout() {
|
void FolderView::onAutoSelectionTimeout() {
|
||||||
if(QApplication::mouseButtons() != Qt::NoButton) {
|
if(QApplication::mouseButtons() != Qt::NoButton) {
|
||||||
@ -1218,8 +1349,10 @@ void FolderView::onClipboardDataChange() {
|
|||||||
if(!folder()->path().hasUriScheme("search") // skip for search results
|
if(!folder()->path().hasUriScheme("search") // skip for search results
|
||||||
&& isCutSelection
|
&& isCutSelection
|
||||||
&& Fm::isCurrentPidClipboardData(*data)) { // set cut files only with this app
|
&& Fm::isCurrentPidClipboardData(*data)) { // set cut files only with this app
|
||||||
auto cutDirPath = paths.size() > 0 ? paths[0].parent(): FilePath();
|
auto cutDirPath = paths.size() > 0 ? paths[0].parent() : FilePath();
|
||||||
if(folder()->path() == cutDirPath) {
|
// set the cut file(s) only if the cutting is done here
|
||||||
|
if(folder()->path() == cutDirPath
|
||||||
|
&& selectedFilePaths() == paths) {
|
||||||
model_->setCutFiles(selectionModel()->selection());
|
model_->setCutFiles(selectionModel()->selection());
|
||||||
}
|
}
|
||||||
else if(folder()->hadCutFilesUnset() || folder()->hasCutFiles()) {
|
else if(folder()->hadCutFilesUnset() || folder()->hasCutFiles()) {
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
#include <libfm/fm.h>
|
#include <libfm/fm.h>
|
||||||
#include "foldermodel.h"
|
#include "foldermodel.h"
|
||||||
#include "proxyfoldermodel.h"
|
#include "proxyfoldermodel.h"
|
||||||
#include "path.h"
|
|
||||||
|
|
||||||
#include "core/folder.h"
|
#include "core/folder.h"
|
||||||
|
|
||||||
@ -102,6 +101,7 @@ public:
|
|||||||
Fm::FilePathList selectedFilePaths() const;
|
Fm::FilePathList selectedFilePaths() const;
|
||||||
bool hasSelection() const;
|
bool hasSelection() const;
|
||||||
QModelIndex indexFromFolderPath(const Fm::FilePath& folderPath) const;
|
QModelIndex indexFromFolderPath(const Fm::FilePath& folderPath) const;
|
||||||
|
void selectFiles(const Fm::FileInfoList& files, bool add = false);
|
||||||
|
|
||||||
void selectAll();
|
void selectAll();
|
||||||
|
|
||||||
@ -160,6 +160,7 @@ private Q_SLOTS:
|
|||||||
void onAutoSelectionTimeout();
|
void onAutoSelectionTimeout();
|
||||||
void onSelChangedTimeout();
|
void onSelChangedTimeout();
|
||||||
void onClosingEditor(QWidget* editor, QAbstractItemDelegate::EndEditHint hint);
|
void onClosingEditor(QWidget* editor, QAbstractItemDelegate::EndEditHint hint);
|
||||||
|
void scrollSmoothly();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void clicked(int type, const std::shared_ptr<const Fm::FileInfo>& file);
|
void clicked(int type, const std::shared_ptr<const Fm::FileInfo>& file);
|
||||||
@ -181,6 +182,14 @@ private:
|
|||||||
QTimer* selChangedTimer_;
|
QTimer* selChangedTimer_;
|
||||||
// the cell margins in the icon and thumbnail modes
|
// the cell margins in the icon and thumbnail modes
|
||||||
QSize itemDelegateMargins_;
|
QSize itemDelegateMargins_;
|
||||||
|
// smooth scrolling:
|
||||||
|
struct scollData {
|
||||||
|
int delta;
|
||||||
|
int leftFrames;
|
||||||
|
};
|
||||||
|
QTimer *smoothScrollTimer_;
|
||||||
|
QWheelEvent *wheelEvent_;
|
||||||
|
QList<scollData> queuedScrollSteps_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,80 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2012 - 2015 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "icontheme.h"
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
#include <QList>
|
|
||||||
#include <QIcon>
|
|
||||||
#include <QtGlobal>
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QDesktopWidget>
|
|
||||||
|
|
||||||
#include "core/iconinfo.h"
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
static IconTheme* theIconTheme = nullptr; // the global single instance of IconTheme.
|
|
||||||
|
|
||||||
IconTheme::IconTheme():
|
|
||||||
currentThemeName_(QIcon::themeName()) {
|
|
||||||
// NOTE: only one instance is allowed
|
|
||||||
Q_ASSERT(theIconTheme == nullptr);
|
|
||||||
Q_ASSERT(qApp != nullptr); // QApplication should exists before contructing IconTheme.
|
|
||||||
|
|
||||||
theIconTheme = this;
|
|
||||||
|
|
||||||
// We need to get notified when there is a QEvent::StyleChange event so
|
|
||||||
// we can check if the current icon theme name is changed.
|
|
||||||
// To do this, we can filter QApplication object itself to intercept
|
|
||||||
// signals of all widgets, but this may be too inefficient.
|
|
||||||
// So, we only filter the events on QDesktopWidget instead.
|
|
||||||
qApp->desktop()->installEventFilter(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
IconTheme::~IconTheme() {
|
|
||||||
}
|
|
||||||
|
|
||||||
IconTheme* IconTheme::instance() {
|
|
||||||
return theIconTheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the icon theme name is changed and emit "changed()" signal if any change is detected.
|
|
||||||
void IconTheme::checkChanged() {
|
|
||||||
if(QIcon::themeName() != theIconTheme->currentThemeName_) {
|
|
||||||
// if the icon theme is changed
|
|
||||||
theIconTheme->currentThemeName_ = QIcon::themeName();
|
|
||||||
// invalidate the cached data
|
|
||||||
Fm::IconInfo::updateQIcons();
|
|
||||||
Q_EMIT theIconTheme->changed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
// FIXME: QEvent::ThemeChange seems to be interal to Qt 5 and is not documented
|
|
||||||
if(event->type() == QEvent::StyleChange || event->type() == QEvent::ThemeChange) {
|
|
||||||
checkChanged(); // check if the icon theme is changed
|
|
||||||
}
|
|
||||||
return QObject::eventFilter(obj, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Fm
|
|
@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2012 - 2015 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_ICONTHEME_H
|
|
||||||
#define FM_ICONTHEME_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QIcon>
|
|
||||||
#include <QString>
|
|
||||||
#include "libfm/fm.h"
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class LIBFM_QT_API IconTheme: public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
IconTheme();
|
|
||||||
~IconTheme();
|
|
||||||
|
|
||||||
static IconTheme* instance();
|
|
||||||
|
|
||||||
static void checkChanged(); // check if current icon theme name is changed
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void changed(); // emitted when the name of current icon theme is changed
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool eventFilter(QObject* obj, QEvent* event);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString currentThemeName_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_ICONTHEME_H
|
|
@ -5,7 +5,7 @@ includedir=${prefix}/include
|
|||||||
|
|
||||||
Name: libfm-qt
|
Name: libfm-qt
|
||||||
Description: A Qt/glib/gio-based lib used to develop file managers providing some file management utilities. (This is a Qt port of the original libfm library)
|
Description: A Qt/glib/gio-based lib used to develop file managers providing some file management utilities. (This is a Qt port of the original libfm library)
|
||||||
URL: http://pcmanfm.sourceforge.net/
|
URL: https://github.com/lxqt/libfm-qt
|
||||||
Requires: @REQUIRED_QT@ libfm >= 1.2.0
|
Requires: @REQUIRED_QT@ libfm >= 1.2.0
|
||||||
Version: @LIBFM_QT_VERSION@
|
Version: @LIBFM_QT_VERSION@
|
||||||
Libs: -L${libdir} -lfm -l@LIBFM_QT_LIBRARY_NAME@
|
Libs: -L${libdir} -lfm -l@LIBFM_QT_LIBRARY_NAME@
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
#include "libfmqt.h"
|
#include "libfmqt.h"
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
#include <QPixmapCache>
|
#include <QPixmapCache>
|
||||||
#include "icontheme.h"
|
|
||||||
#include "core/thumbnailer.h"
|
#include "core/thumbnailer.h"
|
||||||
#include "xdndworkaround.h"
|
#include "xdndworkaround.h"
|
||||||
|
|
||||||
@ -31,7 +30,6 @@ struct LibFmQtData {
|
|||||||
LibFmQtData();
|
LibFmQtData();
|
||||||
~LibFmQtData();
|
~LibFmQtData();
|
||||||
|
|
||||||
IconTheme* iconTheme;
|
|
||||||
QTranslator translator;
|
QTranslator translator;
|
||||||
XdndWorkaround workaround;
|
XdndWorkaround workaround;
|
||||||
int refCount;
|
int refCount;
|
||||||
@ -52,7 +50,6 @@ LibFmQtData::LibFmQtData(): refCount(1) {
|
|||||||
fm_init(nullptr);
|
fm_init(nullptr);
|
||||||
// turn on glib debug message
|
// turn on glib debug message
|
||||||
// g_setenv("G_MESSAGES_DEBUG", "all", true);
|
// g_setenv("G_MESSAGES_DEBUG", "all", true);
|
||||||
iconTheme = new IconTheme();
|
|
||||||
Fm::Thumbnailer::loadAll();
|
Fm::Thumbnailer::loadAll();
|
||||||
translator.load("libfm-qt_" + QLocale::system().name(), LIBFM_QT_DATA_DIR "/translations");
|
translator.load("libfm-qt_" + QLocale::system().name(), LIBFM_QT_DATA_DIR "/translations");
|
||||||
|
|
||||||
@ -67,7 +64,6 @@ LibFmQtData::~LibFmQtData() {
|
|||||||
GVfs* vfs = g_vfs_get_default();
|
GVfs* vfs = g_vfs_get_default();
|
||||||
g_vfs_unregister_uri_scheme(vfs, "menu");
|
g_vfs_unregister_uri_scheme(vfs, "menu");
|
||||||
g_vfs_unregister_uri_scheme(vfs, "search");
|
g_vfs_unregister_uri_scheme(vfs, "search");
|
||||||
delete iconTheme;
|
|
||||||
fm_finalize();
|
fm_finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "mountoperationpassworddialog_p.h"
|
#include "mountoperationpassworddialog_p.h"
|
||||||
#include "mountoperationquestiondialog_p.h"
|
#include "mountoperationquestiondialog_p.h"
|
||||||
#include "ui_mount-operation-password.h"
|
#include "ui_mount-operation-password.h"
|
||||||
|
#include "core/gioptrs.h"
|
||||||
|
|
||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
|
||||||
@ -83,6 +84,16 @@ MountOperation::~MountOperation() {
|
|||||||
// qDebug("MountOperation deleted");
|
// qDebug("MountOperation deleted");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MountOperation::mountEnclosingVolume(const FilePath &path) {
|
||||||
|
g_file_mount_enclosing_volume(path.gfile().get(), G_MOUNT_MOUNT_NONE, op, cancellable_,
|
||||||
|
(GAsyncReadyCallback)onMountFileFinished, new QPointer<MountOperation>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MountOperation::mountMountable(const FilePath &mountable) {
|
||||||
|
g_file_mount_mountable(mountable.gfile().get(), G_MOUNT_MOUNT_NONE, op, cancellable_,
|
||||||
|
(GAsyncReadyCallback)onMountMountableFinished, new QPointer<MountOperation>(this));
|
||||||
|
}
|
||||||
|
|
||||||
void MountOperation::onAbort(GMountOperation* /*_op*/, MountOperation* /*pThis*/) {
|
void MountOperation::onAbort(GMountOperation* /*_op*/, MountOperation* /*pThis*/) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -143,6 +154,15 @@ void MountOperation::onMountFileFinished(GFile* file, GAsyncResult* res, QPointe
|
|||||||
delete pThis;
|
delete pThis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MountOperation::onMountMountableFinished(GFile* file, GAsyncResult* res, QPointer<MountOperation>* pThis) {
|
||||||
|
if(*pThis) {
|
||||||
|
GError* error = nullptr;
|
||||||
|
g_file_mount_mountable_finish(file, res, &error);
|
||||||
|
(*pThis)->handleFinish(error);
|
||||||
|
}
|
||||||
|
delete pThis;
|
||||||
|
}
|
||||||
|
|
||||||
void MountOperation::onMountVolumeFinished(GVolume* volume, GAsyncResult* res, QPointer< MountOperation >* pThis) {
|
void MountOperation::onMountVolumeFinished(GVolume* volume, GAsyncResult* res, QPointer< MountOperation >* pThis) {
|
||||||
if(*pThis) {
|
if(*pThis) {
|
||||||
GError* error = nullptr;
|
GError* error = nullptr;
|
||||||
|
@ -48,11 +48,15 @@ public:
|
|||||||
explicit MountOperation(bool interactive = true, QWidget* parent = 0);
|
explicit MountOperation(bool interactive = true, QWidget* parent = 0);
|
||||||
~MountOperation();
|
~MountOperation();
|
||||||
|
|
||||||
|
FM_QT_DEPRECATED
|
||||||
void mount(const Fm::FilePath& path) {
|
void mount(const Fm::FilePath& path) {
|
||||||
g_file_mount_enclosing_volume(path.gfile().get(), G_MOUNT_MOUNT_NONE, op, cancellable_,
|
mountEnclosingVolume(path);
|
||||||
(GAsyncReadyCallback)onMountFileFinished, new QPointer<MountOperation>(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mountEnclosingVolume(const Fm::FilePath& path);
|
||||||
|
|
||||||
|
void mountMountable(const Fm::FilePath& mountable);
|
||||||
|
|
||||||
void mount(GVolume* volume) {
|
void mount(GVolume* volume) {
|
||||||
g_volume_mount(volume, G_MOUNT_MOUNT_NONE, op, cancellable_, (GAsyncReadyCallback)onMountVolumeFinished, new QPointer<MountOperation>(this));
|
g_volume_mount(volume, G_MOUNT_MOUNT_NONE, op, cancellable_, (GAsyncReadyCallback)onMountVolumeFinished, new QPointer<MountOperation>(this));
|
||||||
}
|
}
|
||||||
@ -135,6 +139,7 @@ private:
|
|||||||
|
|
||||||
// it's possible that this object is freed when the callback is called by gio, so guarding with QPointer is needed here.
|
// it's possible that this object is freed when the callback is called by gio, so guarding with QPointer is needed here.
|
||||||
static void onMountFileFinished(GFile* file, GAsyncResult* res, QPointer<MountOperation>* pThis);
|
static void onMountFileFinished(GFile* file, GAsyncResult* res, QPointer<MountOperation>* pThis);
|
||||||
|
static void onMountMountableFinished(GFile* file, GAsyncResult* res, QPointer<MountOperation>* pThis);
|
||||||
static void onMountVolumeFinished(GVolume* volume, GAsyncResult* res, QPointer<MountOperation>* pThis);
|
static void onMountVolumeFinished(GVolume* volume, GAsyncResult* res, QPointer<MountOperation>* pThis);
|
||||||
static void onUnmountMountFinished(GMount* mount, GAsyncResult* res, QPointer<MountOperation>* pThis);
|
static void onUnmountMountFinished(GMount* mount, GAsyncResult* res, QPointer<MountOperation>* pThis);
|
||||||
static void onEjectMountFinished(GMount* mount, GAsyncResult* res, QPointer<MountOperation>* pThis);
|
static void onEjectMountFinished(GMount* mount, GAsyncResult* res, QPointer<MountOperation>* pThis);
|
||||||
|
441
src/path.h
441
src/path.h
@ -1,441 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 __LIBFM_QT_FM_PATH_H__
|
|
||||||
#define __LIBFM_QT_FM_PATH_H__
|
|
||||||
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
#include <QObject>
|
|
||||||
#include <QtGlobal>
|
|
||||||
#include <QMetaType>
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
|
|
||||||
class LIBFM_QT_API PathList {
|
|
||||||
public:
|
|
||||||
|
|
||||||
|
|
||||||
PathList(void ) {
|
|
||||||
dataPtr_ = reinterpret_cast<FmPathList*>(fm_path_list_new());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PathList(FmPathList* dataPtr){
|
|
||||||
dataPtr_ = dataPtr != nullptr ? reinterpret_cast<FmPathList*>(fm_list_ref(FM_LIST(dataPtr))) : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// copy constructor
|
|
||||||
PathList(const PathList& other) {
|
|
||||||
dataPtr_ = other.dataPtr_ != nullptr ? reinterpret_cast<FmPathList*>(fm_list_ref(FM_LIST(other.dataPtr_))) : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// move constructor
|
|
||||||
PathList(PathList&& other) {
|
|
||||||
dataPtr_ = reinterpret_cast<FmPathList*>(other.takeDataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// destructor
|
|
||||||
~PathList() {
|
|
||||||
if(dataPtr_ != nullptr) {
|
|
||||||
fm_list_unref(FM_LIST(dataPtr_));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// create a wrapper for the data pointer without increasing the reference count
|
|
||||||
static PathList wrapPtr(FmPathList* dataPtr) {
|
|
||||||
PathList obj;
|
|
||||||
obj.dataPtr_ = reinterpret_cast<FmPathList*>(dataPtr);
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
// disown the managed data pointer
|
|
||||||
FmPathList* takeDataPtr() {
|
|
||||||
FmPathList* data = reinterpret_cast<FmPathList*>(dataPtr_);
|
|
||||||
dataPtr_ = nullptr;
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the raw pointer wrapped
|
|
||||||
FmPathList* dataPtr() {
|
|
||||||
return reinterpret_cast<FmPathList*>(dataPtr_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// automatic type casting
|
|
||||||
operator FmPathList*() {
|
|
||||||
return dataPtr();
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy assignment
|
|
||||||
PathList& operator=(const PathList& other) {
|
|
||||||
if(dataPtr_ != nullptr) {
|
|
||||||
fm_list_unref(FM_LIST(dataPtr_));
|
|
||||||
}
|
|
||||||
dataPtr_ = other.dataPtr_ != nullptr ? reinterpret_cast<FmPathList*>(fm_list_ref(FM_LIST(other.dataPtr_))) : nullptr;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// move assignment
|
|
||||||
PathList& operator=(PathList&& other) {
|
|
||||||
dataPtr_ = reinterpret_cast<FmPathList*>(other.takeDataPtr());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isNull() {
|
|
||||||
return (dataPtr_ == nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// methods
|
|
||||||
|
|
||||||
void writeUriList(GString* buf) {
|
|
||||||
fm_path_list_write_uri_list(dataPtr(), buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
char* toUriList(void) {
|
|
||||||
return fm_path_list_to_uri_list(dataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int getLength() {
|
|
||||||
return fm_path_list_get_length(dataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isEmpty() {
|
|
||||||
return fm_path_list_is_empty(dataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
FmPath* peekHead() {
|
|
||||||
return fm_path_list_peek_head(dataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
GList* peekHeadLink() {
|
|
||||||
return fm_path_list_peek_head_link(dataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
void pushTail(FmPath* path) {
|
|
||||||
fm_path_list_push_tail(dataPtr(), path);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PathList newFromFileInfoGslist(GSList* fis) {
|
|
||||||
return PathList::wrapPtr(fm_path_list_new_from_file_info_gslist(fis));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static PathList newFromFileInfoGlist(GList* fis) {
|
|
||||||
return PathList::wrapPtr(fm_path_list_new_from_file_info_glist(fis));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static PathList newFromFileInfoList(FmFileInfoList* fis) {
|
|
||||||
return PathList::wrapPtr(fm_path_list_new_from_file_info_list(fis));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static PathList newFromUris(char* const* uris) {
|
|
||||||
return PathList::wrapPtr(fm_path_list_new_from_uris(uris));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static PathList newFromUriList(const char* uri_list) {
|
|
||||||
return PathList::wrapPtr(fm_path_list_new_from_uri_list(uri_list));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
FmPathList* dataPtr_; // data pointer for the underlying C struct
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class LIBFM_QT_API Path {
|
|
||||||
public:
|
|
||||||
|
|
||||||
|
|
||||||
// default constructor
|
|
||||||
Path() {
|
|
||||||
dataPtr_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Path(FmPath* dataPtr){
|
|
||||||
dataPtr_ = dataPtr != nullptr ? reinterpret_cast<FmPath*>(fm_path_ref(dataPtr)) : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// copy constructor
|
|
||||||
Path(const Path& other) {
|
|
||||||
dataPtr_ = other.dataPtr_ != nullptr ? reinterpret_cast<FmPath*>(fm_path_ref(other.dataPtr_)) : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// move constructor
|
|
||||||
Path(Path&& other) {
|
|
||||||
dataPtr_ = reinterpret_cast<FmPath*>(other.takeDataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// destructor
|
|
||||||
~Path() {
|
|
||||||
if(dataPtr_ != nullptr) {
|
|
||||||
fm_path_unref(dataPtr_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// create a wrapper for the data pointer without increasing the reference count
|
|
||||||
static Path wrapPtr(FmPath* dataPtr) {
|
|
||||||
Path obj;
|
|
||||||
obj.dataPtr_ = reinterpret_cast<FmPath*>(dataPtr);
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
// disown the managed data pointer
|
|
||||||
FmPath* takeDataPtr() {
|
|
||||||
FmPath* data = reinterpret_cast<FmPath*>(dataPtr_);
|
|
||||||
dataPtr_ = nullptr;
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the raw pointer wrapped
|
|
||||||
FmPath* dataPtr() {
|
|
||||||
return reinterpret_cast<FmPath*>(dataPtr_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// automatic type casting
|
|
||||||
operator FmPath*() {
|
|
||||||
return dataPtr();
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy assignment
|
|
||||||
Path& operator=(const Path& other) {
|
|
||||||
if(dataPtr_ != nullptr) {
|
|
||||||
fm_path_unref(dataPtr_);
|
|
||||||
}
|
|
||||||
dataPtr_ = other.dataPtr_ != nullptr ? reinterpret_cast<FmPath*>(fm_path_ref(other.dataPtr_)) : nullptr;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// move assignment
|
|
||||||
Path& operator=(Path&& other) {
|
|
||||||
dataPtr_ = reinterpret_cast<FmPath*>(other.takeDataPtr());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isNull() {
|
|
||||||
return (dataPtr_ == nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// methods
|
|
||||||
bool isNative() {
|
|
||||||
return fm_path_is_native(dataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isTrash() {
|
|
||||||
return fm_path_is_trash(dataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isTrashRoot() {
|
|
||||||
return fm_path_is_trash_root(dataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isNativeOrTrash() {
|
|
||||||
return fm_path_is_native_or_trash(dataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
int depth(void) {
|
|
||||||
return fm_path_depth(dataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool equalStr(const gchar* str, int n) {
|
|
||||||
return fm_path_equal_str(dataPtr(), str, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int compare(FmPath* p2) {
|
|
||||||
return fm_path_compare(dataPtr(), p2);
|
|
||||||
}
|
|
||||||
|
|
||||||
int compare(Path& p2) {
|
|
||||||
return fm_path_compare(dataPtr(), p2.dataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool equal(FmPath* p2) {
|
|
||||||
return fm_path_equal(dataPtr(), p2);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool equal(Path& p2) {
|
|
||||||
return fm_path_equal(dataPtr(), p2.dataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator == (Path& other) {
|
|
||||||
return fm_path_equal(dataPtr(), other.dataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator != (Path& other) {
|
|
||||||
return !fm_path_equal(dataPtr(), other.dataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator < (Path& other) {
|
|
||||||
return compare(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator > (Path& other) {
|
|
||||||
return (other < *this);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int hash(void) {
|
|
||||||
return fm_path_hash(dataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char* displayBasename(void) {
|
|
||||||
return fm_path_display_basename(dataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
char* displayName(gboolean human_readable) {
|
|
||||||
return fm_path_display_name(dataPtr(), human_readable);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
GFile* toGfile(void) {
|
|
||||||
return fm_path_to_gfile(dataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char* toUri(void) {
|
|
||||||
return fm_path_to_uri(dataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char* toStr(void) {
|
|
||||||
return fm_path_to_str(dataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Path getSchemePath(void) {
|
|
||||||
return Path(fm_path_get_scheme_path(dataPtr()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool hasPrefix(FmPath* prefix) {
|
|
||||||
return fm_path_has_prefix(dataPtr(), prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FmPathFlags getFlags(void) {
|
|
||||||
return fm_path_get_flags(dataPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Path getParent(void) {
|
|
||||||
return Path(fm_path_get_parent(dataPtr()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Path getAppsMenu(void ) {
|
|
||||||
return Path(fm_path_get_apps_menu());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Path getTrash(void ) {
|
|
||||||
return Path(fm_path_get_trash());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Path getDesktop(void ) {
|
|
||||||
return Path(fm_path_get_desktop());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Path getHome(void ) {
|
|
||||||
return Path(fm_path_get_home());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Path getRoot(void ) {
|
|
||||||
return Path(fm_path_get_root());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Path newForGfile(GFile* gf) {
|
|
||||||
return Path::wrapPtr(fm_path_new_for_gfile(gf));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Path newRelative(const char* rel) {
|
|
||||||
return Path::wrapPtr(fm_path_new_relative(dataPtr(), rel));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Path newChildLen(const char* basename, int name_len) {
|
|
||||||
return Path::wrapPtr(fm_path_new_child_len(dataPtr(), basename, name_len));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Path newChild(const char* basename) {
|
|
||||||
return Path::wrapPtr(fm_path_new_child(dataPtr(), basename));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Path newForCommandlineArg(const char* arg) {
|
|
||||||
return Path::wrapPtr(fm_path_new_for_commandline_arg(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Path newForStr(const char* path_str) {
|
|
||||||
return Path::wrapPtr(fm_path_new_for_str(path_str));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Path newForDisplayName(const char* path_name) {
|
|
||||||
return Path::wrapPtr(fm_path_new_for_display_name(path_name));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Path newForUri(const char* uri) {
|
|
||||||
return Path::wrapPtr(fm_path_new_for_uri(uri));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Path newForPath(const char* path_name) {
|
|
||||||
return Path::wrapPtr(fm_path_new_for_path(path_name));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
FmPath* dataPtr_; // data pointer for the underlying C struct
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_DECLARE_OPAQUE_POINTER(FmPath*)
|
|
||||||
|
|
||||||
#endif // __LIBFM_QT_FM_PATH_H__
|
|
@ -305,8 +305,9 @@ void PathBar::openEditor() {
|
|||||||
connect(tempPathEdit_, &PathEdit::returnPressed, this, &PathBar::onReturnPressed);
|
connect(tempPathEdit_, &PathEdit::returnPressed, this, &PathBar::onReturnPressed);
|
||||||
connect(tempPathEdit_, &PathEdit::editingFinished, this, &PathBar::closeEditor);
|
connect(tempPathEdit_, &PathEdit::editingFinished, this, &PathBar::closeEditor);
|
||||||
}
|
}
|
||||||
tempPathEdit_->setFocus();
|
|
||||||
tempPathEdit_->selectAll();
|
tempPathEdit_->selectAll();
|
||||||
|
QApplication::clipboard()->setText(tempPathEdit_->text(), QClipboard::Selection);
|
||||||
|
QTimer::singleShot(0, tempPathEdit_, SLOT(setFocus()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathBar::closeEditor() {
|
void PathBar::closeEditor() {
|
||||||
|
@ -112,7 +112,7 @@ bool PathEdit::event(QEvent* e) {
|
|||||||
if(keyEvent->key() == Qt::Key_Tab && keyEvent->modifiers() == Qt::NoModifier) { // Tab key is pressed
|
if(keyEvent->key() == Qt::Key_Tab && keyEvent->modifiers() == Qt::NoModifier) { // Tab key is pressed
|
||||||
e->accept();
|
e->accept();
|
||||||
// do auto-completion when the user press the Tab key.
|
// do auto-completion when the user press the Tab key.
|
||||||
// This fixes #201: https://github.com/lxde/pcmanfm-qt/issues/201
|
// This fixes #201: https://github.com/lxqt/pcmanfm-qt/issues/201
|
||||||
autoComplete();
|
autoComplete();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "placesmodel.h"
|
#include "placesmodel.h"
|
||||||
#include "icontheme.h"
|
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
@ -55,25 +54,19 @@ PlacesModel::PlacesModel(QObject* parent):
|
|||||||
|
|
||||||
createTrashItem();
|
createTrashItem();
|
||||||
|
|
||||||
// FIXME: add an option to hide network:///
|
computerItem = new PlacesModelItem("computer", tr("Computer"), Fm::FilePath::fromUri("computer:///"));
|
||||||
if(true) {
|
placesRoot->appendRow(computerItem);
|
||||||
computerItem = new PlacesModelItem("computer", tr("Computer"), Fm::FilePath::fromUri("computer:///"));
|
|
||||||
placesRoot->appendRow(computerItem);
|
{ // Applications
|
||||||
}
|
const char* applicaion_icon_names[] = {"system-software-install", "applications-accessories", "application-x-executable"};
|
||||||
else {
|
// NOTE: g_themed_icon_new_from_names() accepts char**, but actually const char** is OK.
|
||||||
computerItem = nullptr;
|
Fm::GIconPtr gicon{g_themed_icon_new_from_names((char**)applicaion_icon_names, G_N_ELEMENTS(applicaion_icon_names)), false};
|
||||||
|
auto fmicon = Fm::IconInfo::fromGIcon(std::move(gicon));
|
||||||
|
applicationsItem = new PlacesModelItem(fmicon, tr("Applications"), Fm::FilePath::fromUri("menu:///applications/"));
|
||||||
|
placesRoot->appendRow(applicationsItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: add an option to hide applications:///
|
{ // Network
|
||||||
const char* applicaion_icon_names[] = {"system-software-install", "applications-accessories", "application-x-executable"};
|
|
||||||
// NOTE: g_themed_icon_new_from_names() accepts char**, but actually const char** is OK.
|
|
||||||
Fm::GIconPtr gicon{g_themed_icon_new_from_names((char**)applicaion_icon_names, G_N_ELEMENTS(applicaion_icon_names)), false};
|
|
||||||
auto fmicon = Fm::IconInfo::fromGIcon(std::move(gicon));
|
|
||||||
applicationsItem = new PlacesModelItem(fmicon, tr("Applications"), Fm::FilePath::fromUri("menu:///applications/"));
|
|
||||||
placesRoot->appendRow(applicationsItem);
|
|
||||||
|
|
||||||
// FIXME: add an option to hide network:///
|
|
||||||
if(true) {
|
|
||||||
const char* network_icon_names[] = {"network", "folder-network", "folder"};
|
const char* network_icon_names[] = {"network", "folder-network", "folder"};
|
||||||
// NOTE: g_themed_icon_new_from_names() accepts char**, but actually const char** is OK.
|
// NOTE: g_themed_icon_new_from_names() accepts char**, but actually const char** is OK.
|
||||||
Fm::GIconPtr gicon{g_themed_icon_new_from_names((char**)network_icon_names, G_N_ELEMENTS(network_icon_names)), false};
|
Fm::GIconPtr gicon{g_themed_icon_new_from_names((char**)network_icon_names, G_N_ELEMENTS(network_icon_names)), false};
|
||||||
@ -81,9 +74,6 @@ PlacesModel::PlacesModel(QObject* parent):
|
|||||||
networkItem = new PlacesModelItem(fmicon, tr("Network"), Fm::FilePath::fromUri("network:///"));
|
networkItem = new PlacesModelItem(fmicon, tr("Network"), Fm::FilePath::fromUri("network:///"));
|
||||||
placesRoot->appendRow(networkItem);
|
placesRoot->appendRow(networkItem);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
networkItem = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
devicesRoot = new QStandardItem(tr("Devices"));
|
devicesRoot = new QStandardItem(tr("Devices"));
|
||||||
devicesRoot->setSelectable(false);
|
devicesRoot->setSelectable(false);
|
||||||
@ -171,7 +161,7 @@ PlacesModel::~PlacesModel() {
|
|||||||
g_object_unref(trashMonitor_);
|
g_object_unref(trashMonitor_);
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_FOREACH(GMount* mount, shadowedMounts_) {
|
for(GMount* const mount : qAsConst(shadowedMounts_)) {
|
||||||
g_object_unref(mount);
|
g_object_unref(mount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -429,6 +419,18 @@ void PlacesModel::onMountRemoved(GVolumeMonitor* monitor, GMount* mount, PlacesM
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PlacesModel::onVolumeAdded(GVolumeMonitor* /*monitor*/, GVolume* volume, PlacesModel* pThis) {
|
void PlacesModel::onVolumeAdded(GVolumeMonitor* /*monitor*/, GVolume* volume, PlacesModel* pThis) {
|
||||||
|
// the item may have been added with "mount-added" (as in loopback mounting)
|
||||||
|
bool itemExists = false;
|
||||||
|
GMount* mount = g_volume_get_mount(volume);
|
||||||
|
if(mount) {
|
||||||
|
if(pThis->itemFromMount(mount)) {
|
||||||
|
itemExists = true;
|
||||||
|
}
|
||||||
|
g_object_unref(mount);
|
||||||
|
}
|
||||||
|
if(itemExists) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// for some unknown reasons, sometimes we get repeated volume-added
|
// for some unknown reasons, sometimes we get repeated volume-added
|
||||||
// signals and added a device more than one. So, make a sanity check here.
|
// signals and added a device more than one. So, make a sanity check here.
|
||||||
PlacesModelVolumeItem* volumeItem = pThis->itemFromVolume(volume);
|
PlacesModelVolumeItem* volumeItem = pThis->itemFromVolume(volume);
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "placesmodelitem.h"
|
#include "placesmodelitem.h"
|
||||||
#include "icontheme.h"
|
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
|
||||||
@ -87,7 +86,7 @@ QVariant PlacesModelItem::data(int role) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PlacesModelBookmarkItem::PlacesModelBookmarkItem(std::shared_ptr<const Fm::BookmarkItem> bm_item):
|
PlacesModelBookmarkItem::PlacesModelBookmarkItem(std::shared_ptr<const Fm::BookmarkItem> bm_item):
|
||||||
PlacesModelItem{Fm::IconInfo::fromName("folder"), bm_item->name(), bm_item->path()},
|
PlacesModelItem{bm_item->icon(), bm_item->name(), bm_item->path()},
|
||||||
bookmarkItem_{std::move(bm_item)} {
|
bookmarkItem_{std::move(bm_item)} {
|
||||||
setEditable(true);
|
setEditable(true);
|
||||||
}
|
}
|
||||||
|
@ -32,12 +32,112 @@
|
|||||||
|
|
||||||
namespace Fm {
|
namespace Fm {
|
||||||
|
|
||||||
|
std::shared_ptr<PlacesProxyModel> PlacesView::proxyModel_;
|
||||||
|
|
||||||
|
PlacesProxyModel::PlacesProxyModel(QObject* parent) :
|
||||||
|
QSortFilterProxyModel(parent),
|
||||||
|
showAll_(false),
|
||||||
|
hiddenItemsRestored_(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
PlacesProxyModel::~PlacesProxyModel() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlacesProxyModel::restoreHiddenItems(const QSet<QString>& items) {
|
||||||
|
// hidden items should be restored only once
|
||||||
|
if(!hiddenItemsRestored_ && !items.isEmpty()) {
|
||||||
|
hidden_.clear();
|
||||||
|
QSet<QString>::const_iterator i = items.constBegin();
|
||||||
|
while (i != items.constEnd()) {
|
||||||
|
if(!(*i).isEmpty()) {
|
||||||
|
hidden_ << *i;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
hiddenItemsRestored_ = true;
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlacesProxyModel::setHidden(const QString& str, bool hide) {
|
||||||
|
if(hide) {
|
||||||
|
if(!str.isEmpty()) {
|
||||||
|
hidden_ << str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
hidden_.remove(str);
|
||||||
|
}
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlacesProxyModel::showAll(bool show) {
|
||||||
|
showAll_ = show;
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PlacesProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const {
|
||||||
|
if(showAll_ || hidden_.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(PlacesModel* srcModel = static_cast<PlacesModel*>(sourceModel())) {
|
||||||
|
QModelIndex index = srcModel->index(source_row, 0, source_parent);
|
||||||
|
if(PlacesModelItem* item = static_cast<PlacesModelItem*>(srcModel->itemFromIndex(index))) {
|
||||||
|
if(item->type() == PlacesModelItem::Places) {
|
||||||
|
if(auto path = item->path()) {
|
||||||
|
if(hidden_.contains(path.toString().get())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(item->type() == PlacesModelItem::Volume) {
|
||||||
|
CStrPtr uuid{g_volume_get_uuid(static_cast<PlacesModelVolumeItem*>(item)->volume())};
|
||||||
|
if(uuid && hidden_.contains(uuid.get())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// show a root items only if, at least, one of its children is shown
|
||||||
|
else if((source_row == 0 || source_row == 1) && !source_parent.isValid()) {
|
||||||
|
QModelIndex indx = index.child(0, 0);
|
||||||
|
while(PlacesModelItem* childItem = static_cast<PlacesModelItem*>(srcModel->itemFromIndex(indx))) {
|
||||||
|
if(childItem->type() == PlacesModelItem::Places) {
|
||||||
|
if(auto path = childItem->path()) {
|
||||||
|
if(!hidden_.contains(path.toString().get())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(childItem->type() == PlacesModelItem::Volume) {
|
||||||
|
CStrPtr uuid{g_volume_get_uuid(static_cast<PlacesModelVolumeItem*>(childItem)->volume())};
|
||||||
|
if(uuid == nullptr || !hidden_.contains(uuid.get())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
indx = indx.sibling(indx.row() + 1, 0);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
PlacesView::PlacesView(QWidget* parent):
|
PlacesView::PlacesView(QWidget* parent):
|
||||||
QTreeView(parent) {
|
QTreeView(parent) {
|
||||||
setRootIsDecorated(false);
|
setRootIsDecorated(false);
|
||||||
setHeaderHidden(true);
|
setHeaderHidden(true);
|
||||||
setIndentation(12);
|
setIndentation(12);
|
||||||
|
|
||||||
|
/* merge with the surroundings */
|
||||||
|
setFrameShape(QFrame::NoFrame);
|
||||||
|
QPalette p = palette();
|
||||||
|
p.setColor(QPalette::Base, QColor(Qt::transparent));
|
||||||
|
setPalette(p);
|
||||||
|
viewport()->setAutoFillBackground(false);
|
||||||
|
|
||||||
connect(this, &QTreeView::clicked, this, &PlacesView::onClicked);
|
connect(this, &QTreeView::clicked, this, &PlacesView::onClicked);
|
||||||
connect(this, &QTreeView::pressed, this, &PlacesView::onPressed);
|
connect(this, &QTreeView::pressed, this, &PlacesView::onPressed);
|
||||||
|
|
||||||
@ -49,7 +149,27 @@ PlacesView::PlacesView(QWidget* parent):
|
|||||||
setItemDelegateForColumn(0, delegate);
|
setItemDelegateForColumn(0, delegate);
|
||||||
|
|
||||||
model_ = PlacesModel::globalInstance();
|
model_ = PlacesModel::globalInstance();
|
||||||
setModel(model_.get());
|
if(!proxyModel_) {
|
||||||
|
proxyModel_ = std::make_shared<PlacesProxyModel>();
|
||||||
|
}
|
||||||
|
if(!proxyModel_->sourceModel()) { // all places-views may have been closed
|
||||||
|
proxyModel_->setSourceModel(model_.get());
|
||||||
|
}
|
||||||
|
setModel(proxyModel_.get());
|
||||||
|
|
||||||
|
// these 2 connections are needed to update filtering
|
||||||
|
connect(model_.get(), &QAbstractItemModel::rowsInserted, this, [this](const QModelIndex&, int, int) {
|
||||||
|
proxyModel_->setHidden(QString()); // just invalidates filter
|
||||||
|
expandAll();
|
||||||
|
// for some reason (a Qt bug?), spanning is reset
|
||||||
|
setFirstColumnSpanned(0, QModelIndex(), true);
|
||||||
|
setFirstColumnSpanned(1, QModelIndex(), true);
|
||||||
|
setFirstColumnSpanned(2, QModelIndex(), true);
|
||||||
|
|
||||||
|
});
|
||||||
|
connect(model_.get(), &QAbstractItemModel::rowsRemoved, this, [this](const QModelIndex&, int, int) {
|
||||||
|
proxyModel_->setHidden(QString());
|
||||||
|
});
|
||||||
|
|
||||||
QHeaderView* headerView = header();
|
QHeaderView* headerView = header();
|
||||||
headerView->setSectionResizeMode(0, QHeaderView::Stretch);
|
headerView->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||||
@ -84,7 +204,7 @@ void PlacesView::activateRow(int type, const QModelIndex& index) {
|
|||||||
if(!index.parent().isValid()) { // ignore root items
|
if(!index.parent().isValid()) { // ignore root items
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PlacesModelItem* item = static_cast<PlacesModelItem*>(model_->itemFromIndex(index));
|
PlacesModelItem* item = static_cast<PlacesModelItem*>(model_->itemFromIndex(proxyModel_->mapToSource(index)));
|
||||||
if(item) {
|
if(item) {
|
||||||
auto path = item->path();
|
auto path = item->path();
|
||||||
if(!path) {
|
if(!path) {
|
||||||
@ -155,10 +275,10 @@ void PlacesView::onClicked(const QModelIndex& index) {
|
|||||||
activateRow(0, index);
|
activateRow(0, index);
|
||||||
}
|
}
|
||||||
else if(index.column() == 1) { // column 1 contains eject buttons of the mounted devices
|
else if(index.column() == 1) { // column 1 contains eject buttons of the mounted devices
|
||||||
if(index.parent() == model_->devicesRoot->index()) { // this is a mounted device
|
if(index.parent() == proxyModel_->mapFromSource(model_->devicesRoot->index())) { // this is a mounted device
|
||||||
// the eject button is clicked
|
// the eject button is clicked
|
||||||
QModelIndex itemIndex = index.sibling(index.row(), 0); // the real item is at column 0
|
QModelIndex itemIndex = index.sibling(index.row(), 0); // the real item is at column 0
|
||||||
PlacesModelItem* item = static_cast<PlacesModelItem*>(model_->itemFromIndex(itemIndex));
|
PlacesModelItem* item = static_cast<PlacesModelItem*>(model_->itemFromIndex(proxyModel_->mapToSource(itemIndex)));
|
||||||
if(item) {
|
if(item) {
|
||||||
// eject the volume or the mount
|
// eject the volume or the mount
|
||||||
onEjectButtonClicked(item);
|
onEjectButtonClicked(item);
|
||||||
@ -176,7 +296,7 @@ void PlacesView::setCurrentPath(Fm::FilePath path) {
|
|||||||
// TODO: search for item with the path in model_ and select it.
|
// TODO: search for item with the path in model_ and select it.
|
||||||
PlacesModelItem* item = model_->itemFromPath(currentPath_);
|
PlacesModelItem* item = model_->itemFromPath(currentPath_);
|
||||||
if(item) {
|
if(item) {
|
||||||
selectionModel()->select(item->index(), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
|
selectionModel()->select(proxyModel_->mapFromSource(item->index()), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
clearSelection();
|
clearSelection();
|
||||||
@ -252,7 +372,7 @@ void PlacesView::onDeleteBookmark() {
|
|||||||
// virtual
|
// virtual
|
||||||
void PlacesView::commitData(QWidget* editor) {
|
void PlacesView::commitData(QWidget* editor) {
|
||||||
QTreeView::commitData(editor);
|
QTreeView::commitData(editor);
|
||||||
PlacesModelBookmarkItem* item = static_cast<PlacesModelBookmarkItem*>(model_->itemFromIndex(currentIndex()));
|
PlacesModelBookmarkItem* item = static_cast<PlacesModelBookmarkItem*>(model_->itemFromIndex(proxyModel_->mapToSource(currentIndex())));
|
||||||
auto bookmarkItem = item->bookmark();
|
auto bookmarkItem = item->bookmark();
|
||||||
// rename bookmark
|
// rename bookmark
|
||||||
Fm::Bookmarks::globalInstance()->rename(bookmarkItem, item->text());
|
Fm::Bookmarks::globalInstance()->rename(bookmarkItem, item->text());
|
||||||
@ -287,8 +407,8 @@ void PlacesView::onRenameBookmark() {
|
|||||||
}
|
}
|
||||||
PlacesModelBookmarkItem* item = static_cast<PlacesModelBookmarkItem*>(model_->itemFromIndex(action->index()));
|
PlacesModelBookmarkItem* item = static_cast<PlacesModelBookmarkItem*>(model_->itemFromIndex(action->index()));
|
||||||
setFocus();
|
setFocus();
|
||||||
setCurrentIndex(item->index());
|
setCurrentIndex(proxyModel_->mapFromSource(item->index()));
|
||||||
edit(item->index());
|
edit(proxyModel_->mapFromSource(item->index()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlacesView::onMountVolume() {
|
void PlacesView::onMountVolume() {
|
||||||
@ -338,21 +458,22 @@ void PlacesView::onEjectVolume() {
|
|||||||
|
|
||||||
void PlacesView::contextMenuEvent(QContextMenuEvent* event) {
|
void PlacesView::contextMenuEvent(QContextMenuEvent* event) {
|
||||||
QModelIndex index = indexAt(event->pos());
|
QModelIndex index = indexAt(event->pos());
|
||||||
if(index.isValid() && index.parent().isValid()) {
|
if(index.isValid()) {
|
||||||
if(index.column() != 0) { // the real item is at column 0
|
if(index.column() != 0) { // the real item is at column 0
|
||||||
index = index.sibling(index.row(), 0);
|
index = index.sibling(index.row(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not take the ownership of the menu since
|
// Do not take the ownership of the menu since
|
||||||
// it will be deleted with deleteLater() upon hidden.
|
// it will be deleted with deleteLater() upon hidden.
|
||||||
// This is possibly related to #145 - https://github.com/lxde/pcmanfm-qt/issues/145
|
// This is possibly related to #145 - https://github.com/lxqt/pcmanfm-qt/issues/145
|
||||||
QMenu* menu = new QMenu();
|
QMenu* menu = new QMenu();
|
||||||
QAction* action;
|
QAction* action = nullptr;
|
||||||
PlacesModelItem* item = static_cast<PlacesModelItem*>(model_->itemFromIndex(index));
|
PlacesModelItem* item = static_cast<PlacesModelItem*>(model_->itemFromIndex(proxyModel_->mapToSource(index)));
|
||||||
|
|
||||||
if(item->type() != PlacesModelItem::Mount
|
if(index.parent().isValid()
|
||||||
&& (item->type() != PlacesModelItem::Volume
|
&& item->type() != PlacesModelItem::Mount
|
||||||
|| static_cast<PlacesModelVolumeItem*>(item)->isMounted())) {
|
&& (item->type() != PlacesModelItem::Volume
|
||||||
|
|| static_cast<PlacesModelVolumeItem*>(item)->isMounted())) {
|
||||||
action = new PlacesModel::ItemAction(item->index(), tr("Open in New Tab"), menu);
|
action = new PlacesModel::ItemAction(item->index(), tr("Open in New Tab"), menu);
|
||||||
connect(action, &QAction::triggered, this, &PlacesView::onOpenNewTab);
|
connect(action, &QAction::triggered, this, &PlacesView::onOpenNewTab);
|
||||||
menu->addAction(action);
|
menu->addAction(action);
|
||||||
@ -364,11 +485,40 @@ void PlacesView::contextMenuEvent(QContextMenuEvent* event) {
|
|||||||
switch(item->type()) {
|
switch(item->type()) {
|
||||||
case PlacesModelItem::Places: {
|
case PlacesModelItem::Places: {
|
||||||
auto path = item->path();
|
auto path = item->path();
|
||||||
auto path_str = path.toString();
|
|
||||||
// FIXME: inefficient
|
// FIXME: inefficient
|
||||||
if(path && strcmp(path_str.get(), "trash:///") == 0) {
|
if(path) {
|
||||||
action = new PlacesModel::ItemAction(item->index(), tr("Empty Trash"), menu);
|
auto path_str = path.toString();
|
||||||
connect(action, &QAction::triggered, this, &PlacesView::onEmptyTrash);
|
if(strcmp(path_str.get(), "trash:///") == 0) {
|
||||||
|
action = new PlacesModel::ItemAction(item->index(), tr("Empty Trash"), menu);
|
||||||
|
auto icn = item->icon();
|
||||||
|
if(icn && icn->qicon().name() == QLatin1String("user-trash")) { // surely an empty trash
|
||||||
|
action->setEnabled(false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
connect(action, &QAction::triggered, this, &PlacesView::onEmptyTrash);
|
||||||
|
}
|
||||||
|
// add the "Empty Trash" item on the top
|
||||||
|
QList<QAction*> actions = menu->actions();
|
||||||
|
if(!actions.isEmpty()) {
|
||||||
|
menu->insertAction(actions.at(0), action);
|
||||||
|
menu->insertSeparator(actions.at(0));
|
||||||
|
}
|
||||||
|
else { // impossible
|
||||||
|
menu->addAction(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// add a "Hide" action to the end
|
||||||
|
menu->addSeparator();
|
||||||
|
action = new PlacesModel::ItemAction(item->index(), tr("Hide"), menu);
|
||||||
|
QString pathStr(path_str.get());
|
||||||
|
action->setCheckable(true);
|
||||||
|
if(proxyModel_->isShowingAll()) {
|
||||||
|
action->setChecked(proxyModel_->isHidden(pathStr));
|
||||||
|
}
|
||||||
|
connect(action, &QAction::triggered, [this, pathStr](bool checked) {
|
||||||
|
proxyModel_->setHidden(pathStr, checked);
|
||||||
|
Q_EMIT hiddenItemSet(pathStr, checked);
|
||||||
|
});
|
||||||
menu->addAction(action);
|
menu->addAction(action);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -411,6 +561,22 @@ void PlacesView::contextMenuEvent(QContextMenuEvent* event) {
|
|||||||
connect(action, &QAction::triggered, this, &PlacesView::onEjectVolume);
|
connect(action, &QAction::triggered, this, &PlacesView::onEjectVolume);
|
||||||
menu->addAction(action);
|
menu->addAction(action);
|
||||||
}
|
}
|
||||||
|
// add a "Hide" action to the end
|
||||||
|
CStrPtr uuid{g_volume_get_uuid(static_cast<PlacesModelVolumeItem*>(item)->volume())};
|
||||||
|
if(uuid) {
|
||||||
|
QString str = uuid.get();
|
||||||
|
menu->addSeparator();
|
||||||
|
action = new PlacesModel::ItemAction(item->index(), tr("Hide"), menu);
|
||||||
|
action->setCheckable(true);
|
||||||
|
if(proxyModel_->isShowingAll()) {
|
||||||
|
action->setChecked(proxyModel_->isHidden(str));
|
||||||
|
}
|
||||||
|
connect(action, &QAction::triggered, [this, str](bool checked) {
|
||||||
|
proxyModel_->setHidden(str, checked);
|
||||||
|
Q_EMIT hiddenItemSet(str, checked);
|
||||||
|
});
|
||||||
|
menu->addAction(action);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PlacesModelItem::Mount: {
|
case PlacesModelItem::Mount: {
|
||||||
@ -420,6 +586,21 @@ void PlacesView::contextMenuEvent(QContextMenuEvent* event) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// also add an acton for showing all hidden items
|
||||||
|
if(proxyModel_->hasHidden()) {
|
||||||
|
if(item->type() == PlacesModelItem::Bookmark) {
|
||||||
|
menu->addSeparator();
|
||||||
|
}
|
||||||
|
action = new PlacesModel::ItemAction(item->index(), tr("Show All Entries"), menu);
|
||||||
|
action->setCheckable(true);
|
||||||
|
action->setChecked(proxyModel_->isShowingAll());
|
||||||
|
connect(action, &QAction::triggered, [this](bool checked) {
|
||||||
|
showAll(checked);
|
||||||
|
});
|
||||||
|
menu->addAction(action);
|
||||||
|
}
|
||||||
|
|
||||||
if(menu->actions().size()) {
|
if(menu->actions().size()) {
|
||||||
menu->popup(mapToGlobal(event->pos()));
|
menu->popup(mapToGlobal(event->pos()));
|
||||||
connect(menu, &QMenu::aboutToHide, menu, &QMenu::deleteLater);
|
connect(menu, &QMenu::aboutToHide, menu, &QMenu::deleteLater);
|
||||||
@ -430,5 +611,19 @@ void PlacesView::contextMenuEvent(QContextMenuEvent* event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlacesView::restoreHiddenItems(const QSet<QString>& items) {
|
||||||
|
proxyModel_->restoreHiddenItems(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlacesView::showAll(bool show) {
|
||||||
|
proxyModel_->showAll(show);
|
||||||
|
if(show) {
|
||||||
|
expandAll();
|
||||||
|
// for some reason (a Qt bug?), spanning is reset
|
||||||
|
setFirstColumnSpanned(0, QModelIndex(), true);
|
||||||
|
setFirstColumnSpanned(1, QModelIndex(), true);
|
||||||
|
setFirstColumnSpanned(2, QModelIndex(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Fm
|
} // namespace Fm
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user