initial import of ark
4
ark/.reviewboardrc
Normal file
|
@ -0,0 +1,4 @@
|
|||
REPOSITORY = "git://anongit.kde.org/ark"
|
||||
REVIEWBOARD_URL = "https://git.reviewboard.kde.org"
|
||||
TARGET_GROUPS = "kdeutils"
|
||||
TARGET_PEOPLE = "rkcosta"
|
50
ark/CMakeLists.txt
Normal file
|
@ -0,0 +1,50 @@
|
|||
project(ark)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
find_package(KDE4)
|
||||
include( KDE4Defaults )
|
||||
include_directories(${KDE4_INCLUDES})
|
||||
|
||||
add_definitions(${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
|
||||
add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS)
|
||||
|
||||
# If definitions like -D_GNU_SOURCE are needed for these checks they
|
||||
# should be added to _KDE4_PLATFORM_DEFINITIONS when it is originally
|
||||
# defined outside this file. Here we include these definitions in
|
||||
# CMAKE_REQUIRED_DEFINITIONS so they will be included in the build of
|
||||
# checks below.
|
||||
set( CMAKE_REQUIRED_DEFINITIONS ${_KDE4_PLATFORM_DEFINITIONS} )
|
||||
endif()
|
||||
|
||||
include( MacroLibrary )
|
||||
list(APPEND CMAKE_MODULE_PATH ${ark_SOURCE_DIR}/cmake/modules)
|
||||
|
||||
macro_optional_find_package(LibArchive)
|
||||
macro_log_feature(LIBARCHIVE_FOUND "LibArchive" "A library for dealing with a wide variety of archive file formats" "http://code.google.com/p/libarchive/" FALSE "" "Required for among others tar, tar.gz, tar.bz2 formats in Ark.")
|
||||
|
||||
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CTestCustom.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake)
|
||||
|
||||
add_definitions(-DQT_NO_CAST_FROM_ASCII)
|
||||
|
||||
option(WITH_TEST_COVERAGE "Build with test coverage support" OFF)
|
||||
if (WITH_TEST_COVERAGE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
|
||||
endif (WITH_TEST_COVERAGE)
|
||||
|
||||
set(SUPPORTED_ARK_MIMETYPES "")
|
||||
|
||||
add_subdirectory(plugins)
|
||||
add_subdirectory(kerfuffle)
|
||||
add_subdirectory(part)
|
||||
add_subdirectory(app)
|
||||
add_subdirectory(doc)
|
||||
|
||||
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
message(STATUS "Supported MIME types: ${SUPPORTED_ARK_MIMETYPES}")
|
||||
macro_display_feature_log()
|
||||
endif(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
|
346
ark/COPYING
Normal file
|
@ -0,0 +1,346 @@
|
|||
NOTE! The GPL below is copyrighted by the Free Software Foundation, but
|
||||
the instance of code that it refers to (the kde programs) are copyrighted
|
||||
by the authors who actually wrote it.
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
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 Library 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
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
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
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
216
ark/COPYING.icons
Normal file
|
@ -0,0 +1,216 @@
|
|||
The Oxygen Icon Theme
|
||||
Copyright (C) 2007 Nuno Pinheiro <nuno@oxygen-icons.org>
|
||||
Copyright (C) 2007 David Vignoni <david@icon-king.com>
|
||||
Copyright (C) 2007 David Miller <miller@oxygen-icons.org>
|
||||
Copyright (C) 2007 Johann Ollivier Lapeyre <johann@oxygen-icons.org>
|
||||
Copyright (C) 2007 Kenneth Wimer <kwwii@bootsplash.org>
|
||||
Copyright (C) 2007 Riccardo Iaconelli <riccardo@oxygen-icons.org>
|
||||
|
||||
|
||||
and others
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Clarification:
|
||||
|
||||
The GNU Lesser General Public License or LGPL is written for
|
||||
software libraries in the first place. We expressly want the LGPL to
|
||||
be valid for this artwork library too.
|
||||
|
||||
KDE Oxygen theme icons is a special kind of software library, it is an
|
||||
artwork library, it's elements can be used in a Graphical User Interface, or
|
||||
GUI.
|
||||
|
||||
Source code, for this library means:
|
||||
- where they exist, SVG;
|
||||
- otherwise, if applicable, the multi-layered formats xcf or psd, or
|
||||
otherwise png.
|
||||
|
||||
The LGPL in some sections obliges you to make the files carry
|
||||
notices. With images this is in some cases impossible or hardly useful.
|
||||
|
||||
With this library a notice is placed at a prominent place in the directory
|
||||
containing the elements. You may follow this practice.
|
||||
|
||||
The exception in section 5 of the GNU Lesser General Public License covers
|
||||
the use of elements of this art library in a GUI.
|
||||
|
||||
kde-artists [at] kde.org
|
||||
|
||||
-----
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser 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
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
13
ark/CTestConfig.cmake
Normal file
|
@ -0,0 +1,13 @@
|
|||
## This file should be placed in the root directory of your project.
|
||||
## Then modify the CMakeLists.txt file in the root directory of your
|
||||
## project to incorporate the testing dashboard.
|
||||
## # The following are required to uses Dart and the Cdash dashboard
|
||||
## ENABLE_TESTING()
|
||||
## INCLUDE(CTest)
|
||||
set(CTEST_PROJECT_NAME "ark")
|
||||
set(CTEST_NIGHTLY_START_TIME "20:00:00 CET")
|
||||
|
||||
set(CTEST_DROP_METHOD "http")
|
||||
set(CTEST_DROP_SITE "my.cdash.org")
|
||||
set(CTEST_DROP_LOCATION "/submit.php?project=ark")
|
||||
set(CTEST_DROP_SITE_CDASH TRUE)
|
1
ark/CTestCustom.cmake.in
Normal file
|
@ -0,0 +1 @@
|
|||
set(CTEST_CUSTOM_COVERAGE_EXCLUDE ".moc$" "moc_" "ui_")
|
52
ark/HACKING
Normal file
|
@ -0,0 +1,52 @@
|
|||
== Coding Style ==
|
||||
Ark follows the kdelibs/Qt coding style. For more information about them,
|
||||
please see:
|
||||
|
||||
- http://techbase.kde.org/Policies/Kdelibs_Coding_Style
|
||||
- http://wiki.qt-project.org/Coding_Style
|
||||
- http://wiki.qt-project.org/Coding_Conventions
|
||||
|
||||
== Sending patches ==
|
||||
To send patches for Ark, you can either use git's send-email command and send
|
||||
it to the kde-utils-devel@kde.org mailing list, or use KDE's ReviewBoard tool
|
||||
in <https://git.reviewboard.kde.org>. In case you choose the latter, the
|
||||
review should be sent for the Ark product, and the `kdeutils' group should be
|
||||
added to the review request.
|
||||
|
||||
If you already have a KDE commit account, it is still preferrable to contact
|
||||
the maintainer instead of committing directly, at least to be a good citizen
|
||||
and especially so that git mistakes are not made (see the `Using git' section).
|
||||
|
||||
== Using git ==
|
||||
The development model adopted by Ark is simple and rely on git's easy merging
|
||||
and branching capabilities. If in doubt, do not hesitate to ask!
|
||||
|
||||
First of all, you should do your work in a separate branch, and each commit
|
||||
should be as atomic as possible. This way, if you are asked to make changes to
|
||||
them, the rest of your work is not disturbed and you can easily rebase.
|
||||
|
||||
New features are committed to the `master' branch, respecting KDE's Release
|
||||
Schedule policies. This means the soft and hard freeze periods must be
|
||||
respected, as well as the string freeze policy.
|
||||
|
||||
Bug fixes are committed to the latest stable branch (for example, KDE/4.8),
|
||||
which is then merged into the `master' branch. Do *NOT* cherry-pick commits
|
||||
into multiple branches! It makes following history unnecessarily harder for no
|
||||
reason.
|
||||
|
||||
To merge the stable branch into `master', the following steps can be followed:
|
||||
|
||||
$ git checkout KDE/4.8 # Whatever the stable branch is
|
||||
$ # hack, hack, hack
|
||||
$ # commit
|
||||
$ git checkout master
|
||||
$ git merge --log --edit -s recursive -Xours KDE/4.8
|
||||
|
||||
Do not worry if unrelated commits (such as translation ones made by KDE's
|
||||
translation infrastructure) are also merged: translation commits are
|
||||
automatically reverted when needed, and other commits being merged should be
|
||||
bug fixes by definition.
|
||||
|
||||
When committing your changes, do *NOT* create unnecessary merge commits with
|
||||
`git pull', as these commits are completely avoidable and make following
|
||||
history harder. If you are committing your changes, *rebase* first.
|
8
ark/Mainpage.dox
Normal file
|
@ -0,0 +1,8 @@
|
|||
/** @mainpage ark
|
||||
|
||||
The ark application
|
||||
|
||||
*/
|
||||
|
||||
// DOXYGEN_REFERENCES = kdecore
|
||||
// DOXYGEN_SET_PROJECT_NAME = ark
|
6
ark/Messages.sh
Normal file
|
@ -0,0 +1,6 @@
|
|||
#! /bin/sh
|
||||
$EXTRACTRC $(find . -name '*.rc') >> rc.cpp || exit 11
|
||||
$EXTRACTRC $(find . -name '*.ui') >> rc.cpp || exit 12
|
||||
$EXTRACTRC $(find . -name '*.kcfg') >> rc.cpp
|
||||
$XGETTEXT app/*.cpp kerfuffle/*.cpp part/*.cpp plugins/*/*.cpp rc.cpp -o $podir/ark.pot
|
||||
rm -f rc.cpp
|
50
ark/app/CMakeLists.txt
Normal file
|
@ -0,0 +1,50 @@
|
|||
add_subdirectory(icons)
|
||||
|
||||
set(ark_SRCS
|
||||
batchextract.cpp
|
||||
main.cpp
|
||||
mainwindow.cpp
|
||||
)
|
||||
|
||||
# For Mac and Windows.
|
||||
kde4_add_app_icon(ark_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/icons/hi*-apps-ark.png")
|
||||
|
||||
kde4_add_executable( ark ${ark_SRCS} )
|
||||
|
||||
target_link_libraries( ark kerfuffle ${KDE4_KFILE_LIBS} ${KDE4_KPARTS_LIBS} )
|
||||
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ark.desktop.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ark.desktop
|
||||
)
|
||||
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ark_dndextract.desktop.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ark_dndextract.desktop
|
||||
)
|
||||
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ark_servicemenu.desktop.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ark_servicemenu.desktop
|
||||
)
|
||||
|
||||
install( TARGETS ark ${INSTALL_TARGETS_DEFAULT_ARGS} )
|
||||
install(FILES ark_addtoservicemenu.desktop ${CMAKE_CURRENT_BINARY_DIR}/ark_servicemenu.desktop DESTINATION ${SERVICES_INSTALL_DIR}/ServiceMenus)
|
||||
install( PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/ark.desktop DESTINATION ${XDG_APPS_INSTALL_DIR} )
|
||||
install( FILES ${CMAKE_CURRENT_SOURCE_DIR}/ark.appdata.xml DESTINATION share/appdata )
|
||||
install( FILES arkui.rc DESTINATION ${DATA_INSTALL_DIR}/ark )
|
||||
|
||||
########### konqueror ark_extract_here plugin ###############
|
||||
macro_optional_find_package( LibKonq )
|
||||
macro_log_feature( LIBKONQ_FOUND "LIBKONQ" "libkonq library" "kdebase" FALSE "" "Need to integrate in konqueror" )
|
||||
|
||||
|
||||
if (LIBKONQ_FOUND)
|
||||
set(extracthere_SRCS batchextract.cpp extractHereDndPlugin.cpp)
|
||||
kde4_add_plugin(extracthere WITH_PREFIX ${extracthere_SRCS})
|
||||
target_link_libraries(extracthere kerfuffle ${KDE4_KDECORE_LIBS} ${KDE4_KPARTS_LIBS} ${KDE4_KFILE_LIBS} ${LIBKONQ_LIBRARY} )
|
||||
include_directories(${LIBKONQ_INCLUDE_DIR})
|
||||
install( TARGETS extracthere DESTINATION ${PLUGIN_INSTALL_DIR} )
|
||||
install( FILES ${CMAKE_CURRENT_BINARY_DIR}/ark_dndextract.desktop DESTINATION ${SERVICES_INSTALL_DIR} )
|
||||
endif (LIBKONQ_FOUND)
|
||||
|
226
ark/app/ark.appdata.xml
Normal file
|
@ -0,0 +1,226 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<component type="desktop">
|
||||
<id>ark.desktop</id>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>GPL-2.0+</project_license>
|
||||
<name>Ark</name>
|
||||
<name xml:lang="ar">آرك</name>
|
||||
<name xml:lang="bg">Ark</name>
|
||||
<name xml:lang="ca">Ark</name>
|
||||
<name xml:lang="cs">Ark</name>
|
||||
<name xml:lang="da">Ark</name>
|
||||
<name xml:lang="de">Ark</name>
|
||||
<name xml:lang="en-GB">Ark</name>
|
||||
<name xml:lang="es">Ark</name>
|
||||
<name xml:lang="et">Ark</name>
|
||||
<name xml:lang="fi">Ark</name>
|
||||
<name xml:lang="fr">Ark</name>
|
||||
<name xml:lang="hu">Ark</name>
|
||||
<name xml:lang="it">Ark</name>
|
||||
<name xml:lang="ko">Ark</name>
|
||||
<name xml:lang="lt">Ark</name>
|
||||
<name xml:lang="nb">Ark</name>
|
||||
<name xml:lang="nds">Ark</name>
|
||||
<name xml:lang="nl">Ark</name>
|
||||
<name xml:lang="pl">Ark</name>
|
||||
<name xml:lang="pt">Ark</name>
|
||||
<name xml:lang="pt-BR">Ark</name>
|
||||
<name xml:lang="sk">Ark</name>
|
||||
<name xml:lang="sl">Ark</name>
|
||||
<name xml:lang="sr">Арк</name>
|
||||
<name xml:lang="sr-Latn">Ark</name>
|
||||
<name xml:lang="sr-ijekavian">Арк</name>
|
||||
<name xml:lang="sr-ijekavianlatin">Ark</name>
|
||||
<name xml:lang="sv">Ark</name>
|
||||
<name xml:lang="tr">Ark</name>
|
||||
<name xml:lang="uk">Ark</name>
|
||||
<name xml:lang="x-test">xxArkxx</name>
|
||||
<name xml:lang="zh-CN">Ark</name>
|
||||
<name xml:lang="zh-TW">檔案壓縮_Ark</name>
|
||||
<summary>Archiving Tool</summary>
|
||||
<summary xml:lang="ar">أداة أرشفة</summary>
|
||||
<summary xml:lang="bg">Работа с архиви</summary>
|
||||
<summary xml:lang="ca">Eina d'arxivament</summary>
|
||||
<summary xml:lang="cs">Archivační nástroj</summary>
|
||||
<summary xml:lang="da">Arkiveringsværktøj</summary>
|
||||
<summary xml:lang="de">Archivprogramm</summary>
|
||||
<summary xml:lang="en-GB">Archiving Tool</summary>
|
||||
<summary xml:lang="es">Herramienta de archivado</summary>
|
||||
<summary xml:lang="et">Arhiivide haldamise rakendus</summary>
|
||||
<summary xml:lang="fi">Pakkausohjelma</summary>
|
||||
<summary xml:lang="fr">Outil d'archivage</summary>
|
||||
<summary xml:lang="hu">Fájltömörítő</summary>
|
||||
<summary xml:lang="it">Strumento di archiviazione</summary>
|
||||
<summary xml:lang="ko">압축 도구</summary>
|
||||
<summary xml:lang="lt">Archyvavimo įrankis</summary>
|
||||
<summary xml:lang="nb">Arkiveringsverktøy</summary>
|
||||
<summary xml:lang="nds">Archievwarktüüch</summary>
|
||||
<summary xml:lang="nl">Archiefgereedschap</summary>
|
||||
<summary xml:lang="pl">Narzędzie do archiwizowania</summary>
|
||||
<summary xml:lang="pt">Ferramenta de Arquivo</summary>
|
||||
<summary xml:lang="pt-BR">Ferramenta de arquivamento</summary>
|
||||
<summary xml:lang="sk">Archivačný nástroj</summary>
|
||||
<summary xml:lang="sl">Orodje za ravnanje z arhivi</summary>
|
||||
<summary xml:lang="sr">Алатка за архивирање</summary>
|
||||
<summary xml:lang="sr-Latn">Alatka za arhiviranje</summary>
|
||||
<summary xml:lang="sr-ijekavian">Алатка за архивирање</summary>
|
||||
<summary xml:lang="sr-ijekavianlatin">Alatka za arhiviranje</summary>
|
||||
<summary xml:lang="sv">Arkiveringsverktyg</summary>
|
||||
<summary xml:lang="tr">Arşivleme Aracı</summary>
|
||||
<summary xml:lang="uk">Інструмент роботи з архівами</summary>
|
||||
<summary xml:lang="x-test">xxArchiving Toolxx</summary>
|
||||
<summary xml:lang="zh-CN">压缩工具</summary>
|
||||
<summary xml:lang="zh-TW">壓縮工具</summary>
|
||||
<description>
|
||||
<p>
|
||||
Ark is a graphical file compression/decompression utility with support for multiple formats,
|
||||
including tar, gzip, bzip2, rar and zip, as well as CD-ROM images.
|
||||
Ark can be used to browse, extract, create, and modify archives.
|
||||
</p>
|
||||
<p xml:lang="ar">آرك أداة رسوميّة لضغط وفكّ ضغط الملفات مع دعم لصيغ متعدّدة، منها tar، وgzip، وbzip2، وrar، وzip، إضافة إلى صور الأقراص الضوئيّة. يمكن استخدام آرك لتصفح، واستخراج، وإنشاء، وتعديل الأرشيفات.</p>
|
||||
<p xml:lang="bg">Ark е графичен инструмент за архивиране/разархивиране, поддържащ множество формати, включително tar, gzip, bzip2, rar и zip, както и образи на CD-ROM. Ark може да се използва за разглеждане, извличане, създаване и променяне на архиви.</p>
|
||||
<p xml:lang="ca">L'Ark és una utilitat gràfica de compressió/descompressió de fitxers que implementa múltiples formats, incloent tar, gzip, bzip2, rar i zip, i també imatges de CD-ROM. L'Ark es pot utilitzar per explorar, extreure, crear, i modificar arxiua.</p>
|
||||
<p xml:lang="da">Ark er et grafisk værktøj til komprimering/dekomprimering, med understøttelse for flere formater, derunder tar, gzip, bzip2, rar og zip, såvel som cd-rom-imagefiler. Ark kan bruges til at gennemse, udtrække, oprette og redigere.</p>
|
||||
<p xml:lang="de">Ark ist ein grafisches Dienstprogramm zum Packen/Entpacken von Dateien mit Unterstützung für mehrere Formate wie tar, gzip, bzip2, rar, zip und auch CD-Abbilder. Mit Ark können Sie können Sie Archive durchsehen, entpacken, erstellen und bearbeiten.</p>
|
||||
<p xml:lang="en-GB">Ark is a graphical file compression/decompression utility with support for multiple formats, including tar, gzip, bzip2, rar and zip, as well as CD-ROM images. Ark can be used to browse, extract, create, and modify archives.</p>
|
||||
<p xml:lang="es">Ark es una utilidad gráfica de compresión y descompresión de archivos que permite usar diversos formatos, como tar, gzip, bzip2, rar y zip, así como imágenes de CD-ROM. Ark se puede usar para explorar, extraer, crear y modificar archivos comprimidos.</p>
|
||||
<p xml:lang="et">Ark on graafiline failide tihendamise ehk kokkupakkimise ja nende lahtipakkimise tööriist, mis toetab väga paljusid vorminguid, sealhulgas tar, gzip, bzip2, rar and zip, samuti CD-ROM-i tõmmised. Arki abil saab arhiivifaile sirvida, lahti pakkida, luua ja muuta.</p>
|
||||
<p xml:lang="fi">Ark on graafinen tiedostojen pakkaus-/purkuohjelma, joka tukee useita tiedostomuotoja kuten tar, gzip, bzip2, rar and zip sekä myös CD-ROM-levykuvia. Arkilla voi selata, purkaa, luoda ja muuttaa paketteja.</p>
|
||||
<p xml:lang="fr">Ark est un utilitaire graphique de compression/décompression de fichier prenant en charge de multiples formats, notamment tar, gzip, bzip2, rar et zip, ainsi que les images de CD-ROM. Ark peut être utilisé pour parcourir, extraire, créer et modifier des archives.</p>
|
||||
<p xml:lang="hu">Az Ark egy grafikus fájltömörítő és kibontó segédprogram többféle formátum támogatásával, beleértve a tar, gzip, bzip2, rar és zip formátumokat, valamint a CD-ROM képfájlokat. Az Ark használható archívumok böngészéséhez, kibontásához, létrehozásához és módosításához.</p>
|
||||
<p xml:lang="it">Ark è uno strumento grafico per la compressione/decompressione dei file che supporta molti formati, tra i quali tar, gzip, bzip2, rar e zip, così come le immagini dei CD-ROM. Ark può essere utilizzato per sfogliare, estrarre, creare e modificare archivi.</p>
|
||||
<p xml:lang="ko">Ark는 그래픽 압축 파일 관리 도구이며, tar, gzip, bzip2, rar, zip, CD-ROM 이미지를 포함한 여러 파일 형식을 지원합니다. Ark를 사용하여 압축 파일을 열고, 생성하고, 수정하고, 압축을 풀 수 있습니다.</p>
|
||||
<p xml:lang="nb">Ark er et verktøy med grafisk brukerflate, for komprimering/dekomprimering, med støtte for mange formater, deriblant tar, gzip, rar og zip, samt CD-ROM-bilder. Ark kan brukes til å bla i, pakke opp, opprette og endre arkiver.</p>
|
||||
<p xml:lang="nds">Ark is en graafsch Komprimeer- un Dekomprimeerwarktüüch, dat en Barg Formaten ünnerstütten deit. Dor sünd tar, gzip, bzip2, rar un zip bi, un ok CD-ROM-Afbiller. Mit Ark kannst Du Archiven dörkieken, opstellen un ännern un Dateien dor ruttrecken.</p>
|
||||
<p xml:lang="nl">Ark is een grafisch hulpmiddel om bestanden te comprimeren/uit te pakken met ondersteuning van meerdere formaten, inclusief tar, gzip, bzip2, rar en zip, evenals cd-ROM images. Ark kan gebruikt worden om door archieven te bladeren, deze uit te pakken, te maken en te wijzigen.</p>
|
||||
<p xml:lang="pl">Ark jest graficznym narzędziem do pakowania/rozpakowywania plików wraz z obsługą różnych formatów, włączając w to tar, gzip, bzip2, rar oraz zip, a także obrazy CD-ROM. Programu Ark można używać do przeglądania, tworzenia, zmieniania oraz wydobywania z archiwów</p>
|
||||
<p xml:lang="pt">O Ark é um utilitário de compressão/descompressão com o suporte para diversos formatos, incluindo o 'tar', 'gzip', 'bzip2', 'rar' e 'zip', assim como imagens de CD-ROM. O Ark pode ser usado para navegar, extrair, criar e modificar esses pacotes.</p>
|
||||
<p xml:lang="pt-BR">O Ark é um utilitário de compressão/descompressão com o suporte a diversos formatos, incluindo tar, gzip, bzip2, rar e zip, assim como imagens de CD-ROM. O Ark pode ser usado para navegar, extrair, criar e modificar esses arquivos.</p>
|
||||
<p xml:lang="sk">Ark je grafický nástroj na kompresiu a dekompresiu súborov s podporou pre mnoho formátov, vrátane tar, gzip bzip2, rar a zip, ako ako CD-ROM obrazy. Ark sa dá použiť na prehliadanie, rozbaľovanie vytváranie a úpravu archívov.</p>
|
||||
<p xml:lang="sl">Ark je grafično orodje za stiskanje/razširjanje datotek, ki podpira večje število arhivov (med podprtimi so tudi tar, gzip, bzip2, rar in zip) kot tudi odtise CD-ROM. Ark lahko uporabite za brskanje po, razširjanje, ustvarjanje in spreminjanje arhivov.</p>
|
||||
<p xml:lang="sr">Арк је графичка алатка за компресовање и декомпресовање фајлова. Подржава више формата, међу њима и: тар, гзип, бзип2, РАР, ЗИП, као и ЦД одразе. Може се користити за прегледање, распакивање, стварање и мењање архива.</p>
|
||||
<p xml:lang="sr-Latn">Ark je grafička alatka za kompresovanje i dekompresovanje fajlova. Podržava više formata, među njima i: tar, gzip, bzip2, RAR, ZIP, kao i CD odraze. Može se koristiti za pregledanje, raspakivanje, stvaranje i menjanje arhiva.</p>
|
||||
<p xml:lang="sr-ijekavian">Арк је графичка алатка за компресовање и декомпресовање фајлова. Подржава више формата, међу њима и: тар, гзип, бзип2, РАР, ЗИП, као и ЦД одразе. Може се користити за прегледање, распакивање, стварање и мењање архива.</p>
|
||||
<p xml:lang="sr-ijekavianlatin">Ark je grafička alatka za kompresovanje i dekompresovanje fajlova. Podržava više formata, među njima i: tar, gzip, bzip2, RAR, ZIP, kao i CD odraze. Može se koristiti za pregledanje, raspakivanje, stvaranje i menjanje arhiva.</p>
|
||||
<p xml:lang="sv">Ark är ett grafiskt verktyg för komprimering och uppackning av filer med stöd för flera format, inklusive tar, gzip, bzip2, rar och zip, samt cd-rom avbilder. Ark kan användas för att bläddra i, packa upp, skapa och ändra arkiv.</p>
|
||||
<p xml:lang="tr">Ark; tar, gzip, bzip2, rar ve zip dosyalarının yanında CD-ROM kalıplarını da destekleyen grafiksel bir dosya sıkıştırma/açma yardımcısıdır. Ark arşivlerde gezinmek, arşiv ayıklamak, oluşturmak ve değiştirmek için kullanılabilir.</p>
|
||||
<p xml:lang="uk">Ark — програма з графічним інтерфейсом, призначена для стискання даних у архіви та видобування даних з архівів. Передбачено підтримку декількох форматів архівів, зокрема tar, gzip, bzip2, rar та zip, а також образів дисків. Ark можна використовувати для перегляду, видобування, створення та внесення змін до архівів.</p>
|
||||
<p xml:lang="x-test">xxArk is a graphical file compression/decompression utility with support for multiple formats, including tar, gzip, bzip2, rar and zip, as well as CD-ROM images. Ark can be used to browse, extract, create, and modify archives.xx</p>
|
||||
<p xml:lang="zh-CN">Ark 是图形文件压缩和解压工具,支持多种格式,包括 tar, gzip, bzip2, rar and zip 以及 CD-ROM 镜像。Ark 可以用来浏览、解压、创建和修改压缩包。</p>
|
||||
<p xml:lang="zh-TW">Ark 是一套圖形介面的檔案壓縮/解壓縮工具,支援多種格式,包括 tar, gzip, bzip2, rar 與 zip 等,還有 CD-ROM 映像檔等。Ark 有瀏覽、解開、建立與變更壓縮檔的功能。</p>
|
||||
<p>Features:</p>
|
||||
<p xml:lang="ar">المزايا</p>
|
||||
<p xml:lang="bg">Функции:</p>
|
||||
<p xml:lang="ca">Característiques:</p>
|
||||
<p xml:lang="cs">Vlastnosti:</p>
|
||||
<p xml:lang="da">Funktioner:</p>
|
||||
<p xml:lang="de">Leistungsmerkmale:</p>
|
||||
<p xml:lang="en-GB">Features:</p>
|
||||
<p xml:lang="es">Funcionalidades:</p>
|
||||
<p xml:lang="et">Omadused:</p>
|
||||
<p xml:lang="fi">Ominaisuudet:</p>
|
||||
<p xml:lang="fr">Fonctionnalités :</p>
|
||||
<p xml:lang="hu">Szolgáltatások:</p>
|
||||
<p xml:lang="it">Funzionalità:</p>
|
||||
<p xml:lang="ko">기능:</p>
|
||||
<p xml:lang="lt">Galimybės:</p>
|
||||
<p xml:lang="nb">Egenskaper:</p>
|
||||
<p xml:lang="nds">Markmalen:</p>
|
||||
<p xml:lang="nl">Mogelijkheden:</p>
|
||||
<p xml:lang="pl">Cechy:</p>
|
||||
<p xml:lang="pt">Características:</p>
|
||||
<p xml:lang="pt-BR">Funcionalidades:</p>
|
||||
<p xml:lang="sk">Funkcie:</p>
|
||||
<p xml:lang="sl">Zmožnosti:</p>
|
||||
<p xml:lang="sr">Могућности:</p>
|
||||
<p xml:lang="sr-Latn">Mogućnosti:</p>
|
||||
<p xml:lang="sr-ijekavian">Могућности:</p>
|
||||
<p xml:lang="sr-ijekavianlatin">Mogućnosti:</p>
|
||||
<p xml:lang="sv">Funktioner:</p>
|
||||
<p xml:lang="tr">Özellikler:</p>
|
||||
<p xml:lang="uk">Можливості:</p>
|
||||
<p xml:lang="x-test">xxFeatures:xx</p>
|
||||
<p xml:lang="zh-CN">功能:</p>
|
||||
<p xml:lang="zh-TW">特色:</p>
|
||||
<ul>
|
||||
<li>Several formats supported: gzip, bzip2, zip, rar, 7z and more</li>
|
||||
<li xml:lang="ar">دعم صيغ متعدّدة: مثل gzip، و bzip2، و zip، و rar، و 7z وغيرها</li>
|
||||
<li xml:lang="bg">Поддържани са много формати: gzip, bzip2, zip, rar, 7z и други</li>
|
||||
<li xml:lang="ca">Diversos formats implementats: gzip, bzip2, zip, rar, 7z i més</li>
|
||||
<li xml:lang="cs">Je podporováno několik formátů: gzip, bzip2, zip, rar, 7z a další</li>
|
||||
<li xml:lang="da">Flere understøttede formater: gzip, bzip2, zip, rar, 7z og flere</li>
|
||||
<li xml:lang="de">Mehrere unterstützte Formate wie gzip, bzip2, zip, rar, 7z und mehr</li>
|
||||
<li xml:lang="en-GB">Several formats supported: gzip, bzip2, zip, rar, 7z and more</li>
|
||||
<li xml:lang="es">Permite el uso de diversos formatos: gzip, bzip2, zip, rar, 7z y más</li>
|
||||
<li xml:lang="et">Paljude vormingute toetus: gzip, bzip2, zip, rar, 7z ja veel paljud.</li>
|
||||
<li xml:lang="fi">Tukee useita tiedostomuotoja: gzip, bzip2, zip, rar, 7z ja monia muita</li>
|
||||
<li xml:lang="fr">Plusieurs formats sont pris en charge : gzip, bzip2, zip, rar, 7z et d'autres</li>
|
||||
<li xml:lang="hu">Számos formátum támogatott: gzip, bzip2, zip, rar, 7z és továbbiak</li>
|
||||
<li xml:lang="it">Diversi formati supportati: gzip, bzip2, zip, rar, 7z e altri</li>
|
||||
<li xml:lang="ko">다양한 형식 지원: gzip, bzip2, zip, rar, 7z 등</li>
|
||||
<li xml:lang="nb">Mange formater støttet: gzip, bzip2, zip, rar, 7z og mer</li>
|
||||
<li xml:lang="nds">En Reeg Fomaten warrt ünnerstütt: gzip, bzip2, zip, rar, 7z un anner</li>
|
||||
<li xml:lang="nl">Ondersteuning voor een aantal formaten: gzip, bzip2, zip, rar, 7z en meer</li>
|
||||
<li xml:lang="pl">Obsługa kilku formatów: gzip, bzip2, zip, rar, 7z oraz więcej</li>
|
||||
<li xml:lang="pt">Diversos formatos suportados: gzip, bzip2, zip, rar, 7z, entre outros</li>
|
||||
<li xml:lang="pt-BR">Diversos formatos suportados: gzip, bzip2, zip, rar, 7z, entre outros</li>
|
||||
<li xml:lang="sk">Niektoré z podporovaných formátov: gzip, bzip2, zip, rar, 7z a viac</li>
|
||||
<li xml:lang="sl">Številne podprte vrste arhivov: gzip, bzip2, zip, rar, 7z in več</li>
|
||||
<li xml:lang="sr">Више подржаних формата: гзип, бзип2, ЗИП, РАР, 7зип, итд.</li>
|
||||
<li xml:lang="sr-Latn">Više podržanih formata: gzip, bzip2, ZIP, RAR, 7zip, itd.</li>
|
||||
<li xml:lang="sr-ijekavian">Више подржаних формата: гзип, бзип2, ЗИП, РАР, 7зип, итд.</li>
|
||||
<li xml:lang="sr-ijekavianlatin">Više podržanih formata: gzip, bzip2, ZIP, RAR, 7zip, itd.</li>
|
||||
<li xml:lang="sv">En mängd format stöds: gzip, bzip2, zip, rar, 7z med flera</li>
|
||||
<li xml:lang="tr">Çeşitli biçimler destekleniyor: gzip, bzip2, zip, rar, 7z ve dahası</li>
|
||||
<li xml:lang="uk">Підтримка декількох форматів: gzip, bzip2, zip, rar, 7z тощо</li>
|
||||
<li xml:lang="x-test">xxSeveral formats supported: gzip, bzip2, zip, rar, 7z and morexx</li>
|
||||
<li xml:lang="zh-CN">支持多种格式:gzip, bzip2, zip, rar, 7z 等</li>
|
||||
<li xml:lang="zh-TW">支援格式:gzip, bzip2, zip, rar, 7z 等等</li>
|
||||
<li>Preview file contents without extracting files</li>
|
||||
<li xml:lang="ar">استعراض محتوى الملف دون استخراج الملفات منه</li>
|
||||
<li xml:lang="bg">Преглеждане съдържанието на файла, без извличане на файловете</li>
|
||||
<li xml:lang="ca">Vista prèvia del contingut de fitxers sense extreure'ls</li>
|
||||
<li xml:lang="cs">Náhled obsahu souborů bez jejich rozbalení</li>
|
||||
<li xml:lang="da">Forhåndsvis filindhold uden at udtrække filer</li>
|
||||
<li xml:lang="de">Vorschau der Dateiinhalte ohne das Entpacken der Dateien</li>
|
||||
<li xml:lang="en-GB">Preview file contents without extracting files</li>
|
||||
<li xml:lang="es">Vista previa del contenido de archivos sin extraerlos</li>
|
||||
<li xml:lang="et">Failide sisu näitamine ilma neid lahti pakkimata.</li>
|
||||
<li xml:lang="fi">Tiedoston sisällön esikatselu purkamatta tiedostoa</li>
|
||||
<li xml:lang="fr">Prévisualiser le contenu des fichiers sans les extraire</li>
|
||||
<li xml:lang="hu">Fájltartalom előnézete a fájlok kibontása nélkül</li>
|
||||
<li xml:lang="it">Anteprima dei file senza estrarre i file</li>
|
||||
<li xml:lang="ko">압축 풀지 않고 파일 내용 미리 보기</li>
|
||||
<li xml:lang="nb">Forhåndsvis innhold uten å pakke ut filer</li>
|
||||
<li xml:lang="nds">Datein ahn Ruttrecken vörweg ankieken</li>
|
||||
<li xml:lang="nl">Voorvertoning van inhoud van bestand zonder bestanden uit te pakken</li>
|
||||
<li xml:lang="pl">Podejrzyj zawartość pliku bez jego wypakowywania</li>
|
||||
<li xml:lang="pt">Antevisão do conteúdo dos ficheiros sem os extrair</li>
|
||||
<li xml:lang="pt-BR">Visualização do conteúdo dos arquivos sem precisar extraí-los</li>
|
||||
<li xml:lang="sk">Náhľad obsahu súboru bez rozbalenia súborov</li>
|
||||
<li xml:lang="sl">Predoglejte vsebino datoteke brez razširjanja</li>
|
||||
<li xml:lang="sr">Преглед садржаја фајлова без распакивања.</li>
|
||||
<li xml:lang="sr-Latn">Pregled sadržaja fajlova bez raspakivanja.</li>
|
||||
<li xml:lang="sr-ijekavian">Преглед садржаја фајлова без распакивања.</li>
|
||||
<li xml:lang="sr-ijekavianlatin">Pregled sadržaja fajlova bez raspakivanja.</li>
|
||||
<li xml:lang="sv">Förhandsgranska filinnehåll utan att packa upp filer</li>
|
||||
<li xml:lang="tr">Dosyaları ayıklamadan dosya içeriği önizlemesi</li>
|
||||
<li xml:lang="uk">Попередній перегляд вмісту файлів без розпаковування</li>
|
||||
<li xml:lang="x-test">xxPreview file contents without extracting filesxx</li>
|
||||
<li xml:lang="zh-CN">不解压就预览文件</li>
|
||||
<li xml:lang="zh-TW">不需解壓縮即可預覽檔案內容</li>
|
||||
</ul>
|
||||
</description>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image width="834" height="651">http://kde.org/images/screenshots/ark.png</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<url type="homepage">http://kde.org/applications/utilities/ark/</url>
|
||||
<url type="bugtracker">https://bugs.kde.org/enter_bug.cgi?format=guided&product=ark</url>
|
||||
<url type="help">http://docs.kde.org/stable/en/kdeutils/ark/index.html</url>
|
||||
<project_group>KDE</project_group>
|
||||
<provides>
|
||||
<binary>ark</binary>
|
||||
</provides>
|
||||
</component>
|
158
ark/app/ark.desktop.cmake
Executable file
|
@ -0,0 +1,158 @@
|
|||
[Desktop Entry]
|
||||
MimeType=@SUPPORTED_ARK_MIMETYPES@
|
||||
GenericName=Archiving Tool
|
||||
GenericName[af]=Argiveer Program
|
||||
GenericName[ar]=أداة أرشفة
|
||||
GenericName[ast]=Ferramienta p'archivar
|
||||
GenericName[bg]=Работа с архиви
|
||||
GenericName[br]=Ostilh merañ an Dielloù
|
||||
GenericName[bs]=Alatka za arhiviranje
|
||||
GenericName[ca]=Eina d'arxivament
|
||||
GenericName[ca@valencia]=Eina d'arxivament
|
||||
GenericName[cs]=Archivační nástroj
|
||||
GenericName[cy]=Erfyn Archifo
|
||||
GenericName[da]=Arkiveringsværktøj
|
||||
GenericName[de]=Archivprogramm
|
||||
GenericName[el]=Εργαλείο αρχειοθέτησης
|
||||
GenericName[en_GB]=Archiving Tool
|
||||
GenericName[eo]=Arkivilo
|
||||
GenericName[es]=Archivador
|
||||
GenericName[et]=Arhiivide haldamise rakendus
|
||||
GenericName[eu]=Artxibatzeko tresna
|
||||
GenericName[fa]=ابزار بایگانی
|
||||
GenericName[fi]=Pakkausohjelma
|
||||
GenericName[fr]=Outil d'archivage
|
||||
GenericName[ga]=Uirlis Chartlannaithe
|
||||
GenericName[gl]=Utilidade de arquivo
|
||||
GenericName[he]=כלי לניהול ארכיונים
|
||||
GenericName[hne]=अभिलेखन औजार
|
||||
GenericName[hr]=Alat za arhiviranje
|
||||
GenericName[hu]=Fájltömörítő
|
||||
GenericName[ia]=Instrumento per archivar
|
||||
GenericName[id]=Perkakas Pengarsip
|
||||
GenericName[is]=Vinna með safnskrár
|
||||
GenericName[it]=Strumento di archiviazione
|
||||
GenericName[ja]=アーカイブツール
|
||||
GenericName[kk]=Архивтеу құралы
|
||||
GenericName[km]=ឧបករណ៍ប័ណ្ណសារ
|
||||
GenericName[ko]=압축 도구
|
||||
GenericName[lt]=Archyvavimo priemonė
|
||||
GenericName[lv]=Arhivēšanas rīks
|
||||
GenericName[mk]=Алатка за архивирање
|
||||
GenericName[mr]=संग्रह साधन
|
||||
GenericName[ms]=Alatan Pengarkiban
|
||||
GenericName[nb]=Arkiveringsverktøy
|
||||
GenericName[nds]=Archievwarktüüch
|
||||
GenericName[ne]=सङ्ग्रहण उपकरण
|
||||
GenericName[nl]=Archiefgereedschap
|
||||
GenericName[nn]=Arkiveringsverktøy
|
||||
GenericName[pa]=ਅਕਾਇਵਿੰਗ ਟੂਲ
|
||||
GenericName[pl]=Narzędzie do archiwizacji
|
||||
GenericName[pt]=Ferramenta de Armazenamento
|
||||
GenericName[pt_BR]=Ferramenta de Arquivamento
|
||||
GenericName[ro]=Utilitar de arhivare
|
||||
GenericName[ru]=Архиватор
|
||||
GenericName[sk]=Archivačný nástroj
|
||||
GenericName[sl]=Orodje za ravnanje z arhivi
|
||||
GenericName[sq]=Mjeti Arkivues
|
||||
GenericName[sr]=Алатка за архивирање
|
||||
GenericName[sr@ijekavian]=Алатка за архивирање
|
||||
GenericName[sr@ijekavianlatin]=Alatka za arhiviranje
|
||||
GenericName[sr@latin]=Alatka za arhiviranje
|
||||
GenericName[sv]=Arkiveringsverktyg
|
||||
GenericName[ta]=காப்பக கருவி
|
||||
GenericName[tg]=Асбобҳои Бойгонӣ
|
||||
GenericName[th]=เครื่องมือจัดการแฟ้มจัดเก็บ
|
||||
GenericName[tr]=Arşivleme Aracı
|
||||
GenericName[ug]=ئارخىپ قورالى
|
||||
GenericName[uk]=Засіб роботи з архівами
|
||||
GenericName[uz]=Arxivlash vositasi
|
||||
GenericName[uz@cyrillic]=Архивлаш воситаси
|
||||
GenericName[vi]=Công Cụ Nén
|
||||
GenericName[wa]=Usteye d' årtchivaedje
|
||||
GenericName[xh]=Isixhobo Sokuphatha i Archive
|
||||
GenericName[x-test]=xxArchiving Toolxx
|
||||
GenericName[zh_CN]=压缩归档工具
|
||||
GenericName[zh_TW]=壓縮工具
|
||||
Name=Ark
|
||||
Name[af]=Ark
|
||||
Name[ar]=أرك
|
||||
Name[ast]=Ark
|
||||
Name[bg]=Ark
|
||||
Name[br]=Ark
|
||||
Name[bs]=Ark
|
||||
Name[ca]=Ark
|
||||
Name[ca@valencia]=Ark
|
||||
Name[cs]=Ark
|
||||
Name[cy]=Ark
|
||||
Name[da]=Ark
|
||||
Name[de]=Ark
|
||||
Name[el]=Ark
|
||||
Name[en_GB]=Ark
|
||||
Name[eo]=Arko
|
||||
Name[es]=Ark
|
||||
Name[et]=Ark
|
||||
Name[eu]=Ark
|
||||
Name[fi]=Ark
|
||||
Name[fr]=Ark
|
||||
Name[ga]=Ark
|
||||
Name[gl]=Ark
|
||||
Name[he]=Ark
|
||||
Name[hne]=आर्क
|
||||
Name[hr]=Ark
|
||||
Name[hu]=Ark
|
||||
Name[ia]=Ark
|
||||
Name[id]=Ark
|
||||
Name[is]=Ark
|
||||
Name[it]=Ark
|
||||
Name[ja]=Ark
|
||||
Name[kk]=Ark
|
||||
Name[km]=Ark
|
||||
Name[ko]=Ark
|
||||
Name[lt]=Ark
|
||||
Name[lv]=Ark
|
||||
Name[mk]=Ark
|
||||
Name[mr]=आर्क
|
||||
Name[ms]=Ark
|
||||
Name[nb]=Ark
|
||||
Name[nds]=Ark
|
||||
Name[ne]=आर्क
|
||||
Name[nl]=Ark
|
||||
Name[nn]=Ark
|
||||
Name[pa]=ਆਕ
|
||||
Name[pl]=Ark
|
||||
Name[pt]=Ark
|
||||
Name[pt_BR]=Ark
|
||||
Name[ro]=Ark
|
||||
Name[ru]=Ark
|
||||
Name[sk]=Ark
|
||||
Name[sl]=Ark
|
||||
Name[sq]=Ark
|
||||
Name[sr]=Арк
|
||||
Name[sr@ijekavian]=Арк
|
||||
Name[sr@ijekavianlatin]=Ark
|
||||
Name[sr@latin]=Ark
|
||||
Name[sv]=Ark
|
||||
Name[ta]=ஆர்க்
|
||||
Name[tg]=Ark
|
||||
Name[th]=อาร์ก
|
||||
Name[tr]=Ark
|
||||
Name[ug]=Ark
|
||||
Name[uk]=Ark
|
||||
Name[uz]=Ark
|
||||
Name[uz@cyrillic]=Ark
|
||||
Name[vi]=Ark
|
||||
Name[wa]=Ark
|
||||
Name[xh]=Ark
|
||||
Name[x-test]=xxArkxx
|
||||
Name[zh_CN]=Ark
|
||||
Name[zh_TW]=Ark
|
||||
Exec=ark -caption %c %U
|
||||
Icon=ark
|
||||
X-DocPath=ark/index.html
|
||||
Type=Application
|
||||
Terminal=false
|
||||
X-DBUS-StartupType=Unique
|
||||
X-KDE-HasTempFileOption=true
|
||||
Categories=Qt;KDE;Utility;Archiving;Compression;X-KDE-Utilities-File;
|
||||
InitialPreference=3
|
351
ark/app/ark_addtoservicemenu.desktop
Normal file
|
@ -0,0 +1,351 @@
|
|||
[Desktop Entry]
|
||||
Type=Service
|
||||
ServiceTypes=KonqPopupMenu/Plugin
|
||||
MimeType=all/all;
|
||||
Actions=compressHere;compressAsZip;compressAsRar;compressAsTar;compressTo;
|
||||
X-KDE-Submenu=Compress
|
||||
X-KDE-Submenu[ar]=اضغط
|
||||
X-KDE-Submenu[ast]=Comprimir
|
||||
X-KDE-Submenu[bg]=Компресиране
|
||||
X-KDE-Submenu[bs]=Kompresuj
|
||||
X-KDE-Submenu[ca]=Compressió
|
||||
X-KDE-Submenu[ca@valencia]=Compressió
|
||||
X-KDE-Submenu[cs]=Zkomprimovat
|
||||
X-KDE-Submenu[da]=Komprimér
|
||||
X-KDE-Submenu[de]=Komprimieren
|
||||
X-KDE-Submenu[el]=Συμπίεση
|
||||
X-KDE-Submenu[en_GB]=Compress
|
||||
X-KDE-Submenu[es]=Comprimir
|
||||
X-KDE-Submenu[et]=Paki
|
||||
X-KDE-Submenu[eu]=Konprimatu
|
||||
X-KDE-Submenu[fi]=Pakkaa
|
||||
X-KDE-Submenu[fr]=Compresser
|
||||
X-KDE-Submenu[ga]=Comhbhrúigh
|
||||
X-KDE-Submenu[gl]=Comprimir
|
||||
X-KDE-Submenu[hne]=संपीडित करव
|
||||
X-KDE-Submenu[hr]=Zapakiraj
|
||||
X-KDE-Submenu[hu]=Tömörítés
|
||||
X-KDE-Submenu[ia]=Comprime
|
||||
X-KDE-Submenu[id]=Kompres
|
||||
X-KDE-Submenu[it]=Comprimi
|
||||
X-KDE-Submenu[ja]=圧縮
|
||||
X-KDE-Submenu[kk]=Сығу
|
||||
X-KDE-Submenu[km]=បង្ហាប់
|
||||
X-KDE-Submenu[ko]=압축하기
|
||||
X-KDE-Submenu[lt]=Suspausti
|
||||
X-KDE-Submenu[lv]=Saspiest
|
||||
X-KDE-Submenu[mr]=संक्षिप्त करा
|
||||
X-KDE-Submenu[nb]=Komprimer
|
||||
X-KDE-Submenu[nds]=Komprimeren
|
||||
X-KDE-Submenu[nl]=Comprimeren
|
||||
X-KDE-Submenu[nn]=Komprimer
|
||||
X-KDE-Submenu[pa]=ਕੰਪਰੈੱਸ
|
||||
X-KDE-Submenu[pl]=Kompresuj
|
||||
X-KDE-Submenu[pt]=Comprimir
|
||||
X-KDE-Submenu[pt_BR]=Compactar
|
||||
X-KDE-Submenu[ro]=Comprimă
|
||||
X-KDE-Submenu[ru]=Упаковать
|
||||
X-KDE-Submenu[sk]=Komprimovať
|
||||
X-KDE-Submenu[sl]=Stisni
|
||||
X-KDE-Submenu[sq]=Ngjish
|
||||
X-KDE-Submenu[sr]=Компресуј
|
||||
X-KDE-Submenu[sr@ijekavian]=Компресуј
|
||||
X-KDE-Submenu[sr@ijekavianlatin]=Kompresuj
|
||||
X-KDE-Submenu[sr@latin]=Kompresuj
|
||||
X-KDE-Submenu[sv]=Komprimera
|
||||
X-KDE-Submenu[th]=บีบข้อมูล
|
||||
X-KDE-Submenu[tr]=Sıkıştır
|
||||
X-KDE-Submenu[ug]=پرېس
|
||||
X-KDE-Submenu[uk]=Стиснути
|
||||
X-KDE-Submenu[wa]=Rastrinde
|
||||
X-KDE-Submenu[x-test]=xxCompressxx
|
||||
X-KDE-Submenu[zh_CN]=压缩
|
||||
X-KDE-Submenu[zh_TW]=壓縮
|
||||
X-KDE-StartupNotify=false
|
||||
X-KDE-Priority=TopLevel
|
||||
|
||||
[Desktop Action compressHere]
|
||||
Name=Here
|
||||
Name[ar]=هنا
|
||||
Name[ast]=Equí
|
||||
Name[bg]=Тук
|
||||
Name[bs]=ovdje
|
||||
Name[ca]=Aquí
|
||||
Name[ca@valencia]=Ací
|
||||
Name[cs]=Sem
|
||||
Name[da]=Her
|
||||
Name[de]=Hier
|
||||
Name[el]=Εδώ
|
||||
Name[en_GB]=Here
|
||||
Name[es]=Aquí
|
||||
Name[et]=Siia
|
||||
Name[eu]=Hemen
|
||||
Name[fi]=Tähän
|
||||
Name[fr]=Ici
|
||||
Name[ga]=Anseo
|
||||
Name[gl]=Aquí
|
||||
Name[hr]=Ovdje
|
||||
Name[hu]=Ide
|
||||
Name[ia]=Hic
|
||||
Name[id]=Di Sini
|
||||
Name[is]=Hér
|
||||
Name[it]=Qui
|
||||
Name[ja]=ここに
|
||||
Name[kk]=Осында
|
||||
Name[km]=នៅទីនេះ
|
||||
Name[ko]=여기
|
||||
Name[lt]=Čia
|
||||
Name[lv]=Šeit
|
||||
Name[mr]=येथे
|
||||
Name[nb]=Her
|
||||
Name[nds]=Hier
|
||||
Name[nl]=Hier
|
||||
Name[nn]=Her
|
||||
Name[pa]=ਇੱਥੇ
|
||||
Name[pl]=Tutaj
|
||||
Name[pt]=Aqui
|
||||
Name[pt_BR]=Aqui
|
||||
Name[ro]=Aici
|
||||
Name[ru]=В эту папку
|
||||
Name[sk]=Sem
|
||||
Name[sl]=Sem
|
||||
Name[sq]=Këtu
|
||||
Name[sr]=овде
|
||||
Name[sr@ijekavian]=овдје
|
||||
Name[sr@ijekavianlatin]=ovdje
|
||||
Name[sr@latin]=ovde
|
||||
Name[sv]=Här
|
||||
Name[th]=ไว้ที่นี่
|
||||
Name[tr]=Buraya
|
||||
Name[ug]=بۇ جاي
|
||||
Name[uk]=Сюди
|
||||
Name[wa]=Cial
|
||||
Name[x-test]=xxHerexx
|
||||
Name[zh_CN]=这里
|
||||
Name[zh_TW]=這裡
|
||||
Icon=ark
|
||||
Exec=ark --changetofirstpath --add --autofilename tar.gz %F
|
||||
|
||||
[Desktop Action compressAsZip]
|
||||
Name=As ZIP Archive
|
||||
Name[ar]=ك أرشيف ZIP
|
||||
Name[ast]=Como archivu comprimíu ZIP
|
||||
Name[bg]=Като ZIP архив
|
||||
Name[bs]=kao ZIP arhivu
|
||||
Name[ca]=Com a arxiu ZIP
|
||||
Name[ca@valencia]=Com a arxiu ZIP
|
||||
Name[cs]=Jako archiv ZIP
|
||||
Name[da]=Som ZIP-arkiv
|
||||
Name[de]=Als ZIP-Archiv
|
||||
Name[el]=Ως αρχειοθήκη ZIP
|
||||
Name[en_GB]=As ZIP Archive
|
||||
Name[es]=Como archivo comprimido ZIP
|
||||
Name[et]=ZIP-arhiivina
|
||||
Name[eu]=ZIP artxibo gisa
|
||||
Name[fi]=ZIP-paketiksi
|
||||
Name[fr]=Comme une archive « ZIP »
|
||||
Name[ga]=Mar Chartlann ZIP
|
||||
Name[gl]=Como arquivo ZIP
|
||||
Name[hr]=Kao ZIP-arhiva
|
||||
Name[hu]=ZIP archívumként
|
||||
Name[ia]=Como archivo ZIP
|
||||
Name[id]=Sebagai Arsip ZIP
|
||||
Name[it]=Come archivio ZIP
|
||||
Name[ja]=ZIP アーカイブに
|
||||
Name[kk]=ZIP архиві қылып
|
||||
Name[km]=ជាប័ណ្ណសារ ZIP
|
||||
Name[ko]=ZIP 파일로
|
||||
Name[lt]=ZIP archyvas
|
||||
Name[lv]=Kā ZIP arhīvu
|
||||
Name[mr]=ZIP संग्रह प्रमाणे
|
||||
Name[nb]=Som ZIP-arkiv
|
||||
Name[nds]=As Zip-Archiev
|
||||
Name[nl]=Als ZIP-archief
|
||||
Name[nn]=Som ZIP-arkiv
|
||||
Name[pa]=ਜ਼ਿਪ ਅਕਾਇਵ ਵਾਂਗ
|
||||
Name[pl]=Jako archiwum ZIP
|
||||
Name[pt]=Como Pacote ZIP
|
||||
Name[pt_BR]=Como arquivo ZIP
|
||||
Name[ro]=Ca arhivă ZIP
|
||||
Name[ru]=Как архив ZIP
|
||||
Name[sk]=Do ZIP archívu
|
||||
Name[sl]=Kot arhiv ZIP
|
||||
Name[sq]=Si Arkiv ZIP
|
||||
Name[sr]=као ЗИП архиву
|
||||
Name[sr@ijekavian]=као ЗИП архиву
|
||||
Name[sr@ijekavianlatin]=kao ZIP arhivu
|
||||
Name[sr@latin]=kao ZIP arhivu
|
||||
Name[sv]=Som ZIP-arkiv
|
||||
Name[th]=เป็นแฟ้มจัดเก็บบีบอัดแบบ ZIP
|
||||
Name[tr]=ZIP Arşivi Olarak
|
||||
Name[ug]=ZIP ئارخىپى
|
||||
Name[uk]=Як архів ZIP
|
||||
Name[wa]=Come årtchive ZIP
|
||||
Name[x-test]=xxAs ZIP Archivexx
|
||||
Name[zh_CN]=为 ZIP 归档
|
||||
Name[zh_TW]=成 ZIP 壓縮檔
|
||||
Icon=ark
|
||||
Exec=ark --changetofirstpath --add --autofilename zip %F
|
||||
|
||||
[Desktop Action compressAsRar]
|
||||
Name=As RAR Archive
|
||||
Name[ar]=كأرشيف RAR
|
||||
Name[ast]=Como archivu comprimíu RAR
|
||||
Name[bg]=Като RAR архив
|
||||
Name[bs]=kao RAR arhivu
|
||||
Name[ca]=Com a arxiu RAR
|
||||
Name[ca@valencia]=Com a arxiu RAR
|
||||
Name[cs]=Jako archiv RAR
|
||||
Name[da]=Som RAR-arkiv
|
||||
Name[de]=Als RAR-Archiv
|
||||
Name[el]=Ως αρχειοθήκη RAR
|
||||
Name[en_GB]=As RAR Archive
|
||||
Name[es]=Como archivo comprimido RAR
|
||||
Name[et]=RAR-arhiivina
|
||||
Name[eu]=RAR artxibo gisa
|
||||
Name[fi]=RAR-paketiksi
|
||||
Name[fr]=Comme une archive « RAR »
|
||||
Name[ga]=Mar Chartlann RAR
|
||||
Name[gl]=Como arquivo RAR
|
||||
Name[hr]=Kao RAR-arhiva
|
||||
Name[hu]=RAR archívumként
|
||||
Name[ia]=Como archivo RAR
|
||||
Name[id]=Sebagai Arsip RAR
|
||||
Name[it]=Come archivio RAR
|
||||
Name[ja]=RAR アーカイブに
|
||||
Name[kk]=RAR архиві қылып
|
||||
Name[km]=ជាប័ណ្ណសារ RAR
|
||||
Name[ko]=RAR 파일로
|
||||
Name[lt]=RAR archyvas
|
||||
Name[lv]=Kā RAR arhīvu
|
||||
Name[mr]=RAR संग्रह प्रमाणे
|
||||
Name[nb]=Som RAR-arkiv
|
||||
Name[nds]=As RAR-Archiev
|
||||
Name[nl]=Als RAR-archief
|
||||
Name[nn]=Som RAR-arkiv
|
||||
Name[pa]=RAR ਅਕਾਇਵ ਵਾਂਗ
|
||||
Name[pl]=Jako archiwum RAR
|
||||
Name[pt]=Como Pacote RAR
|
||||
Name[pt_BR]=Como arquivo RAR
|
||||
Name[ro]=Ca arhivă RAR
|
||||
Name[ru]=Как архив RAR
|
||||
Name[sk]=Do RAR archívu
|
||||
Name[sl]=Kot arhiv RAR
|
||||
Name[sq]=Si Arkiv RAR
|
||||
Name[sr]=као РАР архиву
|
||||
Name[sr@ijekavian]=као РАР архиву
|
||||
Name[sr@ijekavianlatin]=kao RAR arhivu
|
||||
Name[sr@latin]=kao RAR arhivu
|
||||
Name[sv]=Som RAR-arkiv
|
||||
Name[th]=เป็นแฟ้มจัดเก็บบีบอัดแบบ RAR
|
||||
Name[tr]=RAR Arşivi Olarak
|
||||
Name[ug]=RAR ئارخىپى
|
||||
Name[uk]=Як архів RAR
|
||||
Name[wa]=Come årtchive RAR
|
||||
Name[x-test]=xxAs RAR Archivexx
|
||||
Name[zh_CN]=为 RAR 归档
|
||||
Name[zh_TW]=成 RAR 壓縮檔
|
||||
Icon=ark
|
||||
Exec=ark --changetofirstpath --add --autofilename rar %F
|
||||
|
||||
[Desktop Action compressAsTar]
|
||||
Name=As TAR.GZ Archive
|
||||
Name[ar]=كأرشيف TAR.GZ
|
||||
Name[bg]=Като TAR.GZ архив
|
||||
Name[ca]=Com a arxiu TAR.GZ
|
||||
Name[cs]=Jako archiv TAR.GZ
|
||||
Name[da]=Som TAR.GZ-arkiv
|
||||
Name[de]=Als TAR.GZ-Archiv
|
||||
Name[en_GB]=As TAR.GZ Archive
|
||||
Name[es]=Como archivo comprimido TAR.GZ
|
||||
Name[et]=TAR.GZ-arhiivina
|
||||
Name[fi]=TAR.GZ-paketiksi
|
||||
Name[fr]=Comme une archive « TAR.GZ »
|
||||
Name[hu]=TAR.GZ archívumként
|
||||
Name[ia]=Como archivo TAR.GZ
|
||||
Name[it]=Come archivio TAR.GZ
|
||||
Name[ja]=TAR.GZ アーカイブに
|
||||
Name[ko]=TAR.GZ 파일로
|
||||
Name[nb]=Som TAR.GZ-arkiv
|
||||
Name[nds]=As TAR.GZ-Archiev
|
||||
Name[nl]=Als TAR.GZ-archief
|
||||
Name[pa]=TAR.GZ ਅਕਾਇਵ ਵਜੋਂ
|
||||
Name[pl]=Jako archiwum TAR.GZ
|
||||
Name[pt]=Como Pacote TAR.GZ
|
||||
Name[pt_BR]=Como arquivo TAR.GZ
|
||||
Name[ru]=Как архив TAR.GZ
|
||||
Name[sk]=Ako TAR.GZ archív
|
||||
Name[sl]=Kot arhiv TAR.GZ
|
||||
Name[sr]=као таргз архиву
|
||||
Name[sr@ijekavian]=као таргз архиву
|
||||
Name[sr@ijekavianlatin]=kao targz arhivu
|
||||
Name[sr@latin]=kao targz arhivu
|
||||
Name[sv]=Som TAR.GZ-arkiv
|
||||
Name[tr]=TAR.GZ Arşivi Olarak
|
||||
Name[uk]=Як архів TAR.GZ
|
||||
Name[x-test]=xxAs TAR.GZ Archivexx
|
||||
Name[zh_CN]=为 TAR.GZ 归档
|
||||
Name[zh_TW]=成 TAR.GZ 壓縮檔
|
||||
Icon=ark
|
||||
Exec=ark --changetofirstpath --add --autofilename tar.gz %F
|
||||
|
||||
[Desktop Action compressTo]
|
||||
Name=Compress To...
|
||||
Name[ar]=اضغط إلى...
|
||||
Name[ast]=Comprimir en...
|
||||
Name[bg]=Компресиране в...
|
||||
Name[bs]=Kompresuj u...
|
||||
Name[ca]=Comprimeix a...
|
||||
Name[ca@valencia]=Comprimeix a...
|
||||
Name[cs]=Zkomprimovat do...
|
||||
Name[da]=Komprimér til...
|
||||
Name[de]=Komprimieren nach ...
|
||||
Name[el]=Συμπίεση σε...
|
||||
Name[en_GB]=Compress To...
|
||||
Name[es]=Comprimir en...
|
||||
Name[et]=Paki asukohta...
|
||||
Name[eu]=Konprimatu hona...
|
||||
Name[fi]=Pakkaa…
|
||||
Name[fr]=Compresser vers...
|
||||
Name[ga]=Comhbhrúigh Go...
|
||||
Name[gl]=Comprimir en...
|
||||
Name[hr]=Zapakiraj u …
|
||||
Name[hu]=Tömörítés ide…
|
||||
Name[ia]=Comprime a...
|
||||
Name[id]=Kompres ke...
|
||||
Name[it]=Comprimi in...
|
||||
Name[ja]=圧縮...
|
||||
Name[kk]=Мыныған архивтеу,,,
|
||||
Name[km]=បង្ហាប់ទៅជា...
|
||||
Name[ko]=다음으로 압축하기...
|
||||
Name[lt]=Suspausti į...
|
||||
Name[lv]=Saspiest uz...
|
||||
Name[mr]=यावर संक्षिप्त करा...
|
||||
Name[nb]=Komprimer til …
|
||||
Name[nds]=Komprimeren as...
|
||||
Name[nl]=Comprimeren naar...
|
||||
Name[nn]=Komprimer til …
|
||||
Name[pa]=...ਵਜੋਂ ਕੰਪਰੈੱਸ ਕਰੋ
|
||||
Name[pl]=Kompresuj do...
|
||||
Name[pt]=Comprimir Para...
|
||||
Name[pt_BR]=Compactar para...
|
||||
Name[ro]=Comprimă în...
|
||||
Name[ru]=Упаковать в архив...
|
||||
Name[sk]=Komprimovať do...
|
||||
Name[sl]=Stisni v ...
|
||||
Name[sq]=Ngjishe Tek...
|
||||
Name[sr]=другде...
|
||||
Name[sr@ijekavian]=другдје...
|
||||
Name[sr@ijekavianlatin]=drugdje...
|
||||
Name[sr@latin]=drugde...
|
||||
Name[sv]=Komprimera till...
|
||||
Name[th]=บีบข้อมูลไปยัง...
|
||||
Name[tr]=Farklı Sıkıştır...
|
||||
Name[ug]=… غا پرېسلاش
|
||||
Name[uk]=Стиснути до...
|
||||
Name[wa]=Rastrinde eyet rlomer...
|
||||
Name[x-test]=xxCompress To...xx
|
||||
Name[zh_CN]=压缩到...
|
||||
Name[zh_TW]=壓縮為...
|
||||
Icon=ark
|
||||
Exec=ark --add --changetofirstpath --dialog %F
|
61
ark/app/ark_dndextract.desktop.cmake
Normal file
|
@ -0,0 +1,61 @@
|
|||
[Desktop Entry]
|
||||
Type=Service
|
||||
X-KDE-ServiceTypes=KonqDndPopupMenu/Plugin
|
||||
X-KDE-Library=libextracthere
|
||||
Name=Ark Extract Here
|
||||
Name[ar]=أرك استخرج هنا
|
||||
Name[ast]=Estrayer equí con Ark
|
||||
Name[bg]=Извличане тук
|
||||
Name[bs]=Raspakuj Arkom ovde
|
||||
Name[ca]=Extracció de l'Ark aquí
|
||||
Name[ca@valencia]=Extracció de l'Ark ací
|
||||
Name[cs]=Rozbalit Arkem sem
|
||||
Name[da]=Pak ud med Ark her
|
||||
Name[de]=Ark – Hierher auspacken
|
||||
Name[el]=Εξαγωγή Ark εδώ
|
||||
Name[en_GB]=Ark Extract Here
|
||||
Name[es]=Extraer aquí con Ark
|
||||
Name[et]=Paki siia lahti
|
||||
Name[eu]=Ark: atera hemen
|
||||
Name[fi]=Ark – Pura tähän
|
||||
Name[fr]=Extraire un fichier « Ark » ici
|
||||
Name[ga]=Bain an chartlann Ark amach agus cuir é anseo
|
||||
Name[gl]=Extraer aquí con Ark
|
||||
Name[hr]=Ovdje Ark-otpakiraj
|
||||
Name[hu]=Kibontás ide
|
||||
Name[ia]=Ark Extrahe hic
|
||||
Name[id]=Ark Ekstrak di Sini
|
||||
Name[it]=Ark Estrai qui
|
||||
Name[ja]=Ark ここに展開
|
||||
Name[kk]=Мынаған тарқату
|
||||
Name[km]=ស្រង់ចេញ Ark នៅទីនេះ
|
||||
Name[ko]=Ark 여기에 풀기
|
||||
Name[lt]=Čia išpakuoti archyvą
|
||||
Name[lv]=Ark atspiest šeit
|
||||
Name[mr]=येथे आर्क पुर्ववत करा
|
||||
Name[nb]=Pakk ut arkivet her med Ark
|
||||
Name[nds]=Hier mit Ark utpacken
|
||||
Name[nl]=Ark: hier uitpakken
|
||||
Name[nn]=Pakk ut med Ark her
|
||||
Name[pa]=ਅਕਾਇਵ ਇੱਥੇ ਖੋਲ੍ਹੋ
|
||||
Name[pl]=Rozpakuj tutaj
|
||||
Name[pt]=Extrair para Aqui
|
||||
Name[pt_BR]=Extrair com o Ark aqui
|
||||
Name[ro]=Ark extrage aici
|
||||
Name[ru]=Распаковать в эту папку
|
||||
Name[sk]=Ark - rozbaliť sem
|
||||
Name[sl]=Razširi sem z Arkom
|
||||
Name[sq]=Ark Ekstrakton Këtu
|
||||
Name[sr]=Распакуј Арком овде
|
||||
Name[sr@ijekavian]=Распакуј Арком овдје
|
||||
Name[sr@ijekavianlatin]=Raspakuj Arkom ovdje
|
||||
Name[sr@latin]=Raspakuj Arkom ovde
|
||||
Name[sv]=Packa upp arkiv här
|
||||
Name[th]=อาร์ก คลายแฟ้มไว้ที่นี่
|
||||
Name[tr]=Ark Arşivi Buraya Çıkart
|
||||
Name[uk]=Видобути архів сюди з Ark
|
||||
Name[wa]=Saetchî foû avou Ark cial
|
||||
Name[x-test]=xxArk Extract Herexx
|
||||
Name[zh_CN]=Ark 在此解压缩
|
||||
Name[zh_TW]=在此解壓縮
|
||||
MimeType=@SUPPORTED_ARK_MIMETYPES@
|
238
ark/app/ark_servicemenu.desktop.cmake
Normal file
|
@ -0,0 +1,238 @@
|
|||
[Desktop Entry]
|
||||
Type=Service
|
||||
ServiceTypes=KonqPopupMenu/Plugin
|
||||
MimeType=@SUPPORTED_ARK_MIMETYPES@
|
||||
Actions=arkAutoExtractHere;arkExtractTo;arkExtractHere;
|
||||
X-KDE-Priority=TopLevel
|
||||
X-KDE-StartupNotify=false
|
||||
#StartupNotify=false
|
||||
X-KDE-Submenu=Extract
|
||||
X-KDE-Submenu[ar]=استخرِج
|
||||
X-KDE-Submenu[bg]=Извличане
|
||||
X-KDE-Submenu[bs]=Raspakivanje
|
||||
X-KDE-Submenu[ca]=Extreu
|
||||
X-KDE-Submenu[ca@valencia]=Extrau
|
||||
X-KDE-Submenu[cs]=Rozbalit
|
||||
X-KDE-Submenu[da]=Pak ud
|
||||
X-KDE-Submenu[de]=Entpacken
|
||||
X-KDE-Submenu[el]=Εξαγωγή
|
||||
X-KDE-Submenu[en_GB]=Extract
|
||||
X-KDE-Submenu[es]=Extraer
|
||||
X-KDE-Submenu[et]=Lahtipakkimine
|
||||
X-KDE-Submenu[eu]=Atera
|
||||
X-KDE-Submenu[fi]=Pura
|
||||
X-KDE-Submenu[fr]=Extraire
|
||||
X-KDE-Submenu[ga]=Bain amach
|
||||
X-KDE-Submenu[gl]=Extraer
|
||||
X-KDE-Submenu[hr]=Otpakiraj
|
||||
X-KDE-Submenu[hu]=Kibontás
|
||||
X-KDE-Submenu[ia]=Extrahe
|
||||
X-KDE-Submenu[it]=Estrai
|
||||
X-KDE-Submenu[ja]=展開
|
||||
X-KDE-Submenu[kk]=Тарқату
|
||||
X-KDE-Submenu[km]=ស្រង់ចេញ
|
||||
X-KDE-Submenu[ko]=압축 풀기
|
||||
X-KDE-Submenu[lt]=Išpakuoti
|
||||
X-KDE-Submenu[mr]=पुर्ववत करा
|
||||
X-KDE-Submenu[nb]=Pakk ut
|
||||
X-KDE-Submenu[nds]=Utpacken
|
||||
X-KDE-Submenu[nl]=Uitpakken
|
||||
X-KDE-Submenu[pa]=ਇੱਥੇ ਖਿਲਾਰੋ
|
||||
X-KDE-Submenu[pl]=Rozpakuj
|
||||
X-KDE-Submenu[pt]=Extrair
|
||||
X-KDE-Submenu[pt_BR]=Extrair
|
||||
X-KDE-Submenu[ro]=Extrage
|
||||
X-KDE-Submenu[ru]=Распаковать
|
||||
X-KDE-Submenu[sk]=Rozbaliť
|
||||
X-KDE-Submenu[sl]=Razširi
|
||||
X-KDE-Submenu[sr]=Распакуј
|
||||
X-KDE-Submenu[sr@ijekavian]=Распакуј
|
||||
X-KDE-Submenu[sr@ijekavianlatin]=Raspakuj
|
||||
X-KDE-Submenu[sr@latin]=Raspakuj
|
||||
X-KDE-Submenu[sv]=Packa upp
|
||||
X-KDE-Submenu[tr]=Çıkart
|
||||
X-KDE-Submenu[ug]=ئايرىش
|
||||
X-KDE-Submenu[uk]=Видобути
|
||||
X-KDE-Submenu[x-test]=xxExtractxx
|
||||
X-KDE-Submenu[zh_CN]=解压缩
|
||||
X-KDE-Submenu[zh_TW]=解開
|
||||
|
||||
[Desktop Action arkExtractHere]
|
||||
Name=Extract Archive Here
|
||||
Name[ar]=فك الأرشيف هنا
|
||||
Name[ast]=Estrayer archivu comprimíu equí
|
||||
Name[bg]=Извличане тук
|
||||
Name[bs]=Raspakuj arhivu ovde
|
||||
Name[ca]=Extreu l'arxiu aquí
|
||||
Name[ca@valencia]=Extrau l'arxiu ací
|
||||
Name[cs]=Rozbalit archiv sem
|
||||
Name[da]=Udpak arkiv her
|
||||
Name[de]=Archiv hierher auspacken
|
||||
Name[el]=Εξαγωγή αρχειοθήκης εδώ
|
||||
Name[en_GB]=Extract Archive Here
|
||||
Name[es]=Extraer archivo comprimido aquí
|
||||
Name[et]=Paki arhiiv siia lahti
|
||||
Name[eu]=Atera artxiboa hemen
|
||||
Name[fi]=Pura paketti tähän
|
||||
Name[fr]=Extraire l'archive ici
|
||||
Name[ga]=Bain an chartlann amach agus cuir é anseo
|
||||
Name[gl]=Extraer o arquivo aquí
|
||||
Name[hr]=Ovdje otpakiraj arhivu
|
||||
Name[hu]=Kibontás ide
|
||||
Name[ia]=Extrahe archivo hic
|
||||
Name[id]=Ekstrak Arsip di Sini
|
||||
Name[it]=Estrai l'archivio qui
|
||||
Name[ja]=アーカイブをここに展開
|
||||
Name[kk]=Архивті мынаған тарқату
|
||||
Name[km]=ស្រង់ចេញប័ណ្ណសារនៅទីនេះ
|
||||
Name[ko]=여기에 압축 풀기
|
||||
Name[lt]=Čia išpakuoti archyvą
|
||||
Name[lv]=Atspiest arhīvu šeit
|
||||
Name[mr]=येथे संग्रह पुर्ववत करा
|
||||
Name[nb]=Pakk ut arkivet her
|
||||
Name[nds]=Archiev hier utpacken
|
||||
Name[nl]=Archief hier uitpakken
|
||||
Name[nn]=Pakk ut arkivet her
|
||||
Name[pa]=ਅਕਾਇਵ ਇੱਥੇ ਖੋਲ੍ਹੋ
|
||||
Name[pl]=Rozpakuj archiwum tutaj
|
||||
Name[pt]=Extrair o Pacote para Aqui
|
||||
Name[pt_BR]=Extrair arquivo aqui
|
||||
Name[ro]=Extrage arhiva aici
|
||||
Name[ru]=В эту папку
|
||||
Name[sk]=Rozbaliť archív sem
|
||||
Name[sl]=Razširi arhiv sem
|
||||
Name[sq]=Ekstrakto Arkivin Këtu
|
||||
Name[sr]=Распакуј архиву овде
|
||||
Name[sr@ijekavian]=Распакуј архиву овдје
|
||||
Name[sr@ijekavianlatin]=Raspakuj arhivu ovdje
|
||||
Name[sr@latin]=Raspakuj arhivu ovde
|
||||
Name[sv]=Packa upp arkiv här
|
||||
Name[th]=คลายแฟ้มจัดเก็บไว้ที่นี่
|
||||
Name[tr]=Arşivi Buraya Çıkart
|
||||
Name[uk]=Видобути архів сюди
|
||||
Name[wa]=Saetchî l' årtchive foû cial
|
||||
Name[x-test]=xxExtract Archive Herexx
|
||||
Name[zh_CN]=在此解压缩归档
|
||||
Name[zh_TW]=在此解壓縮
|
||||
Icon=ark
|
||||
Exec=ark --batch --autodestination %F
|
||||
|
||||
[Desktop Action arkExtractTo]
|
||||
Name=Extract Archive To...
|
||||
Name[ar]=فك الأرشيف إلى...
|
||||
Name[ast]=Estrayer archivu comprimíu en...
|
||||
Name[bg]=Извличане в...
|
||||
Name[bs]=Raspakuj arhivu u...
|
||||
Name[ca]=Extreu l'arxiu a...
|
||||
Name[ca@valencia]=Extrau l'arxiu a...
|
||||
Name[cs]=Rozbalit archiv do...
|
||||
Name[da]=Udpak arkiv til...
|
||||
Name[de]=Archiv auspacken nach ...
|
||||
Name[el]=Εξαγωγή αρχειοθήκης σε...
|
||||
Name[en_GB]=Extract Archive To...
|
||||
Name[es]=Extraer archivo comprimido en...
|
||||
Name[et]=Paki arhiiv lahti...
|
||||
Name[eu]=Atera artxiboa hona...
|
||||
Name[fi]=Pura paketti…
|
||||
Name[fr]=Extraire l'archive vers...
|
||||
Name[ga]=Bain an chartlann amach go...
|
||||
Name[gl]=Extraer o arquivo en...
|
||||
Name[hr]=Otpakiraj arhivu u …
|
||||
Name[hu]=Kibontás ide…
|
||||
Name[ia]=Extrahe archivo in...
|
||||
Name[id]=Ekstrak Arsip ke...
|
||||
Name[it]=Estrai l'archivio in...
|
||||
Name[ja]=アーカイブを展開...
|
||||
Name[kk]=Мынаған тарқату...
|
||||
Name[km]=ស្រង់ចេញប័ណ្ណសារទៅ...
|
||||
Name[ko]=다음 경로에 압축 풀기...
|
||||
Name[lt]=Išpakuoti archyvą į...
|
||||
Name[lv]=Atspiest arhīvu uz...
|
||||
Name[mr]=यावर संग्रह पुर्ववत करा...
|
||||
Name[nb]=Pakk ut arkivet til …
|
||||
Name[nds]=Archiev utpacken as...
|
||||
Name[nl]=Archief uitpakken naar...
|
||||
Name[nn]=Pakk ut arkivet til …
|
||||
Name[pa]=...ਵਜੋਂ ਅਕਾਇਵ ਐਕਸਟਰੈਕਟ
|
||||
Name[pl]=Rozpakuj archiwum do...
|
||||
Name[pt]=Extrair o Pacote Para...
|
||||
Name[pt_BR]=Extrair arquivo para...
|
||||
Name[ro]=Extrage arhiva în...
|
||||
Name[ru]=Указать путь...
|
||||
Name[sk]=Rozbaliť archív do...
|
||||
Name[sl]=Razširi arhiv v ...
|
||||
Name[sq]=Ekstrakto Arkivin Tek...
|
||||
Name[sr]=Распакуј архиву у...
|
||||
Name[sr@ijekavian]=Распакуј архиву у...
|
||||
Name[sr@ijekavianlatin]=Raspakuj arhivu u...
|
||||
Name[sr@latin]=Raspakuj arhivu u...
|
||||
Name[sv]=Packa upp arkiv i...
|
||||
Name[th]=คลายแฟ้มจัดเก็บไปยัง...
|
||||
Name[tr]=Arşivi Şuraya Çıkart...
|
||||
Name[uk]=Видобути архів до...
|
||||
Name[wa]=Saetchî l' årtchive foû eyet l' rilomer...
|
||||
Name[x-test]=xxExtract Archive To...xx
|
||||
Name[zh_CN]=解压缩归档到...
|
||||
Name[zh_TW]=解壓縮到...
|
||||
Icon=ark
|
||||
Exec=ark --batch --autodestination --dialog %F
|
||||
|
||||
[Desktop Action arkAutoExtractHere]
|
||||
Name=Extract Archive Here, Autodetect Subfolder
|
||||
Name[ar]=فك الأرشيف هنا ، تعرف تلقائي للمجلدات الفرعية
|
||||
Name[ast]=Estrayer archivu comprimíu equí, autodeteutar subcarpeta
|
||||
Name[bg]=Извличане тук, автоматична подпапка
|
||||
Name[bs]=Raspakuj arhivu ovdje, pogodi poddirektorij
|
||||
Name[ca]=Extreu l'arxiu aquí, detecta automàticament la subcarpeta
|
||||
Name[ca@valencia]=Extrau l'arxiu ací, detecta automàticament la subcarpeta
|
||||
Name[cs]=Rozbalit archiv sem, automaticky detekovat podsložku
|
||||
Name[da]=Udpak arkiv her og find automatisk undermappe
|
||||
Name[de]=Archiv hierher auspacken, Unterordner selbständig ermitteln
|
||||
Name[el]=Εξαγωγή αρχειοθήκης εδώ, αυτόματη επιλογή υποφακέλου
|
||||
Name[en_GB]=Extract Archive Here, Autodetect Subfolder
|
||||
Name[es]=Extraer archivo comprimido aquí, autodetectar subcarpeta
|
||||
Name[et]=Paki arhiiv siia lahti, tuvasta automaatselt alamkataloog
|
||||
Name[eu]=Atera artxiboa hona, automatikoki detektatu azpikarpeta
|
||||
Name[fi]=Pura paketti tähän, tunnista alikansio automaattisesti
|
||||
Name[fr]=Extraire l'archive ici, auto-détecter les sous-dossiers
|
||||
Name[ga]=Bain an chartlann amach agus cuir é anseo, braith fofhillteán go huathoibríoch
|
||||
Name[gl]=Extraer o arquivo aquí, detectar o subcartafol
|
||||
Name[hr]=Ovdje otpakiraj arhivu i automatski prepoznaj podmapu
|
||||
Name[hu]=Kibontás ide (automatikus almappalétrehozás)
|
||||
Name[ia]=Extrahe archivo hic, auto-releva subdossier
|
||||
Name[id]=Ekstrak Arsip di Sini, Deteksi Otomatis Subfolder
|
||||
Name[it]=Estrai l'archivio qui, autorileva la sottocartella
|
||||
Name[ja]=アーカイブをここに展開、サブフォルダを自動検出
|
||||
Name[kk]=Мынаған, ішкі қапшығына тарқату
|
||||
Name[km]=ស្រង់ចេញប័ណ្ណសារនៅទីនេះ រកថតរងឃើញដោយស្វ័យប្រវត្តិ
|
||||
Name[ko]=하위 폴더를 감지해서 여기에 압축 풀기
|
||||
Name[lt]=Išpakuoti archyvą čia, automatiškai rasti poaplankius
|
||||
Name[lv]=Atspiest arhīvu šeit, automātiska apakšmape
|
||||
Name[mr]=येथे संग्रह पुर्ववत करा, उपसंचयीका स्वंयंशोध
|
||||
Name[nb]=Pakk ut arkivet her, finn undermapper automatisk
|
||||
Name[nds]=Archiev hier utpacken, Ünnerorner autom. opdecken
|
||||
Name[nl]=Archief hier uitpakken, submap autodetecteren
|
||||
Name[nn]=Pakk ut arkivet her / til undermappe
|
||||
Name[pa]=ਅਕਾਇਵ ਇੱਥੇ ਖੋਲ੍ਹੋ, ਸਬ-ਫੋਲਡਰ ਆਪੇ ਖੋਜੋ
|
||||
Name[pl]=Rozpakuj archiwum tutaj, wykryj podkatalogi
|
||||
Name[pt]=Extrair o Pacote Aqui com Detecção da Sub-Pasta
|
||||
Name[pt_BR]=Extrair aqui detectando subpasta
|
||||
Name[ro]=Extrage arhiva aici, autodetectează subdosarul
|
||||
Name[ru]=Во вложенную папку
|
||||
Name[sk]=Rozbaliť archív sem, automaticky určiť podpriečinok
|
||||
Name[sl]=Razširi arhiv sem, samodejno zaznaj podmapo
|
||||
Name[sq]=Ekstrakto Arkivin Këtu, Vetëdallo Nëndosjen
|
||||
Name[sr]=Распакуј архиву овде, погоди потфасциклу
|
||||
Name[sr@ijekavian]=Распакуј архиву овдје, погоди потфасциклу
|
||||
Name[sr@ijekavianlatin]=Raspakuj arhivu ovdje, pogodi potfasciklu
|
||||
Name[sr@latin]=Raspakuj arhivu ovde, pogodi potfasciklu
|
||||
Name[sv]=Packa upp arkiv här, detektera underkatalog automatiskt
|
||||
Name[th]=คลายแฟ้มจัดเก็บไว้ที่นี่, และตรวจสอบโฟลเดอร์ย่อยอัตโนมัติ
|
||||
Name[tr]=Arşivi Buraya Çıkart, Alt Dizinleri Otomatik Belirle
|
||||
Name[uk]=Видобути архів сюди, автоматично визначити підтеку
|
||||
Name[wa]=Saetchî l' årtchive foû cial, deteccion otomatike do ridant efant
|
||||
Name[x-test]=xxExtract Archive Here, Autodetect Subfolderxx
|
||||
Name[zh_CN]=在此解压缩归档,自动探测子文件夹
|
||||
Name[zh_TW]=在此解壓縮,自動偵測子資料夾
|
||||
Icon=ark
|
||||
Exec=ark --batch --autodestination --autosubfolder %F
|
17
ark/app/arkui.rc
Normal file
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE kpartgui>
|
||||
<kpartgui name="ark" version="12">
|
||||
<MenuBar>
|
||||
<Menu name="file">
|
||||
<DefineGroup name="file_save" append="save_merge"/>
|
||||
</Menu>
|
||||
<Merge/>
|
||||
<Menu name="settings">
|
||||
<DefineGroup name="settings_show" append="show_merge"/>
|
||||
</Menu>
|
||||
</MenuBar>
|
||||
<ToolBar noMerge="1" name="mainToolBar">
|
||||
<text>Main Toolbar</text>
|
||||
<Action name="file_new"/>
|
||||
<Action name="file_open"/>
|
||||
</ToolBar>
|
||||
</kpartgui>
|
292
ark/app/batchextract.cpp
Normal file
|
@ -0,0 +1,292 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2008 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
* Copyright (C) 2009-2010 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "batchextract.h"
|
||||
|
||||
#include "kerfuffle/archive.h"
|
||||
#include "kerfuffle/extractiondialog.h"
|
||||
#include "kerfuffle/jobs.h"
|
||||
#include "kerfuffle/queries.h"
|
||||
|
||||
#include <KDebug>
|
||||
#include <KGlobal>
|
||||
#include <KLocale>
|
||||
#include <KMessageBox>
|
||||
#include <KRun>
|
||||
#include <KIO/RenameDialog>
|
||||
#include <kwidgetjobtracker.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QTimer>
|
||||
#include <QWeakPointer>
|
||||
|
||||
BatchExtract::BatchExtract()
|
||||
: KCompositeJob(0),
|
||||
m_autoSubfolder(false),
|
||||
m_preservePaths(true),
|
||||
m_openDestinationAfterExtraction(false)
|
||||
{
|
||||
setCapabilities(KJob::Killable);
|
||||
|
||||
connect(this, SIGNAL(result(KJob*)), SLOT(showFailedFiles()));
|
||||
}
|
||||
|
||||
BatchExtract::~BatchExtract()
|
||||
{
|
||||
if (!m_inputs.isEmpty()) {
|
||||
KIO::getJobTracker()->unregisterJob(this);
|
||||
}
|
||||
}
|
||||
|
||||
void BatchExtract::addExtraction(Kerfuffle::Archive* archive)
|
||||
{
|
||||
QString destination = destinationFolder();
|
||||
|
||||
if ((autoSubfolder()) && (!archive->isSingleFolderArchive())) {
|
||||
const QDir d(destination);
|
||||
QString subfolderName = archive->subfolderName();
|
||||
|
||||
if (d.exists(subfolderName)) {
|
||||
subfolderName = KIO::RenameDialog::suggestName(destination, subfolderName);
|
||||
}
|
||||
|
||||
d.mkdir(subfolderName);
|
||||
|
||||
destination += QLatin1Char( '/' ) + subfolderName;
|
||||
}
|
||||
|
||||
Kerfuffle::ExtractionOptions options;
|
||||
options[QLatin1String( "PreservePaths" )] = preservePaths();
|
||||
|
||||
Kerfuffle::ExtractJob *job = archive->copyFiles(QVariantList(), destination, options);
|
||||
|
||||
kDebug() << QString(QLatin1String( "Registering job from archive %1, to %2, preservePaths %3" )).arg(archive->fileName()).arg(destination).arg(preservePaths());
|
||||
|
||||
addSubjob(job);
|
||||
|
||||
m_fileNames[job] = qMakePair(archive->fileName(), destination);
|
||||
|
||||
connect(job, SIGNAL(percent(KJob*,ulong)),
|
||||
this, SLOT(forwardProgress(KJob*,ulong)));
|
||||
connect(job, SIGNAL(userQuery(Kerfuffle::Query*)),
|
||||
this, SLOT(slotUserQuery(Kerfuffle::Query*)));
|
||||
}
|
||||
|
||||
void BatchExtract::slotUserQuery(Kerfuffle::Query *query)
|
||||
{
|
||||
query->execute();
|
||||
}
|
||||
|
||||
bool BatchExtract::autoSubfolder() const
|
||||
{
|
||||
return m_autoSubfolder;
|
||||
}
|
||||
|
||||
void BatchExtract::setAutoSubfolder(bool value)
|
||||
{
|
||||
m_autoSubfolder = value;
|
||||
}
|
||||
|
||||
void BatchExtract::start()
|
||||
{
|
||||
QTimer::singleShot(0, this, SLOT(slotStartJob()));
|
||||
}
|
||||
|
||||
void BatchExtract::slotStartJob()
|
||||
{
|
||||
// If none of the archives could be loaded, there is no subjob to run
|
||||
if (m_inputs.isEmpty()) {
|
||||
emitResult();
|
||||
return;
|
||||
}
|
||||
|
||||
foreach(Kerfuffle::Archive *archive, m_inputs) {
|
||||
addExtraction(archive);
|
||||
}
|
||||
|
||||
KIO::getJobTracker()->registerJob(this);
|
||||
|
||||
emit description(this,
|
||||
i18n("Extracting file..."),
|
||||
qMakePair(i18n("Source archive"), m_fileNames.value(subjobs().at(0)).first),
|
||||
qMakePair(i18n("Destination"), m_fileNames.value(subjobs().at(0)).second)
|
||||
);
|
||||
|
||||
m_initialJobCount = subjobs().size();
|
||||
|
||||
kDebug() << "Starting first job";
|
||||
|
||||
subjobs().at(0)->start();
|
||||
}
|
||||
|
||||
void BatchExtract::showFailedFiles()
|
||||
{
|
||||
if (!m_failedFiles.isEmpty()) {
|
||||
KMessageBox::informationList(0, i18n("The following files could not be extracted:"), m_failedFiles);
|
||||
}
|
||||
}
|
||||
|
||||
void BatchExtract::slotResult(KJob *job)
|
||||
{
|
||||
kDebug();
|
||||
|
||||
// TODO: The user must be informed about which file caused the error, and that the other files
|
||||
// in the queue will not be extracted.
|
||||
if (job->error()) {
|
||||
kDebug() << "There was en error, " << job->errorText();
|
||||
|
||||
setErrorText(job->errorText());
|
||||
setError(job->error());
|
||||
|
||||
removeSubjob(job);
|
||||
|
||||
KMessageBox::error(NULL, job->errorText().isEmpty() ?
|
||||
i18n("There was an error during extraction.") : job->errorText()
|
||||
);
|
||||
|
||||
emitResult();
|
||||
|
||||
return;
|
||||
} else {
|
||||
removeSubjob(job);
|
||||
}
|
||||
|
||||
if (!hasSubjobs()) {
|
||||
if (openDestinationAfterExtraction()) {
|
||||
KUrl destination(destinationFolder());
|
||||
destination.cleanPath();
|
||||
KRun::runUrl(destination, QLatin1String( "inode/directory" ), 0);
|
||||
}
|
||||
|
||||
kDebug() << "Finished, emitting the result";
|
||||
emitResult();
|
||||
} else {
|
||||
kDebug() << "Starting the next job";
|
||||
emit description(this,
|
||||
i18n("Extracting file..."),
|
||||
qMakePair(i18n("Source archive"), m_fileNames.value(subjobs().at(0)).first),
|
||||
qMakePair(i18n("Destination"), m_fileNames.value(subjobs().at(0)).second)
|
||||
);
|
||||
subjobs().at(0)->start();
|
||||
}
|
||||
}
|
||||
|
||||
void BatchExtract::forwardProgress(KJob *job, unsigned long percent)
|
||||
{
|
||||
Q_UNUSED(job)
|
||||
int jobPart = 100 / m_initialJobCount;
|
||||
setPercent(jobPart *(m_initialJobCount - subjobs().size()) + percent / m_initialJobCount);
|
||||
}
|
||||
|
||||
bool BatchExtract::addInput(const KUrl& url)
|
||||
{
|
||||
Kerfuffle::Archive *archive = Kerfuffle::Archive::create(url.pathOrUrl(), this);
|
||||
|
||||
if ((archive == NULL) || (!QFileInfo(url.pathOrUrl()).exists())) {
|
||||
m_failedFiles.append(url.fileName());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_inputs.append(archive);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BatchExtract::openDestinationAfterExtraction() const
|
||||
{
|
||||
return m_openDestinationAfterExtraction;
|
||||
}
|
||||
|
||||
bool BatchExtract::preservePaths() const
|
||||
{
|
||||
return m_preservePaths;
|
||||
}
|
||||
|
||||
QString BatchExtract::destinationFolder() const
|
||||
{
|
||||
if (m_destinationFolder.isEmpty()) {
|
||||
return QDir::currentPath();
|
||||
} else {
|
||||
return m_destinationFolder;
|
||||
}
|
||||
}
|
||||
|
||||
void BatchExtract::setDestinationFolder(const QString& folder)
|
||||
{
|
||||
if (QFileInfo(folder).isDir()) {
|
||||
m_destinationFolder = folder;
|
||||
}
|
||||
}
|
||||
|
||||
void BatchExtract::setOpenDestinationAfterExtraction(bool value)
|
||||
{
|
||||
m_openDestinationAfterExtraction = value;
|
||||
}
|
||||
|
||||
void BatchExtract::setPreservePaths(bool value)
|
||||
{
|
||||
m_preservePaths = value;
|
||||
}
|
||||
|
||||
bool BatchExtract::showExtractDialog()
|
||||
{
|
||||
QWeakPointer<Kerfuffle::ExtractionDialog> dialog =
|
||||
new Kerfuffle::ExtractionDialog;
|
||||
|
||||
if (m_inputs.size() > 1) {
|
||||
dialog.data()->batchModeOption();
|
||||
}
|
||||
|
||||
dialog.data()->setAutoSubfolder(autoSubfolder());
|
||||
dialog.data()->setCurrentUrl(destinationFolder());
|
||||
dialog.data()->setPreservePaths(preservePaths());
|
||||
|
||||
if (m_inputs.size() == 1) {
|
||||
if (m_inputs.at(0)->isSingleFolderArchive()) {
|
||||
dialog.data()->setSingleFolderArchive(true);
|
||||
}
|
||||
dialog.data()->setSubfolder(m_inputs.at(0)->subfolderName());
|
||||
}
|
||||
|
||||
if (!dialog.data()->exec()) {
|
||||
delete dialog.data();
|
||||
return false;
|
||||
}
|
||||
|
||||
setAutoSubfolder(dialog.data()->autoSubfolders());
|
||||
setDestinationFolder(dialog.data()->destinationDirectory().pathOrUrl());
|
||||
setOpenDestinationAfterExtraction(dialog.data()->openDestinationAfterExtraction());
|
||||
setPreservePaths(dialog.data()->preservePaths());
|
||||
|
||||
delete dialog.data();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#include <batchextract.moc>
|
234
ark/app/batchextract.h
Normal file
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2008 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
* Copyright (C) 2009-2010 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef BATCHEXTRACT_H
|
||||
#define BATCHEXTRACT_H
|
||||
|
||||
#include <kcompositejob.h>
|
||||
#include <KUrl>
|
||||
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QPair>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
namespace Kerfuffle
|
||||
{
|
||||
class Archive;
|
||||
class Query;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class schedules the extraction of all given compressed archives.
|
||||
*
|
||||
* Like AddToArchive, this class does not need the GUI to be active, and
|
||||
* provides the functionality available from the --batch command-line option.
|
||||
*
|
||||
* @author Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
*/
|
||||
class BatchExtract : public KCompositeJob
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new BatchExtract object.
|
||||
*/
|
||||
BatchExtract();
|
||||
|
||||
/**
|
||||
* Destroys a BatchExtract object.
|
||||
*/
|
||||
virtual ~BatchExtract();
|
||||
|
||||
/**
|
||||
* Creates an ExtractJob for the given @p archive and puts it on the queue.
|
||||
*
|
||||
* If necessary, the destination directory for the archive is created.
|
||||
*
|
||||
* @param archive The archive that will be extracted.
|
||||
*
|
||||
* @see setAutoSubfolder
|
||||
*/
|
||||
void addExtraction(Kerfuffle::Archive* archive);
|
||||
|
||||
/**
|
||||
* A wrapper that calls slotStartJob() when the event loop has started.
|
||||
*/
|
||||
void start();
|
||||
|
||||
/**
|
||||
* Whether to automatically create a folder inside the destination
|
||||
* directory if the archive has more than one directory or file
|
||||
* at top level.
|
||||
*
|
||||
* @return @c true Create the subdirectory automatically.
|
||||
* @return @c false Do not create the subdirectory automatically.
|
||||
*/
|
||||
bool autoSubfolder() const;
|
||||
|
||||
/**
|
||||
* Set whether a folder should be created when necessary so
|
||||
* the archive is extracted to it.
|
||||
*
|
||||
* If set to @c true, when the archive does not consist of a
|
||||
* single folder with the other files and directories inside,
|
||||
* a directory will be automatically created inside the destination
|
||||
* directory and the archive will be extracted there.
|
||||
*
|
||||
* @param value Whether to create this directory automatically
|
||||
* when needed.
|
||||
*/
|
||||
void setAutoSubfolder(bool value);
|
||||
|
||||
/**
|
||||
* Adds a file to the list of files that will be extracted.
|
||||
*
|
||||
* @param url The file that will be added to the list.
|
||||
*
|
||||
* @return @c true The file exists and a suitable plugin
|
||||
* could be found for it.
|
||||
* @return @c false The file does not exist or a suitable
|
||||
* plugin could not be found.
|
||||
*/
|
||||
bool addInput(const KUrl& url);
|
||||
|
||||
/**
|
||||
* Shows the extract options dialog before extracting the files.
|
||||
*
|
||||
* @return @c true The user has set some options and clicked OK.
|
||||
* @return @c false The user has canceled extraction.
|
||||
*/
|
||||
bool showExtractDialog();
|
||||
|
||||
/**
|
||||
* Returns the destination directory where the archives
|
||||
* will be extracted to.
|
||||
*
|
||||
* @return The destination directory. If no directory has been manually
|
||||
* set with setDestinationFolder, QDir::currentPath() will be
|
||||
* returned.
|
||||
*/
|
||||
QString destinationFolder() const;
|
||||
|
||||
/**
|
||||
* Sets the directory the archives will be extracted to.
|
||||
*
|
||||
* If @c setSubfolder has been used, the final destination
|
||||
* directory will be the concatenation of both.
|
||||
*
|
||||
* If @p folder does not exist, the current destination
|
||||
* folder will not change.
|
||||
*
|
||||
* @param folder The directory that will be used.
|
||||
*/
|
||||
void setDestinationFolder(const QString& folder);
|
||||
|
||||
/**
|
||||
* Returns whether the destination folder should
|
||||
* be open after all archives are extracted.
|
||||
*
|
||||
* @return @c true Open the destination folder.
|
||||
* @return @c false Do not open the destination folder.
|
||||
*/
|
||||
bool openDestinationAfterExtraction() const;
|
||||
|
||||
/**
|
||||
* Whether to open the destination folder after
|
||||
* all archives are extracted.
|
||||
*
|
||||
* @param value Whether to open the destination.
|
||||
*/
|
||||
void setOpenDestinationAfterExtraction(bool value);
|
||||
|
||||
/**
|
||||
* Whether all files should be extracted to the same directory,
|
||||
* even if they're in different directories in the archive.
|
||||
*
|
||||
* This is also known as "flat" extraction.
|
||||
*
|
||||
* @return @c true Paths should be preserved.
|
||||
* @return @c false Paths should be ignored.
|
||||
*/
|
||||
bool preservePaths() const;
|
||||
|
||||
/**
|
||||
* Sets whether paths should be preserved during extraction.
|
||||
*
|
||||
* When it is set to false, all files are extracted to a single
|
||||
* directory, regardless of their hierarchy in the archive.
|
||||
*
|
||||
* @param value Whether to preserve paths.
|
||||
*/
|
||||
void setPreservePaths(bool value);
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* Updates the percentage of the job that has been completed.
|
||||
*/
|
||||
void forwardProgress(KJob *job, unsigned long percent);
|
||||
|
||||
/**
|
||||
* Shows a dialog with a list of all the files that could not
|
||||
* be successfully extracted.
|
||||
*/
|
||||
void showFailedFiles();
|
||||
|
||||
/**
|
||||
* Shows an error message if the current job hasn't finished
|
||||
* successfully, and advances to the next extraction job if
|
||||
* there are more.
|
||||
*/
|
||||
void slotResult(KJob *job);
|
||||
|
||||
/**
|
||||
* Shows a query dialog, which may happen when a file already exists.
|
||||
*/
|
||||
void slotUserQuery(Kerfuffle::Query *query);
|
||||
|
||||
/**
|
||||
* Does the real work for start() and extracts all scheduled files.
|
||||
*
|
||||
* Each extraction job is started after the last one finishes.
|
||||
* The jobs are executed in the order they were added via addInput().
|
||||
*/
|
||||
void slotStartJob();
|
||||
|
||||
private:
|
||||
int m_initialJobCount;
|
||||
QMap<KJob*, QPair<QString, QString> > m_fileNames;
|
||||
bool m_autoSubfolder;
|
||||
|
||||
QList<Kerfuffle::Archive*> m_inputs;
|
||||
QString m_destinationFolder;
|
||||
QStringList m_failedFiles;
|
||||
bool m_preservePaths;
|
||||
bool m_openDestinationAfterExtraction;
|
||||
};
|
||||
|
||||
#endif // BATCHEXTRACT_H
|
82
ark/app/extractHereDndPlugin.cpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2009 Harald Hvaal <haraldhv (at@at) stud.ntnu.no>
|
||||
*
|
||||
* 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 "extractHereDndPlugin.h"
|
||||
#include "batchextract.h"
|
||||
#include "kerfuffle/archive.h"
|
||||
|
||||
#include <KAction>
|
||||
#include <KDebug>
|
||||
#include <KPluginFactory>
|
||||
#include <KPluginLoader>
|
||||
#include <KLocale>
|
||||
#include <kfileitemlistproperties.h>
|
||||
|
||||
K_PLUGIN_FACTORY(ExtractHerePluginFactory,
|
||||
registerPlugin<ExtractHereDndPlugin>();
|
||||
)
|
||||
K_EXPORT_PLUGIN(ExtractHerePluginFactory("stupidname", "ark"))
|
||||
|
||||
void ExtractHereDndPlugin::slotTriggered()
|
||||
{
|
||||
kDebug() << "Preparing job";
|
||||
BatchExtract *batchJob = new BatchExtract();
|
||||
|
||||
batchJob->setAutoSubfolder(true);
|
||||
batchJob->setDestinationFolder(m_dest.pathOrUrl());
|
||||
batchJob->setPreservePaths(true);
|
||||
foreach(const KUrl& url, m_urls) {
|
||||
batchJob->addInput(url);
|
||||
}
|
||||
|
||||
batchJob->start();
|
||||
kDebug() << "Started job";
|
||||
|
||||
}
|
||||
|
||||
ExtractHereDndPlugin::ExtractHereDndPlugin(QObject* parent, const QVariantList&)
|
||||
: KonqDndPopupMenuPlugin(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void ExtractHereDndPlugin::setup(const KFileItemListProperties& popupMenuInfo,
|
||||
KUrl destination,
|
||||
QList<QAction*>& userActions)
|
||||
{
|
||||
const QString extractHereMessage = i18nc("@action:inmenu Context menu shown when an archive is being drag'n'dropped", "Extract here");
|
||||
|
||||
if (!Kerfuffle::supportedMimeTypes().contains(popupMenuInfo.mimeType())) {
|
||||
kDebug() << popupMenuInfo.mimeType() << "is not a supported mimetype";
|
||||
return;
|
||||
}
|
||||
|
||||
kDebug() << "Plugin executed";
|
||||
|
||||
KAction *action = new KAction(KIcon(QLatin1String("archive-extract")),
|
||||
extractHereMessage, NULL);
|
||||
connect(action, SIGNAL(triggered()), this, SLOT(slotTriggered()));
|
||||
|
||||
userActions.append(action);
|
||||
m_dest = destination;
|
||||
m_urls = popupMenuInfo.urlList();
|
||||
}
|
||||
|
||||
#include "extractHereDndPlugin.moc"
|
46
ark/app/extractHereDndPlugin.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2009 Harald Hvaal <haraldhv (at@at) stud.ntnu.no>
|
||||
*
|
||||
* 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 EXTRACTHEREDNDPLUGIN_H
|
||||
#define EXTRACTHEREDNDPLUGIN_H
|
||||
|
||||
#include <kurl.h>
|
||||
#include <konq_dndpopupmenuplugin.h>
|
||||
|
||||
class ExtractHereDndPlugin : public KonqDndPopupMenuPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void slotTriggered();
|
||||
|
||||
public:
|
||||
ExtractHereDndPlugin(QObject* parent, const QVariantList&);
|
||||
|
||||
virtual void setup(const KFileItemListProperties& popupMenuInfo,
|
||||
KUrl destination,
|
||||
QList<QAction*>& userActions);
|
||||
private:
|
||||
KUrl m_dest;
|
||||
QList<KUrl> m_urls;
|
||||
};
|
||||
|
||||
#endif /* EXTRACTHEREDNDPLUGIN_H */
|
1
ark/app/icons/CMakeLists.txt
Normal file
|
@ -0,0 +1 @@
|
|||
kde4_install_icons(${ICON_INSTALL_DIR})
|
BIN
ark/app/icons/hi128-apps-ark.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
ark/app/icons/hi16-apps-ark.png
Normal file
After Width: | Height: | Size: 528 B |
BIN
ark/app/icons/hi22-apps-ark.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
ark/app/icons/hi32-apps-ark.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
ark/app/icons/hi48-apps-ark.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
ark/app/icons/hi64-apps-ark.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
ark/app/icons/hisc-apps-ark.svgz
Normal file
210
ark/app/main.cpp
Normal file
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
|
||||
* Copyright (C) 2008-2009 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
*
|
||||
* 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 "mainwindow.h"
|
||||
#include "batchextract.h"
|
||||
#include "kerfuffle/addtoarchive.h"
|
||||
|
||||
#include <KAboutData>
|
||||
#include <KApplication>
|
||||
#include <KCmdLineArgs>
|
||||
#include <KDebug>
|
||||
#include <KLocale>
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QFileInfo>
|
||||
|
||||
using Kerfuffle::AddToArchive;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
KAboutData aboutData("ark", 0, ki18n("Ark"),
|
||||
"2.19", ki18n("KDE Archiving tool"),
|
||||
KAboutData::License_GPL,
|
||||
ki18n("(c) 1997-2011, The Various Ark Developers"),
|
||||
KLocalizedString(),
|
||||
"http://utils.kde.org/projects/ark"
|
||||
);
|
||||
|
||||
aboutData.addAuthor(ki18n("Raphael Kubo da Costa"),
|
||||
ki18n("Maintainer"),
|
||||
"rakuco@FreeBSD.org");
|
||||
aboutData.addAuthor(ki18n("Harald Hvaal"),
|
||||
ki18n("Former Maintainer"),
|
||||
"haraldhv@stud.ntnu.no");
|
||||
aboutData.addAuthor(ki18n("Henrique Pinto"),
|
||||
ki18n("Former Maintainer"),
|
||||
"henrique.pinto@kdemail.net");
|
||||
aboutData.addAuthor(ki18n("Helio Chissini de Castro"),
|
||||
ki18n("Former maintainer"),
|
||||
"helio@kde.org");
|
||||
aboutData.addAuthor(ki18n("Georg Robbers"),
|
||||
KLocalizedString(),
|
||||
"Georg.Robbers@urz.uni-hd.de");
|
||||
aboutData.addAuthor(ki18n("Roberto Selbach Teixeira"),
|
||||
KLocalizedString(),
|
||||
"maragato@kde.org");
|
||||
aboutData.addAuthor(ki18n("Francois-Xavier Duranceau"),
|
||||
KLocalizedString(),
|
||||
"duranceau@kde.org");
|
||||
aboutData.addAuthor(ki18n("Emily Ezust (Corel Corporation)"),
|
||||
KLocalizedString(),
|
||||
"emilye@corel.com");
|
||||
aboutData.addAuthor(ki18n("Michael Jarrett (Corel Corporation)"),
|
||||
KLocalizedString(),
|
||||
"michaelj@corel.com");
|
||||
aboutData.addAuthor(ki18n("Robert Palmbos"),
|
||||
KLocalizedString(),
|
||||
"palm9744@kettering.edu");
|
||||
|
||||
aboutData.addCredit(ki18n("Bryce Corkins"),
|
||||
ki18n("Icons"),
|
||||
"dbryce@attglobal.net");
|
||||
aboutData.addCredit(ki18n("Liam Smit"),
|
||||
ki18n("Ideas, help with the icons"),
|
||||
"smitty@absamail.co.za");
|
||||
aboutData.addCredit(ki18n("Andrew Smith"),
|
||||
ki18n("bkisofs code"),
|
||||
QByteArray(),
|
||||
"http://littlesvr.ca/misc/contactandrew.php");
|
||||
aboutData.setProgramIconName(QLatin1String("ark"));
|
||||
|
||||
KCmdLineArgs::init(argc, argv, &aboutData);
|
||||
KCmdLineOptions option;
|
||||
option.add("+[url]", ki18n("URL of an archive to be opened"));
|
||||
option.add("d").add("dialog", ki18n("Show a dialog for specifying the options for the operation (extract/add)"));
|
||||
option.add("o").add("destination <directory>", ki18n("Destination folder to extract to. Defaults to current path if not specified."));
|
||||
option.add(":", ki18n("Options for adding files"));
|
||||
option.add("c").add("add", ki18n("Query the user for an archive filename and add specified files to it. Quit when finished."));
|
||||
option.add("t").add("add-to <filename>", ki18n("Add the specified files to 'filename'. Create archive if it does not exist. Quit when finished."));
|
||||
option.add("p").add("changetofirstpath", ki18n("Change the current dir to the first entry and add all other entries relative to this one."));
|
||||
option.add("f").add("autofilename <suffix>", ki18n("Automatically choose a filename, with the selected suffix (for example rar, tar.gz, zip or any other supported types)"));
|
||||
option.add(":", ki18n("Options for batch extraction:"));
|
||||
option.add("b").add("batch", ki18n("Use the batch interface instead of the usual dialog. This option is implied if more than one url is specified."));
|
||||
option.add("e").add("autodestination", ki18n("The destination argument will be set to the path of the first file supplied."));
|
||||
option.add("a").add("autosubfolder", ki18n("Archive contents will be read, and if detected to not be a single folder archive, a subfolder with the name of the archive will be created."));
|
||||
KCmdLineArgs::addCmdLineOptions(option);
|
||||
KCmdLineArgs::addTempFileOption();
|
||||
|
||||
KApplication application;
|
||||
application.setQuitOnLastWindowClosed(false);
|
||||
|
||||
//session restoring
|
||||
if (application.isSessionRestored()) {
|
||||
MainWindow* window = NULL;
|
||||
|
||||
if (KMainWindow::canBeRestored(1)) {
|
||||
window = new MainWindow;
|
||||
window->restore(1);
|
||||
if (!window->loadPart()) {
|
||||
delete window;
|
||||
window = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (window == NULL) {
|
||||
return -1;
|
||||
}
|
||||
} else { //new ark window (no restored session)
|
||||
// open any given URLs
|
||||
KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
|
||||
|
||||
if (args->isSet("add") || args->isSet("add-to")) {
|
||||
AddToArchive *addToArchiveJob = new AddToArchive;
|
||||
application.connect(addToArchiveJob, SIGNAL(result(KJob*)), SLOT(quit()), Qt::QueuedConnection);
|
||||
|
||||
if (args->isSet("changetofirstpath")) {
|
||||
addToArchiveJob->setChangeToFirstPath(true);
|
||||
}
|
||||
|
||||
if (args->isSet("add-to")) {
|
||||
addToArchiveJob->setFilename(args->getOption("add-to"));
|
||||
}
|
||||
|
||||
if (args->isSet("autofilename")) {
|
||||
addToArchiveJob->setAutoFilenameSuffix(args->getOption("autofilename"));
|
||||
}
|
||||
|
||||
for (int i = 0; i < args->count(); ++i) {
|
||||
//TODO: use the returned value here?
|
||||
addToArchiveJob->addInput(args->url(i));
|
||||
}
|
||||
|
||||
if (args->isSet("dialog")) {
|
||||
if (!addToArchiveJob->showAddDialog()) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
addToArchiveJob->start();
|
||||
} else if (args->isSet("batch")) {
|
||||
BatchExtract *batchJob = new BatchExtract;
|
||||
application.connect(batchJob, SIGNAL(result(KJob*)), SLOT(quit()), Qt::QueuedConnection);
|
||||
|
||||
for (int i = 0; i < args->count(); ++i) {
|
||||
batchJob->addInput(args->url(i));
|
||||
}
|
||||
|
||||
if (args->isSet("autosubfolder")) {
|
||||
kDebug() << "Setting autosubfolder";
|
||||
batchJob->setAutoSubfolder(true);
|
||||
}
|
||||
|
||||
if (args->isSet("autodestination")) {
|
||||
QString autopath = QFileInfo(args->url(0).path()).path();
|
||||
kDebug() << "By autodestination, setting path to " << autopath;
|
||||
batchJob->setDestinationFolder(autopath);
|
||||
}
|
||||
|
||||
if (args->isSet("destination")) {
|
||||
kDebug() << "Setting destination to " << args->getOption("destination");
|
||||
batchJob->setDestinationFolder(args->getOption("destination"));
|
||||
}
|
||||
|
||||
if (args->isSet("dialog")) {
|
||||
if (!batchJob->showExtractDialog()) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
batchJob->start();
|
||||
} else {
|
||||
MainWindow *window = new MainWindow;
|
||||
if (!window->loadPart()) { // if loading the part fails
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (args->count()) {
|
||||
kDebug() << "trying to open" << args->url(0);
|
||||
|
||||
if (args->isSet("dialog")) {
|
||||
window->setShowExtractDialog(true);
|
||||
}
|
||||
window->openUrl(args->url(0));
|
||||
}
|
||||
window->show();
|
||||
}
|
||||
}
|
||||
|
||||
kDebug() << "Entering application loop";
|
||||
return application.exec();
|
||||
}
|
259
ark/app/mainwindow.cpp
Normal file
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2002-2003: Georg Robbers <Georg.Robbers@urz.uni-hd.de>
|
||||
* Copyright (C) 2003: Helio Chissini de Castro <helio@conectiva.com>
|
||||
* Copyright (C) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
|
||||
* Copyright (C) 2008 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
*
|
||||
* 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 "mainwindow.h"
|
||||
#include "kerfuffle/archive.h"
|
||||
#include "part/interface.h"
|
||||
|
||||
#include <KPluginLoader>
|
||||
#include <KPluginFactory>
|
||||
#include <KMessageBox>
|
||||
#include <KApplication>
|
||||
#include <KLocale>
|
||||
#include <KActionCollection>
|
||||
#include <KStandardAction>
|
||||
#include <KFileDialog>
|
||||
#include <KRecentFilesAction>
|
||||
#include <KGlobal>
|
||||
#include <KDebug>
|
||||
#include <KEditToolBar>
|
||||
#include <KShortcutsDialog>
|
||||
|
||||
#include <QDragEnterEvent>
|
||||
#include <QDragMoveEvent>
|
||||
#include <QWeakPointer>
|
||||
|
||||
static bool isValidArchiveDrag(const QMimeData *data)
|
||||
{
|
||||
return ((data->hasUrls()) && (data->urls().count() == 1));
|
||||
}
|
||||
|
||||
MainWindow::MainWindow(QWidget *)
|
||||
: KParts::MainWindow()
|
||||
{
|
||||
setXMLFile(QLatin1String( "arkui.rc" ));
|
||||
|
||||
setupActions();
|
||||
statusBar();
|
||||
|
||||
if (!initialGeometrySet()) {
|
||||
resize(640, 480);
|
||||
}
|
||||
setAutoSaveSettings(QLatin1String( "MainWindow" ));
|
||||
|
||||
setAcceptDrops(true);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
if (m_recentFilesAction) {
|
||||
m_recentFilesAction->saveEntries(KGlobal::config()->group("Recent Files"));
|
||||
}
|
||||
delete m_part;
|
||||
m_part = 0;
|
||||
}
|
||||
|
||||
void MainWindow::dragEnterEvent(QDragEnterEvent * event)
|
||||
{
|
||||
kDebug() << event;
|
||||
|
||||
Interface *iface = qobject_cast<Interface*>(m_part);
|
||||
if (iface->isBusy()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((event->source() == NULL) &&
|
||||
(isValidArchiveDrag(event->mimeData()))) {
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void MainWindow::dropEvent(QDropEvent * event)
|
||||
{
|
||||
kDebug() << event;
|
||||
|
||||
Interface *iface = qobject_cast<Interface*>(m_part);
|
||||
if (iface->isBusy()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((event->source() == NULL) &&
|
||||
(isValidArchiveDrag(event->mimeData()))) {
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
//TODO: if this call provokes a message box the drag will still be going
|
||||
//while the box is onscreen. looks buggy, do something about it
|
||||
openUrl(event->mimeData()->urls().at(0));
|
||||
}
|
||||
|
||||
void MainWindow::dragMoveEvent(QDragMoveEvent * event)
|
||||
{
|
||||
kDebug() << event;
|
||||
|
||||
Interface *iface = qobject_cast<Interface*>(m_part);
|
||||
if (iface->isBusy()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((event->source() == NULL) &&
|
||||
(isValidArchiveDrag(event->mimeData()))) {
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWindow::loadPart()
|
||||
{
|
||||
KPluginLoader loader(QLatin1String( "arkpart" ));
|
||||
KPluginFactory *factory = loader.factory();
|
||||
if (factory) {
|
||||
m_part = static_cast<KParts::ReadWritePart*>(factory->create<KParts::ReadWritePart>(this));
|
||||
}
|
||||
if (!factory || !m_part) {
|
||||
KMessageBox::error(this, i18n("Unable to find Ark's KPart component, please check your installation."));
|
||||
kWarning() << "Error loading Ark KPart: " << loader.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_part->setObjectName( QLatin1String("ArkPart" ));
|
||||
setCentralWidget(m_part->widget());
|
||||
createGUI(m_part);
|
||||
|
||||
connect(m_part, SIGNAL(busy()), this, SLOT(updateActions()));
|
||||
connect(m_part, SIGNAL(ready()), this, SLOT(updateActions()));
|
||||
connect(m_part, SIGNAL(quit()), this, SLOT(quit()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MainWindow::setupActions()
|
||||
{
|
||||
m_newAction = KStandardAction::openNew(this, SLOT(newArchive()), actionCollection());
|
||||
m_openAction = KStandardAction::open(this, SLOT(openArchive()), actionCollection());
|
||||
KStandardAction::quit(this, SLOT(quit()), actionCollection());
|
||||
|
||||
m_recentFilesAction = KStandardAction::openRecent(this, SLOT(openUrl(KUrl)), actionCollection());
|
||||
m_recentFilesAction->setToolBarMode(KRecentFilesAction::MenuMode);
|
||||
m_recentFilesAction->setToolButtonPopupMode(QToolButton::DelayedPopup);
|
||||
m_recentFilesAction->setIconText(i18nc("action, to open an archive", "Open"));
|
||||
m_recentFilesAction->setStatusTip(i18n("Click to open an archive, click and hold to open a recently-opened archive"));
|
||||
m_recentFilesAction->setToolTip(i18n("Open an archive"));
|
||||
m_recentFilesAction->loadEntries(KGlobal::config()->group("Recent Files"));
|
||||
connect(m_recentFilesAction, SIGNAL(triggered()),
|
||||
this, SLOT(openArchive()));
|
||||
|
||||
createStandardStatusBarAction();
|
||||
|
||||
KStandardAction::configureToolbars(this, SLOT(editToolbars()), actionCollection());
|
||||
KStandardAction::keyBindings(this, SLOT(editKeyBindings()), actionCollection());
|
||||
}
|
||||
|
||||
void MainWindow::updateActions()
|
||||
{
|
||||
Interface *iface = qobject_cast<Interface*>(m_part);
|
||||
m_newAction->setEnabled(!iface->isBusy());
|
||||
m_openAction->setEnabled(!iface->isBusy());
|
||||
m_recentFilesAction->setEnabled(!iface->isBusy());
|
||||
}
|
||||
|
||||
void MainWindow::editKeyBindings()
|
||||
{
|
||||
KShortcutsDialog dlg(KShortcutsEditor::AllActions, KShortcutsEditor::LetterShortcutsAllowed, this);
|
||||
dlg.addCollection(actionCollection());
|
||||
dlg.addCollection(m_part->actionCollection());
|
||||
|
||||
dlg.configure();
|
||||
}
|
||||
|
||||
void MainWindow::editToolbars()
|
||||
{
|
||||
saveMainWindowSettings(KGlobal::config()->group(QLatin1String("MainWindow")));
|
||||
|
||||
QWeakPointer<KEditToolBar> dlg = new KEditToolBar(factory(), this);
|
||||
dlg.data()->exec();
|
||||
|
||||
createGUI(m_part);
|
||||
|
||||
applyMainWindowSettings(KGlobal::config()->group(QLatin1String("MainWindow")));
|
||||
|
||||
delete dlg.data();
|
||||
}
|
||||
|
||||
void MainWindow::openArchive()
|
||||
{
|
||||
Interface *iface = qobject_cast<Interface*>(m_part);
|
||||
Q_ASSERT(iface);
|
||||
const KUrl url = KFileDialog::getOpenUrl(KUrl("kfiledialog:///ArkOpenDir"),
|
||||
Kerfuffle::supportedMimeTypes().join( QLatin1String( " " )),
|
||||
this);
|
||||
openUrl(url);
|
||||
}
|
||||
|
||||
void MainWindow::openUrl(const KUrl& url)
|
||||
{
|
||||
if (!url.isEmpty()) {
|
||||
m_part->setArguments(m_openArgs);
|
||||
|
||||
if (m_part->openUrl(url)) {
|
||||
m_recentFilesAction->addUrl(url);
|
||||
} else {
|
||||
m_recentFilesAction->removeUrl(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::setShowExtractDialog(bool option)
|
||||
{
|
||||
if (option) {
|
||||
m_openArgs.metaData()[QLatin1String( "showExtractDialog" )] = QLatin1String( "true" );
|
||||
} else {
|
||||
m_openArgs.metaData().remove(QLatin1String( "showExtractDialog" ));
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::quit()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void MainWindow::newArchive()
|
||||
{
|
||||
Interface *iface = qobject_cast<Interface*>(m_part);
|
||||
Q_ASSERT(iface);
|
||||
|
||||
const QStringList mimeTypes = Kerfuffle::supportedWriteMimeTypes();
|
||||
|
||||
kDebug() << "Supported mimetypes are" << mimeTypes.join( QLatin1String( " " ));
|
||||
|
||||
const KUrl saveFileUrl =
|
||||
KFileDialog::getSaveUrl(KUrl("kfiledialog:///ArkNewDir"),
|
||||
mimeTypes.join(QLatin1String(" ")));
|
||||
|
||||
m_openArgs.metaData()[QLatin1String( "createNewArchive" )] = QLatin1String( "true" );
|
||||
|
||||
openUrl(saveFileUrl);
|
||||
|
||||
m_openArgs.metaData().remove(QLatin1String( "showExtractDialog" ));
|
||||
m_openArgs.metaData().remove(QLatin1String( "createNewArchive" ));
|
||||
}
|
66
ark/app/mainwindow.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
|
||||
* Copyright (C) 2008 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
*
|
||||
* 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 MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <KParts/MainWindow>
|
||||
#include <KParts/ReadWritePart>
|
||||
#include <KUrl>
|
||||
|
||||
class KRecentFilesAction;
|
||||
|
||||
class MainWindow: public KParts::MainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MainWindow(QWidget *parent = 0);
|
||||
~MainWindow();
|
||||
bool loadPart();
|
||||
|
||||
void dragEnterEvent(class QDragEnterEvent * event);
|
||||
void dropEvent(class QDropEvent * event);
|
||||
void dragMoveEvent(class QDragMoveEvent * event);
|
||||
|
||||
public slots:
|
||||
void openUrl(const KUrl& url);
|
||||
void setShowExtractDialog(bool);
|
||||
|
||||
private slots:
|
||||
void updateActions();
|
||||
void newArchive();
|
||||
void openArchive();
|
||||
void quit();
|
||||
|
||||
void editKeyBindings();
|
||||
void editToolbars();
|
||||
|
||||
private:
|
||||
void setupActions();
|
||||
|
||||
KParts::ReadWritePart *m_part;
|
||||
KRecentFilesAction *m_recentFilesAction;
|
||||
QAction *m_openAction;
|
||||
QAction *m_newAction;
|
||||
KParts::OpenUrlArguments m_openArgs;
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
22
ark/cmake/modules/COPYING-CMAKE-SCRIPTS
Normal file
|
@ -0,0 +1,22 @@
|
|||
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.
|
46
ark/cmake/modules/FindLibArchive.cmake
Normal file
|
@ -0,0 +1,46 @@
|
|||
# - Try to find libarchive
|
||||
# Once done this will define
|
||||
#
|
||||
# LIBARCHIVE_FOUND - system has libarchive
|
||||
# LIBARCHIVE_INCLUDE_DIR - the libarchive include directory
|
||||
# LIBARCHIVE_LIBRARY - Link this to use libarchive
|
||||
# HAVE_LIBARCHIVE_GZIP_SUPPORT - whether libarchive has been compiled with gzip support
|
||||
# HAVE_LIBARCHIVE_LZMA_SUPPORT - whether libarchive has been compiled with lzma support
|
||||
# HAVE_LIBARCHIVE_XZ_SUPPORT - whether libarchive has been compiled with xz support
|
||||
# HAVE_LIBARCHIVE_RPM_SUPPORT - whether libarchive has been compiled with rpm support
|
||||
# HAVE_LIBARCHIVE_CAB_SUPPORT - whether libarchive has been compiled with cab support
|
||||
#
|
||||
# Copyright (c) 2006, Pino Toscano, <toscano.pino@tiscali.it>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
include(CheckLibraryExists)
|
||||
|
||||
if (LIBARCHIVE_LIBRARY AND LIBARCHIVE_INCLUDE_DIR)
|
||||
# in cache already
|
||||
set(LIBARCHIVE_FOUND TRUE)
|
||||
else (LIBARCHIVE_LIBRARY AND LIBARCHIVE_INCLUDE_DIR)
|
||||
find_path(LIBARCHIVE_INCLUDE_DIR archive.h
|
||||
${GNUWIN32_DIR}/include
|
||||
)
|
||||
|
||||
find_library(LIBARCHIVE_LIBRARY NAMES archive libarchive archive2 libarchive2
|
||||
PATHS
|
||||
${GNUWIN32_DIR}/lib
|
||||
)
|
||||
|
||||
if (LIBARCHIVE_LIBRARY)
|
||||
check_library_exists(${LIBARCHIVE_LIBRARY} archive_write_set_compression_gzip "" HAVE_LIBARCHIVE_GZIP_SUPPORT)
|
||||
check_library_exists(${LIBARCHIVE_LIBRARY} archive_write_set_compression_lzma "" HAVE_LIBARCHIVE_LZMA_SUPPORT)
|
||||
check_library_exists(${LIBARCHIVE_LIBRARY} archive_write_set_compression_xz "" HAVE_LIBARCHIVE_XZ_SUPPORT)
|
||||
check_library_exists(${LIBARCHIVE_LIBRARY} archive_read_support_compression_rpm "" HAVE_LIBARCHIVE_RPM_SUPPORT)
|
||||
check_library_exists(${LIBARCHIVE_LIBRARY} archive_read_disk_entry_from_file "" HAVE_LIBARCHIVE_READ_DISK_API)
|
||||
check_library_exists(${LIBARCHIVE_LIBRARY} archive_read_support_format_cab "" HAVE_LIBARCHIVE_CAB_SUPPORT)
|
||||
endif (LIBARCHIVE_LIBRARY)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(LibArchive DEFAULT_MSG LIBARCHIVE_INCLUDE_DIR LIBARCHIVE_LIBRARY HAVE_LIBARCHIVE_GZIP_SUPPORT)
|
||||
|
||||
mark_as_advanced(LIBARCHIVE_INCLUDE_DIR LIBARCHIVE_LIBRARY HAVE_LIBARCHIVE_GZIP_SUPPORT HAVE_LIBARCHIVE_LZMA_SUPPORT HAVE_LIBARCHIVE_RPM_SUPPORT HAVE_LIBARCHIVE_CAB_SUPPORT)
|
||||
endif (LIBARCHIVE_LIBRARY AND LIBARCHIVE_INCLUDE_DIR)
|
2
ark/config.h.cmake
Normal file
|
@ -0,0 +1,2 @@
|
|||
#cmakedefine HAVE_LIBARCHIVE_LZMA_SUPPORT ${HAVE_LIBARCHIVE_LZMA_SUPPORT}
|
||||
#cmakedefine HAVE_LIBARCHIVE_XZ_SUPPORT ${HAVE_LIBARCHIVE_XZ_SUPPORT}
|
5
ark/doc/CMakeLists.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
########### install files ###############
|
||||
#
|
||||
kde4_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR ark)
|
||||
kde4_create_manpage(man-ark.1.docbook 1 INSTALL_DESTINATION ${MAN_INSTALL_DIR})
|
||||
|
BIN
ark/doc/ark-mainwindow.png
Normal file
After Width: | Height: | Size: 53 KiB |
336
ark/doc/index.docbook
Normal file
|
@ -0,0 +1,336 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!DOCTYPE book PUBLIC "-//KDE//DTD DocBook XML V4.2-Based Variant V1.1//EN" "dtd/kdex.dtd" [
|
||||
<!ENTITY kappname "&ark;">
|
||||
<!ENTITY package "kdeutils">
|
||||
<!ENTITY % addindex "IGNORE">
|
||||
<!ENTITY % English "INCLUDE" > <!-- change language only here -->
|
||||
]>
|
||||
|
||||
<book id="ark" lang="&language;">
|
||||
|
||||
<bookinfo>
|
||||
<title>The &ark; Handbook</title>
|
||||
|
||||
<authorgroup>
|
||||
<author>
|
||||
&Matt.Johnston; &Matt.Johnston.mail;
|
||||
</author>
|
||||
|
||||
<!-- TRANS:ROLES_OF_TRANSLATORS -->
|
||||
</authorgroup>
|
||||
|
||||
<copyright>
|
||||
<year>2000</year>
|
||||
<holder>&Matt.Johnston;</holder>
|
||||
</copyright>
|
||||
|
||||
<copyright>
|
||||
<year>2004</year>
|
||||
<holder>Henrique Pinto</holder>
|
||||
</copyright>
|
||||
|
||||
|
||||
<legalnotice>&FDLNotice;</legalnotice>
|
||||
|
||||
<date>2013-06-21</date>
|
||||
<releaseinfo>2.19 &kde; (4.11)</releaseinfo>
|
||||
|
||||
<abstract>
|
||||
<para>&ark; is an archive manager for &kde;.</para></abstract>
|
||||
|
||||
<keywordset>
|
||||
<keyword>KDE</keyword>
|
||||
<keyword>gzip</keyword>
|
||||
<keyword>gunzip</keyword>
|
||||
<keyword>tar</keyword>
|
||||
<keyword>archive</keyword>
|
||||
<keyword>zip</keyword>
|
||||
<keyword>compression</keyword>
|
||||
<keyword>7z</keyword>
|
||||
<keyword>kdeutils</keyword>
|
||||
<keyword>ark</keyword>
|
||||
</keywordset>
|
||||
</bookinfo>
|
||||
|
||||
<chapter id="introduction">
|
||||
<title>Introduction</title>
|
||||
|
||||
<para>&ark; is a program for viewing, extracting, creating and modifying
|
||||
archives.
|
||||
&ark; can handle various archive formats such as
|
||||
<command>tar</command>, <command>gzip</command>,
|
||||
<command>bzip2</command>, <command>zip</command>, <command>rar</command>,
|
||||
<command>7zip</command>, <command>xz</command>, <command>rpm</command>,
|
||||
<command>cab</command> and <command>deb</command> (support for certain archive formats depend on
|
||||
the appropriate command-line programs being installed).</para>
|
||||
|
||||
<screenshot>
|
||||
<screeninfo>&ark;'s main window</screeninfo>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="ark-mainwindow.png" format="PNG"/>
|
||||
</imageobject>
|
||||
<textobject>
|
||||
<phrase>&ark;'s main window</phrase>
|
||||
</textobject>
|
||||
</mediaobject>
|
||||
</screenshot>
|
||||
|
||||
</chapter>
|
||||
|
||||
<chapter id="using-ark">
|
||||
<title>Using &ark;</title>
|
||||
|
||||
<sect1 id="ark-open">
|
||||
<title>Opening Archives</title>
|
||||
|
||||
<para>To open an archive in &ark;, choose
|
||||
<guimenuitem>Open...</guimenuitem> (<keycombo
|
||||
action="simul">&Ctrl;<keycap>O</keycap></keycombo>) from the <guimenu>File</guimenu>
|
||||
menu. You can also open archive files by dragging and dropping from
|
||||
&konqueror; or &dolphin;. Archive files should be associated with &ark;, so you can
|
||||
also <mousebutton>right</mousebutton> click a file in &konqueror; or &dolphin; and
|
||||
select <guimenuitem>Open with &ark;</guimenuitem> to open it or select an extract action for this file.</para>
|
||||
|
||||
<para>If you have enabled the information panel in the <guimenu>Settings</guimenu> menu
|
||||
additional information about the selected folders or files in the archive is displayed.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="ark-work-files">
|
||||
<title>Working with Files</title>
|
||||
|
||||
<para>Once an archive has been opened, you can perform various
|
||||
operations on the files inside the archive. By
|
||||
selecting a file and using the <guimenu>Action</guimenu>
|
||||
menu, you can choose what you want to do:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><guimenuitem>Add File...</guimenuitem> will add files from your disk to the archive.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><guimenuitem>Add Folder...</guimenuitem> will add folders from your disk to the archive.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><guimenuitem>Delete</guimenuitem> (<keycap>Del</keycap>) will remove the currently
|
||||
selected file(s) from the archive.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><guimenuitem>Extract...</guimenuitem> (<keycombo
|
||||
action="simul">&Ctrl;<keycap>E</keycap></keycombo>) opens a submenu with previously accessed folders,
|
||||
and you can select to quick extract into any of them.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><guimenuitem>Preview</guimenuitem> will open the file in the associated viewer for that file type.</para>
|
||||
<!-- File Associations Embedding first item in Service Preference Order for a file type-->
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</sect1>
|
||||
<sect1 id="ark-extract">
|
||||
<title>Extracting Archives and Removing Files</title>
|
||||
|
||||
<para>Once an archive has been opened in &ark;, it can be extracted. To
|
||||
quick extract files from an archive, you can select
|
||||
<guisubmenu>Extract</guisubmenu> from the
|
||||
<guimenu>Action</guimenu> menu. This opens a submenu with previously accessed folders,
|
||||
and you can select to quick extract into any of them. Clicking on the check mark at
|
||||
the right side of the <guibutton>Extract</guibutton> button in the toolbar performes the same action.
|
||||
</para>
|
||||
<para>
|
||||
To open the <guilabel>Extract</guilabel> dialog click the <guibutton>Extract</guibutton>
|
||||
button in the toolbar or use the shortcut <keycombo action="simul">&Ctrl;
|
||||
<keycap>E</keycap></keycombo>.
|
||||
|
||||
This dialog allows you to select where you will extract files to. The default
|
||||
location is the folder the archive is in.</para>
|
||||
<para>You can specify to extract the files into a subfolder. The default name of this
|
||||
subfolder is the first part of the archive name, but you can edit it to your needs.
|
||||
If you want to preserve paths when extracting, select this option.
|
||||
You may also choose to open the destination folder
|
||||
in &konqueror; or &dolphin; or close &ark; once the extraction is complete.</para>
|
||||
|
||||
<para>If a file in the archive list is highlighted, you can
|
||||
also select which files to extract:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><guimenuitem>Selected files only</guimenuitem> extracts only the files
|
||||
which have been selected.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><guimenuitem>All files</guimenuitem> extracts the entire contents of the
|
||||
archive.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>To extract a single file from an archive, click on the filename and drag it to the
|
||||
target folder
|
||||
</para>
|
||||
<!--FIXME extract several files by drag + drop? - only in basyskom branch-->
|
||||
<para>Extracting files from an archive does not change the archive and its contents.
|
||||
Use <menuchoice><guimenu>Action</guimenu><guimenuitem>Delete</guimenuitem></menuchoice>
|
||||
(<keysym>Del</keysym>) for this task.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="ark-create">
|
||||
<title>Creating Archives and Adding Files</title>
|
||||
|
||||
<para>To create a new archive in &ark;, choose
|
||||
<guimenuitem>New</guimenuitem> from the <guimenu>File</guimenu>
|
||||
menu.</para>
|
||||
|
||||
<para>You can then type the name of the archive, with the appropriate
|
||||
extension (<literal role="extension">tar.gz</literal>, <literal
|
||||
role="extension">zip</literal>, <literal role="extension">bz2</literal>
|
||||
&etc;) or select a supported format in the <guilabel>Filter</guilabel> combo box
|
||||
and check the <guilabel>Automatically select filename extension</guilabel> option.
|
||||
To add files to the archive, choose <guimenuitem>Add
|
||||
File...</guimenuitem> from the <guimenu>Action</guimenu> menu. If you
|
||||
want to add an entire folder to an archive, choose <guimenuitem>Add
|
||||
Folder...</guimenuitem> from the <guimenu>Action</guimenu> menu.</para>
|
||||
|
||||
<para>An alternative way to add files to the archive is to drag one or more files
|
||||
from &konqueror;, &dolphin; or the desktop into the main &ark; window, and it will
|
||||
be added to the current archive.</para>
|
||||
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
<chapter id="ark-in_filemanager">
|
||||
<title>Using &ark; in the Filemanager</title>
|
||||
|
||||
<para>Clicking with the &RMB; on an archive in a filemanager like &dolphin; or &konqueror;
|
||||
displays a context menu with an item <guimenuitem>Open with Ark</guimenuitem>.
|
||||
The menu has these additional items to extract an archive using &ark;:
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><guimenuitem>Extract Archive Here, Autodetect Subfolder</guimenuitem> creates a
|
||||
subfolder in the folder with the archive and extracts the folders and files into it.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><guimenuitem>Extract Archive To...</guimenuitem> works like in &ark;.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><guimenuitem>Extract Archive Here</guimenuitem> extracts the content of the archive into same folder.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
&dolphin;'s or &konqueror;'s context menu for a selection displays these actions in the
|
||||
<guimenu>Compress</guimenu> submenu:
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><guimenuitem>Here</guimenuitem> creates a Tar archive (gzip-compressed) in the current folder
|
||||
with the extension <filename class="extension">.tar.gz</filename>.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><guimenuitem>As ZIP Archive</guimenuitem>, <guimenuitem>As RAR Archive</guimenuitem>
|
||||
or <guimenuitem>As ZIP/TAR Archive</guimenuitem> creates these archive types in the current folder.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><guimenuitem>Compress To...</guimenuitem> opens a dialog where you can select folder, name and archive type.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</chapter>
|
||||
|
||||
<chapter id="batchmode">
|
||||
<title>Advanced Batch Mode</title>
|
||||
<para>&ark; has an advanced batch mode to manage archives without launching a &GUI; interface.
|
||||
This mode allows you to extract or create archives and add files to them.</para>
|
||||
|
||||
<para>The batch mode is documented in <ulink url="man:/ark">&ark;'s man page</ulink>.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="credits">
|
||||
|
||||
<title>Credits and License</title>
|
||||
|
||||
<para>&ark; is Copyright © 1997-2008, The Various &ark; Developers</para>
|
||||
|
||||
<itemizedlist>
|
||||
<title>Authors:</title>
|
||||
<listitem><para>Raphael Kubo da Costa
|
||||
<email>rakuco@FreeBSD.org</email></para></listitem>
|
||||
<listitem><para>Harald Hvaal
|
||||
<email>haraldhv@stud.ntnu.no</email></para></listitem>
|
||||
<listitem><para>Helio Chissini de Castro
|
||||
<email>helio@conectiva.com.br</email></para></listitem>
|
||||
<listitem><para>Georg Robbers
|
||||
<email>Georg.Robbers@urz.uni-hd.de</email></para></listitem>
|
||||
<listitem><para>Henrique Pinto
|
||||
<email>henrique.pinto@kdemail.net</email></para></listitem>
|
||||
<listitem><para>Roberto Selbach Teixeira
|
||||
<email>maragato@kde.org</email></para></listitem>
|
||||
<listitem><para>Robert Palmbos
|
||||
<email>palm9744@kettering.edu</email></para></listitem>
|
||||
<listitem><para>Francois-Xavier Duranceau
|
||||
<email>duranceau@kde.org</email></para></listitem>
|
||||
<listitem><para>Corel Corporation (author: Emily Ezust)
|
||||
<email>emilye@corel.com</email></para></listitem>
|
||||
<listitem><para>Corel Corporation (author: Michael Jarrett)
|
||||
<email>michaelj@corel.com</email></para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>Documentation Copyright © 2000 &Matt.Johnston;
|
||||
&Matt.Johnston.mail;</para>
|
||||
|
||||
<para>Documentation updated for &kde; 3.3 by Henrique Pinto
|
||||
<email>henrique.pinto@kdemail.net</email>.</para>
|
||||
|
||||
<!-- TRANS:CREDIT_FOR_TRANSLATORS -->
|
||||
&underFDL;
|
||||
&underGPL;
|
||||
|
||||
</chapter>
|
||||
|
||||
<appendix id="installation">
|
||||
<title>Installation</title>
|
||||
|
||||
<sect1 id="getting-ark">
|
||||
<title>How to obtain &ark;</title>
|
||||
|
||||
&install.intro.documentation;
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="requirements">
|
||||
<title>Requirements</title>
|
||||
|
||||
<para>In order to successfully use &ark;, you need &kde;
|
||||
4. &GNU; <command>tar</command> and a recent
|
||||
<command>gzip</command> are also needed if you want &ark; to handle tar archives. To handle other
|
||||
file formats, you need the appropriate command line programs, such as <command>bzip2</command>,
|
||||
<command>zip</command>, <command>unzip</command>, <command>ar</command>, <command>rar</command>,
|
||||
<command>7zip</command>, <command>xz</command>, <command>rpm</command>,
|
||||
<command>cab</command> and <command>deb</command>.</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="compilation">
|
||||
<title>Compilation and Installation</title>
|
||||
|
||||
&install.compile.documentation;
|
||||
|
||||
</sect1>
|
||||
|
||||
</appendix>
|
||||
|
||||
&documentation.index;
|
||||
</book>
|
||||
|
||||
<!--
|
||||
Local Variables:
|
||||
mode: sgml
|
||||
sgml-minimize-attributes: nil
|
||||
sgml-general-insert-case: lower
|
||||
End:
|
||||
-->
|
||||
|
208
ark/doc/man-ark.1.docbook
Normal file
|
@ -0,0 +1,208 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!DOCTYPE refentry PUBLIC "-//KDE//DTD DocBook XML V4.2-Based Variant V1.1//EN" "dtd/kdex.dtd" [
|
||||
<!ENTITY kappname "&ark;">
|
||||
<!ENTITY % English "INCLUDE">
|
||||
]>
|
||||
|
||||
<refentry lang="&language;">
|
||||
<refentryinfo>
|
||||
<title>&kde; User's Manual</title>
|
||||
<author><firstname>Lauri</firstname><surname>Watts</surname> <contrib>Initial version of &ark; man page.</contrib></author>
|
||||
|
||||
<author><firstname>Raphael</firstname><surname>Kubo da Costa</surname> <contrib>Update &ark; man page.</contrib></author>
|
||||
|
||||
<date>2013-08-23</date>
|
||||
<releaseinfo>2.19 (&kde; 4.11)</releaseinfo>
|
||||
<productname>K Desktop Environment</productname>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle><command>ark</command></refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname><command>ark</command></refname>
|
||||
<refpurpose>&kde; archiving tool</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>ark</command>
|
||||
<group choice="opt"><option>-b</option></group>
|
||||
<group choice="opt"><option>-a</option></group>
|
||||
<group choice="opt"><option>-e</option></group>
|
||||
<group choice="opt"><option>-c</option></group>
|
||||
<group choice="opt"><option>-f</option> <replaceable>
|
||||
suffix</replaceable></group>
|
||||
<group choice="opt"><option>-p</option></group>
|
||||
<group choice="opt"><option>-t</option> <replaceable>
|
||||
file</replaceable></group>
|
||||
<group choice="opt"><option>-d</option></group>
|
||||
<group choice="opt"><option>-o</option> <replaceable>
|
||||
directory</replaceable></group>
|
||||
<arg choice="opt">&kde; Generic Options</arg>
|
||||
<arg choice="opt">&Qt; Generic Options</arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
<para>&ark; is a program for managing various compressed file formats
|
||||
within &kde;. Archives can be viewed, extracted, created
|
||||
and modified with &ark;. The program can handle various
|
||||
formats such as <application>tar</application>,
|
||||
<application>gzip</application>, <application>bzip2</application>,
|
||||
<application>zip</application>, <application>rar</application>
|
||||
(when the appropriate libraries or command-line programs are
|
||||
installed).</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Operation modes</title>
|
||||
<para>&ark; can be used either as a stand-alone &GUI; program as well as a
|
||||
command-line program in order to perform some specific tasks.</para>
|
||||
<para>If invoked without the -b (--batch) or -c (--add) options, &ark; is started
|
||||
as a normal &GUI; program.</para>
|
||||
<para>When the -b (--batch) option is used, &ark; can be used to extract the
|
||||
contents of one or more files directly from the command-line, without
|
||||
launching its &GUI;.</para>
|
||||
<para>When the -c (--add) option is used, &ark; prompts for files that should
|
||||
be added to a new archive or to an existing archive.</para>
|
||||
<para></para>
|
||||
<para></para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Options</title>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>-d, --dialog</option></term>
|
||||
<listitem>
|
||||
<para>Show a dialog for specifying the options for a batch or add operation.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-o, --destination
|
||||
<replaceable>directory</replaceable></option></term>
|
||||
<listitem><para>Default the extraction directory to <replaceable>directory</replaceable>.
|
||||
If not passed, the current path is used.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<refsect2>
|
||||
<title>Options for adding files</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>-c, --add</option></term>
|
||||
<listitem>
|
||||
<para>Query the user for an archive filename and add specified files to it.
|
||||
Quit when finished.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-t, --add-to <replaceable>filename</replaceable></option></term>
|
||||
<listitem>
|
||||
<para>Add the specified files to <replaceable>filename</replaceable>. Create archive
|
||||
if it does not exist. Quit when finished.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-p, --changetofirstpath</option></term>
|
||||
<listitem>
|
||||
<para>Change the current directory to the first entry and add all other entries relative
|
||||
to this one.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-f, --autofilename <replaceable>suffix</replaceable></option></term>
|
||||
<listitem>
|
||||
<para>Automatically choose a filename, with the selected <replaceable>suffix</replaceable>
|
||||
(for example rar, tar.gz, zip or any other supported types).</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title>Options for batch extraction</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>-b, --batch</option></term>
|
||||
<listitem>
|
||||
<para>Use the batch interface instead of the usual dialog. This option is implied
|
||||
if more than one url is specified.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-e, --autodestination</option></term>
|
||||
<listitem>
|
||||
<para>The destination argument will be set to the path of the first file
|
||||
supplied.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-a, --autosubfolder</option></term>
|
||||
<listitem>
|
||||
<para>Archive contents will be read, and if detected to not be a single folder archive,
|
||||
a subfolder by the name of the archive will be created.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</refsect2>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Examples</title>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><userinput><command>ark</command> <option>--batch</option>
|
||||
<replaceable>archive.tar.bz2</replaceable></userinput></term>
|
||||
<listitem>
|
||||
<para>Will extract <replaceable>archive.tar.bz2</replaceable> into the current directory
|
||||
without showing any &GUI;.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><userinput><command>ark</command> <option>-b</option> <option>-d</option>
|
||||
<replaceable>archive.tar.bz2</replaceable> <replaceable>archive2.zip</replaceable></userinput></term>
|
||||
<listitem>
|
||||
<para>Will first show an extraction options dialog and then extract both
|
||||
<replaceable>archive.tar.bz2</replaceable> and <replaceable>archive2.zip</replaceable>
|
||||
into the directory chosen in the dialog.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><userinput><command>ark</command> <option>--add-to</option>
|
||||
<replaceable>my-archive.zip</replaceable> <replaceable>photo1.jpg</replaceable>
|
||||
<replaceable>text.txt</replaceable></userinput></term>
|
||||
<listitem>
|
||||
<para>Will create <replaceable>my-archive.zip</replaceable> if does not exist and
|
||||
then add <replaceable>photo1.jpg</replaceable> and <replaceable>text.txt</replaceable> to it.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Authors</title>
|
||||
<para>&ark; is currently maintained by &Harald.Hvaal; &Harald.Hvaal.mail;
|
||||
and &Raphael.Kubo.da.Costa; &Raphael.Kubo.da.Costa.mail;.</para>
|
||||
<para>This man page was first written by &Lauri.Watts;
|
||||
&Lauri.Watts.mail; in 2005 for &kde; 3.4, and was later updated in 2009 by
|
||||
&Raphael.Kubo.da.Costa; &Raphael.Kubo.da.Costa.mail;.</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
50
ark/kerfuffle/CMakeLists.txt
Normal file
|
@ -0,0 +1,50 @@
|
|||
macro_optional_find_package(QJSON)
|
||||
macro_log_feature(QJSON_FOUND "qjson" "A library for processing and serializing JSON files" "http://qjson.sourceforge.net" FALSE "" "Required for compiling Ark's unit tests")
|
||||
|
||||
########### next target ###############
|
||||
|
||||
set(kerfuffle_SRCS
|
||||
archive.cpp
|
||||
archiveinterface.cpp
|
||||
jobs.cpp
|
||||
extractiondialog.cpp
|
||||
adddialog.cpp
|
||||
queries.cpp
|
||||
addtoarchive.cpp
|
||||
cliinterface.cpp
|
||||
)
|
||||
|
||||
kde4_add_kcfg_files(kerfuffle_SRCS settings.kcfgc)
|
||||
|
||||
kde4_add_ui_files(kerfuffle_SRCS extractiondialog.ui adddialog.ui )
|
||||
|
||||
kde4_add_library(kerfuffle SHARED ${kerfuffle_SRCS})
|
||||
|
||||
target_link_libraries(kerfuffle ${KDE4_KFILE_LIBS} ${KDE4_KPARTS_LIBS})
|
||||
if (NOT WIN32)
|
||||
target_link_libraries(kerfuffle ${KDE4_KPTY_LIBS})
|
||||
endif (NOT WIN32)
|
||||
|
||||
set_target_properties(kerfuffle PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION})
|
||||
|
||||
install(TARGETS kerfuffle ${INSTALL_TARGETS_DEFAULT_ARGS})
|
||||
|
||||
install(FILES kerfufflePlugin.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR})
|
||||
install(FILES ark.kcfg DESTINATION ${KCFG_INSTALL_DIR})
|
||||
|
||||
if (QJSON_FOUND)
|
||||
# This is a hack to make QJSON work with both 0.7.1 (the latest stable)
|
||||
# and the current master (b440550), which uses a different casing for
|
||||
# the CMake variables.
|
||||
# It should be removed when QJSON master becomes sane and reverts the
|
||||
# casing again.
|
||||
if (QJSON_LIBRARIES AND QJSON_INCLUDE_DIR)
|
||||
set(KERFUFFLE_QJSON_LIBRARIES "${QJSON_LIBRARIES}")
|
||||
set(KERFUFFLE_QJSON_INCLUDE_DIR "${QJSON_INCLUDE_DIR}")
|
||||
else (QJSON_LIBRARIES AND QJSON_INCLUDE_DIR)
|
||||
set(KERFUFFLE_QJSON_LIBRARIES "${qjson_LIBRARIES}")
|
||||
set(KERFUFFLE_QJSON_INCLUDE_DIR "${qjson_INCLUDE_DIR}")
|
||||
endif (QJSON_LIBRARIES AND QJSON_INCLUDE_DIR)
|
||||
|
||||
add_subdirectory(tests)
|
||||
endif (QJSON_FOUND)
|
135
ark/kerfuffle/adddialog.cpp
Normal file
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2008 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
* Copyright (C) 2009,2011 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "adddialog.h"
|
||||
#include "ui_adddialog.h"
|
||||
#include "kerfuffle/archive.h"
|
||||
|
||||
#include <KConfigGroup>
|
||||
#include <KFilePlacesModel>
|
||||
#include <KGlobal>
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QStandardItemModel>
|
||||
|
||||
namespace Kerfuffle
|
||||
{
|
||||
class AddDialogUI: public QWidget, public Ui::AddDialog
|
||||
{
|
||||
public:
|
||||
AddDialogUI(QWidget *parent = 0)
|
||||
: QWidget(parent) {
|
||||
setupUi(this);
|
||||
}
|
||||
};
|
||||
|
||||
AddDialog::AddDialog(const QStringList& itemsToAdd,
|
||||
const KUrl & startDir,
|
||||
const QString & filter,
|
||||
QWidget * parent,
|
||||
QWidget * widget
|
||||
)
|
||||
: KFileDialog(startDir, filter, parent, widget)
|
||||
{
|
||||
setOperationMode(KFileDialog::Saving);
|
||||
setMode(KFile::File | KFile::LocalOnly);
|
||||
setConfirmOverwrite(true);
|
||||
setCaption(i18n("Compress to Archive"));
|
||||
|
||||
loadConfiguration();
|
||||
|
||||
connect(this, SIGNAL(okClicked()), SLOT(updateDefaultMimeType()));
|
||||
|
||||
m_ui = new AddDialogUI(this);
|
||||
mainWidget()->layout()->addWidget(m_ui);
|
||||
|
||||
setupIconList(itemsToAdd);
|
||||
|
||||
// Set up a default name if there's only one file to compress
|
||||
if (itemsToAdd.size() == 1) {
|
||||
const QFileInfo fileInfo(itemsToAdd.first());
|
||||
const QString fileName =
|
||||
fileInfo.isDir() ? fileInfo.dir().dirName() : fileInfo.baseName();
|
||||
|
||||
// #272914: Add an extension when it is present, otherwise KFileDialog
|
||||
// will not automatically add it as baseFileName is a file which
|
||||
// already exists.
|
||||
setSelection(fileName + currentFilterMimeType()->mainExtension());
|
||||
}
|
||||
|
||||
//These extra options will be implemented in a 4.2+ version of
|
||||
//ark
|
||||
m_ui->groupExtraOptions->hide();
|
||||
}
|
||||
|
||||
void AddDialog::loadConfiguration()
|
||||
{
|
||||
m_config = KConfigGroup(KGlobal::config()->group("AddDialog"));
|
||||
|
||||
const QString defaultMimeType = QLatin1String( "application/x-compressed-tar" );
|
||||
const QStringList writeMimeTypes = Kerfuffle::supportedWriteMimeTypes();
|
||||
const QString lastMimeType = m_config.readEntry("LastMimeType", defaultMimeType);
|
||||
|
||||
if (writeMimeTypes.contains(lastMimeType)) {
|
||||
setMimeFilter(writeMimeTypes, lastMimeType);
|
||||
} else {
|
||||
setMimeFilter(writeMimeTypes, defaultMimeType);
|
||||
}
|
||||
}
|
||||
|
||||
void AddDialog::setupIconList(const QStringList& itemsToAdd)
|
||||
{
|
||||
QStandardItemModel* listModel = new QStandardItemModel(this);
|
||||
QStringList sortedList(itemsToAdd);
|
||||
|
||||
sortedList.sort();
|
||||
|
||||
Q_FOREACH(const QString& urlString, sortedList) {
|
||||
KUrl url(urlString);
|
||||
|
||||
QStandardItem* item = new QStandardItem;
|
||||
item->setText(url.fileName());
|
||||
|
||||
QString iconName = KMimeType::iconNameForUrl(url);
|
||||
item->setIcon(KIcon(iconName));
|
||||
|
||||
item->setData(QVariant(url), KFilePlacesModel::UrlRole);
|
||||
|
||||
listModel->appendRow(item);
|
||||
}
|
||||
|
||||
m_ui->compressList->setModel(listModel);
|
||||
}
|
||||
|
||||
void AddDialog::updateDefaultMimeType()
|
||||
{
|
||||
m_config.writeEntry("LastMimeType", currentMimeFilter());
|
||||
}
|
||||
}
|
||||
|
||||
#include "adddialog.moc"
|
63
ark/kerfuffle/adddialog.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2008 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
* Copyright (C) 2009 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ADDDIALOG_H
|
||||
#define ADDDIALOG_H
|
||||
|
||||
#include "kerfuffle_export.h"
|
||||
|
||||
#include <KConfigGroup>
|
||||
#include <KFileDialog>
|
||||
|
||||
namespace Kerfuffle
|
||||
{
|
||||
class KERFUFFLE_EXPORT AddDialog : public KFileDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AddDialog(const QStringList & itemsToAdd,
|
||||
const KUrl & startDir,
|
||||
const QString & filter,
|
||||
QWidget * parent,
|
||||
QWidget * widget = 0
|
||||
);
|
||||
|
||||
private:
|
||||
class AddDialogUI *m_ui;
|
||||
KConfigGroup m_config;
|
||||
|
||||
void loadConfiguration();
|
||||
void setupIconList(const QStringList& itemsToAdd);
|
||||
|
||||
private slots:
|
||||
void updateDefaultMimeType();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
113
ark/kerfuffle/adddialog.ui
Normal file
|
@ -0,0 +1,113 @@
|
|||
<ui version="4.0" >
|
||||
<class>AddDialog</class>
|
||||
<widget class="QWidget" name="AddDialog" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>565</width>
|
||||
<height>113</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" >
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupCompressFiles" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Preferred" hsizetype="MinimumExpanding" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title" >
|
||||
<string>Files/Folders to Compress</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2" >
|
||||
<item>
|
||||
<widget class="QListView" name="compressList" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Preferred" hsizetype="Expanding" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="autoFillBackground" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="frameShape" >
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow" >
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="editTriggers" >
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="selectionMode" >
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
<property name="iconSize" >
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="textElideMode" >
|
||||
<enum>Qt::ElideMiddle</enum>
|
||||
</property>
|
||||
<property name="verticalScrollMode" >
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="resizeMode" >
|
||||
<enum>QListView::Adjust</enum>
|
||||
</property>
|
||||
<property name="viewMode" >
|
||||
<enum>QListView::IconMode</enum>
|
||||
</property>
|
||||
<property name="uniformItemSizes" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupExtraOptions" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title" >
|
||||
<string>Extra Compression Options</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>Easter egg for the developers:
|
||||
This is where future versions will have extra compression options for the various compression interfaces.</string>
|
||||
</property>
|
||||
<property name="wordWrap" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
213
ark/kerfuffle/addtoarchive.cpp
Normal file
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2008 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
* Copyright (C) 2009 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "addtoarchive.h"
|
||||
#include "adddialog.h"
|
||||
#include "archive.h"
|
||||
#include "jobs.h"
|
||||
|
||||
#include <KConfig>
|
||||
#include <kdebug.h>
|
||||
#include <kjobtrackerinterface.h>
|
||||
#include <kmessagebox.h>
|
||||
#include <klocale.h>
|
||||
#include <kio/job.h>
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#include <QTimer>
|
||||
#include <QWeakPointer>
|
||||
|
||||
namespace Kerfuffle
|
||||
{
|
||||
AddToArchive::AddToArchive(QObject *parent)
|
||||
: KJob(parent), m_changeToFirstPath(false)
|
||||
{
|
||||
}
|
||||
|
||||
AddToArchive::~AddToArchive()
|
||||
{
|
||||
}
|
||||
|
||||
void AddToArchive::setAutoFilenameSuffix(const QString& suffix)
|
||||
{
|
||||
m_autoFilenameSuffix = suffix;
|
||||
}
|
||||
|
||||
void AddToArchive::setChangeToFirstPath(bool value)
|
||||
{
|
||||
m_changeToFirstPath = value;
|
||||
}
|
||||
|
||||
void AddToArchive::setFilename(const KUrl& path)
|
||||
{
|
||||
m_filename = path.pathOrUrl();
|
||||
}
|
||||
|
||||
void AddToArchive::setMimeType(const QString & mimeType)
|
||||
{
|
||||
m_mimeType = mimeType;
|
||||
}
|
||||
|
||||
bool AddToArchive::showAddDialog(void)
|
||||
{
|
||||
QWeakPointer<Kerfuffle::AddDialog> dialog = new Kerfuffle::AddDialog(
|
||||
m_inputs, // itemsToAdd
|
||||
KUrl(m_firstPath), // startDir
|
||||
QLatin1String( "" ), // filter
|
||||
NULL, // parent
|
||||
NULL); // widget
|
||||
|
||||
bool ret = dialog.data()->exec();
|
||||
|
||||
if (ret) {
|
||||
kDebug() << "Returned URL:" << dialog.data()->selectedUrl();
|
||||
kDebug() << "Returned mime:" << dialog.data()->currentMimeFilter();
|
||||
setFilename(dialog.data()->selectedUrl());
|
||||
setMimeType(dialog.data()->currentMimeFilter());
|
||||
}
|
||||
|
||||
delete dialog.data();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool AddToArchive::addInput(const KUrl& url)
|
||||
{
|
||||
m_inputs << url.pathOrUrl(
|
||||
QFileInfo(url.pathOrUrl()).isDir() ?
|
||||
KUrl::AddTrailingSlash :
|
||||
KUrl::RemoveTrailingSlash
|
||||
);
|
||||
|
||||
if (m_firstPath.isEmpty()) {
|
||||
QString firstEntry = url.pathOrUrl(KUrl::RemoveTrailingSlash);
|
||||
m_firstPath = QFileInfo(firstEntry).dir().absolutePath();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddToArchive::start()
|
||||
{
|
||||
QTimer::singleShot(0, this, SLOT(slotStartJob()));
|
||||
}
|
||||
|
||||
// TODO: If this class should ever be called outside main.cpp,
|
||||
// the returns should be preceded by emitResult().
|
||||
void AddToArchive::slotStartJob(void)
|
||||
{
|
||||
kDebug();
|
||||
|
||||
Kerfuffle::CompressionOptions options;
|
||||
|
||||
if (!m_inputs.size()) {
|
||||
KMessageBox::error(NULL, i18n("No input files were given."));
|
||||
return;
|
||||
}
|
||||
|
||||
Kerfuffle::Archive *archive;
|
||||
if (!m_filename.isEmpty()) {
|
||||
archive = Kerfuffle::Archive::create(m_filename, m_mimeType, this);
|
||||
kDebug() << "Set filename to " << m_filename;
|
||||
} else {
|
||||
if (m_autoFilenameSuffix.isEmpty()) {
|
||||
KMessageBox::error(NULL, i18n("You need to either supply a filename for the archive or a suffix (such as rar, tar.gz) with the <command>--autofilename</command> argument."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_firstPath.isEmpty()) {
|
||||
kDebug() << "Weird, this should not happen. no firstpath defined. aborting";
|
||||
return;
|
||||
}
|
||||
|
||||
QString base = QFileInfo(m_inputs.first()).absoluteFilePath();
|
||||
if (base.endsWith(QLatin1Char('/'))) {
|
||||
base.chop(1);
|
||||
}
|
||||
|
||||
QString finalName = base + QLatin1Char( '.' ) + m_autoFilenameSuffix;
|
||||
|
||||
//if file already exists, append a number to the base until it doesn't
|
||||
//exist
|
||||
int appendNumber = 0;
|
||||
while (QFileInfo(finalName).exists()) {
|
||||
++appendNumber;
|
||||
finalName = base + QLatin1Char( '_' ) + QString::number(appendNumber) + QLatin1Char( '.' ) + m_autoFilenameSuffix;
|
||||
}
|
||||
|
||||
kDebug() << "Autoset filename to "<< finalName;
|
||||
archive = Kerfuffle::Archive::create(finalName, m_mimeType, this);
|
||||
}
|
||||
|
||||
if (archive == NULL) {
|
||||
KMessageBox::error(NULL, i18n("Failed to create the new archive. Permissions might not be sufficient."));
|
||||
return;
|
||||
} else if (archive->isReadOnly()) {
|
||||
KMessageBox::error(NULL, i18n("It is not possible to create archives of this type."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_changeToFirstPath) {
|
||||
if (m_firstPath.isEmpty()) {
|
||||
kDebug() << "Weird, this should not happen. no firstpath defined. aborting";
|
||||
return;
|
||||
}
|
||||
|
||||
const QDir stripDir(m_firstPath);
|
||||
|
||||
for (int i = 0; i < m_inputs.size(); ++i) {
|
||||
m_inputs[i] = stripDir.absoluteFilePath(m_inputs.at(i));
|
||||
}
|
||||
|
||||
options[QLatin1String( "GlobalWorkDir" )] = stripDir.path();
|
||||
kDebug() << "Setting GlobalWorkDir to " << stripDir.path();
|
||||
}
|
||||
|
||||
Kerfuffle::AddJob *job =
|
||||
archive->addFiles(m_inputs, options);
|
||||
|
||||
KIO::getJobTracker()->registerJob(job);
|
||||
|
||||
connect(job, SIGNAL(result(KJob*)),
|
||||
this, SLOT(slotFinished(KJob*)));
|
||||
|
||||
job->start();
|
||||
}
|
||||
|
||||
void AddToArchive::slotFinished(KJob *job)
|
||||
{
|
||||
kDebug();
|
||||
|
||||
if (job->error()) {
|
||||
KMessageBox::error(NULL, job->errorText());
|
||||
}
|
||||
|
||||
emitResult();
|
||||
}
|
||||
}
|
85
ark/kerfuffle/addtoarchive.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2008 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
* Copyright (C) 2009 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ADDTOARCHIVE_H
|
||||
#define ADDTOARCHIVE_H
|
||||
|
||||
#include "kerfuffle_export.h"
|
||||
|
||||
#include <KJob>
|
||||
#include <KUrl>
|
||||
|
||||
/**
|
||||
* Compresses all input files into an archive.
|
||||
*
|
||||
* This is a job class that creates a compressed archive
|
||||
* with all the given input files.
|
||||
*
|
||||
* It provides the functionality for the --add command-line
|
||||
* option, and does not need the GUI to be running.
|
||||
*
|
||||
* @author Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
*/
|
||||
namespace Kerfuffle
|
||||
{
|
||||
class KERFUFFLE_EXPORT AddToArchive : public KJob
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AddToArchive(QObject *parent = 0);
|
||||
~AddToArchive();
|
||||
|
||||
bool showAddDialog();
|
||||
void setPreservePaths(bool value);
|
||||
void setChangeToFirstPath(bool value);
|
||||
|
||||
public slots:
|
||||
bool addInput(const KUrl& url);
|
||||
void setAutoFilenameSuffix(const QString& suffix);
|
||||
void setFilename(const KUrl& path);
|
||||
void setMimeType(const QString & mimeType);
|
||||
void start();
|
||||
|
||||
private slots:
|
||||
void slotFinished(KJob*);
|
||||
void slotStartJob();
|
||||
|
||||
private:
|
||||
QString m_filename;
|
||||
QString m_strippedPath;
|
||||
QString m_autoFilenameSuffix;
|
||||
QString m_firstPath;
|
||||
QString m_mimeType;
|
||||
QStringList m_inputs;
|
||||
bool m_changeToFirstPath;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ADDTOARCHIVE_H
|
||||
|
333
ark/kerfuffle/archive.cpp
Normal file
|
@ -0,0 +1,333 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
|
||||
* Copyright (c) 2008 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
* Copyright (c) 2009-2011 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "archive.h"
|
||||
#include "archiveinterface.h"
|
||||
#include "jobs.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QEventLoop>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
|
||||
#include <KDebug>
|
||||
#include <KPluginLoader>
|
||||
#include <KMimeType>
|
||||
#include <KMimeTypeTrader>
|
||||
#include <KServiceTypeTrader>
|
||||
|
||||
static bool comparePlugins(const KService::Ptr &p1, const KService::Ptr &p2)
|
||||
{
|
||||
return (p1->property(QLatin1String( "X-KDE-Priority" )).toInt()) > (p2->property(QLatin1String( "X-KDE-Priority" )).toInt());
|
||||
}
|
||||
|
||||
static QString determineMimeType(const QString& filename)
|
||||
{
|
||||
if (!QFile::exists(filename)) {
|
||||
return KMimeType::findByPath(filename)->name();
|
||||
}
|
||||
|
||||
QFile file(filename);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
const qint64 maxSize = 0x100000; // 1MB
|
||||
const qint64 bufferSize = qMin(maxSize, file.size());
|
||||
const QByteArray buffer = file.read(bufferSize);
|
||||
|
||||
return KMimeType::findByNameAndContent(filename, buffer)->name();
|
||||
}
|
||||
|
||||
static KService::List findPluginOffers(const QString& filename, const QString& fixedMimeType)
|
||||
{
|
||||
KService::List offers;
|
||||
|
||||
const QString mimeType = fixedMimeType.isEmpty() ? determineMimeType(filename) : fixedMimeType;
|
||||
|
||||
if (!mimeType.isEmpty()) {
|
||||
offers = KMimeTypeTrader::self()->query(mimeType, QLatin1String( "Kerfuffle/Plugin" ), QLatin1String( "(exist Library)" ));
|
||||
qSort(offers.begin(), offers.end(), comparePlugins);
|
||||
}
|
||||
|
||||
return offers;
|
||||
}
|
||||
|
||||
namespace Kerfuffle
|
||||
{
|
||||
|
||||
Archive *Archive::create(const QString &fileName, QObject *parent)
|
||||
{
|
||||
return create(fileName, QString(), parent);
|
||||
}
|
||||
|
||||
Archive *Archive::create(const QString &fileName, const QString &fixedMimeType, QObject *parent)
|
||||
{
|
||||
qRegisterMetaType<ArchiveEntry>("ArchiveEntry");
|
||||
|
||||
const KService::List offers = findPluginOffers(fileName, fixedMimeType);
|
||||
|
||||
if (offers.isEmpty()) {
|
||||
kDebug() << "Could not find a plugin to handle" << fileName;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const QString pluginName = offers.first()->library();
|
||||
kDebug() << "Loading plugin" << pluginName;
|
||||
|
||||
KPluginFactory * const factory = KPluginLoader(pluginName).factory();
|
||||
if (!factory) {
|
||||
kDebug() << "Invalid plugin factory for" << pluginName;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
QVariantList args;
|
||||
args.append(QVariant(QFileInfo(fileName).absoluteFilePath()));
|
||||
|
||||
ReadOnlyArchiveInterface * const iface = factory->create<ReadOnlyArchiveInterface>(0, args);
|
||||
if (!iface) {
|
||||
kDebug() << "Could not create plugin instance" << pluginName << "for" << fileName;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new Archive(iface, parent);
|
||||
}
|
||||
|
||||
Archive::Archive(ReadOnlyArchiveInterface *archiveInterface, QObject *parent)
|
||||
: QObject(parent),
|
||||
m_iface(archiveInterface),
|
||||
m_hasBeenListed(false),
|
||||
m_isPasswordProtected(false),
|
||||
m_isSingleFolderArchive(false)
|
||||
{
|
||||
Q_ASSERT(archiveInterface);
|
||||
archiveInterface->setParent(this);
|
||||
}
|
||||
|
||||
Archive::~Archive()
|
||||
{
|
||||
}
|
||||
|
||||
bool Archive::isReadOnly() const
|
||||
{
|
||||
return m_iface->isReadOnly();
|
||||
}
|
||||
|
||||
KJob* Archive::open()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
KJob* Archive::create()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ListJob* Archive::list()
|
||||
{
|
||||
ListJob *job = new ListJob(m_iface, this);
|
||||
job->setAutoDelete(false);
|
||||
|
||||
//if this job has not been listed before, we grab the opportunity to
|
||||
//collect some information about the archive
|
||||
if (!m_hasBeenListed) {
|
||||
connect(job, SIGNAL(result(KJob*)),
|
||||
this, SLOT(onListFinished(KJob*)));
|
||||
}
|
||||
return job;
|
||||
}
|
||||
|
||||
DeleteJob* Archive::deleteFiles(const QList<QVariant> & files)
|
||||
{
|
||||
if (m_iface->isReadOnly()) {
|
||||
return 0;
|
||||
}
|
||||
DeleteJob *newJob = new DeleteJob(files, static_cast<ReadWriteArchiveInterface*>(m_iface), this);
|
||||
|
||||
return newJob;
|
||||
}
|
||||
|
||||
AddJob* Archive::addFiles(const QStringList & files, const CompressionOptions& options)
|
||||
{
|
||||
Q_ASSERT(!m_iface->isReadOnly());
|
||||
AddJob *newJob = new AddJob(files, options, static_cast<ReadWriteArchiveInterface*>(m_iface), this);
|
||||
connect(newJob, SIGNAL(result(KJob*)),
|
||||
this, SLOT(onAddFinished(KJob*)));
|
||||
return newJob;
|
||||
}
|
||||
|
||||
ExtractJob* Archive::copyFiles(const QList<QVariant> & files, const QString & destinationDir, ExtractionOptions options)
|
||||
{
|
||||
ExtractionOptions newOptions = options;
|
||||
if (isPasswordProtected()) {
|
||||
newOptions[QLatin1String( "PasswordProtectedHint" )] = true;
|
||||
}
|
||||
|
||||
ExtractJob *newJob = new ExtractJob(files, destinationDir, newOptions, m_iface, this);
|
||||
return newJob;
|
||||
}
|
||||
|
||||
QString Archive::fileName() const
|
||||
{
|
||||
return m_iface->filename();
|
||||
}
|
||||
|
||||
void Archive::onAddFinished(KJob* job)
|
||||
{
|
||||
//if the archive was previously a single folder archive and an add job
|
||||
//has successfully finished, then it is no longer a single folder
|
||||
//archive (for the current implementation, which does not allow adding
|
||||
//folders/files other places than the root.
|
||||
//TODO: handle the case of creating a new file and singlefolderarchive
|
||||
//then.
|
||||
if (m_isSingleFolderArchive && !job->error()) {
|
||||
m_isSingleFolderArchive = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Archive::onListFinished(KJob* job)
|
||||
{
|
||||
ListJob *ljob = qobject_cast<ListJob*>(job);
|
||||
m_extractedFilesSize = ljob->extractedFilesSize();
|
||||
m_isSingleFolderArchive = ljob->isSingleFolderArchive();
|
||||
m_isPasswordProtected = ljob->isPasswordProtected();
|
||||
m_subfolderName = ljob->subfolderName();
|
||||
if (m_subfolderName.isEmpty()) {
|
||||
QFileInfo fi(fileName());
|
||||
QString base = fi.completeBaseName();
|
||||
|
||||
//special case for tar.gz/bzip2 files
|
||||
if (base.right(4).toUpper() == QLatin1String(".TAR")) {
|
||||
base.chop(4);
|
||||
}
|
||||
|
||||
m_subfolderName = base;
|
||||
}
|
||||
|
||||
m_hasBeenListed = true;
|
||||
}
|
||||
|
||||
void Archive::listIfNotListed()
|
||||
{
|
||||
if (!m_hasBeenListed) {
|
||||
KJob *job = list();
|
||||
|
||||
connect(job, SIGNAL(userQuery(Kerfuffle::Query*)),
|
||||
SLOT(onUserQuery(Kerfuffle::Query*)));
|
||||
|
||||
QEventLoop loop(this);
|
||||
|
||||
connect(job, SIGNAL(result(KJob*)),
|
||||
&loop, SLOT(quit()));
|
||||
job->start();
|
||||
loop.exec(); // krazy:exclude=crashy
|
||||
}
|
||||
}
|
||||
|
||||
void Archive::onUserQuery(Query* query)
|
||||
{
|
||||
query->execute();
|
||||
}
|
||||
|
||||
bool Archive::isSingleFolderArchive()
|
||||
{
|
||||
listIfNotListed();
|
||||
return m_isSingleFolderArchive;
|
||||
}
|
||||
|
||||
bool Archive::isPasswordProtected()
|
||||
{
|
||||
listIfNotListed();
|
||||
return m_isPasswordProtected;
|
||||
}
|
||||
|
||||
QString Archive::subfolderName()
|
||||
{
|
||||
listIfNotListed();
|
||||
return m_subfolderName;
|
||||
}
|
||||
|
||||
void Archive::setPassword(const QString &password)
|
||||
{
|
||||
m_iface->setPassword(password);
|
||||
}
|
||||
|
||||
QStringList supportedMimeTypes()
|
||||
{
|
||||
const QLatin1String constraint("(exist Library)");
|
||||
const QLatin1String basePartService("Kerfuffle/Plugin");
|
||||
|
||||
const KService::List offers = KServiceTypeTrader::self()->query(basePartService, constraint);
|
||||
KService::List::ConstIterator it = offers.constBegin();
|
||||
KService::List::ConstIterator itEnd = offers.constEnd();
|
||||
|
||||
QStringList supported;
|
||||
|
||||
for (; it != itEnd; ++it) {
|
||||
KService::Ptr service = *it;
|
||||
QStringList mimeTypes = service->serviceTypes();
|
||||
|
||||
foreach (const QString& mimeType, mimeTypes) {
|
||||
if (mimeType != basePartService && !supported.contains(mimeType)) {
|
||||
supported.append(mimeType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kDebug() << "Returning" << supported;
|
||||
|
||||
return supported;
|
||||
}
|
||||
|
||||
QStringList supportedWriteMimeTypes()
|
||||
{
|
||||
const QLatin1String constraint("(exist Library) and ([X-KDE-Kerfuffle-ReadWrite] == true)");
|
||||
const QLatin1String basePartService("Kerfuffle/Plugin");
|
||||
|
||||
const KService::List offers = KServiceTypeTrader::self()->query(basePartService, constraint);
|
||||
KService::List::ConstIterator it = offers.constBegin();
|
||||
KService::List::ConstIterator itEnd = offers.constEnd();
|
||||
|
||||
QStringList supported;
|
||||
|
||||
for (; it != itEnd; ++it) {
|
||||
KService::Ptr service = *it;
|
||||
QStringList mimeTypes = service->serviceTypes();
|
||||
|
||||
foreach (const QString& mimeType, mimeTypes) {
|
||||
if (mimeType != basePartService && !supported.contains(mimeType)) {
|
||||
supported.append(mimeType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kDebug() << "Returning" << supported;
|
||||
|
||||
return supported;
|
||||
}
|
||||
|
||||
} // namespace Kerfuffle
|
149
ark/kerfuffle/archive.h
Normal file
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
|
||||
* Copyright (c) 2008 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
* Copyright (c) 2011 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ARCHIVE_H
|
||||
#define ARCHIVE_H
|
||||
|
||||
#include "kerfuffle_export.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QHash>
|
||||
|
||||
class KJob;
|
||||
|
||||
namespace Kerfuffle
|
||||
{
|
||||
class ListJob;
|
||||
class ExtractJob;
|
||||
class DeleteJob;
|
||||
class AddJob;
|
||||
class Query;
|
||||
class ReadOnlyArchiveInterface;
|
||||
|
||||
/**
|
||||
* Meta data related to one entry in a compressed archive.
|
||||
*
|
||||
* When creating a plugin, information about every single entry in
|
||||
* an archive is contained in an ArchiveEntry, and metadata
|
||||
* is set with the entries in this enum.
|
||||
*
|
||||
* Please notice that not all archive formats support all the properties
|
||||
* below, so set those that are available.
|
||||
*/
|
||||
enum EntryMetaDataType {
|
||||
FileName = 0, /**< The entry's file name */
|
||||
InternalID, /**< The entry's ID for Ark's internal manipulation */
|
||||
Permissions, /**< The entry's permissions */
|
||||
Owner, /**< The user the entry belongs to */
|
||||
Group, /**< The user group the entry belongs to */
|
||||
Size, /**< The entry's original size */
|
||||
CompressedSize, /**< The compressed size for the entry */
|
||||
Link, /**< The entry is a symbolic link */
|
||||
Ratio, /**< The compression ratio for the entry */
|
||||
CRC, /**< The entry's CRC */
|
||||
Method, /**< The compression method used on the entry */
|
||||
Version, /**< The archiver version needed to extract the entry */
|
||||
Timestamp, /**< The timestamp for the current entry */
|
||||
IsDirectory, /**< The entry is a directory */
|
||||
Comment,
|
||||
IsPasswordProtected, /**< The entry is password-protected */
|
||||
Custom = 1048576
|
||||
};
|
||||
|
||||
typedef QHash<int, QVariant> ArchiveEntry;
|
||||
|
||||
/**
|
||||
These are the extra options for doing the compression. Naming convention
|
||||
is CamelCase with either Global, or the compression type (such as Zip,
|
||||
Rar, etc), followed by the property name used
|
||||
*/
|
||||
typedef QHash<QString, QVariant> CompressionOptions;
|
||||
typedef QHash<QString, QVariant> ExtractionOptions;
|
||||
|
||||
class KERFUFFLE_EXPORT Archive : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static Archive *create(const QString &fileName, QObject *parent = 0);
|
||||
static Archive *create(const QString &fileName, const QString &fixedMimeType, QObject *parent = 0);
|
||||
~Archive();
|
||||
|
||||
QString fileName() const;
|
||||
bool isReadOnly() const;
|
||||
|
||||
KJob* open();
|
||||
KJob* create();
|
||||
ListJob* list();
|
||||
DeleteJob* deleteFiles(const QList<QVariant> & files);
|
||||
|
||||
/**
|
||||
* Compression options that should be handled by all interfaces:
|
||||
*
|
||||
* GlobalWorkDir - Change to this dir before adding the new files.
|
||||
* The path names should then be added relative to this directory.
|
||||
*
|
||||
* TODO: find a way to actually add files to specific locations in
|
||||
* the archive
|
||||
* (not supported yet) GlobalPathInArchive - a path relative to the
|
||||
* archive root where the files will be added under
|
||||
*
|
||||
*/
|
||||
AddJob* addFiles(const QStringList & files, const CompressionOptions& options = CompressionOptions());
|
||||
|
||||
ExtractJob* copyFiles(const QList<QVariant> & files, const QString & destinationDir, ExtractionOptions options = ExtractionOptions());
|
||||
|
||||
bool isSingleFolderArchive();
|
||||
QString subfolderName();
|
||||
bool isPasswordProtected();
|
||||
|
||||
void setPassword(const QString &password);
|
||||
|
||||
private slots:
|
||||
void onListFinished(KJob*);
|
||||
void onAddFinished(KJob*);
|
||||
void onUserQuery(Kerfuffle::Query*);
|
||||
|
||||
private:
|
||||
Archive(ReadOnlyArchiveInterface *archiveInterface, QObject *parent = 0);
|
||||
|
||||
void listIfNotListed();
|
||||
ReadOnlyArchiveInterface *m_iface;
|
||||
bool m_hasBeenListed;
|
||||
bool m_isPasswordProtected;
|
||||
bool m_isSingleFolderArchive;
|
||||
QString m_subfolderName;
|
||||
qlonglong m_extractedFilesSize;
|
||||
};
|
||||
|
||||
KERFUFFLE_EXPORT QStringList supportedMimeTypes();
|
||||
KERFUFFLE_EXPORT QStringList supportedWriteMimeTypes();
|
||||
} // namespace Kerfuffle
|
||||
|
||||
|
||||
#endif // ARCHIVE_H
|
122
ark/kerfuffle/archiveinterface.cpp
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
|
||||
* Copyright (c) 2008-2009 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
* Copyright (c) 2009-2012 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "archiveinterface.h"
|
||||
#include <kdebug.h>
|
||||
#include <kfileitem.h>
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
|
||||
namespace Kerfuffle
|
||||
{
|
||||
ReadOnlyArchiveInterface::ReadOnlyArchiveInterface(QObject *parent, const QVariantList & args)
|
||||
: QObject(parent), m_waitForFinishedSignal(false)
|
||||
{
|
||||
kDebug();
|
||||
m_filename = args.first().toString();
|
||||
}
|
||||
|
||||
ReadOnlyArchiveInterface::~ReadOnlyArchiveInterface()
|
||||
{
|
||||
}
|
||||
|
||||
QString ReadOnlyArchiveInterface::filename() const
|
||||
{
|
||||
return m_filename;
|
||||
}
|
||||
|
||||
bool ReadOnlyArchiveInterface::isReadOnly() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReadOnlyArchiveInterface::open()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void ReadOnlyArchiveInterface::setPassword(const QString &password)
|
||||
{
|
||||
m_password = password;
|
||||
}
|
||||
|
||||
QString ReadOnlyArchiveInterface::password() const
|
||||
{
|
||||
return m_password;
|
||||
}
|
||||
|
||||
bool ReadOnlyArchiveInterface::doKill()
|
||||
{
|
||||
//default implementation
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ReadOnlyArchiveInterface::doSuspend()
|
||||
{
|
||||
//default implementation
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ReadOnlyArchiveInterface::doResume()
|
||||
{
|
||||
//default implementation
|
||||
return false;
|
||||
}
|
||||
|
||||
ReadWriteArchiveInterface::ReadWriteArchiveInterface(QObject *parent, const QVariantList & args)
|
||||
: ReadOnlyArchiveInterface(parent, args)
|
||||
{
|
||||
}
|
||||
|
||||
ReadWriteArchiveInterface::~ReadWriteArchiveInterface()
|
||||
{
|
||||
}
|
||||
|
||||
bool ReadOnlyArchiveInterface::waitForFinishedSignal()
|
||||
{
|
||||
return m_waitForFinishedSignal;
|
||||
}
|
||||
|
||||
void ReadOnlyArchiveInterface::setWaitForFinishedSignal(bool value)
|
||||
{
|
||||
m_waitForFinishedSignal = value;
|
||||
}
|
||||
|
||||
bool ReadWriteArchiveInterface::isReadOnly() const
|
||||
{
|
||||
QFileInfo fileInfo(filename());
|
||||
if (fileInfo.exists()) {
|
||||
return ! fileInfo.isWritable();
|
||||
} else {
|
||||
return !fileInfo.dir().exists(); // TODO: Should also check if we can create a file in that directory
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Kerfuffle
|
||||
|
||||
#include "archiveinterface.moc"
|
138
ark/kerfuffle/archiveinterface.h
Normal file
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
|
||||
* Copyright (c) 2008-2009 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
* Copyright (c) 2009-2012 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ARCHIVEINTERFACE_H
|
||||
#define ARCHIVEINTERFACE_H
|
||||
|
||||
#include "archive.h"
|
||||
#include "kerfuffle_export.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
#include <QString>
|
||||
#include <QVariantList>
|
||||
|
||||
namespace Kerfuffle
|
||||
{
|
||||
class Query;
|
||||
|
||||
class KERFUFFLE_EXPORT ReadOnlyArchiveInterface: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ReadOnlyArchiveInterface(QObject *parent, const QVariantList & args);
|
||||
virtual ~ReadOnlyArchiveInterface();
|
||||
|
||||
/**
|
||||
* Returns the filename of the archive currently being handled.
|
||||
*/
|
||||
QString filename() const;
|
||||
|
||||
/**
|
||||
* Returns whether the file can only be read.
|
||||
*
|
||||
* @return @c true The file cannot be written.
|
||||
* @return @c false The file can be read and written.
|
||||
*/
|
||||
virtual bool isReadOnly() const;
|
||||
|
||||
virtual bool open();
|
||||
|
||||
/**
|
||||
* List archive contents.
|
||||
* This runs the process of reading archive contents.
|
||||
* When subclassing, you can block as long as you need, the function runs
|
||||
* in its own thread.
|
||||
* @returns whether the listing succeeded.
|
||||
* @note If returning false, make sure to emit the error() signal beforewards to notify
|
||||
* the user of the error condition.
|
||||
*/
|
||||
virtual bool list() = 0;
|
||||
void setPassword(const QString &password);
|
||||
|
||||
/**
|
||||
* Extract files from archive.
|
||||
* Globally recognized extraction options:
|
||||
* @li PreservePaths - preserve file paths (extract flat if false)
|
||||
* @li RootNode - node in the archive which will correspond to the @arg destinationDirectory
|
||||
* When subclassing, you can block as long as you need, the function runs
|
||||
* in its own thread.
|
||||
* @returns whether the listing succeeded.
|
||||
* @note If returning false, make sure to emit the error() signal beforewards to notify
|
||||
* the user of the error condition.
|
||||
*/
|
||||
virtual bool copyFiles(const QList<QVariant> & files, const QString & destinationDirectory, ExtractionOptions options) = 0;
|
||||
|
||||
bool waitForFinishedSignal();
|
||||
|
||||
virtual bool doKill();
|
||||
virtual bool doSuspend();
|
||||
virtual bool doResume();
|
||||
|
||||
signals:
|
||||
void error(const QString &message, const QString &details = QString());
|
||||
void entry(const ArchiveEntry &archiveEntry);
|
||||
void entryRemoved(const QString &path);
|
||||
void progress(double progress);
|
||||
void info(const QString &info);
|
||||
void finished(bool result);
|
||||
void userQuery(Query *query);
|
||||
|
||||
protected:
|
||||
QString password() const;
|
||||
/**
|
||||
* Setting this option to true will not exit the thread with the
|
||||
* exit of the various functions, but rather when finished(bool) is
|
||||
* called. Doing this one can use the event loop easily while doing
|
||||
* the operation.
|
||||
*/
|
||||
void setWaitForFinishedSignal(bool value);
|
||||
|
||||
private:
|
||||
QString m_filename;
|
||||
QString m_password;
|
||||
bool m_waitForFinishedSignal;
|
||||
};
|
||||
|
||||
class KERFUFFLE_EXPORT ReadWriteArchiveInterface: public ReadOnlyArchiveInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ReadWriteArchiveInterface(QObject *parent, const QVariantList & args);
|
||||
virtual ~ReadWriteArchiveInterface();
|
||||
|
||||
virtual bool isReadOnly() const;
|
||||
|
||||
//see archive.h for a list of what the compressionoptions might
|
||||
//contain
|
||||
virtual bool addFiles(const QStringList & files, const CompressionOptions& options) = 0;
|
||||
virtual bool deleteFiles(const QList<QVariant> & files) = 0;
|
||||
};
|
||||
|
||||
} // namespace Kerfuffle
|
||||
|
||||
#endif // ARCHIVEINTERFACE_H
|
25
ark/kerfuffle/ark.kcfg
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
|
||||
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
|
||||
<kcfgfile name="arkrc"/>
|
||||
<group name="Extraction">
|
||||
<entry name="openDestinationFolderAfterExtraction" type="Bool">
|
||||
<label>Open destination folder after extraction</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="closeAfterExtraction" type="Bool">
|
||||
<label>Close Ark after extraction</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="preservePaths" type="Bool">
|
||||
<label>Preserve paths when extracting</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
</group>
|
||||
<group name="MainWindow">
|
||||
<entry name="splitterSizes" type="IntList" />
|
||||
<entry name="splitterSizesWithBothWidgets" type="IntList" />
|
||||
</group>
|
||||
</kcfg>
|
751
ark/kerfuffle/cliinterface.cpp
Normal file
|
@ -0,0 +1,751 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2009 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
* Copyright (C) 2009-2011 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "cliinterface.h"
|
||||
#include "queries.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
# include <KProcess>
|
||||
#else
|
||||
# include <KPtyDevice>
|
||||
# include <KPtyProcess>
|
||||
#endif
|
||||
|
||||
#include <KStandardDirs>
|
||||
#include <KDebug>
|
||||
#include <KLocale>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QEventLoop>
|
||||
#include <QFile>
|
||||
#include <QProcess>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
|
||||
namespace Kerfuffle
|
||||
{
|
||||
CliInterface::CliInterface(QObject *parent, const QVariantList & args)
|
||||
: ReadWriteArchiveInterface(parent, args),
|
||||
m_process(0),
|
||||
m_listEmptyLines(false),
|
||||
m_abortingOperation(false)
|
||||
{
|
||||
//because this interface uses the event loop
|
||||
setWaitForFinishedSignal(true);
|
||||
|
||||
if (QMetaType::type("QProcess::ExitStatus") == 0) {
|
||||
qRegisterMetaType<QProcess::ExitStatus>("QProcess::ExitStatus");
|
||||
}
|
||||
}
|
||||
|
||||
void CliInterface::cacheParameterList()
|
||||
{
|
||||
m_param = parameterList();
|
||||
Q_ASSERT(m_param.contains(ExtractProgram));
|
||||
Q_ASSERT(m_param.contains(ListProgram));
|
||||
Q_ASSERT(m_param.contains(PreservePathSwitch));
|
||||
Q_ASSERT(m_param.contains(FileExistsExpression));
|
||||
Q_ASSERT(m_param.contains(FileExistsInput));
|
||||
}
|
||||
|
||||
CliInterface::~CliInterface()
|
||||
{
|
||||
Q_ASSERT(!m_process);
|
||||
}
|
||||
|
||||
void CliInterface::setListEmptyLines(bool emptyLines)
|
||||
{
|
||||
m_listEmptyLines = emptyLines;
|
||||
}
|
||||
|
||||
bool CliInterface::list()
|
||||
{
|
||||
cacheParameterList();
|
||||
m_operationMode = List;
|
||||
|
||||
QStringList args = m_param.value(ListArgs).toStringList();
|
||||
substituteListVariables(args);
|
||||
|
||||
if (!runProcess(m_param.value(ListProgram).toStringList(), args)) {
|
||||
failOperation();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CliInterface::copyFiles(const QList<QVariant> & files, const QString & destinationDirectory, ExtractionOptions options)
|
||||
{
|
||||
kDebug();
|
||||
cacheParameterList();
|
||||
|
||||
m_operationMode = Copy;
|
||||
|
||||
//start preparing the argument list
|
||||
QStringList args = m_param.value(ExtractArgs).toStringList();
|
||||
|
||||
//now replace the various elements in the list
|
||||
for (int i = 0; i < args.size(); ++i) {
|
||||
QString argument = args.at(i);
|
||||
kDebug() << "Processing argument " << argument;
|
||||
|
||||
if (argument == QLatin1String( "$Archive" )) {
|
||||
args[i] = filename();
|
||||
}
|
||||
|
||||
if (argument == QLatin1String( "$PreservePathSwitch" )) {
|
||||
QStringList replacementFlags = m_param.value(PreservePathSwitch).toStringList();
|
||||
Q_ASSERT(replacementFlags.size() == 2);
|
||||
|
||||
bool preservePaths = options.value(QLatin1String( "PreservePaths" )).toBool();
|
||||
QString theReplacement;
|
||||
if (preservePaths) {
|
||||
theReplacement = replacementFlags.at(0);
|
||||
} else {
|
||||
theReplacement = replacementFlags.at(1);
|
||||
}
|
||||
|
||||
if (theReplacement.isEmpty()) {
|
||||
args.removeAt(i);
|
||||
--i; //decrement to compensate for the variable we removed
|
||||
} else {
|
||||
//but in this case we don't have to decrement, we just
|
||||
//replace it
|
||||
args[i] = theReplacement;
|
||||
}
|
||||
}
|
||||
|
||||
if (argument == QLatin1String( "$PasswordSwitch" )) {
|
||||
//if the PasswordSwitch argument has been added, we at least
|
||||
//assume that the format of the switch has been added as well
|
||||
Q_ASSERT(m_param.contains(PasswordSwitch));
|
||||
|
||||
//we will decrement i afterwards
|
||||
args.removeAt(i);
|
||||
|
||||
//if we get a hint about this being a password protected archive, ask about
|
||||
//the password in advance.
|
||||
if ((options.value(QLatin1String("PasswordProtectedHint")).toBool()) &&
|
||||
(password().isEmpty())) {
|
||||
kDebug() << "Password hint enabled, querying user";
|
||||
|
||||
Kerfuffle::PasswordNeededQuery query(filename());
|
||||
emit userQuery(&query);
|
||||
query.waitForResponse();
|
||||
|
||||
if (query.responseCancelled()) {
|
||||
failOperation();
|
||||
return false;
|
||||
}
|
||||
setPassword(query.password());
|
||||
}
|
||||
|
||||
QString pass = password();
|
||||
|
||||
if (!pass.isEmpty()) {
|
||||
QStringList theSwitch = m_param.value(PasswordSwitch).toStringList();
|
||||
for (int j = 0; j < theSwitch.size(); ++j) {
|
||||
//get the argument part
|
||||
QString newArg = theSwitch.at(j);
|
||||
|
||||
//substitute the $Path
|
||||
newArg.replace(QLatin1String( "$Password" ), pass);
|
||||
|
||||
//put it in the arg list
|
||||
args.insert(i + j, newArg);
|
||||
++i;
|
||||
|
||||
}
|
||||
}
|
||||
--i; //decrement to compensate for the variable we replaced
|
||||
}
|
||||
|
||||
if (argument == QLatin1String( "$RootNodeSwitch" )) {
|
||||
//if the RootNodeSwitch argument has been added, we at least
|
||||
//assume that the format of the switch has been added as well
|
||||
Q_ASSERT(m_param.contains(RootNodeSwitch));
|
||||
|
||||
//we will decrement i afterwards
|
||||
args.removeAt(i);
|
||||
|
||||
QString rootNode;
|
||||
if (options.contains(QLatin1String( "RootNode" ))) {
|
||||
rootNode = options.value(QLatin1String( "RootNode" )).toString();
|
||||
kDebug() << "Set root node " << rootNode;
|
||||
}
|
||||
|
||||
if (!rootNode.isEmpty()) {
|
||||
QStringList theSwitch = m_param.value(RootNodeSwitch).toStringList();
|
||||
for (int j = 0; j < theSwitch.size(); ++j) {
|
||||
//get the argument part
|
||||
QString newArg = theSwitch.at(j);
|
||||
|
||||
//substitute the $Path
|
||||
newArg.replace(QLatin1String( "$Path" ), rootNode);
|
||||
|
||||
//put it in the arg list
|
||||
args.insert(i + j, newArg);
|
||||
++i;
|
||||
|
||||
}
|
||||
}
|
||||
--i; //decrement to compensate for the variable we replaced
|
||||
}
|
||||
|
||||
if (argument == QLatin1String( "$Files" )) {
|
||||
args.removeAt(i);
|
||||
for (int j = 0; j < files.count(); ++j) {
|
||||
args.insert(i + j, escapeFileName(files.at(j).toString()));
|
||||
++i;
|
||||
}
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
kDebug() << "Setting current dir to " << destinationDirectory;
|
||||
QDir::setCurrent(destinationDirectory);
|
||||
|
||||
if (!runProcess(m_param.value(ExtractProgram).toStringList(), args)) {
|
||||
failOperation();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CliInterface::addFiles(const QStringList & files, const CompressionOptions& options)
|
||||
{
|
||||
cacheParameterList();
|
||||
|
||||
m_operationMode = Add;
|
||||
|
||||
const QString globalWorkDir = options.value(QLatin1String( "GlobalWorkDir" )).toString();
|
||||
const QDir workDir = globalWorkDir.isEmpty() ? QDir::current() : QDir(globalWorkDir);
|
||||
if (!globalWorkDir.isEmpty()) {
|
||||
kDebug() << "GlobalWorkDir is set, changing dir to " << globalWorkDir;
|
||||
QDir::setCurrent(globalWorkDir);
|
||||
}
|
||||
|
||||
//start preparing the argument list
|
||||
QStringList args = m_param.value(AddArgs).toStringList();
|
||||
|
||||
//now replace the various elements in the list
|
||||
for (int i = 0; i < args.size(); ++i) {
|
||||
const QString argument = args.at(i);
|
||||
kDebug() << "Processing argument " << argument;
|
||||
|
||||
if (argument == QLatin1String( "$Archive" )) {
|
||||
args[i] = filename();
|
||||
}
|
||||
|
||||
if (argument == QLatin1String( "$Files" )) {
|
||||
args.removeAt(i);
|
||||
for (int j = 0; j < files.count(); ++j) {
|
||||
// #191821: workDir must be used instead of QDir::current()
|
||||
// so that symlinks aren't resolved automatically
|
||||
// TODO: this kind of call should be moved upwards in the
|
||||
// class hierarchy to avoid code duplication
|
||||
const QString relativeName =
|
||||
workDir.relativeFilePath(files.at(j));
|
||||
|
||||
args.insert(i + j, relativeName);
|
||||
++i;
|
||||
}
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
if (!runProcess(m_param.value(AddProgram).toStringList(), args)) {
|
||||
failOperation();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CliInterface::deleteFiles(const QList<QVariant> & files)
|
||||
{
|
||||
cacheParameterList();
|
||||
m_operationMode = Delete;
|
||||
|
||||
//start preparing the argument list
|
||||
QStringList args = m_param.value(DeleteArgs).toStringList();
|
||||
|
||||
//now replace the various elements in the list
|
||||
for (int i = 0; i < args.size(); ++i) {
|
||||
QString argument = args.at(i);
|
||||
kDebug() << "Processing argument " << argument;
|
||||
|
||||
if (argument == QLatin1String( "$Archive" )) {
|
||||
args[i] = filename();
|
||||
} else if (argument == QLatin1String( "$Files" )) {
|
||||
args.removeAt(i);
|
||||
for (int j = 0; j < files.count(); ++j) {
|
||||
args.insert(i + j, escapeFileName(files.at(j).toString()));
|
||||
++i;
|
||||
}
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
m_removedFiles = files;
|
||||
|
||||
if (!runProcess(m_param.value(DeleteProgram).toStringList(), args)) {
|
||||
failOperation();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CliInterface::runProcess(const QStringList& programNames, const QStringList& arguments)
|
||||
{
|
||||
QString programPath;
|
||||
for (int i = 0; i < programNames.count(); i++) {
|
||||
programPath = KStandardDirs::findExe(programNames.at(i));
|
||||
if (!programPath.isEmpty())
|
||||
break;
|
||||
}
|
||||
if (programPath.isEmpty()) {
|
||||
const QString names = programNames.join(QLatin1String(", "));
|
||||
emit error(i18ncp("@info", "Failed to locate program <filename>%2</filename> on disk.",
|
||||
"Failed to locate programs <filename>%2</filename> on disk.", programNames.count(), names));
|
||||
emit finished(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
kDebug() << "Executing" << programPath << arguments;
|
||||
|
||||
if (m_process) {
|
||||
m_process->waitForFinished();
|
||||
delete m_process;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
m_process = new KProcess;
|
||||
#else
|
||||
m_process = new KPtyProcess;
|
||||
m_process->setPtyChannels(KPtyProcess::StdinChannel);
|
||||
QEventLoop loop;
|
||||
connect(m_process, SIGNAL(finished(int,QProcess::ExitStatus)), &loop, SLOT(quit()), Qt::DirectConnection);
|
||||
#endif
|
||||
|
||||
m_process->setOutputChannelMode(KProcess::MergedChannels);
|
||||
m_process->setNextOpenMode(QIODevice::ReadWrite | QIODevice::Unbuffered | QIODevice::Text);
|
||||
m_process->setProgram(programPath, arguments);
|
||||
|
||||
connect(m_process, SIGNAL(readyReadStandardOutput()), SLOT(readStdout()), Qt::DirectConnection);
|
||||
connect(m_process, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(processFinished(int,QProcess::ExitStatus)), Qt::DirectConnection);
|
||||
|
||||
m_stdOutData.clear();
|
||||
|
||||
m_process->start();
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
bool ret = m_process->waitForFinished(-1);
|
||||
#else
|
||||
bool ret = (loop.exec(QEventLoop::WaitForMoreEvents | QEventLoop::ExcludeUserInputEvents) == 0);
|
||||
#endif
|
||||
|
||||
Q_ASSERT(!m_process);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CliInterface::processFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||
{
|
||||
kDebug() << exitCode << exitStatus;
|
||||
|
||||
//if the m_process pointer is gone, then there is nothing to worry
|
||||
//about here
|
||||
if (!m_process) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_operationMode == Delete) {
|
||||
foreach(const QVariant& v, m_removedFiles) {
|
||||
emit entryRemoved(v.toString());
|
||||
}
|
||||
}
|
||||
|
||||
//handle all the remaining data in the process
|
||||
readStdout(true);
|
||||
|
||||
delete m_process;
|
||||
m_process = 0;
|
||||
|
||||
emit progress(1.0);
|
||||
|
||||
if (m_operationMode == Add) {
|
||||
list();
|
||||
return;
|
||||
}
|
||||
|
||||
//and we're finished
|
||||
emit finished(true);
|
||||
}
|
||||
|
||||
void CliInterface::failOperation()
|
||||
{
|
||||
// TODO: Would be good to unit test #304764/#304178.
|
||||
kDebug();
|
||||
doKill();
|
||||
}
|
||||
|
||||
void CliInterface::readStdout(bool handleAll)
|
||||
{
|
||||
//when hacking this function, please remember the following:
|
||||
//- standard output comes in unpredictable chunks, this is why
|
||||
//you can never know if the last part of the output is a complete line or not
|
||||
//- console applications are not really consistent about what
|
||||
//characters they send out (newline, backspace, carriage return,
|
||||
//etc), so keep in mind that this function is supposed to handle
|
||||
//all those special cases and be the lowest common denominator
|
||||
|
||||
if (m_abortingOperation)
|
||||
return;
|
||||
|
||||
Q_ASSERT(m_process);
|
||||
|
||||
if (!m_process->bytesAvailable()) {
|
||||
//if process has no more data, we can just bail out
|
||||
return;
|
||||
}
|
||||
|
||||
//if the process is still not finished (m_process is appearantly not
|
||||
//set to NULL if here), then the operation should definitely not be in
|
||||
//the main thread as this would freeze everything. assert this.
|
||||
Q_ASSERT(QThread::currentThread() != QApplication::instance()->thread());
|
||||
|
||||
QByteArray dd = m_process->readAllStandardOutput();
|
||||
m_stdOutData += dd;
|
||||
|
||||
QList<QByteArray> lines = m_stdOutData.split('\n');
|
||||
|
||||
//The reason for this check is that archivers often do not end
|
||||
//queries (such as file exists, wrong password) on a new line, but
|
||||
//freeze waiting for input. So we check for errors on the last line in
|
||||
//all cases.
|
||||
// TODO: QLatin1String() might not be the best choice here.
|
||||
// The call to handleLine() at the end of the method uses
|
||||
// QString::fromLocal8Bit(), for example.
|
||||
// TODO: The same check methods are called in handleLine(), this
|
||||
// is suboptimal.
|
||||
bool foundErrorMessage =
|
||||
(checkForErrorMessage(QLatin1String( lines.last() ), WrongPasswordPatterns) ||
|
||||
checkForErrorMessage(QLatin1String( lines.last() ), ExtractionFailedPatterns) ||
|
||||
checkForPasswordPromptMessage(QLatin1String(lines.last())) ||
|
||||
checkForFileExistsMessage(QLatin1String( lines.last() )));
|
||||
|
||||
if (foundErrorMessage) {
|
||||
handleAll = true;
|
||||
}
|
||||
|
||||
//this is complex, here's an explanation:
|
||||
//if there is no newline, then there is no guaranteed full line to
|
||||
//handle in the output. The exception is that it is supposed to handle
|
||||
//all the data, OR if there's been an error message found in the
|
||||
//partial data.
|
||||
if (lines.size() == 1 && !handleAll) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (handleAll) {
|
||||
m_stdOutData.clear();
|
||||
} else {
|
||||
//because the last line might be incomplete we leave it for now
|
||||
//note, this last line may be an empty string if the stdoutdata ends
|
||||
//with a newline
|
||||
m_stdOutData = lines.takeLast();
|
||||
}
|
||||
|
||||
foreach(const QByteArray& line, lines) {
|
||||
if (!line.isEmpty() || (m_listEmptyLines && m_operationMode == List)) {
|
||||
handleLine(QString::fromLocal8Bit(line));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CliInterface::handleLine(const QString& line)
|
||||
{
|
||||
// TODO: This should be implemented by each plugin; the way progress is
|
||||
// shown by each CLI application is subject to a lot of variation.
|
||||
if ((m_operationMode == Copy || m_operationMode == Add) && m_param.contains(CaptureProgress) && m_param.value(CaptureProgress).toBool()) {
|
||||
//read the percentage
|
||||
int pos = line.indexOf(QLatin1Char( '%' ));
|
||||
if (pos != -1 && pos > 1) {
|
||||
int percentage = line.mid(pos - 2, 2).toInt();
|
||||
emit progress(float(percentage) / 100);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_operationMode == Copy) {
|
||||
if (checkForPasswordPromptMessage(line)) {
|
||||
kDebug() << "Found a password prompt";
|
||||
|
||||
Kerfuffle::PasswordNeededQuery query(filename());
|
||||
emit userQuery(&query);
|
||||
query.waitForResponse();
|
||||
|
||||
if (query.responseCancelled()) {
|
||||
failOperation();
|
||||
return;
|
||||
}
|
||||
|
||||
setPassword(query.password());
|
||||
|
||||
const QString response(password() + QLatin1Char('\n'));
|
||||
writeToProcess(response.toLocal8Bit());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkForErrorMessage(line, WrongPasswordPatterns)) {
|
||||
kDebug() << "Wrong password!";
|
||||
emit error(i18n("Incorrect password."));
|
||||
failOperation();
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkForErrorMessage(line, ExtractionFailedPatterns)) {
|
||||
kDebug() << "Error in extraction!!";
|
||||
emit error(i18n("Extraction failed because of an unexpected error."));
|
||||
failOperation();
|
||||
return;
|
||||
}
|
||||
|
||||
if (handleFileExistsMessage(line)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_operationMode == List) {
|
||||
if (checkForPasswordPromptMessage(line)) {
|
||||
kDebug() << "Found a password prompt";
|
||||
|
||||
Kerfuffle::PasswordNeededQuery query(filename());
|
||||
emit userQuery(&query);
|
||||
query.waitForResponse();
|
||||
|
||||
if (query.responseCancelled()) {
|
||||
failOperation();
|
||||
return;
|
||||
}
|
||||
|
||||
setPassword(query.password());
|
||||
|
||||
const QString response(password() + QLatin1Char('\n'));
|
||||
writeToProcess(response.toLocal8Bit());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkForErrorMessage(line, WrongPasswordPatterns)) {
|
||||
kDebug() << "Wrong password!";
|
||||
emit error(i18n("Incorrect password."));
|
||||
failOperation();
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkForErrorMessage(line, ExtractionFailedPatterns)) {
|
||||
kDebug() << "Error in extraction!!";
|
||||
emit error(i18n("Extraction failed because of an unexpected error."));
|
||||
failOperation();
|
||||
return;
|
||||
}
|
||||
|
||||
if (handleFileExistsMessage(line)) {
|
||||
return;
|
||||
}
|
||||
|
||||
readListLine(line);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool CliInterface::checkForPasswordPromptMessage(const QString& line)
|
||||
{
|
||||
const QString passwordPromptPattern(m_param.value(PasswordPromptPattern).toString());
|
||||
|
||||
if (passwordPromptPattern.isEmpty())
|
||||
return false;
|
||||
|
||||
if (m_passwordPromptPattern.isEmpty()) {
|
||||
m_passwordPromptPattern.setPattern(m_param.value(PasswordPromptPattern).toString());
|
||||
}
|
||||
|
||||
if (m_passwordPromptPattern.indexIn(line) != -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CliInterface::checkForFileExistsMessage(const QString& line)
|
||||
{
|
||||
if (m_existsPattern.isEmpty()) {
|
||||
m_existsPattern.setPattern(m_param.value(FileExistsExpression).toString());
|
||||
}
|
||||
if (m_existsPattern.indexIn(line) != -1) {
|
||||
kDebug() << "Detected file existing!! Filename " << m_existsPattern.cap(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CliInterface::handleFileExistsMessage(const QString& line)
|
||||
{
|
||||
if (!checkForFileExistsMessage(line)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const QString filename = m_existsPattern.cap(1);
|
||||
|
||||
Kerfuffle::OverwriteQuery query(QDir::current().path() + QLatin1Char( '/' ) + filename);
|
||||
query.setNoRenameMode(true);
|
||||
emit userQuery(&query);
|
||||
kDebug() << "Waiting response";
|
||||
query.waitForResponse();
|
||||
|
||||
kDebug() << "Finished response";
|
||||
|
||||
QString responseToProcess;
|
||||
const QStringList choices = m_param.value(FileExistsInput).toStringList();
|
||||
|
||||
if (query.responseOverwrite()) {
|
||||
responseToProcess = choices.at(0);
|
||||
} else if (query.responseSkip()) {
|
||||
responseToProcess = choices.at(1);
|
||||
} else if (query.responseOverwriteAll()) {
|
||||
responseToProcess = choices.at(2);
|
||||
} else if (query.responseAutoSkip()) {
|
||||
responseToProcess = choices.at(3);
|
||||
} else if (query.responseCancelled()) {
|
||||
if (choices.count() < 5) { // If the program has no way to cancel the extraction, we resort to killing it
|
||||
return doKill();
|
||||
}
|
||||
responseToProcess = choices.at(4);
|
||||
}
|
||||
|
||||
Q_ASSERT(!responseToProcess.isEmpty());
|
||||
|
||||
responseToProcess += QLatin1Char( '\n' );
|
||||
|
||||
writeToProcess(responseToProcess.toLocal8Bit());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CliInterface::checkForErrorMessage(const QString& line, int parameterIndex)
|
||||
{
|
||||
QList<QRegExp> patterns;
|
||||
|
||||
if (m_patternCache.contains(parameterIndex)) {
|
||||
patterns = m_patternCache.value(parameterIndex);
|
||||
} else {
|
||||
if (!m_param.contains(parameterIndex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach(const QString& rawPattern, m_param.value(parameterIndex).toStringList()) {
|
||||
patterns << QRegExp(rawPattern);
|
||||
}
|
||||
m_patternCache[parameterIndex] = patterns;
|
||||
}
|
||||
|
||||
foreach(const QRegExp& pattern, patterns) {
|
||||
if (pattern.indexIn(line) != -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CliInterface::doKill()
|
||||
{
|
||||
if (m_process) {
|
||||
// Give some time for the application to finish gracefully
|
||||
m_abortingOperation = true;
|
||||
if (!m_process->waitForFinished(5)) {
|
||||
m_process->kill();
|
||||
}
|
||||
m_abortingOperation = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CliInterface::doSuspend()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CliInterface::doResume()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void CliInterface::substituteListVariables(QStringList& params)
|
||||
{
|
||||
for (int i = 0; i < params.size(); ++i) {
|
||||
const QString parameter = params.at(i);
|
||||
|
||||
if (parameter == QLatin1String( "$Archive" )) {
|
||||
params[i] = filename();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString CliInterface::escapeFileName(const QString& fileName) const
|
||||
{
|
||||
return fileName;
|
||||
}
|
||||
|
||||
void CliInterface::writeToProcess(const QByteArray& data)
|
||||
{
|
||||
Q_ASSERT(m_process);
|
||||
Q_ASSERT(!data.isNull());
|
||||
|
||||
kDebug() << "Writing" << data << "to the process";
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
m_process->write(data);
|
||||
#else
|
||||
m_process->pty()->write(data);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "cliinterface.moc"
|
349
ark/kerfuffle/cliinterface.h
Normal file
|
@ -0,0 +1,349 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2009 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
* Copyright (C) 2009-2011 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef CLIINTERFACE_H
|
||||
#define CLIINTERFACE_H
|
||||
|
||||
#include "archiveinterface.h"
|
||||
#include "kerfuffle_export.h"
|
||||
#include <QtCore/QProcess>
|
||||
#include <QtCore/QRegExp>
|
||||
|
||||
class KProcess;
|
||||
class KPtyProcess;
|
||||
|
||||
namespace Kerfuffle
|
||||
{
|
||||
|
||||
enum CliInterfaceParameters {
|
||||
|
||||
///////////////[ COMMON ]/////////////
|
||||
|
||||
/**
|
||||
* Bool (default false)
|
||||
* Will look for the %-sign in the stdout while working, in the form of
|
||||
* (2%, 14%, 35%, etc etc), and report progress based upon this
|
||||
*/
|
||||
CaptureProgress = 0,
|
||||
|
||||
/**
|
||||
* QString
|
||||
* Default: empty
|
||||
* A regexp pattern that matches the program's password prompt.
|
||||
*/
|
||||
PasswordPromptPattern,
|
||||
|
||||
///////////////[ LIST ]/////////////
|
||||
|
||||
/**
|
||||
* QStringList
|
||||
* The names to the program that will handle listing of this
|
||||
* archive (eg "rar"). Will be searched for in PATH
|
||||
*/
|
||||
ListProgram,
|
||||
/**
|
||||
* QStringList
|
||||
* The arguments that are passed to the program above for
|
||||
* listing the archive. Special strings that will be
|
||||
* substituted:
|
||||
* $Archive - the path of the archive
|
||||
*/
|
||||
ListArgs,
|
||||
|
||||
///////////////[ EXTRACT ]/////////////
|
||||
|
||||
/**
|
||||
* QStringList
|
||||
* The names to the program that will handle extracting of this
|
||||
* archive (eg "rar"). Will be searched for in PATH
|
||||
*/
|
||||
ExtractProgram,
|
||||
/**
|
||||
* QStringList
|
||||
* The arguments that are passed to the program above for
|
||||
* extracting the archive. Special strings that will be
|
||||
* substituted:
|
||||
* $Archive - the path of the archive
|
||||
* $Files - the files selected to be extracted, if any
|
||||
* $PreservePathSwitch - the flag for extracting with full paths
|
||||
* $RootNodeSwitch - the internal work dir in the archive (for example
|
||||
* when the user has dragged a folder from the archive and wants it
|
||||
* extracted relative to it)
|
||||
* $PasswordSwitch - the switch setting the password. Note that this
|
||||
* will not be inserted unless the listing function has emitted an
|
||||
* entry with the IsPasswordProtected property set to true.
|
||||
*/
|
||||
ExtractArgs,
|
||||
/**
|
||||
* Bool (default false)
|
||||
* When passing directories to the extract program, do not
|
||||
* include trailing slashes
|
||||
* e.g. if the user selected "foo/" and "foo/bar" in the gui, the
|
||||
* paths "foo" and "foo/bar" will be sent to the program.
|
||||
*/
|
||||
NoTrailingSlashes,
|
||||
/**
|
||||
* QStringList
|
||||
* This should be a qstringlist with either two elements. The first
|
||||
* string is what PreservePathSwitch in the ExtractArgs will be replaced
|
||||
* with if PreservePath is True/enabled. The second is for the disabled
|
||||
* case. An empty string means that the argument will not be used in
|
||||
* that case.
|
||||
* Example: for rar, "x" means extract with full paths, and "e" means
|
||||
* extract without full paths. in this case we will use the stringlist
|
||||
* ("x", "e"). Or, for another format that might use the switch
|
||||
* "--extractFull" for preservePaths, and nothing otherwise: we use the
|
||||
* stringlist ("--extractFull", "")
|
||||
*/
|
||||
PreservePathSwitch,
|
||||
/**
|
||||
* QStringList (default empty)
|
||||
* The format of the root node switch. The variable $Path will be
|
||||
* substituted for the path string.
|
||||
* Example: ("--internalPath=$Path)
|
||||
* or ("--path", "$Path")
|
||||
*/
|
||||
RootNodeSwitch,
|
||||
/**
|
||||
* QStringList (default empty)
|
||||
* The format of the root node switch. The variable $Password will be
|
||||
* substituted for the password string. NOTE: supplying passwords
|
||||
* through a virtual terminal is not supported (yet?), because this
|
||||
* is not cross platform compatible. As of KDE 4.3 there are no plans to
|
||||
* change this.
|
||||
* Example: ("-p$Password)
|
||||
* or ("--password", "$Password")
|
||||
*/
|
||||
PasswordSwitch,
|
||||
/**
|
||||
* QString
|
||||
* This is a regexp, defining how to recognize a "File already exists"
|
||||
* prompt when extracting. It should have one captured string, which is
|
||||
* the filename of the file/folder that already exists.
|
||||
*/
|
||||
FileExistsExpression,
|
||||
/**
|
||||
* int
|
||||
* This sets on what output channel the FileExistsExpression regex
|
||||
* should be applied on, in other words, on what stream the "file
|
||||
* exists" output will appear in. Values accepted:
|
||||
* 0 - Standard error, stderr (default)
|
||||
* 1 - Standard output, stdout
|
||||
*/
|
||||
FileExistsMode,
|
||||
/**
|
||||
* QStringList
|
||||
* The various responses that can be supplied as a response to the
|
||||
* "file exists" prompt. The various items are to be supplied in the
|
||||
* following order:
|
||||
* index 0 - Yes (overwrite)
|
||||
* index 1 - No (skip/do not overwrite)
|
||||
* index 2 - All (overwrite all)
|
||||
* index 3 - Do not overwrite any files (autoskip)
|
||||
* index 4 - Cancel operation
|
||||
*/
|
||||
FileExistsInput,
|
||||
|
||||
///////////////[ DELETE ]/////////////
|
||||
|
||||
/**
|
||||
* QStringList
|
||||
* The names to the program that will handle deleting of elements in this
|
||||
* archive format (eg "rar"). Will be searched for in PATH
|
||||
*/
|
||||
DeleteProgram,
|
||||
/**
|
||||
* QStringList
|
||||
* The arguments that are passed to the program above for
|
||||
* deleting from the archive. Special strings that will be
|
||||
* substituted:
|
||||
* $Archive - the path of the archive
|
||||
* $Files - the files selected to be deleted
|
||||
*/
|
||||
DeleteArgs,
|
||||
/**
|
||||
* QStringList
|
||||
* Default: empty
|
||||
* A list of regexp patterns that will cause the extraction to exit
|
||||
* with a general fail message
|
||||
*/
|
||||
ExtractionFailedPatterns,
|
||||
/**
|
||||
* QStringList
|
||||
* Default: empty
|
||||
* A list of regexp patterns that will alert the user that the password
|
||||
* was wrong.
|
||||
*/
|
||||
WrongPasswordPatterns,
|
||||
|
||||
///////////////[ ADD ]/////////////
|
||||
|
||||
/**
|
||||
* QStringList
|
||||
* The names to the program that will handle adding in this
|
||||
* archive format (eg "rar"). Will be searched for in PATH
|
||||
*/
|
||||
AddProgram,
|
||||
/**
|
||||
* QStringList
|
||||
* The arguments that are passed to the program above for
|
||||
* adding to the archive. Special strings that will be
|
||||
* substituted:
|
||||
* $Archive - the path of the archive
|
||||
* $Files - the files selected to be added
|
||||
*/
|
||||
AddArgs
|
||||
};
|
||||
|
||||
typedef QHash<int, QVariant> ParameterList;
|
||||
|
||||
class KERFUFFLE_EXPORT CliInterface : public ReadWriteArchiveInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum OperationMode {
|
||||
List, Copy, Add, Delete
|
||||
};
|
||||
OperationMode m_operationMode;
|
||||
|
||||
explicit CliInterface(QObject *parent, const QVariantList & args);
|
||||
virtual ~CliInterface();
|
||||
|
||||
virtual bool list();
|
||||
virtual bool copyFiles(const QList<QVariant> & files, const QString & destinationDirectory, ExtractionOptions options);
|
||||
virtual bool addFiles(const QStringList & files, const CompressionOptions& options);
|
||||
virtual bool deleteFiles(const QList<QVariant> & files);
|
||||
|
||||
virtual ParameterList parameterList() const = 0;
|
||||
virtual bool readListLine(const QString &line) = 0;
|
||||
|
||||
bool doKill();
|
||||
bool doSuspend();
|
||||
bool doResume();
|
||||
|
||||
/**
|
||||
* Returns the list of characters which are preceded by a
|
||||
* backslash when a file name in an archive is passed to
|
||||
* a program.
|
||||
*
|
||||
* @see setEscapedCharacters().
|
||||
*/
|
||||
QString escapedCharacters();
|
||||
|
||||
/**
|
||||
* Sets which characters will be preceded by a backslash when
|
||||
* a file name in an archive is passed to a program.
|
||||
*
|
||||
* @see escapedCharacters().
|
||||
*/
|
||||
void setEscapedCharacters(const QString& characters);
|
||||
|
||||
/**
|
||||
* Sets if the listing should include empty lines.
|
||||
*
|
||||
* The default value is false.
|
||||
*/
|
||||
void setListEmptyLines(bool emptyLines);
|
||||
|
||||
private:
|
||||
void substituteListVariables(QStringList& params);
|
||||
|
||||
void cacheParameterList();
|
||||
|
||||
/**
|
||||
* Checks whether a line of the program's output is a password prompt.
|
||||
*
|
||||
* It uses the regular expression in the @c PasswordPromptPattern parameter
|
||||
* for the check.
|
||||
*
|
||||
* @param line A line of the program's output.
|
||||
*
|
||||
* @return @c true if the given @p line is a password prompt, @c false
|
||||
* otherwise.
|
||||
*/
|
||||
|
||||
bool checkForPasswordPromptMessage(const QString& line);
|
||||
|
||||
bool checkForFileExistsMessage(const QString& line);
|
||||
bool handleFileExistsMessage(const QString& filename);
|
||||
bool checkForErrorMessage(const QString& line, int parameterIndex);
|
||||
void handleLine(const QString& line);
|
||||
|
||||
void failOperation();
|
||||
|
||||
/**
|
||||
* Run @p programName with the given @p arguments.
|
||||
* The method waits until @p programName is finished to exit.
|
||||
*
|
||||
* @param programName The program that will be run (not the whole path).
|
||||
* @param arguments A list of arguments that will be passed to the program.
|
||||
*
|
||||
* @return @c true if the program was found and the process ran correctly,
|
||||
* @c false otherwise.
|
||||
*/
|
||||
bool runProcess(const QStringList& programNames, const QStringList& arguments);
|
||||
|
||||
/**
|
||||
* Performs any additional escaping and processing on @p fileName
|
||||
* before passing it to the underlying process.
|
||||
*
|
||||
* The default implementation returns @p fileName unchanged.
|
||||
*
|
||||
* @param fileName String to escape.
|
||||
*/
|
||||
virtual QString escapeFileName(const QString &fileName) const;
|
||||
|
||||
/**
|
||||
* Wrapper around KProcess::write() or KPtyDevice::write(), depending on
|
||||
* the platform.
|
||||
*/
|
||||
void writeToProcess(const QByteArray& data);
|
||||
|
||||
QByteArray m_stdOutData;
|
||||
QRegExp m_existsPattern;
|
||||
QRegExp m_passwordPromptPattern;
|
||||
QHash<int, QList<QRegExp> > m_patternCache;
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
KProcess *m_process;
|
||||
#else
|
||||
KPtyProcess *m_process;
|
||||
#endif
|
||||
|
||||
ParameterList m_param;
|
||||
QVariantList m_removedFiles;
|
||||
bool m_listEmptyLines;
|
||||
bool m_abortingOperation;
|
||||
|
||||
private slots:
|
||||
void readStdout(bool handleAll = false);
|
||||
void processFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* CLIINTERFACE_H */
|
234
ark/kerfuffle/extractiondialog.cpp
Normal file
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2009 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "extractiondialog.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include <KLocale>
|
||||
#include <KIconLoader>
|
||||
#include <KMessageBox>
|
||||
#include <KStandardDirs>
|
||||
#include <KDebug>
|
||||
#include <KIO/NetAccess>
|
||||
|
||||
#include <QDir>
|
||||
|
||||
#include "ui_extractiondialog.h"
|
||||
|
||||
namespace Kerfuffle
|
||||
{
|
||||
|
||||
class ExtractionDialogUI: public QFrame, public Ui::ExtractionDialog
|
||||
{
|
||||
public:
|
||||
ExtractionDialogUI(QWidget *parent = 0)
|
||||
: QFrame(parent) {
|
||||
setupUi(this);
|
||||
}
|
||||
};
|
||||
|
||||
ExtractionDialog::ExtractionDialog(QWidget *parent)
|
||||
: KDirSelectDialog(KUrl(), false, parent)
|
||||
{
|
||||
m_ui = new ExtractionDialogUI(this);
|
||||
|
||||
mainWidget()->layout()->addWidget(m_ui);
|
||||
setCaption(i18nc("@title:window", "Extract"));
|
||||
m_ui->iconLabel->setPixmap(DesktopIcon(QLatin1String( "archive-extract" )));
|
||||
|
||||
m_ui->filesToExtractGroupBox->hide();
|
||||
m_ui->allFilesButton->setChecked(true);
|
||||
m_ui->extractAllLabel->show();
|
||||
|
||||
setSingleFolderArchive(false);
|
||||
|
||||
m_ui->autoSubfolders->hide();
|
||||
|
||||
loadSettings();
|
||||
|
||||
connect(this, SIGNAL(finished(int)), SLOT(writeSettings()));
|
||||
}
|
||||
|
||||
void ExtractionDialog::loadSettings()
|
||||
{
|
||||
setOpenDestinationFolderAfterExtraction(ArkSettings::openDestinationFolderAfterExtraction());
|
||||
setCloseAfterExtraction(ArkSettings::closeAfterExtraction());
|
||||
setPreservePaths(ArkSettings::preservePaths());
|
||||
}
|
||||
|
||||
void ExtractionDialog::setSingleFolderArchive(bool value)
|
||||
{
|
||||
m_ui->singleFolderGroup->setChecked(!value);
|
||||
}
|
||||
|
||||
void ExtractionDialog::batchModeOption()
|
||||
{
|
||||
m_ui->autoSubfolders->show();
|
||||
m_ui->autoSubfolders->setEnabled(true);
|
||||
m_ui->singleFolderGroup->hide();
|
||||
m_ui->extractAllLabel->setText(i18n("Extract multiple archives"));
|
||||
}
|
||||
|
||||
void ExtractionDialog::accept()
|
||||
{
|
||||
if (extractToSubfolder()) {
|
||||
if (subfolder().contains(QLatin1String( "/" ))) {
|
||||
KMessageBox::error(NULL, i18n("The subfolder name may not contain the character '/'."));
|
||||
return;
|
||||
}
|
||||
|
||||
const QString pathWithSubfolder = url().pathOrUrl(KUrl::AddTrailingSlash) + subfolder();
|
||||
|
||||
while (1) {
|
||||
if (KIO::NetAccess::exists(pathWithSubfolder, KIO::NetAccess::SourceSide, 0)) {
|
||||
if (QFileInfo(pathWithSubfolder).isDir()) {
|
||||
int overwrite = KMessageBox::questionYesNoCancel(0, i18nc("@info", "The folder <filename>%1</filename> already exists. Are you sure you want to extract here?", pathWithSubfolder), i18n("Folder exists"), KGuiItem(i18n("Extract here")), KGuiItem(i18n("Retry")), KGuiItem(i18n("Cancel")));
|
||||
|
||||
if (overwrite == KMessageBox::No) {
|
||||
// The user clicked Retry.
|
||||
continue;
|
||||
} else if (overwrite == KMessageBox::Cancel) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
KMessageBox::detailedError(0,
|
||||
i18nc("@info", "The folder <filename>%1</filename> could not be created.", subfolder()),
|
||||
i18nc("@info", "<filename>%1</filename> already exists, but is not a folder.", subfolder()));
|
||||
return;
|
||||
}
|
||||
} else if (!KIO::NetAccess::mkdir(pathWithSubfolder, 0)) {
|
||||
KMessageBox::detailedError(0,
|
||||
i18nc("@info", "The folder <filename>%1</filename> could not be created.", subfolder()),
|
||||
i18n("Please check your permissions to create it."));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
KDirSelectDialog::accept();
|
||||
}
|
||||
|
||||
void ExtractionDialog::setSubfolder(const QString& subfolder)
|
||||
{
|
||||
m_ui->subfolder->setText(subfolder);
|
||||
}
|
||||
|
||||
QString ExtractionDialog::subfolder() const
|
||||
{
|
||||
return m_ui->subfolder->text();
|
||||
}
|
||||
|
||||
ExtractionDialog::~ExtractionDialog()
|
||||
{
|
||||
delete m_ui;
|
||||
m_ui = 0;
|
||||
}
|
||||
|
||||
void ExtractionDialog::setShowSelectedFiles(bool value)
|
||||
{
|
||||
if (value) {
|
||||
m_ui->filesToExtractGroupBox->show();
|
||||
m_ui->selectedFilesButton->setChecked(true);
|
||||
m_ui->extractAllLabel->hide();
|
||||
} else {
|
||||
m_ui->filesToExtractGroupBox->hide();
|
||||
m_ui->selectedFilesButton->setChecked(false);
|
||||
m_ui->extractAllLabel->show();
|
||||
}
|
||||
}
|
||||
|
||||
bool ExtractionDialog::extractAllFiles() const
|
||||
{
|
||||
return m_ui->allFilesButton->isChecked();
|
||||
}
|
||||
|
||||
void ExtractionDialog::setAutoSubfolder(bool value)
|
||||
{
|
||||
m_ui->autoSubfolders->setChecked(value);
|
||||
}
|
||||
|
||||
bool ExtractionDialog::autoSubfolders() const
|
||||
{
|
||||
return m_ui->autoSubfolders->isChecked();
|
||||
}
|
||||
|
||||
bool ExtractionDialog::extractToSubfolder() const
|
||||
{
|
||||
return m_ui->singleFolderGroup->isChecked();
|
||||
}
|
||||
|
||||
void ExtractionDialog::setOpenDestinationFolderAfterExtraction(bool value)
|
||||
{
|
||||
m_ui->openFolderCheckBox->setChecked(value);
|
||||
}
|
||||
|
||||
void ExtractionDialog::setCloseAfterExtraction(bool value)
|
||||
{
|
||||
m_ui->closeAfterExtraction->setChecked(value);
|
||||
}
|
||||
|
||||
void ExtractionDialog::setPreservePaths(bool value)
|
||||
{
|
||||
m_ui->preservePaths->setChecked(value);
|
||||
}
|
||||
|
||||
bool ExtractionDialog::preservePaths() const
|
||||
{
|
||||
return m_ui->preservePaths->isChecked();
|
||||
}
|
||||
|
||||
bool ExtractionDialog::openDestinationAfterExtraction() const
|
||||
{
|
||||
return m_ui->openFolderCheckBox->isChecked();
|
||||
}
|
||||
|
||||
bool ExtractionDialog::closeAfterExtraction() const
|
||||
{
|
||||
return m_ui->closeAfterExtraction->isChecked();
|
||||
}
|
||||
|
||||
KUrl ExtractionDialog::destinationDirectory() const
|
||||
{
|
||||
if (extractToSubfolder()) {
|
||||
return QString(url().pathOrUrl(KUrl::AddTrailingSlash) + subfolder() + QLatin1Char( '/' ));
|
||||
} else {
|
||||
return url().pathOrUrl(KUrl::AddTrailingSlash);
|
||||
}
|
||||
}
|
||||
|
||||
void ExtractionDialog::writeSettings()
|
||||
{
|
||||
ArkSettings::setOpenDestinationFolderAfterExtraction(openDestinationAfterExtraction());
|
||||
ArkSettings::setCloseAfterExtraction(closeAfterExtraction());
|
||||
ArkSettings::setPreservePaths(preservePaths());
|
||||
ArkSettings::self()->writeConfig();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "extractiondialog.moc"
|
78
ark/kerfuffle/extractiondialog.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
|
||||
* Copyright (C) 2008 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef EXTRACTIONDIALOG_H
|
||||
#define EXTRACTIONDIALOG_H
|
||||
|
||||
#include "kerfuffle_export.h"
|
||||
|
||||
#include <KDirSelectDialog>
|
||||
|
||||
#include <KDialog>
|
||||
|
||||
namespace Kerfuffle
|
||||
{
|
||||
class KERFUFFLE_EXPORT ExtractionDialog : public KDirSelectDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ExtractionDialog(QWidget *parent = 0);
|
||||
virtual ~ExtractionDialog();
|
||||
|
||||
void setShowSelectedFiles(bool);
|
||||
void setSingleFolderArchive(bool);
|
||||
void setPreservePaths(bool);
|
||||
void batchModeOption();
|
||||
void setOpenDestinationFolderAfterExtraction(bool);
|
||||
void setCloseAfterExtraction(bool);
|
||||
void setAutoSubfolder(bool value);
|
||||
|
||||
bool extractAllFiles() const;
|
||||
bool openDestinationAfterExtraction() const;
|
||||
bool closeAfterExtraction() const;
|
||||
bool extractToSubfolder() const;
|
||||
bool autoSubfolders() const;
|
||||
bool preservePaths() const;
|
||||
KUrl destinationDirectory() const;
|
||||
QString subfolder() const;
|
||||
virtual void accept();
|
||||
|
||||
public Q_SLOTS:
|
||||
void setSubfolder(const QString& subfolder);
|
||||
|
||||
private Q_SLOTS:
|
||||
void writeSettings();
|
||||
|
||||
private:
|
||||
void loadSettings();
|
||||
|
||||
class ExtractionDialogUI *m_ui;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // EXTRACTIONDIALOG_H
|
220
ark/kerfuffle/extractiondialog.ui
Normal file
|
@ -0,0 +1,220 @@
|
|||
<ui version="4.0" >
|
||||
<author>Henrique Pinto <henrique.pinto@kdemail.net></author>
|
||||
<class>ExtractionDialog</class>
|
||||
<widget class="QWidget" name="ExtractionDialog" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>314</width>
|
||||
<height>422</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Preferred" hsizetype="Fixed" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Extraction Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2" >
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="iconLabel" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Minimum" hsizetype="Fixed" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>256</width>
|
||||
<height>256</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap" >
|
||||
<pixmap>../../../../../kde-devel/ark-trunk/pics/ox32-action-ark_extract.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="extractAllLabel" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Maximum" hsizetype="Expanding" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font" >
|
||||
<font>
|
||||
<pointsize>15</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Extract All Files</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="singleFolderGroup" >
|
||||
<property name="title" >
|
||||
<string>&Extraction into subfolder:</string>
|
||||
</property>
|
||||
<property name="checkable" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" >
|
||||
<item>
|
||||
<widget class="KLineEdit" name="subfolder" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="showClearButton" stdset="0" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Expanding" hsizetype="Preferred" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title" >
|
||||
<string>Options</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout" >
|
||||
<item row="6" column="0" >
|
||||
<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>
|
||||
<item row="2" column="0" >
|
||||
<widget class="QCheckBox" name="openFolderCheckBox" >
|
||||
<property name="text" >
|
||||
<string>Open &destination folder after extraction</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" >
|
||||
<widget class="QCheckBox" name="closeAfterExtraction" >
|
||||
<property name="text" >
|
||||
<string>Close &Ark after extraction</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" >
|
||||
<widget class="QCheckBox" name="preservePaths" >
|
||||
<property name="text" >
|
||||
<string>&Preserve paths when extracting</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" >
|
||||
<widget class="QCheckBox" name="autoSubfolders" >
|
||||
<property name="text" >
|
||||
<string>&Automatically create subfolders</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="filesToExtractGroupBox" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Preferred" hsizetype="Expanding" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title" >
|
||||
<string comment="@title:group">Extract</string>
|
||||
</property>
|
||||
<property name="flat" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="checkable" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<widget class="QRadioButton" name="selectedFilesButton" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>&Selected files only</string>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="allFilesButton" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>All &files</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>KLineEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>klineedit.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
346
ark/kerfuffle/jobs.cpp
Normal file
|
@ -0,0 +1,346 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
|
||||
* Copyright (c) 2008-2009 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
* Copyright (c) 2009-2012 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "jobs.h"
|
||||
|
||||
#include <QThread>
|
||||
|
||||
#include <KDebug>
|
||||
#include <KLocale>
|
||||
|
||||
//#define DEBUG_RACECONDITION
|
||||
|
||||
namespace Kerfuffle
|
||||
{
|
||||
|
||||
class Job::Private : public QThread
|
||||
{
|
||||
public:
|
||||
Private(Job *job, QObject *parent = 0)
|
||||
: QThread(parent)
|
||||
, q(job)
|
||||
{
|
||||
connect(q, SIGNAL(result(KJob*)), SLOT(quit()));
|
||||
}
|
||||
|
||||
virtual void run();
|
||||
|
||||
private:
|
||||
Job *q;
|
||||
};
|
||||
|
||||
void Job::Private::run()
|
||||
{
|
||||
q->doWork();
|
||||
|
||||
if (q->isRunning()) {
|
||||
exec();
|
||||
}
|
||||
|
||||
#ifdef DEBUG_RACECONDITION
|
||||
QThread::sleep(2);
|
||||
#endif
|
||||
}
|
||||
|
||||
Job::Job(ReadOnlyArchiveInterface *interface, QObject *parent)
|
||||
: KJob(parent)
|
||||
, m_archiveInterface(interface)
|
||||
, m_isRunning(false)
|
||||
, d(new Private(this))
|
||||
{
|
||||
static bool onlyOnce = false;
|
||||
if (!onlyOnce) {
|
||||
qRegisterMetaType<QPair<QString, QString> >("QPair<QString,QString>");
|
||||
onlyOnce = true;
|
||||
}
|
||||
|
||||
setCapabilities(KJob::Killable);
|
||||
}
|
||||
|
||||
Job::~Job()
|
||||
{
|
||||
if (d->isRunning()) {
|
||||
d->wait();
|
||||
}
|
||||
|
||||
delete d;
|
||||
}
|
||||
|
||||
ReadOnlyArchiveInterface *Job::archiveInterface()
|
||||
{
|
||||
return m_archiveInterface;
|
||||
}
|
||||
|
||||
bool Job::isRunning() const
|
||||
{
|
||||
return m_isRunning;
|
||||
}
|
||||
|
||||
void Job::start()
|
||||
{
|
||||
m_isRunning = true;
|
||||
d->start();
|
||||
}
|
||||
|
||||
void Job::emitResult()
|
||||
{
|
||||
m_isRunning = false;
|
||||
KJob::emitResult();
|
||||
}
|
||||
|
||||
void Job::connectToArchiveInterfaceSignals()
|
||||
{
|
||||
connect(archiveInterface(), SIGNAL(error(QString,QString)), SLOT(onError(QString,QString)));
|
||||
connect(archiveInterface(), SIGNAL(entry(ArchiveEntry)), SLOT(onEntry(ArchiveEntry)));
|
||||
connect(archiveInterface(), SIGNAL(entryRemoved(QString)), SLOT(onEntryRemoved(QString)));
|
||||
connect(archiveInterface(), SIGNAL(progress(double)), SLOT(onProgress(double)));
|
||||
connect(archiveInterface(), SIGNAL(info(QString)), SLOT(onInfo(QString)));
|
||||
connect(archiveInterface(), SIGNAL(finished(bool)), SLOT(onFinished(bool)), Qt::DirectConnection);
|
||||
connect(archiveInterface(), SIGNAL(userQuery(Query*)), SLOT(onUserQuery(Query*)));
|
||||
}
|
||||
|
||||
void Job::onError(const QString & message, const QString & details)
|
||||
{
|
||||
Q_UNUSED(details)
|
||||
|
||||
setError(1);
|
||||
setErrorText(message);
|
||||
}
|
||||
|
||||
void Job::onEntry(const ArchiveEntry & archiveEntry)
|
||||
{
|
||||
emit newEntry(archiveEntry);
|
||||
}
|
||||
|
||||
void Job::onProgress(double value)
|
||||
{
|
||||
setPercent(static_cast<unsigned long>(100.0*value));
|
||||
}
|
||||
|
||||
void Job::onInfo(const QString& info)
|
||||
{
|
||||
emit infoMessage(this, info);
|
||||
}
|
||||
|
||||
void Job::onEntryRemoved(const QString & path)
|
||||
{
|
||||
emit entryRemoved(path);
|
||||
}
|
||||
|
||||
void Job::onFinished(bool result)
|
||||
{
|
||||
kDebug() << result;
|
||||
|
||||
archiveInterface()->disconnect(this);
|
||||
|
||||
emitResult();
|
||||
}
|
||||
|
||||
void Job::onUserQuery(Query *query)
|
||||
{
|
||||
emit userQuery(query);
|
||||
}
|
||||
|
||||
bool Job::doKill()
|
||||
{
|
||||
kDebug();
|
||||
bool ret = archiveInterface()->doKill();
|
||||
if (!ret) {
|
||||
kDebug() << "Killing does not seem to be supported here.";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ListJob::ListJob(ReadOnlyArchiveInterface *interface, QObject *parent)
|
||||
: Job(interface, parent)
|
||||
, m_isSingleFolderArchive(true)
|
||||
, m_isPasswordProtected(false)
|
||||
, m_extractedFilesSize(0)
|
||||
{
|
||||
connect(this, SIGNAL(newEntry(ArchiveEntry)),
|
||||
this, SLOT(onNewEntry(ArchiveEntry)));
|
||||
}
|
||||
|
||||
void ListJob::doWork()
|
||||
{
|
||||
emit description(this, i18n("Loading archive..."));
|
||||
connectToArchiveInterfaceSignals();
|
||||
bool ret = archiveInterface()->list();
|
||||
|
||||
if (!archiveInterface()->waitForFinishedSignal()) {
|
||||
onFinished(ret);
|
||||
}
|
||||
}
|
||||
|
||||
qlonglong ListJob::extractedFilesSize() const
|
||||
{
|
||||
return m_extractedFilesSize;
|
||||
}
|
||||
|
||||
bool ListJob::isPasswordProtected() const
|
||||
{
|
||||
return m_isPasswordProtected;
|
||||
}
|
||||
|
||||
bool ListJob::isSingleFolderArchive() const
|
||||
{
|
||||
return m_isSingleFolderArchive;
|
||||
}
|
||||
|
||||
void ListJob::onNewEntry(const ArchiveEntry& entry)
|
||||
{
|
||||
m_extractedFilesSize += entry[ Size ].toLongLong();
|
||||
m_isPasswordProtected |= entry [ IsPasswordProtected ].toBool();
|
||||
|
||||
if (m_isSingleFolderArchive) {
|
||||
const QString fileName(entry[FileName].toString());
|
||||
const QString basePath(fileName.split(QLatin1Char( '/' )).at(0));
|
||||
|
||||
if (m_basePath.isEmpty()) {
|
||||
m_basePath = basePath;
|
||||
m_subfolderName = basePath;
|
||||
} else {
|
||||
if (m_basePath != basePath) {
|
||||
m_isSingleFolderArchive = false;
|
||||
m_subfolderName.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString ListJob::subfolderName() const
|
||||
{
|
||||
return m_subfolderName;
|
||||
}
|
||||
|
||||
ExtractJob::ExtractJob(const QVariantList& files, const QString& destinationDir, ExtractionOptions options, ReadOnlyArchiveInterface *interface, QObject *parent)
|
||||
: Job(interface, parent)
|
||||
, m_files(files)
|
||||
, m_destinationDir(destinationDir)
|
||||
, m_options(options)
|
||||
{
|
||||
setDefaultOptions();
|
||||
}
|
||||
|
||||
void ExtractJob::doWork()
|
||||
{
|
||||
QString desc;
|
||||
if (m_files.count() == 0) {
|
||||
desc = i18n("Extracting all files");
|
||||
} else {
|
||||
desc = i18np("Extracting one file", "Extracting %1 files", m_files.count());
|
||||
}
|
||||
emit description(this, desc);
|
||||
|
||||
connectToArchiveInterfaceSignals();
|
||||
|
||||
kDebug() << "Starting extraction with selected files:"
|
||||
<< m_files
|
||||
<< "Destination dir:" << m_destinationDir
|
||||
<< "Options:" << m_options;
|
||||
|
||||
bool ret = archiveInterface()->copyFiles(m_files, m_destinationDir, m_options);
|
||||
|
||||
if (!archiveInterface()->waitForFinishedSignal()) {
|
||||
onFinished(ret);
|
||||
}
|
||||
}
|
||||
|
||||
void ExtractJob::setDefaultOptions()
|
||||
{
|
||||
ExtractionOptions defaultOptions;
|
||||
|
||||
defaultOptions[QLatin1String("PreservePaths")] = false;
|
||||
|
||||
ExtractionOptions::const_iterator it = defaultOptions.constBegin();
|
||||
for (; it != defaultOptions.constEnd(); ++it) {
|
||||
if (!m_options.contains(it.key())) {
|
||||
m_options[it.key()] = it.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString ExtractJob::destinationDirectory() const
|
||||
{
|
||||
return m_destinationDir;
|
||||
}
|
||||
|
||||
ExtractionOptions ExtractJob::extractionOptions() const
|
||||
{
|
||||
return m_options;
|
||||
}
|
||||
|
||||
AddJob::AddJob(const QStringList& files, const CompressionOptions& options , ReadWriteArchiveInterface *interface, QObject *parent)
|
||||
: Job(interface, parent)
|
||||
, m_files(files)
|
||||
, m_options(options)
|
||||
{
|
||||
}
|
||||
|
||||
void AddJob::doWork()
|
||||
{
|
||||
emit description(this, i18np("Adding a file", "Adding %1 files", m_files.count()));
|
||||
|
||||
ReadWriteArchiveInterface *m_writeInterface =
|
||||
qobject_cast<ReadWriteArchiveInterface*>(archiveInterface());
|
||||
|
||||
Q_ASSERT(m_writeInterface);
|
||||
|
||||
connectToArchiveInterfaceSignals();
|
||||
bool ret = m_writeInterface->addFiles(m_files, m_options);
|
||||
|
||||
if (!archiveInterface()->waitForFinishedSignal()) {
|
||||
onFinished(ret);
|
||||
}
|
||||
}
|
||||
|
||||
DeleteJob::DeleteJob(const QVariantList& files, ReadWriteArchiveInterface *interface, QObject *parent)
|
||||
: Job(interface, parent)
|
||||
, m_files(files)
|
||||
{
|
||||
}
|
||||
|
||||
void DeleteJob::doWork()
|
||||
{
|
||||
emit description(this, i18np("Deleting a file from the archive", "Deleting %1 files", m_files.count()));
|
||||
|
||||
ReadWriteArchiveInterface *m_writeInterface =
|
||||
qobject_cast<ReadWriteArchiveInterface*>(archiveInterface());
|
||||
|
||||
Q_ASSERT(m_writeInterface);
|
||||
|
||||
connectToArchiveInterfaceSignals();
|
||||
int ret = m_writeInterface->deleteFiles(m_files);
|
||||
|
||||
if (!archiveInterface()->waitForFinishedSignal()) {
|
||||
onFinished(ret);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Kerfuffle
|
||||
|
||||
#include "jobs.moc"
|
171
ark/kerfuffle/jobs.h
Normal file
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
|
||||
* Copyright (c) 2008-2009 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
* Copyright (c) 2009-2012 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef JOBS_H
|
||||
#define JOBS_H
|
||||
|
||||
#include "kerfuffle_export.h"
|
||||
#include "archiveinterface.h"
|
||||
#include "archive.h"
|
||||
#include "queries.h"
|
||||
|
||||
#include <KJob>
|
||||
#include <QList>
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
|
||||
namespace Kerfuffle
|
||||
{
|
||||
|
||||
class ThreadExecution;
|
||||
|
||||
class KERFUFFLE_EXPORT Job : public KJob
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
void start();
|
||||
|
||||
bool isRunning() const;
|
||||
|
||||
protected:
|
||||
Job(ReadOnlyArchiveInterface *interface, QObject *parent = 0);
|
||||
virtual ~Job();
|
||||
virtual bool doKill();
|
||||
virtual void emitResult();
|
||||
|
||||
ReadOnlyArchiveInterface *archiveInterface();
|
||||
|
||||
void connectToArchiveInterfaceSignals();
|
||||
|
||||
public slots:
|
||||
virtual void doWork() = 0;
|
||||
|
||||
protected slots:
|
||||
virtual void onError(const QString &message, const QString &details);
|
||||
virtual void onInfo(const QString &info);
|
||||
virtual void onEntry(const ArchiveEntry &archiveEntry);
|
||||
virtual void onProgress(double progress);
|
||||
virtual void onEntryRemoved(const QString &path);
|
||||
virtual void onFinished(bool result);
|
||||
virtual void onUserQuery(Query *query);
|
||||
|
||||
signals:
|
||||
void entryRemoved(const QString & entry);
|
||||
void error(const QString& errorMessage, const QString& details);
|
||||
void newEntry(const ArchiveEntry &);
|
||||
void userQuery(Kerfuffle::Query*);
|
||||
|
||||
private:
|
||||
ReadOnlyArchiveInterface *m_archiveInterface;
|
||||
|
||||
bool m_isRunning;
|
||||
|
||||
class Private;
|
||||
Private * const d;
|
||||
};
|
||||
|
||||
class KERFUFFLE_EXPORT ListJob : public Job
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ListJob(ReadOnlyArchiveInterface *interface, QObject *parent = 0);
|
||||
|
||||
qlonglong extractedFilesSize() const;
|
||||
bool isPasswordProtected() const;
|
||||
bool isSingleFolderArchive() const;
|
||||
QString subfolderName() const;
|
||||
|
||||
public slots:
|
||||
virtual void doWork();
|
||||
|
||||
private:
|
||||
bool m_isSingleFolderArchive;
|
||||
bool m_isPasswordProtected;
|
||||
QString m_subfolderName;
|
||||
QString m_basePath;
|
||||
qlonglong m_extractedFilesSize;
|
||||
|
||||
private slots:
|
||||
void onNewEntry(const ArchiveEntry&);
|
||||
};
|
||||
|
||||
class KERFUFFLE_EXPORT ExtractJob : public Job
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ExtractJob(const QVariantList& files, const QString& destinationDir, ExtractionOptions options, ReadOnlyArchiveInterface *interface, QObject *parent = 0);
|
||||
|
||||
QString destinationDirectory() const;
|
||||
ExtractionOptions extractionOptions() const;
|
||||
|
||||
public slots:
|
||||
virtual void doWork();
|
||||
|
||||
private:
|
||||
// TODO: Maybe this should be a method if ExtractionOptions were a class?
|
||||
void setDefaultOptions();
|
||||
|
||||
QVariantList m_files;
|
||||
QString m_destinationDir;
|
||||
ExtractionOptions m_options;
|
||||
};
|
||||
|
||||
class KERFUFFLE_EXPORT AddJob : public Job
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AddJob(const QStringList& files, const CompressionOptions& options, ReadWriteArchiveInterface *interface, QObject *parent = 0);
|
||||
|
||||
public slots:
|
||||
virtual void doWork();
|
||||
|
||||
private:
|
||||
QStringList m_files;
|
||||
CompressionOptions m_options;
|
||||
};
|
||||
|
||||
class KERFUFFLE_EXPORT DeleteJob : public Job
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DeleteJob(const QVariantList& files, ReadWriteArchiveInterface *interface, QObject *parent = 0);
|
||||
|
||||
public slots:
|
||||
virtual void doWork();
|
||||
|
||||
private:
|
||||
QVariantList m_files;
|
||||
};
|
||||
|
||||
} // namespace Kerfuffle
|
||||
|
||||
#endif // JOBS_H
|
74
ark/kerfuffle/kerfufflePlugin.desktop
Normal file
|
@ -0,0 +1,74 @@
|
|||
[Desktop Entry]
|
||||
Type=ServiceType
|
||||
X-KDE-ServiceType=Kerfuffle/Plugin
|
||||
Comment=Plugin for handling of archive formats for the Kerfuffle library
|
||||
Comment[ar]=ملحق للتحكم بهيئات الأرشيف لمكتبة Kerfuffle
|
||||
Comment[ast]=Aplicación pa remanar los formatos de ficheru de la llibrería Kerfuffle
|
||||
Comment[bg]=Приствка за работа с архиви за Kerfuffle
|
||||
Comment[bs]=Priključak za rukovanje formatima arhiva za biblioteku Kerfafl
|
||||
Comment[ca]=Connector per gestionar els formats d'arxiu per la biblioteca Kerfuffle
|
||||
Comment[ca@valencia]=Connector per gestionar els formats d'arxiu per la biblioteca Kerfuffle
|
||||
Comment[cs]=Modul pro správu formátů archivů pro knihovnu Kerfuffle
|
||||
Comment[da]=Plugin til håndtering af arkivformater til Kerfuffle-biblioteket
|
||||
Comment[de]=Modul zum Umgang mit Archivformaten der Kerfuffle-Bibliothek
|
||||
Comment[el]=Πρόσθετο χειρισμού μορφών αρχειοθήκης για τη βιβλιοθήκη Kerfuffle
|
||||
Comment[en_GB]=Plugin for handling of archive formats for the Kerfuffle library
|
||||
Comment[es]=Complemento para manejar formatos de archivo de la biblioteca Kerfuffle
|
||||
Comment[et]=Kerfuffle'i teegi arhiivifailide haldamise plugin
|
||||
Comment[eu]=Kerfuffle liburutegiaren artxibo-formatuak erabiltzeko plugina
|
||||
Comment[fi]=Kerfuffle-kirjaston pakettimuotojen tuki
|
||||
Comment[fr]=Module externe de gestion des formats d'archives pour la bibliothèque « Kerfuffle »
|
||||
Comment[ga]=Breiseán a láimhseálann formáidí cartlainne thar ceann na leabharlainne Kerfuffle
|
||||
Comment[gl]=Extensión da biblioteca Kerfuffle para manexar formatos de arquivo
|
||||
Comment[he]=תוסף לניהול פורמטי ארכיונים לספריית Kerfuffle
|
||||
Comment[hne]=करफुफल लाइब्रेरी बर अभिलेख फारमेट हेंडल करे बर प्लगइन
|
||||
Comment[hr]=Priključak za upravljanje arhivnim formatima za biblioteku Kerfuffle
|
||||
Comment[hu]=Archívumkezelő modul a Kerfuffle programkönyvtárhoz
|
||||
Comment[ia]=Plugin per manear formatos de archivo per le libreria Kerfuffle
|
||||
Comment[id]=Pengaya untuk menangani format arsip pustaka Kerfuffle
|
||||
Comment[it]=Estensione per gestire formati di archivio per la libreria Kerfuffle
|
||||
Comment[ja]=Kerfuffle ライブラリのアーカイブ形式を扱うプラグイン
|
||||
Comment[kk]=Kerfuffle жиын файлға арналған архив пішіндерімен айналасу плагині
|
||||
Comment[km]=កម្មវិធីជំនួយសម្រាប់គ្រប់គ្រងទ្រង់ទ្រាយប័ណ្ណសារសម្រាប់បណ្ណាល័យ Kerfuffle
|
||||
Comment[ko]=Kerfuffle 라이브러리를 위한 압축 파일 플러그인
|
||||
Comment[lt]=Kerfuffle bibliotekos archyvų formatų palaikymo priedas
|
||||
Comment[lv]=Arhīva failu tipu izmantošanas spraudnis Kerfuffle bibliotēkai.
|
||||
Comment[mr]=कर्फफल लायब्ररी करिताचे संग्रह प्रकार हाताळणारे प्लगइन
|
||||
Comment[nb]=Programtillegg som håndterer arkivformater, for Kerfuffle-biblioteket
|
||||
Comment[nds]=Archievformaten-Moduul för de Kerfuffle-Bibliotheek
|
||||
Comment[nl]=Plug-in voor het afhandelen van archiefformaten voor de Kerfuffle-bibliotheek
|
||||
Comment[nn]=Programtillegg som handsamar arkivformat for Kerfuffle-biblioteket
|
||||
Comment[pl]=Wtyczka do obsługi formatów archiwów w bibliotece Kerfuffle
|
||||
Comment[pt]='Plugin' para lidar com os formatos de pacotes da biblioteca Kerfuffle
|
||||
Comment[pt_BR]=Plugin para manipulação de formatos de arquivo, para a biblioteca Kerfuffle
|
||||
Comment[ro]=Modul pentru pentru mînuirea formatelor de arhive pentru biblioteca Kerfuffle
|
||||
Comment[ru]=Расширение для поддержки архивов с помощью библиотеки Kerfuffle
|
||||
Comment[sk]=Modul pre spracovanie formátov archívov pre knižnicu Kerfuffle
|
||||
Comment[sl]=Vstavek za ravnanje z arhivi za knjižnico Kerfuffle
|
||||
Comment[sq]=Plugin që merret me formatet e arkivave për librarinë Kerfuffle
|
||||
Comment[sr]=Прикључак за руковање форматима архива за библиотеку Керфафл
|
||||
Comment[sr@ijekavian]=Прикључак за руковање форматима архива за библиотеку Керфафл
|
||||
Comment[sr@ijekavianlatin]=Priključak za rukovanje formatima arhiva za biblioteku Kerfuffle
|
||||
Comment[sr@latin]=Priključak za rukovanje formatima arhiva za biblioteku Kerfuffle
|
||||
Comment[sv]=Insticksprogram för hantering av arkivformat för Kerfuffle-biblioteket
|
||||
Comment[ta]=கெர்ஃபஃபில் ஃ நூலகத்துக்கு காப்பக வடிவமைப்பை கையாள சொருகிகள்
|
||||
Comment[th]=ส่วนเสริมของไลบรารี Kerfuffle สำหรับจัดการแฟ้มจัดเก็บแบบต่าง ๆ
|
||||
Comment[tr]=Kerfuffle kitaplığı için arşiv biçimleri eklentileri
|
||||
Comment[uk]=Додаток для роботи з форматами архівів для бібліотеки Kerfuffle
|
||||
Comment[x-test]=xxPlugin for handling of archive formats for the Kerfuffle libraryxx
|
||||
Comment[zh_CN]=Kerfuffle 库的压缩归档格式处理插件
|
||||
Comment[zh_TW]=處理 Kerfuffle 函式庫壓縮格式的外掛程式
|
||||
|
||||
# Priority. The greater the better.
|
||||
[PropertyDef::X-KDE-Priority]
|
||||
Type=int
|
||||
|
||||
# Revision of the plugin API.
|
||||
[PropertyDef::X-KDE-Kerfuffle-APIRevision]
|
||||
Type=int
|
||||
|
||||
# Is the plugin read-write or not? (i.e., can it create archives?)
|
||||
[PropertyDef::X-KDE-Kerfuffle-ReadWrite]
|
||||
Type=bool
|
||||
|
||||
|
53
ark/kerfuffle/kerfuffle_export.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* This file is part of the KDE project
|
||||
*
|
||||
* Copyright (C) 2007 David Faure <faure@kde.org>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef KERFUFFLE_EXPORT_H
|
||||
#define KERFUFFLE_EXPORT_H
|
||||
|
||||
/* needed for KDE_EXPORT and KDE_IMPORT macros */
|
||||
#include <kdemacros.h>
|
||||
#include <kpluginfactory.h>
|
||||
|
||||
#ifndef KERFUFFLE_EXPORT
|
||||
# if defined(MAKE_KERFUFFLE_LIB)
|
||||
/* We are building this library */
|
||||
# define KERFUFFLE_EXPORT KDE_EXPORT
|
||||
# else
|
||||
/* We are using this library */
|
||||
# define KERFUFFLE_EXPORT KDE_IMPORT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
# ifndef KERFUFFLE_EXPORT_DEPRECATED
|
||||
# define KERFUFFLE_EXPORT_DEPRECATED KDE_DEPRECATED KERFUFFLE_EXPORT
|
||||
# endif
|
||||
|
||||
#define KERFUFFLE_EXPORT_PLUGIN(p) \
|
||||
K_PLUGIN_FACTORY( ArkPluginFactory, registerPlugin< p >(); ) \
|
||||
K_EXPORT_PLUGIN( ArkPluginFactory("p") )
|
||||
|
||||
#endif
|
204
ark/kerfuffle/queries.cpp
Normal file
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2008-2009 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "queries.h"
|
||||
|
||||
#include <KLocale>
|
||||
#include <KPasswordDialog>
|
||||
#include <kdebug.h>
|
||||
#include <kio/renamedialog.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QWeakPointer>
|
||||
|
||||
namespace Kerfuffle
|
||||
{
|
||||
Query::Query()
|
||||
{
|
||||
m_responseMutex.lock();
|
||||
}
|
||||
|
||||
QVariant Query::response()
|
||||
{
|
||||
return m_data.value(QLatin1String( "response" ));
|
||||
}
|
||||
|
||||
void Query::waitForResponse()
|
||||
{
|
||||
kDebug();
|
||||
|
||||
//if there is no response set yet, wait
|
||||
if (!m_data.contains(QLatin1String("response"))) {
|
||||
m_responseCondition.wait(&m_responseMutex);
|
||||
}
|
||||
m_responseMutex.unlock();
|
||||
}
|
||||
|
||||
void Query::setResponse(QVariant response)
|
||||
{
|
||||
kDebug();
|
||||
|
||||
m_data[QLatin1String( "response" )] = response;
|
||||
m_responseCondition.wakeAll();
|
||||
}
|
||||
|
||||
OverwriteQuery::OverwriteQuery(const QString &filename) :
|
||||
m_noRenameMode(false),
|
||||
m_multiMode(true)
|
||||
{
|
||||
m_data[QLatin1String( "filename" )] = filename;
|
||||
}
|
||||
|
||||
void OverwriteQuery::execute()
|
||||
{
|
||||
// If we are being called from the KPart, the cursor is probably Qt::WaitCursor
|
||||
// at the moment (#231974)
|
||||
QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor));
|
||||
|
||||
KIO::RenameDialog_Mode mode = (KIO::RenameDialog_Mode)(KIO::M_OVERWRITE | KIO::M_SKIP);
|
||||
if (m_noRenameMode) {
|
||||
mode = (KIO::RenameDialog_Mode)(mode | KIO::M_NORENAME);
|
||||
}
|
||||
if (m_multiMode) {
|
||||
mode = (KIO::RenameDialog_Mode)(mode | KIO::M_MULTI);
|
||||
}
|
||||
|
||||
KUrl sourceUrl(m_data.value(QLatin1String( "filename" )).toString());
|
||||
KUrl destUrl(m_data.value(QLatin1String( "filename" )).toString());
|
||||
sourceUrl.cleanPath();
|
||||
destUrl.cleanPath();
|
||||
|
||||
QWeakPointer<KIO::RenameDialog> dialog = new KIO::RenameDialog(
|
||||
NULL,
|
||||
i18n("File already exists"),
|
||||
sourceUrl,
|
||||
destUrl,
|
||||
mode);
|
||||
dialog.data()->exec();
|
||||
|
||||
m_data[QLatin1String("newFilename")] = dialog.data()->newDestUrl().pathOrUrl();
|
||||
|
||||
setResponse(dialog.data()->result());
|
||||
|
||||
delete dialog.data();
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
bool OverwriteQuery::responseCancelled()
|
||||
{
|
||||
return m_data.value(QLatin1String( "response" )).toInt() == KIO::R_CANCEL;
|
||||
}
|
||||
bool OverwriteQuery::responseOverwriteAll()
|
||||
{
|
||||
return m_data.value(QLatin1String( "response" )).toInt() == KIO::R_OVERWRITE_ALL;
|
||||
}
|
||||
bool OverwriteQuery::responseOverwrite()
|
||||
{
|
||||
return m_data.value(QLatin1String( "response" )).toInt() == KIO::R_OVERWRITE;
|
||||
}
|
||||
|
||||
bool OverwriteQuery::responseRename()
|
||||
{
|
||||
return m_data.value(QLatin1String( "response" )).toInt() == KIO::R_RENAME;
|
||||
}
|
||||
|
||||
bool OverwriteQuery::responseSkip()
|
||||
{
|
||||
return m_data.value(QLatin1String( "response" )).toInt() == KIO::R_SKIP;
|
||||
}
|
||||
|
||||
bool OverwriteQuery::responseAutoSkip()
|
||||
{
|
||||
return m_data.value(QLatin1String( "response" )).toInt() == KIO::R_AUTO_SKIP;
|
||||
}
|
||||
|
||||
QString OverwriteQuery::newFilename()
|
||||
{
|
||||
return m_data.value(QLatin1String( "newFilename" )).toString();
|
||||
}
|
||||
|
||||
void OverwriteQuery::setNoRenameMode(bool enableNoRenameMode)
|
||||
{
|
||||
m_noRenameMode = enableNoRenameMode;
|
||||
}
|
||||
|
||||
bool OverwriteQuery::noRenameMode()
|
||||
{
|
||||
return m_noRenameMode;
|
||||
}
|
||||
|
||||
void OverwriteQuery::setMultiMode(bool enableMultiMode)
|
||||
{
|
||||
m_multiMode = enableMultiMode;
|
||||
}
|
||||
|
||||
bool OverwriteQuery::multiMode()
|
||||
{
|
||||
return m_multiMode;
|
||||
}
|
||||
|
||||
PasswordNeededQuery::PasswordNeededQuery(const QString& archiveFilename, bool incorrectTryAgain)
|
||||
{
|
||||
m_data[QLatin1String( "archiveFilename" )] = archiveFilename;
|
||||
m_data[QLatin1String( "incorrectTryAgain" )] = incorrectTryAgain;
|
||||
}
|
||||
|
||||
void PasswordNeededQuery::execute()
|
||||
{
|
||||
// If we are being called from the KPart, the cursor is probably Qt::WaitCursor
|
||||
// at the moment (#231974)
|
||||
QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor));
|
||||
|
||||
QWeakPointer<KPasswordDialog> dlg = new KPasswordDialog;
|
||||
dlg.data()->setPrompt(i18nc("@info", "The archive <filename>%1</filename> is password protected. Please enter the password to extract the file.", m_data.value(QLatin1String( "archiveFilename" )).toString()));
|
||||
|
||||
if (m_data.value(QLatin1String("incorrectTryAgain")).toBool()) {
|
||||
dlg.data()->showErrorMessage(i18n("Incorrect password, please try again."), KPasswordDialog::PasswordError);
|
||||
}
|
||||
|
||||
const bool notCancelled = dlg.data()->exec();
|
||||
const QString password = dlg.data()->password();
|
||||
|
||||
m_data[QLatin1String("password")] = password;
|
||||
setResponse(notCancelled && !password.isEmpty());
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
delete dlg.data();
|
||||
}
|
||||
|
||||
QString PasswordNeededQuery::password()
|
||||
{
|
||||
return m_data.value(QLatin1String( "password" )).toString();
|
||||
}
|
||||
|
||||
bool PasswordNeededQuery::responseCancelled()
|
||||
{
|
||||
return !m_data.value(QLatin1String( "response" )).toBool();
|
||||
}
|
||||
}
|
111
ark/kerfuffle/queries.h
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2008 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef QUERIES_H
|
||||
#define QUERIES_H
|
||||
|
||||
#include "kerfuffle_export.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QHash>
|
||||
#include <QWaitCondition>
|
||||
#include <QMutex>
|
||||
#include <QVariant>
|
||||
|
||||
namespace Kerfuffle
|
||||
{
|
||||
|
||||
typedef QHash<QString, QVariant> QueryData;
|
||||
|
||||
class KERFUFFLE_EXPORT Query
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Execute the response. Will happen in the GUI thread, so it's
|
||||
* safe to use widgets/gui elements here. Must call setResponse
|
||||
* when done.
|
||||
*/
|
||||
virtual void execute() = 0;
|
||||
|
||||
/**
|
||||
* Will block until the response have been set
|
||||
*/
|
||||
void waitForResponse();
|
||||
|
||||
QVariant response();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Protected constructor
|
||||
*/
|
||||
Query();
|
||||
virtual ~Query() {}
|
||||
|
||||
void setResponse(QVariant response);
|
||||
|
||||
QueryData m_data;
|
||||
|
||||
private:
|
||||
QWaitCondition m_responseCondition;
|
||||
QMutex m_responseMutex;
|
||||
};
|
||||
|
||||
class KERFUFFLE_EXPORT OverwriteQuery : public Query
|
||||
{
|
||||
public:
|
||||
explicit OverwriteQuery(const QString& filename);
|
||||
void execute();
|
||||
bool responseCancelled();
|
||||
bool responseOverwriteAll();
|
||||
bool responseOverwrite();
|
||||
bool responseRename();
|
||||
bool responseSkip();
|
||||
bool responseAutoSkip();
|
||||
QString newFilename();
|
||||
|
||||
void setNoRenameMode(bool enableNoRenameMode);
|
||||
bool noRenameMode();
|
||||
void setMultiMode(bool enableMultiMode);
|
||||
bool multiMode();
|
||||
private:
|
||||
bool m_noRenameMode;
|
||||
bool m_multiMode;
|
||||
};
|
||||
|
||||
class KERFUFFLE_EXPORT PasswordNeededQuery : public Query
|
||||
{
|
||||
public:
|
||||
explicit PasswordNeededQuery(const QString& archiveFilename, bool incorrectTryAgain = false);
|
||||
void execute();
|
||||
|
||||
bool responseCancelled();
|
||||
QString password();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* ifndef QUERIES_H */
|
7
ark/kerfuffle/settings.kcfgc
Normal file
|
@ -0,0 +1,7 @@
|
|||
File=ark.kcfg
|
||||
ClassName=ArkSettings
|
||||
Singleton=true
|
||||
Mutators=true
|
||||
SetUserTexts=true
|
||||
IncludeFiles=\"kerfuffle/kerfuffle_export.h\"
|
||||
Visibility=KERFUFFLE_EXPORT
|
21
ark/kerfuffle/tests/CMakeLists.txt
Normal file
|
@ -0,0 +1,21 @@
|
|||
include_directories(${KERFUFFLE_QJSON_INCLUDE_DIR})
|
||||
|
||||
set(RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(JSONINTERFACE_SOURCES
|
||||
jsonarchiveinterface.cpp
|
||||
jsonparser.cpp
|
||||
)
|
||||
kde4_add_library(jsoninterface STATIC ${JSONINTERFACE_SOURCES})
|
||||
|
||||
macro(KERFUFFLE_UNIT_TESTS)
|
||||
foreach(_testname ${ARGN})
|
||||
kde4_add_unit_test(${_testname} NOGUI ${_testname}.cpp)
|
||||
target_link_libraries(${_testname} jsoninterface kerfuffle ${KDE4_KDEUI_LIBS} ${QT_QTTEST_LIBRARY} ${KERFUFFLE_QJSON_LIBRARIES})
|
||||
endforeach(_testname)
|
||||
endmacro(KERFUFFLE_UNIT_TESTS)
|
||||
|
||||
KERFUFFLE_UNIT_TESTS(
|
||||
archivetest
|
||||
jobstest
|
||||
)
|
76
ark/kerfuffle/tests/archivetest.cpp
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2011 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "kerfuffle/archive.h"
|
||||
|
||||
#include <qtest_kde.h>
|
||||
|
||||
class ArchiveTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void testFileName();
|
||||
void testIsPasswordProtected();
|
||||
void testOpenNonExistentFile();
|
||||
};
|
||||
|
||||
QTEST_KDEMAIN_CORE(ArchiveTest)
|
||||
|
||||
void ArchiveTest::testFileName()
|
||||
{
|
||||
Kerfuffle::Archive *archive = Kerfuffle::Archive::create(QLatin1String("/tmp/foo.tar.gz"), this);
|
||||
|
||||
if (!archive) {
|
||||
QSKIP("There is no plugin to handle tar.gz files. Skipping test.", SkipSingle);
|
||||
}
|
||||
|
||||
QCOMPARE(archive->fileName(), QLatin1String("/tmp/foo.tar.gz"));
|
||||
}
|
||||
|
||||
void ArchiveTest::testIsPasswordProtected()
|
||||
{
|
||||
Kerfuffle::Archive *archive;
|
||||
|
||||
archive = Kerfuffle::Archive::create(QLatin1String(KDESRCDIR "data/archivetest_encrypted.zip"), this);
|
||||
if (!archive) {
|
||||
QSKIP("There is no plugin to handle zip files. Skipping test.", SkipSingle);
|
||||
}
|
||||
|
||||
QVERIFY(archive->isPasswordProtected());
|
||||
|
||||
archive->deleteLater();
|
||||
|
||||
archive = Kerfuffle::Archive::create(QLatin1String(KDESRCDIR "data/archivetest_unencrypted.zip"), this);
|
||||
|
||||
QVERIFY(!archive->isPasswordProtected());
|
||||
}
|
||||
|
||||
void ArchiveTest::testOpenNonExistentFile()
|
||||
{
|
||||
QSKIP("How should we deal with files that do not exist? Should factory() return NULL?", SkipSingle);
|
||||
}
|
||||
|
||||
#include "archivetest.moc"
|
20
ark/kerfuffle/tests/data/archive-deepsinglehierarchy.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
[
|
||||
{
|
||||
"FileName": "aDir/",
|
||||
"IsDirectory": true
|
||||
},
|
||||
{
|
||||
"FileName": "aDir/b.txt"
|
||||
},
|
||||
{
|
||||
"FileName": "aDir/aDirInside/",
|
||||
"IsDirectory": true
|
||||
},
|
||||
{
|
||||
"FileName": "aDir/aDirInside/anotherDir/",
|
||||
"IsDirectory": true
|
||||
},
|
||||
{
|
||||
"FileName": "aDir/aDirInside/anotherDir/file.txt"
|
||||
}
|
||||
]
|
16
ark/kerfuffle/tests/data/archive-multiplefolders.json
Normal file
|
@ -0,0 +1,16 @@
|
|||
[
|
||||
{
|
||||
"FileName": "aDir/",
|
||||
"IsDirectory": true
|
||||
},
|
||||
{
|
||||
"FileName": "aDir/b.txt"
|
||||
},
|
||||
{
|
||||
"FileName": "anotherDir/",
|
||||
"IsDirectory": true
|
||||
},
|
||||
{
|
||||
"FileName": "anotherDir/file.txt"
|
||||
}
|
||||
]
|
8
ark/kerfuffle/tests/data/archive-nodir-manyfiles.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
[
|
||||
{
|
||||
"FileName": "a.txt"
|
||||
},
|
||||
{
|
||||
"FileName": "file.txt"
|
||||
}
|
||||
]
|
9
ark/kerfuffle/tests/data/archive-onetopfolder.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
[
|
||||
{
|
||||
"FileName": "aDir/",
|
||||
"IsDirectory": true
|
||||
},
|
||||
{
|
||||
"FileName": "aDir/b.txt"
|
||||
}
|
||||
]
|
13
ark/kerfuffle/tests/data/archive-password.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
[
|
||||
{
|
||||
"FileName": "foo.txt",
|
||||
"IsPasswordProtected": true
|
||||
},
|
||||
{
|
||||
"FileName": "bar.txt"
|
||||
},
|
||||
{
|
||||
"FileName": "aDirectory/",
|
||||
"IsDirectory": true
|
||||
}
|
||||
]
|
5
ark/kerfuffle/tests/data/archive-singlefile.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
[
|
||||
{
|
||||
"FileName": "a.txt"
|
||||
}
|
||||
]
|
16
ark/kerfuffle/tests/data/archive-unorderedsinglefolder.json
Normal file
|
@ -0,0 +1,16 @@
|
|||
[
|
||||
{
|
||||
"FileName": "aDir/anotherDir/bar.txt"
|
||||
},
|
||||
{
|
||||
"FileName": "aDir/foo.txt"
|
||||
},
|
||||
{
|
||||
"FileName": "aDir/anotherDir/",
|
||||
"IsDirectory": true
|
||||
},
|
||||
{
|
||||
"FileName": "aDir/",
|
||||
"IsDirectory": true
|
||||
}
|
||||
]
|
15
ark/kerfuffle/tests/data/archive001.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
[
|
||||
{
|
||||
"FileName": "a.txt"
|
||||
},
|
||||
{
|
||||
"FileName": "aDir/",
|
||||
"IsDirectory": true
|
||||
},
|
||||
{
|
||||
"FileName": "aDir/b.txt"
|
||||
},
|
||||
{
|
||||
"FileName": "c.txt"
|
||||
}
|
||||
]
|
18
ark/kerfuffle/tests/data/archive002.json
Normal file
|
@ -0,0 +1,18 @@
|
|||
[
|
||||
{
|
||||
"FileName": "a.txt",
|
||||
"Size": 5
|
||||
},
|
||||
{
|
||||
"FileName": "aDir/",
|
||||
"IsDirectory": true
|
||||
},
|
||||
{
|
||||
"FileName": "aDir/b.txt",
|
||||
"Size": 954
|
||||
},
|
||||
{
|
||||
"FileName": "c.txt",
|
||||
"Size": 45000
|
||||
}
|
||||
]
|
BIN
ark/kerfuffle/tests/data/archivetest_encrypted.zip
Normal file
BIN
ark/kerfuffle/tests/data/archivetest_unencrypted.zip
Normal file
BIN
ark/kerfuffle/tests/data/simplearchive.tar.gz
Normal file
366
ark/kerfuffle/tests/jobstest.cpp
Normal file
|
@ -0,0 +1,366 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2011 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "kerfuffle/jobs.h"
|
||||
|
||||
#include "jsonarchiveinterface.h"
|
||||
|
||||
#include <kdebug.h>
|
||||
#include <kglobal.h>
|
||||
#include <qtest_kde.h>
|
||||
|
||||
#include <qeventloop.h>
|
||||
#include <qsignalspy.h>
|
||||
|
||||
using Kerfuffle::ArchiveEntry;
|
||||
|
||||
class JobsTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
JobsTest();
|
||||
|
||||
protected Q_SLOTS:
|
||||
void init();
|
||||
|
||||
void slotNewEntry(const ArchiveEntry& entry);
|
||||
|
||||
private Q_SLOTS:
|
||||
// ListJob-related tests
|
||||
void testExtractedFilesSize();
|
||||
void testIsPasswordProtected();
|
||||
void testIsSingleFolderArchive();
|
||||
void testListEntries();
|
||||
|
||||
// ExtractJob-related tests
|
||||
void testExtractJobAccessors();
|
||||
|
||||
// DeleteJob-related tests
|
||||
void testRemoveEntry();
|
||||
|
||||
// AddJob-related tests
|
||||
void testAddEntry();
|
||||
|
||||
private:
|
||||
JSONArchiveInterface *createArchiveInterface(const QString& filePath);
|
||||
QList<Kerfuffle::ArchiveEntry> listEntries(JSONArchiveInterface *iface);
|
||||
void startAndWaitForResult(KJob *job);
|
||||
|
||||
QList<Kerfuffle::ArchiveEntry> m_entries;
|
||||
QEventLoop m_eventLoop;
|
||||
};
|
||||
|
||||
QTEST_KDEMAIN_CORE(JobsTest)
|
||||
|
||||
JobsTest::JobsTest()
|
||||
: QObject(0)
|
||||
, m_eventLoop(this)
|
||||
{
|
||||
// Hackish way to make sure the i18n stuff
|
||||
// is called from the main thread
|
||||
KGlobal::locale();
|
||||
|
||||
qRegisterMetaType<ArchiveEntry>("ArchiveEntry");
|
||||
}
|
||||
|
||||
void JobsTest::init()
|
||||
{
|
||||
m_entries.clear();
|
||||
}
|
||||
|
||||
JSONArchiveInterface *JobsTest::createArchiveInterface(const QString& filePath)
|
||||
{
|
||||
QVariantList args;
|
||||
args.append(filePath);
|
||||
|
||||
JSONArchiveInterface *iface = new JSONArchiveInterface(this, args);
|
||||
if (!iface->open()) {
|
||||
kDebug() << "Could not open" << filePath;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return iface;
|
||||
}
|
||||
|
||||
void JobsTest::startAndWaitForResult(KJob *job)
|
||||
{
|
||||
connect(job, SIGNAL(result(KJob*)), &m_eventLoop, SLOT(quit()));
|
||||
job->start();
|
||||
m_eventLoop.exec();
|
||||
}
|
||||
|
||||
void JobsTest::testExtractedFilesSize()
|
||||
{
|
||||
Kerfuffle::ListJob *listJob;
|
||||
|
||||
JSONArchiveInterface *noSizeIface =
|
||||
createArchiveInterface(QLatin1String(KDESRCDIR "data/archive001.json"));
|
||||
JSONArchiveInterface *sizeIface =
|
||||
createArchiveInterface(QLatin1String(KDESRCDIR "data/archive002.json"));
|
||||
|
||||
listJob = new Kerfuffle::ListJob(noSizeIface, this);
|
||||
listJob->setAutoDelete(false);
|
||||
startAndWaitForResult(listJob);
|
||||
|
||||
QCOMPARE(listJob->extractedFilesSize(), 0LL);
|
||||
|
||||
listJob = new Kerfuffle::ListJob(sizeIface, this);
|
||||
listJob->setAutoDelete(false);
|
||||
startAndWaitForResult(listJob);
|
||||
|
||||
QCOMPARE(listJob->extractedFilesSize(), 45959LL);
|
||||
|
||||
noSizeIface->deleteLater();
|
||||
sizeIface->deleteLater();
|
||||
}
|
||||
|
||||
void JobsTest::testIsPasswordProtected()
|
||||
{
|
||||
Kerfuffle::ListJob *listJob;
|
||||
|
||||
JSONArchiveInterface *noPasswordIface =
|
||||
createArchiveInterface(QLatin1String(KDESRCDIR "data/archive002.json"));
|
||||
JSONArchiveInterface *passwordIface =
|
||||
createArchiveInterface(QLatin1String(KDESRCDIR "data/archive-password.json"));
|
||||
|
||||
listJob = new Kerfuffle::ListJob(noPasswordIface, this);
|
||||
listJob->setAutoDelete(false);
|
||||
startAndWaitForResult(listJob);
|
||||
|
||||
QVERIFY(!listJob->isPasswordProtected());
|
||||
|
||||
listJob = new Kerfuffle::ListJob(passwordIface, this);
|
||||
listJob->setAutoDelete(false);
|
||||
startAndWaitForResult(listJob);
|
||||
|
||||
QVERIFY(listJob->isPasswordProtected());
|
||||
|
||||
noPasswordIface->deleteLater();
|
||||
passwordIface->deleteLater();
|
||||
}
|
||||
|
||||
void JobsTest::testIsSingleFolderArchive()
|
||||
{
|
||||
JSONArchiveInterface *iface =
|
||||
createArchiveInterface(QLatin1String(KDESRCDIR "data/archive001.json"));
|
||||
|
||||
Kerfuffle::ListJob *listJob = new Kerfuffle::ListJob(iface, this);
|
||||
listJob->setAutoDelete(false);
|
||||
startAndWaitForResult(listJob);
|
||||
QVERIFY(!listJob->isSingleFolderArchive());
|
||||
QCOMPARE(listJob->subfolderName(), QString());
|
||||
iface->deleteLater();
|
||||
|
||||
iface = createArchiveInterface(QLatin1String(KDESRCDIR "data/archive-singlefile.json"));
|
||||
listJob = new Kerfuffle::ListJob(iface, this);
|
||||
listJob->setAutoDelete(false);
|
||||
startAndWaitForResult(listJob);
|
||||
QVERIFY(listJob->isSingleFolderArchive());
|
||||
QCOMPARE(listJob->subfolderName(), QLatin1String("a.txt"));
|
||||
iface->deleteLater();
|
||||
|
||||
iface = createArchiveInterface(QLatin1String(KDESRCDIR "data/archive-onetopfolder.json"));
|
||||
listJob = new Kerfuffle::ListJob(iface, this);
|
||||
listJob->setAutoDelete(false);
|
||||
startAndWaitForResult(listJob);
|
||||
QVERIFY(listJob->isSingleFolderArchive());
|
||||
QCOMPARE(listJob->subfolderName(), QLatin1String("aDir"));
|
||||
iface->deleteLater();
|
||||
|
||||
iface = createArchiveInterface
|
||||
(QLatin1String(KDESRCDIR "data/archive-multiplefolders.json"));
|
||||
listJob = new Kerfuffle::ListJob(iface, this);
|
||||
listJob->setAutoDelete(false);
|
||||
startAndWaitForResult(listJob);
|
||||
QVERIFY(!listJob->isSingleFolderArchive());
|
||||
QCOMPARE(listJob->subfolderName(), QString());
|
||||
iface->deleteLater();
|
||||
|
||||
iface = createArchiveInterface
|
||||
(QLatin1String(KDESRCDIR "data/archive-nodir-manyfiles.json"));
|
||||
listJob = new Kerfuffle::ListJob(iface, this);
|
||||
listJob->setAutoDelete(false);
|
||||
startAndWaitForResult(listJob);
|
||||
QVERIFY(!listJob->isSingleFolderArchive());
|
||||
QCOMPARE(listJob->subfolderName(), QString());
|
||||
iface->deleteLater();
|
||||
|
||||
iface = createArchiveInterface
|
||||
(QLatin1String(KDESRCDIR "data/archive-deepsinglehierarchy.json"));
|
||||
listJob = new Kerfuffle::ListJob(iface, this);
|
||||
listJob->setAutoDelete(false);
|
||||
startAndWaitForResult(listJob);
|
||||
QVERIFY(listJob->isSingleFolderArchive());
|
||||
QCOMPARE(listJob->subfolderName(), QLatin1String("aDir"));
|
||||
iface->deleteLater();
|
||||
|
||||
iface = createArchiveInterface
|
||||
(QLatin1String(KDESRCDIR "data/archive-unorderedsinglefolder.json"));
|
||||
listJob = new Kerfuffle::ListJob(iface, this);
|
||||
listJob->setAutoDelete(false);
|
||||
startAndWaitForResult(listJob);
|
||||
QVERIFY(listJob->isSingleFolderArchive());
|
||||
QCOMPARE(listJob->subfolderName(), QLatin1String("aDir"));
|
||||
iface->deleteLater();
|
||||
}
|
||||
|
||||
void JobsTest::testListEntries()
|
||||
{
|
||||
JSONArchiveInterface *iface =
|
||||
createArchiveInterface(QLatin1String(KDESRCDIR "data/archive001.json"));
|
||||
|
||||
QList<Kerfuffle::ArchiveEntry> archiveEntries(listEntries(iface));
|
||||
|
||||
QStringList entries;
|
||||
entries.append(QLatin1String("a.txt"));
|
||||
entries.append(QLatin1String("aDir/"));
|
||||
entries.append(QLatin1String("aDir/b.txt"));
|
||||
entries.append(QLatin1String("c.txt"));
|
||||
|
||||
QCOMPARE(entries.count(), archiveEntries.count());
|
||||
|
||||
for (int i = 0; i < entries.count(); ++i) {
|
||||
Kerfuffle::ArchiveEntry e(archiveEntries.at(i));
|
||||
|
||||
QCOMPARE(entries[i], e[Kerfuffle::FileName].toString());
|
||||
}
|
||||
|
||||
iface->deleteLater();
|
||||
}
|
||||
|
||||
void JobsTest::slotNewEntry(const ArchiveEntry& entry)
|
||||
{
|
||||
m_entries.append(entry);
|
||||
}
|
||||
|
||||
QList<Kerfuffle::ArchiveEntry> JobsTest::listEntries(JSONArchiveInterface *iface)
|
||||
{
|
||||
m_entries.clear();
|
||||
|
||||
Kerfuffle::ListJob *listJob = new Kerfuffle::ListJob(iface, this);
|
||||
connect(listJob, SIGNAL(newEntry(ArchiveEntry)),
|
||||
SLOT(slotNewEntry(ArchiveEntry)));
|
||||
|
||||
startAndWaitForResult(listJob);
|
||||
|
||||
return m_entries;
|
||||
}
|
||||
|
||||
void JobsTest::testExtractJobAccessors()
|
||||
{
|
||||
JSONArchiveInterface *iface = createArchiveInterface(QLatin1String(KDESRCDIR "data/archive001.json"));
|
||||
Kerfuffle::ExtractJob *job =
|
||||
new Kerfuffle::ExtractJob(QVariantList(), QLatin1String("/tmp/some-dir"),
|
||||
Kerfuffle::ExtractionOptions(), iface, this);
|
||||
Kerfuffle::ExtractionOptions defaultOptions;
|
||||
defaultOptions[QLatin1String("PreservePaths")] = false;
|
||||
|
||||
QCOMPARE(job->destinationDirectory(), QLatin1String("/tmp/some-dir"));
|
||||
QCOMPARE(job->extractionOptions(), defaultOptions);
|
||||
|
||||
job->setAutoDelete(false);
|
||||
startAndWaitForResult(job);
|
||||
|
||||
QCOMPARE(job->destinationDirectory(), QLatin1String("/tmp/some-dir"));
|
||||
QCOMPARE(job->extractionOptions(), defaultOptions);
|
||||
|
||||
Kerfuffle::ExtractionOptions options;
|
||||
options[QLatin1String("PreservePaths")] = true;
|
||||
options[QLatin1String("foo")] = QLatin1String("bar");
|
||||
options[QLatin1String("pi")] = 3.14f;
|
||||
|
||||
job = new Kerfuffle::ExtractJob(QVariantList(), QLatin1String("/root"),
|
||||
options, iface, this);
|
||||
|
||||
QCOMPARE(job->destinationDirectory(), QLatin1String("/root"));
|
||||
QCOMPARE(job->extractionOptions(), options);
|
||||
|
||||
job->setAutoDelete(false);
|
||||
startAndWaitForResult(job);
|
||||
|
||||
QCOMPARE(job->destinationDirectory(), QLatin1String("/root"));
|
||||
QCOMPARE(job->extractionOptions(), options);
|
||||
}
|
||||
|
||||
void JobsTest::testRemoveEntry()
|
||||
{
|
||||
QVariantList filesToDelete;
|
||||
JSONArchiveInterface *iface;
|
||||
Kerfuffle::DeleteJob *deleteJob;
|
||||
QStringList expectedEntries;
|
||||
|
||||
filesToDelete.append(QLatin1String("c.txt"));
|
||||
iface = createArchiveInterface(QLatin1String(KDESRCDIR "data/archive001.json"));
|
||||
deleteJob = new Kerfuffle::DeleteJob(filesToDelete, iface, this);
|
||||
startAndWaitForResult(deleteJob);
|
||||
QList<Kerfuffle::ArchiveEntry> archiveEntries(listEntries(iface));
|
||||
expectedEntries.append(QLatin1String("a.txt"));
|
||||
expectedEntries.append(QLatin1String("aDir/"));
|
||||
expectedEntries.append(QLatin1String("aDir/b.txt"));
|
||||
QCOMPARE(archiveEntries.count(), expectedEntries.count());
|
||||
for (int i = 0; i < expectedEntries.count(); ++i) {
|
||||
const Kerfuffle::ArchiveEntry e(archiveEntries.at(i));
|
||||
QCOMPARE(expectedEntries[i], e[Kerfuffle::FileName].toString());
|
||||
}
|
||||
iface->deleteLater();
|
||||
|
||||
// TODO: test for errors
|
||||
}
|
||||
|
||||
void JobsTest::testAddEntry()
|
||||
{
|
||||
JSONArchiveInterface *iface = createArchiveInterface(QLatin1String(KDESRCDIR "data/archive001.json"));
|
||||
|
||||
QList<Kerfuffle::ArchiveEntry> archiveEntries = listEntries(iface);
|
||||
QCOMPARE(archiveEntries.count(), 4);
|
||||
|
||||
QStringList newEntries = QStringList() << QLatin1String("foo");
|
||||
|
||||
Kerfuffle::AddJob *addJob =
|
||||
new Kerfuffle::AddJob(newEntries, Kerfuffle::CompressionOptions(), iface, this);
|
||||
startAndWaitForResult(addJob);
|
||||
|
||||
archiveEntries = listEntries(iface);
|
||||
QCOMPARE(archiveEntries.count(), 5);
|
||||
|
||||
addJob = new Kerfuffle::AddJob(newEntries, Kerfuffle::CompressionOptions(), iface, this);
|
||||
startAndWaitForResult(addJob);
|
||||
|
||||
archiveEntries = listEntries(iface);
|
||||
QCOMPARE(archiveEntries.count(), 5);
|
||||
|
||||
newEntries = QStringList() << QLatin1String("bar") << QLatin1String("aDir/test.txt");
|
||||
|
||||
addJob = new Kerfuffle::AddJob(newEntries, Kerfuffle::CompressionOptions(), iface, this);
|
||||
startAndWaitForResult(addJob);
|
||||
|
||||
archiveEntries = listEntries(iface);
|
||||
QCOMPARE(archiveEntries.count(), 7);
|
||||
|
||||
iface->deleteLater();
|
||||
}
|
||||
|
||||
#include "jobstest.moc"
|
109
ark/kerfuffle/tests/jsonarchiveinterface.cpp
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2011 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "jsonarchiveinterface.h"
|
||||
|
||||
#include <kdebug.h>
|
||||
#include <qjson/parser.h>
|
||||
|
||||
#include <qfile.h>
|
||||
|
||||
JSONArchiveInterface::JSONArchiveInterface(QObject *parent, const QVariantList& args)
|
||||
: Kerfuffle::ReadWriteArchiveInterface(parent, args)
|
||||
{
|
||||
}
|
||||
|
||||
JSONArchiveInterface::~JSONArchiveInterface()
|
||||
{
|
||||
}
|
||||
|
||||
bool JSONArchiveInterface::list()
|
||||
{
|
||||
JSONParser::JSONArchive::const_iterator it = m_archive.constBegin();
|
||||
for (; it != m_archive.constEnd(); ++it) {
|
||||
emit entry(*it);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JSONArchiveInterface::open()
|
||||
{
|
||||
QFile file(filename());
|
||||
|
||||
if (!file.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_archive = JSONParser::parse(&file);
|
||||
|
||||
return !m_archive.isEmpty();
|
||||
}
|
||||
|
||||
bool JSONArchiveInterface::addFiles(const QStringList& files, const Kerfuffle::CompressionOptions& options)
|
||||
{
|
||||
Q_UNUSED(options)
|
||||
|
||||
foreach (const QString& file, files) {
|
||||
if (m_archive.contains(file)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Kerfuffle::ArchiveEntry e;
|
||||
e[Kerfuffle::FileName] = file;
|
||||
|
||||
m_archive[file] = e;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JSONArchiveInterface::copyFiles(const QList<QVariant>& files, const QString& destinationDirectory, Kerfuffle::ExtractionOptions options)
|
||||
{
|
||||
Q_UNUSED(files)
|
||||
Q_UNUSED(destinationDirectory)
|
||||
Q_UNUSED(options)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JSONArchiveInterface::deleteFiles(const QList<QVariant>& files)
|
||||
{
|
||||
foreach (const QVariant& file, files) {
|
||||
const QString fileName = file.toString();
|
||||
if (m_archive.contains(fileName)) {
|
||||
m_archive.remove(fileName);
|
||||
emit entryRemoved(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#include "jsonarchiveinterface.moc"
|
67
ark/kerfuffle/tests/jsonarchiveinterface.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2011 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef JSONARCHIVEINTERFACE_H
|
||||
#define JSONARCHIVEINTERFACE_H
|
||||
|
||||
#include "jsonparser.h"
|
||||
|
||||
#include "kerfuffle/archive.h"
|
||||
#include "kerfuffle/archiveinterface.h"
|
||||
|
||||
/**
|
||||
* A dummy archive interface used by our test cases.
|
||||
*
|
||||
* It reads a JSON file which defines the contents of the archive.
|
||||
* For the file format description, see the documentation for @c JSONParser.
|
||||
*
|
||||
* The file's content is read to memory when open() is called and the archive
|
||||
* is then closed. This means that this class never changes the file's content
|
||||
* on disk, and entry addition or deletion do not change the original file.
|
||||
*
|
||||
* @sa JSONParser
|
||||
*
|
||||
* @author Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*/
|
||||
class JSONArchiveInterface : public Kerfuffle::ReadWriteArchiveInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit JSONArchiveInterface(QObject *parent, const QVariantList& args);
|
||||
virtual ~JSONArchiveInterface();
|
||||
|
||||
virtual bool list();
|
||||
virtual bool open();
|
||||
|
||||
virtual bool addFiles(const QStringList& files, const Kerfuffle::CompressionOptions& options);
|
||||
virtual bool copyFiles(const QList<QVariant>& files, const QString& destinationDirectory, Kerfuffle::ExtractionOptions options);
|
||||
virtual bool deleteFiles(const QList<QVariant>& files);
|
||||
|
||||
private:
|
||||
JSONParser::JSONArchive m_archive;
|
||||
};
|
||||
|
||||
#endif
|
133
ark/kerfuffle/tests/jsonparser.cpp
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "jsonparser.h"
|
||||
|
||||
#include "kerfuffle/archiveinterface.h"
|
||||
|
||||
#include <KDE/KDebug>
|
||||
|
||||
#include <QtCore/QLatin1String>
|
||||
|
||||
#include <qjson/parser.h>
|
||||
|
||||
typedef QMap<QString, Kerfuffle::EntryMetaDataType> ArchiveProperties;
|
||||
|
||||
static ArchiveProperties archiveProperties()
|
||||
{
|
||||
static ArchiveProperties properties;
|
||||
|
||||
if (!properties.isEmpty()) {
|
||||
return properties;
|
||||
}
|
||||
|
||||
properties[QLatin1String("FileName")] = Kerfuffle::FileName;
|
||||
properties[QLatin1String("InternalID")] = Kerfuffle::InternalID;
|
||||
properties[QLatin1String("Permissions")] = Kerfuffle::Permissions;
|
||||
properties[QLatin1String("Owner")] = Kerfuffle::Owner;
|
||||
properties[QLatin1String("Group")] = Kerfuffle::Group;
|
||||
properties[QLatin1String("Size")] = Kerfuffle::Size;
|
||||
properties[QLatin1String("CompressedSize")] = Kerfuffle::CompressedSize;
|
||||
properties[QLatin1String("Link")] = Kerfuffle::Link;
|
||||
properties[QLatin1String("Ratio")] = Kerfuffle::Ratio;
|
||||
properties[QLatin1String("CRC")] = Kerfuffle::CRC;
|
||||
properties[QLatin1String("Method")] = Kerfuffle::Method;
|
||||
properties[QLatin1String("Version")] = Kerfuffle::Version;
|
||||
properties[QLatin1String("Timestamp")] = Kerfuffle::Timestamp;
|
||||
properties[QLatin1String("IsDirectory")] = Kerfuffle::IsDirectory;
|
||||
properties[QLatin1String("Comment")] = Kerfuffle::Comment;
|
||||
properties[QLatin1String("IsPasswordProtected")] = Kerfuffle::IsPasswordProtected;
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
JSONParser::JSONParser()
|
||||
{
|
||||
}
|
||||
|
||||
JSONParser::~JSONParser()
|
||||
{
|
||||
}
|
||||
|
||||
JSONParser::JSONArchive JSONParser::parse(const QString &json)
|
||||
{
|
||||
bool ok;
|
||||
QJson::Parser parser;
|
||||
|
||||
const QVariant result = parser.parse(json.toUtf8(), &ok);
|
||||
|
||||
if (!ok) {
|
||||
kDebug() << "Line" << parser.errorLine() << ":" << parser.errorString();
|
||||
return JSONParser::JSONArchive();
|
||||
}
|
||||
|
||||
return createJSONArchive(result);
|
||||
}
|
||||
|
||||
JSONParser::JSONArchive JSONParser::parse(QIODevice *json)
|
||||
{
|
||||
bool ok;
|
||||
QJson::Parser parser;
|
||||
|
||||
const QVariant result = parser.parse(json, &ok);
|
||||
|
||||
if (!ok) {
|
||||
kDebug() << "Line" << parser.errorLine() << ":" << parser.errorString();
|
||||
return JSONParser::JSONArchive();
|
||||
}
|
||||
|
||||
return createJSONArchive(result);
|
||||
}
|
||||
|
||||
JSONParser::JSONArchive JSONParser::createJSONArchive(const QVariant &json)
|
||||
{
|
||||
static const ArchiveProperties properties = archiveProperties();
|
||||
|
||||
JSONParser::JSONArchive archive;
|
||||
|
||||
foreach (const QVariant &entry, json.toList()) {
|
||||
const QVariantMap entryMap = entry.toMap();
|
||||
|
||||
if (!entryMap.contains(QLatin1String("FileName"))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Kerfuffle::ArchiveEntry archiveEntry;
|
||||
|
||||
QVariantMap::const_iterator entryIterator = entryMap.constBegin();
|
||||
for (; entryIterator != entryMap.constEnd(); ++entryIterator) {
|
||||
if (properties.contains(entryIterator.key())) {
|
||||
archiveEntry[properties[entryIterator.key()]] = entryIterator.value();
|
||||
} else {
|
||||
kDebug() << entryIterator.key() << "is not a valid entry key";
|
||||
}
|
||||
}
|
||||
|
||||
const QString fileName = entryMap[QLatin1String("FileName")].toString();
|
||||
archive[fileName] = archiveEntry;
|
||||
}
|
||||
|
||||
return archive;
|
||||
}
|
82
ark/kerfuffle/tests/jsonparser.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef JSONPARSER_H
|
||||
#define JSONPARSER_H
|
||||
|
||||
#include "kerfuffle/archive.h"
|
||||
|
||||
#include <QtCore/QIODevice>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QString>
|
||||
|
||||
/**
|
||||
* Simple parser which reads JSON files and creates @c ArchiveEntry objects
|
||||
* from it.
|
||||
*
|
||||
* The JSON file is expected to follow a specific format that describes an
|
||||
* archive read by Kerfuffle.
|
||||
*
|
||||
* The format consists of a list of dictionaries whose keys are values from the
|
||||
* EntryMetaDataType enum. The only required key for each entry is FileName;
|
||||
* other values which are omitted for each entry are assumed to be 0 or false.
|
||||
*
|
||||
* Example file:
|
||||
* @code
|
||||
* [
|
||||
* { "FileName": "foo", "IsPasswordProtected": true },
|
||||
* { "FileName": "aDir/", "IsDirectory": true }
|
||||
* ]
|
||||
* @endcode
|
||||
*
|
||||
* @author Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*/
|
||||
class JSONParser
|
||||
{
|
||||
public:
|
||||
typedef QMap<QString, Kerfuffle::ArchiveEntry> JSONArchive;
|
||||
|
||||
~JSONParser();
|
||||
|
||||
static JSONArchive parse(const QString &json);
|
||||
static JSONArchive parse(QIODevice *json);
|
||||
|
||||
private:
|
||||
JSONParser();
|
||||
|
||||
/**
|
||||
* Parses each entry in the QVariant obtained from parsing a JSON file and
|
||||
* creates a @c JSONArchive from them.
|
||||
*
|
||||
* If an entry does not have a "FileName" key, it is ignored. Keys which do
|
||||
* not correspond to a value in the EntryMetaDataType enum are ignored.
|
||||
*
|
||||
* @return A new @c JSONArchive corresponding to the parsed JSON file. If a
|
||||
* parsing error occurs, it is empty.
|
||||
*/
|
||||
static JSONArchive createJSONArchive(const QVariant &json);
|
||||
};
|
||||
|
||||
#endif // JSONPARSER_H
|
30
ark/part/CMakeLists.txt
Normal file
|
@ -0,0 +1,30 @@
|
|||
set(arkpart_PART_SRCS
|
||||
part.cpp
|
||||
infopanel.cpp
|
||||
arkviewer.cpp
|
||||
archivemodel.cpp
|
||||
archiveview.cpp
|
||||
jobtracker.cpp
|
||||
)
|
||||
|
||||
qt4_add_dbus_adaptor(arkpart_PART_SRCS dnddbusinterface.xml part.h Ark::Part)
|
||||
|
||||
kde4_add_ui_files(arkpart_PART_SRCS infopanel.ui )
|
||||
kde4_add_ui_files(arkpart_PART_SRCS jobtracker.ui )
|
||||
|
||||
kde4_add_plugin(arkpart ${arkpart_PART_SRCS})
|
||||
|
||||
target_link_libraries(arkpart kerfuffle ${KDE4_KFILE_LIBS} ${KDE4_KPARTS_LIBS} ${KDE4_KDEUI_LIBS})
|
||||
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ark_part.desktop.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ark_part.desktop
|
||||
)
|
||||
|
||||
install(TARGETS arkpart DESTINATION ${PLUGIN_INSTALL_DIR})
|
||||
|
||||
|
||||
########### install files ###############
|
||||
|
||||
install( FILES ${CMAKE_CURRENT_BINARY_DIR}/ark_part.desktop DESTINATION ${SERVICES_INSTALL_DIR} )
|
||||
install( FILES ark_part.rc DESTINATION ${DATA_INSTALL_DIR}/ark )
|
986
ark/part/archivemodel.cpp
Normal file
|
@ -0,0 +1,986 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
|
||||
* Copyright (C) 2008-2009 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
* Copyright (C) 2010-2012 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 "archivemodel.h"
|
||||
#include "kerfuffle/archive.h"
|
||||
#include "kerfuffle/jobs.h"
|
||||
|
||||
#include <KDebug>
|
||||
#include <KIconLoader>
|
||||
#include <KLocale>
|
||||
#include <KMimeType>
|
||||
#include <KIO/NetAccess>
|
||||
|
||||
#include <QDir>
|
||||
#include <QFont>
|
||||
#include <QLatin1String>
|
||||
#include <QList>
|
||||
#include <QMimeData>
|
||||
#include <QPersistentModelIndex>
|
||||
#include <QPixmap>
|
||||
#include <QtDBus/QtDBus>
|
||||
|
||||
using namespace Kerfuffle;
|
||||
|
||||
class ArchiveDirNode;
|
||||
|
||||
//used to speed up the loading of large archives
|
||||
static ArchiveNode* s_previousMatch = NULL;
|
||||
K_GLOBAL_STATIC(QStringList, s_previousPieces)
|
||||
|
||||
|
||||
// TODO: This class hierarchy needs some love.
|
||||
// Having a parent take a child class as a parameter in the constructor
|
||||
// should trigger one's spider-sense (TM).
|
||||
class ArchiveNode
|
||||
{
|
||||
public:
|
||||
ArchiveNode(ArchiveDirNode *parent, const ArchiveEntry & entry)
|
||||
: m_parent(parent)
|
||||
{
|
||||
setEntry(entry);
|
||||
}
|
||||
|
||||
virtual ~ArchiveNode()
|
||||
{
|
||||
}
|
||||
|
||||
const ArchiveEntry &entry() const
|
||||
{
|
||||
return m_entry;
|
||||
}
|
||||
|
||||
void setEntry(const ArchiveEntry& entry)
|
||||
{
|
||||
m_entry = entry;
|
||||
|
||||
const QStringList pieces = entry[FileName].toString().split(QLatin1Char( '/' ), QString::SkipEmptyParts);
|
||||
m_name = pieces.isEmpty() ? QString() : pieces.last();
|
||||
|
||||
if (entry[IsDirectory].toBool()) {
|
||||
m_icon = KIconLoader::global()->loadMimeTypeIcon(KMimeType::mimeType(QLatin1String("inode/directory"))->iconName(), KIconLoader::Small);
|
||||
} else {
|
||||
const KMimeType::Ptr mimeType = KMimeType::findByPath(m_entry[FileName].toString(), 0, true);
|
||||
m_icon = KIconLoader::global()->loadMimeTypeIcon(mimeType->iconName(), KIconLoader::Small);
|
||||
}
|
||||
}
|
||||
|
||||
ArchiveDirNode *parent() const
|
||||
{
|
||||
return m_parent;
|
||||
}
|
||||
|
||||
int row() const;
|
||||
|
||||
virtual bool isDir() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QPixmap icon() const
|
||||
{
|
||||
return m_icon;
|
||||
}
|
||||
|
||||
QString name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
protected:
|
||||
void setIcon(const QPixmap &icon)
|
||||
{
|
||||
m_icon = icon;
|
||||
}
|
||||
|
||||
private:
|
||||
ArchiveEntry m_entry;
|
||||
QPixmap m_icon;
|
||||
QString m_name;
|
||||
ArchiveDirNode *m_parent;
|
||||
};
|
||||
|
||||
|
||||
class ArchiveDirNode: public ArchiveNode
|
||||
{
|
||||
public:
|
||||
ArchiveDirNode(ArchiveDirNode *parent, const ArchiveEntry & entry)
|
||||
: ArchiveNode(parent, entry)
|
||||
{
|
||||
}
|
||||
|
||||
~ArchiveDirNode()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
QList<ArchiveNode*> entries()
|
||||
{
|
||||
return m_entries;
|
||||
}
|
||||
|
||||
void setEntryAt(int index, ArchiveNode* value)
|
||||
{
|
||||
m_entries[index] = value;
|
||||
}
|
||||
|
||||
void appendEntry(ArchiveNode* entry)
|
||||
{
|
||||
m_entries.append(entry);
|
||||
}
|
||||
|
||||
void removeEntryAt(int index)
|
||||
{
|
||||
delete m_entries.takeAt(index);
|
||||
}
|
||||
|
||||
virtual bool isDir() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
ArchiveNode* find(const QString & name)
|
||||
{
|
||||
foreach(ArchiveNode *node, m_entries) {
|
||||
if (node && (node->name() == name)) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ArchiveNode* findByPath(const QStringList & pieces, int index = 0)
|
||||
{
|
||||
if (index == pieces.count()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ArchiveNode *next = find(pieces.at(index));
|
||||
|
||||
if (index == pieces.count() - 1) {
|
||||
return next;
|
||||
}
|
||||
if (next && next->isDir()) {
|
||||
return static_cast<ArchiveDirNode*>(next)->findByPath(pieces, index + 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void returnDirNodes(QList<ArchiveDirNode*> *store)
|
||||
{
|
||||
foreach(ArchiveNode *node, m_entries) {
|
||||
if (node->isDir()) {
|
||||
store->prepend(static_cast<ArchiveDirNode*>(node));
|
||||
static_cast<ArchiveDirNode*>(node)->returnDirNodes(store);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
qDeleteAll(m_entries);
|
||||
m_entries.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
QList<ArchiveNode*> m_entries;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper functor used by qStableSort.
|
||||
*
|
||||
* It always sorts folders before files.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class ArchiveModelSorter
|
||||
{
|
||||
public:
|
||||
ArchiveModelSorter(int column, Qt::SortOrder order)
|
||||
: m_sortColumn(column)
|
||||
, m_sortOrder(order)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ArchiveModelSorter()
|
||||
{
|
||||
}
|
||||
|
||||
inline bool operator()(const QPair<ArchiveNode*, int> &left, const QPair<ArchiveNode*, int> &right) const
|
||||
{
|
||||
if (m_sortOrder == Qt::AscendingOrder) {
|
||||
return lessThan(left, right);
|
||||
} else {
|
||||
return !lessThan(left, right);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
bool lessThan(const QPair<ArchiveNode*, int> &left, const QPair<ArchiveNode*, int> &right) const
|
||||
{
|
||||
const ArchiveNode * const leftNode = left.first;
|
||||
const ArchiveNode * const rightNode = right.first;
|
||||
|
||||
// #234373: sort folders before files
|
||||
if ((leftNode->isDir()) && (!rightNode->isDir())) {
|
||||
return (m_sortOrder == Qt::AscendingOrder);
|
||||
} else if ((!leftNode->isDir()) && (rightNode->isDir())) {
|
||||
return !(m_sortOrder == Qt::AscendingOrder);
|
||||
}
|
||||
|
||||
const QVariant &leftEntry = leftNode->entry()[m_sortColumn];
|
||||
const QVariant &rightEntry = rightNode->entry()[m_sortColumn];
|
||||
|
||||
switch (m_sortColumn) {
|
||||
case FileName:
|
||||
return leftNode->name() < rightNode->name();
|
||||
case Size:
|
||||
case CompressedSize:
|
||||
return leftEntry.toInt() < rightEntry.toInt();
|
||||
default:
|
||||
return leftEntry.toString() < rightEntry.toString();
|
||||
}
|
||||
|
||||
// We should not get here.
|
||||
Q_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_sortColumn;
|
||||
Qt::SortOrder m_sortOrder;
|
||||
};
|
||||
|
||||
int ArchiveNode::row() const
|
||||
{
|
||||
if (parent()) {
|
||||
return parent()->entries().indexOf(const_cast<ArchiveNode*>(this));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ArchiveModel::ArchiveModel(const QString &dbusPathName, QObject *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
, m_rootNode(new ArchiveDirNode(0, ArchiveEntry()))
|
||||
, m_dbusPathName(dbusPathName)
|
||||
{
|
||||
}
|
||||
|
||||
ArchiveModel::~ArchiveModel()
|
||||
{
|
||||
delete m_rootNode;
|
||||
m_rootNode = 0;
|
||||
}
|
||||
|
||||
QVariant ArchiveModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.isValid()) {
|
||||
ArchiveNode *node = static_cast<ArchiveNode*>(index.internalPointer());
|
||||
switch (role) {
|
||||
case Qt::DisplayRole: {
|
||||
//TODO: complete the columns
|
||||
int columnId = m_showColumns.at(index.column());
|
||||
switch (columnId) {
|
||||
case FileName:
|
||||
return node->name();
|
||||
case Size:
|
||||
if (node->isDir()) {
|
||||
int dirs;
|
||||
int files;
|
||||
const int children = childCount(index, dirs, files);
|
||||
return KIO::itemsSummaryString(children, files, dirs, 0, false);
|
||||
} else if (node->entry().contains(Link)) {
|
||||
return QVariant();
|
||||
} else {
|
||||
return KIO::convertSize(node->entry()[ Size ].toULongLong());
|
||||
}
|
||||
case CompressedSize:
|
||||
if (node->isDir() || node->entry().contains(Link)) {
|
||||
return QVariant();
|
||||
} else {
|
||||
qulonglong compressedSize = node->entry()[ CompressedSize ].toULongLong();
|
||||
if (compressedSize != 0) {
|
||||
return KIO::convertSize(compressedSize);
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
case Ratio: // TODO: Use node->entry()[Ratio] when available
|
||||
if (node->isDir() || node->entry().contains(Link)) {
|
||||
return QVariant();
|
||||
} else {
|
||||
qulonglong compressedSize = node->entry()[ CompressedSize ].toULongLong();
|
||||
qulonglong size = node->entry()[ Size ].toULongLong();
|
||||
if (compressedSize == 0 || size == 0) {
|
||||
return QVariant();
|
||||
} else {
|
||||
int ratio = int(100 * ((double)size - compressedSize) / size);
|
||||
return QString(QString::number(ratio) + QLatin1String( " %" ));
|
||||
}
|
||||
}
|
||||
|
||||
case Timestamp: {
|
||||
const QDateTime timeStamp = node->entry().value(Timestamp).toDateTime();
|
||||
return KGlobal::locale()->formatDateTime(timeStamp);
|
||||
}
|
||||
|
||||
default:
|
||||
return node->entry().value(columnId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Qt::DecorationRole:
|
||||
if (index.column() == 0) {
|
||||
return node->icon();
|
||||
}
|
||||
return QVariant();
|
||||
case Qt::FontRole: {
|
||||
QFont f;
|
||||
f.setItalic(node->entry()[ IsPasswordProtected ].toBool());
|
||||
return f;
|
||||
}
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
Qt::ItemFlags ArchiveModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
Qt::ItemFlags defaultFlags = QAbstractItemModel::flags(index);
|
||||
|
||||
if (index.isValid()) {
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | defaultFlags;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QVariant ArchiveModel::headerData(int section, Qt::Orientation, int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole) {
|
||||
if (section >= m_showColumns.size()) {
|
||||
kDebug() << "WEIRD: showColumns.size = " << m_showColumns.size()
|
||||
<< " and section = " << section;
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int columnId = m_showColumns.at(section);
|
||||
|
||||
switch (columnId) {
|
||||
case FileName:
|
||||
return i18nc("Name of a file inside an archive", "Name");
|
||||
case Size:
|
||||
return i18nc("Uncompressed size of a file inside an archive", "Size");
|
||||
case CompressedSize:
|
||||
return i18nc("Compressed size of a file inside an archive", "Compressed");
|
||||
case Ratio:
|
||||
return i18nc("Compression rate of file", "Rate");
|
||||
case Owner:
|
||||
return i18nc("File's owner username", "Owner");
|
||||
case Group:
|
||||
return i18nc("File's group", "Group");
|
||||
case Permissions:
|
||||
return i18nc("File permissions", "Mode");
|
||||
case CRC:
|
||||
return i18nc("CRC hash code", "CRC");
|
||||
case Method:
|
||||
return i18nc("Compression method", "Method");
|
||||
case Version:
|
||||
//TODO: what exactly is a file version?
|
||||
return i18nc("File version", "Version");
|
||||
case Timestamp:
|
||||
return i18nc("Timestamp", "Date");
|
||||
case Comment:
|
||||
return i18nc("File comment", "Comment");
|
||||
default:
|
||||
return i18nc("Unnamed column", "??");
|
||||
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QModelIndex ArchiveModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (hasIndex(row, column, parent)) {
|
||||
ArchiveDirNode *parentNode = parent.isValid() ? static_cast<ArchiveDirNode*>(parent.internalPointer()) : m_rootNode;
|
||||
|
||||
Q_ASSERT(parentNode->isDir());
|
||||
|
||||
ArchiveNode *item = parentNode->entries().value(row, 0);
|
||||
if (item) {
|
||||
return createIndex(row, column, item);
|
||||
}
|
||||
}
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex ArchiveModel::parent(const QModelIndex &index) const
|
||||
{
|
||||
if (index.isValid()) {
|
||||
ArchiveNode *item = static_cast<ArchiveNode*>(index.internalPointer());
|
||||
Q_ASSERT(item);
|
||||
if (item->parent() && (item->parent() != m_rootNode)) {
|
||||
return createIndex(item->parent()->row(), 0, item->parent());
|
||||
}
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
ArchiveEntry ArchiveModel::entryForIndex(const QModelIndex &index)
|
||||
{
|
||||
if (index.isValid()) {
|
||||
ArchiveNode *item = static_cast<ArchiveNode*>(index.internalPointer());
|
||||
Q_ASSERT(item);
|
||||
return item->entry();
|
||||
}
|
||||
return ArchiveEntry();
|
||||
}
|
||||
|
||||
int ArchiveModel::childCount(const QModelIndex &index, int &dirs, int &files) const
|
||||
{
|
||||
if (index.isValid()) {
|
||||
dirs = files = 0;
|
||||
ArchiveNode *item = static_cast<ArchiveNode*>(index.internalPointer());
|
||||
Q_ASSERT(item);
|
||||
if (item->isDir()) {
|
||||
const QList<ArchiveNode*> entries = static_cast<ArchiveDirNode*>(item)->entries();
|
||||
foreach(const ArchiveNode *node, entries) {
|
||||
if (node->isDir()) {
|
||||
dirs++;
|
||||
} else {
|
||||
files++;
|
||||
}
|
||||
}
|
||||
return entries.count();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ArchiveModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.column() <= 0) {
|
||||
ArchiveNode *parentNode = parent.isValid() ? static_cast<ArchiveNode*>(parent.internalPointer()) : m_rootNode;
|
||||
|
||||
if (parentNode && parentNode->isDir()) {
|
||||
return static_cast<ArchiveDirNode*>(parentNode)->entries().count();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ArchiveModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return m_showColumns.size();
|
||||
if (parent.isValid()) {
|
||||
return static_cast<ArchiveNode*>(parent.internalPointer())->entry().size();
|
||||
}
|
||||
}
|
||||
|
||||
void ArchiveModel::sort(int column, Qt::SortOrder order)
|
||||
{
|
||||
if (m_showColumns.size() <= column) {
|
||||
return;
|
||||
}
|
||||
|
||||
emit layoutAboutToBeChanged();
|
||||
|
||||
QList<ArchiveDirNode*> dirNodes;
|
||||
m_rootNode->returnDirNodes(&dirNodes);
|
||||
dirNodes.append(m_rootNode);
|
||||
|
||||
const ArchiveModelSorter modelSorter(m_showColumns.at(column), order);
|
||||
|
||||
foreach(ArchiveDirNode* dir, dirNodes) {
|
||||
QVector < QPair<ArchiveNode*,int> > sorting(dir->entries().count());
|
||||
for (int i = 0; i < dir->entries().count(); ++i) {
|
||||
ArchiveNode *item = dir->entries().at(i);
|
||||
sorting[i].first = item;
|
||||
sorting[i].second = i;
|
||||
}
|
||||
|
||||
qStableSort(sorting.begin(), sorting.end(), modelSorter);
|
||||
|
||||
QModelIndexList fromIndexes;
|
||||
QModelIndexList toIndexes;
|
||||
for (int r = 0; r < sorting.count(); ++r) {
|
||||
ArchiveNode *item = sorting.at(r).first;
|
||||
toIndexes.append(createIndex(r, 0, item));
|
||||
fromIndexes.append(createIndex(sorting.at(r).second, 0, sorting.at(r).first));
|
||||
dir->setEntryAt(r, sorting.at(r).first);
|
||||
}
|
||||
|
||||
changePersistentIndexList(fromIndexes, toIndexes);
|
||||
|
||||
emit dataChanged(
|
||||
index(0, 0, indexForNode(dir)),
|
||||
index(dir->entries().size() - 1, 0, indexForNode(dir)));
|
||||
}
|
||||
|
||||
emit layoutChanged();
|
||||
}
|
||||
|
||||
Qt::DropActions ArchiveModel::supportedDropActions() const
|
||||
{
|
||||
return Qt::CopyAction | Qt::MoveAction;
|
||||
}
|
||||
|
||||
QStringList ArchiveModel::mimeTypes() const
|
||||
{
|
||||
QStringList types;
|
||||
|
||||
// MIME types we accept for dragging (eg. Dolphin -> Ark).
|
||||
types << QLatin1String("text/uri-list")
|
||||
<< QLatin1String("text/plain")
|
||||
<< QLatin1String("text/x-moz-url");
|
||||
|
||||
// MIME types we accept for dropping (eg. Ark -> Dolphin).
|
||||
types << QLatin1String("application/x-kde-ark-dndextract-service")
|
||||
<< QLatin1String("application/x-kde-ark-dndextract-path");
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
QMimeData *ArchiveModel::mimeData(const QModelIndexList &indexes) const
|
||||
{
|
||||
Q_UNUSED(indexes)
|
||||
|
||||
QMimeData *mimeData = new QMimeData;
|
||||
mimeData->setData(QLatin1String("application/x-kde-ark-dndextract-service"),
|
||||
QDBusConnection::sessionBus().baseService().toUtf8());
|
||||
mimeData->setData(QLatin1String("application/x-kde-ark-dndextract-path"),
|
||||
m_dbusPathName.toUtf8());
|
||||
|
||||
return mimeData;
|
||||
}
|
||||
|
||||
bool ArchiveModel::dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent)
|
||||
{
|
||||
Q_UNUSED(action)
|
||||
Q_UNUSED(row)
|
||||
Q_UNUSED(column)
|
||||
Q_UNUSED(parent)
|
||||
|
||||
if (!data->hasUrls()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList paths;
|
||||
foreach(const QUrl &url, data->urls()) {
|
||||
paths << url.toLocalFile();
|
||||
}
|
||||
|
||||
//for now, this code is not used because adding files to paths inside the
|
||||
//archive is not supported yet. need a solution for this later.
|
||||
QString path;
|
||||
#if 0
|
||||
if (parent.isValid()) {
|
||||
QModelIndex droppedOnto = index(row, column, parent);
|
||||
if (entryForIndex(droppedOnto).value(IsDirectory).toBool()) {
|
||||
kDebug() << "Using entry";
|
||||
path = entryForIndex(droppedOnto).value(FileName).toString();
|
||||
} else {
|
||||
path = entryForIndex(parent).value(FileName).toString();
|
||||
}
|
||||
}
|
||||
|
||||
kDebug() << "Dropped onto " << path;
|
||||
|
||||
#endif
|
||||
|
||||
emit droppedFiles(paths, path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// For a rationale, see bugs #194241 and #241967
|
||||
QString ArchiveModel::cleanFileName(const QString& fileName)
|
||||
{
|
||||
if ((fileName == QLatin1String("/")) ||
|
||||
(fileName == QLatin1String("."))) { // "." is present in ISO files
|
||||
return QString();
|
||||
} else if (fileName.startsWith(QLatin1String("./"))) {
|
||||
return fileName.mid(2);
|
||||
}
|
||||
|
||||
return fileName;
|
||||
}
|
||||
|
||||
ArchiveDirNode* ArchiveModel::parentFor(const ArchiveEntry& entry)
|
||||
{
|
||||
QStringList pieces = entry[ FileName ].toString().split(QLatin1Char( '/' ), QString::SkipEmptyParts);
|
||||
if (pieces.isEmpty()) {
|
||||
return NULL;
|
||||
}
|
||||
pieces.removeLast();
|
||||
|
||||
if (s_previousMatch) {
|
||||
//the number of path elements must be the same for the shortcut
|
||||
//to work
|
||||
if (s_previousPieces->count() == pieces.count()) {
|
||||
bool equal = true;
|
||||
|
||||
//make sure all the pieces match up
|
||||
for (int i = 0; i < s_previousPieces->count(); ++i) {
|
||||
if (s_previousPieces->at(i) != pieces.at(i)) {
|
||||
equal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//if match return it
|
||||
if (equal) {
|
||||
return static_cast<ArchiveDirNode*>(s_previousMatch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ArchiveDirNode *parent = m_rootNode;
|
||||
|
||||
foreach(const QString &piece, pieces) {
|
||||
ArchiveNode *node = parent->find(piece);
|
||||
if (!node) {
|
||||
ArchiveEntry e;
|
||||
e[ FileName ] = (parent == m_rootNode) ?
|
||||
piece : parent->entry()[ FileName ].toString() + QLatin1Char( '/' ) + piece;
|
||||
e[ IsDirectory ] = true;
|
||||
node = new ArchiveDirNode(parent, e);
|
||||
insertNode(node);
|
||||
}
|
||||
if (!node->isDir()) {
|
||||
ArchiveEntry e(node->entry());
|
||||
node = new ArchiveDirNode(parent, e);
|
||||
//Maybe we have both a file and a directory of the same name
|
||||
// We avoid removing previous entries unless necessary
|
||||
insertNode(node);
|
||||
}
|
||||
parent = static_cast<ArchiveDirNode*>(node);
|
||||
}
|
||||
|
||||
s_previousMatch = parent;
|
||||
*s_previousPieces = pieces;
|
||||
|
||||
return parent;
|
||||
}
|
||||
QModelIndex ArchiveModel::indexForNode(ArchiveNode *node)
|
||||
{
|
||||
Q_ASSERT(node);
|
||||
if (node != m_rootNode) {
|
||||
Q_ASSERT(node->parent());
|
||||
Q_ASSERT(node->parent()->isDir());
|
||||
return createIndex(node->row(), 0, node);
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
void ArchiveModel::slotEntryRemoved(const QString & path)
|
||||
{
|
||||
kDebug() << "Removed node at path " << path;
|
||||
|
||||
const QString entryFileName(cleanFileName(path));
|
||||
if (entryFileName.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ArchiveNode *entry = m_rootNode->findByPath(entryFileName.split(QLatin1Char( '/' ), QString::SkipEmptyParts));
|
||||
if (entry) {
|
||||
ArchiveDirNode *parent = entry->parent();
|
||||
QModelIndex index = indexForNode(entry);
|
||||
|
||||
beginRemoveRows(indexForNode(parent), entry->row(), entry->row());
|
||||
|
||||
//delete parent->entries()[ entry->row() ];
|
||||
//parent->entries()[ entry->row() ] = 0;
|
||||
parent->removeEntryAt(entry->row());
|
||||
|
||||
endRemoveRows();
|
||||
} else {
|
||||
kDebug() << "Did not find the removed node";
|
||||
}
|
||||
}
|
||||
|
||||
void ArchiveModel::slotUserQuery(Kerfuffle::Query *query)
|
||||
{
|
||||
query->execute();
|
||||
}
|
||||
|
||||
void ArchiveModel::slotNewEntryFromSetArchive(const ArchiveEntry& entry)
|
||||
{
|
||||
// we cache all entries that appear when opening a new archive
|
||||
// so we can all them together once it's done, this is a huge
|
||||
// performance improvement because we save from doing lots of
|
||||
// begin/endInsertRows
|
||||
m_newArchiveEntries.push_back(entry);
|
||||
}
|
||||
|
||||
void ArchiveModel::slotNewEntry(const ArchiveEntry& entry)
|
||||
{
|
||||
newEntry(entry, NotifyViews);
|
||||
}
|
||||
|
||||
void ArchiveModel::newEntry(const ArchiveEntry& receivedEntry, InsertBehaviour behaviour)
|
||||
{
|
||||
if (receivedEntry[FileName].toString().isEmpty()) {
|
||||
kDebug() << "Weird, received empty entry (no filename) - skipping";
|
||||
return;
|
||||
}
|
||||
|
||||
//if there are no addidional columns registered, then have a look at the
|
||||
//entry and populate some
|
||||
if (m_showColumns.isEmpty()) {
|
||||
//these are the columns we are interested in showing in the display
|
||||
static const QList<int> columnsForDisplay =
|
||||
QList<int>()
|
||||
<< FileName
|
||||
<< Size
|
||||
<< CompressedSize
|
||||
<< Permissions
|
||||
<< Owner
|
||||
<< Group
|
||||
<< Ratio
|
||||
<< CRC
|
||||
<< Method
|
||||
<< Version
|
||||
<< Timestamp
|
||||
<< Comment;
|
||||
|
||||
QList<int> toInsert;
|
||||
|
||||
foreach(int column, columnsForDisplay) {
|
||||
if (receivedEntry.contains(column)) {
|
||||
toInsert << column;
|
||||
}
|
||||
}
|
||||
beginInsertColumns(QModelIndex(), 0, toInsert.size() - 1);
|
||||
m_showColumns << toInsert;
|
||||
endInsertColumns();
|
||||
|
||||
kDebug() << "Show columns detected: " << m_showColumns;
|
||||
}
|
||||
|
||||
//make a copy
|
||||
ArchiveEntry entry = receivedEntry;
|
||||
|
||||
//#194241: Filenames such as "./file" should be displayed as "file"
|
||||
//#241967: Entries called "/" should be ignored
|
||||
QString entryFileName = cleanFileName(entry[FileName].toString());
|
||||
if (entryFileName.isEmpty()) { // The entry contains only "." or "./"
|
||||
return;
|
||||
}
|
||||
entry[FileName] = entryFileName;
|
||||
|
||||
/// 1. Skip already created nodes
|
||||
if (m_rootNode) {
|
||||
ArchiveNode *existing = m_rootNode->findByPath(entry[ FileName ].toString().split(QLatin1Char( '/' )));
|
||||
if (existing) {
|
||||
kDebug() << "Refreshing entry for" << entry[FileName].toString();
|
||||
|
||||
// Multi-volume files are repeated at least in RAR archives.
|
||||
// In that case, we need to sum the compressed size for each volume
|
||||
qulonglong currentCompressedSize = existing->entry()[CompressedSize].toULongLong();
|
||||
entry[CompressedSize] = currentCompressedSize + entry[CompressedSize].toULongLong();
|
||||
|
||||
//TODO: benchmark whether it's a bad idea to reset the entry here.
|
||||
existing->setEntry(entry);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// 2. Find Parent Node, creating missing ArchiveDirNodes in the process
|
||||
ArchiveDirNode *parent = parentFor(entry);
|
||||
|
||||
/// 3. Create an ArchiveNode
|
||||
QString name = entry[ FileName ].toString().split(QLatin1Char( '/' ), QString::SkipEmptyParts).last();
|
||||
ArchiveNode *node = parent->find(name);
|
||||
if (node) {
|
||||
node->setEntry(entry);
|
||||
} else {
|
||||
if (entry[ FileName ].toString().endsWith(QLatin1Char( '/' )) || (entry.contains(IsDirectory) && entry[ IsDirectory ].toBool())) {
|
||||
node = new ArchiveDirNode(parent, entry);
|
||||
} else {
|
||||
node = new ArchiveNode(parent, entry);
|
||||
}
|
||||
insertNode(node, behaviour);
|
||||
}
|
||||
}
|
||||
|
||||
void ArchiveModel::slotLoadingFinished(KJob *job)
|
||||
{
|
||||
//kDebug() << entry;
|
||||
foreach(const ArchiveEntry &entry, m_newArchiveEntries) {
|
||||
newEntry(entry, DoNotNotifyViews);
|
||||
}
|
||||
reset();
|
||||
m_newArchiveEntries.clear();
|
||||
|
||||
emit loadingFinished(job);
|
||||
}
|
||||
|
||||
void ArchiveModel::insertNode(ArchiveNode *node, InsertBehaviour behaviour)
|
||||
{
|
||||
Q_ASSERT(node);
|
||||
ArchiveDirNode *parent = node->parent();
|
||||
Q_ASSERT(parent);
|
||||
if (behaviour == NotifyViews) {
|
||||
beginInsertRows(indexForNode(parent), parent->entries().count(), parent->entries().count());
|
||||
}
|
||||
parent->appendEntry(node);
|
||||
if (behaviour == NotifyViews) {
|
||||
endInsertRows();
|
||||
}
|
||||
}
|
||||
|
||||
Kerfuffle::Archive* ArchiveModel::archive() const
|
||||
{
|
||||
return m_archive.data();
|
||||
}
|
||||
|
||||
KJob* ArchiveModel::setArchive(Kerfuffle::Archive *archive)
|
||||
{
|
||||
m_archive.reset(archive);
|
||||
|
||||
m_rootNode->clear();
|
||||
s_previousMatch = 0;
|
||||
s_previousPieces->clear();
|
||||
|
||||
Kerfuffle::ListJob *job = NULL;
|
||||
|
||||
m_newArchiveEntries.clear();
|
||||
if (m_archive) {
|
||||
job = m_archive->list(); // TODO: call "open" or "create"?
|
||||
|
||||
connect(job, SIGNAL(newEntry(ArchiveEntry)),
|
||||
this, SLOT(slotNewEntryFromSetArchive(ArchiveEntry)));
|
||||
|
||||
connect(job, SIGNAL(result(KJob*)),
|
||||
this, SLOT(slotLoadingFinished(KJob*)));
|
||||
|
||||
connect(job, SIGNAL(userQuery(Kerfuffle::Query*)),
|
||||
this, SLOT(slotUserQuery(Kerfuffle::Query*)));
|
||||
|
||||
emit loadingStarted();
|
||||
|
||||
// TODO: make sure if it's ok to not have calls to beginRemoveColumns here
|
||||
m_showColumns.clear();
|
||||
}
|
||||
reset();
|
||||
return job;
|
||||
}
|
||||
|
||||
ExtractJob* ArchiveModel::extractFile(const QVariant& fileName, const QString & destinationDir, const Kerfuffle::ExtractionOptions options) const
|
||||
{
|
||||
QList<QVariant> files;
|
||||
files << fileName;
|
||||
return extractFiles(files, destinationDir, options);
|
||||
}
|
||||
|
||||
ExtractJob* ArchiveModel::extractFiles(const QList<QVariant>& files, const QString & destinationDir, const Kerfuffle::ExtractionOptions options) const
|
||||
{
|
||||
Q_ASSERT(m_archive);
|
||||
ExtractJob *newJob = m_archive->copyFiles(files, destinationDir, options);
|
||||
connect(newJob, SIGNAL(userQuery(Kerfuffle::Query*)),
|
||||
this, SLOT(slotUserQuery(Kerfuffle::Query*)));
|
||||
return newJob;
|
||||
}
|
||||
|
||||
AddJob* ArchiveModel::addFiles(const QStringList & filenames, const CompressionOptions& options)
|
||||
{
|
||||
if (!m_archive) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!m_archive->isReadOnly()) {
|
||||
AddJob *job = m_archive->addFiles(filenames, options);
|
||||
connect(job, SIGNAL(newEntry(ArchiveEntry)),
|
||||
this, SLOT(slotNewEntry(ArchiveEntry)));
|
||||
connect(job, SIGNAL(userQuery(Kerfuffle::Query*)),
|
||||
this, SLOT(slotUserQuery(Kerfuffle::Query*)));
|
||||
|
||||
|
||||
return job;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DeleteJob* ArchiveModel::deleteFiles(const QList<QVariant> & files)
|
||||
{
|
||||
Q_ASSERT(m_archive);
|
||||
if (!m_archive->isReadOnly()) {
|
||||
DeleteJob *job = m_archive->deleteFiles(files);
|
||||
connect(job, SIGNAL(entryRemoved(QString)),
|
||||
this, SLOT(slotEntryRemoved(QString)));
|
||||
|
||||
connect(job, SIGNAL(finished(KJob*)),
|
||||
this, SLOT(slotCleanupEmptyDirs()));
|
||||
|
||||
connect(job, SIGNAL(userQuery(Kerfuffle::Query*)),
|
||||
this, SLOT(slotUserQuery(Kerfuffle::Query*)));
|
||||
return job;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ArchiveModel::slotCleanupEmptyDirs()
|
||||
{
|
||||
kDebug();
|
||||
QList<QPersistentModelIndex> queue;
|
||||
QList<QPersistentModelIndex> nodesToDelete;
|
||||
|
||||
//add root nodes
|
||||
for (int i = 0; i < rowCount(); ++i) {
|
||||
queue.append(QPersistentModelIndex(index(i, 0)));
|
||||
}
|
||||
|
||||
//breadth-first traverse
|
||||
while (!queue.isEmpty()) {
|
||||
QPersistentModelIndex node = queue.takeFirst();
|
||||
ArchiveEntry entry = entryForIndex(node);
|
||||
//kDebug() << "Trying " << entry[FileName].toString();
|
||||
|
||||
if (!hasChildren(node)) {
|
||||
if (!entry.contains(InternalID)) {
|
||||
nodesToDelete << node;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < rowCount(node); ++i) {
|
||||
queue.append(QPersistentModelIndex(index(i, 0, node)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach(const QPersistentModelIndex& node, nodesToDelete) {
|
||||
ArchiveNode *rawNode = static_cast<ArchiveNode*>(node.internalPointer());
|
||||
kDebug() << "Delete with parent entries " << rawNode->parent()->entries() << " and row " << rawNode->row();
|
||||
beginRemoveRows(parent(node), rawNode->row(), rawNode->row());
|
||||
rawNode->parent()->removeEntryAt(rawNode->row());
|
||||
endRemoveRows();
|
||||
//kDebug() << "Removed entry " << entry[FileName].toString();
|
||||
}
|
||||
}
|
||||
|
||||
#include "archivemodel.moc"
|
126
ark/part/archivemodel.h
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
|
||||
* Copyright (C) 2008-2009 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
*
|
||||
* 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 ARCHIVEMODEL_H
|
||||
#define ARCHIVEMODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QScopedPointer>
|
||||
|
||||
#include <kjobtrackerinterface.h>
|
||||
#include "kerfuffle/archive.h"
|
||||
|
||||
using Kerfuffle::ArchiveEntry;
|
||||
|
||||
namespace Kerfuffle
|
||||
{
|
||||
class Query;
|
||||
}
|
||||
|
||||
class ArchiveNode;
|
||||
class ArchiveDirNode;
|
||||
|
||||
class ArchiveModel: public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ArchiveModel(const QString &dbusPathName, QObject *parent = 0);
|
||||
~ArchiveModel();
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const;
|
||||
QModelIndex index(int row, int column,
|
||||
const QModelIndex &parent = QModelIndex()) const;
|
||||
QModelIndex parent(const QModelIndex &index) const;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
|
||||
virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
|
||||
|
||||
//drag and drop related
|
||||
virtual Qt::DropActions supportedDropActions() const;
|
||||
virtual QStringList mimeTypes() const;
|
||||
virtual QMimeData * mimeData(const QModelIndexList & indexes) const;
|
||||
|
||||
virtual bool dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent);
|
||||
|
||||
KJob* setArchive(Kerfuffle::Archive *archive);
|
||||
Kerfuffle::Archive *archive() const;
|
||||
|
||||
Kerfuffle::ArchiveEntry entryForIndex(const QModelIndex &index);
|
||||
int childCount(const QModelIndex &index, int &dirs, int &files) const;
|
||||
|
||||
Kerfuffle::ExtractJob* extractFile(const QVariant& fileName, const QString & destinationDir, const Kerfuffle::ExtractionOptions options = Kerfuffle::ExtractionOptions()) const;
|
||||
Kerfuffle::ExtractJob* extractFiles(const QList<QVariant>& files, const QString & destinationDir, const Kerfuffle::ExtractionOptions options = Kerfuffle::ExtractionOptions()) const;
|
||||
|
||||
Kerfuffle::AddJob* addFiles(const QStringList & paths, const Kerfuffle::CompressionOptions& options = Kerfuffle::CompressionOptions());
|
||||
Kerfuffle::DeleteJob* deleteFiles(const QList<QVariant> & files);
|
||||
|
||||
signals:
|
||||
void loadingStarted();
|
||||
void loadingFinished(KJob *);
|
||||
void extractionFinished(bool success);
|
||||
void error(const QString& error, const QString& details);
|
||||
void droppedFiles(const QStringList& files, const QString& path = QString());
|
||||
|
||||
private slots:
|
||||
void slotNewEntryFromSetArchive(const ArchiveEntry& entry);
|
||||
void slotNewEntry(const ArchiveEntry& entry);
|
||||
void slotLoadingFinished(KJob *job);
|
||||
void slotEntryRemoved(const QString & path);
|
||||
void slotUserQuery(Kerfuffle::Query *query);
|
||||
void slotCleanupEmptyDirs();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Strips file names that start with './'.
|
||||
*
|
||||
* For more information, see bug 194241.
|
||||
*
|
||||
* @param fileName The file name that will be stripped.
|
||||
*
|
||||
* @return @p fileName without the leading './'
|
||||
*/
|
||||
QString cleanFileName(const QString& fileName);
|
||||
|
||||
ArchiveDirNode* parentFor(const Kerfuffle::ArchiveEntry& entry);
|
||||
QModelIndex indexForNode(ArchiveNode *node);
|
||||
static bool compareAscending(const QModelIndex& a, const QModelIndex& b);
|
||||
static bool compareDescending(const QModelIndex& a, const QModelIndex& b);
|
||||
/**
|
||||
* Insert the node @p node into the model, ensuring all views are notified
|
||||
* of the change.
|
||||
*/
|
||||
enum InsertBehaviour { NotifyViews, DoNotNotifyViews };
|
||||
void insertNode(ArchiveNode *node, InsertBehaviour behaviour = NotifyViews);
|
||||
void newEntry(const Kerfuffle::ArchiveEntry& entry, InsertBehaviour behaviour);
|
||||
|
||||
QList<Kerfuffle::ArchiveEntry> m_newArchiveEntries; // holds entries from opening a new archive until it's totally open
|
||||
QList<int> m_showColumns;
|
||||
QScopedPointer<Kerfuffle::Archive> m_archive;
|
||||
ArchiveDirNode *m_rootNode;
|
||||
|
||||
QString m_dbusPathName;
|
||||
};
|
||||
|
||||
#endif // ARCHIVEMODEL_H
|
142
ark/part/archiveview.cpp
Normal file
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2008-2009 Harald Hvaal <haraldhv (at@at) stud.ntnu.no>
|
||||
*
|
||||
* 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 "archiveview.h"
|
||||
|
||||
#include <KDebug>
|
||||
#include <KGlobalSettings>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDragEnterEvent>
|
||||
#include <QDragMoveEvent>
|
||||
#include <QMouseEvent>
|
||||
|
||||
ArchiveView::ArchiveView(QWidget *parent)
|
||||
: QTreeView(parent)
|
||||
, m_mouseButtons(Qt::NoButton)
|
||||
{
|
||||
connect(this, SIGNAL(pressed(QModelIndex)),
|
||||
SLOT(updateMouseButtons()));
|
||||
connect(this, SIGNAL(clicked(QModelIndex)),
|
||||
SLOT(slotClicked(QModelIndex)));
|
||||
connect(this, SIGNAL(doubleClicked(QModelIndex)),
|
||||
SLOT(slotDoubleClicked(QModelIndex)));
|
||||
}
|
||||
|
||||
// FIXME: this is a workaround taken from Dolphin until QTBUG-1067 is resolved
|
||||
void ArchiveView::updateMouseButtons()
|
||||
{
|
||||
m_mouseButtons = QApplication::mouseButtons();
|
||||
}
|
||||
|
||||
void ArchiveView::slotClicked(const QModelIndex& index)
|
||||
{
|
||||
if (KGlobalSettings::singleClick()) {
|
||||
if (m_mouseButtons != Qt::LeftButton) { // FIXME: see QTBUG-1067
|
||||
return;
|
||||
}
|
||||
|
||||
// If the user is pressing shift or control, more than one item is being selected
|
||||
const Qt::KeyboardModifiers modifier = QApplication::keyboardModifiers();
|
||||
if ((modifier & Qt::ShiftModifier) || (modifier & Qt::ControlModifier)) {
|
||||
return;
|
||||
}
|
||||
|
||||
emit itemTriggered(index);
|
||||
}
|
||||
}
|
||||
|
||||
void ArchiveView::slotDoubleClicked(const QModelIndex& index)
|
||||
{
|
||||
if (!KGlobalSettings::singleClick()) {
|
||||
emit itemTriggered(index);
|
||||
}
|
||||
}
|
||||
|
||||
void ArchiveView::setModel(QAbstractItemModel *model)
|
||||
{
|
||||
kDebug();
|
||||
QTreeView::setModel(model);
|
||||
setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
setAlternatingRowColors(true);
|
||||
setAnimated(true);
|
||||
setAllColumnsShowFocus(true);
|
||||
setSortingEnabled(true);
|
||||
|
||||
//drag and drop
|
||||
setDragEnabled(true);
|
||||
setAcceptDrops(true);
|
||||
setDropIndicatorShown(true);
|
||||
setDragDropMode(QAbstractItemView::DragDrop);
|
||||
}
|
||||
|
||||
void ArchiveView::startDrag(Qt::DropActions supportedActions)
|
||||
{
|
||||
//only start the drag if it's over the filename column. this allows dragging selection in
|
||||
//tree/detail view
|
||||
if (currentIndex().column() != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
kDebug() << "Singling out the current selection...";
|
||||
selectionModel()->setCurrentIndex(currentIndex(), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
|
||||
QTreeView::startDrag(supportedActions);
|
||||
}
|
||||
|
||||
|
||||
void ArchiveView::dragEnterEvent(QDragEnterEvent * event)
|
||||
{
|
||||
//TODO: if no model, trigger some mechanism to create one automatically!
|
||||
kDebug() << event;
|
||||
|
||||
if (event->source() == this) {
|
||||
//we don't support internal drops yet.
|
||||
return;
|
||||
}
|
||||
|
||||
QTreeView::dragEnterEvent(event);
|
||||
}
|
||||
|
||||
void ArchiveView::dropEvent(QDropEvent * event)
|
||||
{
|
||||
kDebug() << event;
|
||||
|
||||
if (event->source() == this) {
|
||||
//we don't support internal drops yet.
|
||||
return;
|
||||
}
|
||||
|
||||
QTreeView::dropEvent(event);
|
||||
}
|
||||
|
||||
void ArchiveView::dragMoveEvent(QDragMoveEvent * event)
|
||||
{
|
||||
if (event->source() == this) {
|
||||
//we don't support internal drops yet.
|
||||
return;
|
||||
}
|
||||
|
||||
QTreeView::dragMoveEvent(event);
|
||||
if (event->mimeData()->hasFormat(QLatin1String("text/uri-list"))) {
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
}
|
54
ark/part/archiveview.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2008 Harald Hvaal <haraldhv (at@at) stud.ntnu.no>
|
||||
*
|
||||
* 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 ARCHIVEVIEW_H
|
||||
#define ARCHIVEVIEW_H
|
||||
|
||||
#include <QTreeView>
|
||||
|
||||
class ArchiveView : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ArchiveView(QWidget *parent = 0);
|
||||
virtual void dragEnterEvent(class QDragEnterEvent * event);
|
||||
virtual void dropEvent(class QDropEvent * event);
|
||||
virtual void dragMoveEvent(class QDragMoveEvent * event);
|
||||
virtual void startDrag(Qt::DropActions supportedActions);
|
||||
|
||||
void setModel(QAbstractItemModel *model);
|
||||
|
||||
protected slots:
|
||||
void slotClicked(const QModelIndex & index);
|
||||
void slotDoubleClicked(const QModelIndex & index);
|
||||
|
||||
private slots:
|
||||
void updateMouseButtons();
|
||||
|
||||
signals:
|
||||
void itemTriggered(const QModelIndex & index);
|
||||
|
||||
private:
|
||||
Qt::MouseButtons m_mouseButtons; // FIXME: workaround until QTBUG-1067 is resolved
|
||||
};
|
||||
|
||||
#endif /* ARCHIVEVIEW_H */
|
152
ark/part/ark_part.desktop.cmake
Normal file
|
@ -0,0 +1,152 @@
|
|||
[Desktop Entry]
|
||||
Icon=ark
|
||||
Name=Archiver
|
||||
Name[af]=Argifeerder
|
||||
Name[ar]=المؤرشف
|
||||
Name[ast]=Archivador
|
||||
Name[bg]=Архиватор
|
||||
Name[br]=Dieller
|
||||
Name[bs]=Arhivar
|
||||
Name[ca]=Arxivador
|
||||
Name[ca@valencia]=Arxivador
|
||||
Name[cs]=Archivátor
|
||||
Name[cy]=Archifydd
|
||||
Name[da]=Arkivbehandler
|
||||
Name[de]=Archivprogramm
|
||||
Name[el]=Πρόγραμμα αρχειοθέτησης
|
||||
Name[en_GB]=Archiver
|
||||
Name[eo]=Arkivilo
|
||||
Name[es]=Archivador
|
||||
Name[et]=Arhiveerija
|
||||
Name[eu]=Artxibatzeko programa
|
||||
Name[fa]=بایگانیکننده
|
||||
Name[fi]=Pakkausohjelma
|
||||
Name[fr]=Archiveur
|
||||
Name[ga]=Archiver
|
||||
Name[gl]=Arquivador
|
||||
Name[he]=מנהל הארכיונים
|
||||
Name[hne]=अभिलेखक
|
||||
Name[hr]=Arhiver
|
||||
Name[hu]=Ark fájltömörítő
|
||||
Name[ia]=Archivator
|
||||
Name[id]=Pengarsip
|
||||
Name[is]=Skráasafnari
|
||||
Name[it]=Utilità di archiviazione
|
||||
Name[ja]=アーカイバ
|
||||
Name[kk]=Архивтегіш
|
||||
Name[km]=កម្មវិធីប័ណ្ណសារ
|
||||
Name[ko]=Archiver
|
||||
Name[lt]=Archyvatorius
|
||||
Name[lv]=Arhivātors
|
||||
Name[mk]=Архивер
|
||||
Name[mr]=संग्रहकर्ता
|
||||
Name[ms]=Pengarkib
|
||||
Name[nb]=Arkivbehandler
|
||||
Name[nds]=Archivater
|
||||
Name[ne]=सङ्ग्रहक
|
||||
Name[nl]=Archiefgereedschap
|
||||
Name[nn]=Arkivprogram
|
||||
Name[pa]=ਅਕਾਇਵਰ
|
||||
Name[pl]=Ark
|
||||
Name[pt]=Ark
|
||||
Name[pt_BR]=Arquivador
|
||||
Name[ro]=Arhivator
|
||||
Name[ru]=Архиватор
|
||||
Name[sk]=Archivačný nástroj
|
||||
Name[sl]=Pakirnik
|
||||
Name[sq]=Arkivues
|
||||
Name[sr]=Архивар
|
||||
Name[sr@ijekavian]=Архивар
|
||||
Name[sr@ijekavianlatin]=Arhivar
|
||||
Name[sr@latin]=Arhivar
|
||||
Name[sv]=Arkiverare
|
||||
Name[ta]=காப்பகம் உருவாக்கி
|
||||
Name[tg]=Бойгонигар
|
||||
Name[th]=ตัวสร้างแฟ้มจัดเก็บ
|
||||
Name[tr]=Arşivleyici
|
||||
Name[uk]=Архіватор
|
||||
Name[uz]=Arxivlagich
|
||||
Name[uz@cyrillic]=Архивлагич
|
||||
Name[vi]=Trình Lưu Trữ
|
||||
Name[wa]=Årtchiveu
|
||||
Name[xh]=Umenzi woshicilelo lukawonke-wonke noxwebhu lweMbali
|
||||
Name[x-test]=xxArchiverxx
|
||||
Name[zh_CN]=压缩存档工具
|
||||
Name[zh_TW]=壓縮檔處理器
|
||||
Comment=Archive Handling Tool
|
||||
Comment[af]=Argief Handtering Program
|
||||
Comment[ar]=أداة التعامل مع الملفات المضغوطة
|
||||
Comment[ast]=Ferramienta pa remanar archivadores
|
||||
Comment[bg]=Работа с архиви
|
||||
Comment[br]=Ostilh merañ an dielloù
|
||||
Comment[bs]=Alatka za rukovanje arhivama
|
||||
Comment[ca]=Eina per a treballar amb arxius
|
||||
Comment[ca@valencia]=Eina per a treballar amb arxius
|
||||
Comment[cs]=Program pro práci s archivy
|
||||
Comment[cy]=Erfyn Triniaeth Archif
|
||||
Comment[da]=Arkivbehandlingsværktøj
|
||||
Comment[de]=Archiv-Verwaltung
|
||||
Comment[el]=Εργαλείο χειρισμού αρχειοθηκών
|
||||
Comment[en_GB]=Archive Handling Tool
|
||||
Comment[eo]=Administrilo por arĥivoj
|
||||
Comment[es]=Herramienta de gestión de archivos
|
||||
Comment[et]=Arhiivide haldamise rakendus
|
||||
Comment[eu]=Artxiboak kudeatzeko tresna
|
||||
Comment[fa]=ابزار گرداندن بایگانی
|
||||
Comment[fi]=Pakkausohjelma
|
||||
Comment[fr]=Outil de manipulation d'archives
|
||||
Comment[ga]=Uirlis Láimhseála Cartlainne
|
||||
Comment[gl]=Utilidade de manexo de arquivos
|
||||
Comment[he]=כלי לניהול ארכיונים
|
||||
Comment[hne]=अभिलेख संभाल औजार
|
||||
Comment[hr]=Uslužni program za arhiviranje
|
||||
Comment[hu]=Tömörítőprogram
|
||||
Comment[ia]=Instrumento de manear archivo
|
||||
Comment[id]=Perkakas Penanganan Arsip
|
||||
Comment[is]=Vinna með safnskrár
|
||||
Comment[it]=Gestione degli archivi
|
||||
Comment[ja]=アーカイブを操作するツール
|
||||
Comment[kk]=Архивпен айналысу құралы
|
||||
Comment[km]=ឧបករណ៍គ្រប់គ្រងប័ណ្ណសារ
|
||||
Comment[ko]=압축 파일 도구
|
||||
Comment[lt]=Archyvo valdymo priemonė
|
||||
Comment[lv]=Arhīvu apstrādes rīks
|
||||
Comment[mk]=Алатка за справување со архивирани датотеки
|
||||
Comment[mr]=संग्रह हाताळणारे साधन
|
||||
Comment[ms]=Alatan Pengendalian Arkib
|
||||
Comment[nb]=Arkivbehandlingsverktøy
|
||||
Comment[nds]=En Warktüüch för de Archievpleeg
|
||||
Comment[ne]=ह्यान्डलिङ उपकरण सङ्ग्रह गर्नुहोस्
|
||||
Comment[nl]=Hulpprogramma voor het beheren van archieven
|
||||
Comment[nn]=Verktøy for arkivhandsaming
|
||||
Comment[pa]=ਅਕਾਇਵ ਹੈਡਲਿੰਗ ਟੂਲ
|
||||
Comment[pl]=Program obsługi archiwów
|
||||
Comment[pt]=Programa de gestão de arquivos
|
||||
Comment[pt_BR]=Ferramenta de manipulação de arquivos
|
||||
Comment[ro]=Utilitar de manipulare arhive
|
||||
Comment[ru]=Программа работы с архивами
|
||||
Comment[sk]=Nástroj na prácu s archívmi
|
||||
Comment[sl]=Orodje za ravnanje z arhivi
|
||||
Comment[sq]=Mjet Për Përpunimin e Arkivave
|
||||
Comment[sr]=Алатка за руковање архивама
|
||||
Comment[sr@ijekavian]=Алатка за руковање архивама
|
||||
Comment[sr@ijekavianlatin]=Alatka za rukovanje arhivama
|
||||
Comment[sr@latin]=Alatka za rukovanje arhivama
|
||||
Comment[sv]=Verktyg för att hantera filarkiv
|
||||
Comment[ta]=காப்பகத்தை கையாளும் கருவி
|
||||
Comment[tg]=Асбобҳои Дасткории Бойгонӣ
|
||||
Comment[th]=เครื่องมือจัดการแฟ้มจัดเก็บ
|
||||
Comment[tr]=Arşiv İşleme Aracı
|
||||
Comment[uk]=Засіб роботи з архівами
|
||||
Comment[uz]=Arxiv uchun vosita
|
||||
Comment[uz@cyrillic]=Архив учун восита
|
||||
Comment[vi]=Công Cụ Xử Lý Các Tập Tin Nén
|
||||
Comment[wa]=Usteye po-z apougnî les årtchives
|
||||
Comment[xh]=Isixhobo sokuphatha i Archive
|
||||
Comment[x-test]=xxArchive Handling Toolxx
|
||||
Comment[zh_CN]=压缩归档处理工具
|
||||
Comment[zh_TW]=壓縮檔處理工具
|
||||
X-KDE-ServiceTypes=KParts/ReadOnlyPart,Browser/View
|
||||
X-KDE-Library=arkpart
|
||||
Type=Service
|
||||
MimeType=@SUPPORTED_ARK_MIMETYPES@
|
28
ark/part/ark_part.rc
Normal file
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE kpartgui>
|
||||
<kpartgui name="ark_part" version="1">
|
||||
<MenuBar>
|
||||
<Menu name="file">
|
||||
<text>&File</text>
|
||||
<Action name="file_save_as" group="file_save"/>
|
||||
</Menu>
|
||||
<Menu name="action">
|
||||
<text>&Action</text>
|
||||
<Action name="add"/>
|
||||
<Action name="add-dir"/>
|
||||
<Action name="delete"/>
|
||||
<Action name="extract"/>
|
||||
<Action name="preview"/>
|
||||
</Menu>
|
||||
<Menu name="settings">
|
||||
<text>&Settings</text>
|
||||
<Action name="show-infopanel" group="settings_show"/>
|
||||
</Menu>
|
||||
</MenuBar>
|
||||
<ToolBar name="mainToolBar">
|
||||
<Action name="add"/>
|
||||
<Action name="add-dir"/>
|
||||
<Action name="delete"/>
|
||||
<Action name="extract"/>
|
||||
<Action name="preview"/>
|
||||
</ToolBar>
|
||||
</kpartgui>
|
266
ark/part/arkviewer.cpp
Normal file
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
* ark: A program for modifying archives via a GUI.
|
||||
*
|
||||
* Copyright (C) 2004-2008 Henrique Pinto <henrique.pinto@kdemail.net>
|
||||
*
|
||||
* 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 "arkviewer.h"
|
||||
|
||||
#include <KLocale>
|
||||
#include <KMimeTypeTrader>
|
||||
#include <KMimeType>
|
||||
#include <KDebug>
|
||||
#include <KUrl>
|
||||
#include <KGlobal>
|
||||
#include <KIconLoader>
|
||||
#include <KVBox>
|
||||
#include <KMessageBox>
|
||||
#include <KProgressDialog>
|
||||
#include <KPushButton>
|
||||
#include <KRun>
|
||||
#include <KIO/NetAccess>
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QFile>
|
||||
#include <QFrame>
|
||||
#include <QLabel>
|
||||
|
||||
ArkViewer::ArkViewer(QWidget * parent, Qt::WFlags flags)
|
||||
: KDialog(parent, flags)
|
||||
{
|
||||
setButtons(Close);
|
||||
m_widget = new KVBox(this);
|
||||
m_widget->layout()->setSpacing(10);
|
||||
|
||||
setMainWidget(m_widget);
|
||||
|
||||
connect(this, SIGNAL(finished()), SLOT(dialogClosed()));
|
||||
}
|
||||
|
||||
ArkViewer::~ArkViewer()
|
||||
{
|
||||
}
|
||||
|
||||
void ArkViewer::dialogClosed()
|
||||
{
|
||||
KConfigGroup conf = KGlobal::config()->group("Viewer");
|
||||
saveDialogSize(conf);
|
||||
|
||||
if (m_part) {
|
||||
KProgressDialog progressDialog
|
||||
(this, i18n("Closing preview"),
|
||||
i18n("Please wait while the preview is being closed..."));
|
||||
|
||||
progressDialog.setMinimumDuration(500);
|
||||
progressDialog.setModal(true);
|
||||
progressDialog.setAllowCancel(false);
|
||||
progressDialog.progressBar()->setRange(0, 0);
|
||||
|
||||
// #261785: this preview dialog is not modal, so we need to delete
|
||||
// the previewed file ourselves when the dialog is closed;
|
||||
// we used to remove it at the end of ArkViewer::view() when
|
||||
// QDialog::exec() was called instead of QDialog::show().
|
||||
const QString previewedFilePath(m_part.data()->url().pathOrUrl());
|
||||
|
||||
m_part.data()->closeUrl();
|
||||
|
||||
if (!previewedFilePath.isEmpty()) {
|
||||
QFile::remove(previewedFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ArkViewer::view(const QString& fileName, QWidget *parent)
|
||||
{
|
||||
KMimeType::Ptr mimeType = KMimeType::findByPath(fileName);
|
||||
kDebug() << "MIME type" << mimeType->name();
|
||||
KService::Ptr viewer = ArkViewer::getViewer(mimeType);
|
||||
|
||||
const bool needsExternalViewer = (!viewer.isNull() &&
|
||||
!viewer->hasServiceType(QLatin1String("KParts/ReadOnlyPart")));
|
||||
if (needsExternalViewer) {
|
||||
// We have already resolved the MIME type and the service above.
|
||||
// So there is no point in using KRun::runUrl() which would need
|
||||
// to do the same again.
|
||||
|
||||
const KUrl::List fileUrlList = KUrl(fileName);
|
||||
// The last argument (tempFiles) set to true means that the temporary
|
||||
// file will be removed when the viewer application exits.
|
||||
KRun::run(*viewer, fileUrlList, parent, true);
|
||||
return;
|
||||
}
|
||||
|
||||
bool viewInInternalViewer = true;
|
||||
if (viewer.isNull()) {
|
||||
// No internal viewer available for the file. Ask the user if it
|
||||
// should be previewed as text/plain.
|
||||
|
||||
int response;
|
||||
if (!mimeType->isDefault()) {
|
||||
// File has a defined MIME type, and not the default
|
||||
// application/octet-stream. So it could be viewable as
|
||||
// plain text, ask the user.
|
||||
response = KMessageBox::warningContinueCancel(parent,
|
||||
i18n("The internal viewer cannot preview this type of file<nl/>(%1).<nl/><nl/>Do you want to try to view it as plain text?", mimeType->name()),
|
||||
i18nc("@title:window", "Cannot Preview File"),
|
||||
KGuiItem(i18nc("@action:button", "Preview as Text"), KIcon(QLatin1String("text-plain"))),
|
||||
KStandardGuiItem::cancel(),
|
||||
QString(QLatin1String("PreviewAsText_%1")).arg(mimeType->name()));
|
||||
}
|
||||
else {
|
||||
// No defined MIME type, or the default application/octet-stream.
|
||||
// There is still a possibility that it could be viewable as plain
|
||||
// text, so ask the user. Not the same as the message/question
|
||||
// above, because the wording and default are different.
|
||||
response = KMessageBox::warningContinueCancel(parent,
|
||||
i18n("The internal viewer cannot preview this unknown type of file.<nl/><nl/>Do you want to try to view it as plain text?"),
|
||||
i18nc("@title:window", "Cannot Preview File"),
|
||||
KGuiItem(i18nc("@action:button", "Preview as Text"), KIcon(QLatin1String("text-plain"))),
|
||||
KStandardGuiItem::cancel(),
|
||||
QString(),
|
||||
KMessageBox::Dangerous);
|
||||
}
|
||||
|
||||
if (response == KMessageBox::Cancel) {
|
||||
viewInInternalViewer = false;
|
||||
}
|
||||
else { // set for viewer later
|
||||
mimeType = KMimeType::mimeType(QLatin1String("text/plain"));
|
||||
}
|
||||
}
|
||||
|
||||
if (viewInInternalViewer) {
|
||||
ArkViewer *internalViewer = new ArkViewer(parent, Qt::Window);
|
||||
if (internalViewer->viewInInternalViewer(fileName, mimeType)) {
|
||||
internalViewer->show();
|
||||
// The internal viewer is showing the file, and will
|
||||
// remove the temporary file in dialogClosed(). So there
|
||||
// is no more to do here.
|
||||
return;
|
||||
}
|
||||
else {
|
||||
KMessageBox::sorry(parent, i18n("The internal viewer cannot preview this file."));
|
||||
delete internalViewer;
|
||||
}
|
||||
}
|
||||
|
||||
// Only get here if there is no internal viewer available or could be
|
||||
// used for the file, and no external viewer was opened. Nothing can be
|
||||
// done with the temporary file, so remove it now.
|
||||
QFile::remove(fileName);
|
||||
}
|
||||
|
||||
void ArkViewer::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
KPushButton *defButton = button(defaultButton());
|
||||
|
||||
// Only handle the event the usual way if the default button has focus
|
||||
// Otherwise, pressing enter on KatePart still closes the dialog, for example.
|
||||
if ((defButton) && (defButton->hasFocus())) {
|
||||
KDialog::keyPressEvent(event);
|
||||
}
|
||||
|
||||
event->accept();
|
||||
}
|
||||
|
||||
// This sets the default size of the dialog. It will only take effect in the case
|
||||
// where there is no saved size in the config file - it sets the default values
|
||||
// for KDialog::restoreDialogSize().
|
||||
QSize ArkViewer::sizeHint() const
|
||||
{
|
||||
return QSize(560, 400);
|
||||
}
|
||||
|
||||
bool ArkViewer::viewInInternalViewer(const QString& fileName, const KMimeType::Ptr& mimeType)
|
||||
{
|
||||
const KUrl fileUrl(fileName);
|
||||
|
||||
setCaption(fileUrl.fileName());
|
||||
restoreDialogSize(KGlobal::config()->group("Viewer"));
|
||||
|
||||
QFrame *header = new QFrame(m_widget);
|
||||
QHBoxLayout *headerLayout = new QHBoxLayout(header);
|
||||
|
||||
QLabel *iconLabel = new QLabel(header);
|
||||
headerLayout->addWidget(iconLabel);
|
||||
iconLabel->setPixmap(KIconLoader::global()->loadMimeTypeIcon(mimeType->iconName(), KIconLoader::Desktop));
|
||||
iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
|
||||
|
||||
KVBox *headerRight = new KVBox(header);
|
||||
headerLayout->addWidget(headerRight);
|
||||
new QLabel(QString(QLatin1String( "<qt><b>%1</b></qt>" ))
|
||||
.arg(fileUrl.fileName()), headerRight
|
||||
);
|
||||
new QLabel(mimeType->comment(), headerRight);
|
||||
|
||||
header->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
|
||||
|
||||
m_part = KMimeTypeTrader::self()->createPartInstanceFromQuery<KParts::ReadOnlyPart>(mimeType->name(),
|
||||
m_widget,
|
||||
this);
|
||||
|
||||
if (!m_part.data()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_part.data()->browserExtension()) {
|
||||
connect(m_part.data()->browserExtension(),
|
||||
SIGNAL(openUrlRequestDelayed(KUrl,KParts::OpenUrlArguments,KParts::BrowserArguments)),
|
||||
SLOT(slotOpenUrlRequestDelayed(KUrl,KParts::OpenUrlArguments,KParts::BrowserArguments)));
|
||||
}
|
||||
|
||||
m_part.data()->openUrl(fileUrl);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ArkViewer::slotOpenUrlRequestDelayed(const KUrl& url, const KParts::OpenUrlArguments& arguments, const KParts::BrowserArguments& browserArguments)
|
||||
{
|
||||
kDebug() << "Opening URL: " << url;
|
||||
|
||||
Q_UNUSED(arguments)
|
||||
Q_UNUSED(browserArguments)
|
||||
|
||||
KRun *runner = new KRun(url, 0, 0, false);
|
||||
runner->setRunExecutables(false);
|
||||
}
|
||||
|
||||
KService::Ptr ArkViewer::getViewer(const KMimeType::Ptr &mimeType)
|
||||
{
|
||||
// No point in even trying to find anything for application/octet-stream
|
||||
if (mimeType->isDefault()) {
|
||||
return KService::Ptr();
|
||||
}
|
||||
|
||||
// Try to get a read-only kpart for the internal viewer
|
||||
KService::List offers = KMimeTypeTrader::self()->query(mimeType->name(), QString::fromLatin1("KParts/ReadOnlyPart"));
|
||||
|
||||
// If we can't find a kpart, try to get an external application
|
||||
if (offers.size() == 0) {
|
||||
offers = KMimeTypeTrader::self()->query(mimeType->name(), QString::fromLatin1("Application"));
|
||||
}
|
||||
|
||||
if (offers.size() > 0) {
|
||||
return offers.first();
|
||||
} else {
|
||||
return KService::Ptr();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#include "arkviewer.moc"
|
63
ark/part/arkviewer.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* ark: A program for modifying archives via a GUI.
|
||||
*
|
||||
* Copyright (C) 2004-2008, Henrique Pinto <henrique.pinto@kdemail.net>
|
||||
*
|
||||
* 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 ARKVIEWER_H
|
||||
#define ARKVIEWER_H
|
||||
|
||||
#include <KDialog>
|
||||
#include <KMimeType>
|
||||
#include <KParts/BrowserExtension>
|
||||
#include <KParts/ReadOnlyPart>
|
||||
#include <KService>
|
||||
|
||||
#include <QtCore/QWeakPointer>
|
||||
|
||||
class ArkViewer : public KDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
virtual ~ArkViewer();
|
||||
virtual QSize sizeHint() const;
|
||||
|
||||
static void view(const QString& fileName, QWidget* parent = 0);
|
||||
|
||||
protected:
|
||||
virtual void keyPressEvent(QKeyEvent *event);
|
||||
|
||||
protected slots:
|
||||
void slotOpenUrlRequestDelayed(const KUrl& url, const KParts::OpenUrlArguments& arguments, const KParts::BrowserArguments& browserArguments);
|
||||
|
||||
private slots:
|
||||
void dialogClosed();
|
||||
|
||||
private:
|
||||
explicit ArkViewer(QWidget* parent = 0, Qt::WFlags flags = 0);
|
||||
|
||||
static KService::Ptr getViewer(const KMimeType::Ptr& mimeType);
|
||||
bool viewInInternalViewer(const QString& fileName, const KMimeType::Ptr& mimeType);
|
||||
|
||||
QWeakPointer<KParts::ReadOnlyPart> m_part;
|
||||
QWidget *m_widget;
|
||||
};
|
||||
|
||||
#endif // ARKVIEWER_H
|
||||
|
8
ark/part/dnddbusinterface.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.kde.ark.DndExtract">
|
||||
<method name="extractSelectedFilesTo">
|
||||
<arg direction="in" type="s" name="path" />
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
213
ark/part/infopanel.cpp
Normal file
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
|
||||
*
|
||||
* 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 "infopanel.h"
|
||||
#include "kerfuffle/archive.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
#include <QFileInfo>
|
||||
|
||||
#include <KLocale>
|
||||
#include <KMimeType>
|
||||
#include <KIconLoader>
|
||||
#include <KIO/NetAccess>
|
||||
|
||||
using namespace Kerfuffle;
|
||||
|
||||
static QPixmap getMimeIcon(const QString& mimeName)
|
||||
{
|
||||
return KIconLoader::global()->loadMimeTypeIcon(mimeName, KIconLoader::Desktop, KIconLoader::SizeHuge);
|
||||
}
|
||||
|
||||
InfoPanel::InfoPanel(ArchiveModel *model, QWidget *parent)
|
||||
: QFrame(parent), m_model(model)
|
||||
{
|
||||
setupUi(this);
|
||||
|
||||
// Make the file name font bigger than the rest
|
||||
QFont fnt = fileName->font();
|
||||
if (fnt.pointSize() > -1) {
|
||||
fnt.setPointSize(fnt.pointSize() + 1);
|
||||
} else {
|
||||
fnt.setPixelSize(fnt.pixelSize() + 3);
|
||||
}
|
||||
fileName->setFont(fnt);
|
||||
|
||||
updateWithDefaults();
|
||||
}
|
||||
|
||||
InfoPanel::~InfoPanel()
|
||||
{
|
||||
}
|
||||
|
||||
void InfoPanel::updateWithDefaults()
|
||||
{
|
||||
iconLabel->setPixmap(KIconLoader::global()->loadIcon(QLatin1String( "utilities-file-archiver" ), KIconLoader::Desktop, KIconLoader::SizeHuge));
|
||||
|
||||
const QString currentFileName = prettyFileName();
|
||||
|
||||
if (currentFileName.isEmpty()) {
|
||||
fileName->setText(i18n("No archive loaded"));
|
||||
} else {
|
||||
fileName->setText(currentFileName);
|
||||
}
|
||||
|
||||
additionalInfo->setText(QString());
|
||||
hideMetaData();
|
||||
hideActions();
|
||||
}
|
||||
|
||||
QString InfoPanel::prettyFileName() const
|
||||
{
|
||||
if (m_prettyFileName.isEmpty()) {
|
||||
if (m_model->archive()) {
|
||||
QFileInfo fileInfo(m_model->archive()->fileName());
|
||||
return fileInfo.fileName();
|
||||
}
|
||||
}
|
||||
|
||||
return m_prettyFileName;
|
||||
}
|
||||
|
||||
void InfoPanel::setPrettyFileName(const QString& fileName)
|
||||
{
|
||||
m_prettyFileName = fileName;
|
||||
}
|
||||
|
||||
void InfoPanel::setIndex(const QModelIndex& index)
|
||||
{
|
||||
if (!index.isValid()) {
|
||||
updateWithDefaults();
|
||||
} else {
|
||||
const ArchiveEntry& entry = m_model->entryForIndex(index);
|
||||
|
||||
KMimeType::Ptr mimeType;
|
||||
|
||||
if (entry[ IsDirectory ].toBool()) {
|
||||
mimeType = KMimeType::mimeType(QLatin1String( "inode/directory" ));
|
||||
} else {
|
||||
mimeType = KMimeType::findByPath(entry[ FileName ].toString(), 0, true);
|
||||
}
|
||||
|
||||
iconLabel->setPixmap(getMimeIcon(mimeType->iconName()));
|
||||
if (entry[ IsDirectory ].toBool()) {
|
||||
int dirs;
|
||||
int files;
|
||||
const int children = m_model->childCount(index, dirs, files);
|
||||
additionalInfo->setText(KIO::itemsSummaryString(children, files, dirs, 0, false));
|
||||
} else if (entry.contains(Link)) {
|
||||
additionalInfo->setText(i18n("Symbolic Link"));
|
||||
} else {
|
||||
if (entry.contains(Size)) {
|
||||
additionalInfo->setText(KIO::convertSize(entry[ Size ].toULongLong()));
|
||||
} else {
|
||||
additionalInfo->setText(i18n("Unknown size"));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const QStringList nameParts = entry[ FileName ].toString().split(QLatin1Char( '/' ), QString::SkipEmptyParts);
|
||||
const QString name = (nameParts.count() > 0) ? nameParts.last() : entry[ FileName ].toString();
|
||||
fileName->setText(name);
|
||||
|
||||
metadataLabel->setText(metadataTextFor(index));
|
||||
showMetaData();
|
||||
}
|
||||
}
|
||||
|
||||
void InfoPanel::setIndexes(const QModelIndexList &list)
|
||||
{
|
||||
if (list.size() == 0) {
|
||||
setIndex(QModelIndex());
|
||||
} else if (list.size() == 1) {
|
||||
setIndex(list[ 0 ]);
|
||||
} else {
|
||||
iconLabel->setPixmap(KIconLoader::global()->loadIcon(QLatin1String( "utilities-file-archiver" ), KIconLoader::Desktop, KIconLoader::SizeHuge));
|
||||
fileName->setText(i18np("One file selected", "%1 files selected", list.size()));
|
||||
quint64 totalSize = 0;
|
||||
foreach(const QModelIndex& index, list) {
|
||||
const ArchiveEntry& entry = m_model->entryForIndex(index);
|
||||
totalSize += entry[ Size ].toULongLong();
|
||||
}
|
||||
additionalInfo->setText(KIO::convertSize(totalSize));
|
||||
hideMetaData();
|
||||
}
|
||||
}
|
||||
|
||||
void InfoPanel::showMetaData()
|
||||
{
|
||||
firstSeparator->show();
|
||||
metadataLabel->show();
|
||||
}
|
||||
|
||||
void InfoPanel::hideMetaData()
|
||||
{
|
||||
firstSeparator->hide();
|
||||
metadataLabel->hide();
|
||||
}
|
||||
|
||||
void InfoPanel::showActions()
|
||||
{
|
||||
secondSeparator->show();
|
||||
actionsLabel->show();
|
||||
}
|
||||
|
||||
void InfoPanel::hideActions()
|
||||
{
|
||||
secondSeparator->hide();
|
||||
actionsLabel->hide();
|
||||
}
|
||||
|
||||
QString InfoPanel::metadataTextFor(const QModelIndex &index)
|
||||
{
|
||||
const ArchiveEntry& entry = m_model->entryForIndex(index);
|
||||
QString text;
|
||||
|
||||
KMimeType::Ptr mimeType;
|
||||
|
||||
if (entry[ IsDirectory ].toBool()) {
|
||||
mimeType = KMimeType::mimeType(QLatin1String( "inode/directory" ));
|
||||
} else {
|
||||
mimeType = KMimeType::findByPath(entry[ FileName ].toString(), 0, true);
|
||||
}
|
||||
|
||||
text += i18n("<b>Type:</b> %1<br/>", mimeType->comment());
|
||||
|
||||
if (entry.contains(Owner)) {
|
||||
text += i18n("<b>Owner:</b> %1<br/>", entry[ Owner ].toString());
|
||||
}
|
||||
|
||||
if (entry.contains(Group)) {
|
||||
text += i18n("<b>Group:</b> %1<br/>", entry[ Group ].toString());
|
||||
}
|
||||
|
||||
if (entry.contains(Link)) {
|
||||
text += i18n("<b>Target:</b> %1<br/>", entry[ Link ].toString());
|
||||
}
|
||||
|
||||
if (entry.contains(IsPasswordProtected) && entry[ IsPasswordProtected ].toBool()) {
|
||||
text += i18n("<b>Password protected:</b> Yes<br/>");
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
#include "infopanel.moc"
|
76
ark/part/infopanel.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
|
||||
*
|
||||
* 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 INFOPANEL_H
|
||||
#define INFOPANEL_H
|
||||
|
||||
#include "kerfuffle/archive.h"
|
||||
#include "archivemodel.h"
|
||||
#include "ui_infopanel.h"
|
||||
|
||||
#include <QFrame>
|
||||
|
||||
class InfoPanel: public QFrame, Ui::InformationPanel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit InfoPanel(ArchiveModel *model, QWidget *parent = 0);
|
||||
virtual ~InfoPanel();
|
||||
|
||||
void setIndex(const QModelIndex &);
|
||||
void setIndexes(const QModelIndexList &list);
|
||||
|
||||
/**
|
||||
* Returns the file name that is displayed on the info panel.
|
||||
*
|
||||
* @return The current file name. If no pretty name has been
|
||||
* set, it returns the name of the loaded archive.
|
||||
*/
|
||||
QString prettyFileName() const;
|
||||
|
||||
/**
|
||||
* Sets a different file name for the current open archive.
|
||||
*
|
||||
* This is particularly useful when a temporary archive (from
|
||||
* a remote location) is loaded, and the window title shows the
|
||||
* remote file name and the info panel, by default, would show
|
||||
* the name of the temporary downloaded file.
|
||||
*
|
||||
* @param fileName The new file name.
|
||||
*/
|
||||
void setPrettyFileName(const QString& fileName);
|
||||
|
||||
void updateWithDefaults();
|
||||
|
||||
private:
|
||||
void showMetaData();
|
||||
void hideMetaData();
|
||||
|
||||
void showActions();
|
||||
void hideActions();
|
||||
|
||||
QString metadataTextFor(const QModelIndex &);
|
||||
|
||||
ArchiveModel *m_model;
|
||||
QString m_prettyFileName;
|
||||
};
|
||||
|
||||
#endif // INFOPANEL_H
|
126
ark/part/infopanel.ui
Normal file
|
@ -0,0 +1,126 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>InformationPanel</class>
|
||||
<widget class="QWidget" name="InformationPanel" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>118</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Preferred" hsizetype="Maximum" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Information Panel</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="iconLabel" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="KSqueezedTextLabel" name="fileName">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">KSqueezedTextLabel</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textElideMode">
|
||||
<enum>Qt::ElideRight</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="additionalInfo" >
|
||||
<property name="text" >
|
||||
<string>Unknown file type</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="firstSeparator" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="metadataLabel" >
|
||||
<property name="text" >
|
||||
<string>Metadata Label</string>
|
||||
</property>
|
||||
<property name="margin" >
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="indent" >
|
||||
<number>20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="secondSeparator" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="actionsLabel" >
|
||||
<property name="text" >
|
||||
<string>ActionsLabel</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>KSqueezedTextLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>ksqueezedtextlabel.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
37
ark/part/interface.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
|
||||
*
|
||||
* 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 INTERFACE_H
|
||||
#define INTERFACE_H
|
||||
|
||||
#include <QStringList>
|
||||
#include <QtPlugin>
|
||||
|
||||
class Interface
|
||||
{
|
||||
public:
|
||||
virtual ~Interface() {}
|
||||
|
||||
virtual bool isBusy() const = 0;
|
||||
};
|
||||
|
||||
Q_DECLARE_INTERFACE(Interface, "org.kde.kerfuffle.partinterface/0.42")
|
||||
|
||||
#endif // INTERFACE_H
|
107
ark/part/jobtracker.cpp
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
|
||||
* Copyright (C) 2008 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
*
|
||||
* 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 "jobtracker.h"
|
||||
|
||||
#include <KDebug>
|
||||
|
||||
JobTrackerWidget::JobTrackerWidget(QWidget *parent)
|
||||
: QFrame(parent)
|
||||
{
|
||||
setupUi(this);
|
||||
}
|
||||
|
||||
JobTracker::JobTracker(QWidget *parent)
|
||||
: KAbstractWidgetJobTracker(parent)
|
||||
{
|
||||
m_ui = new JobTrackerWidget(parent);
|
||||
resetUi();
|
||||
}
|
||||
|
||||
JobTracker::~JobTracker()
|
||||
{
|
||||
foreach(KJob *job, m_jobs) {
|
||||
job->kill();
|
||||
delete job;
|
||||
}
|
||||
}
|
||||
|
||||
void JobTracker::description(KJob *job, const QString &title, const QPair< QString, QString > &f1, const QPair< QString, QString > &f2)
|
||||
{
|
||||
Q_UNUSED(job)
|
||||
Q_UNUSED(f1)
|
||||
Q_UNUSED(f2)
|
||||
m_ui->descriptionLabel->setText(QString(QLatin1String( "<b>%1</b>" )).arg(title));
|
||||
m_ui->descriptionLabel->show();
|
||||
}
|
||||
|
||||
void JobTracker::infoMessage(KJob *job, const QString &plain, const QString &rich)
|
||||
{
|
||||
Q_UNUSED(job)
|
||||
Q_UNUSED(rich)
|
||||
m_ui->informationLabel->setText(plain);
|
||||
m_ui->informationLabel->show();
|
||||
}
|
||||
|
||||
void JobTracker::warning(KJob *job, const QString &plain, const QString &rich)
|
||||
{
|
||||
Q_UNUSED(job)
|
||||
Q_UNUSED(rich)
|
||||
m_ui->informationLabel->setText(plain);
|
||||
}
|
||||
|
||||
void JobTracker::registerJob(KJob *job)
|
||||
{
|
||||
m_jobs << job;
|
||||
KJobTrackerInterface::registerJob(job);
|
||||
m_ui->show();
|
||||
m_ui->informationLabel->hide();
|
||||
m_ui->progressBar->show();
|
||||
}
|
||||
|
||||
void JobTracker::percent(KJob *job, unsigned long percent)
|
||||
{
|
||||
Q_UNUSED(job)
|
||||
m_ui->progressBar->setMaximum(100);
|
||||
m_ui->progressBar->setMinimum(0);
|
||||
m_ui->progressBar->setValue(percent);
|
||||
}
|
||||
|
||||
void JobTracker::unregisterJob(KJob *job)
|
||||
{
|
||||
m_jobs.remove(job);
|
||||
KJobTrackerInterface::unregisterJob(job);
|
||||
resetUi();
|
||||
}
|
||||
|
||||
void JobTracker::resetUi()
|
||||
{
|
||||
m_ui->hide();
|
||||
m_ui->descriptionLabel->hide();
|
||||
m_ui->informationLabel->hide();
|
||||
m_ui->progressBar->setMaximum(0);
|
||||
m_ui->progressBar->setMinimum(0);
|
||||
}
|
||||
|
||||
QWidget* JobTracker::widget(KJob *)
|
||||
{
|
||||
return m_ui;
|
||||
}
|
68
ark/part/jobtracker.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
|
||||
* Copyright (C) 2008 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
*
|
||||
* 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 JOBTRACKER_H
|
||||
#define JOBTRACKER_H
|
||||
|
||||
#include <QFrame>
|
||||
#include <kabstractwidgetjobtracker.h>
|
||||
#include "ui_jobtracker.h"
|
||||
|
||||
class KJob;
|
||||
|
||||
class JobTrackerWidget: public QFrame, public Ui::JobTrackerWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
JobTrackerWidget(QWidget *parent = 0);
|
||||
};
|
||||
|
||||
class JobTracker: public KAbstractWidgetJobTracker
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
JobTracker(QWidget *parent = 0);
|
||||
~JobTracker();
|
||||
|
||||
virtual QWidget *widget(KJob *);
|
||||
|
||||
public slots:
|
||||
virtual void registerJob(KJob *job);
|
||||
virtual void unregisterJob(KJob *job);
|
||||
|
||||
protected slots:
|
||||
virtual void description(KJob *job, const QString &title, const QPair< QString, QString > &f1, const QPair< QString, QString > &f2);
|
||||
virtual void infoMessage(KJob *job, const QString &plain, const QString &rich);
|
||||
virtual void warning(KJob *job, const QString &plain, const QString &rich);
|
||||
|
||||
virtual void percent(KJob *job, unsigned long percent);
|
||||
|
||||
private slots:
|
||||
void resetUi();
|
||||
|
||||
private:
|
||||
JobTrackerWidget *m_ui;
|
||||
QSet<KJob*> m_jobs;
|
||||
};
|
||||
|
||||
#endif // JOBTRACKER_H
|
92
ark/part/jobtracker.ui
Normal file
|
@ -0,0 +1,92 @@
|
|||
<ui version="4.0" >
|
||||
<class>JobTrackerWidget</class>
|
||||
<widget class="QWidget" name="JobTrackerWidget" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>409</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Job Tracker</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="leftMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="descriptionLabel" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string><b>Job Description</b></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="informationLabel" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Preferred" hsizetype="Expanding" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Some Information about the job</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximum" >
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
916
ark/part/part.cpp
Normal file
|
@ -0,0 +1,916 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
|
||||
* Copyright (C) 2008-2009 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
* Copyright (C) 2009-2012 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 "part.h"
|
||||
#include "archivemodel.h"
|
||||
#include "archiveview.h"
|
||||
#include "arkviewer.h"
|
||||
#include "dnddbusinterfaceadaptor.h"
|
||||
#include "infopanel.h"
|
||||
#include "jobtracker.h"
|
||||
#include "kerfuffle/archive.h"
|
||||
#include "kerfuffle/extractiondialog.h"
|
||||
#include "kerfuffle/jobs.h"
|
||||
#include "kerfuffle/settings.h"
|
||||
|
||||
#include <KAboutData>
|
||||
#include <KAction>
|
||||
#include <KActionCollection>
|
||||
#include <KApplication>
|
||||
#include <KConfigGroup>
|
||||
#include <KDebug>
|
||||
#include <KFileDialog>
|
||||
#include <KGuiItem>
|
||||
#include <KIO/Job>
|
||||
#include <KIO/NetAccess>
|
||||
#include <KIcon>
|
||||
#include <KInputDialog>
|
||||
#include <KMessageBox>
|
||||
#include <KPluginFactory>
|
||||
#include <KRun>
|
||||
#include <KSelectAction>
|
||||
#include <KStandardDirs>
|
||||
#include <KStandardGuiItem>
|
||||
#include <KTempDir>
|
||||
#include <KToggleAction>
|
||||
#include <KXMLGUIFactory>
|
||||
|
||||
#include <QAction>
|
||||
#include <QCursor>
|
||||
#include <QHeaderView>
|
||||
#include <QMenu>
|
||||
#include <QMimeData>
|
||||
#include <QMouseEvent>
|
||||
#include <QScopedPointer>
|
||||
#include <QSplitter>
|
||||
#include <QTimer>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWeakPointer>
|
||||
#include <QtDBus/QtDBus>
|
||||
|
||||
using namespace Kerfuffle;
|
||||
|
||||
K_PLUGIN_FACTORY(Factory, registerPlugin<Ark::Part>();)
|
||||
K_EXPORT_PLUGIN(Factory("ark"))
|
||||
|
||||
namespace Ark
|
||||
{
|
||||
|
||||
static quint32 s_instanceCounter = 1;
|
||||
|
||||
Part::Part(QWidget *parentWidget, QObject *parent, const QVariantList& args)
|
||||
: KParts::ReadWritePart(parent),
|
||||
m_splitter(0),
|
||||
m_busy(false),
|
||||
m_jobTracker(0)
|
||||
{
|
||||
Q_UNUSED(args)
|
||||
setComponentData(Factory::componentData(), false);
|
||||
|
||||
new DndExtractAdaptor(this);
|
||||
|
||||
const QString pathName = QString(QLatin1String("/DndExtract/%1")).arg(s_instanceCounter++);
|
||||
if (!QDBusConnection::sessionBus().registerObject(pathName, this)) {
|
||||
kFatal() << "Could not register a D-Bus object for drag'n'drop";
|
||||
}
|
||||
|
||||
m_model = new ArchiveModel(pathName, this);
|
||||
|
||||
m_splitter = new QSplitter(Qt::Horizontal, parentWidget);
|
||||
setWidget(m_splitter);
|
||||
|
||||
m_view = new ArchiveView;
|
||||
m_infoPanel = new InfoPanel(m_model);
|
||||
|
||||
m_splitter->addWidget(m_view);
|
||||
m_splitter->addWidget(m_infoPanel);
|
||||
|
||||
QList<int> splitterSizes = ArkSettings::splitterSizes();
|
||||
if (splitterSizes.isEmpty()) {
|
||||
splitterSizes.append(200);
|
||||
splitterSizes.append(100);
|
||||
}
|
||||
m_splitter->setSizes(splitterSizes);
|
||||
|
||||
setupView();
|
||||
setupActions();
|
||||
|
||||
connect(m_model, SIGNAL(loadingStarted()),
|
||||
this, SLOT(slotLoadingStarted()));
|
||||
connect(m_model, SIGNAL(loadingFinished(KJob*)),
|
||||
this, SLOT(slotLoadingFinished(KJob*)));
|
||||
connect(m_model, SIGNAL(droppedFiles(QStringList,QString)),
|
||||
this, SLOT(slotAddFiles(QStringList,QString)));
|
||||
connect(m_model, SIGNAL(error(QString,QString)),
|
||||
this, SLOT(slotError(QString,QString)));
|
||||
|
||||
connect(this, SIGNAL(busy()),
|
||||
this, SLOT(setBusyGui()));
|
||||
connect(this, SIGNAL(ready()),
|
||||
this, SLOT(setReadyGui()));
|
||||
connect(this, SIGNAL(completed()),
|
||||
this, SLOT(setFileNameFromArchive()));
|
||||
|
||||
m_statusBarExtension = new KParts::StatusBarExtension(this);
|
||||
|
||||
setXMLFile(QLatin1String( "ark_part.rc" ));
|
||||
}
|
||||
|
||||
Part::~Part()
|
||||
{
|
||||
factory()->removeClient(this);
|
||||
|
||||
saveSplitterSizes();
|
||||
|
||||
m_extractFilesAction->menu()->deleteLater();
|
||||
}
|
||||
|
||||
void Part::registerJob(KJob* job)
|
||||
{
|
||||
if (!m_jobTracker) {
|
||||
m_jobTracker = new JobTracker(widget());
|
||||
m_statusBarExtension->addStatusBarItem(m_jobTracker->widget(0), 0, true);
|
||||
m_jobTracker->widget(job)->show();
|
||||
}
|
||||
m_jobTracker->registerJob(job);
|
||||
|
||||
emit busy();
|
||||
connect(job, SIGNAL(result(KJob*)), this, SIGNAL(ready()));
|
||||
}
|
||||
|
||||
// TODO: One should construct a KUrl out of localPath in order to be able to handle
|
||||
// non-local destinations (ie. trash:/ or a remote location)
|
||||
// See bugs #189322 and #204323.
|
||||
void Part::extractSelectedFilesTo(const QString& localPath)
|
||||
{
|
||||
kDebug() << "Extract to " << localPath;
|
||||
if (!m_model) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_view->selectionModel()->selectedRows().count() != 1) {
|
||||
m_view->selectionModel()->setCurrentIndex(m_view->currentIndex(), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
|
||||
}
|
||||
if (m_view->selectionModel()->selectedRows().count() != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
QVariant internalRoot;
|
||||
kDebug() << "valid " << m_view->currentIndex().parent().isValid();
|
||||
if (m_view->currentIndex().parent().isValid()) {
|
||||
internalRoot = m_model->entryForIndex(m_view->currentIndex().parent()).value(InternalID);
|
||||
}
|
||||
|
||||
if (internalRoot.isNull()) {
|
||||
//we have the special case valid parent, but the parent does not
|
||||
//actually correspond to an item in the archive, but an automatically
|
||||
//created folder. for now, we will just use the filename of the node
|
||||
//instead, but for plugins that rely on a non-filename value as the
|
||||
//InternalId, this WILL break things. TODO find a solution
|
||||
internalRoot = m_model->entryForIndex(m_view->currentIndex().parent()).value(FileName);
|
||||
}
|
||||
|
||||
QList<QVariant> files = selectedFilesWithChildren();
|
||||
if (files.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
kDebug() << "selected files are " << files;
|
||||
Kerfuffle::ExtractionOptions options;
|
||||
options[QLatin1String( "PreservePaths" )] = true;
|
||||
if (!internalRoot.isNull()) {
|
||||
options[QLatin1String("RootNode")] = internalRoot;
|
||||
}
|
||||
|
||||
ExtractJob *job = m_model->extractFiles(files, localPath, options);
|
||||
registerJob(job);
|
||||
|
||||
connect(job, SIGNAL(result(KJob*)),
|
||||
this, SLOT(slotExtractionDone(KJob*)));
|
||||
|
||||
job->start();
|
||||
}
|
||||
|
||||
void Part::setupView()
|
||||
{
|
||||
m_view->setModel(m_model);
|
||||
|
||||
m_view->setSortingEnabled(true);
|
||||
|
||||
connect(m_view->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
|
||||
this, SLOT(updateActions()));
|
||||
connect(m_view->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
|
||||
this, SLOT(selectionChanged()));
|
||||
|
||||
//TODO: fix an actual eventhandler
|
||||
connect(m_view, SIGNAL(itemTriggered(QModelIndex)),
|
||||
this, SLOT(slotPreview(QModelIndex)));
|
||||
|
||||
connect(m_model, SIGNAL(columnsInserted(QModelIndex,int,int)),
|
||||
this, SLOT(adjustColumns()));
|
||||
}
|
||||
|
||||
void Part::setupActions()
|
||||
{
|
||||
KToggleAction *showInfoPanelAction = new KToggleAction(i18nc("@action:inmenu", "Show information panel"), this);
|
||||
actionCollection()->addAction(QLatin1String( "show-infopanel" ), showInfoPanelAction);
|
||||
showInfoPanelAction->setChecked(m_splitter->sizes().at(1) > 0);
|
||||
connect(showInfoPanelAction, SIGNAL(triggered(bool)),
|
||||
this, SLOT(slotToggleInfoPanel(bool)));
|
||||
|
||||
m_saveAsAction = KStandardAction::saveAs(this, SLOT(slotSaveAs()), actionCollection());
|
||||
|
||||
m_previewAction = actionCollection()->addAction(QLatin1String( "preview" ));
|
||||
m_previewAction->setText(i18nc("to preview a file inside an archive", "Pre&view"));
|
||||
m_previewAction->setIcon(KIcon( QLatin1String( "document-preview-archive" )));
|
||||
m_previewAction->setStatusTip(i18n("Click to preview the selected file"));
|
||||
m_previewAction->setShortcuts(QList<QKeySequence>() << Qt::Key_Return << Qt::Key_Space);
|
||||
connect(m_previewAction, SIGNAL(triggered(bool)),
|
||||
this, SLOT(slotPreview()));
|
||||
|
||||
m_extractFilesAction = actionCollection()->addAction(QLatin1String( "extract" ));
|
||||
m_extractFilesAction->setText(i18n("E&xtract"));
|
||||
m_extractFilesAction->setIcon(KIcon( QLatin1String( "archive-extract" )));
|
||||
m_extractFilesAction->setStatusTip(i18n("Click to open an extraction dialog, where you can choose to extract either all files or just the selected ones"));
|
||||
m_extractFilesAction->setShortcut(QKeySequence( QLatin1String( "Ctrl+E" ) ));
|
||||
connect(m_extractFilesAction, SIGNAL(triggered(bool)),
|
||||
this, SLOT(slotExtractFiles()));
|
||||
|
||||
m_addFilesAction = actionCollection()->addAction(QLatin1String( "add" ));
|
||||
m_addFilesAction->setIcon(KIcon( QLatin1String( "archive-insert" )));
|
||||
m_addFilesAction->setText(i18n("Add &File..."));
|
||||
m_addFilesAction->setStatusTip(i18n("Click to add files to the archive"));
|
||||
connect(m_addFilesAction, SIGNAL(triggered(bool)),
|
||||
this, SLOT(slotAddFiles()));
|
||||
|
||||
m_addDirAction = actionCollection()->addAction(QLatin1String( "add-dir" ));
|
||||
m_addDirAction->setIcon(KIcon( QLatin1String( "archive-insert-directory" )));
|
||||
m_addDirAction->setText(i18n("Add Fo&lder..."));
|
||||
m_addDirAction->setStatusTip(i18n("Click to add a folder to the archive"));
|
||||
connect(m_addDirAction, SIGNAL(triggered(bool)),
|
||||
this, SLOT(slotAddDir()));
|
||||
|
||||
m_deleteFilesAction = actionCollection()->addAction(QLatin1String( "delete" ));
|
||||
m_deleteFilesAction->setIcon(KIcon( QLatin1String( "archive-remove" )));
|
||||
m_deleteFilesAction->setText(i18n("De&lete"));
|
||||
m_deleteFilesAction->setShortcut(Qt::Key_Delete);
|
||||
m_deleteFilesAction->setStatusTip(i18n("Click to delete the selected files"));
|
||||
connect(m_deleteFilesAction, SIGNAL(triggered(bool)),
|
||||
this, SLOT(slotDeleteFiles()));
|
||||
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void Part::updateActions()
|
||||
{
|
||||
bool isWritable = m_model->archive() && (!m_model->archive()->isReadOnly());
|
||||
|
||||
m_previewAction->setEnabled(!isBusy() && (m_view->selectionModel()->selectedRows().count() == 1)
|
||||
&& isPreviewable(m_view->selectionModel()->currentIndex()));
|
||||
m_extractFilesAction->setEnabled(!isBusy() && (m_model->rowCount() > 0));
|
||||
m_addFilesAction->setEnabled(!isBusy() && isWritable);
|
||||
m_addDirAction->setEnabled(!isBusy() && isWritable);
|
||||
m_deleteFilesAction->setEnabled(!isBusy() && (m_view->selectionModel()->selectedRows().count() > 0)
|
||||
&& isWritable);
|
||||
|
||||
QMenu *menu = m_extractFilesAction->menu();
|
||||
if (!menu) {
|
||||
menu = new QMenu;
|
||||
m_extractFilesAction->setMenu(menu);
|
||||
connect(menu, SIGNAL(triggered(QAction*)),
|
||||
this, SLOT(slotQuickExtractFiles(QAction*)));
|
||||
|
||||
// Remember to keep this action's properties as similar to
|
||||
// m_extractFilesAction's as possible (except where it does not make
|
||||
// sense, such as the text or the shortcut).
|
||||
QAction *extractTo = menu->addAction(i18n("Extract To..."));
|
||||
extractTo->setIcon(m_extractFilesAction->icon());
|
||||
extractTo->setStatusTip(m_extractFilesAction->statusTip());
|
||||
connect(extractTo, SIGNAL(triggered(bool)), SLOT(slotExtractFiles()));
|
||||
|
||||
menu->addSeparator();
|
||||
|
||||
QAction *header = menu->addAction(i18n("Quick Extract To..."));
|
||||
header->setEnabled(false);
|
||||
header->setIcon(KIcon( QLatin1String( "archive-extract" )));
|
||||
}
|
||||
|
||||
while (menu->actions().size() > 3) {
|
||||
menu->removeAction(menu->actions().last());
|
||||
}
|
||||
|
||||
const KConfigGroup conf(KGlobal::config(), "DirSelect Dialog");
|
||||
const QStringList dirHistory = conf.readPathEntry("History Items", QStringList());
|
||||
|
||||
for (int i = 0; i < qMin(10, dirHistory.size()); ++i) {
|
||||
const KUrl dirUrl(dirHistory.at(i));
|
||||
QAction *newAction = menu->addAction(dirUrl.pathOrUrl());
|
||||
newAction->setData(dirUrl.pathOrUrl());
|
||||
}
|
||||
}
|
||||
|
||||
void Part::slotQuickExtractFiles(QAction *triggeredAction)
|
||||
{
|
||||
// #190507: triggeredAction->data.isNull() means it's the "Extract to..."
|
||||
// action, and we do not want it to run here
|
||||
if (!triggeredAction->data().isNull()) {
|
||||
kDebug() << "Extract to " << triggeredAction->data().toString();
|
||||
|
||||
const QString userDestination = triggeredAction->data().toString();
|
||||
QString finalDestinationDirectory;
|
||||
const QString detectedSubfolder = detectSubfolder();
|
||||
|
||||
if (!isSingleFolderArchive()) {
|
||||
finalDestinationDirectory = userDestination +
|
||||
QDir::separator() + detectedSubfolder;
|
||||
QDir(userDestination).mkdir(detectedSubfolder);
|
||||
} else {
|
||||
finalDestinationDirectory = userDestination;
|
||||
}
|
||||
|
||||
Kerfuffle::ExtractionOptions options;
|
||||
options[QLatin1String( "PreservePaths" )] = true;
|
||||
QList<QVariant> files = selectedFiles();
|
||||
ExtractJob *job = m_model->extractFiles(files, finalDestinationDirectory, options);
|
||||
registerJob(job);
|
||||
|
||||
connect(job, SIGNAL(result(KJob*)),
|
||||
this, SLOT(slotExtractionDone(KJob*)));
|
||||
|
||||
job->start();
|
||||
}
|
||||
}
|
||||
|
||||
bool Part::isPreviewable(const QModelIndex& index) const
|
||||
{
|
||||
return index.isValid() && (!m_model->entryForIndex(index)[ IsDirectory ].toBool());
|
||||
}
|
||||
|
||||
void Part::selectionChanged()
|
||||
{
|
||||
m_infoPanel->setIndexes(m_view->selectionModel()->selectedRows());
|
||||
}
|
||||
|
||||
KAboutData* Part::createAboutData()
|
||||
{
|
||||
return new KAboutData("ark", 0, ki18n("ArkPart"), "3.0");
|
||||
}
|
||||
|
||||
bool Part::openFile()
|
||||
{
|
||||
const QString localFile(localFilePath());
|
||||
const QFileInfo localFileInfo(localFile);
|
||||
const bool creatingNewArchive =
|
||||
arguments().metaData()[QLatin1String("createNewArchive")] == QLatin1String("true");
|
||||
|
||||
if (localFileInfo.isDir()) {
|
||||
KMessageBox::error(NULL, i18nc("@info",
|
||||
"<filename>%1</filename> is a directory.",
|
||||
localFile));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (creatingNewArchive) {
|
||||
if (localFileInfo.exists()) {
|
||||
int overwrite = KMessageBox::questionYesNo(NULL, i18nc("@info", "The archive <filename>%1</filename> already exists. Would you like to open it instead?", localFile), i18nc("@title:window", "File Exists"), KGuiItem(i18n("Open File")), KStandardGuiItem::cancel());
|
||||
|
||||
if (overwrite == KMessageBox::No) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!localFileInfo.exists()) {
|
||||
KMessageBox::sorry(NULL, i18nc("@info", "The archive <filename>%1</filename> was not found.", localFile), i18nc("@title:window", "Error Opening Archive"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
QScopedPointer<Kerfuffle::Archive> archive(Kerfuffle::Archive::create(localFile, m_model));
|
||||
|
||||
if ((!archive) || ((creatingNewArchive) && (archive->isReadOnly()))) {
|
||||
QStringList mimeTypeList;
|
||||
QHash<QString, QString> mimeTypes;
|
||||
|
||||
if (creatingNewArchive) {
|
||||
mimeTypeList = Kerfuffle::supportedWriteMimeTypes();
|
||||
} else {
|
||||
mimeTypeList = Kerfuffle::supportedMimeTypes();
|
||||
}
|
||||
|
||||
foreach(const QString& mime, mimeTypeList) {
|
||||
KMimeType::Ptr mimePtr(KMimeType::mimeType(mime));
|
||||
if (mimePtr) {
|
||||
// Key = "application/zip", Value = "Zip Archive"
|
||||
mimeTypes[mime] = mimePtr->comment();
|
||||
}
|
||||
}
|
||||
|
||||
QStringList mimeComments(mimeTypes.values());
|
||||
mimeComments.sort();
|
||||
|
||||
bool ok;
|
||||
QString item;
|
||||
|
||||
if (creatingNewArchive) {
|
||||
item = KInputDialog::getItem(i18nc("@title:window", "Invalid Archive Type"),
|
||||
i18nc("@info", "Ark cannot create archives of the type you have chosen.<nl/><nl/>Please choose another archive type below."),
|
||||
mimeComments, 0, false, &ok);
|
||||
} else {
|
||||
item = KInputDialog::getItem(i18nc("@title:window", "Unable to Determine Archive Type"),
|
||||
i18nc("@info", "Ark was unable to determine the archive type of the filename.<nl/><nl/>Please choose the correct archive type below."),
|
||||
mimeComments,
|
||||
0,
|
||||
false,
|
||||
&ok);
|
||||
}
|
||||
|
||||
if ((!ok) || (item.isEmpty())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
archive.reset(Kerfuffle::Archive::create(localFile, mimeTypes.key(item), m_model));
|
||||
}
|
||||
|
||||
if (!archive) {
|
||||
KMessageBox::sorry(NULL, i18nc("@info", "Ark was not able to open the archive <filename>%1</filename>. No plugin capable of handling the file was found.", localFile), i18nc("@title:window", "Error Opening Archive"));
|
||||
return false;
|
||||
}
|
||||
|
||||
KJob *job = m_model->setArchive(archive.take());
|
||||
registerJob(job);
|
||||
job->start();
|
||||
m_infoPanel->setIndex(QModelIndex());
|
||||
|
||||
if (arguments().metaData()[QLatin1String( "showExtractDialog" )] == QLatin1String( "true" )) {
|
||||
QTimer::singleShot(0, this, SLOT(slotExtractFiles()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Part::saveFile()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Part::isBusy() const
|
||||
{
|
||||
return m_busy;
|
||||
}
|
||||
|
||||
void Part::slotLoadingStarted()
|
||||
{
|
||||
}
|
||||
|
||||
void Part::slotLoadingFinished(KJob *job)
|
||||
{
|
||||
kDebug();
|
||||
|
||||
if (job->error()) {
|
||||
if (arguments().metaData()[QLatin1String( "createNewArchive" )] != QLatin1String( "true" )) {
|
||||
KMessageBox::sorry(NULL, i18nc("@info", "Loading the archive <filename>%1</filename> failed with the following error: <message>%2</message>", localFilePath(), job->errorText()), i18nc("@title:window", "Error Opening Archive"));
|
||||
|
||||
// The file failed to open, so reset the open archive, info panel and caption.
|
||||
m_model->setArchive(NULL);
|
||||
|
||||
m_infoPanel->setPrettyFileName(QString());
|
||||
m_infoPanel->updateWithDefaults();
|
||||
|
||||
emit setWindowCaption(QString());
|
||||
}
|
||||
}
|
||||
|
||||
m_view->sortByColumn(0, Qt::AscendingOrder);
|
||||
m_view->expandToDepth(0);
|
||||
|
||||
// After loading all files, resize the columns to fit all fields
|
||||
m_view->header()->resizeSections(QHeaderView::ResizeToContents);
|
||||
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void Part::setReadyGui()
|
||||
{
|
||||
kDebug();
|
||||
QApplication::restoreOverrideCursor();
|
||||
m_busy = false;
|
||||
m_view->setEnabled(true);
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void Part::setBusyGui()
|
||||
{
|
||||
kDebug();
|
||||
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
||||
m_busy = true;
|
||||
m_view->setEnabled(false);
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void Part::setFileNameFromArchive()
|
||||
{
|
||||
const QString prettyName = url().fileName();
|
||||
|
||||
m_infoPanel->setPrettyFileName(prettyName);
|
||||
m_infoPanel->updateWithDefaults();
|
||||
|
||||
emit setWindowCaption(prettyName);
|
||||
}
|
||||
|
||||
void Part::slotPreview()
|
||||
{
|
||||
slotPreview(m_view->selectionModel()->currentIndex());
|
||||
}
|
||||
|
||||
void Part::slotPreview(const QModelIndex & index)
|
||||
{
|
||||
if (!isPreviewable(index)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ArchiveEntry& entry = m_model->entryForIndex(index);
|
||||
|
||||
if (!entry.isEmpty()) {
|
||||
Kerfuffle::ExtractionOptions options;
|
||||
options[QLatin1String( "PreservePaths" )] = true;
|
||||
|
||||
ExtractJob *job = m_model->extractFile(entry[ InternalID ], m_previewDir.name(), options);
|
||||
registerJob(job);
|
||||
connect(job, SIGNAL(result(KJob*)),
|
||||
this, SLOT(slotPreviewExtracted(KJob*)));
|
||||
job->start();
|
||||
}
|
||||
}
|
||||
|
||||
void Part::slotPreviewExtracted(KJob *job)
|
||||
{
|
||||
// FIXME: the error checking here isn't really working
|
||||
// if there's an error or an overwrite dialog,
|
||||
// the preview dialog will be launched anyway
|
||||
if (!job->error()) {
|
||||
const ArchiveEntry& entry =
|
||||
m_model->entryForIndex(m_view->selectionModel()->currentIndex());
|
||||
|
||||
QString fullName =
|
||||
m_previewDir.name() + QLatin1Char('/') + entry[FileName].toString();
|
||||
|
||||
// Make sure a maliciously crafted archive with parent folders named ".." do
|
||||
// not cause the previewed file path to be located outside the temporary
|
||||
// directory, resulting in a directory traversal issue.
|
||||
fullName.remove(QLatin1String("../"));
|
||||
|
||||
ArkViewer::view(fullName, widget());
|
||||
} else {
|
||||
KMessageBox::error(widget(), job->errorString());
|
||||
}
|
||||
setReadyGui();
|
||||
}
|
||||
|
||||
void Part::slotError(const QString& errorMessage, const QString& details)
|
||||
{
|
||||
if (details.isEmpty()) {
|
||||
KMessageBox::error(widget(), errorMessage);
|
||||
} else {
|
||||
KMessageBox::detailedError(widget(), errorMessage, details);
|
||||
}
|
||||
}
|
||||
|
||||
bool Part::isSingleFolderArchive() const
|
||||
{
|
||||
return m_model->archive()->isSingleFolderArchive();
|
||||
}
|
||||
|
||||
QString Part::detectSubfolder() const
|
||||
{
|
||||
if (!m_model) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return m_model->archive()->subfolderName();
|
||||
}
|
||||
|
||||
void Part::slotExtractFiles()
|
||||
{
|
||||
if (!m_model) {
|
||||
return;
|
||||
}
|
||||
|
||||
QWeakPointer<Kerfuffle::ExtractionDialog> dialog = new Kerfuffle::ExtractionDialog;
|
||||
|
||||
if (m_view->selectionModel()->selectedRows().count() > 0) {
|
||||
dialog.data()->setShowSelectedFiles(true);
|
||||
}
|
||||
|
||||
dialog.data()->setSingleFolderArchive(isSingleFolderArchive());
|
||||
dialog.data()->setSubfolder(detectSubfolder());
|
||||
|
||||
dialog.data()->setCurrentUrl(QFileInfo(m_model->archive()->fileName()).path());
|
||||
|
||||
if (dialog.data()->exec()) {
|
||||
//this is done to update the quick extract menu
|
||||
updateActions();
|
||||
|
||||
QVariantList files;
|
||||
|
||||
//if the user has chosen to extract only selected entries, fetch these
|
||||
//from the listview
|
||||
if (!dialog.data()->extractAllFiles()) {
|
||||
files = selectedFilesWithChildren();
|
||||
}
|
||||
|
||||
kDebug() << "Selected " << files;
|
||||
|
||||
Kerfuffle::ExtractionOptions options;
|
||||
|
||||
if (dialog.data()->preservePaths()) {
|
||||
options[QLatin1String("PreservePaths")] = true;
|
||||
}
|
||||
|
||||
options[QLatin1String("FollowExtractionDialogSettings")] = true;
|
||||
|
||||
const QString destinationDirectory = dialog.data()->destinationDirectory().pathOrUrl();
|
||||
ExtractJob *job = m_model->extractFiles(files, destinationDirectory, options);
|
||||
registerJob(job);
|
||||
|
||||
connect(job, SIGNAL(result(KJob*)),
|
||||
this, SLOT(slotExtractionDone(KJob*)));
|
||||
|
||||
job->start();
|
||||
}
|
||||
|
||||
delete dialog.data();
|
||||
}
|
||||
|
||||
QList<QVariant> Part::selectedFilesWithChildren()
|
||||
{
|
||||
Q_ASSERT(m_model);
|
||||
|
||||
QModelIndexList toIterate = m_view->selectionModel()->selectedRows();
|
||||
|
||||
for (int i = 0; i < toIterate.size(); ++i) {
|
||||
QModelIndex index = toIterate.at(i);
|
||||
|
||||
for (int j = 0; j < m_model->rowCount(index); ++j) {
|
||||
QModelIndex child = m_model->index(j, 0, index);
|
||||
if (!toIterate.contains(child)) {
|
||||
toIterate << child;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QVariantList ret;
|
||||
foreach(const QModelIndex & index, toIterate) {
|
||||
const ArchiveEntry& entry = m_model->entryForIndex(index);
|
||||
if (entry.contains(InternalID)) {
|
||||
ret << entry[ InternalID ];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QList<QVariant> Part::selectedFiles()
|
||||
{
|
||||
QStringList toSort;
|
||||
|
||||
foreach(const QModelIndex & index, m_view->selectionModel()->selectedRows()) {
|
||||
const ArchiveEntry& entry = m_model->entryForIndex(index);
|
||||
toSort << entry[ InternalID ].toString();
|
||||
}
|
||||
|
||||
toSort.sort();
|
||||
QVariantList ret;
|
||||
foreach(const QString &i, toSort) {
|
||||
ret << i;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Part::slotExtractionDone(KJob* job)
|
||||
{
|
||||
kDebug();
|
||||
if (job->error()) {
|
||||
KMessageBox::error(widget(), job->errorString());
|
||||
} else {
|
||||
ExtractJob *extractJob = qobject_cast<ExtractJob*>(job);
|
||||
Q_ASSERT(extractJob);
|
||||
|
||||
const bool followExtractionDialogSettings =
|
||||
extractJob->extractionOptions().value(QLatin1String("FollowExtractionDialogSettings"), false).toBool();
|
||||
if (!followExtractionDialogSettings) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ArkSettings::openDestinationFolderAfterExtraction()) {
|
||||
|
||||
KUrl destinationDirectory(extractJob->destinationDirectory());
|
||||
destinationDirectory.cleanPath();
|
||||
|
||||
KRun::runUrl(destinationDirectory, QLatin1String("inode/directory"), widget());
|
||||
}
|
||||
|
||||
if (ArkSettings::closeAfterExtraction()) {
|
||||
emit quit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Part::adjustColumns()
|
||||
{
|
||||
kDebug();
|
||||
|
||||
m_view->header()->setResizeMode(0, QHeaderView::ResizeToContents);
|
||||
}
|
||||
|
||||
void Part::slotAddFiles(const QStringList& filesToAdd, const QString& path)
|
||||
{
|
||||
if (filesToAdd.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
kDebug() << "Adding " << filesToAdd << " to " << path;
|
||||
kDebug() << "Warning, for now the path argument is not implemented";
|
||||
|
||||
QStringList cleanFilesToAdd(filesToAdd);
|
||||
for (int i = 0; i < cleanFilesToAdd.size(); ++i) {
|
||||
QString& file = cleanFilesToAdd[i];
|
||||
if (QFileInfo(file).isDir()) {
|
||||
if (!file.endsWith(QLatin1Char( '/' ))) {
|
||||
file += QLatin1Char( '/' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CompressionOptions options;
|
||||
|
||||
QString firstPath = cleanFilesToAdd.first();
|
||||
if (firstPath.right(1) == QLatin1String( "/" )) {
|
||||
firstPath.chop(1);
|
||||
}
|
||||
firstPath = QFileInfo(firstPath).dir().absolutePath();
|
||||
|
||||
kDebug() << "Detected relative path to be " << firstPath;
|
||||
options[QLatin1String( "GlobalWorkDir" )] = firstPath;
|
||||
|
||||
AddJob *job = m_model->addFiles(cleanFilesToAdd, options);
|
||||
if (!job) {
|
||||
return;
|
||||
}
|
||||
|
||||
connect(job, SIGNAL(result(KJob*)),
|
||||
this, SLOT(slotAddFilesDone(KJob*)));
|
||||
registerJob(job);
|
||||
job->start();
|
||||
}
|
||||
|
||||
void Part::slotAddFiles()
|
||||
{
|
||||
kDebug();
|
||||
|
||||
// #264819: passing widget() as the parent will not work as expected.
|
||||
// KFileDialog will create a KFileWidget, which runs an internal
|
||||
// event loop to stat the given directory. This, in turn, leads to
|
||||
// events being delivered to widget(), which is a QSplitter, which
|
||||
// in turn reimplements childEvent() and will end up calling
|
||||
// QWidget::show() on the KFileDialog (thus showing it in a
|
||||
// non-modal state).
|
||||
// When KFileDialog::exec() is called, the widget is already shown
|
||||
// and nothing happens.
|
||||
const QStringList filesToAdd =
|
||||
KFileDialog::getOpenFileNames(KUrl("kfiledialog:///ArkAddFiles"),
|
||||
QString(), widget()->parentWidget(),
|
||||
i18nc("@title:window", "Add Files"));
|
||||
|
||||
slotAddFiles(filesToAdd);
|
||||
}
|
||||
|
||||
void Part::slotAddDir()
|
||||
{
|
||||
kDebug();
|
||||
const QString dirToAdd = KFileDialog::getExistingDirectory(KUrl("kfiledialog:///ArkAddFiles"), widget(), i18nc("@title:window", "Add Folder"));
|
||||
|
||||
if (!dirToAdd.isEmpty()) {
|
||||
slotAddFiles(QStringList() << dirToAdd);
|
||||
}
|
||||
}
|
||||
|
||||
void Part::slotAddFilesDone(KJob* job)
|
||||
{
|
||||
kDebug();
|
||||
if (job->error()) {
|
||||
KMessageBox::error(widget(), job->errorString());
|
||||
}
|
||||
}
|
||||
|
||||
void Part::slotDeleteFilesDone(KJob* job)
|
||||
{
|
||||
kDebug();
|
||||
if (job->error()) {
|
||||
KMessageBox::error(widget(), job->errorString());
|
||||
}
|
||||
}
|
||||
|
||||
void Part::slotDeleteFiles()
|
||||
{
|
||||
kDebug();
|
||||
|
||||
const int reallyDelete =
|
||||
KMessageBox::questionYesNo(NULL,
|
||||
i18n("Deleting these files is not undoable. Are you sure you want to do this?"),
|
||||
i18nc("@title:window", "Delete files"),
|
||||
KStandardGuiItem::del(),
|
||||
KStandardGuiItem::cancel(),
|
||||
QString(),
|
||||
KMessageBox::Dangerous | KMessageBox::Notify);
|
||||
|
||||
if (reallyDelete == KMessageBox::No) {
|
||||
return;
|
||||
}
|
||||
|
||||
DeleteJob *job = m_model->deleteFiles(selectedFilesWithChildren());
|
||||
connect(job, SIGNAL(result(KJob*)),
|
||||
this, SLOT(slotDeleteFilesDone(KJob*)));
|
||||
registerJob(job);
|
||||
job->start();
|
||||
}
|
||||
|
||||
void Part::slotToggleInfoPanel(bool visible)
|
||||
{
|
||||
QList<int> splitterSizes;
|
||||
|
||||
if (visible) {
|
||||
splitterSizes = ArkSettings::splitterSizesWithBothWidgets();
|
||||
} else {
|
||||
splitterSizes = m_splitter->sizes();
|
||||
ArkSettings::setSplitterSizesWithBothWidgets(splitterSizes);
|
||||
splitterSizes[1] = 0;
|
||||
}
|
||||
|
||||
m_splitter->setSizes(splitterSizes);
|
||||
saveSplitterSizes();
|
||||
}
|
||||
|
||||
void Part::saveSplitterSizes()
|
||||
{
|
||||
ArkSettings::setSplitterSizes(m_splitter->sizes());
|
||||
ArkSettings::self()->writeConfig();
|
||||
}
|
||||
|
||||
void Part::slotSaveAs()
|
||||
{
|
||||
KUrl saveUrl = KFileDialog::getSaveUrl(KUrl(QLatin1String( "kfiledialog:///ArkSaveAs/" ) + url().fileName()), QString(), widget());
|
||||
|
||||
if ((saveUrl.isValid()) && (!saveUrl.isEmpty())) {
|
||||
if (KIO::NetAccess::exists(saveUrl, KIO::NetAccess::DestinationSide, widget())) {
|
||||
int overwrite = KMessageBox::warningContinueCancel(widget(),
|
||||
i18nc("@info", "An archive named <filename>%1</filename> already exists. Are you sure you want to overwrite it?", saveUrl.fileName()),
|
||||
QString(),
|
||||
KStandardGuiItem::overwrite());
|
||||
|
||||
if (overwrite != KMessageBox::Continue) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
KUrl srcUrl = KUrl::fromPath(localFilePath());
|
||||
|
||||
if (!QFile::exists(localFilePath())) {
|
||||
if (url().isLocalFile()) {
|
||||
KMessageBox::error(widget(),
|
||||
i18nc("@info", "The archive <filename>%1</filename> cannot be copied to the specified location. The archive does not exist anymore.", localFilePath()));
|
||||
|
||||
return;
|
||||
} else {
|
||||
srcUrl = url();
|
||||
}
|
||||
}
|
||||
|
||||
KIO::Job *copyJob = KIO::file_copy(srcUrl, saveUrl, -1, KIO::Overwrite);
|
||||
|
||||
if (!KIO::NetAccess::synchronousRun(copyJob, widget())) {
|
||||
KMessageBox::error(widget(),
|
||||
i18nc("@info", "The archive could not be saved as <filename>%1</filename>. Try saving it to another location.", saveUrl.pathOrUrl()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Ark
|
126
ark/part/part.h
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* ark -- archiver for the KDE project
|
||||
*
|
||||
* Copyright (C) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
|
||||
* Copyright (C) 2008-2009 Harald Hvaal <haraldhv@stud.ntnu.no>
|
||||
* Copyright (C) 2009 Raphael Kubo da Costa <rakuco@FreeBSD.org>
|
||||
*
|
||||
* 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 PART_H
|
||||
#define PART_H
|
||||
|
||||
#include "interface.h"
|
||||
|
||||
#include <KParts/Part>
|
||||
#include <KParts/StatusBarExtension>
|
||||
#include <KTempDir>
|
||||
|
||||
#include <QModelIndex>
|
||||
|
||||
class ArchiveModel;
|
||||
class InfoPanel;
|
||||
|
||||
class KAbstractWidgetJobTracker;
|
||||
class KAboutData;
|
||||
class KAction;
|
||||
class KJob;
|
||||
|
||||
class QAction;
|
||||
class QSplitter;
|
||||
class QTreeView;
|
||||
|
||||
namespace Ark
|
||||
{
|
||||
|
||||
class Part: public KParts::ReadWritePart, public Interface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Interface)
|
||||
public:
|
||||
Part(QWidget *parentWidget, QObject *parent, const QVariantList &);
|
||||
~Part();
|
||||
static KAboutData* createAboutData();
|
||||
|
||||
virtual bool openFile();
|
||||
virtual bool saveFile();
|
||||
|
||||
bool isBusy() const;
|
||||
|
||||
public slots:
|
||||
void extractSelectedFilesTo(const QString& localPath);
|
||||
|
||||
private slots:
|
||||
void slotLoadingStarted();
|
||||
void slotLoadingFinished(KJob *job);
|
||||
void slotPreview();
|
||||
void slotPreview(const QModelIndex & index);
|
||||
void slotPreviewExtracted(KJob*);
|
||||
void slotError(const QString& errorMessage, const QString& details);
|
||||
void slotExtractFiles();
|
||||
void slotExtractionDone(KJob*);
|
||||
void slotQuickExtractFiles(QAction*);
|
||||
void slotAddFiles();
|
||||
void slotAddFiles(const QStringList& files, const QString& path = QString());
|
||||
void slotAddDir();
|
||||
void slotAddFilesDone(KJob*);
|
||||
void slotDeleteFiles();
|
||||
void slotDeleteFilesDone(KJob*);
|
||||
void saveSplitterSizes();
|
||||
void slotToggleInfoPanel(bool);
|
||||
void slotSaveAs();
|
||||
void updateActions();
|
||||
void selectionChanged();
|
||||
void adjustColumns();
|
||||
void setBusyGui();
|
||||
void setReadyGui();
|
||||
void setFileNameFromArchive();
|
||||
|
||||
signals:
|
||||
void busy();
|
||||
void ready();
|
||||
void quit();
|
||||
|
||||
private:
|
||||
void setupView();
|
||||
void setupActions();
|
||||
bool isSingleFolderArchive() const;
|
||||
QString detectSubfolder() const;
|
||||
bool isPreviewable(const QModelIndex& index) const;
|
||||
QList<QVariant> selectedFiles();
|
||||
QList<QVariant> selectedFilesWithChildren();
|
||||
void registerJob(KJob *job);
|
||||
|
||||
ArchiveModel *m_model;
|
||||
QTreeView *m_view;
|
||||
KAction *m_previewAction;
|
||||
KAction *m_extractFilesAction;
|
||||
KAction *m_addFilesAction;
|
||||
KAction *m_addDirAction;
|
||||
KAction *m_deleteFilesAction;
|
||||
KAction *m_saveAsAction;
|
||||
InfoPanel *m_infoPanel;
|
||||
QSplitter *m_splitter;
|
||||
KTempDir m_previewDir;
|
||||
bool m_busy;
|
||||
|
||||
KAbstractWidgetJobTracker *m_jobTracker;
|
||||
KParts::StatusBarExtension *m_statusBarExtension;
|
||||
};
|
||||
|
||||
} // namespace Ark
|
||||
|
||||
#endif // PART_H
|
21
ark/plugins/CLI-README
Normal file
|
@ -0,0 +1,21 @@
|
|||
In this folder is a general template of what one needs to implement
|
||||
support for a plugin using the cli interface in ark.
|
||||
|
||||
Here are the steps.
|
||||
|
||||
1. First, create a copy of the cliplugin folder
|
||||
2. Change plugins/CMakeLists.txt to include the new subfolder
|
||||
3. Rename the kerfuffle_cli.desktop to a unique name, for example
|
||||
kerfuffle_rar.desktop.
|
||||
4. Fill in the parts in the desktop marked with TODO
|
||||
5. Update the plugins/yourplugin/CMakeLists.txt file, replacing all
|
||||
instances of kerfuffle_cli with kerfuffle_yourplugin (where yourplugin
|
||||
must be a unique plugin name)
|
||||
6. Implement/modify cliplugin.cpp to fit your archive type.
|
||||
Refer to kerfuffle/cliinterface.h for explanations on the values that
|
||||
needs to be implemented. The class name does not need to be changed
|
||||
|
||||
Then finally, email the plugin to the ark maintainer for a code review before
|
||||
it is committed to trunk :D
|
||||
|
||||
Have fun
|