Compare commits
217 Commits
upstream/0
...
ubuntu/res
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
00cf26abba | ||
|
|
572480e2a8 | ||
|
|
b03c7a2d70 | ||
|
|
9f3c34f6a5 | ||
|
|
a15fb8b5f8 | ||
|
|
a61244bb78 | ||
|
|
87d221d5b8 | ||
|
|
979f2f6c5b | ||
|
|
71ef1bd4d1 | ||
|
|
321fd330ac | ||
|
|
4b47bffc4e | ||
|
|
fa488a15e2 | ||
| 22450d34cc | |||
| f2ddcc5b52 | |||
| d74fc4d211 | |||
| 399d02e4bf | |||
| 07aa29aec9 | |||
| e72435a954 | |||
|
|
7fa884cbf1 | ||
|
|
912ab3fe60 | ||
|
|
829a1de024 | ||
|
|
6cfade9fc8 | ||
|
|
21c71bf398 | ||
| d26ace9d2d | |||
| c87edf96d5 | |||
| 373a2574e3 | |||
| 1dedbee57b | |||
| b4b645757a | |||
| 23547f8ba7 | |||
| e21dde4311 | |||
| 733cda357d | |||
| 39655a4287 | |||
| 9682163144 | |||
| 245a200721 | |||
| c813d3f140 | |||
|
|
ab4baeb178 | ||
|
|
e08672cb49 | ||
|
|
637c32ce1b | ||
|
|
59c245310b | ||
|
|
7d655d511a | ||
|
|
fca5fc88e0 | ||
|
|
c67aa0abdc | ||
|
|
bb6c0071df | ||
|
|
cdfc1734c6 | ||
|
|
eff5a84fa6 | ||
|
|
11ffa3d90b | ||
| e0bad6c9b1 | |||
| 34835eb271 | |||
| 4446d0959d | |||
| 9c9c87e096 | |||
| 5c60472b2c | |||
| dfe3ac9066 | |||
| aa61af7064 | |||
| c5995d1954 | |||
| 698ef22927 | |||
| 8ef45eee80 | |||
| 6ade7ae79c | |||
| 2821aac388 | |||
| f55df2d639 | |||
| bc9b37daa9 | |||
| bb5a9128a7 | |||
| 21530fef77 | |||
|
|
169b71e30b | ||
|
|
82d4ef5652 | ||
| a96291458c | |||
| b088e93f7f | |||
| d31663e409 | |||
| ccda7c3087 | |||
| 315c0dc59e | |||
| cfedd381e7 | |||
| dbd537a42d | |||
|
|
9f1ed24cae | ||
|
|
d29bd881e2 | ||
|
|
f73353f96e | ||
|
|
1492432620 | ||
|
|
01ede1aef2 | ||
|
|
4b993cf8a3 | ||
|
|
34f58ecc62 | ||
|
|
6ab55e7491 | ||
|
|
3da5f088cc | ||
|
|
dfc11e6f10 | ||
|
|
799d3d012a | ||
|
|
011d17b63e | ||
|
|
842d629ea2 | ||
|
|
d717e744ce | ||
|
|
9a1edeaf1d | ||
|
|
c4a5aa20f2 | ||
|
|
74a26310af | ||
|
|
080e186170 | ||
|
|
e49123d636 | ||
|
|
6a115f8094 | ||
|
|
1e04a14cf3 | ||
|
|
0bb15fb1bf | ||
|
|
6c761062c5 | ||
|
|
6b4ff33f89 | ||
|
|
9958fa6b82 | ||
|
|
675cbb7210 | ||
|
|
44b4e33961 | ||
|
|
e60a20c17e | ||
|
|
bb042458e5 | ||
|
|
49eb8afa56 | ||
|
|
2f23742571 | ||
|
|
5fba8b840b | ||
|
|
307faf782b | ||
|
|
e34ee74853 | ||
|
|
11e85f2a87 | ||
|
|
6fc1ada88a | ||
|
|
3194275f96 | ||
|
|
c8fa152f29 | ||
|
|
90f60f818b | ||
|
|
98bdec9473 | ||
|
|
49f999091b | ||
|
|
11102b8d08 | ||
|
|
c4f67c3906 | ||
|
|
b9b8a01b55 | ||
|
|
78f7986504 | ||
|
|
4e4a9b3908 | ||
|
|
e5d8da79c0 | ||
|
|
326f8dd6f9 | ||
|
|
15d47c8e57 | ||
|
|
62151a370b | ||
|
|
b370555cc3 | ||
|
|
866039af05 | ||
|
|
480d94f7f5 | ||
|
|
d09888c454 | ||
|
|
eb6916f0a7 | ||
|
|
efed1e3119 | ||
|
|
9ea0f1a4be | ||
|
|
70b4f82ab1 | ||
|
|
7abaf9d2e6 | ||
|
|
61b4bc3d35 | ||
|
|
2a517021f3 | ||
|
|
bec0f3ea86 | ||
|
|
926edb0396 | ||
|
|
3f07200314 | ||
|
|
f801dd7035 | ||
|
|
ee96279965 | ||
|
|
faaa439846 | ||
|
|
356dcd1014 | ||
|
|
557d261df0 | ||
|
|
5d01775fec | ||
|
|
01a9de2c4f | ||
|
|
c502dedff1 | ||
|
|
f1e4f5d637 | ||
|
|
5be41ce493 | ||
|
|
01aeefbffd | ||
|
|
b69cb453e3 | ||
|
|
3875d79e68 | ||
|
|
bcb478e197 | ||
|
|
5ba342087b | ||
|
|
c93248fac7 | ||
|
|
d8393dd74a | ||
|
|
bc985cdd4d | ||
|
|
853122506e | ||
|
|
cd2f3a980a | ||
|
|
4a5f5ef727 | ||
|
|
2dd745096a | ||
|
|
4e3261d606 | ||
|
|
ace6ee4cb7 | ||
|
|
889b917757 | ||
|
|
166a1fae99 | ||
|
|
bc717e9763 | ||
|
|
6181eb55c7 | ||
|
|
1738e4b700 | ||
|
|
e9791a6163 | ||
|
|
41dd175f3f | ||
|
|
8cbd5663e0 | ||
|
|
a74374ee73 | ||
|
|
0b732f1fd4 | ||
|
|
02478c5694 | ||
|
|
794ac4ec2b | ||
|
|
140ea60928 | ||
|
|
15a2c67d9f | ||
|
|
cd3b23dcbb | ||
|
|
ee0255e79f | ||
|
|
8c0281598b | ||
|
|
7da8b31472 | ||
|
|
14e3d3ab91 | ||
|
|
46bbfd4ac8 | ||
|
|
7bce957e57 | ||
|
|
c021d58e02 | ||
|
|
35eb3fdfe0 | ||
|
|
bc6b06ce4f | ||
|
|
7896a7d48d | ||
|
|
5f64a2f182 | ||
|
|
df56a437e5 | ||
|
|
14b1367dd5 | ||
|
|
7550f16b07 | ||
|
|
5ec88a6a38 | ||
|
|
9d92b4a6d3 | ||
|
|
d4bbc4a7b0 | ||
|
|
7c935b14b7 | ||
|
|
4257411f78 | ||
|
|
cc85e464be | ||
|
|
1072e28975 | ||
|
|
62f2c3ca4d | ||
|
|
70b7fc1fa3 | ||
|
|
fec780f7bf | ||
|
|
429371c156 | ||
|
|
9dbd31480c | ||
|
|
241d57f584 | ||
|
|
c837192d61 | ||
|
|
cd6f404585 | ||
|
|
1bacc87d6a | ||
|
|
b34299d874 | ||
|
|
482e5a30c2 | ||
|
|
7d261ba312 | ||
|
|
c120d6ee8f | ||
|
|
a05e6b5b74 | ||
|
|
39c016af94 | ||
|
|
93474b5e33 | ||
|
|
39ae877d1a | ||
|
|
24256dcb0a | ||
|
|
ab2b47837c | ||
|
|
76ede8bd98 | ||
|
|
f2440efe2a | ||
|
|
87f3814a85 |
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,2 +1 @@
|
|||||||
build
|
debian/files
|
||||||
.kdev4
|
|
||||||
|
|||||||
9
AUTHORS
9
AUTHORS
@ -1,9 +0,0 @@
|
|||||||
Upstream Authors:
|
|
||||||
LXQt team: http://lxqt.org
|
|
||||||
Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
Copyright:
|
|
||||||
Copyright (c) 2013-2014 LXQt team
|
|
||||||
|
|
||||||
License: GPL-2
|
|
||||||
The full text of the licenses can be found in the 'COPYING' file.
|
|
||||||
101
CMakeLists.txt
101
CMakeLists.txt
@ -1,101 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.11)
|
|
||||||
project(pcmanfm-qt)
|
|
||||||
|
|
||||||
set(PCMANFM_QT_VERSION_MAJOR 0)
|
|
||||||
set(PCMANFM_QT_VERSION_MINOR 9)
|
|
||||||
set(PCMANFM_QT_VERSION_PATCH 0)
|
|
||||||
set(PCMANFM_QT_VERSION ${PCMANFM_QT_VERSION_MAJOR}.${PCMANFM_QT_VERSION_MINOR}.${PCMANFM_QT_VERSION_PATCH})
|
|
||||||
|
|
||||||
set(LIBFM_QT_VERSION_MAJOR 0)
|
|
||||||
set(LIBFM_QT_VERSION_MINOR 9)
|
|
||||||
set(LIBFM_QT_VERSION_PATCH 0)
|
|
||||||
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")
|
|
||||||
|
|
||||||
# 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.sourceware.org/autobook/autobook/autobook_91.html
|
|
||||||
# http://pusling.com/blog/?p=352
|
|
||||||
# Actually, libtool uses different ways on different operating systems. So there is no
|
|
||||||
# universal way to translate a libtool version-info to a cmake version.
|
|
||||||
# We use "(current-age).age.revision" as the cmake version.
|
|
||||||
# current: 2, revision: 0, age: 0 => version: 2.0.0
|
|
||||||
set(LIBFM_QT_LIB_VERSION "2.0.0")
|
|
||||||
set(LIBFM_QT_LIB_SOVERSION "2")
|
|
||||||
|
|
||||||
find_package(Qt5Widgets 5.2 REQUIRED)
|
|
||||||
find_package(Qt5DBus 5.2 REQUIRED)
|
|
||||||
find_package(Qt5LinguistTools 5.2 REQUIRED)
|
|
||||||
find_package(Qt5X11Extras 5.2 REQUIRED)
|
|
||||||
|
|
||||||
find_package(PkgConfig)
|
|
||||||
pkg_check_modules(SYSTEM_LIBS REQUIRED
|
|
||||||
glib-2.0
|
|
||||||
gio-2.0
|
|
||||||
gio-unix-2.0
|
|
||||||
xcb
|
|
||||||
)
|
|
||||||
|
|
||||||
pkg_check_modules(LIBFM REQUIRED libfm>=1.2.0)
|
|
||||||
pkg_check_modules(LIBMENUCACHE REQUIRED libmenu-cache>=0.4.0)
|
|
||||||
|
|
||||||
option(UPDATE_TRANSLATIONS "Update source translation translations/*.ts files" OFF)
|
|
||||||
include(GNUInstallDirs)
|
|
||||||
include(LXQtTranslateTs)
|
|
||||||
include(LXQtTranslateDesktop)
|
|
||||||
|
|
||||||
add_definitions(-DQT_NO_KEYWORDS)
|
|
||||||
|
|
||||||
if (CMAKE_COMPILER_IS_GNUCXX)
|
|
||||||
# set visibility to hidden to hide symbols, unless they're exported manually in the code
|
|
||||||
set(CMAKE_CXX_FLAGS "-fvisibility=hidden -fvisibility-inlines-hidden -fno-exceptions ${CMAKE_CXX_FLAGS}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(CMAKE_AUTOMOC TRUE)
|
|
||||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
|
||||||
|
|
||||||
add_subdirectory(libfm-qt)
|
|
||||||
add_subdirectory(pcmanfm)
|
|
||||||
|
|
||||||
# manpage for pcmanfm-qt
|
|
||||||
configure_file(
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/pcmanfm-qt.1.in"
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/pcmanfm-qt.1"
|
|
||||||
@ONLY
|
|
||||||
)
|
|
||||||
install(FILES
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/pcmanfm-qt.1"
|
|
||||||
DESTINATION "${CMAKE_INSTALL_MANDIR}/man1"
|
|
||||||
)
|
|
||||||
|
|
||||||
# add Doxygen support to generate API docs
|
|
||||||
# References:
|
|
||||||
# http://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)
|
|
||||||
if(BUILD_DOCUMENTATION)
|
|
||||||
find_package(Doxygen REQUIRED)
|
|
||||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in" "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile" @ONLY)
|
|
||||||
add_custom_target(doc ALL
|
|
||||||
${DOXYGEN_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile"
|
|
||||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
|
||||||
COMMENT "Generating API documentation with Doxygen" VERBATIM
|
|
||||||
)
|
|
||||||
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/docs" DESTINATION "${CMAKE_INSTALL_DOCDIR}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# building tarball with CPack -------------------------------------------------
|
|
||||||
# To create a source distribution, type:
|
|
||||||
# make package_source
|
|
||||||
include(InstallRequiredSystemLibraries)
|
|
||||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING")
|
|
||||||
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README")
|
|
||||||
set(CPACK_PACKAGE_VENDOR "")
|
|
||||||
set(CPACK_PACKAGE_VERSION_MAJOR ${PCMANFM_QT_VERSION_MAJOR})
|
|
||||||
set(CPACK_PACKAGE_VERSION_MINOR ${PCMANFM_QT_VERSION_MINOR})
|
|
||||||
set(CPACK_PACKAGE_VERSION_PATCH ${PCMANFM_QT_VERSION_PATCH})
|
|
||||||
set(CPACK_GENERATOR TBZ2)
|
|
||||||
set(CPACK_SOURCE_GENERATOR TBZ2)
|
|
||||||
set(CPACK_SOURCE_IGNORE_FILES /build/;.gitignore;.*~;.git;.kdev4;temp)
|
|
||||||
include(CPack)
|
|
||||||
280
COPYING
280
COPYING
@ -1,280 +0,0 @@
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
Version 2, June 1991
|
|
||||||
|
|
||||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The licenses for most software are designed to take away your
|
|
||||||
freedom to share and change it. By contrast, the GNU General Public
|
|
||||||
License is intended to guarantee your freedom to share and change free
|
|
||||||
software--to make sure the software is free for all its users. This
|
|
||||||
General Public License applies to most of the Free Software
|
|
||||||
Foundation's software and to any other program whose authors commit to
|
|
||||||
using it. (Some other Free Software Foundation software is covered by
|
|
||||||
the GNU Lesser General Public License instead.) You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
this service if you wish), that you receive source code or can get it
|
|
||||||
if you want it, that you can change the software or use pieces of it
|
|
||||||
in new free programs; and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to make restrictions that forbid
|
|
||||||
anyone to deny you these rights or to ask you to surrender the rights.
|
|
||||||
These restrictions translate to certain responsibilities for you if you
|
|
||||||
distribute copies of the software, or if you modify it.
|
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
|
||||||
gratis or for a fee, you must give the recipients all the rights that
|
|
||||||
you have. You must make sure that they, too, receive or can get the
|
|
||||||
source code. And you must show them these terms so they know their
|
|
||||||
rights.
|
|
||||||
|
|
||||||
We protect your rights with two steps: (1) copyright the software, and
|
|
||||||
(2) offer you this license which gives you legal permission to copy,
|
|
||||||
distribute and/or modify the software.
|
|
||||||
|
|
||||||
Also, for each author's protection and ours, we want to make certain
|
|
||||||
that everyone understands that there is no warranty for this free
|
|
||||||
software. If the software is modified by someone else and passed on, we
|
|
||||||
want its recipients to know that what they have is not the original, so
|
|
||||||
that any problems introduced by others will not reflect on the original
|
|
||||||
authors' reputations.
|
|
||||||
|
|
||||||
Finally, any free program is threatened constantly by software
|
|
||||||
patents. We wish to avoid the danger that redistributors of a free
|
|
||||||
program will individually obtain patent licenses, in effect making the
|
|
||||||
program proprietary. To prevent this, we have made it clear that any
|
|
||||||
patent must be licensed for everyone's free use or not licensed at all.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
|
|
||||||
0. This License applies to any program or other work which contains
|
|
||||||
a notice placed by the copyright holder saying it may be distributed
|
|
||||||
under the terms of this General Public License. The "Program", below,
|
|
||||||
refers to any such program or work, and a "work based on the Program"
|
|
||||||
means either the Program or any derivative work under copyright law:
|
|
||||||
that is to say, a work containing the Program or a portion of it,
|
|
||||||
either verbatim or with modifications and/or translated into another
|
|
||||||
language. (Hereinafter, translation is included without limitation in
|
|
||||||
the term "modification".) Each licensee is addressed as "you".
|
|
||||||
|
|
||||||
Activities other than copying, distribution and modification are not
|
|
||||||
covered by this License; they are outside its scope. The act of
|
|
||||||
running the Program is not restricted, and the output from the Program
|
|
||||||
is covered only if its contents constitute a work based on the
|
|
||||||
Program (independent of having been made by running the Program).
|
|
||||||
Whether that is true depends on what the Program does.
|
|
||||||
|
|
||||||
1. You may copy and distribute verbatim copies of the Program's
|
|
||||||
source code as you receive it, in any medium, provided that you
|
|
||||||
conspicuously and appropriately publish on each copy an appropriate
|
|
||||||
copyright notice and disclaimer of warranty; keep intact all the
|
|
||||||
notices that refer to this License and to the absence of any warranty;
|
|
||||||
and give any other recipients of the Program a copy of this License
|
|
||||||
along with the Program.
|
|
||||||
|
|
||||||
You may charge a fee for the physical act of transferring a copy, and
|
|
||||||
you may at your option offer warranty protection in exchange for a fee.
|
|
||||||
|
|
||||||
2. You may modify your copy or copies of the Program or any portion
|
|
||||||
of it, thus forming a work based on the Program, and copy and
|
|
||||||
distribute such modifications or work under the terms of Section 1
|
|
||||||
above, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) You must cause the modified files to carry prominent notices
|
|
||||||
stating that you changed the files and the date of any change.
|
|
||||||
|
|
||||||
b) You must cause any work that you distribute or publish, that in
|
|
||||||
whole or in part contains or is derived from the Program or any
|
|
||||||
part thereof, to be licensed as a whole at no charge to all third
|
|
||||||
parties under the terms of this License.
|
|
||||||
|
|
||||||
c) If the modified program normally reads commands interactively
|
|
||||||
when run, you must cause it, when started running for such
|
|
||||||
interactive use in the most ordinary way, to print or display an
|
|
||||||
announcement including an appropriate copyright notice and a
|
|
||||||
notice that there is no warranty (or else, saying that you provide
|
|
||||||
a warranty) and that users may redistribute the program under
|
|
||||||
these conditions, and telling the user how to view a copy of this
|
|
||||||
License. (Exception: if the Program itself is interactive but
|
|
||||||
does not normally print such an announcement, your work based on
|
|
||||||
the Program is not required to print an announcement.)
|
|
||||||
|
|
||||||
These requirements apply to the modified work as a whole. If
|
|
||||||
identifiable sections of that work are not derived from the Program,
|
|
||||||
and can be reasonably considered independent and separate works in
|
|
||||||
themselves, then this License, and its terms, do not apply to those
|
|
||||||
sections when you distribute them as separate works. But when you
|
|
||||||
distribute the same sections as part of a whole which is a work based
|
|
||||||
on the Program, the distribution of the whole must be on the terms of
|
|
||||||
this License, whose permissions for other licensees extend to the
|
|
||||||
entire whole, and thus to each and every part regardless of who wrote it.
|
|
||||||
|
|
||||||
Thus, it is not the intent of this section to claim rights or contest
|
|
||||||
your rights to work written entirely by you; rather, the intent is to
|
|
||||||
exercise the right to control the distribution of derivative or
|
|
||||||
collective works based on the Program.
|
|
||||||
|
|
||||||
In addition, mere aggregation of another work not based on the Program
|
|
||||||
with the Program (or with a work based on the Program) on a volume of
|
|
||||||
a storage or distribution medium does not bring the other work under
|
|
||||||
the scope of this License.
|
|
||||||
|
|
||||||
3. You may copy and distribute the Program (or a work based on it,
|
|
||||||
under Section 2) in object code or executable form under the terms of
|
|
||||||
Sections 1 and 2 above provided that you also do one of the following:
|
|
||||||
|
|
||||||
a) Accompany it with the complete corresponding machine-readable
|
|
||||||
source code, which must be distributed under the terms of Sections
|
|
||||||
1 and 2 above on a medium customarily used for software interchange; or,
|
|
||||||
|
|
||||||
b) Accompany it with a written offer, valid for at least three
|
|
||||||
years, to give any third party, for a charge no more than your
|
|
||||||
cost of physically performing source distribution, a complete
|
|
||||||
machine-readable copy of the corresponding source code, to be
|
|
||||||
distributed under the terms of Sections 1 and 2 above on a medium
|
|
||||||
customarily used for software interchange; or,
|
|
||||||
|
|
||||||
c) Accompany it with the information you received as to the offer
|
|
||||||
to distribute corresponding source code. (This alternative is
|
|
||||||
allowed only for noncommercial distribution and only if you
|
|
||||||
received the program in object code or executable form with such
|
|
||||||
an offer, in accord with Subsection b above.)
|
|
||||||
|
|
||||||
The source code for a work means the preferred form of the work for
|
|
||||||
making modifications to it. For an executable work, complete source
|
|
||||||
code means all the source code for all modules it contains, plus any
|
|
||||||
associated interface definition files, plus the scripts used to
|
|
||||||
control compilation and installation of the executable. However, as a
|
|
||||||
special exception, the source code distributed need not include
|
|
||||||
anything that is normally distributed (in either source or binary
|
|
||||||
form) with the major components (compiler, kernel, and so on) of the
|
|
||||||
operating system on which the executable runs, unless that component
|
|
||||||
itself accompanies the executable.
|
|
||||||
|
|
||||||
If distribution of executable or object code is made by offering
|
|
||||||
access to copy from a designated place, then offering equivalent
|
|
||||||
access to copy the source code from the same place counts as
|
|
||||||
distribution of the source code, even though third parties are not
|
|
||||||
compelled to copy the source along with the object code.
|
|
||||||
|
|
||||||
4. You may not copy, modify, sublicense, or distribute the Program
|
|
||||||
except as expressly provided under this License. Any attempt
|
|
||||||
otherwise to copy, modify, sublicense or distribute the Program is
|
|
||||||
void, and will automatically terminate your rights under this License.
|
|
||||||
However, parties who have received copies, or rights, from you under
|
|
||||||
this License will not have their licenses terminated so long as such
|
|
||||||
parties remain in full compliance.
|
|
||||||
|
|
||||||
5. You are not required to accept this License, since you have not
|
|
||||||
signed it. However, nothing else grants you permission to modify or
|
|
||||||
distribute the Program or its derivative works. These actions are
|
|
||||||
prohibited by law if you do not accept this License. Therefore, by
|
|
||||||
modifying or distributing the Program (or any work based on the
|
|
||||||
Program), you indicate your acceptance of this License to do so, and
|
|
||||||
all its terms and conditions for copying, distributing or modifying
|
|
||||||
the Program or works based on it.
|
|
||||||
|
|
||||||
6. Each time you redistribute the Program (or any work based on the
|
|
||||||
Program), the recipient automatically receives a license from the
|
|
||||||
original licensor to copy, distribute or modify the Program subject to
|
|
||||||
these terms and conditions. You may not impose any further
|
|
||||||
restrictions on the recipients' exercise of the rights granted herein.
|
|
||||||
You are not responsible for enforcing compliance by third parties to
|
|
||||||
this License.
|
|
||||||
|
|
||||||
7. If, as a consequence of a court judgment or allegation of patent
|
|
||||||
infringement or for any other reason (not limited to patent issues),
|
|
||||||
conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot
|
|
||||||
distribute so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you
|
|
||||||
may not distribute the Program at all. For example, if a patent
|
|
||||||
license would not permit royalty-free redistribution of the Program by
|
|
||||||
all those who receive copies directly or indirectly through you, then
|
|
||||||
the only way you could satisfy both it and this License would be to
|
|
||||||
refrain entirely from distribution of the Program.
|
|
||||||
|
|
||||||
If any portion of this section is held invalid or unenforceable under
|
|
||||||
any particular circumstance, the balance of the section is intended to
|
|
||||||
apply and the section as a whole is intended to apply in other
|
|
||||||
circumstances.
|
|
||||||
|
|
||||||
It is not the purpose of this section to induce you to infringe any
|
|
||||||
patents or other property right claims or to contest validity of any
|
|
||||||
such claims; this section has the sole purpose of protecting the
|
|
||||||
integrity of the free software distribution system, which is
|
|
||||||
implemented by public license practices. Many people have made
|
|
||||||
generous contributions to the wide range of software distributed
|
|
||||||
through that system in reliance on consistent application of that
|
|
||||||
system; it is up to the author/donor to decide if he or she is willing
|
|
||||||
to distribute software through any other system and a licensee cannot
|
|
||||||
impose that choice.
|
|
||||||
|
|
||||||
This section is intended to make thoroughly clear what is believed to
|
|
||||||
be a consequence of the rest of this License.
|
|
||||||
|
|
||||||
8. If the distribution and/or use of the Program is restricted in
|
|
||||||
certain countries either by patents or by copyrighted interfaces, the
|
|
||||||
original copyright holder who places the Program under this License
|
|
||||||
may add an explicit geographical distribution limitation excluding
|
|
||||||
those countries, so that distribution is permitted only in or among
|
|
||||||
countries not thus excluded. In such case, this License incorporates
|
|
||||||
the limitation as if written in the body of this License.
|
|
||||||
|
|
||||||
9. The Free Software Foundation may publish revised and/or new versions
|
|
||||||
of the General Public License from time to time. Such new versions will
|
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the Program
|
|
||||||
specifies a version number of this License which applies to it and "any
|
|
||||||
later version", you have the option of following the terms and conditions
|
|
||||||
either of that version or of any later version published by the Free
|
|
||||||
Software Foundation. If the Program does not specify a version number of
|
|
||||||
this License, you may choose any version ever published by the Free Software
|
|
||||||
Foundation.
|
|
||||||
|
|
||||||
10. If you wish to incorporate parts of the Program into other free
|
|
||||||
programs whose distribution conditions are different, write to the author
|
|
||||||
to ask for permission. For software which is copyrighted by the Free
|
|
||||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
|
||||||
make exceptions for this. Our decision will be guided by the two goals
|
|
||||||
of preserving the free status of all derivatives of our free software and
|
|
||||||
of promoting the sharing and reuse of software generally.
|
|
||||||
|
|
||||||
NO WARRANTY
|
|
||||||
|
|
||||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
|
||||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
|
||||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
|
||||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
|
||||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
|
||||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
|
||||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
|
||||||
REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
|
||||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
|
||||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
|
||||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
|
||||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
|
||||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
|
||||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGES.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
1890
Doxyfile.in
1890
Doxyfile.in
File diff suppressed because it is too large
Load Diff
11
README
11
README
@ -1,11 +0,0 @@
|
|||||||
PCManFM-Qt is the Qt port of the LXDE file manager PCManFM.
|
|
||||||
Libfm-Qt is a companion library providing components to build desktop file managers.
|
|
||||||
|
|
||||||
Issue tracker:
|
|
||||||
https://github.com/lxde/pcmanfm-qt/issues
|
|
||||||
|
|
||||||
LXQt website:
|
|
||||||
http://lxqt.org
|
|
||||||
|
|
||||||
LXDE website:
|
|
||||||
http://lxde.org
|
|
||||||
@ -1,107 +0,0 @@
|
|||||||
#=============================================================================
|
|
||||||
# The lxqt_translate_desktop() function was copied from the the
|
|
||||||
# LXQt LxQtTranste.cmake
|
|
||||||
#
|
|
||||||
# Original Author: Alexander Sokolov <sokoloff.a@gmail.com>
|
|
||||||
#
|
|
||||||
# funtion lxqt_translate_desktop(_RESULT
|
|
||||||
# SOURCES <sources>
|
|
||||||
# [TRANSLATION_DIR] translation_directory
|
|
||||||
# )
|
|
||||||
# Output:
|
|
||||||
# _RESULT The generated .desktop (.desktop) files
|
|
||||||
#
|
|
||||||
# Input:
|
|
||||||
#
|
|
||||||
# SOURCES List of input desktop files (.destktop.in) to be translated
|
|
||||||
# (merged), relative to the CMakeList.txt.
|
|
||||||
#
|
|
||||||
# TRANSLATION_DIR Optional path to the directory with the .ts files,
|
|
||||||
# relative to the CMakeList.txt. Defaults to
|
|
||||||
# "translations".
|
|
||||||
#
|
|
||||||
#=============================================================================
|
|
||||||
|
|
||||||
function(lxqt_translate_desktop _RESULT)
|
|
||||||
# Parse arguments ***************************************
|
|
||||||
set(oneValueArgs TRANSLATION_DIR)
|
|
||||||
set(multiValueArgs SOURCES)
|
|
||||||
|
|
||||||
cmake_parse_arguments(_ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
||||||
|
|
||||||
# check for unknown arguments
|
|
||||||
set(_UNPARSED_ARGS ${_ARGS_UNPARSED_ARGUMENTS})
|
|
||||||
if (NOT ${_UNPARSED_ARGS} STREQUAL "")
|
|
||||||
MESSAGE(FATAL_ERROR
|
|
||||||
"Unknown arguments '${_UNPARSED_ARGS}'.\n"
|
|
||||||
"See lxqt_translate_desktop() documenation for more information.\n"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (NOT DEFINED _ARGS_SOURCES)
|
|
||||||
set(${_RESULT} "" PARENT_SCOPE)
|
|
||||||
return()
|
|
||||||
else()
|
|
||||||
set(_sources ${_ARGS_SOURCES})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (NOT DEFINED _ARGS_TRANSLATION_DIR)
|
|
||||||
set(_translationDir "translations")
|
|
||||||
else()
|
|
||||||
set(_translationDir ${_ARGS_TRANSLATION_DIR})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
get_filename_component (_translationDir ${_translationDir} ABSOLUTE)
|
|
||||||
|
|
||||||
foreach (_inFile ${_sources})
|
|
||||||
get_filename_component(_inFile ${_inFile} ABSOLUTE)
|
|
||||||
get_filename_component(_fileName ${_inFile} NAME_WE)
|
|
||||||
#Extract the real extension ............
|
|
||||||
get_filename_component(_fileExt ${_inFile} EXT)
|
|
||||||
string(REPLACE ".in" "" _fileExt ${_fileExt})
|
|
||||||
#.......................................
|
|
||||||
set(_outFile "${CMAKE_CURRENT_BINARY_DIR}/${_fileName}${_fileExt}")
|
|
||||||
|
|
||||||
file(GLOB _translations
|
|
||||||
${_translationDir}/${_fileName}_*${_fileExt}
|
|
||||||
${_translationDir}/local/${_fileName}_*${_fileExt}
|
|
||||||
)
|
|
||||||
|
|
||||||
set(_pattern "'\\[.*]\\s*='")
|
|
||||||
if (_translations)
|
|
||||||
add_custom_command(OUTPUT ${_outFile}
|
|
||||||
COMMAND grep -v "'#TRANSLATIONS_DIR='" ${_inFile} > ${_outFile}
|
|
||||||
COMMAND grep -h ${_pattern} ${_translations} >> ${_outFile}
|
|
||||||
COMMENT "Generating ${_fileName}${_fileExt}"
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
add_custom_command(OUTPUT ${_outFile}
|
|
||||||
COMMAND grep -v "'#TRANSLATIONS_DIR='" ${_inFile} > ${_outFile}
|
|
||||||
COMMENT "Generating ${_fileName}${_fileExt}"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(__result ${__result} ${_outFile})
|
|
||||||
|
|
||||||
|
|
||||||
# TX file ***********************************************
|
|
||||||
set(_txFile "${CMAKE_BINARY_DIR}/tx/${_fileName}${_fileExt}.tx.sh")
|
|
||||||
string(REPLACE "${CMAKE_SOURCE_DIR}/" "" _tx_translationDir ${_translationDir})
|
|
||||||
string(REPLACE "${CMAKE_SOURCE_DIR}/" "" _tx_inFile ${_inFile})
|
|
||||||
string(REPLACE "." "" _fileType ${_fileExt})
|
|
||||||
|
|
||||||
file(WRITE ${_txFile}
|
|
||||||
"[ -f ${_inFile} ] || exit 0\n"
|
|
||||||
"echo '[lxde-qt.${_fileName}_${_fileType}]'\n"
|
|
||||||
"echo 'type = DESKTOP'\n"
|
|
||||||
"echo 'source_lang = en'\n"
|
|
||||||
"echo 'source_file = ${_tx_inFile}'\n"
|
|
||||||
"echo 'file_filter = ${_tx_translationDir}/${_fileName}_<lang>${_fileExt}'\n"
|
|
||||||
"echo ''\n"
|
|
||||||
)
|
|
||||||
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
set(${_RESULT} ${__result} PARENT_SCOPE)
|
|
||||||
endfunction(lxqt_translate_desktop)
|
|
||||||
@ -1,131 +0,0 @@
|
|||||||
#=============================================================================
|
|
||||||
# Copyright 2014 Luís Pereira <luis.artur.pereira@gmail.com>
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
#
|
|
||||||
# 1. Redistributions of source code must retain the copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
# 3. The name of the author may not be used to endorse or promote products
|
|
||||||
# derived from this software without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
#=============================================================================
|
|
||||||
#
|
|
||||||
# funtion lxqt_translate_ts(qmFiles
|
|
||||||
# [USE_QT5 [Yes | No]]
|
|
||||||
# [UPDATE_TRANSLATIONS [Yes | No]]
|
|
||||||
# SOURCES <sources>
|
|
||||||
# [TEMPLATE] translation_template
|
|
||||||
# [TRANSLATION_DIR] translation_directory
|
|
||||||
# [INSTALL_DIR] install_directory
|
|
||||||
# )
|
|
||||||
# Output:
|
|
||||||
# qmFiles The generated compiled translations (.qm) files
|
|
||||||
#
|
|
||||||
# Input:
|
|
||||||
# USE_QT5 Optional flag to choose between Qt4 and Qt5. Defaults to Qt5
|
|
||||||
#
|
|
||||||
# UPDATE_TRANSLATIONS Optional flag. Setting it to Yes, extracts and
|
|
||||||
# compiles the translations. Setting it No, only
|
|
||||||
# compiles them.
|
|
||||||
#
|
|
||||||
# TEMPLATE Optional translations files base name. Defaults to
|
|
||||||
# ${PROJECT_NAME}. An .ts extensions is added.
|
|
||||||
#
|
|
||||||
# TRANSLATION_DIR Optional path to the directory with the .ts files,
|
|
||||||
# relative to the CMakeList.txt. Defaults to
|
|
||||||
# "translations".
|
|
||||||
#
|
|
||||||
# INSTALL_DIR Optional destination of the file compiled files (qmFiles).
|
|
||||||
# If not present no installation is performed
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# CMake v2.8.3 needed to use the CMakeParseArguments module
|
|
||||||
cmake_minimum_required(VERSION 2.8.3 FATAL_ERROR)
|
|
||||||
|
|
||||||
# We use our patched version to round a annoying bug.
|
|
||||||
include(Qt5PatchedLinguistToolsMacros)
|
|
||||||
|
|
||||||
function(lxqt_translate_ts qmFiles)
|
|
||||||
set(oneValueArgs USE_QT5 UPDATE_TRANSLATIONS TEMPLATE TRANSLATION_DIR INSTALL_DIR)
|
|
||||||
set(multiValueArgs SOURCES)
|
|
||||||
cmake_parse_arguments(TR "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
||||||
|
|
||||||
if (NOT DEFINED TR_UPDATE_TRANSLATIONS)
|
|
||||||
set(TR_UPDATE_TRANSLATIONS "No")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (NOT DEFINED TR_USE_QT5)
|
|
||||||
set(TR_USE_QT5 "Yes")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT DEFINED TR_TEMPLATE)
|
|
||||||
set(TR_TEMPLATE "${PROJECT_NAME}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (NOT DEFINED TR_TRANSLATION_DIR)
|
|
||||||
set(TR_TRANSLATION_DIR "translations")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
file(GLOB tsFiles "${TR_TRANSLATION_DIR}/${TR_TEMPLATE}_*.ts")
|
|
||||||
set(templateFile "${TR_TRANSLATION_DIR}/${TR_TEMPLATE}.ts")
|
|
||||||
|
|
||||||
if(TR_USE_QT5)
|
|
||||||
# Qt5
|
|
||||||
if (TR_UPDATE_TRANSLATIONS)
|
|
||||||
qt5_patched_create_translation(QMS
|
|
||||||
${TR_SOURCES}
|
|
||||||
${templateFile}
|
|
||||||
OPTIONS -locations absolute
|
|
||||||
)
|
|
||||||
qt5_patched_create_translation(QM
|
|
||||||
${TR_SOURCES}
|
|
||||||
${tsFiles}
|
|
||||||
OPTIONS -locations absolute
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
qt5_patched_add_translation(QM ${tsFiles})
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
# Qt4
|
|
||||||
if(TR_UPDATE_TRANSLATIONS)
|
|
||||||
qt4_create_translation(QMS
|
|
||||||
${TR_SOURCES}
|
|
||||||
${templateFile}
|
|
||||||
OPTIONS -locations absolute
|
|
||||||
)
|
|
||||||
qt4_create_translation(QM
|
|
||||||
${TR_SOURCES}
|
|
||||||
${tsFiles}
|
|
||||||
OPTIONS -locations absolute
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
qt4_add_translation(QM ${tsFiles})
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(TR_UPDATE_TRANSLATIONS)
|
|
||||||
add_custom_target("update_${TR_TEMPLATE}_ts" ALL DEPENDS ${QMS})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(DEFINED TR_INSTALL_DIR)
|
|
||||||
install(FILES ${QM} DESTINATION ${TR_INSTALL_DIR})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(${qmFiles} ${QM} PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
@ -1,112 +0,0 @@
|
|||||||
#=============================================================================
|
|
||||||
# Copyright 2005-2011 Kitware, Inc.
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
#
|
|
||||||
# * Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
#
|
|
||||||
# * Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# * Neither the name of Kitware, Inc. nor the names of its
|
|
||||||
# contributors may be used to endorse or promote products derived
|
|
||||||
# from this software without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
#=============================================================================
|
|
||||||
|
|
||||||
include(CMakeParseArguments)
|
|
||||||
|
|
||||||
function(QT5_PATCHED_CREATE_TRANSLATION _qm_files)
|
|
||||||
set(options)
|
|
||||||
set(oneValueArgs)
|
|
||||||
set(multiValueArgs OPTIONS)
|
|
||||||
|
|
||||||
cmake_parse_arguments(_LUPDATE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
||||||
set(_lupdate_files ${_LUPDATE_UNPARSED_ARGUMENTS})
|
|
||||||
set(_lupdate_options ${_LUPDATE_OPTIONS})
|
|
||||||
|
|
||||||
set(_my_sources)
|
|
||||||
set(_my_tsfiles)
|
|
||||||
foreach(_file ${_lupdate_files})
|
|
||||||
get_filename_component(_ext ${_file} EXT)
|
|
||||||
get_filename_component(_abs_FILE ${_file} ABSOLUTE)
|
|
||||||
if(_ext MATCHES "ts")
|
|
||||||
list(APPEND _my_tsfiles ${_abs_FILE})
|
|
||||||
else()
|
|
||||||
list(APPEND _my_sources ${_abs_FILE})
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
foreach(_ts_file ${_my_tsfiles})
|
|
||||||
if(_my_sources)
|
|
||||||
# make a list file to call lupdate on, so we don't make our commands too
|
|
||||||
# long for some systems
|
|
||||||
# get_filename_component(_ts_name ${_ts_file} NAME_WE)
|
|
||||||
|
|
||||||
get_filename_component(_name ${_ts_file} NAME)
|
|
||||||
string(REGEX REPLACE "^(.+)(\\.[^.]+)$" "\\1" _ts_name ${_name})
|
|
||||||
|
|
||||||
set(_ts_lst_file "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_ts_name}_lst_file")
|
|
||||||
set(_lst_file_srcs)
|
|
||||||
foreach(_lst_file_src ${_my_sources})
|
|
||||||
set(_lst_file_srcs "${_lst_file_src}\n${_lst_file_srcs}")
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
get_directory_property(_inc_DIRS INCLUDE_DIRECTORIES)
|
|
||||||
foreach(_pro_include ${_inc_DIRS})
|
|
||||||
get_filename_component(_abs_include "${_pro_include}" ABSOLUTE)
|
|
||||||
set(_lst_file_srcs "-I${_pro_include}\n${_lst_file_srcs}")
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
file(WRITE ${_ts_lst_file} "${_lst_file_srcs}")
|
|
||||||
endif()
|
|
||||||
add_custom_command(OUTPUT ${_ts_file}
|
|
||||||
COMMAND ${Qt5_LUPDATE_EXECUTABLE}
|
|
||||||
ARGS ${_lupdate_options} "@${_ts_lst_file}" -ts ${_ts_file}
|
|
||||||
DEPENDS ${_my_sources} ${_ts_lst_file} VERBATIM)
|
|
||||||
endforeach()
|
|
||||||
qt5_patched_add_translation(${_qm_files} ${_my_tsfiles})
|
|
||||||
set(${_qm_files} ${${_qm_files}} PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(QT5_PATCHED_ADD_TRANSLATION _qm_files)
|
|
||||||
foreach(_current_FILE ${ARGN})
|
|
||||||
get_filename_component(_abs_FILE ${_current_FILE} ABSOLUTE)
|
|
||||||
# get_filename_component(qm ${_abs_FILE} NAME_WE)
|
|
||||||
|
|
||||||
get_filename_component(_name ${_abs_FILE} NAME)
|
|
||||||
string(REGEX REPLACE "^(.+)(\\.[^.]+)$" "\\1" qm ${_name})
|
|
||||||
|
|
||||||
get_source_file_property(output_location ${_abs_FILE} OUTPUT_LOCATION)
|
|
||||||
if(output_location)
|
|
||||||
file(MAKE_DIRECTORY "${output_location}")
|
|
||||||
set(qm "${output_location}/${qm}.qm")
|
|
||||||
else()
|
|
||||||
set(qm "${CMAKE_CURRENT_BINARY_DIR}/${qm}.qm")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_custom_command(OUTPUT ${qm}
|
|
||||||
COMMAND ${Qt5_LRELEASE_EXECUTABLE}
|
|
||||||
ARGS ${_abs_FILE} -qm ${qm}
|
|
||||||
DEPENDS ${_abs_FILE} VERBATIM
|
|
||||||
)
|
|
||||||
list(APPEND ${_qm_files} ${qm})
|
|
||||||
endforeach()
|
|
||||||
set(${_qm_files} ${${_qm_files}} PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
669
debian/changelog
vendored
Normal file
669
debian/changelog
vendored
Normal file
@ -0,0 +1,669 @@
|
|||||||
|
pcmanfm-qt (2.2.0-0ubuntu3) resolute; urgency=medium
|
||||||
|
|
||||||
|
* Recommend kf6-breeze-icon-theme instead of transitional package.
|
||||||
|
|
||||||
|
-- Rik Mills <rikmills@kde.org> Thu, 18 Dec 2025 13:15:06 +0000
|
||||||
|
|
||||||
|
pcmanfm-qt (2.2.0-0ubuntu2) questing; urgency=medium
|
||||||
|
|
||||||
|
* Bump depends to latest libfm-qt.
|
||||||
|
|
||||||
|
-- Rik Mills <rikmills@kde.org> Wed, 20 Aug 2025 18:33:18 +0100
|
||||||
|
|
||||||
|
pcmanfm-qt (2.2.0-0ubuntu1) questing; urgency=medium
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
- Update build dependencies.
|
||||||
|
- Refresh Lubuntu Manual patch.
|
||||||
|
- Removed unneeded Lintian overrides.
|
||||||
|
* Update copyright file.
|
||||||
|
* Bump Standards-Version to 4.7.2, no changes needed.
|
||||||
|
|
||||||
|
-- Aaron Rainbolt <arraybolt3@ubuntu.com> Wed, 30 Jul 2025 15:14:44 -0500
|
||||||
|
|
||||||
|
pcmanfm-qt (2.1.0-0ubuntu3) plucky; urgency=medium
|
||||||
|
|
||||||
|
* Update Standards-Version to 4.7.1, no changes needed.
|
||||||
|
|
||||||
|
-- Simon Quigley <tsimonq2@ubuntu.com> Fri, 21 Feb 2025 16:35:29 -0600
|
||||||
|
|
||||||
|
pcmanfm-qt (2.1.0-0ubuntu2) plucky; urgency=medium
|
||||||
|
|
||||||
|
* No-change rebuild for lxqt-build-tools C++17 -> C++20.
|
||||||
|
|
||||||
|
-- Simon Quigley <tsimonq2@ubuntu.com> Fri, 03 Jan 2025 04:00:52 -0600
|
||||||
|
|
||||||
|
pcmanfm-qt (2.1.0-0ubuntu1) plucky; urgency=medium
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
- Update build dependencies.
|
||||||
|
|
||||||
|
-- Simon Quigley <tsimonq2@ubuntu.com> Fri, 15 Nov 2024 15:33:33 -0600
|
||||||
|
|
||||||
|
pcmanfm-qt (2.0.0-0ubuntu1) oracular; urgency=medium
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
* Bump Standards-Version to 4.7.0, no changes necessary.
|
||||||
|
* Adjust build dependencies.
|
||||||
|
|
||||||
|
-- Aaron Rainbolt <arraybolt3@ubuntu.com> Thu, 15 Aug 2024 16:27:12 -0500
|
||||||
|
|
||||||
|
pcmanfm-qt (1.4.1-0ubuntu1) noble; urgency=medium
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
* Updated copyright file.
|
||||||
|
|
||||||
|
-- Aaron Rainbolt <arraybolt3@ubuntu.com> Sun, 18 Feb 2024 16:31:24 -0600
|
||||||
|
|
||||||
|
pcmanfm-qt (1.4.0-0ubuntu3) noble; urgency=medium
|
||||||
|
|
||||||
|
* Update the Lubuntu Manual patch to use the dedicated icon.
|
||||||
|
|
||||||
|
-- Simon Quigley <tsimonq2@ubuntu.com> Fri, 01 Dec 2023 14:54:31 -0600
|
||||||
|
|
||||||
|
pcmanfm-qt (1.4.0-0ubuntu2) noble; urgency=medium
|
||||||
|
|
||||||
|
* Bump runtime dependency.
|
||||||
|
|
||||||
|
-- Simon Quigley <tsimonq2@ubuntu.com> Mon, 13 Nov 2023 15:51:03 -0600
|
||||||
|
|
||||||
|
pcmanfm-qt (1.4.0-0ubuntu1) noble; urgency=medium
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
* Bump build dependencies.
|
||||||
|
* Update Lubuntu Manual patch. Needs testing.
|
||||||
|
* Install new SVG file.
|
||||||
|
|
||||||
|
-- Simon Quigley <tsimonq2@ubuntu.com> Sun, 12 Nov 2023 21:27:52 -0600
|
||||||
|
|
||||||
|
pcmanfm-qt (1.3.0-0ubuntu1) mantic; urgency=medium
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
* Bump build dependencies.
|
||||||
|
|
||||||
|
-- Simon Quigley <tsimonq2@ubuntu.com> Fri, 11 Aug 2023 09:52:17 -0500
|
||||||
|
|
||||||
|
pcmanfm-qt (1.2.1-0ubuntu3) lunar; urgency=medium
|
||||||
|
|
||||||
|
* Made the General tab in Desktop Preferences the default tab again.
|
||||||
|
|
||||||
|
-- Aaron Rainbolt <arraybolt3@ubuntu.com> Tue, 07 Mar 2023 12:35:39 -0600
|
||||||
|
|
||||||
|
pcmanfm-qt (1.2.1-0ubuntu2) lunar; urgency=medium
|
||||||
|
|
||||||
|
* Put the Lubuntu Manual checkbox where it belongs in the Desktop
|
||||||
|
Preferences window. (LP: #1998528)
|
||||||
|
* Make the Lubuntu Manual checkbox behave correctly (if the shortcut is
|
||||||
|
present, it should be checked, if the shortcut is missing, it should be
|
||||||
|
unchecked).
|
||||||
|
* Make the context menu of the Lubuntu Manual shortcut on the desktop behave
|
||||||
|
like the other special shortcuts (Home, Trash, Computer, Network).
|
||||||
|
|
||||||
|
-- Aaron Rainbolt <arraybolt3@ubuntu.com> Thu, 02 Mar 2023 17:41:45 -0600
|
||||||
|
|
||||||
|
pcmanfm-qt (1.2.1-0ubuntu1) lunar; urgency=medium
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
* Updated copyright file.
|
||||||
|
* Bumped Standards-Version to 4.6.2, no changes necessary.
|
||||||
|
* Bumped build dependency for libfm-qt.
|
||||||
|
* Removed obsolete '-Wl,--as-needed' linker flag.
|
||||||
|
* Added 'Rules-Requires-Root: no' to debian/control.
|
||||||
|
* Removed trailing whitespace from changelog.
|
||||||
|
|
||||||
|
-- Aaron Rainbolt <arraybolt3@ubuntu.com> Fri, 27 Jan 2023 15:55:12 -0600
|
||||||
|
|
||||||
|
pcmanfm-qt (1.2.0-0ubuntu1) lunar; urgency=medium
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
* Fix the watch file, for real this time.
|
||||||
|
* Lubuntuify the package slightly, to make debhelper happy.
|
||||||
|
* Bump Standards-version to 4.6.1, no changes needed.
|
||||||
|
* Bump build dependencies in debian/control.
|
||||||
|
* Remove reverse-applicable upstream patches.
|
||||||
|
* Brief copyright update.
|
||||||
|
|
||||||
|
-- Simon Quigley <tsimonq2@ubuntu.com> Fri, 18 Nov 2022 18:55:38 -0600
|
||||||
|
|
||||||
|
pcmanfm-qt (1.1.0-0ubuntu4) kinetic; urgency=medium
|
||||||
|
|
||||||
|
* Backport some upstream patches:
|
||||||
|
- Prevent an empty desktop path.
|
||||||
|
+ https://github.com/lxqt/pcmanfm-qt/pull/1601
|
||||||
|
+ https://github.com/lxqt/pcmanfm-qt/commit/f1438b
|
||||||
|
- Allow customizing workspace margins on desktop.
|
||||||
|
+ https://github.com/lxqt/pcmanfm-qt/pull/1606
|
||||||
|
+ https://github.com/lxqt/pcmanfm-qt/commit/1151f4
|
||||||
|
|
||||||
|
-- Simon Quigley <tsimonq2@ubuntu.com> Wed, 22 Jun 2022 00:03:18 -0500
|
||||||
|
|
||||||
|
pcmanfm-qt (1.1.0-0ubuntu3) kinetic; urgency=medium
|
||||||
|
|
||||||
|
* Create a new patch from thin air (woah, shiny!) which adds the Lubuntu
|
||||||
|
Manual as an optional desktop shortcut. Spread the good work Lyn has been
|
||||||
|
doing for a few years now. :)
|
||||||
|
|
||||||
|
-- Simon Quigley <tsimonq2@ubuntu.com> Thu, 16 Jun 2022 23:06:52 -0400
|
||||||
|
|
||||||
|
pcmanfm-qt (1.1.0-0ubuntu2) kinetic; urgency=medium
|
||||||
|
|
||||||
|
* Cherry-pick upstream commit fixing some scaling oddities:
|
||||||
|
- https://github.com/lxqt/pcmanfm-qt/commit/c84434
|
||||||
|
- https://github.com/lxqt/pcmanfm-qt/issues/1595
|
||||||
|
|
||||||
|
-- Simon Quigley <tsimonq2@ubuntu.com> Wed, 08 Jun 2022 19:05:41 -0500
|
||||||
|
|
||||||
|
pcmanfm-qt (1.1.0-0ubuntu1) kinetic; urgency=medium
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
* Update build dependencies and remove some old Breaks/Replaces.
|
||||||
|
|
||||||
|
-- Simon Quigley <tsimonq2@ubuntu.com> Thu, 02 Jun 2022 09:35:43 -0500
|
||||||
|
|
||||||
|
pcmanfm-qt (0.17.0-0ubuntu1) impish; urgency=medium
|
||||||
|
|
||||||
|
* New upstream release 0.17.0
|
||||||
|
* Update debian/control
|
||||||
|
- Use libfm-qt 0.17.1
|
||||||
|
- Use lxqt-build-tools 0.9.0
|
||||||
|
- Bump Standards-Version to 4.5.1
|
||||||
|
- Readd ${misc:Depends} and ${shlibs:Depends}
|
||||||
|
- Extend description of pcmanfm-qt-l10n
|
||||||
|
* Update debian/copyright
|
||||||
|
|
||||||
|
-- apt-ghetto <apt-ghetto@protonmail.com> Tue, 10 Aug 2021 15:28:47 +0200
|
||||||
|
|
||||||
|
pcmanfm-qt (0.16.0-1ubuntu2) hirsute; urgency=low
|
||||||
|
|
||||||
|
[ Raman Sarda ]
|
||||||
|
* New upstream version.
|
||||||
|
* Bump debhelper-compat requirement to 13.
|
||||||
|
* Drop empty series file.
|
||||||
|
* Update dependencies.
|
||||||
|
|
||||||
|
-- Raman Sarda <theloudspeaker@disroot.org> Mon, 22 Feb 2021 01:37:46 +0530
|
||||||
|
|
||||||
|
pcmanfm-qt (0.16.0-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
[ Alf Gaida ]
|
||||||
|
* Switched to gbp
|
||||||
|
* Bumped Standards-Version to 4.4.0, no changes needed
|
||||||
|
|
||||||
|
[ Debian Janitor ]
|
||||||
|
* Fix field name typo in debian/upstream/metadata (Repository-Browser =>
|
||||||
|
Repository-Browse).
|
||||||
|
* Set upstream metadata fields: Repository.
|
||||||
|
* Remove obsolete field Name from debian/upstream/metadata (already present in
|
||||||
|
machine-readable debian/copyright).
|
||||||
|
* Update standards version to 4.5.0, no changes needed.
|
||||||
|
|
||||||
|
[ Andrew Lee (李健秋) ]
|
||||||
|
* New upstream release. (Closes: #978174)
|
||||||
|
|
||||||
|
-- Andrew Lee (李健秋) <ajqlee@debian.org> Thu, 07 Jan 2021 17:33:42 +0800
|
||||||
|
|
||||||
|
pcmanfm-qt (0.15.0-0ubuntu1) groovy; urgency=medium
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
- Update upstream signing key.
|
||||||
|
- Update LXQt build dependencies.
|
||||||
|
- libfm-qt6 -> libfm-qt7 due to SONAME bump.
|
||||||
|
* Update Standards-version to 4.5.0, no changes needed.
|
||||||
|
* Migrate to debhelper-compat.
|
||||||
|
|
||||||
|
-- Simon Quigley <tsimonq2@ubuntu.com> Thu, 04 Jun 2020 14:18:48 -0500
|
||||||
|
|
||||||
|
pcmanfm-qt (0.14.1-3) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Enhanched the fix and included pcmanfm/settings.cpp - the fallback
|
||||||
|
settings.
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Sun, 12 May 2019 01:41:32 +0200
|
||||||
|
|
||||||
|
pcmanfm-qt (0.14.1-2) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Starting pcmanfm-qt as root session need a running dbus user-session
|
||||||
|
Bug was: pcmanfm-qt does not start as root on Debian live (Closes: #928818)
|
||||||
|
Thanks adrian15 <adrian15sgd@gmail.com> for spotting this.
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Sat, 11 May 2019 20:38:43 +0200
|
||||||
|
|
||||||
|
pcmanfm-qt (0.14.1-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Cherry-picking upstream release 0.14.1.
|
||||||
|
* Bumped minimum version libfm-qt-dev (>= 0.14.1~)
|
||||||
|
* Depend now on libfm-qt6 (>= 0.14.1~)
|
||||||
|
* Improved the description of the language package
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Sun, 24 Feb 2019 23:23:24 +0100
|
||||||
|
|
||||||
|
pcmanfm-qt (0.14.1-0ubuntu3) eoan; urgency=medium
|
||||||
|
|
||||||
|
* Drop patch change-thumbnail-view-icon.patch
|
||||||
|
|
||||||
|
-- apt-ghetto <apt-ghetto@lubuntu.me> Sun, 29 Sep 2019 11:19:46 +0200
|
||||||
|
|
||||||
|
pcmanfm-qt (0.14.1-0ubuntu2) eoan; urgency=medium
|
||||||
|
|
||||||
|
* Changed thumbnail view icon to view-preview
|
||||||
|
|
||||||
|
-- Hans P Möller <hmollercl@lubuntu.me> Sat, 07 Sep 2019 12:34:58 -0400
|
||||||
|
|
||||||
|
pcmanfm-qt (0.14.1-0ubuntu1) disco; urgency=medium
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
* Run wrap-and-sort.
|
||||||
|
|
||||||
|
-- Simon Quigley <tsimonq2@ubuntu.com> Sat, 09 Mar 2019 13:23:17 -0600
|
||||||
|
|
||||||
|
pcmanfm-qt (0.14.0-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Cherry-picking upstream release 0.14.0.
|
||||||
|
* Bumped Standards to 4.3.0, no changes needed
|
||||||
|
* Dropped d/compat, use debhelper-compat = 12, no changes needed
|
||||||
|
* Fixed years in d/copyright
|
||||||
|
* Bumped minimum version libfm-qt-dev (>= 0.14.0~)
|
||||||
|
* Bumped minimum version lxqt-build-tools (>= 0.6.0~)
|
||||||
|
* Depend now on libfm-qt6 (>= 0.14.0~)
|
||||||
|
* Removed obsolete PULL_TRANSLATIONS= OFF from dh_auto_configure
|
||||||
|
* Added Build-Depends-Package field to symbols
|
||||||
|
* Added l10n-package, moved from lxqt-l10n
|
||||||
|
* Added d/upstream/metadata
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Sun, 27 Jan 2019 19:40:51 +0100
|
||||||
|
|
||||||
|
pcmanfm-qt (0.14.0-0ubuntu2) disco; urgency=medium
|
||||||
|
|
||||||
|
* Depend on the newer libfm-qt6 package.
|
||||||
|
|
||||||
|
-- Simon Quigley <tsimonq2@ubuntu.com> Sat, 26 Jan 2019 10:21:10 -0600
|
||||||
|
|
||||||
|
pcmanfm-qt (0.14.0-0ubuntu1) disco; urgency=medium
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
- Bump build dependencies.
|
||||||
|
- Remove reverse-applicable patches.
|
||||||
|
* Bump Standards-version to 4.3.0, no changes needed.
|
||||||
|
* Bump debhelper compat to 12, no changes needed.
|
||||||
|
* Add a new pcmanfm-qt-l10n package.
|
||||||
|
|
||||||
|
-- Simon Quigley <tsimonq2@ubuntu.com> Sat, 26 Jan 2019 01:01:30 -0600
|
||||||
|
|
||||||
|
pcmanfm-qt (0.13.0-2ubuntu2) cosmic; urgency=medium
|
||||||
|
|
||||||
|
* No-change rebuild for changes in libfm-qt.
|
||||||
|
|
||||||
|
-- Simon Quigley <tsimonq2@ubuntu.com> Wed, 10 Oct 2018 21:00:58 -0500
|
||||||
|
|
||||||
|
pcmanfm-qt (0.13.0-2ubuntu1) cosmic; urgency=medium
|
||||||
|
|
||||||
|
* Update Vcs-* and Maintainer for maintaining in Lubuntu.
|
||||||
|
* Polish the drag and drop experience by backporting some upstream commits.
|
||||||
|
|
||||||
|
-- Simon Quigley <tsimonq2@ubuntu.com> Sat, 14 Jul 2018 18:24:46 -0500
|
||||||
|
|
||||||
|
pcmanfm-qt (0.13.0-2) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Switch to unstable
|
||||||
|
* Bumped build dependency libfm-qt-dev to >= 0.13.1~
|
||||||
|
* Bumped Standards to 4.1.5, no changes needed
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Sat, 07 Jul 2018 14:37:15 +0200
|
||||||
|
|
||||||
|
pcmanfm-qt (0.13.0-1) experimental; urgency=medium
|
||||||
|
|
||||||
|
* Cherry-picking upstream release 0.13.0.
|
||||||
|
* Bumped build dependency libfm-qt-dev to >= 0.13.0~
|
||||||
|
* Bumped build dependency lxqt-build-tools to >= 0.5.0~
|
||||||
|
* Added papirus-icon-theme as default alternative for icon-themes
|
||||||
|
* Bumped year in copyright
|
||||||
|
* Removed ported back upstream patches.
|
||||||
|
* Moved debian/.gitignore -> ./.gitignore
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Sat, 26 May 2018 02:25:19 +0200
|
||||||
|
|
||||||
|
pcmanfm-qt (0.12.0-6) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Bumped compat to 11
|
||||||
|
* Bumped debhelper to >= 11~
|
||||||
|
* Bumped Standards to 4.1.4, no changes needed
|
||||||
|
* Fixed a glitch in VCS fields
|
||||||
|
* Changed Homepage, Source and watch to lxqt
|
||||||
|
* Bumped year in copyright
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Sat, 28 Apr 2018 18:43:40 +0200
|
||||||
|
|
||||||
|
pcmanfm-qt (0.12.0-5) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Moved git to salsa, changed the VCS fields that way
|
||||||
|
* Bumped Standards to 4.1.3, no changes needed
|
||||||
|
* Added gfvs-fuse to recommends, thanks robert <maxl1234@gmx.at>
|
||||||
|
(Closes: #886166)
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Fri, 05 Jan 2018 19:12:49 +0100
|
||||||
|
|
||||||
|
pcmanfm-qt (0.12.0-4) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Really bumped Standards.
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Sat, 16 Dec 2017 03:48:34 +0100
|
||||||
|
|
||||||
|
pcmanfm-qt (0.12.0-3) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Bumped Standards to 4.1.2, no changes needed
|
||||||
|
* Move config to /usr/share/pcmanfm-qt/lxqt
|
||||||
|
* Removed branch from VCS fields
|
||||||
|
* Removed debian/gbp.conf
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Fri, 15 Dec 2017 00:49:17 +0100
|
||||||
|
|
||||||
|
pcmanfm-qt (0.12.0-2) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Transition to unstable
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Tue, 05 Dec 2017 01:51:44 +0100
|
||||||
|
|
||||||
|
pcmanfm-qt (0.12.0-1) experimental; urgency=medium
|
||||||
|
|
||||||
|
* Cherry-picking upstream release 0.12.0.
|
||||||
|
* Bumped Standards to 4.1.1
|
||||||
|
* Bumped build-tools >= 0.4.0
|
||||||
|
* Bumped libfm-qt-dev >= 0.12.0
|
||||||
|
* Bumped years in copyright
|
||||||
|
* Added build dependency libexif-dev
|
||||||
|
* Added Breaks and Replaces for lxqt-common << 0.12.0
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Tue, 24 Oct 2017 21:53:39 +0200
|
||||||
|
|
||||||
|
pcmanfm-qt (0.11.3-4) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Depend on desktop-file-utils (Closes: #866900)
|
||||||
|
* Recommend ffmpegthumbnailer (Closes: #867460)
|
||||||
|
* Removed the alternative dependency gksu. Reason: #867236
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Thu, 06 Jul 2017 19:58:03 +0200
|
||||||
|
|
||||||
|
pcmanfm-qt (0.11.3-3) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Bumped Standards to 4.0.0
|
||||||
|
* Depend on lxqt-sudo | gksu we need at least one UI for sudo
|
||||||
|
* Added Recommends: lximage-qt, lxqt-policykit, lxqt-qtplugin
|
||||||
|
(Closes: #866347)
|
||||||
|
* pcmanfm-qt allow multiple file selections with mouse, the implementation is
|
||||||
|
horrible in some places, but it works. (Closes: #853201)
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Sun, 02 Jul 2017 18:05:08 +0200
|
||||||
|
|
||||||
|
pcmanfm-qt (0.11.3-2) unstable; urgency=medium
|
||||||
|
|
||||||
|
* set oxygen-icon-theme as default alternative recommendation
|
||||||
|
(Closes: #851411)
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Sun, 15 Jan 2017 01:35:46 +0100
|
||||||
|
|
||||||
|
pcmanfm-qt (0.11.3-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Cherry-picking upstream release 0.11.3.
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Sat, 14 Jan 2017 03:54:54 +0100
|
||||||
|
|
||||||
|
pcmanfm-qt (0.11.2-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Cherry-picking upstream release 0.11.2.
|
||||||
|
* Removed build dependencies:
|
||||||
|
- libfm-dev
|
||||||
|
- liblxqt0-dev
|
||||||
|
* Bumped minimum versions
|
||||||
|
- libfm-qt-dev (>= 0.11.2)
|
||||||
|
- lxqt-build-tools (>= 0.3.0)
|
||||||
|
- libfm-qt3 (>= 0.11.2)
|
||||||
|
* Suggests: cdtool -> cdtool [linux-any]
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Thu, 22 Dec 2016 02:02:37 +0100
|
||||||
|
|
||||||
|
pcmanfm-qt (0.11.1-3) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Added versioned dependency libfm-qt3 (>= 0.11.1), dh detect only
|
||||||
|
a minimum version of 0.11.0 - false because some symbols are added
|
||||||
|
which are needed for pcmanfm-qt (>= 0.11.1) (Closes: #842080)
|
||||||
|
* Removed build dependencies
|
||||||
|
- libqt5xdg-dev
|
||||||
|
- pkg-config,
|
||||||
|
- qttools5-dev,
|
||||||
|
- qttools5-dev-tools
|
||||||
|
* Added build dependency lxqt-build-tools
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Sat, 05 Nov 2016 02:06:06 +0100
|
||||||
|
|
||||||
|
pcmanfm-qt (0.11.1-2) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Cherry-picking upstream release 0.11.1.
|
||||||
|
* Synced debian foo with experimental
|
||||||
|
* Removed --parallel from rules, standard compat 10
|
||||||
|
* New dep. default-dbus-session-bus | dbus-session-bus | dbus-x11
|
||||||
|
(Closes: #836284)
|
||||||
|
* Fixed Crashes while copying (Closes: #823753)
|
||||||
|
* Bumped minimum version libfm-qt-dev (>= 0.11.1)
|
||||||
|
* Bumped minimum version libqt5xdg-dev (>= 2.0.0)
|
||||||
|
* Added build dependency libkf5windowsystem-dev
|
||||||
|
* Added build dependency libqt5svg5-dev
|
||||||
|
* Added build dependency liblxqt0-dev (>= 0.11.0)
|
||||||
|
* Added Recommends pcmanfm-qt-l10n
|
||||||
|
* Fixed VCS fields, using plain /git/
|
||||||
|
* Fixed copyright Format field, using https
|
||||||
|
* Dropped patches, applied upstream
|
||||||
|
* Added translation controls
|
||||||
|
* Set CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Tue, 18 Oct 2016 22:59:30 +0200
|
||||||
|
|
||||||
|
pcmanfm-qt (0.11.0-10) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Fixed typo in Recommends: oyxgen-icon-theme -> oxygen-icon-theme
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Mon, 19 Sep 2016 21:50:10 +0200
|
||||||
|
|
||||||
|
pcmanfm-qt (0.11.0-9) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Bumped compat to 10
|
||||||
|
* Bumped build dependency debhelper (>=10)
|
||||||
|
* Fixed typo in Recommends: faenza--icon-theme > faenza-icon-theme
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Mon, 19 Sep 2016 04:23:26 +0200
|
||||||
|
|
||||||
|
pcmanfm-qt (0.11.0-8) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Replace dep. dbus-x11 with default-dbus-session-bus | dbus-session-bus
|
||||||
|
(Closes: #836284)
|
||||||
|
* Set CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Thu, 01 Sep 2016 22:56:35 +0200
|
||||||
|
|
||||||
|
pcmanfm-qt (0.11.0-7) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Fixed VCS fields, use plain /git/
|
||||||
|
* Reworked icon-theme recommends (Closes: #833590)
|
||||||
|
Thanks Pino Toscano <pino@debian.org>
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Sun, 07 Aug 2016 11:14:08 +0200
|
||||||
|
|
||||||
|
pcmanfm-qt (0.11.0-6) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Set LC_ALL for reproducible builds.
|
||||||
|
|
||||||
|
-- ChangZhuo Chen (陳昌倬) <czchen@debian.org> Sat, 16 Jul 2016 11:16:41 +0800
|
||||||
|
|
||||||
|
pcmanfm-qt (0.11.0-5) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Backported temporary upstream fix for #826311
|
||||||
|
(https://github.com/lxde/pcmanfm-qt/pull/359)
|
||||||
|
* Bumped standards version to 3.9.8 - no changes needed
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Sat, 04 Jun 2016 19:39:22 +0200
|
||||||
|
|
||||||
|
pcmanfm-qt (0.11.0-4) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Added oxygen-icon-theme | oxygen5-icon-theme | gnome-icon-theme
|
||||||
|
to recommends. (Closes: #826311)
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Sat, 04 Jun 2016 15:54:21 +0200
|
||||||
|
|
||||||
|
pcmanfm-qt (0.11.0-3) unstable; urgency=low
|
||||||
|
|
||||||
|
* Adding "Depends: dbus-x11". Closes: #820079
|
||||||
|
|
||||||
|
-- Yuan CHAO <yuanchao@gmail.com> Tue, 19 Apr 2016 20:30:00 +0800
|
||||||
|
|
||||||
|
pcmanfm-qt (0.11.0-2) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Merge experimental to unstable
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Thu, 31 Mar 2016 22:07:11 +0200
|
||||||
|
|
||||||
|
pcmanfm-qt (0.11.0-1) experimental; urgency=medium
|
||||||
|
|
||||||
|
* New upstream release
|
||||||
|
* Removed grep patch
|
||||||
|
* Bump libfm-qt-dev (>= 0.11.0)
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Mon, 28 Mar 2016 18:12:27 +0200
|
||||||
|
|
||||||
|
pcmanfm-qt (0.10.1-2) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Bump Standards to 3.9.7
|
||||||
|
* Fix years in copyright
|
||||||
|
* Add hardending=+all
|
||||||
|
* simplify rules
|
||||||
|
* make pcmanfm-qt reproducible again, thanks to Eduard Sanou for the
|
||||||
|
bugreport and the patch, but it was fixed before (Closes: #815818)
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Fri, 26 Feb 2016 00:16:22 +0100
|
||||||
|
|
||||||
|
pcmanfm-qt (0.10.1-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
* Remove libfm-qt as upstream moved it into another source repository.
|
||||||
|
* Remove dbg package in favor of dbgsym.
|
||||||
|
* Update Vcs-Browser.
|
||||||
|
|
||||||
|
-- ChangZhuo Chen (陳昌倬) <czchen@debian.org> Sun, 07 Feb 2016 16:13:27 +0800
|
||||||
|
|
||||||
|
pcmanfm-qt (0.10.0-2) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Merge from experimental.
|
||||||
|
* New upstream release.
|
||||||
|
* Update minimum version of liblxqt.
|
||||||
|
* Update symbols.
|
||||||
|
* Remove menu file, see CTTE #741573.
|
||||||
|
|
||||||
|
-- ChangZhuo Chen (陳昌倬) <czchen@debian.org> Sun, 15 Nov 2015 21:14:41 +0800
|
||||||
|
|
||||||
|
pcmanfm-qt (0.9.0+20150908-2) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Menufile deleted
|
||||||
|
* debian/rules --fail-missing included --list-missig, so
|
||||||
|
--list-missing deleted
|
||||||
|
|
||||||
|
-- Alf Gaida <agaida@siduction.org> Fri, 13 Nov 2015 02:37:53 +0100
|
||||||
|
|
||||||
|
pcmanfm-qt (0.9.0+20150908-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
[ Alf Gaida ]
|
||||||
|
* Cherry-picked upstream version 0.9.0+20150908.
|
||||||
|
* Tar-ignore .gitignore
|
||||||
|
* Fixed control with cme fix
|
||||||
|
* Added upstream signing-key and use it in watch file
|
||||||
|
* Removed automoc build dependency - not needed with Qt5
|
||||||
|
* Fixed symbols for i386 and amd64
|
||||||
|
|
||||||
|
[ ChangZhuo Chen (陳昌倬) ]
|
||||||
|
* Use arch-bits to fix 32 bit architecture symbols.
|
||||||
|
* Add Shih-Yuan Lee (FourDollars) as Uploaders.
|
||||||
|
|
||||||
|
-- ChangZhuo Chen (陳昌倬) <czchen@debian.org> Tue, 15 Sep 2015 23:30:13 +0800
|
||||||
|
|
||||||
|
pcmanfm-qt (0.9.0+20150816-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
[ ChangZhuo Chen (陳昌倬) ]
|
||||||
|
* Import debian directory from Wen.Liao.
|
||||||
|
* Initial release (Closes: #747605)
|
||||||
|
* Merge debian directory.
|
||||||
|
* Backup *.ts.
|
||||||
|
* Fix package-contains-empty-directory.
|
||||||
|
* Don't use variable for command.
|
||||||
|
* Add libfm-qt1 and libfm-qt-dev.
|
||||||
|
* Update copyright.
|
||||||
|
* Add Pre-Depends: ${misc:Pre-Depends} to libfm-qt1.
|
||||||
|
* Create manpage for pcmanfm-qt.
|
||||||
|
* add libfm-qt1.symbols.
|
||||||
|
* Revert "Create manpage for pcmanfm-qt".
|
||||||
|
* Add pcmanfm-qt.manpages.
|
||||||
|
* Fix manpage.
|
||||||
|
* Install include to libfm-qt-dev.
|
||||||
|
* Update package description.
|
||||||
|
* Use patch to install manpage.
|
||||||
|
* Migrate to QT5.
|
||||||
|
* Update d/copyright.
|
||||||
|
* Fix copyright typo.
|
||||||
|
* Revert accidiently ts changed.
|
||||||
|
|
||||||
|
[ Alf Gaida ]
|
||||||
|
* gitignore added.
|
||||||
|
* new upstream translation files.
|
||||||
|
* some cleanup in debian rules.
|
||||||
|
* two missed symbols added.
|
||||||
|
* they need a little bit of beautyfing.
|
||||||
|
* we should not save translations in debian/bak. if there is a real
|
||||||
|
problem with the translations this should be fixed upstream.
|
||||||
|
* add two symbols @czchen - would you be so kind and clean them up.
|
||||||
|
* catch up with upstream Patch descriptions changed.
|
||||||
|
* Imported Upstream version 0.8.0
|
||||||
|
* Min Qt version 5.3.2.
|
||||||
|
* bump standards to 3.9.6.
|
||||||
|
* removed all patches, integrated in upstream.
|
||||||
|
* fix symbols (two symbols added).
|
||||||
|
* fix prefs desktop file.
|
||||||
|
* fix arch for dbg packages.
|
||||||
|
* Imported Upstream version 0.8.0.
|
||||||
|
* Min Qt version 5.3.2.
|
||||||
|
* bump standards to 3.9.6.
|
||||||
|
* removed all patches, integrated in upstream.
|
||||||
|
* fix symbols (two symbols added).
|
||||||
|
* fix prefs desktop file.
|
||||||
|
* fix arch for dbg packages.
|
||||||
|
* patch added released.
|
||||||
|
* fixing arch dependent symbols.
|
||||||
|
* recommend gfvs-backends.
|
||||||
|
* Some cleanup in debian $foo.
|
||||||
|
* some changes in debian $foo.
|
||||||
|
* drop transitional packages.
|
||||||
|
|
||||||
|
[ ChangZhuo Chen (陳昌倬) ]
|
||||||
|
* Unapply Debian patch.
|
||||||
|
* Add debian/source/local-options.
|
||||||
|
* Backup / Restore translations.
|
||||||
|
* Fix override_dh_clean.
|
||||||
|
* Use override_dh_auto_clean to restore translations.
|
||||||
|
* Update symbol control file.
|
||||||
|
* Quote in symbol control file.
|
||||||
|
* Restore upstream file.
|
||||||
|
* Imported Upstream version 0.9.0+20150816.
|
||||||
|
* Add (c++) to symbol control file.
|
||||||
|
* Update changelog.
|
||||||
|
* Update symbol control file.
|
||||||
|
* Fix symbol control file.
|
||||||
|
* Fix Architecture.
|
||||||
|
* Add Multi-Arch: same.
|
||||||
|
|
||||||
|
[ Shih-Yuan Lee (FourDollars) ]
|
||||||
|
* Polish debian/control by 'cme fix dpkg-control'.
|
||||||
|
* Update package description.
|
||||||
|
|
||||||
|
[ Andrew Lee (李健秋) ]
|
||||||
|
* Added myself as Uploader.
|
||||||
|
* Removing whitespaces at EOL and EOF.
|
||||||
|
* Refine descriptions.
|
||||||
|
* Don't need to backup/restore translation files, this fixed upstream.
|
||||||
|
* Warpped lines in copyright.
|
||||||
|
|
||||||
|
-- Andrew Lee (李健秋) <ajqlee@debian.org> Mon, 17 Aug 2015 21:04:54 +0800
|
||||||
89
debian/control
vendored
Normal file
89
debian/control
vendored
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
Source: pcmanfm-qt
|
||||||
|
Maintainer: Lubuntu Developers <lubuntu-devel@lists.ubuntu.com>
|
||||||
|
Original-Maintainer: LXQt Packaging Team <pkg-lxqt-devel@lists.alioth.debian.org>
|
||||||
|
Uploaders: Alf Gaida <agaida@siduction.org>,
|
||||||
|
ChangZhuo Chen (陳昌倬) <czchen@debian.org>,
|
||||||
|
Andrew Lee (李健秋) <ajqlee@debian.org>,
|
||||||
|
Shih-Yuan Lee (FourDollars) <fourdollars@gmail.com>,
|
||||||
|
Yuan CHAO <yuanchao@gmail.com>
|
||||||
|
Section: x11
|
||||||
|
Priority: optional
|
||||||
|
Build-Depends: debhelper-compat (= 13),
|
||||||
|
layer-shell-qt,
|
||||||
|
libexif-dev,
|
||||||
|
libfm-qt6-dev (>= 2.2.0),
|
||||||
|
libkf6windowsystem-dev,
|
||||||
|
liblayershellqtinterface-dev (>= 6.0.0),
|
||||||
|
libmenu-cache-dev,
|
||||||
|
libx11-dev,
|
||||||
|
libxcb-composite0-dev,
|
||||||
|
libxcb-cursor-dev,
|
||||||
|
libxcb-damage0-dev,
|
||||||
|
libxcb-dpms0-dev,
|
||||||
|
libxcb-dri2-0-dev,
|
||||||
|
libxcb-dri3-dev,
|
||||||
|
libxcb-ewmh-dev,
|
||||||
|
libxcb-glx0-dev,
|
||||||
|
libxcb-icccm4-dev,
|
||||||
|
libxcb-keysyms1-dev,
|
||||||
|
libxcb-present-dev,
|
||||||
|
libxcb-record0-dev,
|
||||||
|
libxcb-render0-dev,
|
||||||
|
libxcb-res0-dev,
|
||||||
|
libxcb-screensaver0-dev,
|
||||||
|
libxcb-shape0-dev,
|
||||||
|
libxcb-shm0-dev,
|
||||||
|
libxcb-util-dev,
|
||||||
|
libxcb-xf86dri0-dev,
|
||||||
|
libxcb-xfixes0-dev,
|
||||||
|
libxcb-xinerama0-dev,
|
||||||
|
libxcb-xinput-dev,
|
||||||
|
libxcb-xkb-dev,
|
||||||
|
libxcb-xtest0-dev,
|
||||||
|
libxcb-xv0-dev,
|
||||||
|
libxcb-xvmc0-dev,
|
||||||
|
libxkbcommon-dev (>= 0.5.0),
|
||||||
|
lxqt-build-tools (>= 2.2.0),
|
||||||
|
qt6-svg-dev (>= 6.6.0),
|
||||||
|
qt6-wayland-dev (>= 6.6.0)
|
||||||
|
Standards-Version: 4.7.2
|
||||||
|
Vcs-Browser: https://git.lubuntu.me/Lubuntu/pcmanfm-qt-packaging
|
||||||
|
Vcs-Git: https://git.lubuntu.me/Lubuntu/pcmanfm-qt-packaging.git
|
||||||
|
Debian-Vcs-Browser: https://salsa.debian.org/lxqt-team/pcmanfm-qt
|
||||||
|
Debian-Vcs-Git: https://salsa.debian.org/lxqt-team/pcmanfm-qt.git
|
||||||
|
Homepage: https://github.com/lxqt/pcmanfm-qt
|
||||||
|
Rules-Requires-Root: no
|
||||||
|
|
||||||
|
Package: pcmanfm-qt
|
||||||
|
Architecture: any
|
||||||
|
Depends: default-dbus-session-bus | dbus-session-bus | dbus-x11,
|
||||||
|
desktop-file-utils,
|
||||||
|
libfm-qt6-16,
|
||||||
|
lxqt-sudo,
|
||||||
|
${misc:Depends},
|
||||||
|
${shlibs:Depends}
|
||||||
|
Recommends: eject,
|
||||||
|
ffmpegthumbnailer,
|
||||||
|
gvfs-backends,
|
||||||
|
gvfs-fuse,
|
||||||
|
lximage-qt,
|
||||||
|
lxqt-policykit,
|
||||||
|
lxqt-qtplugin,
|
||||||
|
papirus-icon-theme | kf6-breeze-icon-theme | faenza-icon-theme | oxygen-icon-theme,
|
||||||
|
pcmanfm-qt-l10n
|
||||||
|
Suggests: cdtool [linux-any]
|
||||||
|
Description: extremely fast and lightweight file and desktop icon manager
|
||||||
|
PCManFM-Qt is the Qt port of the LXDE file manager PCManFM.
|
||||||
|
.
|
||||||
|
Libfm-Qt is a companion library providing components to build desktop file
|
||||||
|
managers.
|
||||||
|
|
||||||
|
Package: pcmanfm-qt-l10n
|
||||||
|
Architecture: all
|
||||||
|
Multi-Arch: foreign
|
||||||
|
Section: localization
|
||||||
|
Depends: qt6-translations-l10n, ${misc:Depends}
|
||||||
|
Description: Language package for pcmanfm-qt
|
||||||
|
PCManFM-Qt is the Qt port of the LXDE file manager PCManFM.
|
||||||
|
.
|
||||||
|
This package contains the l10n files needed by pcmanfm-qt.
|
||||||
39
debian/copyright
vendored
Normal file
39
debian/copyright
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: pcmanfm-qt
|
||||||
|
Source: https://github.com/lxqt/pcmanfm-qt
|
||||||
|
|
||||||
|
Files: *
|
||||||
|
Copyright: 2017, Pedram Pourang (Tsu Jan) <tsujan2000@gmail.com>
|
||||||
|
2013-2025 LXQt team
|
||||||
|
2009-2018 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
||||||
|
2012-2013 Andriy Grytsenko (LStranger) <andrej@rep.kiev.ua>
|
||||||
|
2014 Kuzma Shapran <kuzma.shapran@gmail.com>
|
||||||
|
License: GPL-2.0+
|
||||||
|
|
||||||
|
Files: icons/lubuntu-manual.svg
|
||||||
|
Copyright: 2010-2018 Rafael Laguna <rafaellaguna@gmail.com>
|
||||||
|
License: GPL-2.0+
|
||||||
|
|
||||||
|
Files: debian/*
|
||||||
|
Copyright: 2021-2025 Lubuntu Developers <lubuntu-devel@lists.ubuntu.com>
|
||||||
|
2014-2015 Wen Liao <wen.cf83@gmail.com>
|
||||||
|
2014-2016 ChangZhuo Chen (陳昌倬) <czchen@debian.org>
|
||||||
|
2013-2018 Alf Gaida <agaida@siduction.org>
|
||||||
|
2015 Andrew Lee (李健秋) <ajqlee@debian.org>
|
||||||
|
2025 Aaron Rainbolt <arraybolt3@ubuntu.com>
|
||||||
|
License: GPL-2.0+
|
||||||
|
|
||||||
|
License: GPL-2.0+
|
||||||
|
This package is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
.
|
||||||
|
This package 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 General Public License for more details.
|
||||||
|
.
|
||||||
|
On Debian systems, the complete text of the GNU General
|
||||||
|
Public License version 2 can be found in
|
||||||
|
"/usr/share/common-licenses/GPL-2".
|
||||||
2
debian/docs
vendored
Normal file
2
debian/docs
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
AUTHORS
|
||||||
|
README.md
|
||||||
6
debian/gbp.conf
vendored
Normal file
6
debian/gbp.conf
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[DEFAULT]
|
||||||
|
debian-branch = debian/sid
|
||||||
|
upstream-branch = upstream/latest
|
||||||
|
pristine-tar = True
|
||||||
|
compression = xz
|
||||||
|
|
||||||
801
debian/patches/add-manual.patch
vendored
Normal file
801
debian/patches/add-manual.patch
vendored
Normal file
@ -0,0 +1,801 @@
|
|||||||
|
Description: Add a desktop shortcut for the Lubuntu Manual
|
||||||
|
Forwarded: eventually
|
||||||
|
Author: Simon Quigley <tsimonq2@lubuntu.me>
|
||||||
|
Last-Update: 2023-12-01
|
||||||
|
---
|
||||||
|
--- a/pcmanfm/desktoppreferencesdialog.cpp
|
||||||
|
+++ b/pcmanfm/desktoppreferencesdialog.cpp
|
||||||
|
@@ -124,6 +124,7 @@ DesktopPreferencesDialog::DesktopPrefere
|
||||||
|
ui.trashBox->setChecked(ds.contains(QLatin1String("Trash")));
|
||||||
|
ui.computerBox->setChecked(ds.contains(QLatin1String("Computer")));
|
||||||
|
ui.networkBox->setChecked(ds.contains(QLatin1String("Network")));
|
||||||
|
+ ui.lubuntuManualBox->setChecked(ds.contains(QLatin1String("Lubuntu Manual")));
|
||||||
|
|
||||||
|
// set fallback icon here (cannot be done in .ui)
|
||||||
|
ui.networkBox->setIcon(QIcon::fromTheme(QStringLiteral("network"), QIcon::fromTheme(QStringLiteral("folder-network"))));
|
||||||
|
@@ -215,6 +216,9 @@ void DesktopPreferencesDialog::applySett
|
||||||
|
if(ui.networkBox->isChecked()) {
|
||||||
|
ds << QLatin1String("Network");
|
||||||
|
}
|
||||||
|
+ if(ui.lubuntuManualBox->isChecked()) {
|
||||||
|
+ ds << QLatin1String("Lubuntu Manual");
|
||||||
|
+ }
|
||||||
|
settings.setDesktopShortcuts(ds);
|
||||||
|
|
||||||
|
settings.setDesktopCellMargins(QSize(ui.hMargin->value(), ui.vMargin->value()));
|
||||||
|
--- a/pcmanfm/desktopwindow.cpp
|
||||||
|
+++ b/pcmanfm/desktopwindow.cpp
|
||||||
|
@@ -310,6 +310,16 @@ void DesktopWindow::updateShortcutsFromS
|
||||||
|
paths.push_back(Fm::FilePath::fromLocalPath(network.toStdString().c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ // Lubuntu Manual
|
||||||
|
+ if(ds.contains(QLatin1String("Lubuntu Manual"))) {
|
||||||
|
+ createLubuntuManualShortcut();
|
||||||
|
+ }
|
||||||
|
+ else if(!firstCall) {
|
||||||
|
+ QString network = XdgDir::readDesktopDir() + QLatin1String("/lubuntu-manual.desktop");
|
||||||
|
+ if(QFile::exists(network)) {
|
||||||
|
+ paths.push_back(Fm::FilePath::fromLocalPath(network.toStdString().c_str()));
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
// WARNING: QFile::remove() is not compatible with libfm-qt and should not be used.
|
||||||
|
if(!paths.empty()) {
|
||||||
|
@@ -395,6 +405,20 @@ void DesktopWindow::createNetworkShortcu
|
||||||
|
g_key_file_free(kf);
|
||||||
|
}
|
||||||
|
|
||||||
|
+void DesktopWindow::createLubuntuManualShortcut() {
|
||||||
|
+ GKeyFile* kf = g_key_file_new();
|
||||||
|
+ g_key_file_set_string(kf, "Desktop Entry", "Type", "Application");
|
||||||
|
+ g_key_file_set_string(kf, "Desktop Entry", "Exec", "xdg-open https://manual.lubuntu.me");
|
||||||
|
+ g_key_file_set_string(kf, "Desktop Entry", "Icon", "lubuntu-manual");
|
||||||
|
+ const QString name = tr("Lubuntu Manual");
|
||||||
|
+ g_key_file_set_string(kf, "Desktop Entry", "Name", name.toStdString().c_str());
|
||||||
|
+
|
||||||
|
+ auto path = Fm::FilePath::fromLocalPath(XdgDir::readDesktopDir().toStdString().c_str()).localPath();
|
||||||
|
+ auto trash_can = Fm::CStrPtr{g_build_filename(path.get(), "lubuntu-manual.desktop", nullptr)};
|
||||||
|
+ g_key_file_save_to_file(kf, trash_can.get(), nullptr);
|
||||||
|
+ g_key_file_free(kf);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void DesktopWindow::createTrash() {
|
||||||
|
if(trashMonitor_) {
|
||||||
|
return;
|
||||||
|
@@ -1046,7 +1070,8 @@ void DesktopWindow::onFileClicked(int ty
|
||||||
|
if((fileName == QLatin1String("trash-can.desktop") && ds.contains(QLatin1String("Trash")))
|
||||||
|
|| (fileName == QLatin1String("user-home.desktop") && ds.contains(QLatin1String("Home")))
|
||||||
|
|| (fileName == QLatin1String("computer.desktop") && ds.contains(QLatin1String("Computer")))
|
||||||
|
- || (fileName == QLatin1String("network.desktop") && ds.contains(QLatin1String("Network")))) {
|
||||||
|
+ || (fileName == QLatin1String("network.desktop") && ds.contains(QLatin1String("Network")))
|
||||||
|
+ || (fileName == QLatin1String("lubuntu-manual.desktop") && ds.contains(QLatin1String("Lubuntu Manual")))) {
|
||||||
|
QMenu* menu = new QMenu(this);
|
||||||
|
// "Open" action for all
|
||||||
|
QAction* action = menu->addAction(tr("Open"));
|
||||||
|
@@ -1380,7 +1405,8 @@ void DesktopWindow::trustOurDesktopShort
|
||||||
|
const char* execStr = isHome ? homeExec.get() :
|
||||||
|
fileName == QLatin1String("trash-can.desktop") && ds.contains(QLatin1String("Trash")) ? "pcmanfm-qt trash:///" :
|
||||||
|
fileName == QLatin1String("computer.desktop") && ds.contains(QLatin1String("Computer")) ? "pcmanfm-qt computer:///" :
|
||||||
|
- fileName == QLatin1String("network.desktop") && ds.contains(QLatin1String("Network")) ? "pcmanfm-qt network:///" : nullptr;
|
||||||
|
+ fileName == QLatin1String("network.desktop") && ds.contains(QLatin1String("Network")) ? "pcmanfm-qt network:///" :
|
||||||
|
+ fileName == QLatin1String("lubuntu-manual.desktop") && ds.contains(QLatin1String("Lubuntu Manual")) ? "xdg-open https://manual.lubuntu.me" : nullptr ;
|
||||||
|
if(execStr) {
|
||||||
|
GKeyFile* kf = g_key_file_new();
|
||||||
|
if(g_key_file_load_from_file(kf, file->path().toString().get(), G_KEY_FILE_NONE, nullptr)) {
|
||||||
|
--- a/pcmanfm/desktopwindow.h
|
||||||
|
+++ b/pcmanfm/desktopwindow.h
|
||||||
|
@@ -164,6 +164,7 @@ private:
|
||||||
|
void createHomeShortcut();
|
||||||
|
void createComputerShortcut();
|
||||||
|
void createNetworkShortcut();
|
||||||
|
+ void createLubuntuManualShortcut();
|
||||||
|
|
||||||
|
void createTrash();
|
||||||
|
static void onTrashChanged(GFileMonitor* monitor, GFile* gf, GFile* other, GFileMonitorEvent evt, DesktopWindow* pThis);
|
||||||
|
--- a/pcmanfm/desktop-preferences.ui
|
||||||
|
+++ b/pcmanfm/desktop-preferences.ui
|
||||||
|
@@ -660,6 +660,17 @@ are left clicked, even when it is not th
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
+ <item>
|
||||||
|
+ <widget class="QCheckBox" name="lubuntuManualBox">
|
||||||
|
+ <property name="text">
|
||||||
|
+ <string>Lubuntu Manual</string>
|
||||||
|
+ </property>
|
||||||
|
+ <property name="icon">
|
||||||
|
+ <iconset theme="lubuntu-manual">
|
||||||
|
+ <normaloff>.</normaloff>.</iconset>
|
||||||
|
+ </property>
|
||||||
|
+ </widget>
|
||||||
|
+ </item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/icons/lubuntu-manual.svg
|
||||||
|
@@ -0,0 +1,683 @@
|
||||||
|
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
+
|
||||||
|
+<svg
|
||||||
|
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
+ xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
+ xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
+ xmlns="http://www.w3.org/2000/svg"
|
||||||
|
+ xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
+ width="192"
|
||||||
|
+ height="192"
|
||||||
|
+ id="svg4700"
|
||||||
|
+ version="1.1"
|
||||||
|
+ inkscape:version="0.91 r13725"
|
||||||
|
+ sodipodi:docname="manual192.svg"
|
||||||
|
+ inkscape:export-filename="/home/rafa/Documents/lubuntu/icons/lubuntu manual/manual192.png"
|
||||||
|
+ inkscape:export-xdpi="90"
|
||||||
|
+ inkscape:export-ydpi="90">
|
||||||
|
+ <defs
|
||||||
|
+ id="defs4702">
|
||||||
|
+ <linearGradient
|
||||||
|
+ inkscape:collect="always"
|
||||||
|
+ id="linearGradient4224">
|
||||||
|
+ <stop
|
||||||
|
+ style="stop-color:#5a0000;stop-opacity:1"
|
||||||
|
+ offset="0"
|
||||||
|
+ id="stop4226" />
|
||||||
|
+ <stop
|
||||||
|
+ style="stop-color:#ff0101;stop-opacity:1"
|
||||||
|
+ offset="1"
|
||||||
|
+ id="stop4228" />
|
||||||
|
+ </linearGradient>
|
||||||
|
+ <linearGradient
|
||||||
|
+ inkscape:collect="always"
|
||||||
|
+ id="linearGradient4382">
|
||||||
|
+ <stop
|
||||||
|
+ style="stop-color:#ffffff;stop-opacity:0.50196081"
|
||||||
|
+ offset="0"
|
||||||
|
+ id="stop4384" />
|
||||||
|
+ <stop
|
||||||
|
+ style="stop-color:#ffffff;stop-opacity:0;"
|
||||||
|
+ offset="1"
|
||||||
|
+ id="stop4386" />
|
||||||
|
+ </linearGradient>
|
||||||
|
+ <linearGradient
|
||||||
|
+ inkscape:collect="always"
|
||||||
|
+ id="linearGradient4326">
|
||||||
|
+ <stop
|
||||||
|
+ style="stop-color:#000000;stop-opacity:1;"
|
||||||
|
+ offset="0"
|
||||||
|
+ id="stop4328" />
|
||||||
|
+ <stop
|
||||||
|
+ style="stop-color:#000000;stop-opacity:0;"
|
||||||
|
+ offset="1"
|
||||||
|
+ id="stop4330" />
|
||||||
|
+ </linearGradient>
|
||||||
|
+ <inkscape:path-effect
|
||||||
|
+ effect="powerstroke"
|
||||||
|
+ id="path-effect4315"
|
||||||
|
+ is_visible="true"
|
||||||
|
+ offset_points="0,0"
|
||||||
|
+ sort_points="true"
|
||||||
|
+ interpolator_type="Linear"
|
||||||
|
+ interpolator_beta="0.2"
|
||||||
|
+ start_linecap_type="zerowidth"
|
||||||
|
+ linejoin_type="round"
|
||||||
|
+ miter_limit="4"
|
||||||
|
+ end_linecap_type="zerowidth"
|
||||||
|
+ cusp_linecap_type="round" />
|
||||||
|
+ <linearGradient
|
||||||
|
+ id="linearGradient4307">
|
||||||
|
+ <stop
|
||||||
|
+ style="stop-color:#90cfff;stop-opacity:1"
|
||||||
|
+ offset="0"
|
||||||
|
+ id="stop4309" />
|
||||||
|
+ <stop
|
||||||
|
+ style="stop-color:#27a8ff;stop-opacity:0"
|
||||||
|
+ offset="1"
|
||||||
|
+ id="stop4311" />
|
||||||
|
+ </linearGradient>
|
||||||
|
+ <linearGradient
|
||||||
|
+ id="linearGradient4242">
|
||||||
|
+ <stop
|
||||||
|
+ id="stop4244"
|
||||||
|
+ offset="0"
|
||||||
|
+ style="stop-color:#2b8dd1;stop-opacity:1;" />
|
||||||
|
+ <stop
|
||||||
|
+ id="stop4246"
|
||||||
|
+ offset="1"
|
||||||
|
+ style="stop-color:#1a557e;stop-opacity:1" />
|
||||||
|
+ </linearGradient>
|
||||||
|
+ <linearGradient
|
||||||
|
+ id="linearGradient4456">
|
||||||
|
+ <stop
|
||||||
|
+ id="stop4458"
|
||||||
|
+ offset="0"
|
||||||
|
+ style="stop-color:#2b8dd1;stop-opacity:1;" />
|
||||||
|
+ <stop
|
||||||
|
+ id="stop4460"
|
||||||
|
+ offset="1"
|
||||||
|
+ style="stop-color:#1b5781;stop-opacity:1" />
|
||||||
|
+ </linearGradient>
|
||||||
|
+ <linearGradient
|
||||||
|
+ id="linearGradient4389">
|
||||||
|
+ <stop
|
||||||
|
+ id="stop4391"
|
||||||
|
+ offset="0"
|
||||||
|
+ style="stop-color:#1b557e;stop-opacity:1" />
|
||||||
|
+ <stop
|
||||||
|
+ id="stop4393"
|
||||||
|
+ offset="1"
|
||||||
|
+ style="stop-color:#1a5179;stop-opacity:1" />
|
||||||
|
+ </linearGradient>
|
||||||
|
+ <inkscape:path-effect
|
||||||
|
+ cusp_linecap_type="round"
|
||||||
|
+ end_linecap_type="zerowidth"
|
||||||
|
+ miter_limit="4"
|
||||||
|
+ linejoin_type="round"
|
||||||
|
+ start_linecap_type="zerowidth"
|
||||||
|
+ interpolator_beta="0.2"
|
||||||
|
+ interpolator_type="Linear"
|
||||||
|
+ sort_points="true"
|
||||||
|
+ offset_points="0,0"
|
||||||
|
+ is_visible="true"
|
||||||
|
+ id="path-effect4352"
|
||||||
|
+ effect="powerstroke" />
|
||||||
|
+ <inkscape:path-effect
|
||||||
|
+ effect="powerstroke"
|
||||||
|
+ id="path-effect4344"
|
||||||
|
+ is_visible="true"
|
||||||
|
+ offset_points="0,0"
|
||||||
|
+ sort_points="true"
|
||||||
|
+ interpolator_type="Linear"
|
||||||
|
+ interpolator_beta="0.2"
|
||||||
|
+ start_linecap_type="zerowidth"
|
||||||
|
+ linejoin_type="round"
|
||||||
|
+ miter_limit="4"
|
||||||
|
+ end_linecap_type="zerowidth"
|
||||||
|
+ cusp_linecap_type="round" />
|
||||||
|
+ <inkscape:path-effect
|
||||||
|
+ effect="spiro"
|
||||||
|
+ id="path-effect4329"
|
||||||
|
+ is_visible="true" />
|
||||||
|
+ <inkscape:path-effect
|
||||||
|
+ cusp_linecap_type="round"
|
||||||
|
+ end_linecap_type="zerowidth"
|
||||||
|
+ miter_limit="4"
|
||||||
|
+ linejoin_type="round"
|
||||||
|
+ start_linecap_type="zerowidth"
|
||||||
|
+ interpolator_beta="0.2"
|
||||||
|
+ interpolator_type="Linear"
|
||||||
|
+ sort_points="true"
|
||||||
|
+ offset_points="0,0"
|
||||||
|
+ is_visible="true"
|
||||||
|
+ id="path-effect4321"
|
||||||
|
+ effect="powerstroke" />
|
||||||
|
+ <inkscape:path-effect
|
||||||
|
+ effect="powerstroke"
|
||||||
|
+ id="path-effect4281"
|
||||||
|
+ is_visible="true"
|
||||||
|
+ offset_points="0,0"
|
||||||
|
+ sort_points="true"
|
||||||
|
+ interpolator_type="Linear"
|
||||||
|
+ interpolator_beta="0.2"
|
||||||
|
+ start_linecap_type="zerowidth"
|
||||||
|
+ linejoin_type="round"
|
||||||
|
+ miter_limit="4"
|
||||||
|
+ end_linecap_type="zerowidth"
|
||||||
|
+ cusp_linecap_type="round" />
|
||||||
|
+ <linearGradient
|
||||||
|
+ id="linearGradient3834">
|
||||||
|
+ <stop
|
||||||
|
+ style="stop-color:#2b8dd1;stop-opacity:1;"
|
||||||
|
+ offset="0"
|
||||||
|
+ id="stop3836" />
|
||||||
|
+ <stop
|
||||||
|
+ style="stop-color:#2578b2;stop-opacity:1;"
|
||||||
|
+ offset="1"
|
||||||
|
+ id="stop3838" />
|
||||||
|
+ </linearGradient>
|
||||||
|
+ <filter
|
||||||
|
+ id="filter3174"
|
||||||
|
+ style="color-interpolation-filters:sRGB">
|
||||||
|
+ <feGaussianBlur
|
||||||
|
+ stdDeviation="1.71"
|
||||||
|
+ id="feGaussianBlur3176" />
|
||||||
|
+ </filter>
|
||||||
|
+ <linearGradient
|
||||||
|
+ gradientTransform="scale(1.0058652,0.994169)"
|
||||||
|
+ gradientUnits="userSpaceOnUse"
|
||||||
|
+ id="ButtonShadow"
|
||||||
|
+ y2="7.0165396"
|
||||||
|
+ x2="45.447727"
|
||||||
|
+ y1="92.539597"
|
||||||
|
+ x1="45.447727">
|
||||||
|
+ <stop
|
||||||
|
+ offset="0"
|
||||||
|
+ style="stop-color:#000000;stop-opacity:1"
|
||||||
|
+ id="stop3750" />
|
||||||
|
+ <stop
|
||||||
|
+ offset="1"
|
||||||
|
+ style="stop-color:#000000;stop-opacity:0.58823532"
|
||||||
|
+ id="stop3752" />
|
||||||
|
+ </linearGradient>
|
||||||
|
+ <linearGradient
|
||||||
|
+ id="linearGradient5048-8-7">
|
||||||
|
+ <stop
|
||||||
|
+ offset="0"
|
||||||
|
+ style="stop-color:#000000;stop-opacity:0"
|
||||||
|
+ id="stop5050-4-2" />
|
||||||
|
+ <stop
|
||||||
|
+ offset="0.5"
|
||||||
|
+ style="stop-color:#000000;stop-opacity:1"
|
||||||
|
+ id="stop5056-7-4" />
|
||||||
|
+ <stop
|
||||||
|
+ offset="1"
|
||||||
|
+ style="stop-color:#000000;stop-opacity:0"
|
||||||
|
+ id="stop5052-0-1-7" />
|
||||||
|
+ </linearGradient>
|
||||||
|
+ <linearGradient
|
||||||
|
+ id="linearGradient5060-29-0">
|
||||||
|
+ <stop
|
||||||
|
+ offset="0"
|
||||||
|
+ style="stop-color:#000000;stop-opacity:1"
|
||||||
|
+ id="stop5062-9-7" />
|
||||||
|
+ <stop
|
||||||
|
+ offset="1"
|
||||||
|
+ style="stop-color:#000000;stop-opacity:0"
|
||||||
|
+ id="stop5064-08-2" />
|
||||||
|
+ </linearGradient>
|
||||||
|
+ <filter
|
||||||
|
+ id="filter3174-0"
|
||||||
|
+ style="color-interpolation-filters:sRGB">
|
||||||
|
+ <feGaussianBlur
|
||||||
|
+ stdDeviation="1.71"
|
||||||
|
+ id="feGaussianBlur3176-9" />
|
||||||
|
+ </filter>
|
||||||
|
+ <linearGradient
|
||||||
|
+ gradientTransform="scale(1.0058652,0.994169)"
|
||||||
|
+ gradientUnits="userSpaceOnUse"
|
||||||
|
+ id="ButtonShadow-3"
|
||||||
|
+ y2="7.0165396"
|
||||||
|
+ x2="45.447727"
|
||||||
|
+ y1="92.539597"
|
||||||
|
+ x1="45.447727">
|
||||||
|
+ <stop
|
||||||
|
+ offset="0"
|
||||||
|
+ style="stop-color:#000000;stop-opacity:1"
|
||||||
|
+ id="stop3750-8" />
|
||||||
|
+ <stop
|
||||||
|
+ offset="1"
|
||||||
|
+ style="stop-color:#000000;stop-opacity:0.58823532"
|
||||||
|
+ id="stop3752-1" />
|
||||||
|
+ </linearGradient>
|
||||||
|
+ <radialGradient
|
||||||
|
+ inkscape:collect="always"
|
||||||
|
+ xlink:href="#linearGradient5060-29-0"
|
||||||
|
+ id="radialGradient4030"
|
||||||
|
+ gradientUnits="userSpaceOnUse"
|
||||||
|
+ gradientTransform="matrix(0.06214224,0,0,0.02900085,1.6365015,28.953157)"
|
||||||
|
+ cx="605.71429"
|
||||||
|
+ cy="486.64789"
|
||||||
|
+ fx="605.71429"
|
||||||
|
+ fy="486.64789"
|
||||||
|
+ r="117.14286" />
|
||||||
|
+ <linearGradient
|
||||||
|
+ inkscape:collect="always"
|
||||||
|
+ xlink:href="#linearGradient5048-8-7"
|
||||||
|
+ id="linearGradient4032"
|
||||||
|
+ gradientUnits="userSpaceOnUse"
|
||||||
|
+ gradientTransform="matrix(0.06214224,0,0,0.02900085,1.6242719,28.953157)"
|
||||||
|
+ x1="302.85715"
|
||||||
|
+ y1="366.64789"
|
||||||
|
+ x2="302.85715"
|
||||||
|
+ y2="609.50507" />
|
||||||
|
+ <radialGradient
|
||||||
|
+ inkscape:collect="always"
|
||||||
|
+ xlink:href="#linearGradient5060-29-0"
|
||||||
|
+ id="radialGradient4034"
|
||||||
|
+ gradientUnits="userSpaceOnUse"
|
||||||
|
+ gradientTransform="matrix(-0.06214224,0,0,0.02900085,46.53201,28.953157)"
|
||||||
|
+ cx="605.71429"
|
||||||
|
+ cy="486.64789"
|
||||||
|
+ fx="605.71429"
|
||||||
|
+ fy="486.64789"
|
||||||
|
+ r="117.14286" />
|
||||||
|
+ <linearGradient
|
||||||
|
+ id="linearGradient3768"
|
||||||
|
+ inkscape:collect="always">
|
||||||
|
+ <stop
|
||||||
|
+ id="stop3770"
|
||||||
|
+ offset="0"
|
||||||
|
+ style="stop-color:#61bbff;stop-opacity:1" />
|
||||||
|
+ <stop
|
||||||
|
+ id="stop3772"
|
||||||
|
+ offset="1"
|
||||||
|
+ style="stop-color:#0091f3;stop-opacity:1" />
|
||||||
|
+ </linearGradient>
|
||||||
|
+ <linearGradient
|
||||||
|
+ inkscape:collect="always"
|
||||||
|
+ xlink:href="#linearGradient4242"
|
||||||
|
+ id="linearGradient3840"
|
||||||
|
+ x1="33.189663"
|
||||||
|
+ y1="1005.5547"
|
||||||
|
+ x2="33.189663"
|
||||||
|
+ y2="1051.2649"
|
||||||
|
+ gradientUnits="userSpaceOnUse"
|
||||||
|
+ gradientTransform="matrix(3.3666402,0,0,3.7220007,15.040259,-3882.4165)" />
|
||||||
|
+ <linearGradient
|
||||||
|
+ inkscape:collect="always"
|
||||||
|
+ xlink:href="#linearGradient3768"
|
||||||
|
+ id="linearGradient3465"
|
||||||
|
+ gradientUnits="userSpaceOnUse"
|
||||||
|
+ gradientTransform="matrix(3.356103,0,0,3.0865386,15.45353,-3243.4134)"
|
||||||
|
+ x1="15"
|
||||||
|
+ y1="1005.3622"
|
||||||
|
+ x2="15"
|
||||||
|
+ y2="1051.3622" />
|
||||||
|
+ <linearGradient
|
||||||
|
+ inkscape:collect="always"
|
||||||
|
+ xlink:href="#linearGradient4389"
|
||||||
|
+ id="linearGradient3467"
|
||||||
|
+ gradientUnits="userSpaceOnUse"
|
||||||
|
+ x1="1.254336"
|
||||||
|
+ y1="1058.204"
|
||||||
|
+ x2="15.183573"
|
||||||
|
+ y2="1058.204"
|
||||||
|
+ gradientTransform="matrix(3.3666405,0,0,3.0865371,15.040261,-3243.786)" />
|
||||||
|
+ <linearGradient
|
||||||
|
+ inkscape:collect="always"
|
||||||
|
+ xlink:href="#linearGradient4307"
|
||||||
|
+ id="linearGradient3469"
|
||||||
|
+ gradientUnits="userSpaceOnUse"
|
||||||
|
+ gradientTransform="matrix(3.3157894,0,0,3.0340879,16.421055,-3189.475)"
|
||||||
|
+ x1="34.285713"
|
||||||
|
+ y1="1002.3465"
|
||||||
|
+ x2="21.42857"
|
||||||
|
+ y2="1031.8778" />
|
||||||
|
+ <linearGradient
|
||||||
|
+ inkscape:collect="always"
|
||||||
|
+ xlink:href="#linearGradient3834"
|
||||||
|
+ id="linearGradient4317"
|
||||||
|
+ gradientUnits="userSpaceOnUse"
|
||||||
|
+ gradientTransform="matrix(3.3666405,0,0,3.0865371,15.040258,-3243.786)"
|
||||||
|
+ x1="33.189663"
|
||||||
|
+ y1="1005.5547"
|
||||||
|
+ x2="33.189663"
|
||||||
|
+ y2="1051.2649" />
|
||||||
|
+ <linearGradient
|
||||||
|
+ inkscape:collect="always"
|
||||||
|
+ xlink:href="#linearGradient3768"
|
||||||
|
+ id="linearGradient4323"
|
||||||
|
+ gradientUnits="userSpaceOnUse"
|
||||||
|
+ gradientTransform="matrix(-3.356103,0,0,3.0865386,174.39992,-3273.2809)"
|
||||||
|
+ x1="15"
|
||||||
|
+ y1="1005.3622"
|
||||||
|
+ x2="15"
|
||||||
|
+ y2="1051.3622" />
|
||||||
|
+ <linearGradient
|
||||||
|
+ inkscape:collect="always"
|
||||||
|
+ xlink:href="#linearGradient4456"
|
||||||
|
+ id="linearGradient4325"
|
||||||
|
+ gradientUnits="userSpaceOnUse"
|
||||||
|
+ gradientTransform="matrix(-3.3666405,0,0,3.0865371,174.81318,-3273.6535)"
|
||||||
|
+ x1="33.189663"
|
||||||
|
+ y1="1005.5547"
|
||||||
|
+ x2="33.540394"
|
||||||
|
+ y2="1060.9689" />
|
||||||
|
+ <linearGradient
|
||||||
|
+ inkscape:collect="always"
|
||||||
|
+ xlink:href="#linearGradient3768"
|
||||||
|
+ id="linearGradient4297"
|
||||||
|
+ gradientUnits="userSpaceOnUse"
|
||||||
|
+ gradientTransform="matrix(3.3563192,0,0,3.086755,15.448336,-3243.636)"
|
||||||
|
+ x1="15"
|
||||||
|
+ y1="1005.3622"
|
||||||
|
+ x2="15"
|
||||||
|
+ y2="1051.3622" />
|
||||||
|
+ <linearGradient
|
||||||
|
+ inkscape:collect="always"
|
||||||
|
+ xlink:href="#linearGradient4242"
|
||||||
|
+ id="linearGradient4299"
|
||||||
|
+ gradientUnits="userSpaceOnUse"
|
||||||
|
+ gradientTransform="matrix(3.3668574,0,0,3.0867535,15.035041,-3244.0086)"
|
||||||
|
+ x1="33.189663"
|
||||||
|
+ y1="1005.5547"
|
||||||
|
+ x2="33.189663"
|
||||||
|
+ y2="1051.2649" />
|
||||||
|
+ <linearGradient
|
||||||
|
+ inkscape:collect="always"
|
||||||
|
+ xlink:href="#linearGradient4326"
|
||||||
|
+ id="linearGradient4332"
|
||||||
|
+ x1="40"
|
||||||
|
+ y1="43"
|
||||||
|
+ x2="42"
|
||||||
|
+ y2="43"
|
||||||
|
+ gradientUnits="userSpaceOnUse"
|
||||||
|
+ gradientTransform="matrix(4.2631576,0,0,4.2666859,-6.3157863,-156.80092)" />
|
||||||
|
+ <linearGradient
|
||||||
|
+ inkscape:collect="always"
|
||||||
|
+ xlink:href="#linearGradient4382"
|
||||||
|
+ id="linearGradient4388"
|
||||||
|
+ x1="15"
|
||||||
|
+ y1="37"
|
||||||
|
+ x2="15"
|
||||||
|
+ y2="4"
|
||||||
|
+ gradientUnits="userSpaceOnUse"
|
||||||
|
+ gradientTransform="matrix(4.2631576,0,0,4.2666859,-6.3157863,-156.80092)" />
|
||||||
|
+ <linearGradient
|
||||||
|
+ inkscape:collect="always"
|
||||||
|
+ xlink:href="#linearGradient4224"
|
||||||
|
+ id="linearGradient4230"
|
||||||
|
+ x1="34"
|
||||||
|
+ y1="40"
|
||||||
|
+ x2="34"
|
||||||
|
+ y2="43"
|
||||||
|
+ gradientUnits="userSpaceOnUse"
|
||||||
|
+ gradientTransform="matrix(4.2631576,0,0,4.2666859,-6.3157863,-156.80092)" />
|
||||||
|
+ <linearGradient
|
||||||
|
+ inkscape:collect="always"
|
||||||
|
+ xlink:href="#linearGradient4326"
|
||||||
|
+ id="linearGradient3453"
|
||||||
|
+ gradientUnits="userSpaceOnUse"
|
||||||
|
+ x1="40"
|
||||||
|
+ y1="43"
|
||||||
|
+ x2="42"
|
||||||
|
+ y2="43"
|
||||||
|
+ gradientTransform="matrix(4.2631576,0,0,4.2666859,-6.3157863,-156.80092)" />
|
||||||
|
+ <linearGradient
|
||||||
|
+ inkscape:collect="always"
|
||||||
|
+ xlink:href="#linearGradient4326"
|
||||||
|
+ id="linearGradient3455"
|
||||||
|
+ gradientUnits="userSpaceOnUse"
|
||||||
|
+ x1="40"
|
||||||
|
+ y1="43"
|
||||||
|
+ x2="42"
|
||||||
|
+ y2="43"
|
||||||
|
+ gradientTransform="matrix(4.2631576,0,0,4.2666859,-6.3157863,-156.80092)" />
|
||||||
|
+ </defs>
|
||||||
|
+ <sodipodi:namedview
|
||||||
|
+ id="base"
|
||||||
|
+ pagecolor="#ffffff"
|
||||||
|
+ bordercolor="#666666"
|
||||||
|
+ borderopacity="1.0"
|
||||||
|
+ inkscape:pageopacity="0.0"
|
||||||
|
+ inkscape:pageshadow="2"
|
||||||
|
+ inkscape:zoom="2"
|
||||||
|
+ inkscape:cx="148.16082"
|
||||||
|
+ inkscape:cy="73.78278"
|
||||||
|
+ inkscape:current-layer="layer1"
|
||||||
|
+ showgrid="true"
|
||||||
|
+ inkscape:grid-bbox="true"
|
||||||
|
+ inkscape:document-units="px"
|
||||||
|
+ inkscape:window-width="1301"
|
||||||
|
+ inkscape:window-height="744"
|
||||||
|
+ inkscape:window-x="65"
|
||||||
|
+ inkscape:window-y="24"
|
||||||
|
+ inkscape:window-maximized="1"
|
||||||
|
+ inkscape:snap-to-guides="false"
|
||||||
|
+ inkscape:snap-grids="true"
|
||||||
|
+ inkscape:snap-page="true"
|
||||||
|
+ inkscape:snap-center="false"
|
||||||
|
+ inkscape:snap-object-midpoints="false"
|
||||||
|
+ inkscape:snap-bbox="true"
|
||||||
|
+ inkscape:snap-bbox-edge-midpoints="true"
|
||||||
|
+ inkscape:bbox-nodes="true"
|
||||||
|
+ inkscape:bbox-paths="true"
|
||||||
|
+ inkscape:snap-smooth-nodes="true"
|
||||||
|
+ inkscape:object-nodes="true"
|
||||||
|
+ inkscape:snap-intersection-paths="true"
|
||||||
|
+ inkscape:object-paths="true"
|
||||||
|
+ showguides="false"
|
||||||
|
+ inkscape:snap-bbox-midpoints="true"
|
||||||
|
+ inkscape:snap-others="false"
|
||||||
|
+ inkscape:snap-global="false">
|
||||||
|
+ <inkscape:grid
|
||||||
|
+ type="xygrid"
|
||||||
|
+ id="grid1021" />
|
||||||
|
+ </sodipodi:namedview>
|
||||||
|
+ <metadata
|
||||||
|
+ id="metadata4705">
|
||||||
|
+ <rdf:RDF>
|
||||||
|
+ <cc:Work
|
||||||
|
+ rdf:about="">
|
||||||
|
+ <dc:format>image/svg+xml</dc:format>
|
||||||
|
+ <dc:type
|
||||||
|
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
+ <dc:title></dc:title>
|
||||||
|
+ </cc:Work>
|
||||||
|
+ </rdf:RDF>
|
||||||
|
+ </metadata>
|
||||||
|
+ <g
|
||||||
|
+ id="layer1"
|
||||||
|
+ inkscape:label="Layer 1"
|
||||||
|
+ inkscape:groupmode="layer"
|
||||||
|
+ transform="translate(0,144)">
|
||||||
|
+ <g
|
||||||
|
+ id="layer2"
|
||||||
|
+ style="display:none"
|
||||||
|
+ transform="translate(5.204491,-179.6879)">
|
||||||
|
+ <rect
|
||||||
|
+ width="86"
|
||||||
|
+ height="85"
|
||||||
|
+ rx="6"
|
||||||
|
+ ry="6"
|
||||||
|
+ x="5"
|
||||||
|
+ y="7"
|
||||||
|
+ id="rect3745"
|
||||||
|
+ style="opacity:0.9;fill:url(#ButtonShadow);fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3174)" />
|
||||||
|
+ </g>
|
||||||
|
+ <g
|
||||||
|
+ id="layer2-0"
|
||||||
|
+ style="display:none"
|
||||||
|
+ transform="matrix(1.9515901,0,0,1.9515901,-37.264816,-396.93714)">
|
||||||
|
+ <rect
|
||||||
|
+ width="86"
|
||||||
|
+ height="85"
|
||||||
|
+ rx="3.0744162"
|
||||||
|
+ ry="3.0744162"
|
||||||
|
+ x="5"
|
||||||
|
+ y="7"
|
||||||
|
+ id="rect3745-9"
|
||||||
|
+ style="opacity:0.9;fill:url(#ButtonShadow-3);fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3174-0)" />
|
||||||
|
+ </g>
|
||||||
|
+ <g
|
||||||
|
+ id="g1017-7"
|
||||||
|
+ transform="matrix(3.5621042,0,0,4.2405982,10.209386,-149.73618)">
|
||||||
|
+ <path
|
||||||
|
+ inkscape:connector-curvature="0"
|
||||||
|
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:url(#radialGradient4030);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:104.96237946;marker:none"
|
||||||
|
+ id="path5058-0-2"
|
||||||
|
+ d="m 39.087163,39.586499 c 0,0 0,7.042675 0,7.042675 3.200171,0.01326 7.736457,-1.577906 7.736455,-3.52179 0,-1.943885 -3.57115,-3.520884 -7.736455,-3.520885 z" />
|
||||||
|
+ <rect
|
||||||
|
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:url(#linearGradient4032);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:104.96237946;marker:none"
|
||||||
|
+ id="rect4173-6-3"
|
||||||
|
+ y="39.58625"
|
||||||
|
+ x="9.0813398"
|
||||||
|
+ height="7.0430632"
|
||||||
|
+ width="30.005821" />
|
||||||
|
+ <path
|
||||||
|
+ inkscape:connector-curvature="0"
|
||||||
|
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:url(#radialGradient4034);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:104.96237946;marker:none"
|
||||||
|
+ id="path5018-7-4"
|
||||||
|
+ d="m 9.0813406,39.586499 c 0,0 0,7.042675 0,7.042675 -3.2001721,0.01326 -7.7364568,-1.577906 -7.7364568,-3.52179 0,-1.943885 3.57115,-3.520884 7.7364568,-3.520885 z" />
|
||||||
|
+ </g>
|
||||||
|
+ <g
|
||||||
|
+ id="g4574"
|
||||||
|
+ transform="matrix(6.8513602,0,0,6.831439,-103.74555,-218.3363)" />
|
||||||
|
+ <g
|
||||||
|
+ id="layer4"
|
||||||
|
+ transform="matrix(4.2631576,0,0,4.2666859,-239.91768,-919.20606)" />
|
||||||
|
+ <g
|
||||||
|
+ id="layer4-7"
|
||||||
|
+ transform="matrix(8.3199362,0,0,8.326822,-165.18157,-1850.407)" />
|
||||||
|
+ <rect
|
||||||
|
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient3840);stroke-width:4.26492119;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||||
|
+ id="rect2996"
|
||||||
|
+ width="157.73683"
|
||||||
|
+ height="174.93413"
|
||||||
|
+ x="17.13158"
|
||||||
|
+ y="-141.86752"
|
||||||
|
+ ry="17.066744"
|
||||||
|
+ rx="17.052629" />
|
||||||
|
+ <path
|
||||||
|
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient3453);stroke-width:4.21033764;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50196078;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
+ d="m 174.86897,-16.000285 c 0,6.4000288 0,12.8000575 0,19.2000863 0,0 5e-4,4.2666859 -2.13083,8.5333717 -2.13133,4.266685 -6.39448,8.53337 -14.92179,8.533372 -41.21077,0 -82.421527,0 -123.632286,0 -8.659836,-4e-6 -12.92299,-4.266688 -15.021189,-8.533372 -2.0982,-4.2666858 -2.031442,-8.5333717 -2.031442,-8.5333717 2.16e-4,-6.4000288 4.32e-4,-12.8000575 6.48e-4,-19.2000863 -2.16e-4,6.4000288 -4.32e-4,12.8000575 -6.48e-4,19.2000863 0,0 -0.06676,4.2666859 2.031442,8.5333717 2.098199,4.266684 6.361353,8.533368 15.021176,8.533372 41.210772,0 82.421529,0 123.632289,0 8.52732,-2e-6 12.79047,-4.266687 14.9218,-8.533372 2.13133,-4.2666858 2.13083,-8.5333717 2.13083,-8.5333717 0,-6.4000288 0,-12.8000575 0,-19.2000863 z"
|
||||||
|
+ id="path4313"
|
||||||
|
+ inkscape:path-effect="#path-effect4315"
|
||||||
|
+ inkscape:original-d="m 174.86897,-16.000285 0,19.2000863 c 0,0 0.002,17.0667437 -17.05263,17.0667437 l -123.632276,0 c -17.319663,0 -17.052631,-17.0667437 -17.052631,-17.0667437 l 6.48e-4,-19.2000863"
|
||||||
|
+ inkscape:connector-curvature="0"
|
||||||
|
+ sodipodi:nodetypes="cccccc" />
|
||||||
|
+ <path
|
||||||
|
+ sodipodi:nodetypes="cccccc"
|
||||||
|
+ inkscape:connector-curvature="0"
|
||||||
|
+ inkscape:original-d="m 174.86897,-24.533657 0,19.2000865 c 0,0 0.002,17.0667435 -17.05263,17.0667435 l -123.632276,0 c -17.319663,0 -17.052631,-17.0667435 -17.052631,-17.0667435 l 6.48e-4,-19.2000865"
|
||||||
|
+ inkscape:path-effect="#path-effect4352"
|
||||||
|
+ id="path4350"
|
||||||
|
+ d="m 174.86897,-24.533657 c 0,6.400029 0,12.800058 0,19.2000865 0,0 5e-4,4.2666859 -2.13083,8.5333717 -2.13133,4.2666849 -6.39448,8.5333698 -14.92179,8.5333718 -41.21077,0 -82.421527,0 -123.632286,0 -8.659836,-4e-6 -12.92299,-4.266688 -15.021189,-8.5333718 -2.0982,-4.2666858 -2.031442,-8.5333717 -2.031442,-8.5333717 2.16e-4,-6.4000285 4.32e-4,-12.8000575 6.48e-4,-19.2000865 -2.16e-4,6.400029 -4.32e-4,12.800058 -6.48e-4,19.2000865 0,0 -0.06676,4.2666859 2.031442,8.5333717 2.098199,4.2666838 6.361353,8.5333678 15.021176,8.5333718 41.210772,0 82.421529,0 123.632289,0 8.52732,-2e-6 12.79047,-4.2666869 14.9218,-8.5333718 2.13133,-4.2666858 2.13083,-8.5333717 2.13083,-8.5333717 0,-6.4000285 0,-12.8000575 0,-19.2000865 z"
|
||||||
|
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient3455);stroke-width:4.21033764;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50196078;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
+ <path
|
||||||
|
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient4332);stroke-width:4.21033764;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50196078;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
+ d="m 174.87916,-7.4941734 c 0,7.11862847 0,14.2372569 0,21.3558854 0,0 -0.92095,3.734551 -3.51435,7.469102 -2.59339,3.734551 -6.85924,7.469101 -13.54902,7.469103 -41.32876,0.0091 -82.657509,0.0182 -123.986259,0.02731 -6.689792,-4e-6 -9.801202,-3.741355 -11.240167,-7.482707 -1.438966,-3.741353 -1.205484,-7.482706 -1.205484,-7.482706 2.1e-4,-7.1186284 4.2e-4,-14.2372568 6.3e-4,-21.3558852 -2.1e-4,7.1186284 -4.2e-4,14.2372568 -6.3e-4,21.3558852 0,0 -0.233482,3.741353 1.205484,7.482706 1.438965,3.741352 4.550375,7.482703 11.240157,7.482707 41.32876,-0.0091 82.657509,-0.0182 123.986259,-0.02731 6.68979,-2e-6 10.95564,-3.734552 13.54903,-7.469103 2.5934,-3.734551 3.51435,-7.469102 3.51435,-7.469102 0,-7.1186285 0,-14.23725693 0,-21.3558854 z"
|
||||||
|
+ id="path4342"
|
||||||
|
+ inkscape:path-effect="#path-effect4344"
|
||||||
|
+ inkscape:original-d="m 174.87916,-7.4941734 0,21.3558854 c 0,0 -3.6838,14.938205 -17.06338,14.938205 L 33.829531,28.827223 C 20.449953,28.827223 21.38388,13.86181 21.38388,13.86181 l 6.3e-4,-21.3558852"
|
||||||
|
+ inkscape:connector-curvature="0"
|
||||||
|
+ sodipodi:nodetypes="cccccc" />
|
||||||
|
+ <rect
|
||||||
|
+ ry="17.066744"
|
||||||
|
+ y="-141.86752"
|
||||||
|
+ x="17.13158"
|
||||||
|
+ height="145.06732"
|
||||||
|
+ width="157.73683"
|
||||||
|
+ id="rect3449"
|
||||||
|
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient4317);stroke-width:4.26492119;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||||
|
+ rx="17.052629" />
|
||||||
|
+ <rect
|
||||||
|
+ ry="17.024317"
|
||||||
|
+ y="-141.8726"
|
||||||
|
+ x="17.126493"
|
||||||
|
+ height="145.0775"
|
||||||
|
+ width="157.74701"
|
||||||
|
+ id="rect4295"
|
||||||
|
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient4297);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient4299);stroke-width:4.25474834;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
|
||||||
|
+ <path
|
||||||
|
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient3465);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient3467);stroke-width:4.26492119;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
+ d="m 85.342102,3.1998013 c -17.05263,0 -34.105261,0 -51.157891,0 0,0 -4.263158,-0.1005755 -8.526312,1.7158093 -4.263161,1.8163879 -8.526318,5.5497384 -8.526318,13.2175914 0,7.600326 4.263158,11.333677 8.526315,13.166945 4.263159,1.833268 8.526312,1.766456 8.526315,1.766456 -34.184211,0 -34.184211,0 51.157891,0 -17.05263,0 -34.105261,0 -51.157891,0 -3e-6,0 -4.263156,0.06681 -8.52631,-1.766453 -4.263162,-1.833271 -8.52632,-5.566622 -8.52632,-13.166948 0,-7.667853 4.263157,-11.4012035 8.526315,-13.2175903 4.263157,-1.8163859 8.526315,-1.7158104 8.526315,-1.7158104 17.05263,0 34.105261,0 51.157891,0 z"
|
||||||
|
+ id="path4279"
|
||||||
|
+ inkscape:original-d="m 85.342102,3.1998013 -51.157891,0 c 0,0 -17.05263,-0.4023059 -17.05263,14.9334007 0,15.200653 17.05263,14.933401 17.05263,14.933401 l 51.157891,0"
|
||||||
|
+ inkscape:connector-curvature="0"
|
||||||
|
+ sodipodi:nodetypes="ccccc"
|
||||||
|
+ inkscape:path-effect="#path-effect4281" />
|
||||||
|
+ <path
|
||||||
|
+ sodipodi:nodetypes="cccccc"
|
||||||
|
+ inkscape:connector-curvature="0"
|
||||||
|
+ inkscape:original-d="m 106.65789,-141.86752 51.15789,0 c 0,0 17.05263,-0.002 17.05263,17.06674 l 0,110.933838 c 0,17.3339957 -17.05263,17.0667433 -17.05263,17.0667433 L 87.458713,3.1991527"
|
||||||
|
+ id="path4319"
|
||||||
|
+ d="m 106.65789,-141.86752 c 17.05263,0 34.10526,0 51.15789,0 0,0 4.26316,-5e-4 8.52631,2.13259 4.26316,2.13309 8.52632,6.39978 8.52632,14.93414 0,36.977956 0,73.955902 0,110.933848 0,8.6670021 -4.26316,12.93368472 -8.52632,15.03362 -4.26315,2.0999364 -8.52631,2.0331233 -8.52631,2.0331233 -23.45236,-2.162e-4 -46.90471,-4.324e-4 -70.357067,-6.486e-4 23.452357,2.162e-4 46.904707,4.324e-4 70.357067,6.486e-4 0,0 4.26316,0.066813 8.52631,-2.0331233 4.26316,-2.09993528 8.52632,-6.3666179 8.52632,-15.033607 0,-36.977959 0,-73.955905 0,-110.933851 0,-8.53437 -4.26316,-12.80106 -8.52632,-14.93415 -4.26315,-2.13309 -8.52631,-2.13259 -8.52631,-2.13259 -17.05263,0 -34.10526,0 -51.15789,0 z"
|
||||||
|
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient4323);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient4325);stroke-width:4.26492119;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
+ inkscape:path-effect="#path-effect4321" />
|
||||||
|
+ <path
|
||||||
|
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#1c5a84;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
+ d="m 27.363159,3.1998013 -12.363157,-14.9334003 0,25.600115 12.363157,-10.6667147 z"
|
||||||
|
+ id="path4327"
|
||||||
|
+ inkscape:path-effect="#path-effect4329"
|
||||||
|
+ inkscape:original-d="m 27.363159,3.1998013 -12.363157,-14.9334003 0,25.600115 z"
|
||||||
|
+ inkscape:connector-curvature="0"
|
||||||
|
+ sodipodi:nodetypes="cccc" />
|
||||||
|
+ <path
|
||||||
|
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#1c5a84;fill-opacity:1;fill-rule:nonzero;stroke:#1b5882;stroke-width:4.26492119;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||||
|
+ d="m 34.184211,-141.86752 12.789473,0 0,145.0673213 -12.789473,0 c -9.447157,0 -17.05263,-7.6117677 -17.05263,-17.0667433 l 0,-110.933838 c 0,-9.45497 7.605473,-17.06674 17.05263,-17.06674 z"
|
||||||
|
+ id="rect4333"
|
||||||
|
+ inkscape:connector-curvature="0"
|
||||||
|
+ sodipodi:nodetypes="sccssss" />
|
||||||
|
+ <rect
|
||||||
|
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:url(#linearGradient3469);stroke-width:4.26492119;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||||
|
+ id="rect3451"
|
||||||
|
+ width="149.21051"
|
||||||
|
+ height="136.53395"
|
||||||
|
+ x="21.394737"
|
||||||
|
+ y="-137.60083"
|
||||||
|
+ ry="12.800057"
|
||||||
|
+ rx="14.921052" />
|
||||||
|
+ <rect
|
||||||
|
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient4388);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50196078;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
+ id="rect4380"
|
||||||
|
+ width="4.2631574"
|
||||||
|
+ height="140.80063"
|
||||||
|
+ x="49.105263"
|
||||||
|
+ y="-139.73418" />
|
||||||
|
+ <path
|
||||||
|
+ sodipodi:nodetypes="cccccc"
|
||||||
|
+ inkscape:connector-curvature="0"
|
||||||
|
+ id="path4245"
|
||||||
|
+ d="m 125.8421,13.866516 25.57894,0 0,34.133487 -12.78947,-12.800058 -12.78947,12.800058 z"
|
||||||
|
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#363636;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50196078;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
+ <path
|
||||||
|
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient4230);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50196078;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
+ d="m 125.8421,9.5998301 25.57894,0 0,34.1334869 L 138.63157,30.93326 125.8421,43.733317 Z"
|
||||||
|
+ id="rect3421"
|
||||||
|
+ inkscape:connector-curvature="0"
|
||||||
|
+ sodipodi:nodetypes="cccccc" />
|
||||||
|
+ <path
|
||||||
|
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:0.50196078;fill-rule:evenodd;stroke:none;stroke-width:1.41732287;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
+ d="m 110.50011,-118 a 46.500106,46.14368 0 0 0 -46.500112,46.143686 46.500106,46.14368 0 0 0 0.08636,2.617885 46.500106,46.14368 0 0 1 46.413622,-44.366931 46.500106,46.14368 0 0 1 46.41362,43.525797 A 46.500106,46.14368 0 0 0 157,-71.856314 46.500106,46.14368 0 0 0 110.49988,-118 Z m 7.24835,23.749936 c -1.80279,-0.24566 -3.67059,0.02197 -5.3368,0.746737 -1.66616,0.725862 -3.12251,1.915797 -4.16043,3.398987 -1.03798,1.483146 -1.65253,3.252734 -1.75589,5.055547 -0.0558,0.972181 0.07,1.938034 0.30291,2.88398 0.27723,-1.261481 0.71089,-2.484245 1.45316,-3.544889 1.03792,-1.483191 2.49426,-2.673126 4.16043,-3.398989 1.6662,-0.725862 3.534,-0.992353 5.33679,-0.746737 2.52598,0.344102 4.89948,1.697605 6.4699,3.690792 l 25.17025,0 -22.08238,-3.012742 c -0.26483,-0.499143 -0.64223,-0.927489 -0.97738,-1.381894 l -2.11049,0 c -1.57042,-1.993188 -3.94392,-3.346648 -6.4699,-3.690792 z m -34.86645,7.132672 c -0.699184,2.0831 -0.853831,4.329155 -0.510305,6.497557 0.119128,-0.722654 0.284315,-1.434234 0.518985,-2.128674 l 27.87757,15.509992 -27.88625,-19.878875 z m 21.80558,1.313248 c -0.24313,1.277916 -0.29228,2.591299 -0.11248,3.87963 0.33569,2.407513 1.42959,4.700415 3.08792,6.488988 -0.86168,-1.590464 -1.27114,-3.415819 -1.16773,-5.218632 0.009,-0.175345 0.0841,-0.340584 0.10362,-0.515006 -0.95714,-1.389453 -1.60367,-2.979739 -1.91155,-4.63498 z m -29.49506,0.575083 c -0.162086,1.411205 -0.212129,2.839242 -0.03543,4.248733 0.42293,3.353505 1.851856,6.555919 4.013402,9.166949 -0.01329,-0.533157 -0.02214,-1.065084 0.02657,-1.596528 l 4.532387,1.261745 c -0.03543,-0.06899 -0.05226,-0.145024 -0.08636,-0.214459 -1.542653,-0.940672 -2.969586,-2.070488 -4.160431,-3.424696 -2.321552,-2.63999 -3.821911,-5.968927 -4.290189,-9.441613 z m 46.11089,9.544623 c -0.003,0.01758 -0.004,0.03515 -0.009,0.05142 -0.61837,3.860952 0.54219,7.763345 1.69534,11.501555 0.73055,2.368314 1.41658,4.798723 1.71258,7.244294 0.009,-0.04922 0.0266,-0.09624 0.0354,-0.145901 0.58156,-3.866577 -0.59409,-7.754776 -1.74721,-11.492986 -0.72159,-2.339264 -1.39801,-4.741592 -1.68666,-7.158467 z m -42.106123,6.669168 c -0.237372,2.754382 0.3069,5.572047 1.556913,8.042537 1.250055,2.470489 3.202351,4.586549 5.570359,6.042624 3.515187,2.161503 7.942971,2.799779 11.936401,1.733816 -4.00025,0.02637 -7.964672,-1.935881 -10.336267,-5.132759 -0.07927,-0.10679 -0.140385,-0.225444 -0.216115,-0.334871 -0.462167,-0.22149 -0.947273,-0.392441 -1.383931,-0.660954 -2.367963,-1.456075 -4.320259,-3.572135 -5.570315,-6.042625 -0.568896,-1.124324 -0.967113,-2.332761 -1.236903,-3.562029 l -0.320186,-0.0857 z m 6.314183,0.09448 c 0.166958,1.615337 0.670178,3.191604 1.435835,4.62641 l 21.943975,3.562073 -18.899325,-5.27875 c -1.456693,-0.701868 -2.782832,-1.661173 -3.909595,-2.815293 l -0.57089,-0.09448 z m 45.05564,14.102345 c -0.45194,2.690132 -1.61346,5.268685 -3.28685,7.441701 -2.25047,2.922389 -5.37727,5.129771 -8.79663,6.549019 -2.55347,1.059855 -5.28223,1.658887 -8.04407,1.836826 -2.5072,0.6236 -5.10296,0.848209 -7.68084,0.66091 l -3.390615,7.982462 0,3.235903 A 46.500106,46.14368 0 0 0 99.809201,-27 l 3.451149,-8.128363 c 5.04783,1.142386 10.44685,0.677873 15.22325,-1.30468 3.41936,-1.419248 6.54615,-3.62663 8.79663,-6.549019 2.25047,-2.92239 3.58941,-6.571652 3.49446,-10.248425 -0.0133,-0.539309 -0.13817,-1.057964 -0.20771,-1.587913 z"
|
||||||
|
+ id="path4301"
|
||||||
|
+ inkscape:connector-curvature="0" />
|
||||||
|
+ <path
|
||||||
|
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:0.51020406;fill-rule:evenodd;stroke:none;stroke-width:1.41732287;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
+ d="m 156.91333,-68 c -0.96122,23.352824 -21.44904,41.828094 -46.41342,41.854254 -3.60184,-0.01658 -7.18951,-0.423488 -10.690817,-1.21458 l -0.441085,0.987849 0,-1.09311 c -19.795942,-4.572965 -34.10029,-20.685325 -35.281476,-39.740875 -0.03986,0.558141 -0.06909,1.116947 -0.08636,1.676125 C 64.000172,-41.489195 84.818891,-22 110.50009,-22 136.18128,-22 157,-41.489195 157,-65.530337 156.996,-66.35418 156.969,-67.17769 156.9136,-68 Z"
|
||||||
|
+ id="path4320"
|
||||||
|
+ inkscape:connector-curvature="0"
|
||||||
|
+ sodipodi:nodetypes="cccccccscc" />
|
||||||
|
+ <path
|
||||||
|
+ id="path5170"
|
||||||
|
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:0.16326533;fill-rule:evenodd;stroke:none;stroke-width:1.41732287;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
+ d="m 116.54149,-96.833799 c -1.98945,0.0088 -3.97672,0.48378 -5.72702,1.379709 -2.15419,1.102683 -3.94018,2.839363 -5.04652,4.906967 -1.1063,2.067649 -1.52799,4.457156 -1.19213,6.752812 0.33569,2.295657 1.42768,4.487165 3.086,6.192649 -0.86162,-1.516592 -1.26989,-3.260796 -1.16648,-4.979831 0.10318,-1.719081 0.71835,-3.407977 1.75628,-4.82227 1.03796,-1.414247 2.49567,-2.549359 4.16183,-3.241523 1.6662,-0.692165 3.53594,-0.939049 5.33872,-0.704836 2.52592,0.328239 4.89763,1.618408 6.46805,3.519032 l 25.16438,0 -22.07945,-2.879317 c -1.83679,-3.300396 -5.47113,-5.644407 -9.38912,-6.055192 -0.4565,-0.04796 -0.91548,-0.0704 -1.37454,-0.0682 z m -39.569522,4.06934 c -1.617356,3.023461 -2.257062,6.507336 -1.812523,9.869817 0.444584,3.36248 1.971597,6.590013 4.326219,9.143243 1.317719,1.428813 2.896059,2.634809 4.634801,3.576893 l -4.923676,-1.309924 c -0.237371,2.626361 0.308671,5.312208 1.558589,7.667925 1.250006,2.355716 3.200611,4.373776 5.568608,5.762195 3.515171,2.061093 7.941653,2.677268 11.935065,1.660824 -4.000276,0.02641 -7.964549,-1.852928 -10.336089,-4.901291 -1.338178,-1.720093 -2.179473,-3.78268 -2.409935,-5.907397 l 23.377543,3.617681 -18.900044,-5.028409 c -1.512045,-0.694716 -2.893668,-1.644764 -4.046644,-2.802316 -1.594238,-1.600588 -2.752441,-3.587056 -3.333424,-5.7167 -0.66517,-2.438481 -0.566546,-5.058548 0.279443,-7.446297 l 27.876339,14.787653 -33.79445,-22.973897 z m 45.460302,11.547669 c -0.55166,1.082663 -0.9354,2.24158 -1.13482,3.428612 -0.61836,3.681569 0.5387,7.400712 1.69185,10.965284 1.15311,3.564529 2.32854,7.273684 1.74698,10.960621 -0.43444,2.754664 -1.85513,5.333284 -3.84293,7.38738 -1.98781,2.054052 -4.52444,3.59766 -7.25005,4.649084 -4.49136,1.73272 -9.54258,2.139765 -14.278968,1.150821 l 0,12.256112 3.894828,-8.748477 c 5.04777,1.089353 10.45163,0.648692 15.22806,-1.241724 3.41934,-1.353307 6.53962,-3.460291 8.79008,-6.2469 2.25042,-2.786608 3.59382,-6.269252 3.49887,-9.775217 -0.11425,-4.213748 -2.21897,-8.118836 -4.25576,-11.867548 -2.03683,-3.748668 -4.10045,-7.68394 -4.12308,-11.899052 -0.002,-0.34012 0.009,-0.679845 0.0354,-1.018996 z m 34.56755,11.216788 A 46.499907,44.000001 0 0 1 110.49991,-26 46.499907,44.000001 0 0 1 63.999998,-70.000002 46.499907,44.000001 0 0 1 110.49991,-114 a 46.499907,44.000001 0 0 1 46.49991,43.999998 z"
|
||||||
|
+ inkscape:connector-curvature="0" />
|
||||||
|
+ </g>
|
||||||
|
+</svg>
|
||||||
1
debian/patches/series
vendored
Normal file
1
debian/patches/series
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
add-manual.patch
|
||||||
1
debian/pcmanfm-qt-l10n.install
vendored
Normal file
1
debian/pcmanfm-qt-l10n.install
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
usr/share/pcmanfm-qt/translations/
|
||||||
8
debian/pcmanfm-qt.install
vendored
Normal file
8
debian/pcmanfm-qt.install
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
etc/xdg/autostart/lxqt-desktop.desktop
|
||||||
|
icons/lubuntu-manual.svg usr/share/icons/hicolor/scalable/apps/
|
||||||
|
usr/bin/pcmanfm-qt
|
||||||
|
usr/share/applications/pcmanfm-qt-desktop-pref.desktop
|
||||||
|
usr/share/applications/pcmanfm-qt.desktop
|
||||||
|
usr/share/icons/hicolor/scalable/apps/pcmanfm-qt.svg
|
||||||
|
usr/share/man/man1/pcmanfm-qt.1
|
||||||
|
usr/share/pcmanfm-qt/lxqt/settings.conf
|
||||||
6
debian/pcmanfm-qt.lintian-overrides
vendored
Normal file
6
debian/pcmanfm-qt.lintian-overrides
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# This is expected
|
||||||
|
pcmanfm-qt: desktop-entry-lacks-keywords-entry [usr/share/applications/pcmanfm-qt-desktop-pref.desktop]
|
||||||
|
pcmanfm-qt: desktop-entry-lacks-keywords-entry [usr/share/applications/pcmanfm-qt.desktop]
|
||||||
|
|
||||||
|
# False positive
|
||||||
|
pcmanfm-qt: hardening-no-fortify-functions [usr/bin/pcmanfm-qt]
|
||||||
14
debian/rules
vendored
Executable file
14
debian/rules
vendored
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/make -f
|
||||||
|
# export DH_VERBOSE=1
|
||||||
|
|
||||||
|
export LC_ALL=C.UTF-8
|
||||||
|
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||||
|
|
||||||
|
%:
|
||||||
|
dh ${@} --buildsystem cmake
|
||||||
|
|
||||||
|
override_dh_auto_configure:
|
||||||
|
dh_auto_configure --\
|
||||||
|
-DPULL_TRANSLATIONS=OFF\
|
||||||
|
-DUPDATE_TRANSLATIONS=OFF\
|
||||||
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||||
1
debian/source/format
vendored
Normal file
1
debian/source/format
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
3.0 (quilt)
|
||||||
5
debian/source/lintian-overrides
vendored
Normal file
5
debian/source/lintian-overrides
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# We add this via quilt patch
|
||||||
|
pcmanfm-qt source: superfluous-file-pattern icons/lubuntu-manual.svg [debian/copyright:*]
|
||||||
|
|
||||||
|
# These are expected
|
||||||
|
pcmanfm-qt source: very-long-line-length-in-source-file * > 512 [debian/patches/add-manual.patch:*]
|
||||||
1
debian/source/options
vendored
Normal file
1
debian/source/options
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
tar-ignore = .gitignore
|
||||||
6
debian/upstream/metadata
vendored
Normal file
6
debian/upstream/metadata
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
Bug-Database: https://github.com/lxqt/pcmanfm-qt/issues
|
||||||
|
Bug-Submit: https://github.com/lxqt/pcmanfm-qt/issues/new
|
||||||
|
Changelog: https://github.com/lxqt/pcmanfm-qt/blob/master/CHANGELOG
|
||||||
|
Repository: https://github.com/lxqt/pcmanfm-qt.git
|
||||||
|
Repository-Browse: https://github.com/lxqt/pcmanfm-qt
|
||||||
|
|
||||||
52
debian/upstream/signing-key.asc
vendored
Normal file
52
debian/upstream/signing-key.asc
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
|
||||||
|
mQINBF6cxrwBEADfl3ydxNfLBbWGPesXty2baQgixZ3D6aCxadI2kX+aikmT8rd0
|
||||||
|
ttDKN18cXV52Ssxnj0qhgf4hwnu/b0be6BzqSEyGM+UQR3X2CYpxrMakfW32Q18K
|
||||||
|
X5ec0RPR2ucBq9G0r9t6FYC8FkJ4uQUU3xxrLW3z302S0Makjgzm8BV9WrFQ7oFF
|
||||||
|
uJQj0BHbHYC4RyaZb2AfxY4Y92BPGTjtGekWqgw6vEXCCnvAbGYVQzvxZt3nw21/
|
||||||
|
1YmV4g7xhGFQPbOf9v3ejFUJeJIGzuJf5NAh7kvfCdUBAGYH0gnj0GpOve4ftnaG
|
||||||
|
sAId2CQwm3oYF4Tu7yBPTOBpkaKkNaT+UdwTyeKERuCZ9ocZWX++/YF9ItRkJ5mM
|
||||||
|
zoP1GluWn2atNWpRh/K97gyAGgr2fSmrAA4d1JrVbMujZAHoHAOKwJKqX9jPziPZ
|
||||||
|
BFHfhcIOzG3ZhXAuumHsd7uwfPBVt20g+G+cOjBghbSSu9EOtMkAZl1g3ybvZixu
|
||||||
|
Jtxa5exZWEmU7vtytEb8eq9Dj5XcGoTDbErE2RpJ/20HPzhyRKg9RN4iGS+0OiHS
|
||||||
|
oRbDi5IEOizvQjp2bsBmfa3rsoDSOqF2pevp+u8I56I6bU1GFpxxNC5IGvgo2Q79
|
||||||
|
quz0oIk5hs3eLlUdEYsLGwR6pWJaJyf36vuDsq7iLrLyvHI5irAowO4r1QARAQAB
|
||||||
|
tCVQZWRyYW0gUG91cmFuZyA8dHN1amFuMjAwMEBnbWFpbC5jb20+iQJOBBMBCAA4
|
||||||
|
FiEEGd/fOleb1QnbtXLYvnkwB60i334FAl6cxrwCGwMFCwkIBwIGFQoJCAsCBBYC
|
||||||
|
AwECHgECF4AACgkQvnkwB60i335f9RAAgRpn8gUa/l10UkVAnpM2Cz0MuNMwwCOq
|
||||||
|
IfVnuZuPBtYYiTU5Su++/aPZe3fF5B4v61F+XjNi7qeVL2t52X3jZ/iIx9Syasb+
|
||||||
|
vDAIfQ5t6lKXvOptWxf6vteOg6CHbXwpGHbPjUkUS2vQwRikjBnR0SnkrMoXtgSX
|
||||||
|
amPFqsitNrOhEJfeDfo0NzKESZuliWrCFt2v8c5q18G8cCZAvPLBlGuwRl58cDep
|
||||||
|
3EIibMI/9MUSJbKoiHlK+LcHtG7BQTNis/e7Pe1PkRmExfhxe1lNajtOx8FO72Tq
|
||||||
|
B6zY6drippM9VaIc1M+zp9BRpsFu8whOmapCqlXHRgAK8xTdQRIGInQFqLWPOxSC
|
||||||
|
f0B6N+EvQvgkyFQ1rW+u91OJBma46uKkhrwf+mDttVRncaIAkgE6e6pqm18yIPFk
|
||||||
|
D42rt/yHcOl+2qkcJS3gPcg5UvlCzqOwg1rKZQIk+TcPuDx3r2UghDEYZN9X6vw3
|
||||||
|
zCBufr7ygZNf4tkbnVARFWTR4GzyCseFkWgOVZL9DccAhs8NeMy1WLkUzB75adeR
|
||||||
|
3LONmEL7xOI8FuknKY4e6EcWhmstNIDgXfRe0hwO0VBdW3unoZC/K2ZM/ZuZyMdK
|
||||||
|
TFjvYJrNewmymKge68wo0054bGZn8oz17i2AosJz7kW+ITsxmxhVcpfl4bav9Neq
|
||||||
|
RpQwhnhK9bC5Ag0EXpzGvAEQANbeRHFbpgQVIqV9WVOVnTj4FIqrTPTPKKa02vJA
|
||||||
|
7tGpgFapgvjdxnMxJfV6wuwOBUUFLR7DrXlV8EVFAYc5qTIeSQXvJsWw6gQ3+f0D
|
||||||
|
z13oGOhZPBIzIKnV/MZI/jhIio8kSPWAuM5hR2X9Hvw3/CLo+H+hZZ6cFYoCxrQS
|
||||||
|
tTzcKMkdQizLLa+WNbqUSxg6I/P5k/smUDY9gKW7RtI5t/PupA3WTnsVD6CYWa3Q
|
||||||
|
c1O/1mUgqT6nQ5N9KCPpjZQRT6D6eIMmePtS85z4PPeYMJxPsKRYWPGRxKhCSdZl
|
||||||
|
/0wsC8aRtmwYT729e0ZgTAmUnj+rQp5hboF/ZPFjIoXR9G+0HnoY0a/nqVO4lUON
|
||||||
|
AV25GnMFGVyiHHlbH/0gboywwnzEg8BZbk+Z/61oOzBIW09sfG8fn8bsbkpL+nHf
|
||||||
|
Mi/Vauge6wSfw7I5AfSiwrSDNHmKVsu39koWV6JGxEeFr2MffF+CuaoJCNOr/ZII
|
||||||
|
SYR5ku3Y/lMKyUH1Oas0RWzFrdRcInqYK90A0x083zP4V445MvCwbRPzQAkm9wOP
|
||||||
|
kILLhE5FW+9/O0/9bpx4joJUDLV4d3hFZy7GSHKiZUs1QW6BV75JQKqoi+cVt+/L
|
||||||
|
+o1S8CMNekjqdC2mWRosM3doo51zT/FWNzQA1QcoZP2hORJDfw66y+4wPq6o8y1W
|
||||||
|
jR35ABEBAAGJAjYEGAEIACAWIQQZ3986V5vVCdu1cti+eTAHrSLffgUCXpzGvAIb
|
||||||
|
DAAKCRC+eTAHrSLffgbJD/4qW5YOo/BayBhaUh2L7VP7JNlECb/2xNNOFKI1NjNr
|
||||||
|
nOmgSJLzf74Uhmt5W+iVjmJBHrDceprIPkizmPrn90kIsPIMtHIDNxzUgKZHbnza
|
||||||
|
j1vZyAeC+JV79X1hOVpprj1TJwy65lpxXNyYnGqeIOgyFokn9fOHXv8aMQwpNuUr
|
||||||
|
bdUJ1C75jYrvwy/NR1DczIFFYgsbkDGDtjVBjyMc5JAgvUBz37/iVPJfWP6dKVnf
|
||||||
|
abRnUVzHgvgK7bnab00SA1TiWvjHURGjo+5rnRtv8X/AgStc2Phjq68TMIgMn0F2
|
||||||
|
kjUVvfQotNqzo9madNshvUDmsGtAzKh4e0dS1ear7u3nRp4Z7fqSrTEtXKNbEPwZ
|
||||||
|
wdWrWmmQLacNQBSe/FtcMzGF6xIVr4lnrL0bFjqBdQpdTC7vns3QSKk8/GFiEfpv
|
||||||
|
kzXrDbGV7jX2OWDjNHKcmXX2+E1CsNaJgS7zOgZw5jvbvlTLJUwyYNlM1VLI2OFW
|
||||||
|
Oa86l8pqli+B7rpTbsAE9Ut8qUaWjm87oUNSJbaKgqNnMaE+b/8VJaEeWHgQJwsD
|
||||||
|
bJSJ/O/vzlRtDjOJ1JDlMRLs7TnOFeUh5pgwyaJoidYbJEiGlMGJbI6BjwhDTBFO
|
||||||
|
NLJtd3SsRjc7ICtGdCvej59IvCDTjxtkhx5okF03APi1aXpHQrE18/arFD7BpoGO
|
||||||
|
sw==
|
||||||
|
=gSIv
|
||||||
|
-----END PGP PUBLIC KEY BLOCK-----
|
||||||
5
debian/watch
vendored
Normal file
5
debian/watch
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
version=4
|
||||||
|
opts="searchmode=plain, \
|
||||||
|
pgpsigurlmangle=s/$/.asc/, \
|
||||||
|
uversionmangle=s/(\d+\.\d+\.\d+).*/$1/" \
|
||||||
|
https://api.github.com/repos/lxqt/@PACKAGE@/releases https:\/\/github.com\/lxqt\/@PACKAGE@\/releases\/download\/@ANY_VERSION@\/@PACKAGE@-@ANY_VERSION@.tar.xz
|
||||||
@ -1,147 +0,0 @@
|
|||||||
project(fm-qt)
|
|
||||||
|
|
||||||
set(LIBRARY_NAME "fm-qt5")
|
|
||||||
set(QTX_INCLUDE_DIRS "")
|
|
||||||
set(QTX_LIBRARIES Qt5::Widgets Qt5::X11Extras)
|
|
||||||
set(libfm_TRANSLATION_TEMPLATE "lib${PROJECT_NAME}")
|
|
||||||
|
|
||||||
include_directories(
|
|
||||||
${QTX_INCLUDE_DIRS}
|
|
||||||
${LIBFM_INCLUDE_DIRS}
|
|
||||||
"${LIBFM_INCLUDEDIR}/libfm" # to workaround incorrect #include in fm-actions.
|
|
||||||
${LIBMENUCACHE_INCLUDE_DIRS}
|
|
||||||
${SYSTEM_LIBS_INCLUDE_DIRS}
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
|
||||||
)
|
|
||||||
|
|
||||||
link_directories(
|
|
||||||
${LIBFM_LIBRARY_DIRS}
|
|
||||||
${LIBMENUCACHE_LIBRARY_DIRS}
|
|
||||||
${SYSTEM_LIBS_LIBRARY_DIRS}
|
|
||||||
)
|
|
||||||
|
|
||||||
set(libfm_SRCS
|
|
||||||
libfmqt.cpp
|
|
||||||
bookmarkaction.cpp
|
|
||||||
sidepane.cpp
|
|
||||||
icontheme.cpp
|
|
||||||
filelauncher.cpp
|
|
||||||
foldermodel.cpp
|
|
||||||
foldermodelitem.cpp
|
|
||||||
cachedfoldermodel.cpp
|
|
||||||
proxyfoldermodel.cpp
|
|
||||||
folderview.cpp
|
|
||||||
folderitemdelegate.cpp
|
|
||||||
createnewmenu.cpp
|
|
||||||
filemenu.cpp
|
|
||||||
foldermenu.cpp
|
|
||||||
filepropsdialog.cpp
|
|
||||||
applaunchcontext.cpp
|
|
||||||
placesview.cpp
|
|
||||||
placesmodel.cpp
|
|
||||||
placesmodelitem.cpp
|
|
||||||
dirtreeview.cpp
|
|
||||||
dirtreemodel.cpp
|
|
||||||
dirtreemodelitem.cpp
|
|
||||||
dnddest.cpp
|
|
||||||
mountoperation.cpp
|
|
||||||
mountoperationpassworddialog.cpp
|
|
||||||
mountoperationquestiondialog.cpp
|
|
||||||
fileoperation.cpp
|
|
||||||
fileoperationdialog.cpp
|
|
||||||
renamedialog.cpp
|
|
||||||
pathedit.cpp
|
|
||||||
colorbutton.cpp
|
|
||||||
fontbutton.cpp
|
|
||||||
browsehistory.cpp
|
|
||||||
utilities.cpp
|
|
||||||
dndactionmenu.cpp
|
|
||||||
editbookmarksdialog.cpp
|
|
||||||
thumbnailloader.cpp
|
|
||||||
path.cpp
|
|
||||||
execfiledialog.cpp
|
|
||||||
appchoosercombobox.cpp
|
|
||||||
appmenuview.cpp
|
|
||||||
appchooserdialog.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
set(libfm_UIS
|
|
||||||
file-props.ui
|
|
||||||
file-operation-dialog.ui
|
|
||||||
rename-dialog.ui
|
|
||||||
mount-operation-password.ui
|
|
||||||
edit-bookmarks.ui
|
|
||||||
exec-file.ui
|
|
||||||
app-chooser-dialog.ui
|
|
||||||
)
|
|
||||||
|
|
||||||
qt5_wrap_ui(libfm_UIS_H ${libfm_UIS})
|
|
||||||
|
|
||||||
# add translation for libfm-qt
|
|
||||||
lxqt_translate_ts(QM_FILES
|
|
||||||
UPDATE_TRANSLATIONS ${UPDATE_TRANSLATIONS}
|
|
||||||
SOURCES ${libfm_SRCS} ${libfm_UIS}
|
|
||||||
TEMPLATE ${libfm_TRANSLATION_TEMPLATE}
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library(${LIBRARY_NAME} SHARED
|
|
||||||
${libfm_SRCS}
|
|
||||||
${libfm_UIS_H}
|
|
||||||
${QM_FILES}
|
|
||||||
)
|
|
||||||
|
|
||||||
set_property(
|
|
||||||
TARGET ${LIBRARY_NAME} APPEND
|
|
||||||
PROPERTY COMPILE_DEFINITIONS
|
|
||||||
LIBFM_QT_COMPILATION=1
|
|
||||||
LIBFM_DATA_DIR="${CMAKE_INSTALL_FULL_DATADIR}/libfm-qt"
|
|
||||||
)
|
|
||||||
|
|
||||||
# only turn on custom actions support if it is enabled in libfm.
|
|
||||||
if(EXISTS ${LIBFM_INCLUDEDIR}/libfm/fm-actions.h)
|
|
||||||
set_property(TARGET ${LIBRARY_NAME} APPEND PROPERTY COMPILE_DEFINITIONS CUSTOM_ACTIONS)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
target_link_libraries(${LIBRARY_NAME}
|
|
||||||
${QTX_LIBRARIES}
|
|
||||||
${LIBFM_LIBRARIES}
|
|
||||||
${LIBMENUCACHE_LIBRARIES}
|
|
||||||
${SYSTEM_LIBS_LIBRARIES}
|
|
||||||
)
|
|
||||||
|
|
||||||
# set libtool soname
|
|
||||||
set_target_properties(${LIBRARY_NAME} PROPERTIES
|
|
||||||
VERSION ${LIBFM_QT_LIB_VERSION}
|
|
||||||
SOVERSION ${LIBFM_QT_LIB_SOVERSION}
|
|
||||||
)
|
|
||||||
|
|
||||||
# install include header files (FIXME: can we make this cleaner? should dir name be versioned?)
|
|
||||||
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
|
||||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
|
||||||
FILES_MATCHING PATTERN "*.h"
|
|
||||||
PATTERN "*_p.h" EXCLUDE # exclude private headers
|
|
||||||
)
|
|
||||||
|
|
||||||
# FIXME: add libtool version to the lib (soname) later.
|
|
||||||
# FIXME: only export public symbols
|
|
||||||
|
|
||||||
install(TARGETS ${LIBRARY_NAME}
|
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
||||||
PUBLIC_HEADER
|
|
||||||
)
|
|
||||||
|
|
||||||
# install a pkgconfig file for libfm-qt
|
|
||||||
set(REQUIRED_QT "Qt5Core >= 5.1 Qt5DBus >= 5.1")
|
|
||||||
configure_file(libfm-qt.pc.in lib${LIBRARY_NAME}.pc @ONLY)
|
|
||||||
# FreeBSD loves to install files to different locations
|
|
||||||
# http://www.freebsd.org/doc/handbook/dirstructure.html
|
|
||||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/lib${LIBRARY_NAME}.pc" DESTINATION libdata/pkgconfig)
|
|
||||||
else()
|
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/lib${LIBRARY_NAME}.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
install(FILES ${QM_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/libfm-qt/translations")
|
|
||||||
|
|
||||||
# prevent the generated files from being deleted during make cleaner
|
|
||||||
set_directory_properties(PROPERTIES CLEAN_NO_CUSTOM true)
|
|
||||||
@ -1,183 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>AppChooserDialog</class>
|
|
||||||
<widget class="QDialog" name="AppChooserDialog">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>432</width>
|
|
||||||
<height>387</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Choose an Application</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QFormLayout" name="formLayout">
|
|
||||||
<property name="fieldGrowthPolicy">
|
|
||||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
|
||||||
</property>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLabel" name="fileTypeHeader"/>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0" colspan="2">
|
|
||||||
<widget class="QTabWidget" name="tabWidget">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>1</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="currentIndex">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="tab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Installed Applications</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="Fm::AppMenuView" name="appMenuView"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="tab_2">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Custom Command</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QFormLayout" name="formLayout_2">
|
|
||||||
<item row="0" column="0" colspan="2">
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="text">
|
|
||||||
<string>Command line to execute:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0" colspan="2">
|
|
||||||
<widget class="QLineEdit" name="cmdLine"/>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="text">
|
|
||||||
<string>Application name:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QLineEdit" name="appName"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0" colspan="2">
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="text">
|
|
||||||
<string><b>These special codes can be used in the command line:</b>
|
|
||||||
<ul>
|
|
||||||
<li><b>%f</b>: Represents a single file name</li>
|
|
||||||
<li><b>%F</b>: Represents multiple file names</li>
|
|
||||||
<li><b>%u</b>: Represents a single URI of the file</li>
|
|
||||||
<li><b>%U</b>: Represents multiple URIs</li>
|
|
||||||
</ul></string>
|
|
||||||
</property>
|
|
||||||
<property name="textFormat">
|
|
||||||
<enum>Qt::RichText</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="0" colspan="2">
|
|
||||||
<widget class="QCheckBox" name="keepTermOpen">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Keep terminal window open after command execution</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0" colspan="2">
|
|
||||||
<widget class="QCheckBox" name="useTerminal">
|
|
||||||
<property name="text">
|
|
||||||
<string>Execute in terminal emulator</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0" colspan="2">
|
|
||||||
<widget class="QCheckBox" name="setDefault">
|
|
||||||
<property name="text">
|
|
||||||
<string>Set selected application as default action of this file type</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0" colspan="2">
|
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<customwidgets>
|
|
||||||
<customwidget>
|
|
||||||
<class>Fm::AppMenuView</class>
|
|
||||||
<extends>QTreeView</extends>
|
|
||||||
<header>appmenuview.h</header>
|
|
||||||
</customwidget>
|
|
||||||
</customwidgets>
|
|
||||||
<resources/>
|
|
||||||
<connections>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>accepted()</signal>
|
|
||||||
<receiver>AppChooserDialog</receiver>
|
|
||||||
<slot>accept()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>227</x>
|
|
||||||
<y>359</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>157</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>rejected()</signal>
|
|
||||||
<receiver>AppChooserDialog</receiver>
|
|
||||||
<slot>reject()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>295</x>
|
|
||||||
<y>365</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>286</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>useTerminal</sender>
|
|
||||||
<signal>toggled(bool)</signal>
|
|
||||||
<receiver>keepTermOpen</receiver>
|
|
||||||
<slot>setEnabled(bool)</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>72</x>
|
|
||||||
<y>260</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>79</x>
|
|
||||||
<y>282</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
</connections>
|
|
||||||
</ui>
|
|
||||||
@ -1,154 +0,0 @@
|
|||||||
/*
|
|
||||||
* <one line to give the library's name and an idea of what it does.>
|
|
||||||
* Copyright (C) 2014 <copyright holder> <email>
|
|
||||||
*
|
|
||||||
* 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 "appchoosercombobox.h"
|
|
||||||
#include "icontheme.h"
|
|
||||||
#include "appchooserdialog.h"
|
|
||||||
#include "utilities.h"
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
AppChooserComboBox::AppChooserComboBox(QWidget* parent):
|
|
||||||
QComboBox(parent),
|
|
||||||
defaultApp_(NULL),
|
|
||||||
appInfos_(NULL),
|
|
||||||
defaultAppIndex_(-1),
|
|
||||||
prevIndex_(0),
|
|
||||||
mimeType_(NULL),
|
|
||||||
blockOnCurrentIndexChanged_(false) {
|
|
||||||
|
|
||||||
// the new Qt5 signal/slot syntax cannot handle overloaded methods by default
|
|
||||||
// hence a type-casting is needed here. really ugly!
|
|
||||||
// reference: http://qt-project.org/forums/viewthread/21513
|
|
||||||
connect((QComboBox*)this, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &AppChooserComboBox::onCurrentIndexChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
AppChooserComboBox::~AppChooserComboBox() {
|
|
||||||
if(mimeType_)
|
|
||||||
fm_mime_type_unref(mimeType_);
|
|
||||||
if(defaultApp_)
|
|
||||||
g_object_unref(defaultApp_);
|
|
||||||
// delete GAppInfo objects stored for Combobox
|
|
||||||
if(appInfos_) {
|
|
||||||
g_list_foreach(appInfos_, (GFunc)g_object_unref, NULL);
|
|
||||||
g_list_free(appInfos_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppChooserComboBox::setMimeType(FmMimeType* mimeType) {
|
|
||||||
clear();
|
|
||||||
if(mimeType_)
|
|
||||||
fm_mime_type_unref(mimeType_);
|
|
||||||
|
|
||||||
mimeType_ = fm_mime_type_ref(mimeType);
|
|
||||||
if(mimeType_) {
|
|
||||||
const char* typeName = fm_mime_type_get_type(mimeType_);
|
|
||||||
defaultApp_ = g_app_info_get_default_for_type(typeName, FALSE);
|
|
||||||
appInfos_ = g_app_info_get_all_for_type(typeName);
|
|
||||||
int i = 0;
|
|
||||||
for(GList* l = appInfos_; l; l = l->next, ++i) {
|
|
||||||
GAppInfo* app = G_APP_INFO(l->data);
|
|
||||||
GIcon* gicon = g_app_info_get_icon(app);
|
|
||||||
QString name = QString::fromUtf8(g_app_info_get_name(app));
|
|
||||||
// QVariant data = qVariantFromValue<void*>(app);
|
|
||||||
// addItem(IconTheme::icon(gicon), name, data);
|
|
||||||
addItem(IconTheme::icon(gicon), name);
|
|
||||||
if(g_app_info_equal(app, defaultApp_))
|
|
||||||
defaultAppIndex_ = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// add "Other applications" item
|
|
||||||
insertSeparator(count());
|
|
||||||
addItem(tr("Customize"));
|
|
||||||
if(defaultAppIndex_ != -1)
|
|
||||||
setCurrentIndex(defaultAppIndex_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns the currently selected app.
|
|
||||||
GAppInfo* AppChooserComboBox::selectedApp() {
|
|
||||||
return G_APP_INFO(g_list_nth_data(appInfos_, currentIndex()));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AppChooserComboBox::isChanged() {
|
|
||||||
return (defaultAppIndex_ != currentIndex());
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppChooserComboBox::onCurrentIndexChanged(int index) {
|
|
||||||
if(index == -1 || index == prevIndex_ || blockOnCurrentIndexChanged_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// the last item is "Customize"
|
|
||||||
if(index == (count() - 1)) {
|
|
||||||
/* TODO: let the user choose an app or add custom actions here. */
|
|
||||||
QWidget* toplevel = topLevelWidget();
|
|
||||||
AppChooserDialog dlg(mimeType_, toplevel);
|
|
||||||
dlg.setWindowModality(Qt::WindowModal);
|
|
||||||
dlg.setCanSetDefault(false);
|
|
||||||
if(dlg.exec() == QDialog::Accepted) {
|
|
||||||
GAppInfo* app = dlg.selectedApp();
|
|
||||||
if(app) {
|
|
||||||
/* see if it's already in the list to prevent duplication */
|
|
||||||
GList* found = NULL;
|
|
||||||
for(found = appInfos_; found; found = found->next) {
|
|
||||||
if(g_app_info_equal(app, G_APP_INFO(found->data)))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// inserting new items or change current index will recursively trigger onCurrentIndexChanged.
|
|
||||||
// we need to block our handler to prevent recursive calls.
|
|
||||||
blockOnCurrentIndexChanged_ = true;
|
|
||||||
/* if it's already in the list, select it */
|
|
||||||
if(found) {
|
|
||||||
setCurrentIndex(g_list_position(appInfos_, found));
|
|
||||||
g_object_unref(app);
|
|
||||||
}
|
|
||||||
else { /* if it's not found, add it to the list */
|
|
||||||
appInfos_ = g_list_prepend(appInfos_, app);
|
|
||||||
GIcon* gicon = g_app_info_get_icon(app);
|
|
||||||
QString name = QString::fromUtf8(g_app_info_get_name(app));
|
|
||||||
insertItem(0, IconTheme::icon(gicon), name);
|
|
||||||
setCurrentIndex(0);
|
|
||||||
}
|
|
||||||
blockOnCurrentIndexChanged_ = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// block our handler to prevent recursive calls.
|
|
||||||
blockOnCurrentIndexChanged_ = true;
|
|
||||||
// restore to previously selected item
|
|
||||||
setCurrentIndex(prevIndex_);
|
|
||||||
blockOnCurrentIndexChanged_ = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
prevIndex_ = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* get a list of custom apps added with app-chooser.
|
|
||||||
* the returned GList is owned by the combo box and shouldn't be freed. */
|
|
||||||
const GList* AppChooserComboBox::customApps() {
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace Fm
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* <one line to give the library's name and an idea of what it does.>
|
|
||||||
* Copyright (C) 2014 <copyright holder> <email>
|
|
||||||
*
|
|
||||||
* 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_APPCHOOSERCOMBOBOX_H
|
|
||||||
#define FM_APPCHOOSERCOMBOBOX_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QComboBox>
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class LIBFM_QT_API AppChooserComboBox : public QComboBox {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
~AppChooserComboBox();
|
|
||||||
AppChooserComboBox(QWidget* parent);
|
|
||||||
|
|
||||||
void setMimeType(FmMimeType* mimeType);
|
|
||||||
|
|
||||||
FmMimeType* mimeType() {
|
|
||||||
return mimeType_;
|
|
||||||
}
|
|
||||||
|
|
||||||
GAppInfo* selectedApp();
|
|
||||||
// const GList* customApps();
|
|
||||||
|
|
||||||
bool isChanged();
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
|
||||||
void onCurrentIndexChanged(int index);
|
|
||||||
|
|
||||||
private:
|
|
||||||
FmMimeType* mimeType_;
|
|
||||||
GList* appInfos_; // applications used to open the file type
|
|
||||||
GAppInfo* defaultApp_; // default application used to open the file type
|
|
||||||
int defaultAppIndex_;
|
|
||||||
int prevIndex_;
|
|
||||||
bool blockOnCurrentIndexChanged_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_APPCHOOSERCOMBOBOX_H
|
|
||||||
@ -1,286 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2014 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
* Copyright 2012-2013 Andriy Grytsenko (LStranger) <andrej@rep.kiev.ua>
|
|
||||||
*
|
|
||||||
* 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 "appchooserdialog.h"
|
|
||||||
#include "ui_app-chooser-dialog.h"
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <gio/gdesktopappinfo.h>
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
AppChooserDialog::AppChooserDialog(FmMimeType* mimeType, QWidget* parent, Qt::WindowFlags f):
|
|
||||||
QDialog(parent, f),
|
|
||||||
mimeType_(NULL),
|
|
||||||
selectedApp_(NULL),
|
|
||||||
canSetDefault_(true),
|
|
||||||
ui(new Ui::AppChooserDialog()) {
|
|
||||||
ui->setupUi(this);
|
|
||||||
|
|
||||||
connect(ui->appMenuView, &AppMenuView::selectionChanged, this, &AppChooserDialog::onSelectionChanged);
|
|
||||||
connect(ui->tabWidget, &QTabWidget::currentChanged, this, &AppChooserDialog::onTabChanged);
|
|
||||||
|
|
||||||
if(!ui->appMenuView->isAppSelected())
|
|
||||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); // disable OK button
|
|
||||||
|
|
||||||
if(mimeType)
|
|
||||||
setMimeType(mimeType);
|
|
||||||
}
|
|
||||||
|
|
||||||
AppChooserDialog::~AppChooserDialog() {
|
|
||||||
delete ui;
|
|
||||||
if(mimeType_)
|
|
||||||
fm_mime_type_unref(mimeType_);
|
|
||||||
if(selectedApp_)
|
|
||||||
g_object_unref(selectedApp_);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AppChooserDialog::isSetDefault() {
|
|
||||||
return ui->setDefault->isChecked();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void on_temp_appinfo_destroy(gpointer data, GObject* objptr) {
|
|
||||||
char* filename = (char*)data;
|
|
||||||
if(g_unlink(filename) < 0)
|
|
||||||
g_critical("failed to remove %s", filename);
|
|
||||||
/* else
|
|
||||||
qDebug("temp file %s removed", filename); */
|
|
||||||
g_free(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GAppInfo* app_info_create_from_commandline(const char* commandline,
|
|
||||||
const char* application_name,
|
|
||||||
const char* bin_name,
|
|
||||||
const char* mime_type,
|
|
||||||
gboolean terminal, gboolean keep) {
|
|
||||||
GAppInfo* app = NULL;
|
|
||||||
char* dirname = g_build_filename(g_get_user_data_dir(), "applications", NULL);
|
|
||||||
const char* app_basename = strrchr(bin_name, '/');
|
|
||||||
|
|
||||||
if(app_basename)
|
|
||||||
app_basename++;
|
|
||||||
else
|
|
||||||
app_basename = bin_name;
|
|
||||||
if(g_mkdir_with_parents(dirname, 0700) == 0) {
|
|
||||||
char* filename = g_strdup_printf("%s/userapp-%s-XXXXXX.desktop", dirname, app_basename);
|
|
||||||
int fd = g_mkstemp(filename);
|
|
||||||
if(fd != -1) {
|
|
||||||
GString* content = g_string_sized_new(256);
|
|
||||||
g_string_printf(content,
|
|
||||||
"[" G_KEY_FILE_DESKTOP_GROUP "]\n"
|
|
||||||
G_KEY_FILE_DESKTOP_KEY_TYPE "=" G_KEY_FILE_DESKTOP_TYPE_APPLICATION "\n"
|
|
||||||
G_KEY_FILE_DESKTOP_KEY_NAME "=%s\n"
|
|
||||||
G_KEY_FILE_DESKTOP_KEY_EXEC "=%s\n"
|
|
||||||
G_KEY_FILE_DESKTOP_KEY_CATEGORIES "=Other;\n"
|
|
||||||
G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY "=true\n",
|
|
||||||
application_name,
|
|
||||||
commandline
|
|
||||||
);
|
|
||||||
if(mime_type)
|
|
||||||
g_string_append_printf(content,
|
|
||||||
G_KEY_FILE_DESKTOP_KEY_MIME_TYPE "=%s\n",
|
|
||||||
mime_type);
|
|
||||||
g_string_append_printf(content,
|
|
||||||
G_KEY_FILE_DESKTOP_KEY_TERMINAL "=%s\n",
|
|
||||||
terminal ? "true" : "false");
|
|
||||||
if(terminal)
|
|
||||||
g_string_append_printf(content, "X-KeepTerminal=%s\n",
|
|
||||||
keep ? "true" : "false");
|
|
||||||
close(fd); /* g_file_set_contents() may fail creating duplicate */
|
|
||||||
if(g_file_set_contents(filename, content->str, content->len, NULL)) {
|
|
||||||
char* fbname = g_path_get_basename(filename);
|
|
||||||
app = G_APP_INFO(g_desktop_app_info_new(fbname));
|
|
||||||
g_free(fbname);
|
|
||||||
/* if there is mime_type set then created application will be
|
|
||||||
saved for the mime type (see fm_choose_app_for_mime_type()
|
|
||||||
below) but if not then we should remove this temp. file */
|
|
||||||
if(!mime_type || !application_name[0])
|
|
||||||
/* save the name so this file will be removed later */
|
|
||||||
g_object_weak_ref(G_OBJECT(app), on_temp_appinfo_destroy,
|
|
||||||
g_strdup(filename));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
g_unlink(filename);
|
|
||||||
g_string_free(content, TRUE);
|
|
||||||
}
|
|
||||||
g_free(filename);
|
|
||||||
}
|
|
||||||
g_free(dirname);
|
|
||||||
return app;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static char* get_binary(const char* cmdline, gboolean* arg_found) {
|
|
||||||
/* see if command line contains %f, %F, %u, or %U. */
|
|
||||||
const char* p = strstr(cmdline, " %");
|
|
||||||
if(p) {
|
|
||||||
if(!strchr("fFuU", *(p + 2)))
|
|
||||||
p = NULL;
|
|
||||||
}
|
|
||||||
if(arg_found)
|
|
||||||
*arg_found = (p != NULL);
|
|
||||||
if(p)
|
|
||||||
return g_strndup(cmdline, p - cmdline);
|
|
||||||
else
|
|
||||||
return g_strdup(cmdline);
|
|
||||||
}
|
|
||||||
|
|
||||||
GAppInfo* AppChooserDialog::customCommandToApp() {
|
|
||||||
GAppInfo* app = NULL;
|
|
||||||
QByteArray cmdline = ui->cmdLine->text().toLocal8Bit();
|
|
||||||
QByteArray app_name = ui->appName->text().toUtf8();
|
|
||||||
if(!cmdline.isEmpty()) {
|
|
||||||
gboolean arg_found = FALSE;
|
|
||||||
char* bin1 = get_binary(cmdline.constData(), &arg_found);
|
|
||||||
qDebug("bin1 = %s", bin1);
|
|
||||||
/* see if command line contains %f, %F, %u, or %U. */
|
|
||||||
if(!arg_found) { /* append %f if no %f, %F, %u, or %U was found. */
|
|
||||||
cmdline += " %f";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: is there any better way to do this? */
|
|
||||||
/* We need to ensure that no duplicated items are added */
|
|
||||||
if(mimeType_) {
|
|
||||||
MenuCache* menu_cache;
|
|
||||||
/* see if the command is already in the list of known apps for this mime-type */
|
|
||||||
GList* apps = g_app_info_get_all_for_type(fm_mime_type_get_type(mimeType_));
|
|
||||||
GList* l;
|
|
||||||
for(l = apps; l; l = l->next) {
|
|
||||||
GAppInfo* app2 = G_APP_INFO(l->data);
|
|
||||||
const char* cmd = g_app_info_get_commandline(app2);
|
|
||||||
char* bin2 = get_binary(cmd, NULL);
|
|
||||||
if(g_strcmp0(bin1, bin2) == 0) {
|
|
||||||
app = G_APP_INFO(g_object_ref(app2));
|
|
||||||
qDebug("found in app list");
|
|
||||||
g_free(bin2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
g_free(bin2);
|
|
||||||
}
|
|
||||||
g_list_foreach(apps, (GFunc)g_object_unref, NULL);
|
|
||||||
g_list_free(apps);
|
|
||||||
if(app)
|
|
||||||
goto _out;
|
|
||||||
|
|
||||||
/* see if this command can be found in menu cache */
|
|
||||||
menu_cache = menu_cache_lookup("applications.menu");
|
|
||||||
if(menu_cache) {
|
|
||||||
MenuCacheDir* root_dir = menu_cache_dup_root_dir(menu_cache);
|
|
||||||
if(root_dir) {
|
|
||||||
GSList* all_apps = menu_cache_list_all_apps(menu_cache);
|
|
||||||
GSList* l;
|
|
||||||
for(l = all_apps; l; l = l->next) {
|
|
||||||
MenuCacheApp* ma = MENU_CACHE_APP(l->data);
|
|
||||||
const char* exec = menu_cache_app_get_exec(ma);
|
|
||||||
char* bin2;
|
|
||||||
if(exec == NULL) {
|
|
||||||
g_warning("application %s has no Exec statement", menu_cache_item_get_id(MENU_CACHE_ITEM(ma)));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
bin2 = get_binary(exec, NULL);
|
|
||||||
if(g_strcmp0(bin1, bin2) == 0) {
|
|
||||||
app = G_APP_INFO(g_desktop_app_info_new(menu_cache_item_get_id(MENU_CACHE_ITEM(ma))));
|
|
||||||
qDebug("found in menu cache");
|
|
||||||
menu_cache_item_unref(MENU_CACHE_ITEM(ma));
|
|
||||||
g_free(bin2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
menu_cache_item_unref(MENU_CACHE_ITEM(ma));
|
|
||||||
g_free(bin2);
|
|
||||||
}
|
|
||||||
g_slist_free(all_apps);
|
|
||||||
menu_cache_item_unref(MENU_CACHE_ITEM(root_dir));
|
|
||||||
}
|
|
||||||
menu_cache_unref(menu_cache);
|
|
||||||
}
|
|
||||||
if(app)
|
|
||||||
goto _out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: g_app_info_create_from_commandline force the use of %f or %u, so this is not we need */
|
|
||||||
app = app_info_create_from_commandline(cmdline.constData(), app_name.constData(), bin1,
|
|
||||||
mimeType_ ? fm_mime_type_get_type(mimeType_) : NULL,
|
|
||||||
ui->useTerminal->isChecked(), ui->keepTermOpen->isChecked());
|
|
||||||
_out:
|
|
||||||
g_free(bin1);
|
|
||||||
}
|
|
||||||
return app;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppChooserDialog::accept() {
|
|
||||||
QDialog::accept();
|
|
||||||
|
|
||||||
if(ui->tabWidget->currentIndex() == 0) {
|
|
||||||
selectedApp_ = ui->appMenuView->selectedApp();
|
|
||||||
}
|
|
||||||
else { // custom command line
|
|
||||||
selectedApp_ = customCommandToApp();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(selectedApp_) {
|
|
||||||
if(mimeType_ && fm_mime_type_get_type(mimeType_) && g_app_info_get_name(selectedApp_)[0]) {
|
|
||||||
/* add this app to the mime-type */
|
|
||||||
#if GLIB_CHECK_VERSION(2, 27, 6)
|
|
||||||
g_app_info_set_as_last_used_for_type(selectedApp_, fm_mime_type_get_type(mimeType_), NULL);
|
|
||||||
#else
|
|
||||||
g_app_info_add_supports_type(selectedApp_, fm_mime_type_get_type(mimeType_), NULL);
|
|
||||||
#endif
|
|
||||||
/* if need to set default */
|
|
||||||
if(ui->setDefault->isChecked())
|
|
||||||
g_app_info_set_as_default_for_type(selectedApp_, fm_mime_type_get_type(mimeType_), NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppChooserDialog::onSelectionChanged() {
|
|
||||||
bool isAppSelected = ui->appMenuView->isAppSelected();
|
|
||||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(isAppSelected);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppChooserDialog::setMimeType(FmMimeType* mimeType) {
|
|
||||||
if(mimeType_)
|
|
||||||
fm_mime_type_unref(mimeType_);
|
|
||||||
|
|
||||||
mimeType_ = mimeType ? fm_mime_type_ref(mimeType) : NULL;
|
|
||||||
if(mimeType_) {
|
|
||||||
QString text = tr("Select an application to open \"%1\" files")
|
|
||||||
.arg(QString::fromUtf8(fm_mime_type_get_desc(mimeType_)));
|
|
||||||
ui->fileTypeHeader->setText(text);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ui->fileTypeHeader->hide();
|
|
||||||
ui->setDefault->hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppChooserDialog::setCanSetDefault(bool value) {
|
|
||||||
canSetDefault_ = value;
|
|
||||||
ui->setDefault->setVisible(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppChooserDialog::onTabChanged(int index) {
|
|
||||||
if(index == 0) { // app menu view
|
|
||||||
onSelectionChanged();
|
|
||||||
}
|
|
||||||
else if(index == 1) { // custom command
|
|
||||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Fm
|
|
||||||
@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2014 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
* Copyright 2012-2013 Andriy Grytsenko (LStranger) <andrej@rep.kiev.ua>
|
|
||||||
*
|
|
||||||
* 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_APPCHOOSERDIALOG_H
|
|
||||||
#define FM_APPCHOOSERDIALOG_H
|
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class AppChooserDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class LIBFM_QT_API AppChooserDialog : public QDialog {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit AppChooserDialog(FmMimeType* mimeType, QWidget* parent = NULL, Qt::WindowFlags f = 0);
|
|
||||||
~AppChooserDialog();
|
|
||||||
|
|
||||||
virtual void accept();
|
|
||||||
|
|
||||||
void setMimeType(FmMimeType* mimeType);
|
|
||||||
FmMimeType* mimeType() {
|
|
||||||
return mimeType_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCanSetDefault(bool value);
|
|
||||||
bool canSetDefault() {
|
|
||||||
return canSetDefault_;
|
|
||||||
}
|
|
||||||
|
|
||||||
GAppInfo* selectedApp() {
|
|
||||||
return G_APP_INFO(g_object_ref(selectedApp_));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isSetDefault();
|
|
||||||
|
|
||||||
private:
|
|
||||||
GAppInfo* customCommandToApp();
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
|
||||||
void onSelectionChanged();
|
|
||||||
void onTabChanged(int index);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::AppChooserDialog* ui;
|
|
||||||
FmMimeType* mimeType_;
|
|
||||||
bool canSetDefault_;
|
|
||||||
GAppInfo* selectedApp_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_APPCHOOSERDIALOG_H
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
<one line to give the library's name and an idea of what it does.>
|
|
||||||
Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "applaunchcontext.h"
|
|
||||||
#include <QX11Info>
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
|
|
||||||
typedef struct _FmAppLaunchContext {
|
|
||||||
GAppLaunchContext parent;
|
|
||||||
}FmAppLaunchContext;
|
|
||||||
|
|
||||||
G_DEFINE_TYPE(FmAppLaunchContext, fm_app_launch_context, G_TYPE_APP_LAUNCH_CONTEXT)
|
|
||||||
|
|
||||||
static char* fm_app_launch_context_get_display(GAppLaunchContext *context, GAppInfo *info, GList *files) {
|
|
||||||
Display* dpy = QX11Info::display();
|
|
||||||
if(dpy) {
|
|
||||||
char* xstr = DisplayString(dpy);
|
|
||||||
return g_strdup(xstr);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char* fm_app_launch_context_get_startup_notify_id(GAppLaunchContext *context, GAppInfo *info, GList *files) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fm_app_launch_context_class_init(FmAppLaunchContextClass* klass) {
|
|
||||||
GAppLaunchContextClass* app_launch_class = G_APP_LAUNCH_CONTEXT_CLASS(klass);
|
|
||||||
app_launch_class->get_display = fm_app_launch_context_get_display;
|
|
||||||
app_launch_class->get_startup_notify_id = fm_app_launch_context_get_startup_notify_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fm_app_launch_context_init(FmAppLaunchContext* context) {
|
|
||||||
}
|
|
||||||
|
|
||||||
FmAppLaunchContext* fm_app_launch_context_new_for_widget(QWidget* widget) {
|
|
||||||
FmAppLaunchContext* context = (FmAppLaunchContext*)g_object_new(FM_TYPE_APP_LAUNCH_CONTEXT, NULL);
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
FmAppLaunchContext* fm_app_launch_context_new() {
|
|
||||||
FmAppLaunchContext* context = (FmAppLaunchContext*)g_object_new(FM_TYPE_APP_LAUNCH_CONTEXT, NULL);
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
<one line to give the library's name and an idea of what it does.>
|
|
||||||
Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FM_APP_LAUNCHCONTEXT_H
|
|
||||||
#define FM_APP_LAUNCHCONTEXT_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <gio/gio.h>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
#define FM_TYPE_APP_LAUNCH_CONTEXT (fm_app_launch_context_get_type())
|
|
||||||
#define FM_APP_LAUNCH_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
|
|
||||||
FM_TYPE_APP_LAUNCH_CONTEXT, FmAppLaunchContext))
|
|
||||||
#define FM_APP_LAUNCH_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),\
|
|
||||||
FM_TYPE_APP_LAUNCH_CONTEXT, FmAppLaunchContextClass))
|
|
||||||
#define FM_IS_APP_LAUNCH_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),\
|
|
||||||
FM_TYPE_APP_LAUNCH_CONTEXT))
|
|
||||||
#define FM_IS_APP_LAUNCH_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\
|
|
||||||
FM_TYPE_APP_LAUNCH_CONTEXT))
|
|
||||||
#define FM_APP_LAUNCH_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),\
|
|
||||||
FM_TYPE_APP_LAUNCH_CONTEXT, FmAppLaunchContextClass))
|
|
||||||
|
|
||||||
typedef struct _FmAppLaunchContext FmAppLaunchContext;
|
|
||||||
|
|
||||||
typedef struct _FmAppLaunchContextClass {
|
|
||||||
GAppLaunchContextClass parent;
|
|
||||||
}FmAppLaunchContextClass;
|
|
||||||
|
|
||||||
FmAppLaunchContext* fm_app_launch_context_new();
|
|
||||||
FmAppLaunchContext* fm_app_launch_context_new_for_widget(QWidget* widget);
|
|
||||||
GType fm_app_launch_context_get_type();
|
|
||||||
|
|
||||||
#endif // FM_APPLAUNCHCONTEXT_H
|
|
||||||
@ -1,159 +0,0 @@
|
|||||||
/*
|
|
||||||
* <one line to give the library's name and an idea of what it does.>
|
|
||||||
* Copyright (C) 2014 <copyright holder> <email>
|
|
||||||
*
|
|
||||||
* 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 "appmenuview.h"
|
|
||||||
#include <QStandardItemModel>
|
|
||||||
#include "icontheme.h"
|
|
||||||
#include "appmenuview_p.h"
|
|
||||||
#include <gio/gdesktopappinfo.h>
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
AppMenuView::AppMenuView(QWidget* parent):
|
|
||||||
model_(new QStandardItemModel()),
|
|
||||||
menu_cache(NULL),
|
|
||||||
menu_cache_reload_notify(NULL),
|
|
||||||
QTreeView(parent) {
|
|
||||||
|
|
||||||
setHeaderHidden(true);
|
|
||||||
setSelectionMode(SingleSelection);
|
|
||||||
|
|
||||||
// initialize model
|
|
||||||
// TODO: share one model among all app menu view widgets
|
|
||||||
// ensure that we're using lxmenu-data (FIXME: should we do this?)
|
|
||||||
QByteArray oldenv = qgetenv("XDG_MENU_PREFIX");
|
|
||||||
qputenv("XDG_MENU_PREFIX", "lxde-");
|
|
||||||
menu_cache = menu_cache_lookup("applications.menu");
|
|
||||||
// if(!oldenv.isEmpty())
|
|
||||||
qputenv("XDG_MENU_PREFIX", oldenv); // restore the original value if needed
|
|
||||||
|
|
||||||
if(menu_cache) {
|
|
||||||
MenuCacheDir* dir = menu_cache_dup_root_dir(menu_cache);
|
|
||||||
menu_cache_reload_notify = menu_cache_add_reload_notify(menu_cache, _onMenuCacheReload, this);
|
|
||||||
if(dir) { /* content of menu is already loaded */
|
|
||||||
addMenuItems(NULL, dir);
|
|
||||||
menu_cache_item_unref(MENU_CACHE_ITEM(dir));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setModel(model_);
|
|
||||||
connect(selectionModel(), &QItemSelectionModel::selectionChanged, this, &AppMenuView::selectionChanged);
|
|
||||||
selectionModel()->select(model_->index(0, 0), QItemSelectionModel::SelectCurrent);
|
|
||||||
}
|
|
||||||
|
|
||||||
AppMenuView::~AppMenuView() {
|
|
||||||
delete model_;
|
|
||||||
if(menu_cache) {
|
|
||||||
if(menu_cache_reload_notify)
|
|
||||||
menu_cache_remove_reload_notify(menu_cache, menu_cache_reload_notify);
|
|
||||||
menu_cache_unref(menu_cache);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppMenuView::addMenuItems(QStandardItem* parentItem, MenuCacheDir* dir) {
|
|
||||||
GSList* l;
|
|
||||||
GSList* list;
|
|
||||||
/* Iterate over all menu items in this directory. */
|
|
||||||
for(l = list = menu_cache_dir_list_children(dir); l != NULL; l = l->next) {
|
|
||||||
/* Get the menu item. */
|
|
||||||
MenuCacheItem* menuItem = MENU_CACHE_ITEM(l->data);
|
|
||||||
switch(menu_cache_item_get_type(menuItem)) {
|
|
||||||
case MENU_CACHE_TYPE_NONE:
|
|
||||||
case MENU_CACHE_TYPE_SEP:
|
|
||||||
break;
|
|
||||||
case MENU_CACHE_TYPE_APP:
|
|
||||||
case MENU_CACHE_TYPE_DIR: {
|
|
||||||
AppMenuViewItem* newItem = new AppMenuViewItem(menuItem);
|
|
||||||
if(parentItem)
|
|
||||||
parentItem->insertRow(parentItem->rowCount(), newItem);
|
|
||||||
else
|
|
||||||
model_->insertRow(model_->rowCount(), newItem);
|
|
||||||
|
|
||||||
if(menu_cache_item_get_type(menuItem) == MENU_CACHE_TYPE_DIR)
|
|
||||||
addMenuItems(newItem, MENU_CACHE_DIR(menuItem));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_slist_free_full(list, (GDestroyNotify)menu_cache_item_unref);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppMenuView::onMenuCacheReload(MenuCache* mc) {
|
|
||||||
MenuCacheDir* dir = menu_cache_dup_root_dir(mc);
|
|
||||||
model_->clear();
|
|
||||||
/* FIXME: preserve original selection */
|
|
||||||
if(dir) {
|
|
||||||
addMenuItems(NULL, dir);
|
|
||||||
menu_cache_item_unref(MENU_CACHE_ITEM(dir));
|
|
||||||
selectionModel()->select(model_->index(0, 0), QItemSelectionModel::SelectCurrent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AppMenuView::isAppSelected() {
|
|
||||||
AppMenuViewItem* item = selectedItem();
|
|
||||||
return (item && item->isApp());
|
|
||||||
}
|
|
||||||
|
|
||||||
AppMenuViewItem* AppMenuView::selectedItem() {
|
|
||||||
QModelIndexList selected = selectedIndexes();
|
|
||||||
if(!selected.isEmpty()) {
|
|
||||||
AppMenuViewItem* item = static_cast<AppMenuViewItem*>(model_->itemFromIndex(selected.first()
|
|
||||||
));
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
GAppInfo* AppMenuView::selectedApp() {
|
|
||||||
const char* id = selectedAppDesktopId();
|
|
||||||
return id ? G_APP_INFO(g_desktop_app_info_new(id)) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray AppMenuView::selectedAppDesktopFilePath() {
|
|
||||||
AppMenuViewItem* item = selectedItem();
|
|
||||||
if(item && item->isApp()) {
|
|
||||||
char* path = menu_cache_item_get_file_path(item->item());
|
|
||||||
QByteArray ret(path);
|
|
||||||
g_free(path);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
return QByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* AppMenuView::selectedAppDesktopId() {
|
|
||||||
AppMenuViewItem* item = selectedItem();
|
|
||||||
if(item && item->isApp()) {
|
|
||||||
return menu_cache_item_get_id(item->item());
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
FmPath* AppMenuView::selectedAppDesktopPath() {
|
|
||||||
AppMenuViewItem* item = selectedItem();
|
|
||||||
if(item && item->isApp()) {
|
|
||||||
char* mpath = menu_cache_dir_make_path(MENU_CACHE_DIR(item));
|
|
||||||
FmPath* path = fm_path_new_relative(fm_path_get_apps_menu(),
|
|
||||||
mpath + 13 /* skip "/Applications" */);
|
|
||||||
g_free(mpath);
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Fm
|
|
||||||
@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
* <one line to give the library's name and an idea of what it does.>
|
|
||||||
* Copyright (C) 2014 <copyright holder> <email>
|
|
||||||
*
|
|
||||||
* 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_APPMENUVIEW_H
|
|
||||||
#define FM_APPMENUVIEW_H
|
|
||||||
|
|
||||||
#include <QTreeView>
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
#include <menu-cache/menu-cache.h>
|
|
||||||
|
|
||||||
class QStandardItemModel;
|
|
||||||
class QStandardItem;
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class AppMenuViewItem;
|
|
||||||
|
|
||||||
class LIBFM_QT_API AppMenuView : public QTreeView {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit AppMenuView(QWidget* parent = NULL);
|
|
||||||
~AppMenuView();
|
|
||||||
|
|
||||||
GAppInfo* selectedApp();
|
|
||||||
|
|
||||||
const char* selectedAppDesktopId();
|
|
||||||
|
|
||||||
QByteArray selectedAppDesktopFilePath();
|
|
||||||
|
|
||||||
FmPath * selectedAppDesktopPath();
|
|
||||||
|
|
||||||
bool isAppSelected();
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void selectionChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void addMenuItems(QStandardItem* parentItem, MenuCacheDir* dir);
|
|
||||||
void onMenuCacheReload(MenuCache* mc);
|
|
||||||
static void _onMenuCacheReload(MenuCache* mc, gpointer user_data) {
|
|
||||||
static_cast<AppMenuView*>(user_data)->onMenuCacheReload(mc);
|
|
||||||
}
|
|
||||||
|
|
||||||
AppMenuViewItem* selectedItem();
|
|
||||||
|
|
||||||
private:
|
|
||||||
// gboolean fm_app_menu_view_is_item_app(, GtkTreeIter* it);
|
|
||||||
QStandardItemModel* model_;
|
|
||||||
MenuCache* menu_cache;
|
|
||||||
MenuCacheNotifyId menu_cache_reload_notify;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_APPMENUVIEW_H
|
|
||||||
@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* <one line to give the library's name and an idea of what it does.>
|
|
||||||
* Copyright (C) 2014 <copyright holder> <email>
|
|
||||||
*
|
|
||||||
* 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_APPMENUVIEW_P_H
|
|
||||||
#define FM_APPMENUVIEW_P_H
|
|
||||||
|
|
||||||
#include <QStandardItem>
|
|
||||||
#include <menu-cache/menu-cache.h>
|
|
||||||
#include "icontheme.h"
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class AppMenuViewItem : public QStandardItem {
|
|
||||||
public:
|
|
||||||
explicit AppMenuViewItem(MenuCacheItem* item):
|
|
||||||
item_(menu_cache_item_ref(item)) {
|
|
||||||
FmIcon* fmicon;
|
|
||||||
if(menu_cache_item_get_icon(item))
|
|
||||||
fmicon = fm_icon_from_name(menu_cache_item_get_icon(item));
|
|
||||||
else
|
|
||||||
fmicon = NULL;
|
|
||||||
setText(QString::fromUtf8(menu_cache_item_get_name(item)));
|
|
||||||
setEditable(false);
|
|
||||||
setDragEnabled(false);
|
|
||||||
if(fmicon) {
|
|
||||||
setIcon(IconTheme::icon(fmicon));
|
|
||||||
fm_icon_unref(fmicon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~AppMenuViewItem() {
|
|
||||||
menu_cache_item_unref(item_);
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuCacheItem* item() {
|
|
||||||
return item_;
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuCacheType type() {
|
|
||||||
return menu_cache_item_get_type(item_);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isApp() {
|
|
||||||
return type() == MENU_CACHE_TYPE_APP;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isDir() {
|
|
||||||
return type() == MENU_CACHE_TYPE_DIR;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
MenuCacheItem* item_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_APPMENUVIEW_P_H
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "bookmarkaction.h"
|
|
||||||
|
|
||||||
using namespace Fm;
|
|
||||||
|
|
||||||
BookmarkAction::BookmarkAction(FmBookmarkItem* item, QObject* parent):
|
|
||||||
QAction(parent),
|
|
||||||
item_(fm_bookmark_item_ref(item)) {
|
|
||||||
|
|
||||||
setText(QString::fromUtf8(item->name));
|
|
||||||
}
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef BOOKMARKACTION_H
|
|
||||||
#define BOOKMARKACTION_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QAction>
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
// action used to create bookmark menu items
|
|
||||||
class LIBFM_QT_API BookmarkAction : public QAction {
|
|
||||||
public:
|
|
||||||
explicit BookmarkAction(FmBookmarkItem* item, QObject* parent = 0);
|
|
||||||
|
|
||||||
virtual ~BookmarkAction() {
|
|
||||||
if(item_)
|
|
||||||
fm_bookmark_item_unref(item_);
|
|
||||||
}
|
|
||||||
|
|
||||||
FmBookmarkItem* bookmark() {
|
|
||||||
return item_;
|
|
||||||
}
|
|
||||||
|
|
||||||
FmPath* path() {
|
|
||||||
return item_->path;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
FmBookmarkItem* item_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // BOOKMARKACTION_H
|
|
||||||
@ -1,87 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "browsehistory.h"
|
|
||||||
|
|
||||||
using namespace Fm;
|
|
||||||
|
|
||||||
BrowseHistory::BrowseHistory():
|
|
||||||
currentIndex_(0),
|
|
||||||
maxCount_(10) {
|
|
||||||
}
|
|
||||||
|
|
||||||
BrowseHistory::~BrowseHistory() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowseHistory::add(FmPath* path, int scrollPos) {
|
|
||||||
int lastIndex = size() - 1;
|
|
||||||
if(currentIndex_ < lastIndex) {
|
|
||||||
// if we're not at the last item, remove items after the current one.
|
|
||||||
erase(begin() + currentIndex_ + 1, end());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(size() + 1 > maxCount_) {
|
|
||||||
// if there are too many items, remove the oldest one.
|
|
||||||
// FIXME: what if currentIndex_ == 0? remove the last item instead?
|
|
||||||
if(currentIndex_ == 0)
|
|
||||||
remove(lastIndex);
|
|
||||||
else {
|
|
||||||
remove(0);
|
|
||||||
--currentIndex_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// add a path and current scroll position to browse history
|
|
||||||
append(BrowseHistoryItem(path, scrollPos));
|
|
||||||
currentIndex_ = size() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowseHistory::setCurrentIndex(int index) {
|
|
||||||
if(index >= 0 && index < size()) {
|
|
||||||
currentIndex_ = index;
|
|
||||||
// FIXME: should we emit a signal for the change?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BrowseHistory::canBackward() const {
|
|
||||||
return (currentIndex_ > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int BrowseHistory::backward() {
|
|
||||||
if(canBackward())
|
|
||||||
--currentIndex_;
|
|
||||||
return currentIndex_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BrowseHistory::canForward() const {
|
|
||||||
return (currentIndex_ + 1 < size());
|
|
||||||
}
|
|
||||||
|
|
||||||
int BrowseHistory::forward() {
|
|
||||||
if(canForward())
|
|
||||||
++currentIndex_;
|
|
||||||
return currentIndex_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowseHistory::setMaxCount(int maxCount) {
|
|
||||||
maxCount_ = maxCount;
|
|
||||||
if(size() > maxCount) {
|
|
||||||
// TODO: remove some items
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,131 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FM_BROWSEHISTORY_H
|
|
||||||
#define FM_BROWSEHISTORY_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QVector>
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
// class used to story browsing history of folder views
|
|
||||||
// We use this class to replace FmNavHistory provided by libfm since
|
|
||||||
// the original Libfm API is hard to use and confusing.
|
|
||||||
|
|
||||||
class LIBFM_QT_API BrowseHistoryItem {
|
|
||||||
public:
|
|
||||||
|
|
||||||
BrowseHistoryItem():
|
|
||||||
path_(NULL),
|
|
||||||
scrollPos_(0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
BrowseHistoryItem(FmPath* path, int scrollPos = 0):
|
|
||||||
path_(fm_path_ref(path)),
|
|
||||||
scrollPos_(scrollPos) {
|
|
||||||
}
|
|
||||||
|
|
||||||
BrowseHistoryItem(const BrowseHistoryItem& other):
|
|
||||||
path_(other.path_ ? fm_path_ref(other.path_) : NULL),
|
|
||||||
scrollPos_(other.scrollPos_) {
|
|
||||||
}
|
|
||||||
|
|
||||||
~BrowseHistoryItem() {
|
|
||||||
if(path_)
|
|
||||||
fm_path_unref(path_);
|
|
||||||
}
|
|
||||||
|
|
||||||
BrowseHistoryItem& operator=(const BrowseHistoryItem& other) {
|
|
||||||
if(path_)
|
|
||||||
fm_path_unref(path_);
|
|
||||||
path_ = other.path_ ? fm_path_ref(other.path_) : NULL;
|
|
||||||
scrollPos_ = other.scrollPos_;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
FmPath* path() const {
|
|
||||||
return path_;
|
|
||||||
}
|
|
||||||
|
|
||||||
int scrollPos() const {
|
|
||||||
return scrollPos_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setScrollPos(int pos) {
|
|
||||||
scrollPos_ = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
FmPath* path_;
|
|
||||||
int scrollPos_;
|
|
||||||
// TODO: we may need to store current selection as well. reserve room for furutre expansion.
|
|
||||||
// void* reserved1;
|
|
||||||
// void* reserved2;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LIBFM_QT_API BrowseHistory : public QVector<BrowseHistoryItem> {
|
|
||||||
|
|
||||||
public:
|
|
||||||
BrowseHistory();
|
|
||||||
virtual ~BrowseHistory();
|
|
||||||
|
|
||||||
int currentIndex() const {
|
|
||||||
return currentIndex_;
|
|
||||||
}
|
|
||||||
void setCurrentIndex(int index);
|
|
||||||
|
|
||||||
FmPath* currentPath() const {
|
|
||||||
return at(currentIndex_).path();
|
|
||||||
}
|
|
||||||
|
|
||||||
int currentScrollPos() const {
|
|
||||||
return at(currentIndex_).scrollPos();
|
|
||||||
}
|
|
||||||
|
|
||||||
BrowseHistoryItem& currentItem() {
|
|
||||||
return operator[](currentIndex_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void add(FmPath* path, int scrollPos = 0);
|
|
||||||
|
|
||||||
bool canForward() const;
|
|
||||||
|
|
||||||
bool canBackward() const;
|
|
||||||
|
|
||||||
int backward();
|
|
||||||
|
|
||||||
int forward();
|
|
||||||
|
|
||||||
int maxCount() const {
|
|
||||||
return maxCount_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMaxCount(int maxCount);
|
|
||||||
|
|
||||||
private:
|
|
||||||
int currentIndex_;
|
|
||||||
int maxCount_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_BROWSEHISTORY_H
|
|
||||||
@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
<one line to give the library's name and an idea of what it does.>
|
|
||||||
Copyright (C) 2013 <copyright holder> <email>
|
|
||||||
|
|
||||||
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 "cachedfoldermodel.h"
|
|
||||||
|
|
||||||
using namespace Fm;
|
|
||||||
|
|
||||||
static GQuark data_id = 0;
|
|
||||||
|
|
||||||
|
|
||||||
CachedFolderModel::CachedFolderModel(FmFolder* folder):
|
|
||||||
FolderModel(),
|
|
||||||
refCount(1) {
|
|
||||||
|
|
||||||
FolderModel::setFolder(folder);
|
|
||||||
}
|
|
||||||
|
|
||||||
CachedFolderModel::~CachedFolderModel() {
|
|
||||||
qDebug("delete CachedFolderModel");
|
|
||||||
}
|
|
||||||
|
|
||||||
CachedFolderModel* CachedFolderModel::modelFromFolder(FmFolder* folder) {
|
|
||||||
CachedFolderModel* model = NULL;
|
|
||||||
if(!data_id)
|
|
||||||
data_id = g_quark_from_static_string("CachedFolderModel");
|
|
||||||
gpointer qdata = g_object_get_qdata(G_OBJECT(folder), data_id);
|
|
||||||
model = reinterpret_cast<CachedFolderModel*>(qdata);
|
|
||||||
if(model) {
|
|
||||||
// qDebug("cache found!!");
|
|
||||||
model->ref();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
model = new CachedFolderModel(folder);
|
|
||||||
g_object_set_qdata(G_OBJECT(folder), data_id, model);
|
|
||||||
}
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
CachedFolderModel* CachedFolderModel::modelFromPath(FmPath* path) {
|
|
||||||
FmFolder* folder = fm_folder_from_path(path);
|
|
||||||
if(folder) {
|
|
||||||
CachedFolderModel* model = modelFromFolder(folder);
|
|
||||||
g_object_unref(folder);
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CachedFolderModel::unref() {
|
|
||||||
// qDebug("unref cache");
|
|
||||||
--refCount;
|
|
||||||
if(refCount <= 0) {
|
|
||||||
g_object_set_qdata(G_OBJECT(folder()), data_id, NULL);
|
|
||||||
deleteLater();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
<one line to give the library's name and an idea of what it does.>
|
|
||||||
Copyright (C) 2013 <copyright holder> <email>
|
|
||||||
|
|
||||||
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_CACHEDFOLDERMODEL_H
|
|
||||||
#define FM_CACHEDFOLDERMODEL_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include "foldermodel.h"
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class LIBFM_QT_API CachedFolderModel : public FolderModel {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
CachedFolderModel(FmFolder* folder);
|
|
||||||
void ref() {
|
|
||||||
++refCount;
|
|
||||||
}
|
|
||||||
void unref();
|
|
||||||
|
|
||||||
static CachedFolderModel* modelFromFolder(FmFolder* folder);
|
|
||||||
static CachedFolderModel* modelFromPath(FmPath* path);
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual ~CachedFolderModel();
|
|
||||||
void setFolder(FmFolder* folder);
|
|
||||||
private:
|
|
||||||
int refCount;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_CACHEDFOLDERMODEL_H
|
|
||||||
@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "colorbutton.h"
|
|
||||||
#include <QColorDialog>
|
|
||||||
|
|
||||||
using namespace Fm;
|
|
||||||
|
|
||||||
ColorButton::ColorButton(QWidget* parent): QPushButton(parent) {
|
|
||||||
connect(this, &QPushButton::clicked, this, &ColorButton::onClicked);
|
|
||||||
}
|
|
||||||
|
|
||||||
ColorButton::~ColorButton() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ColorButton::onClicked() {
|
|
||||||
QColorDialog dlg(color_);
|
|
||||||
if(dlg.exec() == QDialog::Accepted) {
|
|
||||||
setColor(dlg.selectedColor());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ColorButton::setColor(const QColor& color) {
|
|
||||||
if(color != color_) {
|
|
||||||
color_ = color;
|
|
||||||
// use qss instead of QPalette to set the background color
|
|
||||||
// otherwise, this won't work when using the gtk style.
|
|
||||||
QString style = QString("QPushButton{background-color:%1;}").arg(color.name());
|
|
||||||
setStyleSheet(style);
|
|
||||||
Q_EMIT changed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FM_COLORBUTTON_H
|
|
||||||
#define FM_COLORBUTTON_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QColor>
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class LIBFM_QT_API ColorButton : public QPushButton {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit ColorButton(QWidget* parent = 0);
|
|
||||||
virtual ~ColorButton();
|
|
||||||
|
|
||||||
void setColor(const QColor&);
|
|
||||||
|
|
||||||
QColor color() const {
|
|
||||||
return color_;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void changed();
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
|
||||||
void onClicked();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QColor color_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_COLORBUTTON_H
|
|
||||||
@ -1,90 +0,0 @@
|
|||||||
/*
|
|
||||||
Menu with entries to create new folders and files.
|
|
||||||
Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "createnewmenu.h"
|
|
||||||
#include "folderview.h"
|
|
||||||
#include "icontheme.h"
|
|
||||||
#include "utilities.h"
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
CreateNewMenu::CreateNewMenu(QWidget* dialogParent, FmPath* dirPath, QWidget* parent):
|
|
||||||
QMenu(parent), dialogParent_(dialogParent), dirPath_(dirPath) {
|
|
||||||
QAction* action = new QAction(QIcon::fromTheme("folder-new"), tr("Folder"), this);
|
|
||||||
connect(action, &QAction::triggered, this, &CreateNewMenu::onCreateNewFolder);
|
|
||||||
addAction(action);
|
|
||||||
|
|
||||||
action = new QAction(QIcon::fromTheme("document-new"), tr("Blank File"), this);
|
|
||||||
connect(action, &QAction::triggered, this, &CreateNewMenu::onCreateNewFile);
|
|
||||||
addAction(action);
|
|
||||||
|
|
||||||
// add more items to "Create New" menu from templates
|
|
||||||
GList* templates = fm_template_list_all(fm_config->only_user_templates);
|
|
||||||
if(templates) {
|
|
||||||
addSeparator();
|
|
||||||
for(GList* l = templates; l; l = l->next) {
|
|
||||||
FmTemplate* templ = (FmTemplate*)l->data;
|
|
||||||
/* 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(IconTheme::icon(icon), text);
|
|
||||||
action->setObjectName(QString::fromUtf8(fm_template_get_name(templ, NULL)));
|
|
||||||
connect(action, &QAction::triggered, this, &CreateNewMenu::onCreateNew);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CreateNewMenu::~CreateNewMenu() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void CreateNewMenu::onCreateNewFile() {
|
|
||||||
if(dirPath_)
|
|
||||||
createFileOrFolder(CreateNewTextFile, dirPath_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CreateNewMenu::onCreateNewFolder() {
|
|
||||||
if(dirPath_)
|
|
||||||
createFileOrFolder(CreateNewFolder, dirPath_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CreateNewMenu::onCreateNew() {
|
|
||||||
QAction* action = static_cast<QAction*>(sender());
|
|
||||||
QByteArray name = action->objectName().toUtf8();
|
|
||||||
GList* templates = fm_template_list_all(fm_config->only_user_templates);
|
|
||||||
FmTemplate* templ = NULL;
|
|
||||||
for(GList* l = templates; l; l = l->next) {
|
|
||||||
FmTemplate* t = (FmTemplate*)l->data;
|
|
||||||
if(name == fm_template_get_name(t, NULL)) {
|
|
||||||
templ = t;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(templ) { // template found
|
|
||||||
if(dirPath_)
|
|
||||||
createFileOrFolder(CreateWithTemplate, dirPath_, templ, dialogParent_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Fm
|
|
||||||
@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
Menu with entries to create new folders and files.
|
|
||||||
Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FM_CREATENEWMENU_H
|
|
||||||
#define FM_CREATENEWMENU_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QMenu>
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class FolderView;
|
|
||||||
|
|
||||||
class LIBFM_QT_API CreateNewMenu : public QMenu {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit CreateNewMenu(QWidget* dialogParent, FmPath* dirPath,
|
|
||||||
QWidget* parent = 0);
|
|
||||||
virtual ~CreateNewMenu();
|
|
||||||
|
|
||||||
protected Q_SLOTS:
|
|
||||||
void onCreateNewFolder();
|
|
||||||
void onCreateNewFile();
|
|
||||||
void onCreateNew();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QWidget* dialogParent_;
|
|
||||||
FmPath* dirPath_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_CREATENEWMENU_H
|
|
||||||
@ -1,205 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "dirtreemodel.h"
|
|
||||||
#include "dirtreemodelitem.h"
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
DirTreeModel::DirTreeModel(QObject* parent):
|
|
||||||
showHidden_(false) {
|
|
||||||
}
|
|
||||||
|
|
||||||
DirTreeModel::~DirTreeModel() {
|
|
||||||
}
|
|
||||||
|
|
||||||
// QAbstractItemModel implementation
|
|
||||||
|
|
||||||
Qt::ItemFlags DirTreeModel::flags(const QModelIndex& index) const {
|
|
||||||
DirTreeModelItem* item = itemFromIndex(index);
|
|
||||||
if(item && item->isPlaceHolder())
|
|
||||||
return Qt::ItemIsEnabled;
|
|
||||||
return QAbstractItemModel::flags(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant DirTreeModel::data(const QModelIndex& index, int role) const {
|
|
||||||
if(!index.isValid() || index.column() > 1) {
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
DirTreeModelItem* item = itemFromIndex(index);
|
|
||||||
if(item) {
|
|
||||||
FmFileInfo* info = item->fileInfo_;
|
|
||||||
switch(role) {
|
|
||||||
case Qt::ToolTipRole:
|
|
||||||
return QVariant(item->displayName_);
|
|
||||||
case Qt::DisplayRole:
|
|
||||||
return QVariant(item->displayName_);
|
|
||||||
case Qt::DecorationRole:
|
|
||||||
return QVariant(item->icon_);
|
|
||||||
case FileInfoRole:
|
|
||||||
return qVariantFromValue((void*)info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
int DirTreeModel::columnCount(const QModelIndex& parent) const {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DirTreeModel::rowCount(const QModelIndex& parent) const {
|
|
||||||
if(!parent.isValid())
|
|
||||||
return rootItems_.count();
|
|
||||||
DirTreeModelItem* item = itemFromIndex(parent);
|
|
||||||
if(item)
|
|
||||||
return item->children_.count();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
QModelIndex DirTreeModel::parent(const QModelIndex& child) const {
|
|
||||||
DirTreeModelItem* item = itemFromIndex(child);
|
|
||||||
if(item && item->parent_) {
|
|
||||||
item = item->parent_; // go to parent item
|
|
||||||
if(item) {
|
|
||||||
const QList<DirTreeModelItem*>& items = item->parent_ ? item->parent_->children_ : rootItems_;
|
|
||||||
int row = items.indexOf(item); // this is Q(n) and may be slow :-(
|
|
||||||
if(row >= 0)
|
|
||||||
return createIndex(row, 0, (void*)item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QModelIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
QModelIndex DirTreeModel::index(int row, int column, const QModelIndex& parent) const {
|
|
||||||
if(row >= 0 && column >= 0 && column == 0) {
|
|
||||||
if(!parent.isValid()) { // root items
|
|
||||||
if(row < rootItems_.count()) {
|
|
||||||
const DirTreeModelItem* item = rootItems_.at(row);
|
|
||||||
return createIndex(row, column, (void*)item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { // child items
|
|
||||||
DirTreeModelItem* parentItem = itemFromIndex(parent);
|
|
||||||
if(row < parentItem->children_.count()) {
|
|
||||||
const DirTreeModelItem* item = parentItem->children_.at(row);
|
|
||||||
return createIndex(row, column, (void*)item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QModelIndex(); // invalid index
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DirTreeModel::hasChildren(const QModelIndex& parent) const {
|
|
||||||
DirTreeModelItem* item = itemFromIndex(parent);
|
|
||||||
return item ? !item->isPlaceHolder() : true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QModelIndex DirTreeModel::indexFromItem(DirTreeModelItem* item) const {
|
|
||||||
Q_ASSERT(item);
|
|
||||||
const QList<DirTreeModelItem*>& items = item->parent_ ? item->parent_->children_ : rootItems_;
|
|
||||||
int row = items.indexOf(item);
|
|
||||||
if(row >= 0)
|
|
||||||
return createIndex(row, 0, (void*)item);
|
|
||||||
return QModelIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
// public APIs
|
|
||||||
QModelIndex DirTreeModel::addRoot(FmFileInfo* root) {
|
|
||||||
DirTreeModelItem* item = new DirTreeModelItem(root, this);
|
|
||||||
int row = rootItems_.count();
|
|
||||||
beginInsertRows(QModelIndex(), row, row);
|
|
||||||
item->fileInfo_ = fm_file_info_ref(root);
|
|
||||||
rootItems_.append(item);
|
|
||||||
// add_place_holder_child_item(model, item_l, NULL, FALSE);
|
|
||||||
endInsertRows();
|
|
||||||
return QModelIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
DirTreeModelItem* DirTreeModel::itemFromIndex(const QModelIndex& index) const {
|
|
||||||
return reinterpret_cast<DirTreeModelItem*>(index.internalPointer());
|
|
||||||
}
|
|
||||||
|
|
||||||
QModelIndex DirTreeModel::indexFromPath(FmPath* path) const {
|
|
||||||
DirTreeModelItem* item = itemFromPath(path);
|
|
||||||
return item ? item->index() : QModelIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
DirTreeModelItem* DirTreeModel::itemFromPath(FmPath* path) const {
|
|
||||||
Q_FOREACH(DirTreeModelItem* item, rootItems_) {
|
|
||||||
if(item->fileInfo_ && fm_path_equal(path, fm_file_info_get_path(item->fileInfo_))) {
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
DirTreeModelItem* child = item->childFromPath(path, true);
|
|
||||||
if(child)
|
|
||||||
return child;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DirTreeModel::loadRow(const QModelIndex& index) {
|
|
||||||
DirTreeModelItem* item = itemFromIndex(index);
|
|
||||||
Q_ASSERT(item);
|
|
||||||
if(item && !item->isPlaceHolder())
|
|
||||||
item->loadFolder();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirTreeModel::unloadRow(const QModelIndex& index) {
|
|
||||||
DirTreeModelItem* item = itemFromIndex(index);
|
|
||||||
if(item && !item->isPlaceHolder())
|
|
||||||
item->unloadFolder();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DirTreeModel::isLoaded(const QModelIndex& index) {
|
|
||||||
DirTreeModelItem* item = itemFromIndex(index);
|
|
||||||
return item ? item->loaded_ : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QIcon DirTreeModel::icon(const QModelIndex& index) {
|
|
||||||
DirTreeModelItem* item = itemFromIndex(index);
|
|
||||||
return item ? item->icon_ : QIcon();
|
|
||||||
}
|
|
||||||
|
|
||||||
FmFileInfo* DirTreeModel::fileInfo(const QModelIndex& index) {
|
|
||||||
DirTreeModelItem* item = itemFromIndex(index);
|
|
||||||
return item ? item->fileInfo_ : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
FmPath* DirTreeModel::filePath(const QModelIndex& index) {
|
|
||||||
DirTreeModelItem* item = itemFromIndex(index);
|
|
||||||
return item && item->fileInfo_ ? fm_file_info_get_path(item->fileInfo_) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString DirTreeModel::dispName(const QModelIndex& index) {
|
|
||||||
DirTreeModelItem* item = itemFromIndex(index);
|
|
||||||
return item ? item->displayName_ : QString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirTreeModel::setShowHidden(bool show_hidden) {
|
|
||||||
showHidden_ = show_hidden;
|
|
||||||
Q_FOREACH(DirTreeModelItem* item, rootItems_) {
|
|
||||||
item->setShowHidden(show_hidden);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Fm
|
|
||||||
@ -1,90 +0,0 @@
|
|||||||
/*
|
|
||||||
* <one line to give the program's name and a brief idea of what it does.>
|
|
||||||
* Copyright (C) 2014 <copyright holder> <email>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FM_DIRTREEMODEL_H
|
|
||||||
#define FM_DIRTREEMODEL_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QModelIndex>
|
|
||||||
#include <QAbstractItemModel>
|
|
||||||
#include <QIcon>
|
|
||||||
#include <QList>
|
|
||||||
#include <QSharedPointer>
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class DirTreeModelItem;
|
|
||||||
class DirTreeView;
|
|
||||||
|
|
||||||
class LIBFM_QT_API DirTreeModel : public QAbstractItemModel {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
friend class DirTreeModelItem; // allow direct access of private members in DirTreeModelItem
|
|
||||||
friend class DirTreeView; // allow direct access of private members in DirTreeView
|
|
||||||
|
|
||||||
enum Role {
|
|
||||||
FileInfoRole = Qt::UserRole
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit DirTreeModel(QObject* parent);
|
|
||||||
~DirTreeModel();
|
|
||||||
|
|
||||||
QModelIndex addRoot(FmFileInfo* root);
|
|
||||||
void loadRow(const QModelIndex& index);
|
|
||||||
void unloadRow(const QModelIndex& index);
|
|
||||||
|
|
||||||
bool isLoaded(const QModelIndex& index);
|
|
||||||
QIcon icon(const QModelIndex& index);
|
|
||||||
FmFileInfo* fileInfo(const QModelIndex& index);
|
|
||||||
FmPath* filePath(const QModelIndex& index);
|
|
||||||
QString dispName(const QModelIndex& index);
|
|
||||||
|
|
||||||
void setShowHidden(bool show_hidden);
|
|
||||||
bool showHidden() const {
|
|
||||||
return showHidden_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QModelIndex indexFromPath(FmPath* path) const;
|
|
||||||
|
|
||||||
virtual Qt::ItemFlags flags(const QModelIndex& index) const;
|
|
||||||
virtual QVariant data(const QModelIndex& index, int role) const;
|
|
||||||
virtual int columnCount(const QModelIndex& parent) const;
|
|
||||||
virtual int rowCount(const QModelIndex& parent) const;
|
|
||||||
virtual QModelIndex parent(const QModelIndex& child) const;
|
|
||||||
virtual QModelIndex index(int row, int column, const QModelIndex& parent) const;
|
|
||||||
virtual bool hasChildren(const QModelIndex& parent = QModelIndex()) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
DirTreeModelItem* itemFromPath(FmPath* path) const;
|
|
||||||
DirTreeModelItem* itemFromIndex(const QModelIndex& index) const;
|
|
||||||
QModelIndex indexFromItem(DirTreeModelItem* item) const;
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void rowLoaded(const QModelIndex& index);
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool showHidden_;
|
|
||||||
QList<DirTreeModelItem*> rootItems_;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_DIRTREEMODEL_H
|
|
||||||
@ -1,339 +0,0 @@
|
|||||||
/*
|
|
||||||
* <one line to give the program's name and a brief idea of what it does.>
|
|
||||||
* Copyright (C) 2014 <copyright holder> <email>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "dirtreemodelitem.h"
|
|
||||||
#include "dirtreemodel.h"
|
|
||||||
#include "icontheme.h"
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
DirTreeModelItem::DirTreeModelItem():
|
|
||||||
model_(NULL),
|
|
||||||
folder_(NULL),
|
|
||||||
expanded_(false),
|
|
||||||
loaded_(false),
|
|
||||||
fileInfo_(NULL),
|
|
||||||
placeHolderChild_(NULL),
|
|
||||||
parent_(NULL) {
|
|
||||||
}
|
|
||||||
|
|
||||||
DirTreeModelItem::DirTreeModelItem(FmFileInfo* info, DirTreeModel* model, DirTreeModelItem* parent):
|
|
||||||
model_(model),
|
|
||||||
folder_(NULL),
|
|
||||||
expanded_(false),
|
|
||||||
loaded_(false),
|
|
||||||
fileInfo_(fm_file_info_ref(info)),
|
|
||||||
displayName_(QString::fromUtf8(fm_file_info_get_disp_name(info))),
|
|
||||||
icon_(IconTheme::icon(fm_file_info_get_icon(info))),
|
|
||||||
placeHolderChild_(NULL),
|
|
||||||
parent_(parent) {
|
|
||||||
|
|
||||||
if(info)
|
|
||||||
addPlaceHolderChild();
|
|
||||||
}
|
|
||||||
|
|
||||||
DirTreeModelItem::~DirTreeModelItem() {
|
|
||||||
if(fileInfo_)
|
|
||||||
fm_file_info_unref(fileInfo_);
|
|
||||||
|
|
||||||
if(folder_)
|
|
||||||
freeFolder();
|
|
||||||
|
|
||||||
// delete child items if needed
|
|
||||||
if(!children_.isEmpty()) {
|
|
||||||
Q_FOREACH(DirTreeModelItem* item, children_) {
|
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!hiddenChildren_.isEmpty()) {
|
|
||||||
Q_FOREACH(DirTreeModelItem* item, hiddenChildren_) {
|
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirTreeModelItem::addPlaceHolderChild() {
|
|
||||||
placeHolderChild_ = new DirTreeModelItem();
|
|
||||||
placeHolderChild_->parent_ = this;
|
|
||||||
placeHolderChild_->model_ = model_;
|
|
||||||
placeHolderChild_->displayName_ = DirTreeModel::tr("Loading...");
|
|
||||||
children_.append(placeHolderChild_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirTreeModelItem::freeFolder() {
|
|
||||||
if(folder_) {
|
|
||||||
g_signal_handlers_disconnect_by_func(folder_, gpointer(onFolderFinishLoading), this);
|
|
||||||
g_signal_handlers_disconnect_by_func(folder_, gpointer(onFolderFilesAdded), this);
|
|
||||||
g_signal_handlers_disconnect_by_func(folder_, gpointer(onFolderFilesRemoved), this);
|
|
||||||
g_signal_handlers_disconnect_by_func(folder_, gpointer(onFolderFilesChanged), this);
|
|
||||||
g_object_unref(folder_);
|
|
||||||
folder_ = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirTreeModelItem::loadFolder() {
|
|
||||||
if(!expanded_) {
|
|
||||||
/* dynamically load content of the folder. */
|
|
||||||
folder_ = fm_folder_from_path(fm_file_info_get_path(fileInfo_));
|
|
||||||
/* g_debug("fm_dir_tree_model_load_row()"); */
|
|
||||||
/* associate the data with loaded handler */
|
|
||||||
g_signal_connect(folder_, "finish-loading", G_CALLBACK(onFolderFinishLoading), this);
|
|
||||||
g_signal_connect(folder_, "files-added", G_CALLBACK(onFolderFilesAdded), this);
|
|
||||||
g_signal_connect(folder_, "files-removed", G_CALLBACK(onFolderFilesRemoved), this);
|
|
||||||
g_signal_connect(folder_, "files-changed", G_CALLBACK(onFolderFilesChanged), this);
|
|
||||||
|
|
||||||
/* set 'expanded' flag beforehand as callback may check it */
|
|
||||||
expanded_ = true;
|
|
||||||
/* if the folder is already loaded, call "loaded" handler ourselves */
|
|
||||||
if(fm_folder_is_loaded(folder_)) { // already loaded
|
|
||||||
GList* file_l;
|
|
||||||
FmFileInfoList* files = fm_folder_get_files(folder_);
|
|
||||||
for(file_l = fm_file_info_list_peek_head_link(files); file_l; file_l = file_l->next) {
|
|
||||||
FmFileInfo* fi = FM_FILE_INFO(file_l->data);
|
|
||||||
if(fm_file_info_is_dir(fi)) {
|
|
||||||
insertFileInfo(fi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onFolderFinishLoading(folder_, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirTreeModelItem::unloadFolder() {
|
|
||||||
if(expanded_) { /* do some cleanup */
|
|
||||||
/* remove all children, and replace them with a dummy child
|
|
||||||
* item to keep expander in the tree view around. */
|
|
||||||
|
|
||||||
// delete all visible child items
|
|
||||||
model_->beginRemoveRows(index(), 0, children_.count() - 1);
|
|
||||||
if(!children_.isEmpty()) {
|
|
||||||
Q_FOREACH(DirTreeModelItem* item, children_) {
|
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
children_.clear();
|
|
||||||
}
|
|
||||||
model_->endRemoveRows();
|
|
||||||
|
|
||||||
// remove hidden children
|
|
||||||
if(!hiddenChildren_.isEmpty()) {
|
|
||||||
Q_FOREACH(DirTreeModelItem* item, hiddenChildren_) {
|
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
hiddenChildren_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* now, we have no child since all child items are removed.
|
|
||||||
* So we add a place holder child item to keep the expander around. */
|
|
||||||
addPlaceHolderChild();
|
|
||||||
/* deactivate folder since it will be reactivated on expand */
|
|
||||||
freeFolder();
|
|
||||||
expanded_ = false;
|
|
||||||
loaded_ = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QModelIndex DirTreeModelItem::index() {
|
|
||||||
Q_ASSERT(model_);
|
|
||||||
return model_->indexFromItem(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add file info to parent node to proper position.
|
|
||||||
* GtkTreePath tp is the tree path of parent node. */
|
|
||||||
DirTreeModelItem* DirTreeModelItem::insertFileInfo(FmFileInfo* fi) {
|
|
||||||
// qDebug() << "insertFileInfo: " << fm_file_info_get_disp_name(fi);
|
|
||||||
DirTreeModelItem* item = new DirTreeModelItem(fi, model_);
|
|
||||||
insertItem(item);
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
// find a good position to insert the new item
|
|
||||||
int DirTreeModelItem::insertItem(DirTreeModelItem* newItem) {
|
|
||||||
if(model_->showHidden() || !newItem->fileInfo_ || !fm_file_info_is_hidden(newItem->fileInfo_)) {
|
|
||||||
const char* new_key = fm_file_info_get_collate_key(newItem->fileInfo_);
|
|
||||||
int pos = 0;
|
|
||||||
QList<DirTreeModelItem*>::iterator it;
|
|
||||||
for(it = children_.begin(); it != children_.end(); ++it) {
|
|
||||||
DirTreeModelItem* child = *it;
|
|
||||||
if(G_UNLIKELY(!child->fileInfo_))
|
|
||||||
continue;
|
|
||||||
const char* key = fm_file_info_get_collate_key(child->fileInfo_);
|
|
||||||
if(strcmp(new_key, key) <= 0)
|
|
||||||
break;
|
|
||||||
++pos;
|
|
||||||
}
|
|
||||||
// inform the world that we're about to insert the item
|
|
||||||
model_->beginInsertRows(index(), pos, pos);
|
|
||||||
newItem->parent_ = this;
|
|
||||||
children_.insert(it, newItem);
|
|
||||||
model_->endInsertRows();
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
else { // hidden folder
|
|
||||||
hiddenChildren_.append(newItem);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// FmFolder signal handlers
|
|
||||||
|
|
||||||
// static
|
|
||||||
void DirTreeModelItem::onFolderFinishLoading(FmFolder* folder, gpointer user_data) {
|
|
||||||
DirTreeModelItem* _this = (DirTreeModelItem*)user_data;
|
|
||||||
DirTreeModel* model = _this->model_;
|
|
||||||
/* set 'loaded' flag beforehand as callback may check it */
|
|
||||||
_this->loaded_ = true;
|
|
||||||
QModelIndex index = _this->index();
|
|
||||||
qDebug() << "folder loaded";
|
|
||||||
// remove the placeholder child if needed
|
|
||||||
if(_this->children_.count() == 1) { // we have no other child other than the place holder item, leave it
|
|
||||||
_this->placeHolderChild_->displayName_ = DirTreeModel::tr("<No sub folders>");
|
|
||||||
QModelIndex placeHolderIndex = _this->placeHolderChild_->index();
|
|
||||||
// qDebug() << "placeHolderIndex: "<<placeHolderIndex;
|
|
||||||
Q_EMIT model->dataChanged(placeHolderIndex, placeHolderIndex);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int pos = _this->children_.indexOf(_this->placeHolderChild_);
|
|
||||||
model->beginRemoveRows(index, pos, pos);
|
|
||||||
_this->children_.removeAt(pos);
|
|
||||||
delete _this->placeHolderChild_;
|
|
||||||
model->endRemoveRows();
|
|
||||||
_this->placeHolderChild_ = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_EMIT model->rowLoaded(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
void DirTreeModelItem::onFolderFilesAdded(FmFolder* folder, GSList* files, gpointer user_data) {
|
|
||||||
GSList* l;
|
|
||||||
DirTreeModelItem* _this = (DirTreeModelItem*)user_data;
|
|
||||||
for(l = files; l; l = l->next) {
|
|
||||||
FmFileInfo* fi = FM_FILE_INFO(l->data);
|
|
||||||
if(fm_file_info_is_dir(fi)) { /* FIXME: maybe adding files can be allowed later */
|
|
||||||
/* Ideally FmFolder should not emit files-added signals for files that
|
|
||||||
* already exists. So there is no need to check for duplication here. */
|
|
||||||
_this->insertFileInfo(fi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
void DirTreeModelItem::onFolderFilesRemoved(FmFolder* folder, GSList* files, gpointer user_data) {
|
|
||||||
DirTreeModelItem* _this = (DirTreeModelItem*)user_data;
|
|
||||||
DirTreeModel* model = _this->model_;
|
|
||||||
|
|
||||||
for(GSList* l = files; l; l = l->next) {
|
|
||||||
FmFileInfo* fi = FM_FILE_INFO(l->data);
|
|
||||||
int pos;
|
|
||||||
DirTreeModelItem* child = _this->childFromName(fm_file_info_get_name(fi), &pos);
|
|
||||||
if(child) {
|
|
||||||
model->beginRemoveRows(_this->index(), pos, pos);
|
|
||||||
_this->children_.removeAt(pos);
|
|
||||||
delete child;
|
|
||||||
model->endRemoveRows();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
void DirTreeModelItem::onFolderFilesChanged(FmFolder* folder, GSList* files, gpointer user_data) {
|
|
||||||
DirTreeModelItem* _this = (DirTreeModelItem*)user_data;
|
|
||||||
DirTreeModel* model = _this->model_;
|
|
||||||
|
|
||||||
for(GSList* l = files; l; l = l->next) {
|
|
||||||
FmFileInfo* changedFile = FM_FILE_INFO(l->data);
|
|
||||||
int pos;
|
|
||||||
DirTreeModelItem* child = _this->childFromName(fm_file_info_get_name(changedFile), &pos);
|
|
||||||
if(child) {
|
|
||||||
QModelIndex childIndex = child->index();
|
|
||||||
Q_EMIT model->dataChanged(childIndex, childIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DirTreeModelItem* DirTreeModelItem::childFromName(const char* utf8_name, int* pos) {
|
|
||||||
int i = 0;
|
|
||||||
Q_FOREACH(DirTreeModelItem* item, children_) {
|
|
||||||
if(item->fileInfo_ && strcmp(fm_file_info_get_name(item->fileInfo_), utf8_name) == 0) {
|
|
||||||
if(pos)
|
|
||||||
*pos = i;
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
DirTreeModelItem* DirTreeModelItem::childFromPath(FmPath* path, bool recursive) const {
|
|
||||||
Q_ASSERT(path != NULL);
|
|
||||||
|
|
||||||
Q_FOREACH(DirTreeModelItem* item, children_) {
|
|
||||||
// if(item->fileInfo_)
|
|
||||||
// qDebug() << "child: " << QString::fromUtf8(fm_file_info_get_disp_name(item->fileInfo_));
|
|
||||||
if(item->fileInfo_ && fm_path_equal(fm_file_info_get_path(item->fileInfo_), path)) {
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
else if(recursive) {
|
|
||||||
DirTreeModelItem* child = item->childFromPath(path, true);
|
|
||||||
if(child)
|
|
||||||
return child;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirTreeModelItem::setShowHidden(bool show) {
|
|
||||||
if(show) {
|
|
||||||
// move all hidden children to visible list
|
|
||||||
Q_FOREACH(DirTreeModelItem* item, hiddenChildren_) {
|
|
||||||
insertItem(item);
|
|
||||||
}
|
|
||||||
hiddenChildren_.clear();
|
|
||||||
}
|
|
||||||
else { // hide hidden folders
|
|
||||||
QModelIndex _index = index();
|
|
||||||
QList<DirTreeModelItem*>::iterator it, next;
|
|
||||||
int pos = 0;
|
|
||||||
for(it = children_.begin(); it != children_.end(); ++pos) {
|
|
||||||
DirTreeModelItem* item = *it;
|
|
||||||
next = it + 1;
|
|
||||||
if(item->fileInfo_) {
|
|
||||||
if(fm_file_info_is_hidden(item->fileInfo_)) { // hidden folder
|
|
||||||
// remove from the model and add to the hiddenChildren_ list
|
|
||||||
model_->beginRemoveRows(_index, pos, pos);
|
|
||||||
children_.erase(it);
|
|
||||||
hiddenChildren_.append(item);
|
|
||||||
model_->endRemoveRows();
|
|
||||||
}
|
|
||||||
else { // visible folder, recursively filter its children
|
|
||||||
item->setShowHidden(show);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
it = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Fm
|
|
||||||
|
|
||||||
@ -1,84 +0,0 @@
|
|||||||
/*
|
|
||||||
* <one line to give the program's name and a brief idea of what it does.>
|
|
||||||
* Copyright (C) 2014 <copyright holder> <email>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FM_DIRTREEMODELITEM_H
|
|
||||||
#define FM_DIRTREEMODELITEM_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
#include <QIcon>
|
|
||||||
#include <QList>
|
|
||||||
#include <QModelIndex>
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class DirTreeModel;
|
|
||||||
class DirTreeView;
|
|
||||||
|
|
||||||
class LIBFM_QT_API DirTreeModelItem {
|
|
||||||
public:
|
|
||||||
friend class DirTreeModel; // allow direct access of private members in DirTreeModel
|
|
||||||
friend class DirTreeView; // allow direct access of private members in DirTreeView
|
|
||||||
|
|
||||||
explicit DirTreeModelItem();
|
|
||||||
explicit DirTreeModelItem(FmFileInfo* info, DirTreeModel* model, DirTreeModelItem* parent = NULL);
|
|
||||||
~DirTreeModelItem();
|
|
||||||
|
|
||||||
void loadFolder();
|
|
||||||
void unloadFolder();
|
|
||||||
|
|
||||||
bool isPlaceHolder() {
|
|
||||||
return (fileInfo_ == NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setShowHidden(bool show);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void freeFolder();
|
|
||||||
void addPlaceHolderChild();
|
|
||||||
DirTreeModelItem* childFromName(const char* utf8_name, int* pos);
|
|
||||||
DirTreeModelItem* childFromPath(FmPath* path, bool recursive) const;
|
|
||||||
|
|
||||||
DirTreeModelItem* insertFileInfo(FmFileInfo* fi);
|
|
||||||
int insertItem(Fm::DirTreeModelItem* newItem);
|
|
||||||
QModelIndex index();
|
|
||||||
|
|
||||||
static void onFolderFinishLoading(FmFolder* folder, gpointer user_data);
|
|
||||||
static void onFolderFilesAdded(FmFolder* folder, GSList* files, gpointer user_data);
|
|
||||||
static void onFolderFilesRemoved(FmFolder* folder, GSList* files, gpointer user_data);
|
|
||||||
static void onFolderFilesChanged(FmFolder* folder, GSList* files, gpointer user_data);
|
|
||||||
|
|
||||||
private:
|
|
||||||
FmFileInfo* fileInfo_;
|
|
||||||
FmFolder* folder_;
|
|
||||||
QString displayName_ ;
|
|
||||||
QIcon icon_;
|
|
||||||
bool expanded_;
|
|
||||||
bool loaded_;
|
|
||||||
DirTreeModelItem* parent_;
|
|
||||||
DirTreeModelItem* placeHolderChild_;
|
|
||||||
QList<DirTreeModelItem*> children_;
|
|
||||||
QList<DirTreeModelItem*> hiddenChildren_;
|
|
||||||
DirTreeModel* model_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_DIRTREEMODELITEM_H
|
|
||||||
@ -1,296 +0,0 @@
|
|||||||
/*
|
|
||||||
* <one line to give the program's name and a brief idea of what it does.>
|
|
||||||
* Copyright (C) 2014 <copyright holder> <email>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "dirtreeview.h"
|
|
||||||
#include <QHeaderView>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QItemSelection>
|
|
||||||
#include <QGuiApplication>
|
|
||||||
#include <QMouseEvent>
|
|
||||||
#include "dirtreemodel.h"
|
|
||||||
#include "dirtreemodelitem.h"
|
|
||||||
#include "filemenu.h"
|
|
||||||
|
|
||||||
using namespace Fm;
|
|
||||||
|
|
||||||
DirTreeView::DirTreeView(QWidget* parent):
|
|
||||||
currentExpandingItem_(NULL),
|
|
||||||
currentPath_(NULL) {
|
|
||||||
|
|
||||||
setSelectionMode(QAbstractItemView::SingleSelection);
|
|
||||||
setHeaderHidden(true);
|
|
||||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
|
||||||
header()->setStretchLastSection(false);
|
|
||||||
|
|
||||||
connect(this, &DirTreeView::collapsed, this, &DirTreeView::onCollapsed);
|
|
||||||
connect(this, &DirTreeView::expanded, this, &DirTreeView::onExpanded);
|
|
||||||
|
|
||||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
|
||||||
connect(this, &DirTreeView::customContextMenuRequested,
|
|
||||||
this, &DirTreeView::onCustomContextMenuRequested);
|
|
||||||
}
|
|
||||||
|
|
||||||
DirTreeView::~DirTreeView() {
|
|
||||||
if(currentPath_)
|
|
||||||
fm_path_unref(currentPath_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirTreeView::cancelPendingChdir() {
|
|
||||||
if(!pathsToExpand_.isEmpty()) {
|
|
||||||
pathsToExpand_.clear();
|
|
||||||
if(!currentExpandingItem_)
|
|
||||||
return;
|
|
||||||
DirTreeModel* _model = static_cast<DirTreeModel*>(model());
|
|
||||||
disconnect(_model, &DirTreeModel::rowLoaded, this, &DirTreeView::onRowLoaded);
|
|
||||||
currentExpandingItem_ = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirTreeView::expandPendingPath() {
|
|
||||||
if(pathsToExpand_.isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
FmPath* path = pathsToExpand_.first().data();
|
|
||||||
// qDebug() << "expanding: " << Path(path).displayBasename();
|
|
||||||
DirTreeModel* _model = static_cast<DirTreeModel*>(model());
|
|
||||||
DirTreeModelItem* item = _model->itemFromPath(path);
|
|
||||||
// qDebug() << "findItem: " << item;
|
|
||||||
if(item) {
|
|
||||||
currentExpandingItem_ = item;
|
|
||||||
connect(_model, &DirTreeModel::rowLoaded, this, &DirTreeView::onRowLoaded);
|
|
||||||
if(item->loaded_) { // the node is already loaded
|
|
||||||
onRowLoaded(item->index());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// _model->loadRow(item->index());
|
|
||||||
item->loadFolder();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
selectionModel()->clear();
|
|
||||||
/* since we never get it loaded we need to update cwd here */
|
|
||||||
if(currentPath_)
|
|
||||||
fm_path_unref(currentPath_);
|
|
||||||
currentPath_ = fm_path_ref(path);
|
|
||||||
|
|
||||||
cancelPendingChdir(); // FIXME: is this correct? this is not done in the gtk+ version of libfm.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirTreeView::onRowLoaded(const QModelIndex& index) {
|
|
||||||
DirTreeModel* _model = static_cast<DirTreeModel*>(model());
|
|
||||||
if(!currentExpandingItem_)
|
|
||||||
return;
|
|
||||||
if(currentExpandingItem_ != _model->itemFromIndex(index)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* disconnect the handler since we only need it once */
|
|
||||||
disconnect(_model, &DirTreeModel::rowLoaded, this, &DirTreeView::onRowLoaded);
|
|
||||||
|
|
||||||
// DirTreeModelItem* item = _model->itemFromIndex(index);
|
|
||||||
// qDebug() << "row loaded: " << item->displayName_;
|
|
||||||
/* after the folder is loaded, the files should have been added to
|
|
||||||
* the tree model */
|
|
||||||
expand(index);
|
|
||||||
|
|
||||||
/* remove the expanded path from pending list */
|
|
||||||
pathsToExpand_.removeFirst();
|
|
||||||
if(pathsToExpand_.isEmpty()) { /* this is the last one and we're done, select the item */
|
|
||||||
// qDebug() << "Done!";
|
|
||||||
selectionModel()->select(index, QItemSelectionModel::SelectCurrent|QItemSelectionModel::Clear);
|
|
||||||
scrollTo(index, QAbstractItemView::EnsureVisible);
|
|
||||||
}
|
|
||||||
else { /* continue expanding next pending path */
|
|
||||||
expandPendingPath();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DirTreeView::setCurrentPath(FmPath* path) {
|
|
||||||
DirTreeModel* _model = static_cast<DirTreeModel*>(model());
|
|
||||||
if(!_model)
|
|
||||||
return;
|
|
||||||
int rowCount = _model->rowCount(QModelIndex());
|
|
||||||
if(rowCount <= 0 || fm_path_equal(currentPath_, path))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(currentPath_)
|
|
||||||
fm_path_unref(currentPath_);
|
|
||||||
currentPath_ = fm_path_ref(path);
|
|
||||||
|
|
||||||
// NOTE: The content of each node is loaded on demand dynamically.
|
|
||||||
// So, when we ask for a chdir operation, some nodes do not exists yet.
|
|
||||||
// We have to wait for the loading of child nodes and continue the
|
|
||||||
// pending chdir operation after the child nodes become available.
|
|
||||||
|
|
||||||
// cancel previous pending tree expansion
|
|
||||||
cancelPendingChdir();
|
|
||||||
|
|
||||||
/* find a root item containing this path */
|
|
||||||
FmPath* root;
|
|
||||||
for(int row = 0; row < rowCount; ++row) {
|
|
||||||
QModelIndex index = _model->index(row, 0, QModelIndex());
|
|
||||||
root = _model->filePath(index);
|
|
||||||
if(fm_path_has_prefix(path, root))
|
|
||||||
break;
|
|
||||||
root = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(root) { /* root item is found */
|
|
||||||
do { /* add path elements one by one to a list */
|
|
||||||
pathsToExpand_.prepend(path);
|
|
||||||
// qDebug() << "prepend path: " << Path(path).displayBasename();
|
|
||||||
if(fm_path_equal(path, root))
|
|
||||||
break;
|
|
||||||
path = fm_path_get_parent(path);
|
|
||||||
}
|
|
||||||
while(path);
|
|
||||||
|
|
||||||
expandPendingPath();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirTreeView::setModel(QAbstractItemModel* model) {
|
|
||||||
Q_ASSERT(model->inherits("Fm::DirTreeModel"));
|
|
||||||
|
|
||||||
if(!pathsToExpand_.isEmpty()) // if a chdir request is in progress, cancel it
|
|
||||||
cancelPendingChdir();
|
|
||||||
|
|
||||||
QTreeView::setModel(model);
|
|
||||||
header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
|
|
||||||
connect(selectionModel(), &QItemSelectionModel::selectionChanged, this, &DirTreeView::onSelectionChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirTreeView::mousePressEvent(QMouseEvent* event) {
|
|
||||||
if(event && event->button() == Qt::RightButton &&
|
|
||||||
event->type() == QEvent::MouseButtonPress) {
|
|
||||||
// Do not change the selection when the context menu is activated.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QTreeView::mousePressEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirTreeView::onCustomContextMenuRequested(const QPoint& pos) {
|
|
||||||
QModelIndex index = indexAt(pos);
|
|
||||||
if(index.isValid()) {
|
|
||||||
QVariant data = index.data(DirTreeModel::FileInfoRole);
|
|
||||||
FmFileInfo* fileInfo = reinterpret_cast<FmFileInfo*>(data.value<void*>());
|
|
||||||
if(fileInfo) {
|
|
||||||
FmPath* path = fm_file_info_get_path(fileInfo);
|
|
||||||
FmFileInfoList* files = fm_file_info_list_new();
|
|
||||||
fm_file_info_list_push_tail(files, fileInfo);
|
|
||||||
Fm::FileMenu* menu = new Fm::FileMenu(files, fileInfo, path);
|
|
||||||
// FIXME: apply some settings to the menu and set a proper file launcher to it
|
|
||||||
Q_EMIT prepareFileMenu(menu);
|
|
||||||
fm_file_info_list_unref(files);
|
|
||||||
QVariant pathData = qVariantFromValue(reinterpret_cast<void*>(path));
|
|
||||||
QAction* action = menu->openAction();
|
|
||||||
action->disconnect();
|
|
||||||
action->setData(index);
|
|
||||||
connect(action, &QAction::triggered, this, &DirTreeView::onOpen);
|
|
||||||
action = new QAction(QIcon::fromTheme("window-new"), tr("Open in New T&ab"), menu);
|
|
||||||
action->setData(pathData);
|
|
||||||
connect(action, &QAction::triggered, this, &DirTreeView::onNewTab);
|
|
||||||
menu->insertAction(menu->separator1(), action);
|
|
||||||
action = new QAction(QIcon::fromTheme("window-new"), tr("Open in New Win&dow"), menu);
|
|
||||||
action->setData(pathData);
|
|
||||||
connect(action, &QAction::triggered, this, &DirTreeView::onNewWindow);
|
|
||||||
menu->insertAction(menu->separator1(), action);
|
|
||||||
if(fm_file_info_is_native(fileInfo)) {
|
|
||||||
action = new QAction(QIcon::fromTheme("utilities-terminal"), tr("Open in Termina&l"), menu);
|
|
||||||
action->setData(pathData);
|
|
||||||
connect(action, &QAction::triggered, this, &DirTreeView::onOpenInTerminal);
|
|
||||||
menu->insertAction(menu->separator1(), action);
|
|
||||||
}
|
|
||||||
menu->exec(mapToGlobal(pos));
|
|
||||||
delete menu;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirTreeView::onOpen() {
|
|
||||||
if(QAction* action = qobject_cast<QAction*>(sender())) {
|
|
||||||
setCurrentIndex(action->data().toModelIndex());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirTreeView::onNewWindow() {
|
|
||||||
if(QAction* action = qobject_cast<QAction*>(sender())) {
|
|
||||||
FmPath* path = reinterpret_cast<FmPath*>(action->data().value<void*>());
|
|
||||||
Q_EMIT openFolderInNewWindowRequested(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirTreeView::onNewTab() {
|
|
||||||
if(QAction* action = qobject_cast<QAction*>(sender())) {
|
|
||||||
FmPath* path = reinterpret_cast<FmPath*>(action->data().value<void*>());
|
|
||||||
Q_EMIT openFolderInNewTabRequested(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirTreeView::onOpenInTerminal() {
|
|
||||||
if(QAction* action = qobject_cast<QAction*>(sender())) {
|
|
||||||
FmPath* path = reinterpret_cast<FmPath*>(action->data().value<void*>());
|
|
||||||
Q_EMIT openFolderInTerminalRequested(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirTreeView::onNewFolder() {
|
|
||||||
if(QAction* action = qobject_cast<QAction*>(sender())) {
|
|
||||||
FmPath* path = reinterpret_cast<FmPath*>(action->data().value<void*>());
|
|
||||||
Q_EMIT createNewFolderRequested(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirTreeView::onCollapsed(const QModelIndex& index) {
|
|
||||||
DirTreeModel* treeModel = static_cast<DirTreeModel*>(model());
|
|
||||||
if(treeModel) {
|
|
||||||
treeModel->unloadRow(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirTreeView::onExpanded(const QModelIndex& index) {
|
|
||||||
DirTreeModel* treeModel = static_cast<DirTreeModel*>(model());
|
|
||||||
if(treeModel) {
|
|
||||||
treeModel->loadRow(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirTreeView::onSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected) {
|
|
||||||
if(!selected.isEmpty()) {
|
|
||||||
QModelIndex index = selected.first().topLeft();
|
|
||||||
DirTreeModel* _model = static_cast<DirTreeModel*>(model());
|
|
||||||
FmPath* path = _model->filePath(index);
|
|
||||||
if(path && currentPath_ && fm_path_equal(path, currentPath_))
|
|
||||||
return;
|
|
||||||
cancelPendingChdir();
|
|
||||||
if(!path)
|
|
||||||
return;
|
|
||||||
if(currentPath_)
|
|
||||||
fm_path_unref(currentPath_);
|
|
||||||
currentPath_ = fm_path_ref(path);
|
|
||||||
|
|
||||||
// FIXME: use enums for type rather than hard-coded values 0 or 1
|
|
||||||
int type = 0;
|
|
||||||
if(QGuiApplication::mouseButtons() & Qt::MiddleButton)
|
|
||||||
type = 1;
|
|
||||||
Q_EMIT chdirRequested(type, path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,95 +0,0 @@
|
|||||||
/*
|
|
||||||
* <one line to give the program's name and a brief idea of what it does.>
|
|
||||||
* Copyright (C) 2014 <copyright holder> <email>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FM_DIRTREEVIEW_H
|
|
||||||
#define FM_DIRTREEVIEW_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QTreeView>
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
#include "path.h"
|
|
||||||
|
|
||||||
class QItemSelection;
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class FileMenu;
|
|
||||||
class DirTreeModelItem;
|
|
||||||
|
|
||||||
class LIBFM_QT_API DirTreeView : public QTreeView {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
DirTreeView(QWidget* parent);
|
|
||||||
~DirTreeView();
|
|
||||||
|
|
||||||
FmPath* currentPath() {
|
|
||||||
return currentPath_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCurrentPath(FmPath* path);
|
|
||||||
|
|
||||||
// libfm-gtk compatible alias
|
|
||||||
FmPath* getCwd() {
|
|
||||||
return currentPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
void chdir(FmPath* path) {
|
|
||||||
setCurrentPath(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setModel(QAbstractItemModel* model);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void mousePressEvent(QMouseEvent* event);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void cancelPendingChdir();
|
|
||||||
void expandPendingPath();
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void chdirRequested(int type, FmPath* path);
|
|
||||||
void openFolderInNewWindowRequested(FmPath* path);
|
|
||||||
void openFolderInNewTabRequested(FmPath* path);
|
|
||||||
void openFolderInTerminalRequested(FmPath* path);
|
|
||||||
void createNewFolderRequested(FmPath* path);
|
|
||||||
void prepareFileMenu(Fm::FileMenu* menu); // emit before showing a Fm::FileMenu
|
|
||||||
|
|
||||||
protected Q_SLOTS:
|
|
||||||
void onCollapsed(const QModelIndex & index);
|
|
||||||
void onExpanded(const QModelIndex & index);
|
|
||||||
void onRowLoaded(const QModelIndex& index);
|
|
||||||
void onSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected);
|
|
||||||
void onCustomContextMenuRequested(const QPoint& pos);
|
|
||||||
void onOpen();
|
|
||||||
void onNewWindow();
|
|
||||||
void onNewTab();
|
|
||||||
void onOpenInTerminal();
|
|
||||||
void onNewFolder();
|
|
||||||
|
|
||||||
private:
|
|
||||||
FmPath* currentPath_;
|
|
||||||
QList<Path> pathsToExpand_;
|
|
||||||
DirTreeModelItem* currentExpandingItem_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_DIRTREEVIEW_H
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "dndactionmenu.h"
|
|
||||||
|
|
||||||
using namespace Fm;
|
|
||||||
|
|
||||||
DndActionMenu::DndActionMenu(QWidget* parent): QMenu(parent) {
|
|
||||||
copyAction = addAction(QIcon::fromTheme("edit-copy"), tr("Copy here"));
|
|
||||||
moveAction = addAction(tr("Move here"));
|
|
||||||
linkAction = addAction(tr("Create symlink here"));
|
|
||||||
addSeparator();
|
|
||||||
cancelAction = addAction(tr("Cancel"));
|
|
||||||
}
|
|
||||||
|
|
||||||
DndActionMenu::~DndActionMenu() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Qt::DropAction DndActionMenu::askUser(QPoint pos) {
|
|
||||||
Qt::DropAction result;
|
|
||||||
DndActionMenu menu;
|
|
||||||
QAction* action = menu.exec(pos);
|
|
||||||
if(action == menu.copyAction)
|
|
||||||
result = Qt::CopyAction;
|
|
||||||
else if(action == menu.moveAction)
|
|
||||||
result = Qt::MoveAction;
|
|
||||||
else if(action == menu.linkAction)
|
|
||||||
result = Qt::LinkAction;
|
|
||||||
else
|
|
||||||
result = Qt::IgnoreAction;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FM_DNDACTIONMENU_H
|
|
||||||
#define FM_DNDACTIONMENU_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QMenu>
|
|
||||||
#include <QAction>
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class DndActionMenu : public QMenu {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit DndActionMenu(QWidget* parent = 0);
|
|
||||||
virtual ~DndActionMenu();
|
|
||||||
|
|
||||||
static Qt::DropAction askUser(QPoint pos);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QAction* copyAction;
|
|
||||||
QAction* moveAction;
|
|
||||||
QAction* linkAction;
|
|
||||||
QAction* cancelAction;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_DNDACTIONMENU_H
|
|
||||||
@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* <one line to give the program's name and a brief idea of what it does.>
|
|
||||||
* Copyright (C) 2014 <copyright holder> <email>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "dnddest.h"
|
|
||||||
#include "fileoperation.h"
|
|
||||||
#include "utilities.h"
|
|
||||||
|
|
||||||
using namespace Fm;
|
|
||||||
|
|
||||||
const char* supportedMimeTypes[] = {
|
|
||||||
"text/uri-list"
|
|
||||||
"XdndDirectSave0"/* X direct save */
|
|
||||||
/* TODO: add more targets to support: text types, _NETSCAPE_URL, property/bgimage ... */
|
|
||||||
};
|
|
||||||
|
|
||||||
DndDest::DndDest() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DndDest::~DndDest() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DndDest::dropMimeData(const QMimeData* data, Qt::DropAction action) {
|
|
||||||
// FIXME: should we put this in dropEvent handler of FolderView instead?
|
|
||||||
if(data->hasUrls()) {
|
|
||||||
qDebug("drop action: %d", action);
|
|
||||||
FmPathList* srcPaths = pathListFromQUrls(data->urls());
|
|
||||||
switch(action) {
|
|
||||||
case Qt::CopyAction:
|
|
||||||
FileOperation::copyFiles(srcPaths, destPath_.data());
|
|
||||||
break;
|
|
||||||
case Qt::MoveAction:
|
|
||||||
FileOperation::moveFiles(srcPaths, destPath_.data());
|
|
||||||
break;
|
|
||||||
case Qt::LinkAction:
|
|
||||||
FileOperation::symlinkFiles(srcPaths, destPath_.data());
|
|
||||||
default:
|
|
||||||
fm_path_list_unref(srcPaths);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
fm_path_list_unref(srcPaths);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DndDest::isSupported(const QMimeData* data) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DndDest::isSupported(QString mimeType) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
* <one line to give the program's name and a brief idea of what it does.>
|
|
||||||
* Copyright (C) 2014 <copyright holder> <email>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FM_DNDDEST_H
|
|
||||||
#define FM_DNDDEST_H
|
|
||||||
|
|
||||||
#include <QMimeData>
|
|
||||||
#include "path.h"
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class DndDest {
|
|
||||||
public:
|
|
||||||
DndDest();
|
|
||||||
~DndDest();
|
|
||||||
|
|
||||||
void setDestPath(FmPath* dest) {
|
|
||||||
destPath_ = dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Path& destPath() {
|
|
||||||
return destPath_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isSupported(const QMimeData* data);
|
|
||||||
bool isSupported(QString mimeType);
|
|
||||||
|
|
||||||
bool dropMimeData(const QMimeData* data, Qt::DropAction action);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Path destPath_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_DNDDEST_H
|
|
||||||
@ -1,143 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>EditBookmarksDialog</class>
|
|
||||||
<widget class="QDialog" name="EditBookmarksDialog">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>480</width>
|
|
||||||
<height>320</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Edit Bookmarks</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QTreeWidget" name="treeWidget">
|
|
||||||
<property name="acceptDrops">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="dragEnabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="dragDropMode">
|
|
||||||
<enum>QAbstractItemView::InternalMove</enum>
|
|
||||||
</property>
|
|
||||||
<property name="defaultDropAction">
|
|
||||||
<enum>Qt::MoveAction</enum>
|
|
||||||
</property>
|
|
||||||
<property name="rootIsDecorated">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="itemsExpandable">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<attribute name="headerDefaultSectionSize">
|
|
||||||
<number>100</number>
|
|
||||||
</attribute>
|
|
||||||
<column>
|
|
||||||
<property name="text">
|
|
||||||
<string>Name</string>
|
|
||||||
</property>
|
|
||||||
</column>
|
|
||||||
<column>
|
|
||||||
<property name="text">
|
|
||||||
<string>Location</string>
|
|
||||||
</property>
|
|
||||||
</column>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0" colspan="2">
|
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="addItem">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Add Item</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="list-add"/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="removeItem">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Remove Item</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="list-remove"/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Use drag and drop to reorder the items</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>accepted()</signal>
|
|
||||||
<receiver>EditBookmarksDialog</receiver>
|
|
||||||
<slot>accept()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>248</x>
|
|
||||||
<y>254</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>157</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>rejected()</signal>
|
|
||||||
<receiver>EditBookmarksDialog</receiver>
|
|
||||||
<slot>reject()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>316</x>
|
|
||||||
<y>260</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>286</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
</connections>
|
|
||||||
</ui>
|
|
||||||
@ -1,109 +0,0 @@
|
|||||||
/*
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) 2013 PCMan <email>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "editbookmarksdialog.h"
|
|
||||||
#include "ui_edit-bookmarks.h"
|
|
||||||
#include <QByteArray>
|
|
||||||
#include <QUrl>
|
|
||||||
#include <QSaveFile>
|
|
||||||
#include <QStandardPaths>
|
|
||||||
#include <QDir>
|
|
||||||
|
|
||||||
using namespace Fm;
|
|
||||||
|
|
||||||
EditBookmarksDialog::EditBookmarksDialog(FmBookmarks* bookmarks, QWidget* parent, Qt::WindowFlags f):
|
|
||||||
QDialog(parent, f),
|
|
||||||
ui(new Ui::EditBookmarksDialog()),
|
|
||||||
bookmarks_(FM_BOOKMARKS(g_object_ref(bookmarks))) {
|
|
||||||
|
|
||||||
ui->setupUi(this);
|
|
||||||
setAttribute(Qt::WA_DeleteOnClose); // auto delete on close
|
|
||||||
|
|
||||||
// load bookmarks
|
|
||||||
GList* allBookmarks = fm_bookmarks_get_all(bookmarks_);
|
|
||||||
for(GList* l = allBookmarks; l; l = l->next) {
|
|
||||||
FmBookmarkItem* bookmark = reinterpret_cast<FmBookmarkItem*>(l->data);
|
|
||||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
|
||||||
char* path_str = fm_path_display_name(bookmark->path, false);
|
|
||||||
item->setData(0, Qt::DisplayRole, QString::fromUtf8(bookmark->name));
|
|
||||||
item->setData(1, Qt::DisplayRole, QString::fromUtf8(path_str));
|
|
||||||
item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEditable|Qt::ItemIsDragEnabled|Qt::ItemIsEnabled);
|
|
||||||
g_free(path_str);
|
|
||||||
ui->treeWidget->addTopLevelItem(item);
|
|
||||||
}
|
|
||||||
g_list_free_full(allBookmarks, (GDestroyNotify)fm_bookmark_item_unref);
|
|
||||||
|
|
||||||
connect(ui->addItem, &QPushButton::clicked, this, &EditBookmarksDialog::onAddItem);
|
|
||||||
connect(ui->removeItem, &QPushButton::clicked, this, &EditBookmarksDialog::onRemoveItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
EditBookmarksDialog::~EditBookmarksDialog() {
|
|
||||||
g_object_unref(bookmarks_);
|
|
||||||
delete ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditBookmarksDialog::accept() {
|
|
||||||
// save bookmarks
|
|
||||||
// it's easier to recreate the whole bookmark file than
|
|
||||||
// to manipulate FmBookmarks object. So here we generate the file directly.
|
|
||||||
// FIXME: maybe in the future we should add a libfm API to easily replace all FmBookmarks.
|
|
||||||
// Here we use gtk+ 3.0 bookmarks rather than the gtk+ 2.0 one.
|
|
||||||
// Since gtk+ 2.24.12, gtk+2 reads gtk+3 bookmarks file if it exists.
|
|
||||||
// So it's safe to only save gtk+3 bookmarks file.
|
|
||||||
QString path = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation);
|
|
||||||
path += QLatin1String("/gtk-3.0");
|
|
||||||
if(!QDir().mkpath(path))
|
|
||||||
return; // fail to create ~/.config/gtk-3.0 dir
|
|
||||||
path += QLatin1String("/bookmarks");
|
|
||||||
QSaveFile file(path); // use QSaveFile for atomic file operation
|
|
||||||
if(file.open(QIODevice::WriteOnly)){
|
|
||||||
for(int row = 0; ; ++row) {
|
|
||||||
QTreeWidgetItem* item = ui->treeWidget->topLevelItem(row);
|
|
||||||
if(!item)
|
|
||||||
break;
|
|
||||||
QString name = item->data(0, Qt::DisplayRole).toString();
|
|
||||||
QUrl url = QUrl::fromUserInput(item->data(1, Qt::DisplayRole).toString());
|
|
||||||
file.write(url.toEncoded());
|
|
||||||
file.write(" ");
|
|
||||||
file.write(name.toUtf8());
|
|
||||||
file.write("\n");
|
|
||||||
}
|
|
||||||
// FIXME: should we support Qt or KDE specific bookmarks in the future?
|
|
||||||
file.commit();
|
|
||||||
}
|
|
||||||
QDialog::accept();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditBookmarksDialog::onAddItem() {
|
|
||||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
|
||||||
item->setData(0, Qt::DisplayRole, tr("New bookmark"));
|
|
||||||
item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEditable|Qt::ItemIsDragEnabled|Qt::ItemIsEnabled);
|
|
||||||
ui->treeWidget->addTopLevelItem(item);
|
|
||||||
ui->treeWidget->editItem(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditBookmarksDialog::onRemoveItem() {
|
|
||||||
QList<QTreeWidgetItem*> sels = ui->treeWidget->selectedItems();
|
|
||||||
Q_FOREACH(QTreeWidgetItem* item, sels) {
|
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) 2013 PCMan <email>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FM_EDITBOOKMARKSDIALOG_H
|
|
||||||
#define FM_EDITBOOKMARKSDIALOG_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QDialog>
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class EditBookmarksDialog;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class LIBFM_QT_API EditBookmarksDialog : public QDialog {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit EditBookmarksDialog(FmBookmarks* bookmarks, QWidget* parent = 0, Qt::WindowFlags f = 0);
|
|
||||||
virtual ~EditBookmarksDialog();
|
|
||||||
|
|
||||||
virtual void accept();
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
|
||||||
void onAddItem();
|
|
||||||
void onRemoveItem();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::EditBookmarksDialog* ui;
|
|
||||||
FmBookmarks* bookmarks_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_EDITBOOKMARKSDIALOG_H
|
|
||||||
@ -1,163 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>ExecFileDialog</class>
|
|
||||||
<widget class="QDialog" name="ExecFileDialog">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>487</width>
|
|
||||||
<height>58</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Execute file</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,1">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="icon"/>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="msg">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="open">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Open</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="document-open"/>
|
|
||||||
</property>
|
|
||||||
<property name="default">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="exec">
|
|
||||||
<property name="text">
|
|
||||||
<string>E&xecute</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="system-run"/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="execTerm">
|
|
||||||
<property name="text">
|
|
||||||
<string>Execute in &Terminal</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="utilities-terminal"/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="cancel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Cancel</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="dialog-cancel"/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections>
|
|
||||||
<connection>
|
|
||||||
<sender>cancel</sender>
|
|
||||||
<signal>clicked()</signal>
|
|
||||||
<receiver>ExecFileDialog</receiver>
|
|
||||||
<slot>reject()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>341</x>
|
|
||||||
<y>39</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>196</x>
|
|
||||||
<y>28</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>exec</sender>
|
|
||||||
<signal>clicked()</signal>
|
|
||||||
<receiver>ExecFileDialog</receiver>
|
|
||||||
<slot>accept()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>56</x>
|
|
||||||
<y>39</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>196</x>
|
|
||||||
<y>28</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>execTerm</sender>
|
|
||||||
<signal>clicked()</signal>
|
|
||||||
<receiver>ExecFileDialog</receiver>
|
|
||||||
<slot>accept()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>201</x>
|
|
||||||
<y>39</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>196</x>
|
|
||||||
<y>28</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>open</sender>
|
|
||||||
<signal>clicked()</signal>
|
|
||||||
<receiver>ExecFileDialog</receiver>
|
|
||||||
<slot>accept()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>346</x>
|
|
||||||
<y>39</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>250</x>
|
|
||||||
<y>28</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
</connections>
|
|
||||||
</ui>
|
|
||||||
@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* <one line to give the library's name and an idea of what it does.>
|
|
||||||
* Copyright (C) 2014 <copyright holder> <email>
|
|
||||||
*
|
|
||||||
* 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 "execfiledialog_p.h"
|
|
||||||
#include "ui_exec-file.h"
|
|
||||||
#include "icontheme.h"
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
ExecFileDialog::ExecFileDialog(FmFileInfo* file, QWidget* parent, Qt::WindowFlags f):
|
|
||||||
QDialog (parent, f),
|
|
||||||
fileInfo_(fm_file_info_ref(file)),
|
|
||||||
result_(FM_FILE_LAUNCHER_EXEC_CANCEL),
|
|
||||||
ui(new Ui::ExecFileDialog()) {
|
|
||||||
|
|
||||||
ui->setupUi(this);
|
|
||||||
// show file icon
|
|
||||||
FmIcon* icon = fm_file_info_get_icon(fileInfo_);
|
|
||||||
ui->icon->setPixmap(IconTheme::icon(icon).pixmap(QSize(48, 48)));
|
|
||||||
|
|
||||||
QString msg;
|
|
||||||
if(fm_file_info_is_text(file)) {
|
|
||||||
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)));
|
|
||||||
ui->execTerm->setDefault(true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
msg= tr("This file '%1' is executable. Do you want to execute it?")
|
|
||||||
.arg(QString::fromUtf8(fm_file_info_get_disp_name(file)));
|
|
||||||
ui->exec->setDefault(true);
|
|
||||||
ui->open->hide();
|
|
||||||
}
|
|
||||||
ui->msg->setText(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
ExecFileDialog::~ExecFileDialog() {
|
|
||||||
delete ui;
|
|
||||||
if(fileInfo_)
|
|
||||||
fm_file_info_unref(fileInfo_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExecFileDialog::accept() {
|
|
||||||
QObject* _sender = sender();
|
|
||||||
if(_sender == ui->exec)
|
|
||||||
result_ = FM_FILE_LAUNCHER_EXEC;
|
|
||||||
else if(_sender == ui->execTerm)
|
|
||||||
result_ = FM_FILE_LAUNCHER_EXEC_IN_TERMINAL;
|
|
||||||
else if(_sender == ui->open)
|
|
||||||
result_ = FM_FILE_LAUNCHER_EXEC_OPEN;
|
|
||||||
QDialog::accept();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Fm
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* <one line to give the library's name and an idea of what it does.>
|
|
||||||
* Copyright (C) 2014 <copyright holder> <email>
|
|
||||||
*
|
|
||||||
* 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_EXECFILEDIALOG_H
|
|
||||||
#define FM_EXECFILEDIALOG_H
|
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class ExecFileDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class ExecFileDialog : public QDialog {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
~ExecFileDialog();
|
|
||||||
ExecFileDialog(FmFileInfo* fileInfo, QWidget* parent = 0, Qt::WindowFlags f = 0);
|
|
||||||
|
|
||||||
FmFileLauncherExecAction result() {
|
|
||||||
return result_;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void accept();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::ExecFileDialog* ui;
|
|
||||||
FmFileInfo* fileInfo_;
|
|
||||||
FmFileLauncherExecAction result_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_EXECFILEDIALOG_H
|
|
||||||
@ -1,171 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>FileOperationDialog</class>
|
|
||||||
<widget class="QDialog" name="FileOperationDialog">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>450</width>
|
|
||||||
<height>246</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<layout class="QFormLayout" name="formLayout_2">
|
|
||||||
<item row="0" column="0" colspan="2">
|
|
||||||
<widget class="QLabel" name="message">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<layout class="QFormLayout" name="formLayout">
|
|
||||||
<property name="fieldGrowthPolicy">
|
|
||||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
|
||||||
</property>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="destLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Destination:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QLabel" name="dest">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="text">
|
|
||||||
<string>Processing:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QLabel" name="curFile">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Preparing...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="text">
|
|
||||||
<string>Progress</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QProgressBar" name="progressBar">
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Time remaining:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QLabel" name="timeRemaining">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0" colspan="2">
|
|
||||||
<widget class="QListWidget" name="sourceFiles">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0" colspan="2">
|
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Cancel</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>accepted()</signal>
|
|
||||||
<receiver>FileOperationDialog</receiver>
|
|
||||||
<slot>accept()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>248</x>
|
|
||||||
<y>254</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>157</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>rejected()</signal>
|
|
||||||
<receiver>FileOperationDialog</receiver>
|
|
||||||
<slot>reject()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>316</x>
|
|
||||||
<y>260</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>286</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
</connections>
|
|
||||||
</ui>
|
|
||||||
@ -1,736 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>FilePropsDialog</class>
|
|
||||||
<widget class="QDialog" name="FilePropsDialog">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>424</width>
|
|
||||||
<height>456</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>File Properties</string>
|
|
||||||
</property>
|
|
||||||
<property name="windowIcon">
|
|
||||||
<iconset theme="document-properties">
|
|
||||||
<normaloff/>
|
|
||||||
</iconset>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>10</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>10</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>10</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>10</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QTabWidget" name="tabWidget">
|
|
||||||
<property name="currentIndex">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="generalPage">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>General</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QFormLayout" name="formLayout_2">
|
|
||||||
<property name="horizontalSpacing">
|
|
||||||
<number>12</number>
|
|
||||||
</property>
|
|
||||||
<property name="verticalSpacing">
|
|
||||||
<number>6</number>
|
|
||||||
</property>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QPushButton" name="iconButton">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="unknown">
|
|
||||||
<normaloff/>
|
|
||||||
</iconset>
|
|
||||||
</property>
|
|
||||||
<property name="iconSize">
|
|
||||||
<size>
|
|
||||||
<width>32</width>
|
|
||||||
<height>32</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLineEdit" name="fileName"/>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="text">
|
|
||||||
<string>Location:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QLabel" name="location">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="text">
|
|
||||||
<string>File type:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QLabel" name="fileType">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Mime type:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QLabel" name="mimeType">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="0">
|
|
||||||
<widget class="QLabel" name="label_7">
|
|
||||||
<property name="text">
|
|
||||||
<string>File size:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="1">
|
|
||||||
<widget class="QLabel" name="fileSize">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="0">
|
|
||||||
<widget class="QLabel" name="label_6">
|
|
||||||
<property name="text">
|
|
||||||
<string>On-disk size:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="1">
|
|
||||||
<widget class="QLabel" name="onDiskSize">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="0">
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="text">
|
|
||||||
<string>Last modified:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="1">
|
|
||||||
<widget class="QLabel" name="lastModified">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="targetLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Link target:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QLabel" name="target">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="0">
|
|
||||||
<widget class="QLabel" name="openWithLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Open With:</string>
|
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="1">
|
|
||||||
<widget class="Fm::AppChooserComboBox" name="openWith">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="9" column="0">
|
|
||||||
<widget class="QLabel" name="label_12">
|
|
||||||
<property name="text">
|
|
||||||
<string>Last accessed:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="9" column="1">
|
|
||||||
<widget class="QLabel" name="lastAccessed">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="permissionsPage">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Permissions</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>6</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="groupBox_2">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="title">
|
|
||||||
<string>Ownership</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QFormLayout" name="formLayout">
|
|
||||||
<property name="horizontalSpacing">
|
|
||||||
<number>12</number>
|
|
||||||
</property>
|
|
||||||
<property name="verticalSpacing">
|
|
||||||
<number>6</number>
|
|
||||||
</property>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QLineEdit" name="owner"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QLineEdit" name="ownerGroup"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_9">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Group:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_8">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Owner:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="groupBox">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="title">
|
|
||||||
<string>Access Control</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
|
||||||
<item>
|
|
||||||
<widget class="QStackedWidget" name="stackedWidget">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="currentIndex">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="page">
|
|
||||||
<layout class="QFormLayout" name="formLayout_3">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="ownerLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Owner:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QComboBox" name="ownerPerm">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="groupLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Group:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QComboBox" name="groupPerm">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="otherLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Other:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QComboBox" name="otherPerm">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0" colspan="2">
|
|
||||||
<widget class="QCheckBox" name="executable">
|
|
||||||
<property name="text">
|
|
||||||
<string>Make the file executable</string>
|
|
||||||
</property>
|
|
||||||
<property name="tristate">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="page_2">
|
|
||||||
<layout class="QGridLayout" name="gridLayout_2" columnstretch="1,0,0">
|
|
||||||
<item row="0" column="0" rowspan="3">
|
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="spacing">
|
|
||||||
<number>6</number>
|
|
||||||
</property>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Owner:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QCheckBox" name="checkBox">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Read</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="2">
|
|
||||||
<widget class="QCheckBox" name="checkBox_5">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Write</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="3">
|
|
||||||
<widget class="QCheckBox" name="checkBox_8">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Execute</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_10">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Group:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QCheckBox" name="checkBox_4">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Read</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="2">
|
|
||||||
<widget class="QCheckBox" name="checkBox_9">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Write</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="3">
|
|
||||||
<widget class="QCheckBox" name="checkBox_3">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Execute</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_11">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Other:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QCheckBox" name="checkBox_7">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Read</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="2">
|
|
||||||
<widget class="QCheckBox" name="checkBox_2">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Write</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="3">
|
|
||||||
<widget class="QCheckBox" name="checkBox_6">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Execute</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="2">
|
|
||||||
<widget class="QCheckBox" name="checkBox_10">
|
|
||||||
<property name="text">
|
|
||||||
<string>Sticky</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="2">
|
|
||||||
<widget class="QCheckBox" name="checkBox_11">
|
|
||||||
<property name="text">
|
|
||||||
<string>SetUID</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="2">
|
|
||||||
<widget class="QCheckBox" name="checkBox_12">
|
|
||||||
<property name="text">
|
|
||||||
<string>SetGID</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1" rowspan="3">
|
|
||||||
<widget class="Line" name="line">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="pushButton">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Advanced Mode</string>
|
|
||||||
</property>
|
|
||||||
<property name="checkable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<customwidgets>
|
|
||||||
<customwidget>
|
|
||||||
<class>Fm::AppChooserComboBox</class>
|
|
||||||
<extends>QComboBox</extends>
|
|
||||||
<header>appchoosercombobox.h</header>
|
|
||||||
</customwidget>
|
|
||||||
</customwidgets>
|
|
||||||
<resources/>
|
|
||||||
<connections>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>accepted()</signal>
|
|
||||||
<receiver>FilePropsDialog</receiver>
|
|
||||||
<slot>accept()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>248</x>
|
|
||||||
<y>254</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>157</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>rejected()</signal>
|
|
||||||
<receiver>FilePropsDialog</receiver>
|
|
||||||
<slot>reject()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>316</x>
|
|
||||||
<y>260</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>286</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
</connections>
|
|
||||||
</ui>
|
|
||||||
@ -1,121 +0,0 @@
|
|||||||
/*
|
|
||||||
<one line to give the library's name and an idea of what it does.>
|
|
||||||
Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "filelauncher.h"
|
|
||||||
#include "applaunchcontext.h"
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QDebug>
|
|
||||||
#include "execfiledialog_p.h"
|
|
||||||
#include "appchooserdialog.h"
|
|
||||||
#include "utilities.h"
|
|
||||||
|
|
||||||
using namespace Fm;
|
|
||||||
|
|
||||||
FmFileLauncher FileLauncher::funcs = {
|
|
||||||
FileLauncher::_getApp,
|
|
||||||
/* gboolean (*before_open)(GAppLaunchContext* ctx, GList* folder_infos, gpointer user_data); */
|
|
||||||
(FmLaunchFolderFunc)FileLauncher::_openFolder,
|
|
||||||
FileLauncher::_execFile,
|
|
||||||
FileLauncher::_error,
|
|
||||||
FileLauncher::_ask
|
|
||||||
};
|
|
||||||
|
|
||||||
FileLauncher::FileLauncher():
|
|
||||||
quickExec_(false) {
|
|
||||||
}
|
|
||||||
|
|
||||||
FileLauncher::~FileLauncher() {
|
|
||||||
}
|
|
||||||
|
|
||||||
//static
|
|
||||||
bool FileLauncher::launchFiles(QWidget* parent, GList* file_infos) {
|
|
||||||
FmAppLaunchContext* context = fm_app_launch_context_new_for_widget(parent);
|
|
||||||
bool ret = fm_launch_files(G_APP_LAUNCH_CONTEXT(context), file_infos, &funcs, this);
|
|
||||||
g_object_unref(context);
|
|
||||||
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(NULL);
|
|
||||||
if(mime_type)
|
|
||||||
dlg.setMimeType(mime_type);
|
|
||||||
else
|
|
||||||
dlg.setCanSetDefault(false);
|
|
||||||
// FIXME: show error properly?
|
|
||||||
if(execModelessDialog(&dlg) == QDialog::Accepted) {
|
|
||||||
return dlg.selectedApp();
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
/* FIXME: set default button properly */
|
|
||||||
// return fm_askv(data->parent, NULL, msg, btn_labels);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileLauncher::error(GAppLaunchContext* ctx, GError* err, FmPath* path) {
|
|
||||||
/* ask for mount if trying to launch unmounted path */
|
|
||||||
if(err->domain == G_IO_ERROR) {
|
|
||||||
if(path && err->code == G_IO_ERROR_NOT_MOUNTED) {
|
|
||||||
//if(fm_mount_path(data->parent, path, TRUE))
|
|
||||||
// return FALSE; /* ask to retry */
|
|
||||||
}
|
|
||||||
else if(err->code == G_IO_ERROR_FAILED_HANDLED)
|
|
||||||
return true; /* don't show error message */
|
|
||||||
}
|
|
||||||
QMessageBox dlg(QMessageBox::Critical, QObject::tr("Error"), QString::fromUtf8(err->message), QMessageBox::Ok);
|
|
||||||
execModelessDialog(&dlg);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,87 +0,0 @@
|
|||||||
/*
|
|
||||||
<one line to give the library's name and an idea of what it does.>
|
|
||||||
Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FM_FILELAUNCHER_H
|
|
||||||
#define FM_FILELAUNCHER_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QWidget>
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class LIBFM_QT_API FileLauncher {
|
|
||||||
public:
|
|
||||||
FileLauncher();
|
|
||||||
virtual ~FileLauncher();
|
|
||||||
|
|
||||||
bool launchFiles(QWidget* parent, FmFileInfoList* file_infos) {
|
|
||||||
GList* fileList = fm_file_info_list_peek_head_link(file_infos);
|
|
||||||
return launchFiles(parent, fileList);
|
|
||||||
}
|
|
||||||
bool launchPaths(QWidget* parent, FmPathList* paths) {
|
|
||||||
GList* pathList = fm_path_list_peek_head_link(paths);
|
|
||||||
return launchPaths(parent, pathList);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool launchFiles(QWidget* parent, GList* file_infos);
|
|
||||||
bool launchPaths(QWidget* parent, GList* paths);
|
|
||||||
|
|
||||||
bool quickExec() const {
|
|
||||||
return quickExec_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setQuickExec(bool value) {
|
|
||||||
quickExec_ = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
virtual GAppInfo* getApp(GList* file_infos, FmMimeType* mime_type, GError** err);
|
|
||||||
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:
|
|
||||||
static GAppInfo* _getApp(GList* file_infos, FmMimeType* mime_type, gpointer user_data, GError** err) {
|
|
||||||
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:
|
|
||||||
static FmFileLauncher funcs;
|
|
||||||
bool quickExec_; // Don't ask options on launch executable file
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_FILELAUNCHER_H
|
|
||||||
@ -1,381 +0,0 @@
|
|||||||
/*
|
|
||||||
<one line to give the library's name and an idea of what it does.>
|
|
||||||
Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "filemenu.h"
|
|
||||||
#include "createnewmenu.h"
|
|
||||||
#include "icontheme.h"
|
|
||||||
#include "filepropsdialog.h"
|
|
||||||
#include "utilities.h"
|
|
||||||
#include "fileoperation.h"
|
|
||||||
#include "filelauncher.h"
|
|
||||||
#include "appchooserdialog.h"
|
|
||||||
#ifdef CUSTOM_ACTIONS
|
|
||||||
#include <libfm/fm-actions.h>
|
|
||||||
#endif
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QDebug>
|
|
||||||
#include "filemenu_p.h"
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
FileMenu::FileMenu(FmFileInfoList* files, FmFileInfo* info, FmPath* cwd, QWidget* parent):
|
|
||||||
QMenu(parent),
|
|
||||||
fileLauncher_(NULL) {
|
|
||||||
createMenu(files, info, cwd);
|
|
||||||
}
|
|
||||||
|
|
||||||
FileMenu::FileMenu(FmFileInfoList* files, FmFileInfo* info, FmPath* cwd, const QString& title, QWidget* parent):
|
|
||||||
QMenu(title, parent),
|
|
||||||
fileLauncher_(NULL),
|
|
||||||
unTrashAction_(NULL) {
|
|
||||||
createMenu(files, info, cwd);
|
|
||||||
}
|
|
||||||
|
|
||||||
FileMenu::~FileMenu() {
|
|
||||||
if(files_)
|
|
||||||
fm_file_info_list_unref(files_);
|
|
||||||
if(info_)
|
|
||||||
fm_file_info_unref(info_);
|
|
||||||
if(cwd_)
|
|
||||||
fm_path_unref(cwd_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileMenu::createMenu(FmFileInfoList* files, FmFileInfo* info, FmPath* cwd) {
|
|
||||||
useTrash_ = true;
|
|
||||||
confirmDelete_ = true;
|
|
||||||
confirmTrash_ = false; // Confirm before moving files into "trash can"
|
|
||||||
|
|
||||||
files_ = fm_file_info_list_ref(files);
|
|
||||||
info_ = info ? fm_file_info_ref(info) : NULL;
|
|
||||||
cwd_ = cwd ? fm_path_ref(cwd) : NULL;
|
|
||||||
|
|
||||||
FmFileInfo* first = fm_file_info_list_peek_head(files);
|
|
||||||
FmMimeType* mime_type = fm_file_info_get_mime_type(first);
|
|
||||||
FmPath* path = fm_file_info_get_path(first);
|
|
||||||
// check if the files are of the same type
|
|
||||||
sameType_ = fm_file_info_list_is_same_type(files);
|
|
||||||
// check if the files are on the same filesystem
|
|
||||||
sameFilesystem_ = fm_file_info_list_is_same_fs(files);
|
|
||||||
// check if the files are all virtual
|
|
||||||
allVirtual_ = sameFilesystem_ && fm_path_is_virtual(path);
|
|
||||||
// check if the files are all in the trash can
|
|
||||||
allTrash_ = sameFilesystem_ && fm_path_is_trash(path);
|
|
||||||
|
|
||||||
openAction_ = new QAction(QIcon::fromTheme("document-open"), tr("Open"), this);
|
|
||||||
connect(openAction_ , &QAction::triggered, this, &FileMenu::onOpenTriggered);
|
|
||||||
addAction(openAction_);
|
|
||||||
|
|
||||||
openWithMenuAction_ = new QAction(tr("Open With..."), this);
|
|
||||||
addAction(openWithMenuAction_);
|
|
||||||
// create the "Open with..." sub menu
|
|
||||||
QMenu* menu = new QMenu();
|
|
||||||
openWithMenuAction_->setMenu(menu);
|
|
||||||
|
|
||||||
if(sameType_) { /* add specific menu items for this mime type */
|
|
||||||
if(mime_type && !allVirtual_) { /* the file has a valid mime-type and its not virtual */
|
|
||||||
GList* apps = g_app_info_get_all_for_type(fm_mime_type_get_type(mime_type));
|
|
||||||
GList* l;
|
|
||||||
for(l=apps;l;l=l->next) {
|
|
||||||
GAppInfo* app = G_APP_INFO(l->data);
|
|
||||||
|
|
||||||
// check if the command really exists
|
|
||||||
gchar * program_path = g_find_program_in_path(g_app_info_get_executable(app));
|
|
||||||
if (!program_path)
|
|
||||||
continue;
|
|
||||||
g_free(program_path);
|
|
||||||
|
|
||||||
// create a QAction for the application.
|
|
||||||
AppInfoAction* action = new AppInfoAction(app);
|
|
||||||
connect(action, &QAction::triggered, this, &FileMenu::onApplicationTriggered);
|
|
||||||
menu->addAction(action);
|
|
||||||
}
|
|
||||||
g_list_free(apps); /* don't unref GAppInfos now */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
menu->addSeparator();
|
|
||||||
openWithAction_ = new QAction(tr("Other Applications"), this);
|
|
||||||
connect(openWithAction_ , &QAction::triggered, this, &FileMenu::onOpenWithTriggered);
|
|
||||||
menu->addAction(openWithAction_);
|
|
||||||
|
|
||||||
separator1_ = addSeparator();
|
|
||||||
|
|
||||||
QAction* createAction = new QAction(tr("Create &New"), this);
|
|
||||||
FmPath* dirPath = fm_file_info_list_get_length(files) == 1 && fm_file_info_is_dir(first)
|
|
||||||
? path : cwd_;
|
|
||||||
createAction->setMenu(new CreateNewMenu(NULL, dirPath, this));
|
|
||||||
addAction(createAction);
|
|
||||||
addSeparator();
|
|
||||||
|
|
||||||
if(allTrash_) { // all selected files are in trash:///
|
|
||||||
bool can_restore = true;
|
|
||||||
/* only immediate children of trash:/// can be restored. */
|
|
||||||
for(GList* l = fm_file_info_list_peek_head_link(files_); l; l=l->next) {
|
|
||||||
FmPath *trash_path = fm_file_info_get_path(FM_FILE_INFO(l->data));
|
|
||||||
if(!fm_path_get_parent(trash_path) ||
|
|
||||||
!fm_path_is_trash_root(fm_path_get_parent(trash_path))) {
|
|
||||||
can_restore = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(can_restore) {
|
|
||||||
unTrashAction_ = new QAction(tr("&Restore"), this);
|
|
||||||
connect(unTrashAction_, &QAction::triggered, this, &FileMenu::onUnTrashTriggered);
|
|
||||||
addAction(unTrashAction_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { // ordinary files
|
|
||||||
cutAction_ = new QAction(QIcon::fromTheme("edit-cut"), tr("Cut"), this);
|
|
||||||
connect(cutAction_, &QAction::triggered, this, &FileMenu::onCutTriggered);
|
|
||||||
addAction(cutAction_);
|
|
||||||
|
|
||||||
copyAction_ = new QAction(QIcon::fromTheme("edit-copy"), tr("Copy"), this);
|
|
||||||
connect(copyAction_, &QAction::triggered, this, &FileMenu::onCopyTriggered);
|
|
||||||
addAction(copyAction_);
|
|
||||||
|
|
||||||
pasteAction_ = new QAction(QIcon::fromTheme("edit-paste"), tr("Paste"), this);
|
|
||||||
connect(pasteAction_, &QAction::triggered, this, &FileMenu::onPasteTriggered);
|
|
||||||
addAction(pasteAction_);
|
|
||||||
|
|
||||||
deleteAction_ = new QAction(QIcon::fromTheme("user-trash"), tr("&Move to Trash"), this);
|
|
||||||
connect(deleteAction_, &QAction::triggered, this, &FileMenu::onDeleteTriggered);
|
|
||||||
addAction(deleteAction_);
|
|
||||||
|
|
||||||
renameAction_ = new QAction(tr("Rename"), this);
|
|
||||||
connect(renameAction_, &QAction::triggered, this, &FileMenu::onRenameTriggered);
|
|
||||||
addAction(renameAction_);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CUSTOM_ACTIONS
|
|
||||||
// DES-EMA custom actions integration
|
|
||||||
GList* files_list = fm_file_info_list_peek_head_link(files);
|
|
||||||
GList* items = fm_get_actions_for_files(files_list);
|
|
||||||
if(items) {
|
|
||||||
GList* l;
|
|
||||||
for(l=items; l; l=l->next) {
|
|
||||||
FmFileActionItem* item = FM_FILE_ACTION_ITEM(l->data);
|
|
||||||
addCustomActionItem(this, item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_list_foreach(items, (GFunc)fm_file_action_item_unref, NULL);
|
|
||||||
g_list_free(items);
|
|
||||||
#endif
|
|
||||||
// archiver integration
|
|
||||||
// FIXME: we need to modify upstream libfm to include some Qt-based archiver programs.
|
|
||||||
if(!allVirtual_) {
|
|
||||||
if(sameType_) {
|
|
||||||
FmArchiver* archiver = fm_archiver_get_default();
|
|
||||||
if(archiver) {
|
|
||||||
if(fm_archiver_is_mime_type_supported(archiver, fm_mime_type_get_type(mime_type))) {
|
|
||||||
if(cwd_ && archiver->extract_to_cmd) {
|
|
||||||
QAction* action = new QAction(tr("Extract to..."), this);
|
|
||||||
connect(action, &QAction::triggered, this, &FileMenu::onExtract);
|
|
||||||
addAction(action);
|
|
||||||
}
|
|
||||||
if(archiver->extract_cmd) {
|
|
||||||
QAction* action = new QAction(tr("Extract Here"), this);
|
|
||||||
connect(action, &QAction::triggered, this, &FileMenu::onExtractHere);
|
|
||||||
addAction(action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
QAction* action = new QAction(tr("Compress"), this);
|
|
||||||
connect(action, &QAction::triggered, this, &FileMenu::onCompress);
|
|
||||||
addAction(action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
separator2_ = addSeparator();
|
|
||||||
|
|
||||||
propertiesAction_ = new QAction(QIcon::fromTheme("document-properties"), tr("Properties"), this);
|
|
||||||
connect(propertiesAction_, &QAction::triggered, this, &FileMenu::onFilePropertiesTriggered);
|
|
||||||
addAction(propertiesAction_);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CUSTOM_ACTIONS
|
|
||||||
void FileMenu::addCustomActionItem(QMenu* menu, FmFileActionItem* item) {
|
|
||||||
if(!item) { // separator
|
|
||||||
addSeparator();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// this action is not for context menu
|
|
||||||
if(fm_file_action_item_is_action(item) && !(fm_file_action_item_get_target(item) & FM_FILE_ACTION_TARGET_CONTEXT))
|
|
||||||
return;
|
|
||||||
|
|
||||||
CustomAction* action = new CustomAction(item, menu);
|
|
||||||
menu->addAction(action);
|
|
||||||
if(fm_file_action_item_is_menu(item)) {
|
|
||||||
GList* subitems = fm_file_action_item_get_sub_items(item);
|
|
||||||
for(GList* l = subitems; l; l = l->next) {
|
|
||||||
FmFileActionItem* subitem = FM_FILE_ACTION_ITEM(l->data);
|
|
||||||
QMenu* submenu = new QMenu(menu);
|
|
||||||
addCustomActionItem(submenu, subitem);
|
|
||||||
action->setMenu(submenu);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(fm_file_action_item_is_action(item)) {
|
|
||||||
connect(action, &QAction::triggered, this, &FileMenu::onCustomActionTrigerred);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void FileMenu::onOpenTriggered() {
|
|
||||||
if(fileLauncher_) {
|
|
||||||
fileLauncher_->launchFiles(NULL, files_);
|
|
||||||
}
|
|
||||||
else { // use the default launcher
|
|
||||||
Fm::FileLauncher launcher;
|
|
||||||
launcher.launchFiles(NULL, files_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileMenu::onOpenWithTriggered() {
|
|
||||||
AppChooserDialog dlg(NULL);
|
|
||||||
if(sameType_) {
|
|
||||||
dlg.setMimeType(fm_file_info_get_mime_type(info_));
|
|
||||||
}
|
|
||||||
else { // we can only set the selected app as default if all files are of the same type
|
|
||||||
dlg.setCanSetDefault(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(execModelessDialog(&dlg) == QDialog::Accepted) {
|
|
||||||
GAppInfo* app = dlg.selectedApp();
|
|
||||||
if(app) {
|
|
||||||
openFilesWithApp(app);
|
|
||||||
g_object_unref(app);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileMenu::openFilesWithApp(GAppInfo* app) {
|
|
||||||
FmPathList* paths = fm_path_list_new_from_file_info_list(files_);
|
|
||||||
GList* uris = NULL;
|
|
||||||
for(GList* l = fm_path_list_peek_head_link(paths); l; l = l->next) {
|
|
||||||
FmPath* path = FM_PATH(l->data);
|
|
||||||
char* uri = fm_path_to_uri(path);
|
|
||||||
uris = g_list_prepend(uris, uri);
|
|
||||||
}
|
|
||||||
fm_path_list_unref(paths);
|
|
||||||
fm_app_info_launch_uris(app, uris, NULL, NULL);
|
|
||||||
g_list_foreach(uris, (GFunc)g_free, NULL);
|
|
||||||
g_list_free(uris);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileMenu::onApplicationTriggered() {
|
|
||||||
AppInfoAction* action = static_cast<AppInfoAction*>(sender());
|
|
||||||
openFilesWithApp(action->appInfo());
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CUSTOM_ACTIONS
|
|
||||||
void FileMenu::onCustomActionTrigerred() {
|
|
||||||
CustomAction* action = static_cast<CustomAction*>(sender());
|
|
||||||
FmFileActionItem* item = action->item();
|
|
||||||
|
|
||||||
GList* files = fm_file_info_list_peek_head_link(files_);
|
|
||||||
char* output = NULL;
|
|
||||||
/* g_debug("item: %s is activated, id:%s", fm_file_action_item_get_name(item),
|
|
||||||
fm_file_action_item_get_id(item)); */
|
|
||||||
fm_file_action_item_launch(item, NULL, files, &output);
|
|
||||||
if(output) {
|
|
||||||
QMessageBox::information(this, tr("Output"), QString::fromUtf8(output));
|
|
||||||
g_free(output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void FileMenu::onFilePropertiesTriggered() {
|
|
||||||
FilePropsDialog::showForFiles(files_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileMenu::onCopyTriggered() {
|
|
||||||
FmPathList* paths = fm_path_list_new_from_file_info_list(files_);
|
|
||||||
Fm::copyFilesToClipboard(paths);
|
|
||||||
fm_path_list_unref(paths);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileMenu::onCutTriggered() {
|
|
||||||
FmPathList* paths = fm_path_list_new_from_file_info_list(files_);
|
|
||||||
Fm::cutFilesToClipboard(paths);
|
|
||||||
fm_path_list_unref(paths);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileMenu::onDeleteTriggered() {
|
|
||||||
FmPathList* paths = fm_path_list_new_from_file_info_list(files_);
|
|
||||||
if(useTrash_)
|
|
||||||
FileOperation::trashFiles(paths, confirmTrash_);
|
|
||||||
else
|
|
||||||
FileOperation::deleteFiles(paths, confirmDelete_);
|
|
||||||
fm_path_list_unref(paths);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileMenu::onUnTrashTriggered() {
|
|
||||||
FmPathList* paths = fm_path_list_new_from_file_info_list(files_);
|
|
||||||
FileOperation::unTrashFiles(paths);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileMenu::onPasteTriggered() {
|
|
||||||
Fm::pasteFilesFromClipboard(cwd_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileMenu::onRenameTriggered() {
|
|
||||||
for(GList* l = fm_file_info_list_peek_head_link(files_); l; l = l->next) {
|
|
||||||
FmFileInfo* info = FM_FILE_INFO(l->data);
|
|
||||||
Fm::renameFile(info, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileMenu::setUseTrash(bool trash) {
|
|
||||||
if(useTrash_ != trash) {
|
|
||||||
useTrash_ = trash;
|
|
||||||
deleteAction_->setText(useTrash_ ? tr("&Move to Trash") : tr("&Delete"));
|
|
||||||
deleteAction_->setIcon(useTrash_ ? QIcon::fromTheme("user-trash") : QIcon::fromTheme("edit-delete"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileMenu::onCompress() {
|
|
||||||
FmArchiver* archiver = fm_archiver_get_default();
|
|
||||||
if(archiver) {
|
|
||||||
FmPathList* paths = fm_path_list_new_from_file_info_list(files_);
|
|
||||||
fm_archiver_create_archive(archiver, NULL, paths);
|
|
||||||
fm_path_list_unref(paths);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileMenu::onExtract() {
|
|
||||||
FmArchiver* archiver = fm_archiver_get_default();
|
|
||||||
if(archiver) {
|
|
||||||
FmPathList* paths = fm_path_list_new_from_file_info_list(files_);
|
|
||||||
fm_archiver_extract_archives(archiver, NULL, paths);
|
|
||||||
fm_path_list_unref(paths);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileMenu::onExtractHere() {
|
|
||||||
FmArchiver* archiver = fm_archiver_get_default();
|
|
||||||
if(archiver) {
|
|
||||||
FmPathList* paths = fm_path_list_new_from_file_info_list(files_);
|
|
||||||
fm_archiver_extract_archives_to(archiver, NULL, paths, cwd_);
|
|
||||||
fm_path_list_unref(paths);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Fm
|
|
||||||
@ -1,208 +0,0 @@
|
|||||||
/*
|
|
||||||
<one line to give the library's name and an idea of what it does.>
|
|
||||||
Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FM_FILEMENU_H
|
|
||||||
#define FM_FILEMENU_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QMenu>
|
|
||||||
#include <qabstractitemmodel.h>
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
|
|
||||||
class QAction;
|
|
||||||
|
|
||||||
struct _FmFileActionItem;
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class FileLauncher;
|
|
||||||
|
|
||||||
class LIBFM_QT_API FileMenu : public QMenu {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit FileMenu(FmFileInfoList* files, FmFileInfo* info, FmPath* cwd, QWidget* parent = 0);
|
|
||||||
explicit FileMenu(FmFileInfoList* files, FmFileInfo* info, FmPath* cwd, const QString& title, QWidget* parent = 0);
|
|
||||||
~FileMenu();
|
|
||||||
|
|
||||||
bool useTrash() {
|
|
||||||
return useTrash_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setUseTrash(bool trash);
|
|
||||||
|
|
||||||
bool confirmDelete() {
|
|
||||||
return confirmDelete_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setConfirmDelete(bool confirm) {
|
|
||||||
confirmDelete_ = confirm;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* openAction() {
|
|
||||||
return openAction_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* openWithMenuAction() {
|
|
||||||
return openWithMenuAction_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* openWithAction() {
|
|
||||||
return openWithAction_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* separator1() {
|
|
||||||
return separator1_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* cutAction() {
|
|
||||||
return cutAction_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* copyAction() {
|
|
||||||
return copyAction_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* pasteAction() {
|
|
||||||
return pasteAction_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* deleteAction() {
|
|
||||||
return deleteAction_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* unTrashAction() {
|
|
||||||
return unTrashAction_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* renameAction() {
|
|
||||||
return renameAction_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* separator2() {
|
|
||||||
return separator2_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* propertiesAction() {
|
|
||||||
return propertiesAction_;
|
|
||||||
}
|
|
||||||
|
|
||||||
FmFileInfoList* files() {
|
|
||||||
return files_;
|
|
||||||
}
|
|
||||||
|
|
||||||
FmFileInfo* firstFile() {
|
|
||||||
return info_;
|
|
||||||
}
|
|
||||||
|
|
||||||
FmPath* cwd() {
|
|
||||||
return cwd_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setFileLauncher(FileLauncher* launcher) {
|
|
||||||
fileLauncher_ = launcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileLauncher* fileLauncher() {
|
|
||||||
return fileLauncher_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sameType() const {
|
|
||||||
return sameType_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sameFilesystem() const {
|
|
||||||
return sameFilesystem_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool allVirtual() const {
|
|
||||||
return allVirtual_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool allTrash() const {
|
|
||||||
return allTrash_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool confirmTrash() const {
|
|
||||||
return confirmTrash_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setConfirmTrash(bool value) {
|
|
||||||
confirmTrash_ = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void createMenu(FmFileInfoList* files, FmFileInfo* info, FmPath* cwd);
|
|
||||||
#ifdef CUSTOM_ACTIONS
|
|
||||||
void addCustomActionItem(QMenu* menu, struct _FmFileActionItem* item);
|
|
||||||
#endif
|
|
||||||
void openFilesWithApp(GAppInfo* app);
|
|
||||||
|
|
||||||
protected Q_SLOTS:
|
|
||||||
void onOpenTriggered();
|
|
||||||
void onOpenWithTriggered();
|
|
||||||
void onFilePropertiesTriggered();
|
|
||||||
void onApplicationTriggered();
|
|
||||||
#ifdef CUSTOM_ACTIONS
|
|
||||||
void onCustomActionTrigerred();
|
|
||||||
#endif
|
|
||||||
void onCompress();
|
|
||||||
void onExtract();
|
|
||||||
void onExtractHere();
|
|
||||||
|
|
||||||
void onCutTriggered();
|
|
||||||
void onCopyTriggered();
|
|
||||||
void onPasteTriggered();
|
|
||||||
void onRenameTriggered();
|
|
||||||
void onDeleteTriggered();
|
|
||||||
void onUnTrashTriggered();
|
|
||||||
|
|
||||||
private:
|
|
||||||
FmFileInfoList* files_;
|
|
||||||
FmFileInfo* info_;
|
|
||||||
FmPath* cwd_;
|
|
||||||
bool useTrash_;
|
|
||||||
bool confirmDelete_;
|
|
||||||
bool confirmTrash_; // Confirm before moving files into "trash can"
|
|
||||||
|
|
||||||
bool sameType_;
|
|
||||||
bool sameFilesystem_;
|
|
||||||
bool allVirtual_;
|
|
||||||
bool allTrash_;
|
|
||||||
|
|
||||||
QAction* openAction_;
|
|
||||||
QAction* openWithMenuAction_;
|
|
||||||
QAction* openWithAction_;
|
|
||||||
QAction* separator1_;
|
|
||||||
QAction* cutAction_;
|
|
||||||
QAction* copyAction_;
|
|
||||||
QAction* pasteAction_;
|
|
||||||
QAction* deleteAction_;
|
|
||||||
QAction* unTrashAction_;
|
|
||||||
QAction* renameAction_;
|
|
||||||
QAction* separator2_;
|
|
||||||
QAction* propertiesAction_;
|
|
||||||
|
|
||||||
FileLauncher* fileLauncher_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_FILEMENU_H
|
|
||||||
@ -1,84 +0,0 @@
|
|||||||
/*
|
|
||||||
<one line to give the library's name and an idea of what it does.>
|
|
||||||
Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FM_FILEMENU_P_H
|
|
||||||
#define FM_FILEMENU_P_H
|
|
||||||
|
|
||||||
#include "icontheme.h"
|
|
||||||
#ifdef CUSTOM_ACTIONS
|
|
||||||
#include <libfm/fm-actions.h>
|
|
||||||
#endif
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class AppInfoAction : public QAction {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit AppInfoAction(GAppInfo* app, QObject* parent = 0):
|
|
||||||
QAction(QString::fromUtf8(g_app_info_get_name(app)), parent),
|
|
||||||
appInfo_(G_APP_INFO(g_object_ref(app))) {
|
|
||||||
setToolTip(QString::fromUtf8(g_app_info_get_description(app)));
|
|
||||||
GIcon* gicon = g_app_info_get_icon(app);
|
|
||||||
QIcon icon = IconTheme::icon(gicon);
|
|
||||||
setIcon(icon);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~AppInfoAction() {
|
|
||||||
if(appInfo_)
|
|
||||||
g_object_unref(appInfo_);
|
|
||||||
}
|
|
||||||
|
|
||||||
GAppInfo* appInfo() const {
|
|
||||||
return appInfo_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
GAppInfo* appInfo_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef CUSTOM_ACTIONS
|
|
||||||
class CustomAction : public QAction {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit CustomAction(FmFileActionItem* item, QObject* parent = NULL):
|
|
||||||
QAction(QString::fromUtf8(fm_file_action_item_get_name(item)), parent),
|
|
||||||
item_(reinterpret_cast<FmFileActionItem*>(fm_file_action_item_ref(item))) {
|
|
||||||
const char* icon_name = fm_file_action_item_get_icon(item);
|
|
||||||
if(icon_name)
|
|
||||||
setIcon(QIcon::fromTheme(icon_name));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~CustomAction() {
|
|
||||||
fm_file_action_item_unref(item_);
|
|
||||||
}
|
|
||||||
|
|
||||||
FmFileActionItem* item() {
|
|
||||||
return item_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
FmFileActionItem* item_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace Fm
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,304 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "fileoperation.h"
|
|
||||||
#include "fileoperationdialog.h"
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QElapsedTimer>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
using namespace Fm;
|
|
||||||
|
|
||||||
#define SHOW_DLG_DELAY 1000
|
|
||||||
|
|
||||||
FileOperation::FileOperation(Type type, FmPathList* srcFiles, QObject* parent):
|
|
||||||
QObject(parent),
|
|
||||||
dlg(NULL),
|
|
||||||
destPath(NULL),
|
|
||||||
srcPaths(fm_path_list_ref(srcFiles)),
|
|
||||||
uiTimer(NULL),
|
|
||||||
elapsedTimer_(NULL),
|
|
||||||
lastElapsed_(0),
|
|
||||||
updateRemainingTime_(true),
|
|
||||||
autoDestroy_(true),
|
|
||||||
job_(fm_file_ops_job_new((FmFileOpType)type, srcFiles)) {
|
|
||||||
|
|
||||||
g_signal_connect(job_, "ask", G_CALLBACK(onFileOpsJobAsk), this);
|
|
||||||
g_signal_connect(job_, "ask-rename", G_CALLBACK(onFileOpsJobAskRename), this);
|
|
||||||
g_signal_connect(job_, "error", G_CALLBACK(onFileOpsJobError), this);
|
|
||||||
g_signal_connect(job_, "prepared", G_CALLBACK(onFileOpsJobPrepared), this);
|
|
||||||
g_signal_connect(job_, "cur-file", G_CALLBACK(onFileOpsJobCurFile), this);
|
|
||||||
g_signal_connect(job_, "percent", G_CALLBACK(onFileOpsJobPercent), this);
|
|
||||||
g_signal_connect(job_, "finished", G_CALLBACK(onFileOpsJobFinished), this);
|
|
||||||
g_signal_connect(job_, "cancelled", G_CALLBACK(onFileOpsJobCancelled), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileOperation::disconnectJob() {
|
|
||||||
g_signal_handlers_disconnect_by_func(job_, (gpointer)G_CALLBACK(onFileOpsJobAsk), this);
|
|
||||||
g_signal_handlers_disconnect_by_func(job_, (gpointer)G_CALLBACK(onFileOpsJobAskRename), this);
|
|
||||||
g_signal_handlers_disconnect_by_func(job_, (gpointer)G_CALLBACK(onFileOpsJobError), this);
|
|
||||||
g_signal_handlers_disconnect_by_func(job_, (gpointer)G_CALLBACK(onFileOpsJobPrepared), this);
|
|
||||||
g_signal_handlers_disconnect_by_func(job_, (gpointer)G_CALLBACK(onFileOpsJobCurFile), this);
|
|
||||||
g_signal_handlers_disconnect_by_func(job_, (gpointer)G_CALLBACK(onFileOpsJobPercent), this);
|
|
||||||
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() {
|
|
||||||
if(uiTimer) {
|
|
||||||
uiTimer->stop();
|
|
||||||
delete uiTimer;
|
|
||||||
uiTimer = NULL;
|
|
||||||
}
|
|
||||||
if(elapsedTimer_) {
|
|
||||||
delete elapsedTimer_;
|
|
||||||
elapsedTimer_ = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(job_) {
|
|
||||||
disconnectJob();
|
|
||||||
g_object_unref(job_);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(srcPaths)
|
|
||||||
fm_path_list_unref(srcPaths);
|
|
||||||
|
|
||||||
if(destPath)
|
|
||||||
fm_path_unref(destPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileOperation::run() {
|
|
||||||
delete uiTimer;
|
|
||||||
// run the job
|
|
||||||
uiTimer = new QTimer();
|
|
||||||
uiTimer->start(SHOW_DLG_DELAY);
|
|
||||||
connect(uiTimer, &QTimer::timeout, this, &FileOperation::onUiTimeout);
|
|
||||||
|
|
||||||
return fm_job_run_async(FM_JOB(job_));
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileOperation::onUiTimeout() {
|
|
||||||
if(dlg) {
|
|
||||||
dlg->setCurFile(curFile);
|
|
||||||
// estimate remaining time based on past history
|
|
||||||
// FIXME: avoid directly access data member of FmFileOpsJob
|
|
||||||
if(Q_LIKELY(job_->percent > 0 && updateRemainingTime_)) {
|
|
||||||
gint64 remaining = elapsedTime() * ((double(100 - job_->percent) / job_->percent) / 1000);
|
|
||||||
dlg->setRemainingTime(remaining);
|
|
||||||
}
|
|
||||||
// this timeout slot is called every 0.5 second.
|
|
||||||
// by adding this flag, we can update remaining time every 1 second.
|
|
||||||
updateRemainingTime_ = !updateRemainingTime_;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
showDialog();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileOperation::showDialog() {
|
|
||||||
if(!dlg) {
|
|
||||||
dlg = new FileOperationDialog(this);
|
|
||||||
dlg->setSourceFiles(srcPaths);
|
|
||||||
|
|
||||||
if(destPath)
|
|
||||||
dlg->setDestPath(destPath);
|
|
||||||
|
|
||||||
if(curFile.isEmpty()) {
|
|
||||||
dlg->setPrepared();
|
|
||||||
dlg->setCurFile(curFile);
|
|
||||||
}
|
|
||||||
uiTimer->setInterval(500); // change the interval of the timer
|
|
||||||
// now the timer is used to update current file display
|
|
||||||
dlg->show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gint FileOperation::onFileOpsJobAsk(FmFileOpsJob* job, const char* question, char*const* options, FileOperation* pThis) {
|
|
||||||
pThis->pauseElapsedTimer();
|
|
||||||
pThis->showDialog();
|
|
||||||
int ret = pThis->dlg->ask(QString::fromUtf8(question), options);
|
|
||||||
pThis->resumeElapsedTimer();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
gint FileOperation::onFileOpsJobAskRename(FmFileOpsJob* job, FmFileInfo* src, FmFileInfo* dest, char** new_name, FileOperation* pThis) {
|
|
||||||
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!");
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileOperation::onFileOpsJobCurFile(FmFileOpsJob* job, const char* cur_file, FileOperation* pThis) {
|
|
||||||
pThis->curFile = QString::fromUtf8(cur_file);
|
|
||||||
|
|
||||||
// We update the current file name in a timeout slot because drawing a string
|
|
||||||
// in the UI is expansive. Updating the label text too often cause
|
|
||||||
// significant impact on performance.
|
|
||||||
// if(pThis->dlg)
|
|
||||||
// pThis->dlg->setCurFile(pThis->curFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
FmJobErrorAction FileOperation::onFileOpsJobError(FmFileOpsJob* job, GError* err, FmJobErrorSeverity severity, FileOperation* pThis) {
|
|
||||||
pThis->pauseElapsedTimer();
|
|
||||||
pThis->showDialog();
|
|
||||||
FmJobErrorAction act = pThis->dlg->error(err, severity);
|
|
||||||
pThis->resumeElapsedTimer();
|
|
||||||
return act;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileOperation::onFileOpsJobPrepared(FmFileOpsJob* job, FileOperation* pThis) {
|
|
||||||
if(!pThis->elapsedTimer_) {
|
|
||||||
pThis->elapsedTimer_ = new QElapsedTimer();
|
|
||||||
pThis->elapsedTimer_->start();
|
|
||||||
}
|
|
||||||
if(pThis->dlg) {
|
|
||||||
pThis->dlg->setPrepared();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileOperation::handleFinish() {
|
|
||||||
disconnectJob();
|
|
||||||
|
|
||||||
if(uiTimer) {
|
|
||||||
uiTimer->stop();
|
|
||||||
delete uiTimer;
|
|
||||||
uiTimer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(dlg) {
|
|
||||||
dlg->done(QDialog::Accepted);
|
|
||||||
delete dlg;
|
|
||||||
dlg = NULL;
|
|
||||||
}
|
|
||||||
Q_EMIT finished();
|
|
||||||
|
|
||||||
/* sepcial handling for trash
|
|
||||||
* FIXME: need to refactor this to use a more elegant way later. */
|
|
||||||
if(job_->type == FM_FILE_OP_TRASH) { /* FIXME: direct access to job struct! */
|
|
||||||
FmPathList* 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. */
|
|
||||||
if(unable_to_trash) { /* delete them instead */
|
|
||||||
/* FIXME: parent window might be already destroyed! */
|
|
||||||
QWidget* parent = NULL; // FIXME: currently, parent window is not set
|
|
||||||
if(QMessageBox::question(parent, tr("Error"),
|
|
||||||
tr("Some files cannot be moved to trash can because "
|
|
||||||
"the underlying file systems don't support this operation.\n"
|
|
||||||
"Do you want to delete them instead?")) == QMessageBox::Yes) {
|
|
||||||
deleteFiles(unable_to_trash, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_object_unref(job_);
|
|
||||||
job_ = NULL;
|
|
||||||
|
|
||||||
if(autoDestroy_)
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
FileOperation* FileOperation::copyFiles(FmPathList* srcFiles, FmPath* dest, QWidget* parent) {
|
|
||||||
FileOperation* op = new FileOperation(FileOperation::Copy, srcFiles);
|
|
||||||
op->setDestination(dest);
|
|
||||||
op->run();
|
|
||||||
return op;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
FileOperation* FileOperation::moveFiles(FmPathList* srcFiles, FmPath* dest, QWidget* parent) {
|
|
||||||
FileOperation* op = new FileOperation(FileOperation::Move, srcFiles);
|
|
||||||
op->setDestination(dest);
|
|
||||||
op->run();
|
|
||||||
return op;
|
|
||||||
}
|
|
||||||
|
|
||||||
//static
|
|
||||||
FileOperation* FileOperation::symlinkFiles(FmPathList* srcFiles, FmPath* dest, QWidget* parent) {
|
|
||||||
FileOperation* op = new FileOperation(FileOperation::Link, srcFiles);
|
|
||||||
op->setDestination(dest);
|
|
||||||
op->run();
|
|
||||||
return op;
|
|
||||||
}
|
|
||||||
|
|
||||||
//static
|
|
||||||
FileOperation* FileOperation::deleteFiles(FmPathList* srcFiles, bool prompt, QWidget* parent) {
|
|
||||||
if(prompt) {
|
|
||||||
int result = QMessageBox::warning(parent, tr("Confirm"),
|
|
||||||
tr("Do you want to delete the selected files?"),
|
|
||||||
QMessageBox::Yes|QMessageBox::No,
|
|
||||||
QMessageBox::No);
|
|
||||||
if(result != QMessageBox::Yes)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileOperation* op = new FileOperation(FileOperation::Delete, srcFiles);
|
|
||||||
op->run();
|
|
||||||
return op;
|
|
||||||
}
|
|
||||||
|
|
||||||
//static
|
|
||||||
FileOperation* FileOperation::trashFiles(FmPathList* srcFiles, bool prompt, QWidget* parent) {
|
|
||||||
if(prompt) {
|
|
||||||
int result = QMessageBox::warning(parent, tr("Confirm"),
|
|
||||||
tr("Do you want to move the selected files to trash can?"),
|
|
||||||
QMessageBox::Yes|QMessageBox::No,
|
|
||||||
QMessageBox::No);
|
|
||||||
if(result != QMessageBox::Yes)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileOperation* op = new FileOperation(FileOperation::Trash, srcFiles);
|
|
||||||
op->run();
|
|
||||||
return op;
|
|
||||||
}
|
|
||||||
|
|
||||||
//static
|
|
||||||
FileOperation* FileOperation::unTrashFiles(FmPathList* srcFiles, QWidget* parent) {
|
|
||||||
FileOperation* op = new FileOperation(FileOperation::UnTrash, srcFiles);
|
|
||||||
op->run();
|
|
||||||
return op;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
FileOperation* FileOperation::changeAttrFiles(FmPathList* srcFiles, QWidget* parent) {
|
|
||||||
//TODO
|
|
||||||
FileOperation* op = new FileOperation(FileOperation::ChangeAttr, srcFiles);
|
|
||||||
op->run();
|
|
||||||
return op;
|
|
||||||
}
|
|
||||||
@ -1,164 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FM_FILEOPERATION_H
|
|
||||||
#define FM_FILEOPERATION_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QObject>
|
|
||||||
#include <QElapsedTimer>
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
|
|
||||||
class QTimer;
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class FileOperationDialog;
|
|
||||||
|
|
||||||
class LIBFM_QT_API FileOperation : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
enum Type {
|
|
||||||
Copy = FM_FILE_OP_COPY,
|
|
||||||
Move = FM_FILE_OP_MOVE,
|
|
||||||
Link = FM_FILE_OP_LINK,
|
|
||||||
Delete = FM_FILE_OP_DELETE,
|
|
||||||
Trash = FM_FILE_OP_TRASH,
|
|
||||||
UnTrash = FM_FILE_OP_UNTRASH,
|
|
||||||
ChangeAttr = FM_FILE_OP_CHANGE_ATTR
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit FileOperation(Type type, FmPathList* srcFiles, QObject* parent = 0);
|
|
||||||
virtual ~FileOperation();
|
|
||||||
|
|
||||||
void setDestination(FmPath* dest) {
|
|
||||||
destPath = fm_path_ref(dest);
|
|
||||||
fm_file_ops_job_set_dest(job_, dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setChmod(mode_t newMode, mode_t newModeMask) {
|
|
||||||
fm_file_ops_job_set_chmod(job_, newMode, newModeMask);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setChown(gint uid, gint gid) {
|
|
||||||
fm_file_ops_job_set_chown(job_, uid, gid);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This only work for change attr jobs.
|
|
||||||
void setRecursiveChattr(bool recursive) {
|
|
||||||
fm_file_ops_job_set_recursive(job_, (gboolean)recursive);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool run();
|
|
||||||
|
|
||||||
void cancel() {
|
|
||||||
if(job_)
|
|
||||||
fm_job_cancel(FM_JOB(job_));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isRunning() const {
|
|
||||||
return job_ ? fm_job_is_running(FM_JOB(job_)) : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isCancelled() const {
|
|
||||||
return job_ ? fm_job_is_cancelled(FM_JOB(job_)) : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
FmFileOpsJob* job() {
|
|
||||||
return job_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool autoDestroy() {
|
|
||||||
return autoDestroy_;
|
|
||||||
}
|
|
||||||
void setAutoDestroy(bool destroy = true) {
|
|
||||||
autoDestroy_ = destroy;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type type() {
|
|
||||||
return (Type)job_->type;
|
|
||||||
}
|
|
||||||
|
|
||||||
// convinient static functions
|
|
||||||
static FileOperation* copyFiles(FmPathList* srcFiles, FmPath* dest, QWidget* parent = 0);
|
|
||||||
static FileOperation* moveFiles(FmPathList* srcFiles, FmPath* dest, QWidget* parent = 0);
|
|
||||||
static FileOperation* symlinkFiles(FmPathList* srcFiles, FmPath* dest, QWidget* parent = 0);
|
|
||||||
static FileOperation* deleteFiles(FmPathList* srcFiles, bool promp = true, QWidget* parent = 0);
|
|
||||||
static FileOperation* trashFiles(FmPathList* srcFiles, bool promp = true, QWidget* parent = 0);
|
|
||||||
static FileOperation* unTrashFiles(FmPathList* srcFiles, QWidget* parent = 0);
|
|
||||||
static FileOperation* changeAttrFiles(FmPathList* srcFiles, QWidget* parent = 0);
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void finished();
|
|
||||||
|
|
||||||
private:
|
|
||||||
static gint onFileOpsJobAsk(FmFileOpsJob* job, const char* question, char* const* options, FileOperation* pThis);
|
|
||||||
static gint onFileOpsJobAskRename(FmFileOpsJob* job, FmFileInfo* src, FmFileInfo* dest, char** new_name, FileOperation* pThis);
|
|
||||||
static FmJobErrorAction onFileOpsJobError(FmFileOpsJob* job, GError* err, FmJobErrorSeverity severity, FileOperation* pThis);
|
|
||||||
static void onFileOpsJobPrepared(FmFileOpsJob* job, FileOperation* pThis);
|
|
||||||
static void onFileOpsJobCurFile(FmFileOpsJob* job, const char* cur_file, FileOperation* pThis);
|
|
||||||
static void onFileOpsJobPercent(FmFileOpsJob* job, guint percent, FileOperation* pThis);
|
|
||||||
static void onFileOpsJobFinished(FmFileOpsJob* job, FileOperation* pThis);
|
|
||||||
static void onFileOpsJobCancelled(FmFileOpsJob* job, FileOperation* pThis);
|
|
||||||
|
|
||||||
void handleFinish();
|
|
||||||
void disconnectJob();
|
|
||||||
void showDialog();
|
|
||||||
|
|
||||||
void pauseElapsedTimer() {
|
|
||||||
if(Q_LIKELY(elapsedTimer_ != NULL)) {
|
|
||||||
lastElapsed_ += elapsedTimer_->elapsed();
|
|
||||||
elapsedTimer_->invalidate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void resumeElapsedTimer() {
|
|
||||||
if(Q_LIKELY(elapsedTimer_ != NULL)) {
|
|
||||||
elapsedTimer_->start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qint64 elapsedTime() {
|
|
||||||
if(Q_LIKELY(elapsedTimer_ != NULL)) {
|
|
||||||
return lastElapsed_ + elapsedTimer_->elapsed();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
|
||||||
void onUiTimeout();
|
|
||||||
|
|
||||||
private:
|
|
||||||
FmFileOpsJob* job_;
|
|
||||||
FileOperationDialog* dlg;
|
|
||||||
FmPath* destPath;
|
|
||||||
FmPathList* srcPaths;
|
|
||||||
QTimer* uiTimer;
|
|
||||||
QElapsedTimer* elapsedTimer_;
|
|
||||||
qint64 lastElapsed_;
|
|
||||||
bool updateRemainingTime_;
|
|
||||||
QString curFile;
|
|
||||||
bool autoDestroy_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_FILEOPERATION_H
|
|
||||||
@ -1,176 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "fileoperationdialog.h"
|
|
||||||
#include "fileoperation.h"
|
|
||||||
#include "renamedialog.h"
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include "ui_file-operation-dialog.h"
|
|
||||||
|
|
||||||
using namespace Fm;
|
|
||||||
|
|
||||||
FileOperationDialog::FileOperationDialog(FileOperation* _operation):
|
|
||||||
QDialog(NULL),
|
|
||||||
operation(_operation),
|
|
||||||
defaultOption(-1) {
|
|
||||||
|
|
||||||
ui = new Ui::FileOperationDialog();
|
|
||||||
ui->setupUi(this);
|
|
||||||
|
|
||||||
QString title;
|
|
||||||
QString message;
|
|
||||||
switch(_operation->type()) {
|
|
||||||
case FM_FILE_OP_MOVE:
|
|
||||||
title = tr("Move files");
|
|
||||||
message = tr("Moving the following files to destination folder:");
|
|
||||||
break;
|
|
||||||
case FM_FILE_OP_COPY:
|
|
||||||
title = tr("Copy Files");
|
|
||||||
message = tr("Copying the following files to destination folder:");
|
|
||||||
break;
|
|
||||||
case FM_FILE_OP_TRASH:
|
|
||||||
title = tr("Trash Files");
|
|
||||||
message = tr("Moving the following files to trash can:");
|
|
||||||
break;
|
|
||||||
case FM_FILE_OP_DELETE:
|
|
||||||
title = tr("Delete Files");
|
|
||||||
message = tr("Deleting the following files");
|
|
||||||
ui->dest->hide();
|
|
||||||
ui->destLabel->hide();
|
|
||||||
break;
|
|
||||||
case FM_FILE_OP_LINK:
|
|
||||||
title = tr("Create Symlinks");
|
|
||||||
message = tr("Creating symlinks for the following files:");
|
|
||||||
break;
|
|
||||||
case FM_FILE_OP_CHANGE_ATTR:
|
|
||||||
title = tr("Change Attributes");
|
|
||||||
message = tr("Changing attributes of the following files:");
|
|
||||||
ui->dest->hide();
|
|
||||||
ui->destLabel->hide();
|
|
||||||
break;
|
|
||||||
case FM_FILE_OP_UNTRASH:
|
|
||||||
title = tr("Restore Trashed Files");
|
|
||||||
message = tr("Restoring the following files from trash can:");
|
|
||||||
ui->dest->hide();
|
|
||||||
ui->destLabel->hide();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ui->message->setText(message);
|
|
||||||
setWindowTitle(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FileOperationDialog::~FileOperationDialog() {
|
|
||||||
delete ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileOperationDialog::setDestPath(FmPath* dest) {
|
|
||||||
char* pathStr = fm_path_display_name(dest, false);
|
|
||||||
ui->dest->setText(QString::fromUtf8(pathStr));
|
|
||||||
g_free(pathStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileOperationDialog::setSourceFiles(FmPathList* srcFiles) {
|
|
||||||
GList* l;
|
|
||||||
for(l = fm_path_list_peek_head_link(srcFiles); l; l = l->next) {
|
|
||||||
FmPath* path = FM_PATH(l->data);
|
|
||||||
char* pathStr = fm_path_display_name(path, false);
|
|
||||||
ui->sourceFiles->addItem(QString::fromUtf8(pathStr));
|
|
||||||
g_free(pathStr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int FileOperationDialog::ask(QString question, char*const* options) {
|
|
||||||
// TODO: implement FileOperationDialog::ask()
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FileOperationDialog::askRename(FmFileInfo* src, FmFileInfo* dest, QString& new_name) {
|
|
||||||
int ret;
|
|
||||||
if(defaultOption == -1) { // default action is not set, ask the user
|
|
||||||
RenameDialog dlg(src, dest, this);
|
|
||||||
dlg.exec();
|
|
||||||
switch(dlg.action()) {
|
|
||||||
case RenameDialog::ActionOverwrite:
|
|
||||||
ret = FM_FILE_OP_OVERWRITE;
|
|
||||||
if(dlg.applyToAll())
|
|
||||||
defaultOption = ret;
|
|
||||||
break;
|
|
||||||
case RenameDialog::ActionRename:
|
|
||||||
ret = FM_FILE_OP_RENAME;
|
|
||||||
new_name = dlg.newName();
|
|
||||||
break;
|
|
||||||
case RenameDialog::ActionIgnore:
|
|
||||||
ret = FM_FILE_OP_SKIP;
|
|
||||||
if(dlg.applyToAll())
|
|
||||||
defaultOption = ret;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ret = FM_FILE_OP_CANCEL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ret = defaultOption;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
FmJobErrorAction FileOperationDialog::error(GError* err, FmJobErrorSeverity severity) {
|
|
||||||
if(severity >= FM_JOB_ERROR_MODERATE) {
|
|
||||||
QMessageBox::critical(this, tr("Error"), QString::fromUtf8(err->message));
|
|
||||||
if(severity == FM_JOB_ERROR_CRITICAL)
|
|
||||||
return FM_JOB_ABORT;
|
|
||||||
}
|
|
||||||
return FM_JOB_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileOperationDialog::setCurFile(QString cur_file) {
|
|
||||||
ui->curFile->setText(cur_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileOperationDialog::setPercent(unsigned int percent) {
|
|
||||||
ui->progressBar->setValue(percent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileOperationDialog::setRemainingTime(unsigned int sec) {
|
|
||||||
unsigned int min = 0;
|
|
||||||
unsigned int hr = 0;
|
|
||||||
if(sec > 60) {
|
|
||||||
min = sec / 60;
|
|
||||||
sec %= 60;
|
|
||||||
if(min > 60) {
|
|
||||||
hr = min / 60;
|
|
||||||
min %= 60;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ui->timeRemaining->setText(QString("%1:%2:%3")
|
|
||||||
.arg(hr, 2, 10, QChar('0'))
|
|
||||||
.arg(min, 2, 10, QChar('0'))
|
|
||||||
.arg(sec, 2, 10, QChar('0')));
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileOperationDialog::setPrepared() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileOperationDialog::reject() {
|
|
||||||
operation->cancel();
|
|
||||||
QDialog::reject();
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FM_FILEOPERATIONDIALOG_H
|
|
||||||
#define FM_FILEOPERATIONDIALOG_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QDialog>
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class FileOperationDialog;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class FileOperation;
|
|
||||||
|
|
||||||
class LIBFM_QT_API FileOperationDialog : public QDialog {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit FileOperationDialog(FileOperation* _operation);
|
|
||||||
virtual ~FileOperationDialog();
|
|
||||||
|
|
||||||
void setSourceFiles(FmPathList* srcFiles);
|
|
||||||
void setDestPath(FmPath* dest);
|
|
||||||
|
|
||||||
int ask(QString question, char* const* options);
|
|
||||||
int askRename(FmFileInfo* src, FmFileInfo* dest, QString& new_name);
|
|
||||||
FmJobErrorAction error(GError* err, FmJobErrorSeverity severity);
|
|
||||||
void setPrepared();
|
|
||||||
void setCurFile(QString cur_file);
|
|
||||||
void setPercent(unsigned int percent);
|
|
||||||
void setRemainingTime(unsigned int sec);
|
|
||||||
|
|
||||||
virtual void reject();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::FileOperationDialog* ui;
|
|
||||||
FileOperation* operation;
|
|
||||||
int defaultOption;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_FILEOPERATIONDIALOG_H
|
|
||||||
@ -1,441 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "filepropsdialog.h"
|
|
||||||
#include "ui_file-props.h"
|
|
||||||
#include "icontheme.h"
|
|
||||||
#include "utilities.h"
|
|
||||||
#include "fileoperation.h"
|
|
||||||
#include <QStringBuilder>
|
|
||||||
#include <QStringListModel>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <qdial.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#define DIFFERENT_UIDS ((uid)-1)
|
|
||||||
#define DIFFERENT_GIDS ((gid)-1)
|
|
||||||
#define DIFFERENT_PERMS ((mode_t)-1)
|
|
||||||
|
|
||||||
using namespace Fm;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
ACCESS_NO_CHANGE = 0,
|
|
||||||
ACCESS_READ_ONLY,
|
|
||||||
ACCESS_READ_WRITE,
|
|
||||||
ACCESS_FORBID
|
|
||||||
};
|
|
||||||
|
|
||||||
FilePropsDialog::FilePropsDialog(FmFileInfoList* files, QWidget* parent, Qt::WindowFlags f):
|
|
||||||
QDialog(parent, f),
|
|
||||||
fileInfos_(fm_file_info_list_ref(files)),
|
|
||||||
singleType(fm_file_info_list_is_same_type(files)),
|
|
||||||
singleFile(fm_file_info_list_get_length(files) == 1 ? true:false),
|
|
||||||
fileInfo(fm_file_info_list_peek_head(files)),
|
|
||||||
mimeType(NULL) {
|
|
||||||
|
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
|
|
||||||
ui = new Ui::FilePropsDialog();
|
|
||||||
ui->setupUi(this);
|
|
||||||
|
|
||||||
if(singleType) {
|
|
||||||
mimeType = fm_mime_type_ref(fm_file_info_get_mime_type(fileInfo));
|
|
||||||
}
|
|
||||||
|
|
||||||
FmPathList* paths = fm_path_list_new_from_file_info_list(files);
|
|
||||||
deepCountJob = fm_deep_count_job_new(paths, FM_DC_JOB_DEFAULT);
|
|
||||||
fm_path_list_unref(paths);
|
|
||||||
|
|
||||||
initGeneralPage();
|
|
||||||
initPermissionsPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
FilePropsDialog::~FilePropsDialog() {
|
|
||||||
delete ui;
|
|
||||||
|
|
||||||
if(fileInfos_)
|
|
||||||
fm_file_info_list_unref(fileInfos_);
|
|
||||||
if(deepCountJob)
|
|
||||||
g_object_unref(deepCountJob);
|
|
||||||
if(fileSizeTimer) {
|
|
||||||
fileSizeTimer->stop();
|
|
||||||
delete fileSizeTimer;
|
|
||||||
fileSizeTimer = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FilePropsDialog::initApplications() {
|
|
||||||
if(singleType && mimeType && !fm_file_info_is_dir(fileInfo)) {
|
|
||||||
ui->openWith->setMimeType(mimeType);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ui->openWith->hide();
|
|
||||||
ui->openWithLabel->hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FilePropsDialog::initPermissionsPage() {
|
|
||||||
// ownership handling
|
|
||||||
// get owner/group and mode of the first file in the list
|
|
||||||
uid = fm_file_info_get_uid(fileInfo);
|
|
||||||
gid = fm_file_info_get_gid(fileInfo);
|
|
||||||
mode_t mode = fm_file_info_get_mode(fileInfo);
|
|
||||||
ownerPerm = (mode & (S_IRUSR|S_IWUSR|S_IXUSR));
|
|
||||||
groupPerm = (mode & (S_IRGRP|S_IWGRP|S_IXGRP));
|
|
||||||
otherPerm = (mode & (S_IROTH|S_IWOTH|S_IXOTH));
|
|
||||||
execPerm = (mode & (S_IXUSR|S_IXGRP|S_IXOTH));
|
|
||||||
allNative = fm_file_info_is_native(fileInfo);
|
|
||||||
hasDir = S_ISDIR(mode);
|
|
||||||
|
|
||||||
// check if all selected files belongs to the same owner/group or have the same mode
|
|
||||||
// at the same time, check if all files are on native unix filesystems
|
|
||||||
GList* l;
|
|
||||||
for(l = fm_file_info_list_peek_head_link(fileInfos_)->next; l; l = l->next) {
|
|
||||||
FmFileInfo* fi = FM_FILE_INFO(l->data);
|
|
||||||
if(allNative && !fm_file_info_is_native(fi))
|
|
||||||
allNative = false; // not all of the files are native
|
|
||||||
|
|
||||||
mode_t fi_mode = fm_file_info_get_mode(fi);
|
|
||||||
if(S_ISDIR(fi_mode))
|
|
||||||
hasDir = true; // the files list contains dir(s)
|
|
||||||
|
|
||||||
if(uid != DIFFERENT_UIDS && uid != fm_file_info_get_uid(fi))
|
|
||||||
uid = DIFFERENT_UIDS; // not all files have the same owner
|
|
||||||
if(gid != DIFFERENT_GIDS && gid != fm_file_info_get_gid(fi))
|
|
||||||
gid = DIFFERENT_GIDS; // not all files have the same owner group
|
|
||||||
|
|
||||||
if(ownerPerm != DIFFERENT_PERMS && ownerPerm != (fi_mode & (S_IRUSR|S_IWUSR|S_IXUSR)))
|
|
||||||
ownerPerm = DIFFERENT_PERMS; // not all files have the same permission for owner
|
|
||||||
if(groupPerm != DIFFERENT_PERMS && groupPerm != (fi_mode & (S_IRGRP|S_IWGRP|S_IXGRP)))
|
|
||||||
groupPerm = DIFFERENT_PERMS; // not all files have the same permission for grop
|
|
||||||
if(otherPerm != DIFFERENT_PERMS && otherPerm != (fi_mode & (S_IROTH|S_IWOTH|S_IXOTH)))
|
|
||||||
otherPerm = DIFFERENT_PERMS; // not all files have the same permission for other
|
|
||||||
if(execPerm != DIFFERENT_PERMS && execPerm != (fi_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
|
|
||||||
execPerm = DIFFERENT_PERMS; // not all files have the same executable permission
|
|
||||||
}
|
|
||||||
|
|
||||||
// init owner/group
|
|
||||||
initOwner();
|
|
||||||
|
|
||||||
// if all files are of the same type, and some of them are dirs => all of the items are dirs
|
|
||||||
// rwx values have different meanings for dirs
|
|
||||||
// Let's make it clear for the users
|
|
||||||
// init combo boxes for file permissions here
|
|
||||||
QStringList comboItems;
|
|
||||||
comboItems.append("---"); // no change
|
|
||||||
if(singleType && hasDir) { // all files are dirs
|
|
||||||
comboItems.append(tr("View folder content"));
|
|
||||||
comboItems.append(tr("View and modify folder content"));
|
|
||||||
ui->executable->hide();
|
|
||||||
}
|
|
||||||
else { //not all of the files are dirs
|
|
||||||
comboItems.append(tr("Read"));
|
|
||||||
comboItems.append(tr("Read and write"));
|
|
||||||
}
|
|
||||||
comboItems.append(tr("Forbidden"));
|
|
||||||
QStringListModel* comboModel = new QStringListModel(comboItems, this);
|
|
||||||
ui->ownerPerm->setModel(comboModel);
|
|
||||||
ui->groupPerm->setModel(comboModel);
|
|
||||||
ui->otherPerm->setModel(comboModel);
|
|
||||||
|
|
||||||
// owner
|
|
||||||
ownerPermSel = ACCESS_NO_CHANGE;
|
|
||||||
if(ownerPerm != DIFFERENT_PERMS) { // permissions for owner are the same among all files
|
|
||||||
if(ownerPerm & S_IRUSR) { // can read
|
|
||||||
if(ownerPerm & S_IWUSR) // can write
|
|
||||||
ownerPermSel = ACCESS_READ_WRITE;
|
|
||||||
else
|
|
||||||
ownerPermSel = ACCESS_READ_ONLY;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if((ownerPerm & S_IWUSR) == 0) // cannot read or write
|
|
||||||
ownerPermSel = ACCESS_FORBID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ui->ownerPerm->setCurrentIndex(ownerPermSel);
|
|
||||||
|
|
||||||
// owner and group
|
|
||||||
groupPermSel = ACCESS_NO_CHANGE;
|
|
||||||
if(groupPerm != DIFFERENT_PERMS) { // permissions for owner are the same among all files
|
|
||||||
if(groupPerm & S_IRGRP) { // can read
|
|
||||||
if(groupPerm & S_IWGRP) // can write
|
|
||||||
groupPermSel = ACCESS_READ_WRITE;
|
|
||||||
else
|
|
||||||
groupPermSel = ACCESS_READ_ONLY;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if((groupPerm & S_IWGRP) == 0) // cannot read or write
|
|
||||||
groupPermSel = ACCESS_FORBID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ui->groupPerm->setCurrentIndex(groupPermSel);
|
|
||||||
|
|
||||||
// other
|
|
||||||
otherPermSel = ACCESS_NO_CHANGE;
|
|
||||||
if(otherPerm != DIFFERENT_PERMS) { // permissions for owner are the same among all files
|
|
||||||
if(otherPerm & S_IROTH) { // can read
|
|
||||||
if(otherPerm & S_IWOTH) // can write
|
|
||||||
otherPermSel = ACCESS_READ_WRITE;
|
|
||||||
else
|
|
||||||
otherPermSel = ACCESS_READ_ONLY;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if((otherPerm & S_IWOTH) == 0) // cannot read or write
|
|
||||||
otherPermSel = ACCESS_FORBID;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
ui->otherPerm->setCurrentIndex(otherPermSel);
|
|
||||||
|
|
||||||
// set the checkbox to partially checked state
|
|
||||||
// when owner, group, and other have different executable flags set.
|
|
||||||
// some of them have exec, and others do not have.
|
|
||||||
execCheckState = Qt::PartiallyChecked;
|
|
||||||
if(execPerm != DIFFERENT_PERMS) { // if all files have the same executable permission
|
|
||||||
// check if the files are all executable
|
|
||||||
if((mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == (S_IXUSR|S_IXGRP|S_IXOTH)) {
|
|
||||||
// owner, group, and other all have exec permission.
|
|
||||||
ui->executable->setTristate(false);
|
|
||||||
execCheckState = Qt::Checked;
|
|
||||||
}
|
|
||||||
else if((mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0) {
|
|
||||||
// owner, group, and other all have no exec permission
|
|
||||||
ui->executable->setTristate(false);
|
|
||||||
execCheckState = Qt::Unchecked;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ui->executable->setCheckState(execCheckState);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FilePropsDialog::initGeneralPage() {
|
|
||||||
// update UI
|
|
||||||
if(singleType) { // all files are of the same mime-type
|
|
||||||
FmIcon* icon = NULL;
|
|
||||||
// FIXME: handle custom icons for some files
|
|
||||||
// FIXME: display special property pages for special files or
|
|
||||||
// some specified mime-types.
|
|
||||||
if(singleFile) { // only one file is selected.
|
|
||||||
icon = fm_file_info_get_icon(fileInfo);
|
|
||||||
}
|
|
||||||
if(mimeType) {
|
|
||||||
if(!icon) // get an icon from mime type if needed
|
|
||||||
icon = fm_mime_type_get_icon(mimeType);
|
|
||||||
ui->fileType->setText(QString::fromUtf8(fm_mime_type_get_desc(mimeType)));
|
|
||||||
ui->mimeType->setText(QString::fromUtf8(fm_mime_type_get_type(mimeType)));
|
|
||||||
}
|
|
||||||
if(icon) {
|
|
||||||
ui->iconButton->setIcon(IconTheme::icon(icon));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(singleFile && fm_file_info_is_symlink(fileInfo)) {
|
|
||||||
ui->target->setText(QString::fromUtf8(fm_file_info_get_target(fileInfo)));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ui->target->hide();
|
|
||||||
ui->targetLabel->hide();
|
|
||||||
}
|
|
||||||
} // end if(singleType)
|
|
||||||
else { // not singleType, multiple files are selected at the same time
|
|
||||||
ui->fileType->setText(tr("Files of different types"));
|
|
||||||
ui->target->hide();
|
|
||||||
ui->targetLabel->hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: check if all files has the same parent dir, mtime, or atime
|
|
||||||
if(singleFile) { // only one file is selected
|
|
||||||
FmPath* parent_path = fm_path_get_parent(fm_file_info_get_path(fileInfo));
|
|
||||||
char* parent_str = parent_path ? fm_path_display_name(parent_path, true) : NULL;
|
|
||||||
|
|
||||||
ui->fileName->setText(QString::fromUtf8(fm_file_info_get_disp_name(fileInfo)));
|
|
||||||
if(parent_str) {
|
|
||||||
ui->location->setText(QString::fromUtf8(parent_str));
|
|
||||||
g_free(parent_str);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ui->location->clear();
|
|
||||||
|
|
||||||
ui->lastModified->setText(QString::fromUtf8(fm_file_info_get_disp_mtime(fileInfo)));
|
|
||||||
|
|
||||||
// FIXME: need to encapsulate this in an libfm API.
|
|
||||||
time_t atime;
|
|
||||||
struct tm tm;
|
|
||||||
atime = fm_file_info_get_atime(fileInfo);
|
|
||||||
localtime_r(&atime, &tm);
|
|
||||||
char buf[128];
|
|
||||||
strftime(buf, sizeof(buf), "%x %R", &tm);
|
|
||||||
ui->lastAccessed->setText(QString::fromUtf8(buf));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ui->fileName->setText(tr("Multiple Files"));
|
|
||||||
ui->fileName->setEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
initApplications(); // init applications combo box
|
|
||||||
|
|
||||||
// calculate total file sizes
|
|
||||||
fileSizeTimer = new QTimer(this);
|
|
||||||
connect(fileSizeTimer, &QTimer::timeout, this, &FilePropsDialog::onFileSizeTimerTimeout);
|
|
||||||
fileSizeTimer->start(600);
|
|
||||||
g_signal_connect(deepCountJob, "finished", G_CALLBACK(onDeepCountJobFinished), this);
|
|
||||||
fm_job_run_async(FM_JOB(deepCountJob));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*static */ void FilePropsDialog::onDeepCountJobFinished(FmDeepCountJob* job, FilePropsDialog* pThis) {
|
|
||||||
|
|
||||||
pThis->onFileSizeTimerTimeout(); // update file size display
|
|
||||||
|
|
||||||
// free the job
|
|
||||||
g_object_unref(pThis->deepCountJob);
|
|
||||||
pThis->deepCountJob = NULL;
|
|
||||||
|
|
||||||
// stop the timer
|
|
||||||
if(pThis->fileSizeTimer) {
|
|
||||||
pThis->fileSizeTimer->stop();
|
|
||||||
delete pThis->fileSizeTimer;
|
|
||||||
pThis->fileSizeTimer = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FilePropsDialog::onFileSizeTimerTimeout() {
|
|
||||||
if(deepCountJob && !fm_job_is_cancelled(FM_JOB(deepCountJob))) {
|
|
||||||
char size_str[128];
|
|
||||||
fm_file_size_to_str(size_str, sizeof(size_str), deepCountJob->total_size,
|
|
||||||
fm_config->si_unit);
|
|
||||||
// FIXME:
|
|
||||||
// OMG! It's really unbelievable that Qt developers only implement
|
|
||||||
// QObject::tr(... int n). GNU gettext developers are smarter and
|
|
||||||
// they use unsigned long instead of int.
|
|
||||||
// We cannot use Qt here to handle plural forms. So sad. :-(
|
|
||||||
QString str = QString::fromUtf8(size_str) %
|
|
||||||
QString(" (%1 B)").arg(deepCountJob->total_size);
|
|
||||||
// tr(" (%n) byte(s)", "", deepCountJob->total_size);
|
|
||||||
ui->fileSize->setText(str);
|
|
||||||
|
|
||||||
fm_file_size_to_str(size_str, sizeof(size_str), deepCountJob->total_ondisk_size,
|
|
||||||
fm_config->si_unit);
|
|
||||||
str = QString::fromUtf8(size_str) %
|
|
||||||
QString(" (%1 B)").arg(deepCountJob->total_ondisk_size);
|
|
||||||
// tr(" (%n) byte(s)", "", deepCountJob->total_ondisk_size);
|
|
||||||
ui->onDiskSize->setText(str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FilePropsDialog::accept() {
|
|
||||||
|
|
||||||
// applications
|
|
||||||
if(mimeType && ui->openWith->isChanged()) {
|
|
||||||
GAppInfo* currentApp = ui->openWith->selectedApp();
|
|
||||||
g_app_info_set_as_default_for_type(currentApp, fm_mime_type_get_type(mimeType), NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if chown or chmod is needed
|
|
||||||
guint32 newUid = uidFromName(ui->owner->text());
|
|
||||||
guint32 newGid = gidFromName(ui->ownerGroup->text());
|
|
||||||
bool needChown = (newUid != -1 && newUid != uid) || (newGid != -1 && newGid != gid);
|
|
||||||
|
|
||||||
int newOwnerPermSel = ui->ownerPerm->currentIndex();
|
|
||||||
int newGroupPermSel = ui->groupPerm->currentIndex();
|
|
||||||
int newOtherPermSel = ui->otherPerm->currentIndex();
|
|
||||||
Qt::CheckState newExecCheckState = ui->executable->checkState();
|
|
||||||
bool needChmod = ((newOwnerPermSel != ownerPermSel) ||
|
|
||||||
(newGroupPermSel != groupPermSel) ||
|
|
||||||
(newOtherPermSel != otherPermSel) ||
|
|
||||||
(newExecCheckState != execCheckState));
|
|
||||||
|
|
||||||
if(needChmod || needChown) {
|
|
||||||
FmPathList* paths = fm_path_list_new_from_file_info_list(fileInfos_);
|
|
||||||
FileOperation* op = new FileOperation(FileOperation::ChangeAttr, paths);
|
|
||||||
fm_path_list_unref(paths);
|
|
||||||
if(needChown) {
|
|
||||||
// don't do chown if new uid/gid and the original ones are actually the same.
|
|
||||||
if(newUid == uid)
|
|
||||||
newUid = -1;
|
|
||||||
if(newGid == gid)
|
|
||||||
newGid = -1;
|
|
||||||
op->setChown(newUid, newGid);
|
|
||||||
}
|
|
||||||
if(needChmod) {
|
|
||||||
mode_t newMode = 0;
|
|
||||||
mode_t newModeMask = 0;
|
|
||||||
// FIXME: we need to make sure that folders with "r" permission also have "x"
|
|
||||||
// at the same time. Otherwise, it's not able to browse the folder later.
|
|
||||||
if(newOwnerPermSel != ownerPermSel && newOwnerPermSel != ACCESS_NO_CHANGE) {
|
|
||||||
// owner permission changed
|
|
||||||
newModeMask |= (S_IRUSR|S_IWUSR); // affect user bits
|
|
||||||
if(newOwnerPermSel == ACCESS_READ_ONLY)
|
|
||||||
newMode |= S_IRUSR;
|
|
||||||
else if(newOwnerPermSel == ACCESS_READ_WRITE)
|
|
||||||
newMode |= (S_IRUSR|S_IWUSR);
|
|
||||||
}
|
|
||||||
if(newGroupPermSel != groupPermSel && newGroupPermSel != ACCESS_NO_CHANGE) {
|
|
||||||
qDebug("newGroupPermSel: %d", newGroupPermSel);
|
|
||||||
// group permission changed
|
|
||||||
newModeMask |= (S_IRGRP|S_IWGRP); // affect group bits
|
|
||||||
if(newGroupPermSel == ACCESS_READ_ONLY)
|
|
||||||
newMode |= S_IRGRP;
|
|
||||||
else if(newGroupPermSel == ACCESS_READ_WRITE)
|
|
||||||
newMode |= (S_IRGRP|S_IWGRP);
|
|
||||||
}
|
|
||||||
if(newOtherPermSel != otherPermSel && newOtherPermSel != ACCESS_NO_CHANGE) {
|
|
||||||
// other permission changed
|
|
||||||
newModeMask |= (S_IROTH|S_IWOTH); // affect other bits
|
|
||||||
if(newOtherPermSel == ACCESS_READ_ONLY)
|
|
||||||
newMode |= S_IROTH;
|
|
||||||
else if(newOtherPermSel == ACCESS_READ_WRITE)
|
|
||||||
newMode |= (S_IROTH|S_IWOTH);
|
|
||||||
}
|
|
||||||
if(newExecCheckState != execCheckState && newExecCheckState != Qt::PartiallyChecked) {
|
|
||||||
// executable state changed
|
|
||||||
newModeMask |= (S_IXUSR|S_IXGRP|S_IXOTH);
|
|
||||||
if(newExecCheckState == Qt::Checked)
|
|
||||||
newMode |= (S_IXUSR|S_IXGRP|S_IXOTH);
|
|
||||||
}
|
|
||||||
op->setChmod(newMode, newModeMask);
|
|
||||||
|
|
||||||
if(hasDir) { // if there are some dirs in our selected files
|
|
||||||
QMessageBox::StandardButton r = QMessageBox::question(this,
|
|
||||||
tr("Apply changes"),
|
|
||||||
tr("Do you want to recursively apply these changes to all files and sub-folders?"),
|
|
||||||
QMessageBox::Yes|QMessageBox::No);
|
|
||||||
if(r == QMessageBox::Yes)
|
|
||||||
op->setRecursiveChattr(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
op->setAutoDestroy(true);
|
|
||||||
op->run();
|
|
||||||
}
|
|
||||||
|
|
||||||
QDialog::accept();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FilePropsDialog::initOwner() {
|
|
||||||
if(allNative) {
|
|
||||||
if(uid != DIFFERENT_UIDS)
|
|
||||||
ui->owner->setText(uidToName(uid));
|
|
||||||
if(gid != DIFFERENT_GIDS)
|
|
||||||
ui->ownerGroup->setText(gidToName(gid));
|
|
||||||
|
|
||||||
if(geteuid() != 0) { // on local filesystems, only root can do chown.
|
|
||||||
ui->owner->setEnabled(false);
|
|
||||||
ui->ownerGroup->setEnabled(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,97 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FM_FILEPROPSDIALOG_H
|
|
||||||
#define FM_FILEPROPSDIALOG_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QDialog>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class FilePropsDialog;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class LIBFM_QT_API FilePropsDialog : public QDialog {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit FilePropsDialog(FmFileInfoList* files, QWidget* parent = 0, Qt::WindowFlags f = 0);
|
|
||||||
virtual ~FilePropsDialog();
|
|
||||||
|
|
||||||
virtual void accept();
|
|
||||||
|
|
||||||
static FilePropsDialog* showForFile(FmFileInfo* file, QWidget* parent = 0) {
|
|
||||||
FmFileInfoList* files = fm_file_info_list_new();
|
|
||||||
fm_file_info_list_push_tail(files, file);
|
|
||||||
FilePropsDialog* dlg = showForFiles(files, parent);
|
|
||||||
fm_file_info_list_unref(files);
|
|
||||||
return dlg;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FilePropsDialog* showForFiles(FmFileInfoList* files, QWidget* parent = 0) {
|
|
||||||
FilePropsDialog* dlg = new FilePropsDialog(files, parent);
|
|
||||||
dlg->show();
|
|
||||||
return dlg;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void initGeneralPage();
|
|
||||||
void initApplications();
|
|
||||||
void initPermissionsPage();
|
|
||||||
void initOwner();
|
|
||||||
|
|
||||||
static void onDeepCountJobFinished(FmDeepCountJob* job, FilePropsDialog* pThis);
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
|
||||||
void onFileSizeTimerTimeout();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::FilePropsDialog* ui;
|
|
||||||
FmFileInfoList* fileInfos_; // list of all file infos
|
|
||||||
FmFileInfo* fileInfo; // file info of the first file in the list
|
|
||||||
bool singleType; // all files are of the same type?
|
|
||||||
bool singleFile; // only one file is selected?
|
|
||||||
bool hasDir; // is there any dir in the files?
|
|
||||||
bool allNative; // all files are on native UNIX filesystems (not virtual or remote)
|
|
||||||
|
|
||||||
FmMimeType* mimeType; // mime type of the files
|
|
||||||
|
|
||||||
gint32 uid; // owner uid of the files, -1 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
|
|
||||||
mode_t ownerPerm; // read permission of the files, -1 means not all files have the same value
|
|
||||||
int ownerPermSel;
|
|
||||||
mode_t groupPerm; // read permission of the files, -1 means not all files have the same value
|
|
||||||
int groupPermSel;
|
|
||||||
mode_t otherPerm; // read permission of the files, -1 means not all files have the same value
|
|
||||||
int otherPermSel;
|
|
||||||
mode_t execPerm; // exec permission of the files
|
|
||||||
Qt::CheckState execCheckState;
|
|
||||||
|
|
||||||
FmDeepCountJob* deepCountJob; // job used to count total size
|
|
||||||
QTimer* fileSizeTimer;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_FILEPROPSDIALOG_H
|
|
||||||
@ -1,216 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "folderitemdelegate.h"
|
|
||||||
#include "foldermodel.h"
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QModelIndex>
|
|
||||||
#include <QStyleOptionViewItemV4>
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QIcon>
|
|
||||||
#include <QTextLayout>
|
|
||||||
#include <QTextOption>
|
|
||||||
#include <QTextLine>
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
FolderItemDelegate::FolderItemDelegate(QAbstractItemView* view, QObject* parent):
|
|
||||||
QStyledItemDelegate(parent ? parent : view),
|
|
||||||
symlinkIcon_(QIcon::fromTheme("emblem-symbolic-link")),
|
|
||||||
view_(view) {
|
|
||||||
}
|
|
||||||
|
|
||||||
FolderItemDelegate::~FolderItemDelegate() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize FolderItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const {
|
|
||||||
QVariant value = index.data(Qt::SizeHintRole);
|
|
||||||
if(value.isValid())
|
|
||||||
return qvariant_cast<QSize>(value);
|
|
||||||
if(option.decorationPosition == QStyleOptionViewItem::Top ||
|
|
||||||
option.decorationPosition == QStyleOptionViewItem::Bottom) {
|
|
||||||
|
|
||||||
QStyleOptionViewItemV4 opt = option;
|
|
||||||
initStyleOption(&opt, index);
|
|
||||||
opt.decorationAlignment = Qt::AlignHCenter|Qt::AlignTop;
|
|
||||||
opt.displayAlignment = Qt::AlignTop|Qt::AlignHCenter;
|
|
||||||
|
|
||||||
// FIXME: there're some problems in this size hint calculation.
|
|
||||||
Q_ASSERT(gridSize_ != QSize());
|
|
||||||
QRectF textRect(0, 0, gridSize_.width() - 4, gridSize_.height() - opt.decorationSize.height() - 4);
|
|
||||||
drawText(NULL, opt, textRect); // passing NULL for painter will calculate the bounding rect only.
|
|
||||||
int width = qMax((int)textRect.width(), opt.decorationSize.width()) + 4;
|
|
||||||
int height = opt.decorationSize.height() + textRect.height() + 4;
|
|
||||||
return QSize(width, height);
|
|
||||||
}
|
|
||||||
return QStyledItemDelegate::sizeHint(option, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
QIcon::Mode FolderItemDelegate::iconModeFromState(QStyle::State state) {
|
|
||||||
QIcon::Mode iconMode;
|
|
||||||
if(state & QStyle::State_Enabled) {
|
|
||||||
if(state & QStyle::State_Selected)
|
|
||||||
iconMode = QIcon::Selected;
|
|
||||||
else {
|
|
||||||
iconMode = QIcon::Normal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
iconMode = QIcon::Disabled;
|
|
||||||
return iconMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
// special thanks to Razor-qt developer Alec Moskvin(amoskvin) for providing the fix!
|
|
||||||
void FolderItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const {
|
|
||||||
Q_ASSERT(index.isValid());
|
|
||||||
FmFileInfo* file = static_cast<FmFileInfo*>(index.data(FolderModel::FileInfoRole).value<void*>());
|
|
||||||
bool isSymlink = file && fm_file_info_is_symlink(file);
|
|
||||||
|
|
||||||
if(option.decorationPosition == QStyleOptionViewItem::Top ||
|
|
||||||
option.decorationPosition == QStyleOptionViewItem::Bottom) {
|
|
||||||
painter->save();
|
|
||||||
painter->setClipRect(option.rect);
|
|
||||||
|
|
||||||
QStyleOptionViewItemV4 opt = option;
|
|
||||||
initStyleOption(&opt, index);
|
|
||||||
opt.decorationAlignment = Qt::AlignHCenter|Qt::AlignTop;
|
|
||||||
opt.displayAlignment = Qt::AlignTop|Qt::AlignHCenter;
|
|
||||||
|
|
||||||
// draw the icon
|
|
||||||
QIcon::Mode iconMode = iconModeFromState(opt.state);
|
|
||||||
QPoint iconPos(opt.rect.x() + (opt.rect.width() - opt.decorationSize.width()) / 2, opt.rect.y());
|
|
||||||
QPixmap pixmap = opt.icon.pixmap(opt.decorationSize, iconMode);
|
|
||||||
painter->drawPixmap(iconPos, pixmap);
|
|
||||||
|
|
||||||
// draw some emblems for the item if needed
|
|
||||||
// we only support symlink emblem at the moment
|
|
||||||
if(isSymlink)
|
|
||||||
painter->drawPixmap(iconPos, symlinkIcon_.pixmap(opt.decorationSize / 2, iconMode));
|
|
||||||
|
|
||||||
// draw the text
|
|
||||||
QRectF textRect(opt.rect.x(), opt.rect.y() + opt.decorationSize.height(), opt.rect.width(), opt.rect.height() - opt.decorationSize.height());
|
|
||||||
drawText(painter, opt, textRect);
|
|
||||||
painter->restore();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// let QStyledItemDelegate does its default painting
|
|
||||||
QStyledItemDelegate::paint(painter, option, index);
|
|
||||||
|
|
||||||
// draw emblems if needed
|
|
||||||
if(isSymlink) {
|
|
||||||
QStyleOptionViewItemV4 opt = option;
|
|
||||||
initStyleOption(&opt, index);
|
|
||||||
QIcon::Mode iconMode = iconModeFromState(opt.state);
|
|
||||||
QPoint iconPos(opt.rect.x(), opt.rect.y() + (opt.rect.height() - opt.decorationSize.height()) / 2);
|
|
||||||
// draw some emblems for the item if needed
|
|
||||||
// we only support symlink emblem at the moment
|
|
||||||
painter->drawPixmap(iconPos, symlinkIcon_.pixmap(opt.decorationSize / 2, iconMode));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if painter is NULL, the method calculate the bounding rectangle of the text and save it to textRect
|
|
||||||
void FolderItemDelegate::drawText(QPainter* painter, QStyleOptionViewItemV4& opt, QRectF& textRect) const {
|
|
||||||
QTextLayout layout(opt.text, opt.font);
|
|
||||||
QTextOption textOption;
|
|
||||||
textOption.setAlignment(opt.displayAlignment);
|
|
||||||
textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
|
|
||||||
textOption.setTextDirection(opt.direction);
|
|
||||||
layout.setTextOption(textOption);
|
|
||||||
qreal height = 0;
|
|
||||||
qreal width = 0;
|
|
||||||
int visibleLines = 0;
|
|
||||||
layout.beginLayout();
|
|
||||||
QString elidedText;
|
|
||||||
for(;;) {
|
|
||||||
QTextLine line = layout.createLine();
|
|
||||||
if(!line.isValid())
|
|
||||||
break;
|
|
||||||
line.setLineWidth(textRect.width());
|
|
||||||
height += opt.fontMetrics.leading();
|
|
||||||
line.setPosition(QPointF(0, height));
|
|
||||||
if((height + line.height() + textRect.y()) > textRect.bottom()) {
|
|
||||||
// if part of this line falls outside the textRect, ignore it and quit.
|
|
||||||
QTextLine lastLine = layout.lineAt(visibleLines - 1);
|
|
||||||
elidedText = opt.text.mid(lastLine.textStart());
|
|
||||||
elidedText = opt.fontMetrics.elidedText(elidedText, opt.textElideMode, textRect.width());
|
|
||||||
if(visibleLines == 1) // this is the only visible line
|
|
||||||
width = textRect.width();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
height += line.height();
|
|
||||||
width = qMax(width, line.naturalTextWidth());
|
|
||||||
++ visibleLines;
|
|
||||||
}
|
|
||||||
layout.endLayout();
|
|
||||||
|
|
||||||
// draw background for selected item
|
|
||||||
QRectF boundRect = layout.boundingRect();
|
|
||||||
//qDebug() << "bound rect: " << boundRect << "width: " << width;
|
|
||||||
boundRect.setWidth(width);
|
|
||||||
boundRect.moveTo(textRect.x() + (textRect.width() - width)/2, textRect.y());
|
|
||||||
|
|
||||||
if(!painter) { // no painter, calculate the bounding rect only
|
|
||||||
textRect = boundRect;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QPalette::ColorGroup cg = opt.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
|
|
||||||
if(opt.state & QStyle::State_Selected) {
|
|
||||||
painter->fillRect(boundRect, opt.palette.highlight());
|
|
||||||
painter->setPen(opt.palette.color(cg, QPalette::HighlightedText));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
painter->setPen(opt.palette.color(cg, QPalette::Text));
|
|
||||||
|
|
||||||
// draw text
|
|
||||||
for(int i = 0; i < visibleLines; ++i) {
|
|
||||||
QTextLine line = layout.lineAt(i);
|
|
||||||
if(i == (visibleLines - 1) && !elidedText.isEmpty()) { // the last line, draw elided text
|
|
||||||
QPointF pos(textRect.x() + line.position().x(), textRect.y() + line.y() + line.ascent());
|
|
||||||
painter->drawText(pos, elidedText);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
line.draw(painter, textRect.topLeft());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(opt.state & QStyle::State_HasFocus) {
|
|
||||||
// draw focus rect
|
|
||||||
QStyleOptionFocusRect o;
|
|
||||||
o.QStyleOption::operator=(opt);
|
|
||||||
o.rect = boundRect.toRect(); // subElementRect(SE_ItemViewItemFocusRect, vopt, widget);
|
|
||||||
o.state |= QStyle::State_KeyboardFocusChange;
|
|
||||||
o.state |= QStyle::State_Item;
|
|
||||||
QPalette::ColorGroup cg = (opt.state & QStyle::State_Enabled)
|
|
||||||
? QPalette::Normal : QPalette::Disabled;
|
|
||||||
o.backgroundColor = opt.palette.color(cg, (opt.state & QStyle::State_Selected)
|
|
||||||
? QPalette::Highlight : QPalette::Window);
|
|
||||||
if (const QWidget* widget = opt.widget) {
|
|
||||||
QStyle* style = widget->style() ? widget->style() : qApp->style();
|
|
||||||
style->drawPrimitive(QStyle::PE_FrameFocusRect, &o, painter, widget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Fm
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FM_FOLDERITEMDELEGATE_H
|
|
||||||
#define FM_FOLDERITEMDELEGATE_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QStyledItemDelegate>
|
|
||||||
#include <QAbstractItemView>
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class LIBFM_QT_API FolderItemDelegate : public QStyledItemDelegate {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit FolderItemDelegate(QAbstractItemView* view, QObject* parent = 0);
|
|
||||||
virtual ~FolderItemDelegate();
|
|
||||||
|
|
||||||
void setGridSize(QSize size) {
|
|
||||||
gridSize_ = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize gridSize() {
|
|
||||||
return gridSize_;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const;
|
|
||||||
virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void drawText(QPainter* painter, QStyleOptionViewItemV4& opt, QRectF& textRect) const;
|
|
||||||
static QIcon::Mode iconModeFromState(QStyle::State state);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QAbstractItemView* view_;
|
|
||||||
QIcon symlinkIcon_;
|
|
||||||
QSize gridSize_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_FOLDERITEMDELEGATE_H
|
|
||||||
@ -1,232 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013-2014 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
Copyright (C) 2012-2014 Andriy Grytsenko (LStranger) <andrej@rep.kiev.ua>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "foldermenu.h"
|
|
||||||
#include "createnewmenu.h"
|
|
||||||
#include "filepropsdialog.h"
|
|
||||||
#include "folderview.h"
|
|
||||||
#include "utilities.h"
|
|
||||||
#include <cstring> // for memset
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
FolderMenu::FolderMenu(FolderView* view, QWidget* parent):
|
|
||||||
QMenu(parent),
|
|
||||||
view_(view) {
|
|
||||||
|
|
||||||
ProxyFolderModel* model = view_->model();
|
|
||||||
|
|
||||||
createAction_ = new QAction(tr("Create &New"), this);
|
|
||||||
addAction(createAction_);
|
|
||||||
|
|
||||||
createAction_->setMenu(new CreateNewMenu(view_, view_->path(), this));
|
|
||||||
|
|
||||||
separator1_ = addSeparator();
|
|
||||||
|
|
||||||
pasteAction_ = new QAction(QIcon::fromTheme("edit-paste"), tr("&Paste"), this);
|
|
||||||
addAction(pasteAction_);
|
|
||||||
connect(pasteAction_, &QAction::triggered, this, &FolderMenu::onPasteActionTriggered);
|
|
||||||
|
|
||||||
separator2_ = addSeparator();
|
|
||||||
|
|
||||||
selectAllAction_ = new QAction(tr("Select &All"), this);
|
|
||||||
addAction(selectAllAction_);
|
|
||||||
connect(selectAllAction_, &QAction::triggered, this, &FolderMenu::onSelectAllActionTriggered);
|
|
||||||
|
|
||||||
invertSelectionAction_ = new QAction(tr("Invert Selection"), this);
|
|
||||||
addAction(invertSelectionAction_);
|
|
||||||
connect(invertSelectionAction_, &QAction::triggered, this, &FolderMenu::onInvertSelectionActionTriggered);
|
|
||||||
|
|
||||||
separator3_ = addSeparator();
|
|
||||||
|
|
||||||
sortAction_ = new QAction(tr("Sorting"), this);
|
|
||||||
addAction(sortAction_);
|
|
||||||
createSortMenu();
|
|
||||||
sortAction_->setMenu(sortMenu_);
|
|
||||||
|
|
||||||
showHiddenAction_ = new QAction(tr("Show Hidden"), this);
|
|
||||||
addAction(showHiddenAction_);
|
|
||||||
showHiddenAction_->setCheckable(true);
|
|
||||||
showHiddenAction_->setChecked(model->showHidden());
|
|
||||||
connect(showHiddenAction_, &QAction::triggered, this, &FolderMenu::onShowHiddenActionTriggered);
|
|
||||||
|
|
||||||
separator4_ = addSeparator();
|
|
||||||
|
|
||||||
propertiesAction_ = new QAction(tr("Folder Pr&operties"), this);
|
|
||||||
addAction(propertiesAction_);
|
|
||||||
connect(propertiesAction_, &QAction::triggered, this, &FolderMenu::onPropertiesActionTriggered);
|
|
||||||
}
|
|
||||||
|
|
||||||
FolderMenu::~FolderMenu() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderMenu::addSortMenuItem(QString title, int id) {
|
|
||||||
QAction* action = new QAction(title, this);
|
|
||||||
sortMenu_->addAction(action);
|
|
||||||
action->setCheckable(true);
|
|
||||||
sortActionGroup_->addAction(action);
|
|
||||||
connect(action, &QAction::triggered, this, &FolderMenu::onSortActionTriggered);
|
|
||||||
sortActions_[id] = action;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderMenu::createSortMenu() {
|
|
||||||
ProxyFolderModel* model = view_->model();
|
|
||||||
|
|
||||||
sortMenu_ = new QMenu(this);
|
|
||||||
sortActionGroup_ = new QActionGroup(sortMenu_);
|
|
||||||
sortActionGroup_->setExclusive(true);
|
|
||||||
|
|
||||||
std::memset(sortActions_, 0, sizeof(sortActions_));
|
|
||||||
|
|
||||||
addSortMenuItem(tr("By File Name"), FolderModel::ColumnFileName);
|
|
||||||
addSortMenuItem(tr("By Modification Time"), FolderModel::ColumnFileMTime);
|
|
||||||
addSortMenuItem(tr("By File Size"), FolderModel::ColumnFileSize);
|
|
||||||
addSortMenuItem(tr("By File Type"), FolderModel::ColumnFileType);
|
|
||||||
addSortMenuItem(tr("By File Owner"), FolderModel::ColumnFileOwner);
|
|
||||||
|
|
||||||
int col = model->sortColumn();
|
|
||||||
|
|
||||||
if(col >= 0 && col < FolderModel::NumOfColumns) {
|
|
||||||
sortActions_[col]->setChecked(true);;
|
|
||||||
}
|
|
||||||
|
|
||||||
sortMenu_->addSeparator();
|
|
||||||
|
|
||||||
QActionGroup* group = new QActionGroup(this);
|
|
||||||
group->setExclusive(true);
|
|
||||||
actionAscending_ = new QAction(tr("Ascending"), this);
|
|
||||||
actionAscending_->setCheckable(true);
|
|
||||||
sortMenu_->addAction(actionAscending_);
|
|
||||||
group->addAction(actionAscending_);
|
|
||||||
|
|
||||||
actionDescending_ = new QAction(tr("Descending"), this);
|
|
||||||
actionDescending_->setCheckable(true);
|
|
||||||
sortMenu_->addAction(actionDescending_);
|
|
||||||
group->addAction(actionDescending_);
|
|
||||||
|
|
||||||
if(model->sortOrder() == Qt::AscendingOrder)
|
|
||||||
actionAscending_->setChecked(true);
|
|
||||||
else
|
|
||||||
actionDescending_->setChecked(true);
|
|
||||||
|
|
||||||
connect(actionAscending_, &QAction::triggered, this, &FolderMenu::onSortOrderActionTriggered);
|
|
||||||
connect(actionDescending_, &QAction::triggered, this, &FolderMenu::onSortOrderActionTriggered);
|
|
||||||
|
|
||||||
sortMenu_->addSeparator();
|
|
||||||
|
|
||||||
QAction* actionFolderFirst = new QAction(tr("Folder First"), this);
|
|
||||||
sortMenu_->addAction(actionFolderFirst);
|
|
||||||
actionFolderFirst->setCheckable(true);
|
|
||||||
|
|
||||||
if(model->folderFirst())
|
|
||||||
actionFolderFirst->setChecked(true);
|
|
||||||
|
|
||||||
connect(actionFolderFirst, &QAction::triggered, this, &FolderMenu::onFolderFirstActionTriggered);
|
|
||||||
|
|
||||||
QAction* actionCaseSensitive = new QAction(tr("Case Sensitive"), this);
|
|
||||||
sortMenu_->addAction(actionCaseSensitive);
|
|
||||||
actionCaseSensitive->setCheckable(true);
|
|
||||||
|
|
||||||
if(model->sortCaseSensitivity() == Qt::CaseSensitive)
|
|
||||||
actionCaseSensitive->setChecked(true);
|
|
||||||
|
|
||||||
connect(actionCaseSensitive, &QAction::triggered, this, &FolderMenu::onCaseSensitiveActionTriggered);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderMenu::onPasteActionTriggered() {
|
|
||||||
FmPath* folderPath = view_->path();
|
|
||||||
|
|
||||||
if(folderPath)
|
|
||||||
pasteFilesFromClipboard(folderPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderMenu::onSelectAllActionTriggered() {
|
|
||||||
view_->selectAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderMenu::onInvertSelectionActionTriggered() {
|
|
||||||
view_->invertSelection();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderMenu::onSortActionTriggered(bool checked) {
|
|
||||||
ProxyFolderModel* model = view_->model();
|
|
||||||
|
|
||||||
if(model) {
|
|
||||||
QAction* action = static_cast<QAction*>(sender());
|
|
||||||
|
|
||||||
for(int col = 0; col < FolderModel::NumOfColumns; ++col) {
|
|
||||||
if(action == sortActions_[col]) {
|
|
||||||
model->sort(col, model->sortOrder());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderMenu::onSortOrderActionTriggered(bool checked) {
|
|
||||||
ProxyFolderModel* model = view_->model();
|
|
||||||
|
|
||||||
if(model) {
|
|
||||||
QAction* action = static_cast<QAction*>(sender());
|
|
||||||
Qt::SortOrder order;
|
|
||||||
|
|
||||||
if(action == actionAscending_)
|
|
||||||
order = Qt::AscendingOrder;
|
|
||||||
else
|
|
||||||
order = Qt::DescendingOrder;
|
|
||||||
|
|
||||||
model->sort(model->sortColumn(), order);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderMenu::onShowHiddenActionTriggered(bool checked) {
|
|
||||||
ProxyFolderModel* model = view_->model();
|
|
||||||
|
|
||||||
if(model) {
|
|
||||||
qDebug("show hidden: %d", checked);
|
|
||||||
model->setShowHidden(checked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderMenu::onCaseSensitiveActionTriggered(bool checked) {
|
|
||||||
ProxyFolderModel* model = view_->model();
|
|
||||||
|
|
||||||
if(model) {
|
|
||||||
model->setSortCaseSensitivity(checked ? Qt::CaseSensitive : Qt::CaseInsensitive);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderMenu::onFolderFirstActionTriggered(bool checked) {
|
|
||||||
ProxyFolderModel* model = view_->model();
|
|
||||||
|
|
||||||
if(model) {
|
|
||||||
model->setFolderFirst(checked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderMenu::onPropertiesActionTriggered() {
|
|
||||||
FmFileInfo* folderInfo = view_->folderInfo();
|
|
||||||
|
|
||||||
if(folderInfo)
|
|
||||||
FilePropsDialog::showForFile(folderInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Fm
|
|
||||||
@ -1,127 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FM_FOLDERMENU_H
|
|
||||||
#define FM_FOLDERMENU_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QMenu>
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
#include "foldermodel.h"
|
|
||||||
|
|
||||||
class QAction;
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class FolderView;
|
|
||||||
|
|
||||||
class LIBFM_QT_API FolderMenu : public QMenu {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit FolderMenu(FolderView* view, QWidget* parent = 0);
|
|
||||||
virtual ~FolderMenu();
|
|
||||||
|
|
||||||
QAction* createAction() {
|
|
||||||
return createAction_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* separator1() {
|
|
||||||
return separator1_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* pasteAction() {
|
|
||||||
return pasteAction_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* separator2() {
|
|
||||||
return separator2_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* selectAllAction() {
|
|
||||||
return selectAllAction_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* invertSelectionAction() {
|
|
||||||
return invertSelectionAction_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* separator3() {
|
|
||||||
return separator3_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* sortAction() {
|
|
||||||
return sortAction_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* showHiddenAction() {
|
|
||||||
return showHiddenAction_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* separator4() {
|
|
||||||
return separator4_;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* propertiesAction() {
|
|
||||||
return propertiesAction_;
|
|
||||||
}
|
|
||||||
|
|
||||||
FolderView* view() {
|
|
||||||
return view_;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Q_SLOTS:
|
|
||||||
void onPasteActionTriggered();
|
|
||||||
void onSelectAllActionTriggered();
|
|
||||||
void onInvertSelectionActionTriggered();
|
|
||||||
void onSortActionTriggered(bool checked);
|
|
||||||
void onSortOrderActionTriggered(bool checked);
|
|
||||||
void onShowHiddenActionTriggered(bool checked);
|
|
||||||
void onCaseSensitiveActionTriggered(bool checked);
|
|
||||||
void onFolderFirstActionTriggered(bool checked);
|
|
||||||
void onPropertiesActionTriggered();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void createSortMenu();
|
|
||||||
void addSortMenuItem(QString title, int id);
|
|
||||||
|
|
||||||
private:
|
|
||||||
FolderView* view_;
|
|
||||||
QAction* createAction_;
|
|
||||||
QAction* separator1_;
|
|
||||||
QAction* pasteAction_;
|
|
||||||
QAction* separator2_;
|
|
||||||
QAction* selectAllAction_;
|
|
||||||
QAction* invertSelectionAction_;
|
|
||||||
QAction* separator3_;
|
|
||||||
QAction* sortAction_;
|
|
||||||
QActionGroup* sortActionGroup_;
|
|
||||||
QMenu* sortMenu_;
|
|
||||||
QAction* sortActions_[FolderModel::NumOfColumns];
|
|
||||||
QAction* actionAscending_;
|
|
||||||
QAction* actionDescending_;
|
|
||||||
QAction* showHiddenAction_;
|
|
||||||
QAction* separator4_;
|
|
||||||
QAction* propertiesAction_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_FOLDERMENU_H
|
|
||||||
@ -1,556 +0,0 @@
|
|||||||
/*
|
|
||||||
<one line to give the library's name and an idea of what it does.>
|
|
||||||
Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "foldermodel.h"
|
|
||||||
#include "icontheme.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include <QtAlgorithms>
|
|
||||||
#include <QVector>
|
|
||||||
#include <qmimedata.h>
|
|
||||||
#include <QMimeData>
|
|
||||||
#include <QByteArray>
|
|
||||||
#include <QPixmap>
|
|
||||||
#include <QPainter>
|
|
||||||
#include "utilities.h"
|
|
||||||
#include "fileoperation.h"
|
|
||||||
#include "thumbnailloader.h"
|
|
||||||
|
|
||||||
using namespace Fm;
|
|
||||||
|
|
||||||
FolderModel::FolderModel() :
|
|
||||||
folder_(NULL) {
|
|
||||||
/*
|
|
||||||
ColumnIcon,
|
|
||||||
ColumnName,
|
|
||||||
ColumnFileType,
|
|
||||||
ColumnMTime,
|
|
||||||
NumOfColumns
|
|
||||||
*/
|
|
||||||
thumbnailRefCounts.reserve(4);
|
|
||||||
|
|
||||||
// reload all icons when the icon theme is changed
|
|
||||||
connect(IconTheme::instance(), &IconTheme::changed, this, &FolderModel::updateIcons);
|
|
||||||
}
|
|
||||||
|
|
||||||
FolderModel::~FolderModel() {
|
|
||||||
qDebug("delete FolderModel");
|
|
||||||
|
|
||||||
if(folder_)
|
|
||||||
setFolder(NULL);
|
|
||||||
|
|
||||||
// if the thumbnail requests list is not empty, cancel them
|
|
||||||
if(!thumbnailResults.empty()) {
|
|
||||||
Q_FOREACH(FmThumbnailLoader* res, thumbnailResults) {
|
|
||||||
ThumbnailLoader::cancel(res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderModel::setFolder(FmFolder* new_folder) {
|
|
||||||
if(folder_) {
|
|
||||||
removeAll(); // remove old items
|
|
||||||
g_signal_handlers_disconnect_by_func(folder_, gpointer(onStartLoading), this);
|
|
||||||
g_signal_handlers_disconnect_by_func(folder_, gpointer(onFinishLoading), this);
|
|
||||||
g_signal_handlers_disconnect_by_func(folder_, gpointer(onFilesAdded), this);
|
|
||||||
g_signal_handlers_disconnect_by_func(folder_, gpointer(onFilesChanged), this);
|
|
||||||
g_signal_handlers_disconnect_by_func(folder_, gpointer(onFilesRemoved), this);
|
|
||||||
g_object_unref(folder_);
|
|
||||||
}
|
|
||||||
if(new_folder) {
|
|
||||||
folder_ = FM_FOLDER(g_object_ref(new_folder));
|
|
||||||
g_signal_connect(folder_, "start-loading", G_CALLBACK(onStartLoading), this);
|
|
||||||
g_signal_connect(folder_, "finish-loading", G_CALLBACK(onFinishLoading), this);
|
|
||||||
g_signal_connect(folder_, "files-added", G_CALLBACK(onFilesAdded), this);
|
|
||||||
g_signal_connect(folder_, "files-changed", G_CALLBACK(onFilesChanged), this);
|
|
||||||
g_signal_connect(folder_, "files-removed", G_CALLBACK(onFilesRemoved), this);
|
|
||||||
// handle the case if the folder is already loaded
|
|
||||||
if(fm_folder_is_loaded(folder_))
|
|
||||||
insertFiles(0, fm_folder_get_files(folder_));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
folder_ = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderModel::onStartLoading(FmFolder* folder, gpointer user_data) {
|
|
||||||
FolderModel* model = static_cast<FolderModel*>(user_data);
|
|
||||||
// remove all items
|
|
||||||
model->removeAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderModel::onFinishLoading(FmFolder* folder, gpointer user_data) {
|
|
||||||
Q_UNUSED(folder)
|
|
||||||
Q_UNUSED(user_data)
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderModel::onFilesAdded(FmFolder* folder, GSList* files, gpointer user_data) {
|
|
||||||
FolderModel* model = static_cast<FolderModel*>(user_data);
|
|
||||||
int n_files = g_slist_length(files);
|
|
||||||
model->beginInsertRows(QModelIndex(), model->items.count(), model->items.count() + n_files - 1);
|
|
||||||
for(GSList* l = files; l; l = l->next) {
|
|
||||||
FmFileInfo* info = FM_FILE_INFO(l->data);
|
|
||||||
FolderModelItem item(info);
|
|
||||||
/*
|
|
||||||
if(fm_file_info_is_hidden(info)) {
|
|
||||||
model->hiddenItems.append(item);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
model->items.append(item);
|
|
||||||
}
|
|
||||||
model->endInsertRows();
|
|
||||||
}
|
|
||||||
|
|
||||||
//static
|
|
||||||
void FolderModel::onFilesChanged(FmFolder* folder, GSList* files, gpointer user_data) {
|
|
||||||
FolderModel* model = static_cast<FolderModel*>(user_data);
|
|
||||||
for(GSList* l = files; l; l = l->next) {
|
|
||||||
FmFileInfo* info = FM_FILE_INFO(l->data);
|
|
||||||
int row;
|
|
||||||
QList<FolderModelItem>::iterator it = model->findItemByFileInfo(info, &row);
|
|
||||||
if(it != model->items.end()) {
|
|
||||||
FolderModelItem& item = *it;
|
|
||||||
// try to update the item
|
|
||||||
item.displayName = QString::fromUtf8(fm_file_info_get_disp_name(info));
|
|
||||||
item.updateIcon();
|
|
||||||
item.thumbnails.clear();
|
|
||||||
QModelIndex index = model->createIndex(row, 0, &item);
|
|
||||||
Q_EMIT model->dataChanged(index, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//static
|
|
||||||
void FolderModel::onFilesRemoved(FmFolder* folder, GSList* files, gpointer user_data) {
|
|
||||||
FolderModel* model = static_cast<FolderModel*>(user_data);
|
|
||||||
for(GSList* l = files; l; l = l->next) {
|
|
||||||
FmFileInfo* info = FM_FILE_INFO(l->data);
|
|
||||||
const char* name = fm_file_info_get_name(info);
|
|
||||||
int row;
|
|
||||||
QList<FolderModelItem>::iterator it = model->findItemByName(name, &row);
|
|
||||||
if(it != model->items.end()) {
|
|
||||||
model->beginRemoveRows(QModelIndex(), row, row);
|
|
||||||
model->items.erase(it);
|
|
||||||
model->endRemoveRows();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderModel::insertFiles(int row, FmFileInfoList* files) {
|
|
||||||
int n_files = fm_file_info_list_get_length(files);
|
|
||||||
beginInsertRows(QModelIndex(), row, row + n_files - 1);
|
|
||||||
for(GList* l = fm_file_info_list_peek_head_link(files); l; l = l->next) {
|
|
||||||
FolderModelItem item(FM_FILE_INFO(l->data));
|
|
||||||
items.append(item);
|
|
||||||
}
|
|
||||||
endInsertRows();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderModel::removeAll() {
|
|
||||||
if(items.empty())
|
|
||||||
return;
|
|
||||||
beginRemoveRows(QModelIndex(), 0, items.size() - 1);
|
|
||||||
items.clear();
|
|
||||||
endRemoveRows();
|
|
||||||
}
|
|
||||||
|
|
||||||
int FolderModel::rowCount(const QModelIndex & parent) const {
|
|
||||||
if(parent.isValid())
|
|
||||||
return 0;
|
|
||||||
return items.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
int FolderModel::columnCount (const QModelIndex & parent = QModelIndex()) const {
|
|
||||||
if(parent.isValid())
|
|
||||||
return 0;
|
|
||||||
return NumOfColumns;
|
|
||||||
}
|
|
||||||
|
|
||||||
FolderModelItem* FolderModel::itemFromIndex(const QModelIndex& index) const {
|
|
||||||
return reinterpret_cast<FolderModelItem*>(index.internalPointer());
|
|
||||||
}
|
|
||||||
|
|
||||||
FmFileInfo* FolderModel::fileInfoFromIndex(const QModelIndex& index) const {
|
|
||||||
FolderModelItem* item = itemFromIndex(index);
|
|
||||||
return item ? item->info : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant FolderModel::data(const QModelIndex & index, int role = Qt::DisplayRole) const {
|
|
||||||
if(!index.isValid() || index.row() > items.size() || index.column() >= NumOfColumns) {
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
FolderModelItem* item = itemFromIndex(index);
|
|
||||||
FmFileInfo* info = item->info;
|
|
||||||
|
|
||||||
switch(role) {
|
|
||||||
case Qt::ToolTipRole:
|
|
||||||
return QVariant(item->displayName);
|
|
||||||
case Qt::DisplayRole: {
|
|
||||||
switch(index.column()) {
|
|
||||||
case ColumnFileName: {
|
|
||||||
return QVariant(item->displayName);
|
|
||||||
}
|
|
||||||
case ColumnFileType: {
|
|
||||||
FmMimeType* mime = fm_file_info_get_mime_type(info);
|
|
||||||
const char* desc = fm_mime_type_get_desc(mime);
|
|
||||||
return QString::fromUtf8(desc);
|
|
||||||
}
|
|
||||||
case ColumnFileMTime: {
|
|
||||||
const char* name = fm_file_info_get_disp_mtime(info);
|
|
||||||
return QString::fromUtf8(name);
|
|
||||||
}
|
|
||||||
case ColumnFileSize: {
|
|
||||||
const char* name = fm_file_info_get_disp_size(info);
|
|
||||||
return QString::fromUtf8(name);
|
|
||||||
}
|
|
||||||
case ColumnFileOwner: {
|
|
||||||
const char* name = fm_file_info_get_disp_owner(info);
|
|
||||||
return QString::fromUtf8(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case Qt::DecorationRole: {
|
|
||||||
if(index.column() == 0) {
|
|
||||||
// QPixmap pix = IconTheme::loadIcon(fm_file_info_get_icon(info), iconSize_);
|
|
||||||
return QVariant(item->icon);
|
|
||||||
// return QVariant(pix);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case FileInfoRole:
|
|
||||||
return qVariantFromValue((void*)info);
|
|
||||||
}
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant FolderModel::headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const {
|
|
||||||
if(role == Qt::DisplayRole) {
|
|
||||||
if(orientation == Qt::Horizontal) {
|
|
||||||
QString title;
|
|
||||||
switch(section) {
|
|
||||||
case ColumnFileName:
|
|
||||||
title = tr("Name");
|
|
||||||
break;
|
|
||||||
case ColumnFileType:
|
|
||||||
title = tr("Type");
|
|
||||||
break;
|
|
||||||
case ColumnFileSize:
|
|
||||||
title = tr("Size");
|
|
||||||
break;
|
|
||||||
case ColumnFileMTime:
|
|
||||||
title = tr("Modified");
|
|
||||||
break;
|
|
||||||
case ColumnFileOwner:
|
|
||||||
title = tr("Owner");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return QVariant(title);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
QModelIndex FolderModel::index(int row, int column, const QModelIndex & parent) const {
|
|
||||||
if(row <0 || row >= items.size() || column < 0 || column >= NumOfColumns)
|
|
||||||
return QModelIndex();
|
|
||||||
const FolderModelItem& item = items.at(row);
|
|
||||||
return createIndex(row, column, (void*)&item);
|
|
||||||
}
|
|
||||||
|
|
||||||
QModelIndex FolderModel::parent(const QModelIndex & index) const {
|
|
||||||
return QModelIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
Qt::ItemFlags FolderModel::flags(const QModelIndex& index) const {
|
|
||||||
// FIXME: should not return same flags unconditionally for all columns
|
|
||||||
Qt::ItemFlags flags;
|
|
||||||
if(index.isValid()) {
|
|
||||||
flags = Qt::ItemIsEnabled|Qt::ItemIsSelectable;
|
|
||||||
if(index.column() == ColumnFileName)
|
|
||||||
flags |= (Qt::ItemIsDragEnabled|Qt::ItemIsDropEnabled);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
flags = Qt::ItemIsDropEnabled;
|
|
||||||
}
|
|
||||||
return flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: this is very inefficient and should be replaced with a
|
|
||||||
// more reasonable implementation later.
|
|
||||||
QList<FolderModelItem>::iterator FolderModel::findItemByPath(FmPath* path, int* row) {
|
|
||||||
QList<FolderModelItem>::iterator it = items.begin();
|
|
||||||
int i = 0;
|
|
||||||
while(it != items.end()) {
|
|
||||||
FolderModelItem& item = *it;
|
|
||||||
FmPath* item_path = fm_file_info_get_path(item.info);
|
|
||||||
if(fm_path_equal(item_path, path)) {
|
|
||||||
*row = i;
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
++it;
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
return items.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: this is very inefficient and should be replaced with a
|
|
||||||
// more reasonable implementation later.
|
|
||||||
QList<FolderModelItem>::iterator FolderModel::findItemByName(const char* name, int* row) {
|
|
||||||
QList<FolderModelItem>::iterator it = items.begin();
|
|
||||||
int i = 0;
|
|
||||||
while(it != items.end()) {
|
|
||||||
FolderModelItem& item = *it;
|
|
||||||
const char* item_name = fm_file_info_get_name(item.info);
|
|
||||||
if(strcmp(name, item_name) == 0) {
|
|
||||||
*row = i;
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
++it;
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
return items.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
QList< FolderModelItem >::iterator FolderModel::findItemByFileInfo(FmFileInfo* info, int* row) {
|
|
||||||
QList<FolderModelItem>::iterator it = items.begin();
|
|
||||||
int i = 0;
|
|
||||||
while(it != items.end()) {
|
|
||||||
FolderModelItem& item = *it;
|
|
||||||
if(item.info == info) {
|
|
||||||
*row = i;
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
++it;
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
return items.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList FolderModel::mimeTypes() const {
|
|
||||||
qDebug("FolderModel::mimeTypes");
|
|
||||||
QStringList types = QAbstractItemModel::mimeTypes();
|
|
||||||
// now types contains "application/x-qabstractitemmodeldatalist"
|
|
||||||
types << "text/uri-list";
|
|
||||||
// types << "x-special/gnome-copied-files";
|
|
||||||
return types;
|
|
||||||
}
|
|
||||||
|
|
||||||
QMimeData* FolderModel::mimeData(const QModelIndexList& indexes) const {
|
|
||||||
QMimeData* data = QAbstractItemModel::mimeData(indexes);
|
|
||||||
qDebug("FolderModel::mimeData");
|
|
||||||
// build a uri list
|
|
||||||
QByteArray urilist;
|
|
||||||
urilist.reserve(4096);
|
|
||||||
|
|
||||||
QModelIndexList::const_iterator it;
|
|
||||||
for(it = indexes.constBegin(); it != indexes.end(); ++it) {
|
|
||||||
const QModelIndex index = *it;
|
|
||||||
FolderModelItem* item = itemFromIndex(index);
|
|
||||||
if(item) {
|
|
||||||
FmPath* path = fm_file_info_get_path(item->info);
|
|
||||||
char* uri = fm_path_to_uri(path);
|
|
||||||
urilist.append(uri);
|
|
||||||
urilist.append('\n');
|
|
||||||
g_free(uri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data->setData("text/uri-list", urilist);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FolderModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) {
|
|
||||||
qDebug("FolderModel::dropMimeData");
|
|
||||||
if(!folder_)
|
|
||||||
return false;
|
|
||||||
FmPath* destPath;
|
|
||||||
if(parent.isValid()) { // drop on an item
|
|
||||||
FmFileInfo* info;
|
|
||||||
if(row == -1 && column == -1)
|
|
||||||
info = fileInfoFromIndex(parent);
|
|
||||||
else {
|
|
||||||
QModelIndex itemIndex = parent.child(row, column);
|
|
||||||
info = fileInfoFromIndex(itemIndex);
|
|
||||||
}
|
|
||||||
if(info)
|
|
||||||
destPath = fm_file_info_get_path(info);
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else { // drop on blank area of the folder
|
|
||||||
destPath = path();
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: should we put this in dropEvent handler of FolderView instead?
|
|
||||||
if(data->hasUrls()) {
|
|
||||||
qDebug("drop action: %d", action);
|
|
||||||
FmPathList* srcPaths = pathListFromQUrls(data->urls());
|
|
||||||
switch(action) {
|
|
||||||
case Qt::CopyAction:
|
|
||||||
FileOperation::copyFiles(srcPaths, destPath);
|
|
||||||
break;
|
|
||||||
case Qt::MoveAction:
|
|
||||||
FileOperation::moveFiles(srcPaths, destPath);
|
|
||||||
break;
|
|
||||||
case Qt::LinkAction:
|
|
||||||
FileOperation::symlinkFiles(srcPaths, destPath);
|
|
||||||
default:
|
|
||||||
fm_path_list_unref(srcPaths);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
fm_path_list_unref(srcPaths);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if(data->hasFormat("application/x-qabstractitemmodeldatalist")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return QAbstractListModel::dropMimeData(data, action, row, column, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
Qt::DropActions FolderModel::supportedDropActions() const {
|
|
||||||
qDebug("FolderModel::supportedDropActions");
|
|
||||||
return Qt::CopyAction|Qt::MoveAction|Qt::LinkAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ask the model to load thumbnails of the specified size
|
|
||||||
void FolderModel::cacheThumbnails(int size) {
|
|
||||||
QVector<QPair<int, int> >::iterator it;
|
|
||||||
for(it = thumbnailRefCounts.begin(); it != thumbnailRefCounts.end(); ++it) {
|
|
||||||
if(it->first == size) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(it != thumbnailRefCounts.end())
|
|
||||||
++it->second;
|
|
||||||
else
|
|
||||||
thumbnailRefCounts.append(QPair<int, int>(size, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ask the model to free cached thumbnails of the specified size
|
|
||||||
void FolderModel::releaseThumbnails(int size) {
|
|
||||||
QVector<QPair<int, int> >::iterator it;
|
|
||||||
for(it = thumbnailRefCounts.begin(); it != thumbnailRefCounts.end(); ++it) {
|
|
||||||
if(it->first == size) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(it != thumbnailRefCounts.end()) {
|
|
||||||
--it->second;
|
|
||||||
if(it->second == 0) {
|
|
||||||
thumbnailRefCounts.erase(it);
|
|
||||||
|
|
||||||
// remove thumbnails that ara queued for loading from thumbnailResults
|
|
||||||
QLinkedList<FmThumbnailLoader*>::iterator it;
|
|
||||||
for(it = thumbnailResults.begin(); it != thumbnailResults.end();) {
|
|
||||||
QLinkedList<FmThumbnailLoader*>::iterator next = it + 1;
|
|
||||||
FmThumbnailLoader* res = *it;
|
|
||||||
if(ThumbnailLoader::size(res) == size) {
|
|
||||||
ThumbnailLoader::cancel(res);
|
|
||||||
thumbnailResults.erase(it);
|
|
||||||
}
|
|
||||||
it = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove all cached thumbnails of the specified size
|
|
||||||
QList<FolderModelItem>::iterator itemIt;
|
|
||||||
for(itemIt = items.begin(); itemIt != items.end(); ++itemIt) {
|
|
||||||
FolderModelItem& item = *itemIt;
|
|
||||||
item.removeThumbnail(size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderModel::onThumbnailLoaded(FmThumbnailLoader* res, gpointer user_data) {
|
|
||||||
FolderModel* pThis = reinterpret_cast<FolderModel*>(user_data);
|
|
||||||
QLinkedList<FmThumbnailLoader*>::iterator it;
|
|
||||||
for(it = pThis->thumbnailResults.begin(); it != pThis->thumbnailResults.end(); ++it) {
|
|
||||||
if(*it == res) { // the thumbnail result is in our list
|
|
||||||
pThis->thumbnailResults.erase(it); // remove it from the list
|
|
||||||
FmFileInfo* info = ThumbnailLoader::fileInfo(res);
|
|
||||||
int row = -1;
|
|
||||||
// find the model item this thumbnail belongs to
|
|
||||||
QList<FolderModelItem>::iterator it = pThis->findItemByFileInfo(info, &row);
|
|
||||||
if(it != pThis->items.end()) {
|
|
||||||
// the file is found in our model
|
|
||||||
FolderModelItem& item = *it;
|
|
||||||
QModelIndex index = pThis->createIndex(row, 0, (void*)&item);
|
|
||||||
// store the image in the folder model item.
|
|
||||||
int size = ThumbnailLoader::size(res);
|
|
||||||
QImage image = ThumbnailLoader::image(res);
|
|
||||||
FolderModelItem::Thumbnail* thumbnail = item.findThumbnail(size);
|
|
||||||
thumbnail->image = image;
|
|
||||||
// qDebug("thumbnail loaded for: %s, size: %d", item.displayName.toUtf8().constData(), size);
|
|
||||||
if(image.isNull())
|
|
||||||
thumbnail->status = FolderModelItem::ThumbnailFailed;
|
|
||||||
else {
|
|
||||||
thumbnail->status = FolderModelItem::ThumbnailLoaded;
|
|
||||||
// FIXME: due to bugs in Qt's QStyledItemDelegate, if the image width and height
|
|
||||||
// are not the same, painting errors will happen. It's quite unfortunate.
|
|
||||||
// Let's do some padding to make its width and height equals.
|
|
||||||
// This greatly decrease performance :-(
|
|
||||||
// Later if we can re-implement our own item delegate, this can be avoided.
|
|
||||||
QPixmap pixmap = QPixmap(size, size);
|
|
||||||
pixmap.fill(QColor(0, 0, 0, 0)); // fill the pixmap with transparent color (alpha:0)
|
|
||||||
QPainter painter(&pixmap);
|
|
||||||
int x = (size - image.width()) / 2;
|
|
||||||
int y = (size - image.height()) / 2;
|
|
||||||
painter.drawImage(QPoint(x, y), image); // draw the image to the pixmap at center.
|
|
||||||
// FIXME: should we cache QPixmap instead for performance reason?
|
|
||||||
thumbnail->image = pixmap.toImage(); // convert it back to image
|
|
||||||
|
|
||||||
// tell the world that we have the thumbnail loaded
|
|
||||||
Q_EMIT pThis->thumbnailLoaded(index, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get a thumbnail of size at the index
|
|
||||||
// if a thumbnail is not yet loaded, this will initiate loading of the thumbnail.
|
|
||||||
QImage FolderModel::thumbnailFromIndex(const QModelIndex& index, int size) {
|
|
||||||
FolderModelItem* item = itemFromIndex(index);
|
|
||||||
if(item) {
|
|
||||||
FolderModelItem::Thumbnail* thumbnail = item->findThumbnail(size);
|
|
||||||
// qDebug("FolderModel::thumbnailFromIndex: %d, %s", thumbnail->status, item->displayName.toUtf8().data());
|
|
||||||
switch(thumbnail->status) {
|
|
||||||
case FolderModelItem::ThumbnailNotChecked: {
|
|
||||||
// load the thumbnail
|
|
||||||
FmThumbnailLoader* res = ThumbnailLoader::load(item->info, size, onThumbnailLoaded, this);
|
|
||||||
thumbnailResults.push_back(res);
|
|
||||||
thumbnail->status = FolderModelItem::ThumbnailLoading;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case FolderModelItem::ThumbnailLoaded:
|
|
||||||
return thumbnail->image;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QImage();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderModel::updateIcons() {
|
|
||||||
QList<FolderModelItem>::iterator it = items.begin();
|
|
||||||
for(;it != items.end(); ++it) {
|
|
||||||
(*it).updateIcon();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,121 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FM_FOLDERMODEL_H
|
|
||||||
#define FM_FOLDERMODEL_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QAbstractListModel>
|
|
||||||
#include <QIcon>
|
|
||||||
#include <QImage>
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
#include <QList>
|
|
||||||
#include <QVector>
|
|
||||||
#include <QLinkedList>
|
|
||||||
#include <QPair>
|
|
||||||
#include "foldermodelitem.h"
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class LIBFM_QT_API FolderModel : public QAbstractListModel {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum Role {
|
|
||||||
FileInfoRole = Qt::UserRole
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ColumnId {
|
|
||||||
ColumnFileName,
|
|
||||||
ColumnFileType,
|
|
||||||
ColumnFileSize,
|
|
||||||
ColumnFileMTime,
|
|
||||||
ColumnFileOwner,
|
|
||||||
NumOfColumns
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
FolderModel();
|
|
||||||
virtual ~FolderModel();
|
|
||||||
|
|
||||||
FmFolder* folder() {
|
|
||||||
return folder_;
|
|
||||||
}
|
|
||||||
void setFolder(FmFolder* new_folder);
|
|
||||||
|
|
||||||
FmPath* path() {
|
|
||||||
return folder_ ? fm_folder_get_path(folder_) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rowCount(const QModelIndex & parent = QModelIndex()) const;
|
|
||||||
int columnCount (const QModelIndex & parent) const;
|
|
||||||
QVariant data(const QModelIndex & index, int role) const;
|
|
||||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
|
||||||
QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const;
|
|
||||||
QModelIndex parent( const QModelIndex & index ) const;
|
|
||||||
// void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
|
|
||||||
|
|
||||||
Qt::ItemFlags flags(const QModelIndex & index) const;
|
|
||||||
|
|
||||||
virtual QStringList mimeTypes() const;
|
|
||||||
virtual QMimeData* mimeData(const QModelIndexList & indexes) const;
|
|
||||||
virtual Qt::DropActions supportedDropActions() const;
|
|
||||||
virtual bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent);
|
|
||||||
|
|
||||||
FmFileInfo* fileInfoFromIndex(const QModelIndex& index) const;
|
|
||||||
FolderModelItem* itemFromIndex(const QModelIndex& index) const;
|
|
||||||
QImage thumbnailFromIndex(const QModelIndex& index, int size);
|
|
||||||
|
|
||||||
void cacheThumbnails(int size);
|
|
||||||
void releaseThumbnails(int size);
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void thumbnailLoaded(const QModelIndex& index, int size);
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
|
||||||
void updateIcons();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static void onStartLoading(FmFolder* folder, gpointer user_data);
|
|
||||||
static void onFinishLoading(FmFolder* folder, gpointer user_data);
|
|
||||||
static void onFilesAdded(FmFolder* folder, GSList* files, gpointer user_data);
|
|
||||||
static void onFilesChanged(FmFolder* folder, GSList* files, gpointer user_data);
|
|
||||||
static void onFilesRemoved(FmFolder* folder, GSList* files, gpointer user_data);
|
|
||||||
static void onThumbnailLoaded(FmThumbnailLoader *res, gpointer user_data);
|
|
||||||
|
|
||||||
void insertFiles(int row, FmFileInfoList* files);
|
|
||||||
void removeAll();
|
|
||||||
QList<FolderModelItem>::iterator findItemByPath(FmPath* path, int* row);
|
|
||||||
QList<FolderModelItem>::iterator findItemByName(const char* name, int* row);
|
|
||||||
QList<FolderModelItem>::iterator findItemByFileInfo(FmFileInfo* info, int* row);
|
|
||||||
|
|
||||||
private:
|
|
||||||
FmFolder* folder_;
|
|
||||||
// FIXME: should we use a hash table here so item lookup becomes much faster?
|
|
||||||
QList<FolderModelItem> items;
|
|
||||||
|
|
||||||
// record what size of thumbnails we should cache in an array of <size, refCount> pairs.
|
|
||||||
QVector<QPair<int, int> > thumbnailRefCounts;
|
|
||||||
QLinkedList<FmThumbnailLoader*> thumbnailResults;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_FOLDERMODEL_H
|
|
||||||
@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "foldermodelitem.h"
|
|
||||||
|
|
||||||
using namespace Fm;
|
|
||||||
|
|
||||||
FolderModelItem::FolderModelItem(FmFileInfo* _info):
|
|
||||||
info(fm_file_info_ref(_info)) {
|
|
||||||
displayName = QString::fromUtf8(fm_file_info_get_disp_name(info));
|
|
||||||
icon = IconTheme::icon(fm_file_info_get_icon(_info));
|
|
||||||
thumbnails.reserve(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
FolderModelItem::FolderModelItem(const FolderModelItem& other) {
|
|
||||||
info = other.info ? fm_file_info_ref(other.info) : NULL;
|
|
||||||
displayName = QString::fromUtf8(fm_file_info_get_disp_name(info));
|
|
||||||
icon = other.icon;
|
|
||||||
thumbnails = other.thumbnails;
|
|
||||||
}
|
|
||||||
|
|
||||||
FolderModelItem::~FolderModelItem() {
|
|
||||||
if(info)
|
|
||||||
fm_file_info_unref(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
// find thumbnail of the specified size
|
|
||||||
// The returned thumbnail item is temporary and short-lived
|
|
||||||
// If you need to use the struct later, copy it to your own struct to keep it.
|
|
||||||
FolderModelItem::Thumbnail* FolderModelItem::findThumbnail(int size) {
|
|
||||||
QVector<Thumbnail>::iterator it;
|
|
||||||
for(it = thumbnails.begin(); it != thumbnails.end(); ++it) {
|
|
||||||
if(it->size == size) { // an image of the same size is found
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(it == thumbnails.end()) {
|
|
||||||
Thumbnail thumbnail;
|
|
||||||
thumbnail.status = ThumbnailNotChecked;
|
|
||||||
thumbnail.size = size;
|
|
||||||
thumbnails.append(thumbnail);
|
|
||||||
}
|
|
||||||
return &thumbnails.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove cached thumbnail of the specified size
|
|
||||||
void FolderModelItem::removeThumbnail(int size) {
|
|
||||||
QVector<Thumbnail>::iterator it;
|
|
||||||
for(it = thumbnails.begin(); it != thumbnails.end(); ++it) {
|
|
||||||
if(it->size == size) { // an image of the same size is found
|
|
||||||
thumbnails.erase(it);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// cache the thumbnail of the specified size in the folder item
|
|
||||||
void FolderModelItem::setThumbnail(int size, QImage image) {
|
|
||||||
QVector<Thumbnail>::iterator it;
|
|
||||||
for(it = thumbnails.begin(); it != thumbnails.end(); ++it) {
|
|
||||||
if(it->size == size) { // an image of the same size already exists
|
|
||||||
it->image = image; // replace it
|
|
||||||
it->status = ThumbnailLoaded;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(it == thumbnails.end()) { // the image is not found
|
|
||||||
Thumbnail thumbnail;
|
|
||||||
thumbnail.size = size;
|
|
||||||
thumbnail.status = ThumbnailLoaded;
|
|
||||||
thumbnail.image = image;
|
|
||||||
thumbnails.append(thumbnail); // add a new entry
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FM_FOLDERMODELITEM_H
|
|
||||||
#define FM_FOLDERMODELITEM_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
#include <QImage>
|
|
||||||
#include <QString>
|
|
||||||
#include <QIcon>
|
|
||||||
#include <QVector>
|
|
||||||
#include "icontheme.h"
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class LIBFM_QT_API FolderModelItem {
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum ThumbnailStatus {
|
|
||||||
ThumbnailNotChecked,
|
|
||||||
ThumbnailLoading,
|
|
||||||
ThumbnailLoaded,
|
|
||||||
ThumbnailFailed
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Thumbnail {
|
|
||||||
int size;
|
|
||||||
ThumbnailStatus status;
|
|
||||||
QImage image;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
FolderModelItem(FmFileInfo* _info);
|
|
||||||
FolderModelItem(const FolderModelItem& other);
|
|
||||||
virtual ~FolderModelItem();
|
|
||||||
|
|
||||||
Thumbnail* findThumbnail(int size);
|
|
||||||
// void setThumbnail(int size, QImage image);
|
|
||||||
void removeThumbnail(int size);
|
|
||||||
|
|
||||||
void updateIcon() {
|
|
||||||
icon = IconTheme::icon(fm_file_info_get_icon(info));
|
|
||||||
}
|
|
||||||
|
|
||||||
QString displayName;
|
|
||||||
QIcon icon;
|
|
||||||
FmFileInfo* info;
|
|
||||||
QVector<Thumbnail> thumbnails;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_FOLDERMODELITEM_H
|
|
||||||
@ -1,956 +0,0 @@
|
|||||||
/*
|
|
||||||
<one line to give the library's name and an idea of what it does.>
|
|
||||||
Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "folderview.h"
|
|
||||||
#include "foldermodel.h"
|
|
||||||
#include <QHeaderView>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QContextMenuEvent>
|
|
||||||
#include "proxyfoldermodel.h"
|
|
||||||
#include "folderitemdelegate.h"
|
|
||||||
#include "dndactionmenu.h"
|
|
||||||
#include "filemenu.h"
|
|
||||||
#include "foldermenu.h"
|
|
||||||
#include "filelauncher.h"
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QDate>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QMimeData>
|
|
||||||
#include <QHoverEvent>
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QScrollBar>
|
|
||||||
#include <QMetaType>
|
|
||||||
#include "folderview_p.h"
|
|
||||||
|
|
||||||
Q_DECLARE_OPAQUE_POINTER(FmFileInfo*)
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
FolderViewListView::FolderViewListView(QWidget* parent):
|
|
||||||
QListView(parent),
|
|
||||||
activationAllowed_(true) {
|
|
||||||
connect(this, &QListView::activated, this, &FolderViewListView::activation);
|
|
||||||
}
|
|
||||||
|
|
||||||
FolderViewListView::~FolderViewListView() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewListView::startDrag(Qt::DropActions supportedActions) {
|
|
||||||
if(movement() != Static)
|
|
||||||
QListView::startDrag(supportedActions);
|
|
||||||
else
|
|
||||||
QAbstractItemView::startDrag(supportedActions);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewListView::mousePressEvent(QMouseEvent* event) {
|
|
||||||
QListView::mousePressEvent(event);
|
|
||||||
static_cast<FolderView*>(parent())->childMousePressEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
QModelIndex FolderViewListView::indexAt(const QPoint& point) const {
|
|
||||||
QModelIndex index = QListView::indexAt(point);
|
|
||||||
// NOTE: QListView has a severe design flaw here. It does hit-testing based on the
|
|
||||||
// total bound rect of the item. The width of an item is determined by max(icon_width, text_width).
|
|
||||||
// So if the text label is much wider than the icon, when you click outside the icon but
|
|
||||||
// the point is still within the outer bound rect, the item is still selected.
|
|
||||||
// This results in very poor usability. Let's do precise hit-testing here.
|
|
||||||
// An item is hit only when the point is in the icon or text label.
|
|
||||||
// If the point is in the bound rectangle but outside the icon or text, it should not be selected.
|
|
||||||
if(viewMode() == QListView::IconMode && index.isValid()) {
|
|
||||||
// FIXME: this hack only improves the usability partially. We still need more precise sizeHint handling.
|
|
||||||
// FolderItemDelegate* delegate = static_cast<FolderItemDelegate*>(itemDelegateForColumn(FolderModel::ColumnFileName));
|
|
||||||
// Q_ASSERT(delegate != NULL);
|
|
||||||
// We use the grid size - (2, 2) as the size of the bounding rectangle of the whole item.
|
|
||||||
// The width of the text label hence is gridSize.width - 2, and the width and height of the icon is from iconSize().
|
|
||||||
QRect visRect = visualRect(index); // visibal area on the screen
|
|
||||||
QSize itemSize = gridSize();
|
|
||||||
itemSize.setWidth(itemSize.width() - 2);
|
|
||||||
itemSize.setHeight(itemSize.height() - 2);
|
|
||||||
QSize _iconSize = iconSize();
|
|
||||||
int textHeight = itemSize.height() - _iconSize.height();
|
|
||||||
if(point.y() < visRect.bottom() - textHeight) {
|
|
||||||
// the point is in the icon area, not over the text label
|
|
||||||
int iconXMargin = (itemSize.width() - _iconSize.width()) / 2;
|
|
||||||
if(point.x() < (visRect.left() + iconXMargin) || point.x() > (visRect.right() - iconXMargin))
|
|
||||||
return QModelIndex();
|
|
||||||
}
|
|
||||||
// qDebug() << "visualRect: " << visRect << "point:" << point;
|
|
||||||
}
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// NOTE:
|
|
||||||
// QListView has a problem which I consider a bug or a design flaw.
|
|
||||||
// When you set movement property to Static, theoratically the icons
|
|
||||||
// should not be movable. However, if you turned on icon mode,
|
|
||||||
// the icons becomes freely movable despite the value of movement is Static.
|
|
||||||
// To overcome this bug, we override all drag handling methods, and
|
|
||||||
// call QAbstractItemView directly, bypassing QListView.
|
|
||||||
// In this way, we can workaround the buggy behavior.
|
|
||||||
// The drag handlers of QListView basically does the same things
|
|
||||||
// as its parent QAbstractItemView, but it also stores the currently
|
|
||||||
// dragged item and paint them in the view as needed.
|
|
||||||
// TODO: I really should file a bug report to Qt developers.
|
|
||||||
|
|
||||||
void FolderViewListView::dragEnterEvent(QDragEnterEvent* event) {
|
|
||||||
if(movement() != Static)
|
|
||||||
QListView::dragEnterEvent(event);
|
|
||||||
else
|
|
||||||
QAbstractItemView::dragEnterEvent(event);
|
|
||||||
qDebug("dragEnterEvent");
|
|
||||||
//static_cast<FolderView*>(parent())->childDragEnterEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewListView::dragLeaveEvent(QDragLeaveEvent* e) {
|
|
||||||
if(movement() != Static)
|
|
||||||
QListView::dragLeaveEvent(e);
|
|
||||||
else
|
|
||||||
QAbstractItemView::dragLeaveEvent(e);
|
|
||||||
static_cast<FolderView*>(parent())->childDragLeaveEvent(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewListView::dragMoveEvent(QDragMoveEvent* e) {
|
|
||||||
if(movement() != Static)
|
|
||||||
QListView::dragMoveEvent(e);
|
|
||||||
else
|
|
||||||
QAbstractItemView::dragMoveEvent(e);
|
|
||||||
static_cast<FolderView*>(parent())->childDragMoveEvent(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewListView::dropEvent(QDropEvent* e) {
|
|
||||||
|
|
||||||
static_cast<FolderView*>(parent())->childDropEvent(e);
|
|
||||||
|
|
||||||
if(movement() != Static)
|
|
||||||
QListView::dropEvent(e);
|
|
||||||
else
|
|
||||||
QAbstractItemView::dropEvent(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewListView::mouseReleaseEvent(QMouseEvent* event) {
|
|
||||||
bool activationWasAllowed = activationAllowed_;
|
|
||||||
if ((!style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, NULL, this)) || (event->button() != Qt::LeftButton)) {
|
|
||||||
activationAllowed_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QListView::mouseReleaseEvent(event);
|
|
||||||
|
|
||||||
activationAllowed_ = activationWasAllowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewListView::mouseDoubleClickEvent(QMouseEvent* event) {
|
|
||||||
bool activationWasAllowed = activationAllowed_;
|
|
||||||
if ((style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, NULL, this)) || (event->button() != Qt::LeftButton)) {
|
|
||||||
activationAllowed_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QListView::mouseDoubleClickEvent(event);
|
|
||||||
|
|
||||||
activationAllowed_ = activationWasAllowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewListView::activation(const QModelIndex &index) {
|
|
||||||
if (activationAllowed_) {
|
|
||||||
Q_EMIT activatedFiltered(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
FolderViewTreeView::FolderViewTreeView(QWidget* parent):
|
|
||||||
QTreeView(parent),
|
|
||||||
layoutTimer_(NULL),
|
|
||||||
doingLayout_(false),
|
|
||||||
activationAllowed_(true) {
|
|
||||||
|
|
||||||
header()->setStretchLastSection(false);
|
|
||||||
setIndentation(0);
|
|
||||||
|
|
||||||
connect(this, &QTreeView::activated, this, &FolderViewTreeView::activation);
|
|
||||||
}
|
|
||||||
|
|
||||||
FolderViewTreeView::~FolderViewTreeView() {
|
|
||||||
if(layoutTimer_)
|
|
||||||
delete layoutTimer_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewTreeView::setModel(QAbstractItemModel* model) {
|
|
||||||
QTreeView::setModel(model);
|
|
||||||
layoutColumns();
|
|
||||||
if(ProxyFolderModel* proxyModel = qobject_cast<ProxyFolderModel*>(model)) {
|
|
||||||
connect(proxyModel, &ProxyFolderModel::sortFilterChanged, this, &FolderViewTreeView::onSortFilterChanged,
|
|
||||||
Qt::UniqueConnection);
|
|
||||||
onSortFilterChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewTreeView::mousePressEvent(QMouseEvent* event) {
|
|
||||||
QTreeView::mousePressEvent(event);
|
|
||||||
static_cast<FolderView*>(parent())->childMousePressEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewTreeView::dragEnterEvent(QDragEnterEvent* event) {
|
|
||||||
QTreeView::dragEnterEvent(event);
|
|
||||||
static_cast<FolderView*>(parent())->childDragEnterEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewTreeView::dragLeaveEvent(QDragLeaveEvent* e) {
|
|
||||||
QTreeView::dragLeaveEvent(e);
|
|
||||||
static_cast<FolderView*>(parent())->childDragLeaveEvent(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewTreeView::dragMoveEvent(QDragMoveEvent* e) {
|
|
||||||
QTreeView::dragMoveEvent(e);
|
|
||||||
static_cast<FolderView*>(parent())->childDragMoveEvent(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewTreeView::dropEvent(QDropEvent* e) {
|
|
||||||
static_cast<FolderView*>(parent())->childDropEvent(e);
|
|
||||||
QTreeView::dropEvent(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// the default list mode of QListView handles column widths
|
|
||||||
// very badly (worse than gtk+) and it's not very flexible.
|
|
||||||
// so, let's handle column widths outselves.
|
|
||||||
void FolderViewTreeView::layoutColumns() {
|
|
||||||
// qDebug("layoutColumns");
|
|
||||||
if(!model())
|
|
||||||
return;
|
|
||||||
doingLayout_ = true;
|
|
||||||
QHeaderView* headerView = header();
|
|
||||||
// the width that's available for showing the columns.
|
|
||||||
int availWidth = viewport()->contentsRect().width();
|
|
||||||
int desiredWidth = 0;
|
|
||||||
|
|
||||||
// get the width that every column want
|
|
||||||
int numCols = headerView->count();
|
|
||||||
int* widths = new int[numCols]; // array to store the widths every column needs
|
|
||||||
int column;
|
|
||||||
for(column = 0; column < numCols; ++column) {
|
|
||||||
int columnId = headerView->logicalIndex(column);
|
|
||||||
// get the size that the column needs
|
|
||||||
widths[column] = sizeHintForColumn(columnId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// the best case is every column can get its full width
|
|
||||||
for(column = 0; column < numCols; ++column) {
|
|
||||||
desiredWidth += widths[column];
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the total witdh we want exceeds the available space
|
|
||||||
if(desiredWidth > availWidth) {
|
|
||||||
// we don't have that much space for every column
|
|
||||||
int filenameColumn = headerView->visualIndex(FolderModel::ColumnFileName);
|
|
||||||
// shrink the filename column first
|
|
||||||
desiredWidth -= widths[filenameColumn]; // total width of all other columns
|
|
||||||
|
|
||||||
// see if setting the width of the filename column to 200 solve the problem
|
|
||||||
if(desiredWidth + 200 > availWidth) {
|
|
||||||
// even when we reduce the width of the filename column to 200,
|
|
||||||
// the available space is not enough. So we give up trying.
|
|
||||||
widths[filenameColumn] = 200;
|
|
||||||
}
|
|
||||||
else { // we still have more space, so the width of filename column can be increased
|
|
||||||
// expand the filename column to fill all available space.
|
|
||||||
widths[filenameColumn] = availWidth - desiredWidth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// really do the resizing for every column
|
|
||||||
for(int column = 0; column < numCols; ++column) {
|
|
||||||
headerView->resizeSection(column, widths[column]);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete []widths;
|
|
||||||
doingLayout_ = false;
|
|
||||||
|
|
||||||
if(layoutTimer_) {
|
|
||||||
delete layoutTimer_;
|
|
||||||
layoutTimer_ = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewTreeView::resizeEvent(QResizeEvent* event) {
|
|
||||||
QAbstractItemView::resizeEvent(event);
|
|
||||||
// prevent endless recursion.
|
|
||||||
// When manually resizing columns, at the point where a horizontal scroll
|
|
||||||
// bar has to be inserted or removed, the vertical size changes, a resize
|
|
||||||
// event occurs and the column headers are flickering badly if the column
|
|
||||||
// layout is modified at this point. Therefore only layout the columns if
|
|
||||||
// the horizontal size changes.
|
|
||||||
if(!doingLayout_ && event->size().width() != event->oldSize().width())
|
|
||||||
layoutColumns(); // layoutColumns() also triggers resizeEvent
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewTreeView::rowsInserted(const QModelIndex& parent, int start, int end) {
|
|
||||||
QTreeView::rowsInserted(parent, start, end);
|
|
||||||
queueLayoutColumns();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewTreeView::rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end) {
|
|
||||||
QTreeView::rowsAboutToBeRemoved(parent, start, end);
|
|
||||||
queueLayoutColumns();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewTreeView::dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight) {
|
|
||||||
QTreeView::dataChanged(topLeft, bottomRight);
|
|
||||||
// FIXME: this will be very inefficient
|
|
||||||
// queueLayoutColumns();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewTreeView::reset() {
|
|
||||||
// Sometimes when the content of the model is radically changed, Qt does reset()
|
|
||||||
// on the model rather than doing large amount of insertion and deletion.
|
|
||||||
// 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.
|
|
||||||
// This fixes bug #190
|
|
||||||
// https://github.com/lxde/pcmanfm-qt/issues/190
|
|
||||||
QTreeView::reset();
|
|
||||||
queueLayoutColumns();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewTreeView::queueLayoutColumns() {
|
|
||||||
// qDebug("queueLayoutColumns");
|
|
||||||
if(!layoutTimer_) {
|
|
||||||
layoutTimer_ = new QTimer();
|
|
||||||
layoutTimer_->setSingleShot(true);
|
|
||||||
layoutTimer_->setInterval(0);
|
|
||||||
connect(layoutTimer_, &QTimer::timeout, this, &FolderViewTreeView::layoutColumns);
|
|
||||||
}
|
|
||||||
layoutTimer_->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewTreeView::mouseReleaseEvent(QMouseEvent* event) {
|
|
||||||
bool activationWasAllowed = activationAllowed_;
|
|
||||||
if ((!style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, NULL, this)) || (event->button() != Qt::LeftButton)) {
|
|
||||||
activationAllowed_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QTreeView::mouseReleaseEvent(event);
|
|
||||||
|
|
||||||
activationAllowed_ = activationWasAllowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewTreeView::mouseDoubleClickEvent(QMouseEvent* event) {
|
|
||||||
bool activationWasAllowed = activationAllowed_;
|
|
||||||
if ((style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, NULL, this)) || (event->button() != Qt::LeftButton)) {
|
|
||||||
activationAllowed_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QTreeView::mouseDoubleClickEvent(event);
|
|
||||||
|
|
||||||
activationAllowed_ = activationWasAllowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewTreeView::activation(const QModelIndex &index) {
|
|
||||||
if (activationAllowed_) {
|
|
||||||
Q_EMIT activatedFiltered(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderViewTreeView::onSortFilterChanged() {
|
|
||||||
if(QSortFilterProxyModel* proxyModel = qobject_cast<QSortFilterProxyModel*>(model())) {
|
|
||||||
header()->setSortIndicatorShown(true);
|
|
||||||
header()->setSortIndicator(proxyModel->sortColumn(), proxyModel->sortOrder());
|
|
||||||
if (!isSortingEnabled()) {
|
|
||||||
setSortingEnabled(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
FolderView::FolderView(ViewMode _mode, QWidget* parent):
|
|
||||||
QWidget(parent),
|
|
||||||
view(NULL),
|
|
||||||
mode((ViewMode)0),
|
|
||||||
autoSelectionDelay_(600),
|
|
||||||
autoSelectionTimer_(NULL),
|
|
||||||
selChangedTimer_(NULL),
|
|
||||||
fileLauncher_(NULL),
|
|
||||||
model_(NULL) {
|
|
||||||
|
|
||||||
iconSize_[IconMode - FirstViewMode] = QSize(48, 48);
|
|
||||||
iconSize_[CompactMode - FirstViewMode] = QSize(24, 24);
|
|
||||||
iconSize_[ThumbnailMode - FirstViewMode] = QSize(128, 128);
|
|
||||||
iconSize_[DetailedListMode - FirstViewMode] = QSize(24, 24);
|
|
||||||
|
|
||||||
QVBoxLayout* layout = new QVBoxLayout();
|
|
||||||
layout->setMargin(0);
|
|
||||||
setLayout(layout);
|
|
||||||
|
|
||||||
setViewMode(_mode);
|
|
||||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
|
||||||
|
|
||||||
connect(this, &FolderView::clicked, this, &FolderView::onFileClicked);
|
|
||||||
}
|
|
||||||
|
|
||||||
FolderView::~FolderView() {
|
|
||||||
// qDebug("delete FolderView");
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderView::onItemActivated(QModelIndex index) {
|
|
||||||
if(index.isValid() && index.model()) {
|
|
||||||
QVariant data = index.model()->data(index, FolderModel::FileInfoRole);
|
|
||||||
FmFileInfo* info = (FmFileInfo*)data.value<void*>();
|
|
||||||
if(info) {
|
|
||||||
if (!(QApplication::keyboardModifiers() & (Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier))) {
|
|
||||||
Q_EMIT clicked(ActivatedClick, info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderView::onSelChangedTimeout() {
|
|
||||||
selChangedTimer_->deleteLater();
|
|
||||||
selChangedTimer_ = NULL;
|
|
||||||
|
|
||||||
QItemSelectionModel* selModel = selectionModel();
|
|
||||||
int nSel = 0;
|
|
||||||
if(viewMode() == DetailedListMode)
|
|
||||||
nSel = selModel->selectedRows().count();
|
|
||||||
else {
|
|
||||||
nSel = selModel->selectedIndexes().count();
|
|
||||||
}
|
|
||||||
// qDebug()<<"selected:" << nSel;
|
|
||||||
Q_EMIT selChanged(nSel); // FIXME: this is inefficient
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderView::onSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected) {
|
|
||||||
// It's possible that the selected items change too often and this slot gets called for thousands of times.
|
|
||||||
// For example, when you select thousands of files and delete them, we will get one selectionChanged() event
|
|
||||||
// for every deleted file. So, we use a timer to delay the handling to avoid too frequent updates of the UI.
|
|
||||||
if(!selChangedTimer_) {
|
|
||||||
selChangedTimer_ = new QTimer(this);
|
|
||||||
selChangedTimer_->setSingleShot(true);
|
|
||||||
connect(selChangedTimer_, &QTimer::timeout, this, &FolderView::onSelChangedTimeout);
|
|
||||||
selChangedTimer_->start(200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FolderView::setViewMode(ViewMode _mode) {
|
|
||||||
if(_mode == mode) // if it's the same more, ignore
|
|
||||||
return;
|
|
||||||
// FIXME: retain old selection
|
|
||||||
|
|
||||||
// since only detailed list mode uses QTreeView, and others
|
|
||||||
// all use QListView, it's wise to preserve QListView when possible.
|
|
||||||
bool recreateView = false;
|
|
||||||
if(view && (mode == DetailedListMode || _mode == DetailedListMode)) {
|
|
||||||
delete view; // FIXME: no virtual dtor?
|
|
||||||
view = NULL;
|
|
||||||
recreateView = true;
|
|
||||||
}
|
|
||||||
mode = _mode;
|
|
||||||
QSize iconSize = iconSize_[mode - FirstViewMode];
|
|
||||||
|
|
||||||
if(mode == DetailedListMode) {
|
|
||||||
FolderViewTreeView* treeView = new FolderViewTreeView(this);
|
|
||||||
connect(treeView, &FolderViewTreeView::activatedFiltered, this, &FolderView::onItemActivated);
|
|
||||||
|
|
||||||
view = treeView;
|
|
||||||
treeView->setItemsExpandable(false);
|
|
||||||
treeView->setRootIsDecorated(false);
|
|
||||||
treeView->setAllColumnsShowFocus(false);
|
|
||||||
|
|
||||||
// set our own custom delegate
|
|
||||||
FolderItemDelegate* delegate = new FolderItemDelegate(treeView);
|
|
||||||
treeView->setItemDelegateForColumn(FolderModel::ColumnFileName, delegate);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
FolderViewListView* listView;
|
|
||||||
if(view)
|
|
||||||
listView = static_cast<FolderViewListView*>(view);
|
|
||||||
else {
|
|
||||||
listView = new FolderViewListView(this);
|
|
||||||
connect(listView, &FolderViewListView::activatedFiltered, this, &FolderView::onItemActivated);
|
|
||||||
view = listView;
|
|
||||||
}
|
|
||||||
// set our own custom delegate
|
|
||||||
FolderItemDelegate* delegate = new FolderItemDelegate(listView);
|
|
||||||
listView->setItemDelegateForColumn(FolderModel::ColumnFileName, delegate);
|
|
||||||
// FIXME: should we expose the delegate?
|
|
||||||
listView->setMovement(QListView::Static);
|
|
||||||
listView->setResizeMode(QListView::Adjust);
|
|
||||||
listView->setWrapping(true);
|
|
||||||
switch(mode) {
|
|
||||||
case IconMode: {
|
|
||||||
listView->setViewMode(QListView::IconMode);
|
|
||||||
listView->setWordWrap(true);
|
|
||||||
listView->setFlow(QListView::LeftToRight);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CompactMode: {
|
|
||||||
listView->setViewMode(QListView::ListMode);
|
|
||||||
listView->setWordWrap(false);
|
|
||||||
listView->setFlow(QListView::QListView::TopToBottom);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ThumbnailMode: {
|
|
||||||
listView->setViewMode(QListView::IconMode);
|
|
||||||
listView->setWordWrap(true);
|
|
||||||
listView->setFlow(QListView::LeftToRight);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:;
|
|
||||||
}
|
|
||||||
updateGridSize();
|
|
||||||
}
|
|
||||||
if(view) {
|
|
||||||
// we have to install the event filter on the viewport instead of the view itself.
|
|
||||||
view->viewport()->installEventFilter(this);
|
|
||||||
// we want the QEvent::HoverMove event for single click + auto-selection support
|
|
||||||
view->viewport()->setAttribute(Qt::WA_Hover, true);
|
|
||||||
view->setContextMenuPolicy(Qt::NoContextMenu); // defer the context menu handling to parent widgets
|
|
||||||
view->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
|
||||||
view->setIconSize(iconSize);
|
|
||||||
|
|
||||||
view->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
|
||||||
layout()->addWidget(view);
|
|
||||||
|
|
||||||
// enable dnd
|
|
||||||
view->setDragEnabled(true);
|
|
||||||
view->setAcceptDrops(true);
|
|
||||||
view->setDragDropMode(QAbstractItemView::DragDrop);
|
|
||||||
view->setDropIndicatorShown(true);
|
|
||||||
|
|
||||||
if(model_) {
|
|
||||||
// FIXME: preserve selections
|
|
||||||
model_->setThumbnailSize(iconSize.width());
|
|
||||||
view->setModel(model_);
|
|
||||||
if(recreateView)
|
|
||||||
connect(view->selectionModel(), &QItemSelectionModel::selectionChanged, this, &FolderView::onSelectionChanged);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set proper grid size for the QListView based on current view mode, icon size, and font size.
|
|
||||||
void FolderView::updateGridSize() {
|
|
||||||
if(mode == DetailedListMode || !view)
|
|
||||||
return;
|
|
||||||
FolderViewListView* listView = static_cast<FolderViewListView*>(view);
|
|
||||||
QSize icon = iconSize(mode); // size of the icon
|
|
||||||
QFontMetrics fm = fontMetrics(); // size of current font
|
|
||||||
QSize grid; // the final grid size
|
|
||||||
switch(mode) {
|
|
||||||
case IconMode:
|
|
||||||
case ThumbnailMode: {
|
|
||||||
// NOTE by PCMan about finding the optimal text label size:
|
|
||||||
// The average filename length on my root filesystem is roughly 18-20 chars.
|
|
||||||
// So, a reasonable size for the text label is about 10 chars each line since string of this length
|
|
||||||
// can be shown in two lines. If you consider word wrap, then the result is around 10 chars per word.
|
|
||||||
// In average, 10 char per line should be enough to display a "word" in the filename without breaking.
|
|
||||||
// The values can be estimated with this command:
|
|
||||||
// > find / | xargs basename -a | sed -e s'/[_-]/ /g' | wc -mcw
|
|
||||||
// However, this average only applies to English. For some Asian characters, such as Chinese chars,
|
|
||||||
// each char actually takes doubled space. To be safe, we use 13 chars per line x average char width
|
|
||||||
// to get a nearly optimal width for the text label. As most of the filenames have less than 40 chars
|
|
||||||
// 13 chars x 3 lines should be enough to show the full filenames for most files.
|
|
||||||
int textWidth = fm.averageCharWidth() * 12 + 4; // add 2 px padding for left and right border
|
|
||||||
int textHeight = fm.height() * 3 + 4; // add 2 px padding for top and bottom border
|
|
||||||
grid.setWidth(qMax(icon.width(), textWidth) + 8); // add a margin 4 px for every cell
|
|
||||||
grid.setHeight(icon.height() + textHeight + 8); // add a margin 4 px for every cell
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
; // do not use grid size
|
|
||||||
}
|
|
||||||
listView->setGridSize(grid);
|
|
||||||
FolderItemDelegate* delegate = static_cast<FolderItemDelegate*>(listView->itemDelegateForColumn(FolderModel::ColumnFileName));
|
|
||||||
delegate->setGridSize(grid);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderView::setIconSize(ViewMode mode, QSize size) {
|
|
||||||
Q_ASSERT(mode >= FirstViewMode && mode <= LastViewMode);
|
|
||||||
iconSize_[mode - FirstViewMode] = size;
|
|
||||||
if(viewMode() == mode) {
|
|
||||||
view->setIconSize(size);
|
|
||||||
if(model_)
|
|
||||||
model_->setThumbnailSize(size.width());
|
|
||||||
updateGridSize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize FolderView::iconSize(ViewMode mode) const {
|
|
||||||
Q_ASSERT(mode >= FirstViewMode && mode <= LastViewMode);
|
|
||||||
return iconSize_[mode - FirstViewMode];
|
|
||||||
}
|
|
||||||
|
|
||||||
FolderView::ViewMode FolderView::viewMode() const {
|
|
||||||
return mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderView::setAutoSelectionDelay(int delay) {
|
|
||||||
autoSelectionDelay_ = delay;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAbstractItemView* FolderView::childView() const {
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProxyFolderModel* FolderView::model() const {
|
|
||||||
return model_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderView::setModel(ProxyFolderModel* model) {
|
|
||||||
if(view) {
|
|
||||||
view->setModel(model);
|
|
||||||
QSize iconSize = iconSize_[mode - FirstViewMode];
|
|
||||||
model->setThumbnailSize(iconSize.width());
|
|
||||||
if(view->selectionModel())
|
|
||||||
connect(view->selectionModel(), &QItemSelectionModel::selectionChanged, this, &FolderView::onSelectionChanged);
|
|
||||||
}
|
|
||||||
if(model_)
|
|
||||||
delete model_;
|
|
||||||
model_ = model;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FolderView::event(QEvent* event) {
|
|
||||||
switch(event->type()) {
|
|
||||||
case QEvent::StyleChange:
|
|
||||||
break;
|
|
||||||
case QEvent::FontChange:
|
|
||||||
updateGridSize();
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
return QWidget::event(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderView::contextMenuEvent(QContextMenuEvent* event) {
|
|
||||||
QWidget::contextMenuEvent(event);
|
|
||||||
QPoint pos = event->pos();
|
|
||||||
QPoint view_pos = view->mapFromParent(pos);
|
|
||||||
QPoint viewport_pos = view->viewport()->mapFromParent(view_pos);
|
|
||||||
emitClickedAt(ContextMenuClick, viewport_pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderView::childMousePressEvent(QMouseEvent* event) {
|
|
||||||
// called from mousePressEvent() of child view
|
|
||||||
if(event->button() == Qt::MiddleButton) {
|
|
||||||
emitClickedAt(MiddleClick, event->pos());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderView::emitClickedAt(ClickType type, const QPoint& pos) {
|
|
||||||
// indexAt() needs a point in "viewport" coordinates.
|
|
||||||
QModelIndex index = view->indexAt(pos);
|
|
||||||
if(index.isValid()) {
|
|
||||||
QVariant data = index.data(FolderModel::FileInfoRole);
|
|
||||||
FmFileInfo* info = reinterpret_cast<FmFileInfo*>(data.value<void*>());
|
|
||||||
Q_EMIT clicked(type, info);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// FIXME: should we show popup menu for the selected files instead
|
|
||||||
// if there are selected files?
|
|
||||||
if(type == ContextMenuClick) {
|
|
||||||
// clear current selection if clicked outside selected files
|
|
||||||
view->clearSelection();
|
|
||||||
Q_EMIT clicked(type, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QModelIndexList FolderView::selectedRows(int column) const {
|
|
||||||
QItemSelectionModel* selModel = selectionModel();
|
|
||||||
if(selModel) {
|
|
||||||
return selModel->selectedRows(column);
|
|
||||||
}
|
|
||||||
return QModelIndexList();
|
|
||||||
}
|
|
||||||
|
|
||||||
// This returns all selected "cells", which means all cells of the same row are returned.
|
|
||||||
QModelIndexList FolderView::selectedIndexes() const {
|
|
||||||
QItemSelectionModel* selModel = selectionModel();
|
|
||||||
if(selModel) {
|
|
||||||
return selModel->selectedIndexes();
|
|
||||||
}
|
|
||||||
return QModelIndexList();
|
|
||||||
}
|
|
||||||
|
|
||||||
QItemSelectionModel* FolderView::selectionModel() const {
|
|
||||||
return view ? view->selectionModel() : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
FmPathList* FolderView::selectedFilePaths() const {
|
|
||||||
if(model_) {
|
|
||||||
QModelIndexList selIndexes = mode == DetailedListMode ? selectedRows() : selectedIndexes();
|
|
||||||
if(!selIndexes.isEmpty()) {
|
|
||||||
FmPathList* paths = fm_path_list_new();
|
|
||||||
QModelIndexList::const_iterator it;
|
|
||||||
for(it = selIndexes.begin(); it != selIndexes.end(); ++it) {
|
|
||||||
FmFileInfo* file = model_->fileInfoFromIndex(*it);
|
|
||||||
fm_path_list_push_tail(paths, fm_file_info_get_path(file));
|
|
||||||
}
|
|
||||||
return paths;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
FmFileInfoList* FolderView::selectedFiles() const {
|
|
||||||
if(model_) {
|
|
||||||
QModelIndexList selIndexes = mode == DetailedListMode ? selectedRows() : selectedIndexes();
|
|
||||||
if(!selIndexes.isEmpty()) {
|
|
||||||
FmFileInfoList* files = fm_file_info_list_new();
|
|
||||||
QModelIndexList::const_iterator it;
|
|
||||||
for(it = selIndexes.constBegin(); it != selIndexes.constEnd(); ++it) {
|
|
||||||
FmFileInfo* file = model_->fileInfoFromIndex(*it);
|
|
||||||
fm_file_info_list_push_tail(files, file);
|
|
||||||
}
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderView::selectAll() {
|
|
||||||
if(mode == DetailedListMode)
|
|
||||||
view->selectAll();
|
|
||||||
else {
|
|
||||||
// NOTE: By default QListView::selectAll() selects all columns in the model.
|
|
||||||
// However, QListView only show the first column. Normal selection by mouse
|
|
||||||
// can only select the first column of every row. I consider this discripancy yet
|
|
||||||
// another design flaw of Qt. To make them consistent, we do it ourselves by only
|
|
||||||
// selecting the first column of every row and do not select all columns as Qt does.
|
|
||||||
// This will trigger one selectionChanged event per row, which is very inefficient,
|
|
||||||
// but we have no other choices to workaround the Qt bug.
|
|
||||||
// I'll report a Qt bug for this later.
|
|
||||||
if(model_) {
|
|
||||||
int rowCount = model_->rowCount();
|
|
||||||
for(int row = 0; row < rowCount; ++row) {
|
|
||||||
QModelIndex index = model_->index(row, 0);
|
|
||||||
selectionModel()->select(index, QItemSelectionModel::Select);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderView::invertSelection() {
|
|
||||||
if(model_) {
|
|
||||||
QItemSelectionModel* selModel = view->selectionModel();
|
|
||||||
int rows = model_->rowCount();
|
|
||||||
QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::Toggle;
|
|
||||||
if(mode == DetailedListMode)
|
|
||||||
flags |= QItemSelectionModel::Rows;
|
|
||||||
for(int row = 0; row < rows; ++row) {
|
|
||||||
QModelIndex index = model_->index(row, 0);
|
|
||||||
selModel->select(index, flags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderView::childDragEnterEvent(QDragEnterEvent* event) {
|
|
||||||
qDebug("drag enter");
|
|
||||||
if(event->mimeData()->hasFormat("text/uri-list")) {
|
|
||||||
event->accept();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
event->ignore();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderView::childDragLeaveEvent(QDragLeaveEvent* e) {
|
|
||||||
qDebug("drag leave");
|
|
||||||
e->accept();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderView::childDragMoveEvent(QDragMoveEvent* e) {
|
|
||||||
qDebug("drag move");
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderView::childDropEvent(QDropEvent* e) {
|
|
||||||
qDebug("drop");
|
|
||||||
if(e->keyboardModifiers() == Qt::NoModifier) {
|
|
||||||
// if no key modifiers are used, popup a menu
|
|
||||||
// to ask the user for the action he/she wants to perform.
|
|
||||||
Qt::DropAction action = DndActionMenu::askUser(QCursor::pos());
|
|
||||||
e->setDropAction(action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FolderView::eventFilter(QObject* watched, QEvent* event) {
|
|
||||||
// NOTE: Instead of simply filtering the drag and drop events of the child view in
|
|
||||||
// the event filter, we overrided each event handler virtual methods in
|
|
||||||
// both QListView and QTreeView and added some childXXXEvent() callbacks.
|
|
||||||
// We did this because of a design flaw of Qt.
|
|
||||||
// All QAbstractScrollArea derived widgets, including QAbstractItemView
|
|
||||||
// contains an internal child widget, which is called a viewport.
|
|
||||||
// The events actually comes from the child viewport, not the parent view itself.
|
|
||||||
// Qt redirects the events of viewport to the viewportEvent() method of
|
|
||||||
// QAbstractScrollArea and let the parent widget handle the events.
|
|
||||||
// Qt implemented this using a event filter installed on the child viewport widget.
|
|
||||||
// That means, when we try to install an event filter on the viewport,
|
|
||||||
// there is already a filter installed by Qt which will be called before ours.
|
|
||||||
// So we can never intercept the event handling of QAbstractItemView by using a filter.
|
|
||||||
// That's why we override respective virtual methods for different events.
|
|
||||||
if(view && watched == view->viewport()) {
|
|
||||||
switch(event->type()) {
|
|
||||||
case QEvent::HoverMove:
|
|
||||||
// activate items on single click
|
|
||||||
if(style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick)) {
|
|
||||||
QHoverEvent* hoverEvent = static_cast<QHoverEvent*>(event);
|
|
||||||
QModelIndex index = view->indexAt(hoverEvent->pos()); // find out the hovered item
|
|
||||||
if(index.isValid()) { // change the cursor to a hand when hovering on an item
|
|
||||||
setCursor(Qt::PointingHandCursor);
|
|
||||||
if(!selectionModel()->hasSelection())
|
|
||||||
selectionModel()->setCurrentIndex(index, QItemSelectionModel::Current);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
setCursor(Qt::ArrowCursor);
|
|
||||||
// turn on auto-selection for hovered item when single click mode is used.
|
|
||||||
if(autoSelectionDelay_ > 0 && model_) {
|
|
||||||
if(!autoSelectionTimer_) {
|
|
||||||
autoSelectionTimer_ = new QTimer(this);
|
|
||||||
connect(autoSelectionTimer_, &QTimer::timeout, this, &FolderView::onAutoSelectionTimeout);
|
|
||||||
lastAutoSelectionIndex_ = QModelIndex();
|
|
||||||
}
|
|
||||||
autoSelectionTimer_->start(autoSelectionDelay_);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case QEvent::HoverLeave:
|
|
||||||
if(style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick))
|
|
||||||
setCursor(Qt::ArrowCursor);
|
|
||||||
break;
|
|
||||||
case QEvent::Wheel:
|
|
||||||
// This is to fix #85: Scrolling doesn't work in compact view
|
|
||||||
// Actually, I think it's the bug of Qt, not ours.
|
|
||||||
// When in compact mode, only the horizontal scroll bar is used and the vertical one is hidden.
|
|
||||||
// So, when a user scroll his mouse wheel, it's reasonable to scroll the horizontal scollbar.
|
|
||||||
// Qt does not implement such a simple feature, unfortunately.
|
|
||||||
// We do it by forwarding the scroll event in the viewport to the horizontal scrollbar.
|
|
||||||
// FIXME: if someday Qt supports this, we have to disable the workaround.
|
|
||||||
if(mode == CompactMode) {
|
|
||||||
QScrollBar* scroll = view->horizontalScrollBar();
|
|
||||||
if(scroll) {
|
|
||||||
QApplication::sendEvent(scroll, event);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QObject::eventFilter(watched, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
// this slot handles auto-selection of items.
|
|
||||||
void FolderView::onAutoSelectionTimeout() {
|
|
||||||
if(QApplication::mouseButtons() != Qt::NoButton)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Qt::KeyboardModifiers mods = QApplication::keyboardModifiers();
|
|
||||||
QPoint pos = view->viewport()->mapFromGlobal(QCursor::pos()); // convert to viewport coordinates
|
|
||||||
QModelIndex index = view->indexAt(pos); // find out the hovered item
|
|
||||||
QItemSelectionModel::SelectionFlags flags = (mode == DetailedListMode ? QItemSelectionModel::Rows : QItemSelectionModel::NoUpdate);
|
|
||||||
QItemSelectionModel* selModel = view->selectionModel();
|
|
||||||
|
|
||||||
if(mods & Qt::ControlModifier) { // Ctrl key is pressed
|
|
||||||
if(selModel->isSelected(index) && index != lastAutoSelectionIndex_) {
|
|
||||||
// unselect a previously selected item
|
|
||||||
selModel->select(index, flags|QItemSelectionModel::Deselect);
|
|
||||||
lastAutoSelectionIndex_ = QModelIndex();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// select an unselected item
|
|
||||||
selModel->select(index, flags|QItemSelectionModel::Select);
|
|
||||||
lastAutoSelectionIndex_ = index;
|
|
||||||
}
|
|
||||||
selModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate); // move the cursor
|
|
||||||
}
|
|
||||||
else if(mods & Qt::ShiftModifier) { // Shift key is pressed
|
|
||||||
// select all items between current index and the hovered index.
|
|
||||||
QModelIndex current = selModel->currentIndex();
|
|
||||||
if(selModel->hasSelection() && current.isValid()) {
|
|
||||||
selModel->clear(); // clear old selection
|
|
||||||
selModel->setCurrentIndex(current, QItemSelectionModel::NoUpdate);
|
|
||||||
int begin = current.row();
|
|
||||||
int end = index.row();
|
|
||||||
if(begin > end)
|
|
||||||
qSwap(begin, end);
|
|
||||||
for(int row = begin; row <= end; ++row) {
|
|
||||||
QModelIndex sel = model_->index(row, 0);
|
|
||||||
selModel->select(sel, flags|QItemSelectionModel::Select);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { // no items are selected, select the hovered item.
|
|
||||||
if(index.isValid()) {
|
|
||||||
selModel->select(index, flags|QItemSelectionModel::SelectCurrent);
|
|
||||||
selModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastAutoSelectionIndex_ = index;
|
|
||||||
}
|
|
||||||
else if(mods == Qt::NoModifier) { // no modifier keys are pressed.
|
|
||||||
if(index.isValid()) {
|
|
||||||
// select the hovered item
|
|
||||||
view->clearSelection();
|
|
||||||
selModel->select(index, flags|QItemSelectionModel::SelectCurrent);
|
|
||||||
selModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
|
|
||||||
}
|
|
||||||
lastAutoSelectionIndex_ = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
autoSelectionTimer_->deleteLater();
|
|
||||||
autoSelectionTimer_ = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderView::onFileClicked(int type, FmFileInfo* fileInfo) {
|
|
||||||
if(type == ActivatedClick) {
|
|
||||||
if(fileLauncher_) {
|
|
||||||
GList* files = g_list_append(NULL, fileInfo);
|
|
||||||
fileLauncher_->launchFiles(NULL, files);
|
|
||||||
g_list_free(files);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(type == ContextMenuClick) {
|
|
||||||
FmPath* folderPath = path();
|
|
||||||
QMenu* menu = NULL;
|
|
||||||
if(fileInfo) {
|
|
||||||
// show context menu
|
|
||||||
if (FmFileInfoList* files = selectedFiles()) {
|
|
||||||
Fm::FileMenu* fileMenu = new Fm::FileMenu(files, fileInfo, folderPath);
|
|
||||||
fileMenu->setFileLauncher(fileLauncher_);
|
|
||||||
prepareFileMenu(fileMenu);
|
|
||||||
fm_file_info_list_unref(files);
|
|
||||||
menu = fileMenu;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Fm::FolderMenu* folderMenu = new Fm::FolderMenu(this);
|
|
||||||
prepareFolderMenu(folderMenu);
|
|
||||||
menu = folderMenu;
|
|
||||||
}
|
|
||||||
if (menu) {
|
|
||||||
menu->exec(QCursor::pos());
|
|
||||||
delete menu;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderView::prepareFileMenu(FileMenu* menu) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderView::prepareFolderMenu(FolderMenu* menu) {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Fm
|
|
||||||
@ -1,167 +0,0 @@
|
|||||||
/*
|
|
||||||
<one line to give the library's name and an idea of what it does.>
|
|
||||||
Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FM_FOLDERVIEW_H
|
|
||||||
#define FM_FOLDERVIEW_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QListView>
|
|
||||||
#include <QTreeView>
|
|
||||||
#include <QMouseEvent>
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
#include "foldermodel.h"
|
|
||||||
#include "proxyfoldermodel.h"
|
|
||||||
|
|
||||||
class QTimer;
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class FileMenu;
|
|
||||||
class FolderMenu;
|
|
||||||
class FileLauncher;
|
|
||||||
class FolderViewStyle;
|
|
||||||
|
|
||||||
class LIBFM_QT_API FolderView : public QWidget {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum ViewMode {
|
|
||||||
FirstViewMode = 1,
|
|
||||||
IconMode = FirstViewMode,
|
|
||||||
CompactMode,
|
|
||||||
DetailedListMode,
|
|
||||||
ThumbnailMode,
|
|
||||||
LastViewMode = ThumbnailMode,
|
|
||||||
NumViewModes = (LastViewMode - FirstViewMode + 1)
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ClickType {
|
|
||||||
ActivatedClick,
|
|
||||||
MiddleClick,
|
|
||||||
ContextMenuClick
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
friend class FolderViewTreeView;
|
|
||||||
friend class FolderViewListView;
|
|
||||||
|
|
||||||
explicit FolderView(ViewMode _mode = IconMode, QWidget* parent = 0);
|
|
||||||
virtual ~FolderView();
|
|
||||||
|
|
||||||
void setViewMode(ViewMode _mode);
|
|
||||||
ViewMode viewMode() const;
|
|
||||||
|
|
||||||
void setIconSize(ViewMode mode, QSize size);
|
|
||||||
QSize iconSize(ViewMode mode) const;
|
|
||||||
|
|
||||||
QAbstractItemView* childView() const;
|
|
||||||
|
|
||||||
ProxyFolderModel* model() const;
|
|
||||||
void setModel(ProxyFolderModel* _model);
|
|
||||||
|
|
||||||
FmFolder* folder() {
|
|
||||||
return model_ ? static_cast<FolderModel*>(model_->sourceModel())->folder() : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
FmFileInfo* folderInfo() {
|
|
||||||
FmFolder* _folder = folder();
|
|
||||||
return _folder ? fm_folder_get_info(_folder) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
FmPath* path() {
|
|
||||||
FmFolder* _folder = folder();
|
|
||||||
return _folder ? fm_folder_get_path(_folder) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
QItemSelectionModel* selectionModel() const;
|
|
||||||
FmFileInfoList* selectedFiles() const;
|
|
||||||
FmPathList* selectedFilePaths() const;
|
|
||||||
|
|
||||||
void selectAll();
|
|
||||||
|
|
||||||
void invertSelection();
|
|
||||||
|
|
||||||
void setFileLauncher(FileLauncher* launcher) {
|
|
||||||
fileLauncher_ = launcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileLauncher* fileLauncher() {
|
|
||||||
return fileLauncher_;
|
|
||||||
}
|
|
||||||
|
|
||||||
int autoSelectionDelay() const {
|
|
||||||
return autoSelectionDelay_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setAutoSelectionDelay(int delay);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool event(QEvent* event);
|
|
||||||
virtual void contextMenuEvent(QContextMenuEvent* event);
|
|
||||||
virtual void childMousePressEvent(QMouseEvent* event);
|
|
||||||
virtual void childDragEnterEvent(QDragEnterEvent* event);
|
|
||||||
virtual void childDragMoveEvent(QDragMoveEvent* e);
|
|
||||||
virtual void childDragLeaveEvent(QDragLeaveEvent* e);
|
|
||||||
virtual void childDropEvent(QDropEvent* e);
|
|
||||||
|
|
||||||
void emitClickedAt(ClickType type, const QPoint& pos);
|
|
||||||
|
|
||||||
QModelIndexList selectedRows ( int column = 0 ) const;
|
|
||||||
QModelIndexList selectedIndexes() const;
|
|
||||||
|
|
||||||
virtual void prepareFileMenu(Fm::FileMenu* menu);
|
|
||||||
virtual void prepareFolderMenu(Fm::FolderMenu* menu);
|
|
||||||
|
|
||||||
virtual bool eventFilter(QObject* watched, QEvent* event);
|
|
||||||
|
|
||||||
void updateGridSize(); // called when view mode, icon size, or font size is changed
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
|
||||||
void onItemActivated(QModelIndex index);
|
|
||||||
void onSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected);
|
|
||||||
virtual void onFileClicked(int type, FmFileInfo* fileInfo);
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
|
||||||
void onAutoSelectionTimeout();
|
|
||||||
void onSelChangedTimeout();
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void clicked(int type, FmFileInfo* file);
|
|
||||||
void selChanged(int n_sel);
|
|
||||||
void sortChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
QAbstractItemView* view;
|
|
||||||
ProxyFolderModel* model_;
|
|
||||||
ViewMode mode;
|
|
||||||
QSize iconSize_[NumViewModes];
|
|
||||||
FileLauncher* fileLauncher_;
|
|
||||||
int autoSelectionDelay_;
|
|
||||||
QTimer* autoSelectionTimer_;
|
|
||||||
QModelIndex lastAutoSelectionIndex_;
|
|
||||||
QTimer* selChangedTimer_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_FOLDERVIEW_H
|
|
||||||
@ -1,109 +0,0 @@
|
|||||||
/*
|
|
||||||
<one line to give the library's name and an idea of what it does.>
|
|
||||||
Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FM_FOLDERVIEW_P_H
|
|
||||||
#define FM_FOLDERVIEW_P_H
|
|
||||||
|
|
||||||
#include <QListView>
|
|
||||||
#include <QTreeView>
|
|
||||||
#include <QMouseEvent>
|
|
||||||
#include "folderview.h"
|
|
||||||
|
|
||||||
class QTimer;
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
// override these classes for implementing FolderView
|
|
||||||
class FolderViewListView : public QListView {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
friend class FolderView;
|
|
||||||
FolderViewListView(QWidget* parent = 0);
|
|
||||||
virtual ~FolderViewListView();
|
|
||||||
virtual void startDrag(Qt::DropActions supportedActions);
|
|
||||||
virtual void mousePressEvent(QMouseEvent* event);
|
|
||||||
virtual void mouseReleaseEvent(QMouseEvent* event);
|
|
||||||
virtual void mouseDoubleClickEvent(QMouseEvent* event);
|
|
||||||
virtual void dragEnterEvent(QDragEnterEvent* event);
|
|
||||||
virtual void dragMoveEvent(QDragMoveEvent* e);
|
|
||||||
virtual void dragLeaveEvent(QDragLeaveEvent* e);
|
|
||||||
virtual void dropEvent(QDropEvent* e);
|
|
||||||
|
|
||||||
virtual QModelIndex indexAt(const QPoint & point) const;
|
|
||||||
|
|
||||||
inline void setPositionForIndex(const QPoint & position, const QModelIndex & index) {
|
|
||||||
QListView::setPositionForIndex(position, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QRect rectForIndex(const QModelIndex & index) const {
|
|
||||||
return QListView::rectForIndex(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void activatedFiltered(const QModelIndex &index);
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
|
||||||
void activation(const QModelIndex &index);
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool activationAllowed_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FolderViewTreeView : public QTreeView {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
friend class FolderView;
|
|
||||||
FolderViewTreeView(QWidget* parent = 0);
|
|
||||||
virtual ~FolderViewTreeView();
|
|
||||||
virtual void setModel(QAbstractItemModel* model);
|
|
||||||
virtual void mousePressEvent(QMouseEvent* event);
|
|
||||||
virtual void mouseReleaseEvent(QMouseEvent* event);
|
|
||||||
virtual void mouseDoubleClickEvent(QMouseEvent* event);
|
|
||||||
virtual void dragEnterEvent(QDragEnterEvent* event);
|
|
||||||
virtual void dragMoveEvent(QDragMoveEvent* e);
|
|
||||||
virtual void dragLeaveEvent(QDragLeaveEvent* e);
|
|
||||||
virtual void dropEvent(QDropEvent* e);
|
|
||||||
|
|
||||||
virtual void rowsInserted(const QModelIndex& parent,int start, int end);
|
|
||||||
virtual void rowsAboutToBeRemoved(const QModelIndex& parent,int start, int end);
|
|
||||||
virtual void dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
|
||||||
virtual void reset();
|
|
||||||
|
|
||||||
virtual void resizeEvent(QResizeEvent* event);
|
|
||||||
void queueLayoutColumns();
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void activatedFiltered(const QModelIndex &index);
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
|
||||||
void layoutColumns();
|
|
||||||
void activation(const QModelIndex &index);
|
|
||||||
void onSortFilterChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool doingLayout_;
|
|
||||||
QTimer* layoutTimer_;
|
|
||||||
bool activationAllowed_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Fm
|
|
||||||
|
|
||||||
#endif // FM_FOLDERVIEW_P_H
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "fontbutton.h"
|
|
||||||
#include <QFontDialog>
|
|
||||||
#include <X11/X.h>
|
|
||||||
|
|
||||||
using namespace Fm;
|
|
||||||
|
|
||||||
FontButton::FontButton(QWidget* parent): QPushButton(parent) {
|
|
||||||
connect(this, &QPushButton::clicked, this, &FontButton::onClicked);
|
|
||||||
}
|
|
||||||
|
|
||||||
FontButton::~FontButton() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void FontButton::onClicked() {
|
|
||||||
QFontDialog dlg(font_);
|
|
||||||
if(dlg.exec() == QDialog::Accepted) {
|
|
||||||
setFont(dlg.selectedFont());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FontButton::setFont(QFont font) {
|
|
||||||
font_ = font;
|
|
||||||
QString text = font.family();
|
|
||||||
if(font.bold()) {
|
|
||||||
text += " ";
|
|
||||||
text += tr("Bold");
|
|
||||||
}
|
|
||||||
if(font.italic()) {
|
|
||||||
text += " ";
|
|
||||||
text += tr("Italic");
|
|
||||||
}
|
|
||||||
text += QString(" %1").arg(font.pointSize());
|
|
||||||
setText(text);
|
|
||||||
Q_EMIT changed();
|
|
||||||
}
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FM_FONTBUTTON_H
|
|
||||||
#define FM_FONTBUTTON_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QPushButton>
|
|
||||||
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class LIBFM_QT_API FontButton : public QPushButton {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit FontButton(QWidget* parent = 0);
|
|
||||||
virtual ~FontButton();
|
|
||||||
|
|
||||||
QFont font() {
|
|
||||||
return font_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setFont(QFont font);
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void changed();
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
|
||||||
void onClicked();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QFont font_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_FONTBUTTON_H
|
|
||||||
@ -1,143 +0,0 @@
|
|||||||
/*
|
|
||||||
<one line to give the library's name and an idea of what it does.>
|
|
||||||
Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "icontheme.h"
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
#include <QList>
|
|
||||||
#include <QIcon>
|
|
||||||
#include <QtGlobal>
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QDesktopWidget>
|
|
||||||
|
|
||||||
using namespace Fm;
|
|
||||||
|
|
||||||
static IconTheme* theIconTheme = NULL; // the global single instance of IconTheme.
|
|
||||||
static const char* fallbackNames[] = {"unknown", "application-octet-stream", NULL};
|
|
||||||
|
|
||||||
static void fmIconDataDestroy(gpointer data) {
|
|
||||||
QIcon* picon = reinterpret_cast<QIcon*>(data);
|
|
||||||
delete picon;
|
|
||||||
}
|
|
||||||
|
|
||||||
IconTheme::IconTheme():
|
|
||||||
currentThemeName_(QIcon::themeName()) {
|
|
||||||
// NOTE: only one instance is allowed
|
|
||||||
Q_ASSERT(theIconTheme == NULL);
|
|
||||||
Q_ASSERT(qApp != NULL); // QApplication should exists before contructing IconTheme.
|
|
||||||
|
|
||||||
theIconTheme = this;
|
|
||||||
fm_icon_set_user_data_destroy(reinterpret_cast<GDestroyNotify>(fmIconDataDestroy));
|
|
||||||
fallbackIcon_ = iconFromNames(fallbackNames);
|
|
||||||
|
|
||||||
// We need to get notified when there is a QEvent::StyleChange event so
|
|
||||||
// we can check if the current icon theme name is changed.
|
|
||||||
// To do this, we can filter QApplication object itself to intercept
|
|
||||||
// signals of all widgets, but this may be too inefficient.
|
|
||||||
// So, we only filter the events on QDesktopWidget instead.
|
|
||||||
qApp->desktop()->installEventFilter(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
IconTheme::~IconTheme() {
|
|
||||||
}
|
|
||||||
|
|
||||||
IconTheme* IconTheme::instance() {
|
|
||||||
return theIconTheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the icon theme name is changed and emit "changed()" signal if any change is detected.
|
|
||||||
void IconTheme::checkChanged() {
|
|
||||||
if(QIcon::themeName() != theIconTheme->currentThemeName_) {
|
|
||||||
// if the icon theme is changed
|
|
||||||
theIconTheme->currentThemeName_ = QIcon::themeName();
|
|
||||||
// invalidate the cached data
|
|
||||||
fm_icon_reset_user_data_cache(fm_qdata_id);
|
|
||||||
|
|
||||||
theIconTheme->fallbackIcon_ = iconFromNames(fallbackNames);
|
|
||||||
Q_EMIT theIconTheme->changed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QIcon IconTheme::iconFromNames(const char* const* names) {
|
|
||||||
const gchar* const* name;
|
|
||||||
// qDebug("names: %p", names);
|
|
||||||
for(name = names; *name; ++name) {
|
|
||||||
// qDebug("icon name=%s", *name);
|
|
||||||
QString qname = *name;
|
|
||||||
QIcon qicon = QIcon::fromTheme(qname);
|
|
||||||
if(!qicon.isNull()) {
|
|
||||||
return qicon;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QIcon();
|
|
||||||
}
|
|
||||||
|
|
||||||
QIcon IconTheme::convertFromGIcon(GIcon* gicon) {
|
|
||||||
if(G_IS_THEMED_ICON(gicon)) {
|
|
||||||
const gchar * const * names = g_themed_icon_get_names(G_THEMED_ICON(gicon));
|
|
||||||
QIcon icon = iconFromNames(names);
|
|
||||||
if(!icon.isNull())
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
else if(G_IS_FILE_ICON(gicon)) {
|
|
||||||
GFile* file = g_file_icon_get_file(G_FILE_ICON(gicon));
|
|
||||||
char* fpath = g_file_get_path(file);
|
|
||||||
QString path = fpath;
|
|
||||||
g_free(fpath);
|
|
||||||
return QIcon(path);
|
|
||||||
}
|
|
||||||
return theIconTheme->fallbackIcon_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//static
|
|
||||||
QIcon IconTheme::icon(FmIcon* fmicon) {
|
|
||||||
// check if we have a cached version
|
|
||||||
QIcon* picon = reinterpret_cast<QIcon*>(fm_icon_get_user_data(fmicon));
|
|
||||||
if(!picon) { // we don't have a cache yet
|
|
||||||
picon = new QIcon(); // what a waste!
|
|
||||||
*picon = convertFromGIcon(G_ICON(fmicon));
|
|
||||||
fm_icon_set_user_data(fmicon, picon); // store it in FmIcon
|
|
||||||
}
|
|
||||||
return *picon;
|
|
||||||
}
|
|
||||||
|
|
||||||
//static
|
|
||||||
QIcon IconTheme::icon(GIcon* gicon) {
|
|
||||||
if(G_IS_THEMED_ICON(gicon)) {
|
|
||||||
FmIcon* fmicon = fm_icon_from_gicon(gicon);
|
|
||||||
QIcon qicon = icon(fmicon);
|
|
||||||
fm_icon_unref(fmicon);
|
|
||||||
return qicon;
|
|
||||||
}
|
|
||||||
else if(G_IS_FILE_ICON(gicon)) {
|
|
||||||
// we do not map GFileIcon to FmIcon deliberately.
|
|
||||||
return convertFromGIcon(gicon);
|
|
||||||
}
|
|
||||||
return theIconTheme->fallbackIcon_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// this method is called whenever there is an event on the QDesktopWidget object.
|
|
||||||
bool IconTheme::eventFilter(QObject* obj, QEvent* event) {
|
|
||||||
// we're only interested in the StyleChange event.
|
|
||||||
if(event->type() == QEvent::StyleChange) {
|
|
||||||
checkChanged(); // check if the icon theme is changed
|
|
||||||
}
|
|
||||||
return QObject::eventFilter(obj, event);
|
|
||||||
}
|
|
||||||
@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
<one line to give the library's name and an idea of what it does.>
|
|
||||||
Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FM_ICONTHEME_H
|
|
||||||
#define FM_ICONTHEME_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QIcon>
|
|
||||||
#include <QString>
|
|
||||||
#include "libfm/fm.h"
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
// NOTE:
|
|
||||||
// Qt seems to has its own QIcon pixmap caching mechanism internally.
|
|
||||||
// Besides, it also caches QIcon objects created by QIcon::fromTheme().
|
|
||||||
// So maybe we should not duplicate the work.
|
|
||||||
// See http://qt.gitorious.org/qt/qt/blobs/4.8/src/gui/image/qicon.cpp
|
|
||||||
// QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state).
|
|
||||||
// In addition, QPixmap is actually stored in X11 server, not client side.
|
|
||||||
// Hence maybe we should not cache too many pixmaps, I guess?
|
|
||||||
// Let's have Qt do its work and only translate GIcon to QIcon here.
|
|
||||||
|
|
||||||
// Nice article about QPixmap from KDE: http://techbase.kde.org/Development/Tutorials/Graphics/Performance
|
|
||||||
|
|
||||||
class LIBFM_QT_API IconTheme: public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
IconTheme();
|
|
||||||
~IconTheme();
|
|
||||||
|
|
||||||
static IconTheme* instance();
|
|
||||||
static QIcon icon(FmIcon* fmicon);
|
|
||||||
static QIcon icon(GIcon* gicon);
|
|
||||||
|
|
||||||
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);
|
|
||||||
static QIcon convertFromGIcon(GIcon* gicon);
|
|
||||||
static QIcon iconFromNames(const char * const * names);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
QIcon fallbackIcon_;
|
|
||||||
QString currentThemeName_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_ICONTHEME_H
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
prefix=@CMAKE_INSTALL_PREFIX@
|
|
||||||
exec_prefix=${prefix}
|
|
||||||
libdir=${exec_prefix}/lib
|
|
||||||
includedir=${prefix}/include
|
|
||||||
|
|
||||||
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)
|
|
||||||
URL: http://pcmanfm.sourceforge.net/
|
|
||||||
Requires: @REQUIRED_QT@ libfm >= 1.2.0
|
|
||||||
Version: @LIBFM_QT_VERSION@
|
|
||||||
Libs: -L${libdir} -lfm -l@LIBRARY_NAME@
|
|
||||||
Cflags: -I${includedir}
|
|
||||||
@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
<one line to give the library's name and an idea of what it does.>
|
|
||||||
Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
#include "libfmqt.h"
|
|
||||||
#include <QLocale>
|
|
||||||
#include "icontheme.h"
|
|
||||||
#include "thumbnailloader.h"
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
struct LibFmQtData {
|
|
||||||
LibFmQtData();
|
|
||||||
~LibFmQtData();
|
|
||||||
|
|
||||||
IconTheme* iconTheme;
|
|
||||||
ThumbnailLoader* thumbnailLoader;
|
|
||||||
QTranslator translator;
|
|
||||||
int refCount;
|
|
||||||
Q_DISABLE_COPY(LibFmQtData)
|
|
||||||
};
|
|
||||||
|
|
||||||
static LibFmQtData* theLibFmData = NULL;
|
|
||||||
|
|
||||||
LibFmQtData::LibFmQtData(): refCount(1) {
|
|
||||||
#if !GLIB_CHECK_VERSION(2, 36, 0)
|
|
||||||
g_type_init();
|
|
||||||
#endif
|
|
||||||
fm_init(NULL);
|
|
||||||
// turn on glib debug message
|
|
||||||
// g_setenv("G_MESSAGES_DEBUG", "all", true);
|
|
||||||
iconTheme = new IconTheme();
|
|
||||||
thumbnailLoader = new ThumbnailLoader();
|
|
||||||
translator.load("libfm-qt_" + QLocale::system().name(), LIBFM_DATA_DIR "/translations");
|
|
||||||
}
|
|
||||||
|
|
||||||
LibFmQtData::~LibFmQtData() {
|
|
||||||
delete iconTheme;
|
|
||||||
delete thumbnailLoader;
|
|
||||||
fm_finalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
LibFmQt::LibFmQt() {
|
|
||||||
if(!theLibFmData) {
|
|
||||||
theLibFmData = new LibFmQtData();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
++theLibFmData->refCount;
|
|
||||||
d = theLibFmData;
|
|
||||||
}
|
|
||||||
|
|
||||||
LibFmQt::~LibFmQt() {
|
|
||||||
if(--d->refCount == 0) {
|
|
||||||
delete d;
|
|
||||||
theLibFmData = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QTranslator* LibFmQt::translator() {
|
|
||||||
return &d->translator;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Fm
|
|
||||||
@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
<one line to give the library's name and an idea of what it does.>
|
|
||||||
Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FM_APPLICATION_H
|
|
||||||
#define FM_APPLICATION_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QtGlobal>
|
|
||||||
#include <QTranslator>
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
struct LibFmQtData;
|
|
||||||
|
|
||||||
class LIBFM_QT_API LibFmQt {
|
|
||||||
public:
|
|
||||||
LibFmQt();
|
|
||||||
~LibFmQt();
|
|
||||||
|
|
||||||
QTranslator* translator();
|
|
||||||
|
|
||||||
private:
|
|
||||||
LibFmQt(LibFmQt& other); // disable copy
|
|
||||||
LibFmQtData* d;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_APPLICATION_H
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (C) 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _LIBFM_QT_GLOBALS_
|
|
||||||
#define _LIBFM_QT_GLOBALS_
|
|
||||||
|
|
||||||
#include <QtGlobal>
|
|
||||||
|
|
||||||
#ifdef LIBFM_QT_COMPILATION
|
|
||||||
#define LIBFM_QT_API Q_DECL_EXPORT
|
|
||||||
#else
|
|
||||||
#define LIBFM_QT_API Q_DECL_IMPORT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,205 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>MountOperationPasswordDialog</class>
|
|
||||||
<widget class="QDialog" name="MountOperationPasswordDialog">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>244</width>
|
|
||||||
<height>302</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Mount</string>
|
|
||||||
</property>
|
|
||||||
<property name="windowIcon">
|
|
||||||
<iconset theme="dialog-password"/>
|
|
||||||
</property>
|
|
||||||
<property name="sizeGripEnabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="modal">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="message">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="Anonymous">
|
|
||||||
<property name="text">
|
|
||||||
<string>Connect &anonymously</string>
|
|
||||||
</property>
|
|
||||||
<attribute name="buttonGroup">
|
|
||||||
<string notr="true">usernameGroup</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="asUser">
|
|
||||||
<property name="text">
|
|
||||||
<string>Connect as u&ser:</string>
|
|
||||||
</property>
|
|
||||||
<attribute name="buttonGroup">
|
|
||||||
<string notr="true">usernameGroup</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLineEdit" name="username"/>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>&Username:</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>username</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QLineEdit" name="password">
|
|
||||||
<property name="echoMode">
|
|
||||||
<enum>QLineEdit::Password</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>&Password:</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>password</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="domainLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Domain:</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>domain</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QLineEdit" name="domain"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="forgetPassword">
|
|
||||||
<property name="text">
|
|
||||||
<string>Forget password &immediately</string>
|
|
||||||
</property>
|
|
||||||
<attribute name="buttonGroup">
|
|
||||||
<string notr="true">passwordGroup</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="sessionPassword">
|
|
||||||
<property name="text">
|
|
||||||
<string>Remember password until you &logout</string>
|
|
||||||
</property>
|
|
||||||
<attribute name="buttonGroup">
|
|
||||||
<string notr="true">passwordGroup</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="storePassword">
|
|
||||||
<property name="text">
|
|
||||||
<string>Remember &forever</string>
|
|
||||||
</property>
|
|
||||||
<attribute name="buttonGroup">
|
|
||||||
<string notr="true">passwordGroup</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>accepted()</signal>
|
|
||||||
<receiver>MountOperationPasswordDialog</receiver>
|
|
||||||
<slot>accept()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>248</x>
|
|
||||||
<y>254</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>157</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>rejected()</signal>
|
|
||||||
<receiver>MountOperationPasswordDialog</receiver>
|
|
||||||
<slot>reject()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>316</x>
|
|
||||||
<y>260</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>286</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
</connections>
|
|
||||||
<buttongroups>
|
|
||||||
<buttongroup name="usernameGroup"/>
|
|
||||||
<buttongroup name="passwordGroup"/>
|
|
||||||
</buttongroups>
|
|
||||||
</ui>
|
|
||||||
@ -1,227 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 - 2014 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "mountoperation.h"
|
|
||||||
#include <glib/gi18n.h> // for _()
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QEventLoop>
|
|
||||||
#include "mountoperationpassworddialog_p.h"
|
|
||||||
#include "mountoperationquestiondialog_p.h"
|
|
||||||
#include "ui_mount-operation-password.h"
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
MountOperation::MountOperation(bool interactive, QWidget* parent):
|
|
||||||
QObject(parent),
|
|
||||||
interactive_(interactive),
|
|
||||||
running(false),
|
|
||||||
op(g_mount_operation_new()),
|
|
||||||
cancellable_(g_cancellable_new()),
|
|
||||||
eventLoop(NULL),
|
|
||||||
autoDestroy_(true) {
|
|
||||||
|
|
||||||
g_signal_connect(op, "ask-password", G_CALLBACK(onAskPassword), this);
|
|
||||||
g_signal_connect(op, "ask-question", G_CALLBACK(onAskQuestion), this);
|
|
||||||
// g_signal_connect(op, "reply", G_CALLBACK(onReply), this);
|
|
||||||
|
|
||||||
#if GLIB_CHECK_VERSION(2, 20, 0)
|
|
||||||
g_signal_connect(op, "aborted", G_CALLBACK(onAbort), this);
|
|
||||||
#endif
|
|
||||||
#if GLIB_CHECK_VERSION(2, 22, 0)
|
|
||||||
g_signal_connect(op, "show-processes", G_CALLBACK(onShowProcesses), this);
|
|
||||||
#endif
|
|
||||||
#if GLIB_CHECK_VERSION(2, 34, 0)
|
|
||||||
g_signal_connect(op, "show-unmount-progress", G_CALLBACK(onShowUnmountProgress), this);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
MountOperation::~MountOperation() {
|
|
||||||
qDebug("delete MountOperation");
|
|
||||||
if(cancellable_) {
|
|
||||||
cancel();
|
|
||||||
g_object_unref(cancellable_);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(eventLoop) { // if wait() is called to block the main loop, but the event loop is still running
|
|
||||||
// NOTE: is this possible?
|
|
||||||
eventLoop->exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(op) {
|
|
||||||
g_signal_handlers_disconnect_by_func(op, (gpointer)G_CALLBACK(onAskPassword), this);
|
|
||||||
g_signal_handlers_disconnect_by_func(op, (gpointer)G_CALLBACK(onAskQuestion), this);
|
|
||||||
#if GLIB_CHECK_VERSION(2, 20, 0)
|
|
||||||
g_signal_handlers_disconnect_by_func(op, (gpointer)G_CALLBACK(onAbort), this);
|
|
||||||
#endif
|
|
||||||
#if GLIB_CHECK_VERSION(2, 22, 0)
|
|
||||||
g_signal_handlers_disconnect_by_func(op, (gpointer)G_CALLBACK(onShowProcesses), this);
|
|
||||||
#endif
|
|
||||||
#if GLIB_CHECK_VERSION(2, 34, 0)
|
|
||||||
g_signal_handlers_disconnect_by_func(op, (gpointer)G_CALLBACK(onShowUnmountProgress), this);
|
|
||||||
#endif
|
|
||||||
g_object_unref(op);
|
|
||||||
}
|
|
||||||
// qDebug("MountOperation deleted");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MountOperation::onAbort(GMountOperation* _op, MountOperation* pThis) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void MountOperation::onAskPassword(GMountOperation* _op, gchar* message, gchar* default_user, gchar* default_domain, GAskPasswordFlags flags, MountOperation* pThis) {
|
|
||||||
qDebug("ask password");
|
|
||||||
MountOperationPasswordDialog dlg(pThis, flags);
|
|
||||||
dlg.setMessage(QString::fromUtf8(message));
|
|
||||||
dlg.setDefaultUser(QString::fromUtf8(default_user));
|
|
||||||
dlg.setDefaultDomain(QString::fromUtf8(default_domain));
|
|
||||||
dlg.exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MountOperation::onAskQuestion(GMountOperation* _op, gchar* message, GStrv choices, MountOperation* pThis) {
|
|
||||||
qDebug("ask question");
|
|
||||||
MountOperationQuestionDialog dialog(pThis, message, choices);
|
|
||||||
dialog.exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
void MountOperation::onReply(GMountOperation* _op, GMountOperationResult result, MountOperation* pThis) {
|
|
||||||
qDebug("reply");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
void MountOperation::onShowProcesses(GMountOperation* _op, gchar* message, GArray* processes, GStrv choices, MountOperation* pThis) {
|
|
||||||
qDebug("show processes");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MountOperation::onShowUnmountProgress(GMountOperation* _op, gchar* message, gint64 time_left, gint64 bytes_left, MountOperation* pThis) {
|
|
||||||
qDebug("show unmount progress");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MountOperation::onEjectMountFinished(GMount* mount, GAsyncResult* res, QPointer< MountOperation >* pThis) {
|
|
||||||
if(*pThis) {
|
|
||||||
GError* error = NULL;
|
|
||||||
g_mount_eject_with_operation_finish(mount, res, &error);
|
|
||||||
(*pThis)->handleFinish(error);
|
|
||||||
}
|
|
||||||
delete pThis;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MountOperation::onEjectVolumeFinished(GVolume* volume, GAsyncResult* res, QPointer< MountOperation >* pThis) {
|
|
||||||
if(*pThis) {
|
|
||||||
GError* error = NULL;
|
|
||||||
g_volume_eject_with_operation_finish(volume, res, &error);
|
|
||||||
(*pThis)->handleFinish(error);
|
|
||||||
}
|
|
||||||
delete pThis;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MountOperation::onMountFileFinished(GFile* file, GAsyncResult* res, QPointer< MountOperation >* pThis) {
|
|
||||||
if(*pThis) {
|
|
||||||
GError* error = NULL;
|
|
||||||
g_file_mount_enclosing_volume_finish(file, res, &error);
|
|
||||||
(*pThis)->handleFinish(error);
|
|
||||||
}
|
|
||||||
delete pThis;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MountOperation::onMountVolumeFinished(GVolume* volume, GAsyncResult* res, QPointer< MountOperation >* pThis) {
|
|
||||||
if(*pThis) {
|
|
||||||
GError* error = NULL;
|
|
||||||
g_volume_mount_finish(volume, res, &error);
|
|
||||||
(*pThis)->handleFinish(error);
|
|
||||||
}
|
|
||||||
delete pThis;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MountOperation::onUnmountMountFinished(GMount* mount, GAsyncResult* res, QPointer< MountOperation >* pThis) {
|
|
||||||
if(*pThis) {
|
|
||||||
GError* error = NULL;
|
|
||||||
g_mount_unmount_with_operation_finish(mount, res, &error);
|
|
||||||
(*pThis)->handleFinish(error);
|
|
||||||
}
|
|
||||||
delete pThis;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MountOperation::handleFinish(GError* error) {
|
|
||||||
qDebug("operation finished: %p", error);
|
|
||||||
if(error) {
|
|
||||||
bool showError = interactive_;
|
|
||||||
if(error->domain == G_IO_ERROR) {
|
|
||||||
if(error->code == G_IO_ERROR_FAILED) {
|
|
||||||
// Generate a more human-readable error message instead of using a gvfs one.
|
|
||||||
// The original error message is something like:
|
|
||||||
// Error unmounting: umount exited with exit code 1:
|
|
||||||
// helper failed with: umount: only root can unmount
|
|
||||||
// UUID=18cbf00c-e65f-445a-bccc-11964bdea05d from /media/sda4 */
|
|
||||||
// Why they pass this back to us? This is not human-readable for the users at all.
|
|
||||||
if(strstr(error->message, "only root can ")) {
|
|
||||||
g_free(error->message);
|
|
||||||
error->message = g_strdup(_("Only system administrators have the permission to do this."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(error->code == G_IO_ERROR_FAILED_HANDLED)
|
|
||||||
showError = false;
|
|
||||||
}
|
|
||||||
if(showError)
|
|
||||||
QMessageBox::critical(NULL, QObject::tr("Error"), QString::fromUtf8(error->message));
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_EMIT finished(error);
|
|
||||||
|
|
||||||
if(eventLoop) { // if wait() is called to block the main loop
|
|
||||||
eventLoop->exit(error != NULL ? 1 : 0);
|
|
||||||
eventLoop = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(error)
|
|
||||||
g_error_free(error);
|
|
||||||
|
|
||||||
// free ourself here!!
|
|
||||||
if(autoDestroy_)
|
|
||||||
deleteLater();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MountOperation::prepareUnmount(GMount* mount) {
|
|
||||||
/* ensure that CWD is not on the mounted filesystem. */
|
|
||||||
char* cwd_str = g_get_current_dir();
|
|
||||||
GFile* cwd = g_file_new_for_path(cwd_str);
|
|
||||||
GFile* root = g_mount_get_root(mount);
|
|
||||||
g_free(cwd_str);
|
|
||||||
/* FIXME: This cannot cover 100% cases since symlinks are not checked.
|
|
||||||
* There may be other cases that cwd is actually under mount root
|
|
||||||
* but checking prefix is not enough. We already did our best, though. */
|
|
||||||
if(g_file_has_prefix(cwd, root))
|
|
||||||
g_chdir("/");
|
|
||||||
g_object_unref(cwd);
|
|
||||||
g_object_unref(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
// block the operation used an internal QEventLoop and returns
|
|
||||||
// only after the whole operation is finished.
|
|
||||||
bool MountOperation::wait() {
|
|
||||||
QEventLoop loop;
|
|
||||||
eventLoop = &loop;
|
|
||||||
int exitCode = loop.exec();
|
|
||||||
return exitCode == 0 ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Fm
|
|
||||||
@ -1,155 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FM_MOUNTOPERATION_H
|
|
||||||
#define FM_MOUNTOPERATION_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QDialog>
|
|
||||||
#include <libfm/fm.h>
|
|
||||||
#include <gio/gio.h>
|
|
||||||
#include <QPointer>
|
|
||||||
|
|
||||||
class QEventLoop;
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
// FIXME: the original APIs in gtk+ version of libfm for mounting devices is poor.
|
|
||||||
// Need to find a better API design which make things fully async and cancellable.
|
|
||||||
|
|
||||||
// FIXME: parent_ does not work. All dialogs shown by the mount operation has no parent window assigned.
|
|
||||||
// FIXME: Need to reconsider the propery way of API design. Blocking sync calls are handy, but
|
|
||||||
// indeed causes some problems. :-(
|
|
||||||
|
|
||||||
class LIBFM_QT_API MountOperation: public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit MountOperation(bool interactive = true, QWidget* parent = 0);
|
|
||||||
~MountOperation();
|
|
||||||
|
|
||||||
void mount(FmPath* path) {
|
|
||||||
GFile* gf = fm_path_to_gfile(path);
|
|
||||||
g_file_mount_enclosing_volume(gf, G_MOUNT_MOUNT_NONE, op, cancellable_, (GAsyncReadyCallback)onMountFileFinished, new QPointer<MountOperation>(this));
|
|
||||||
g_object_unref(gf);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mount(GVolume* volume) {
|
|
||||||
g_volume_mount(volume, G_MOUNT_MOUNT_NONE, op, cancellable_, (GAsyncReadyCallback)onMountVolumeFinished, new QPointer<MountOperation>(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
void unmount(GMount* mount) {
|
|
||||||
prepareUnmount(mount);
|
|
||||||
g_mount_unmount_with_operation(mount, G_MOUNT_UNMOUNT_NONE, op, cancellable_, (GAsyncReadyCallback)onUnmountMountFinished, new QPointer<MountOperation>(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
void unmount(GVolume* volume) {
|
|
||||||
GMount* mount = g_volume_get_mount(volume);
|
|
||||||
if(!mount)
|
|
||||||
return;
|
|
||||||
unmount(mount);
|
|
||||||
g_object_unref(mount);
|
|
||||||
}
|
|
||||||
|
|
||||||
void eject(GMount* mount) {
|
|
||||||
prepareUnmount(mount);
|
|
||||||
g_mount_eject_with_operation(mount, G_MOUNT_UNMOUNT_NONE, op, cancellable_, (GAsyncReadyCallback)onEjectMountFinished, new QPointer<MountOperation>(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
void eject(GVolume* volume) {
|
|
||||||
GMount* mnt = g_volume_get_mount(volume);
|
|
||||||
prepareUnmount(mnt);
|
|
||||||
g_object_unref(mnt);
|
|
||||||
g_volume_eject_with_operation(volume, G_MOUNT_UNMOUNT_NONE, op, cancellable_, (GAsyncReadyCallback)onEjectVolumeFinished, new QPointer<MountOperation>(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget* parent() const {
|
|
||||||
return parent_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setParent(QWidget* parent) {
|
|
||||||
parent_ = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
GCancellable* cancellable() const {
|
|
||||||
return cancellable_;
|
|
||||||
}
|
|
||||||
|
|
||||||
GMountOperation* mountOperation() {
|
|
||||||
return op;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cancel() {
|
|
||||||
g_cancellable_cancel(cancellable_);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isRunning() const {
|
|
||||||
return running;
|
|
||||||
}
|
|
||||||
|
|
||||||
// block the operation used an internal QEventLoop and returns
|
|
||||||
// only after the whole operation is finished.
|
|
||||||
bool wait();
|
|
||||||
|
|
||||||
bool autoDestroy() {
|
|
||||||
return autoDestroy_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setAutoDestroy(bool destroy = true) {
|
|
||||||
autoDestroy_ = destroy;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void finished(GError* error = NULL);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void prepareUnmount(GMount* mount);
|
|
||||||
|
|
||||||
static void onAskPassword(GMountOperation *_op, gchar* message, gchar* default_user, gchar* default_domain, GAskPasswordFlags flags, MountOperation* pThis);
|
|
||||||
static void onAskQuestion(GMountOperation *_op, gchar* message, GStrv choices, MountOperation* pThis);
|
|
||||||
// static void onReply(GMountOperation *_op, GMountOperationResult result, MountOperation* pThis);
|
|
||||||
|
|
||||||
static void onAbort(GMountOperation *_op, MountOperation* pThis);
|
|
||||||
static void onShowProcesses(GMountOperation *_op, gchar* message, GArray* processes, GStrv choices, MountOperation* pThis);
|
|
||||||
static void onShowUnmountProgress(GMountOperation *_op, gchar* message, gint64 time_left, gint64 bytes_left, MountOperation* pThis);
|
|
||||||
|
|
||||||
// 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 onMountVolumeFinished(GVolume* volume, 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 onEjectVolumeFinished(GVolume* volume, GAsyncResult *res, QPointer<MountOperation>* pThis);
|
|
||||||
|
|
||||||
void handleFinish(GError* error);
|
|
||||||
|
|
||||||
private:
|
|
||||||
GMountOperation* op;
|
|
||||||
GCancellable* cancellable_;
|
|
||||||
QWidget* parent_;
|
|
||||||
bool running;
|
|
||||||
bool interactive_;
|
|
||||||
QEventLoop* eventLoop;
|
|
||||||
bool autoDestroy_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_MOUNTOPERATION_H
|
|
||||||
@ -1,125 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "mountoperationpassworddialog_p.h"
|
|
||||||
#include "ui_mount-operation-password.h"
|
|
||||||
#include "mountoperation.h"
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
MountOperationPasswordDialog::MountOperationPasswordDialog(MountOperation* op, GAskPasswordFlags flags):
|
|
||||||
QDialog(),
|
|
||||||
mountOperation(op),
|
|
||||||
canAnonymous(flags & G_ASK_PASSWORD_ANONYMOUS_SUPPORTED ? true : false),
|
|
||||||
canSavePassword(flags & G_ASK_PASSWORD_SAVING_SUPPORTED ? true : false),
|
|
||||||
needUserName(flags & G_ASK_PASSWORD_NEED_USERNAME ? true : false),
|
|
||||||
needPassword(flags & G_ASK_PASSWORD_NEED_PASSWORD ? true : false),
|
|
||||||
needDomain(flags & G_ASK_PASSWORD_NEED_DOMAIN ? true : false) {
|
|
||||||
|
|
||||||
ui = new Ui::MountOperationPasswordDialog();
|
|
||||||
ui->setupUi(this);
|
|
||||||
|
|
||||||
// change the text of Ok button to Connect
|
|
||||||
ui->buttonBox->buttons().first()->setText(tr("&Connect"));
|
|
||||||
connect(ui->Anonymous, &QAbstractButton::toggled, this, &MountOperationPasswordDialog::onAnonymousToggled);
|
|
||||||
|
|
||||||
if(canAnonymous) {
|
|
||||||
// select ananymous by default if applicable.
|
|
||||||
ui->Anonymous->setChecked(true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ui->Anonymous->setEnabled(false);
|
|
||||||
}
|
|
||||||
if(!needUserName) {
|
|
||||||
ui->username->setEnabled(false);
|
|
||||||
}
|
|
||||||
if(!needPassword) {
|
|
||||||
ui->password->setEnabled(false);
|
|
||||||
}
|
|
||||||
if(!needDomain) {
|
|
||||||
ui->domain->hide();
|
|
||||||
ui->domainLabel->hide();
|
|
||||||
}
|
|
||||||
if(canSavePassword) {
|
|
||||||
ui->sessionPassword->setChecked(true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ui->storePassword->setEnabled(false);
|
|
||||||
ui->sessionPassword->setEnabled(false);
|
|
||||||
ui->forgetPassword->setChecked(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MountOperationPasswordDialog::~MountOperationPasswordDialog() {
|
|
||||||
delete ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MountOperationPasswordDialog::onAnonymousToggled(bool checked) {
|
|
||||||
// disable username/password entries if anonymous mode is used
|
|
||||||
bool useUserPassword = !checked;
|
|
||||||
if(needUserName)
|
|
||||||
ui->username->setEnabled(useUserPassword);
|
|
||||||
if(needPassword)
|
|
||||||
ui->password->setEnabled(useUserPassword);
|
|
||||||
if(needDomain)
|
|
||||||
ui->domain->setEnabled(useUserPassword);
|
|
||||||
|
|
||||||
if(canSavePassword) {
|
|
||||||
ui->forgetPassword->setEnabled(useUserPassword);
|
|
||||||
ui->sessionPassword->setEnabled(useUserPassword);
|
|
||||||
ui->storePassword->setEnabled(useUserPassword);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MountOperationPasswordDialog::setMessage(QString message) {
|
|
||||||
ui->message->setText(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MountOperationPasswordDialog::setDefaultDomain(QString domain) {
|
|
||||||
ui->domain->setText(domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MountOperationPasswordDialog::setDefaultUser(QString user) {
|
|
||||||
ui->username->setText(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MountOperationPasswordDialog::done(int r) {
|
|
||||||
GMountOperation* gmop = mountOperation->mountOperation();
|
|
||||||
|
|
||||||
if(r == QDialog::Accepted) {
|
|
||||||
|
|
||||||
if(needUserName)
|
|
||||||
g_mount_operation_set_username(gmop, ui->username->text().toUtf8());
|
|
||||||
if(needDomain)
|
|
||||||
g_mount_operation_set_domain(gmop, ui->domain->text().toUtf8());
|
|
||||||
if(needPassword)
|
|
||||||
g_mount_operation_set_password(gmop, ui->password->text().toUtf8());
|
|
||||||
if(canAnonymous)
|
|
||||||
g_mount_operation_set_anonymous(gmop, ui->Anonymous->isChecked());
|
|
||||||
|
|
||||||
g_mount_operation_reply(gmop, G_MOUNT_OPERATION_HANDLED);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
g_mount_operation_reply(gmop, G_MOUNT_OPERATION_ABORTED);
|
|
||||||
}
|
|
||||||
QDialog::done(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Fm
|
|
||||||
@ -1,64 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FM_MOUNTOPERATIONPASSWORDDIALOG_H
|
|
||||||
#define FM_MOUNTOPERATIONPASSWORDDIALOG_H
|
|
||||||
|
|
||||||
#include "libfmqtglobals.h"
|
|
||||||
#include <QDialog>
|
|
||||||
#include <gio/gio.h>
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class MountOperationPasswordDialog;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace Fm {
|
|
||||||
|
|
||||||
class MountOperation;
|
|
||||||
|
|
||||||
class MountOperationPasswordDialog : public QDialog {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit MountOperationPasswordDialog(MountOperation* op, GAskPasswordFlags flags);
|
|
||||||
virtual ~MountOperationPasswordDialog();
|
|
||||||
|
|
||||||
void setMessage(QString message);
|
|
||||||
void setDefaultUser(QString user);
|
|
||||||
void setDefaultDomain(QString domain);
|
|
||||||
|
|
||||||
virtual void done(int r);
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
|
||||||
void onAnonymousToggled(bool checked);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::MountOperationPasswordDialog* ui;
|
|
||||||
MountOperation* mountOperation;
|
|
||||||
bool needPassword;
|
|
||||||
bool needUserName;
|
|
||||||
bool needDomain;
|
|
||||||
bool canSavePassword;
|
|
||||||
bool canAnonymous;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FM_MOUNTOPERATIONPASSWORDDIALOG_H
|
|
||||||
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