diff --git a/doc/advanced-functions.docbook b/doc/advanced-functions.docbook
index fda54577..6f4c9870 100644
--- a/doc/advanced-functions.docbook
+++ b/doc/advanced-functions.docbook
@@ -1,60 +1,60 @@
Advanced functions
&vfs;
&compare;
&occupied-space;
&splitter;
&checksum;
Send Files by EmailSelect a file and use
Right-Click menuSend by Email.
Selecting this option will open a new
&kmail; window with the file already attached. Just
fill in the subject and recipient(s) and send it. Of course,
&kmail; must be properly configured.
&profiles;
ACL permissions
ACL permissions are fully
supported when using properties, preserve attributes and the
synchronizer. To view/modify the ACL permissions, select a file
and use the Context Menu:
- Properties
+ Properties...PermissionsAdvanced permissions.
At Copy/Move, the ACL
permissions are also copied. The synchronizer keeps the ACL
permissions as well.
diff --git a/doc/archives.docbook b/doc/archives.docbook
index a7a4dad6..b1643aa1 100644
--- a/doc/archives.docbook
+++ b/doc/archives.docbook
@@ -1,144 +1,143 @@
Archive HandlingArchivesBrowsing ArchivesThe Virtual file systems (VFS) allows you to browse archives as
if it was a directory. Currently &krusader; supports
the following archives types: ace, arj, bzip2, deb, gzip, iso,
lha, rar, rpm, tar, xz, zip, and 7-zip and supports the following
passworded archives: arj, ace, rar and zip. Passwords can be
- stored in Kwallet. Please note that the archive
+ stored in KWallet. Please note that the archive
support first needs to be properly
configured in
- Konfigurator. To open the archive, use &Enter;,
- (double-)click or the
- Right Arrow. &krusader; supports
+ Konfigurator. To open the archive, use &Enter; key,
+ (double-)click or the &Right; key. &krusader; supports
also
hidden archives, these are
renamed archives with a *wrong* extension, ⪚
OpenOffice uses zip archives with the following
extensions: .odt,
.sxw and .odw.
&Enter; will open the
OpenOffice document and the
- Right Arrow will open the archive. Another
+ &Right; key will open the archive. Another
example is J2EE, where the .jar extension means a zip archive.
Since &krusader; auto-detects the supported archive
types, it will open with
- Right Arrow even if it has another MIME type.
+ &Right; key even if it has another &MIME; type.
Please note that browsing archives has a few limitations:
Not all functions are supported by all archive types.
(&ie;: you can not delete files in ace or rar
archives)The permissions you have inside the archive are the
same as the permissions you have for the archive.The command line (if visible) will not follow you
inside the archive but will point to the archive
directory.Before any action is performed on files/directories
inside the archive, they must be extracted. The archive
will be repacked when you leave it or when
&krusader; detects that extracted files have
changed.
- Packing and un-packing are "blocking operations" that
+ Packing and un-packing are blocking operations that
display a progress dialog. However, this might change in
the future since we are planning to create more background
operations.Unpack FilesThere are 2 ways to extract files from archives:If you want to unpack a whole archive(s), browse to the
archive location, select the archive(s) and select
FileUnpack
or
&Alt;&Shift;
U. &krusader; will ask
you where to put the extracted files. The default location is
the inactive panel directory. If you do not cancel the
operation, &krusader; will try to unpack all the
selected files in the inactive panel.If you only want to extract a part of the archive, then
browse the archive and
copy the files you want to extract to their new location just
- as you would copy "normal" files. Note that unpacking from a
+ as you would copy normal files. Note that unpacking from a
browsed archive takes more time (file by file unpack) compared
to unpacking a whole archive with the first method.
The unpack operation can be put in a queue.Packing FilesIf you want to create a new archive, begin by selecting
the elements you want to pack in the active panel and select
File
- Pack
+ Pack...
or
&Alt;&Shift;
P. A dialog will pop-up prompting
you to select the archive name and location. Select the packer
from one of the
supported file name
extensions.To add files to an existing archive(s), open the archive
in one panel and the files to be copied in the other panel,
then simply copy the files into the archive in exactly the same
- way you copy files into a "normal" directory.
+ way you copy files into a normal directory.
The pack operation can be put in a queue.Testing Archives&krusader; will not handle corrupted archives since it may
result in data loss. If you receive an error message when
opening an archive, or if you suspect that there is something
wrong with the archive, you should test it before use. To test
an archive, browse (navigate) to the archive location and
select the archive. Next select
FileTest Archive
or
&Alt;
E. &krusader; will test
the archive file and inform you whether the archive passed or
failed the file integrity test.
diff --git a/doc/basic-functions.docbook b/doc/basic-functions.docbook
index 2ce42d1e..58d75941 100644
--- a/doc/basic-functions.docbook
+++ b/doc/basic-functions.docbook
@@ -1,451 +1,448 @@
Basic FunctionsControlsGeneralThis is a rather short but important section that will
go into the details of controlling &krusader;.
This section does not try to cover all the various key
combinations for two reasons:
there are just too many of themmost of &krusader; actions are
configurable in the
Konfigurator Panel pageWe will only mention the most important
keyboard shortcuts with the default configuration, but keep
in mind that most of the Key-Bindings are
configurable. If you find that you use a certain command a
lot and want to know the shortcut for this command, or you
want to change this command shortcut, then check out the
Configure Shortcuts window (SettingsConfigure Shortcuts...).Moving AroundBy Moving Around we mean the transfer of the keyboard
and mouse focus between the different parts of the
&krusader;
main window. The focus can
be in one of five places: the Left or Right Panel, the Menu
Bar, the Command Line or the Terminal Emulator. The panel
that has the focus is called the Active Panel. An Active
Panel will remain active until the other panel receives the
focus (&ie;: if the Left Panel was active and you
clicked on the Command Line - then the Left Panel remains the
Active Panel). You must deliberately change which panel is
active.The most common way to transfer the focus to a specific
panel is to use the mouse to click on that panel. But you
should be aware of the following:
Clicking on the Toolbar, the FN keys bar or the
Status Bar does not change the focus.Pushing the
Run in Terminal Mode button in the
Command Line will not transfer the focus, so you have to
click inside the Input Line.When you choose a menu, the Menu Bar will become
focused. It remains focused until you choose a command -
the focus returns to the previous owner.There are, of course, ways to use the keyboard to
change the focus:
The 	 Key will switch panels, if one
of the panels has the focus or rotate between all the
commands in a menu, if the Menu Bar is active.The
&Ctrl;
- Down Arrow will take you from
+ &Down; will take you from
the Active Panel to the Command Line or Terminal
Emulator, and the
&Ctrl;
- Up Arrow will take you back
+ &Up; will take you back
from the Command Line to the Active Panel.The &Esc; Key will make the Menu Bar
return the focus, if it has it, to the previous Active
Panel.If you happen to be inside the Terminal Emulator,
you can use the 	 Key, or the mouse, to
navigate to an Active Panel.Pressing
&Alt;
Underlined Letter from the
Menu Bar will open that menu (unless this key combination
- is a "Reserved Key", used by one of
+ is a Reserved Key, used by one of
&krusader;'s actions).Selecting&krusader; offers 4
Selection Modes, to say nothing about the Quickselect bar, only
&krusader;'s Selection Mode is explained
here.Selecting is a skill you need to master in order to get
the most out of &krusader;. Since the Tree Panel allows select
only one directory at a time, this paragraph mainly explains how
to select files in the List Panel.Moving the cursor is easy. Left-clicking on a file or
- directory (referred to herein as "elements" meaning files and
+ directory (referred to herein as elements meaning files and
directories) will select it. Here are some useful pointers
that will make &krusader; even easier to use (assuming you are
using &krusader;'s Mouse Selection Mode):
The
- Space and
- Insert keys will toggle the selection of
+ &Space; and &Ins; keys will toggle the selection of
the file under the cursor without affecting the selection
of other files/directories, the cursor will go one
position down.Left Clicking on a file will select, or
unselect, all previously selected files.&Ctrl;
Left Clicking will toggle the
selection of the file under the cursor without affecting
the selection of other files/directories.&Shift;
Left Clicking will select all
the elements between the previous cursor location and the
new one.
- &Shift;
- Home selects everything above
- the cursor (and deselects everything below the cursor, if
- selected).
+ &Shift;&Home; selects
+ everything above the cursor (and deselects everything
+ below the cursor, if selected).
- &Shift;
- End selects everything below
- the cursor (and unselects everything above the cursor, if
- selected).
+ &Shift;&End; selects
+ everything below the cursor (and unselects everything
+ above the cursor, if selected).
- The ".." entry is not selectable.
+ The .. entry is not selectable.The Edit menu can offer more ways
to select your files.Executing CommandsThere is not a lot to say here, all you need to do is
select some files (if you do not, &krusader; will
operate on the file(s) or directory(s) that have the focus),
choose a
Command from the Menu Bar
or use a Keyboard Shortcut (or the Right Click Menu) and the
selected Command executes. See also
Executing
Files.Quick searchThis feature will do a quick search for the file name
in the Active List Panel.Type
foo(one character) to do a quick search in
- the Active List Panel for a file beginning with "foo". A
+ the Active List Panel for a file beginning with foo. A
small quick search dialog box will open below the Active List
Panel. Type the first few characters of the desired file name
(more than one character allowed), the cursor will jump to
- that filename (if it exists), ⪚ type "ab" to
- search for a file which begins with "ab". The
- Up/Down Arrow will jump to the next or
+ that filename (if it exists), ⪚ type ab to
+ search for a file which begins with ab. The
+ &Up;/&Down; keys will jump to the next or
previous match. &Esc; will close the quick search
line. The cursor will stay on the last file
found. The Quicksearch supports regular expressions for searching files.If you press
&Alt;
foo, the key binding shortcut
will be executed. If there is no configured key binding,
the remaining letter
foo will be used for the quick
search.Use Configure Shortcuts window (SettingsConfigure Shortcuts...).Quick filterThis feature will do a quick filter for the file list
in the Active Panel.Press &Ctrl;I to open Quickfilter bar.
Type foo (one character) to filter out from the Active Panel all the files
- that do not have "foo" in names. You can use wildcards for the filtering. ⪚ use "a*b" to
- filter files which have "a" and "b" in their names. The Quickfilter follows the
+ that do not have foo in names. You can use wildcards for the filtering. ⪚ use a*b to
+ filter files which have a and b in their names. The Quickfilter follows the
case-sensitivity setting of Quicksearch.Pressing &Enter; in Quickfilter mode sets focus to panel, when panel or Quickfilter is focused, &Esc; closes Quickfilter.
To change the default shortcut of Quickfilter use Configure Shortcuts window (SettingsConfigure Shortcuts...).Quick selectThis feature will do a quick select for the file list
in the Active Panel.Press &Ctrl;&Shift;S to open Quickselect bar.
Type foo (one character) to filter out from the Active Panel all the files
- that do not have "foo" in names. You can use wildcards for the filtering. ⪚ use "a*b" to
- filter files which have "a" and "b" in their names. The Quickselect follows the
+ that do not have foo in names. You can use wildcards for the filtering. ⪚ use a*b to
+ filter files which have a and b in their names. The Quickselect follows the
case-sensitivity setting of Quicksearch.Pressing &Enter; in Quickselect mode sets focus to panel, when panel or Quickselect is focused, &Esc; closes Quickselect.
To change the default shortcut of Quickselect use Configure Shortcuts window (SettingsConfigure Shortcuts...).Context Menu&krusader; has many Context menus that allow
you to do fast operations with the mouse, usually a
right-click will open the Context menu (depending on your
Selection Modes settings). This list
gives an overview of the most important context menus. Use
them to discover the available commands.
Main Toolbar (orientation, text
position, icon size)List Panel on a file or
directoryCommand Line (undo, paste, text
completion...)Terminal emulator (send signal, font,
history...)Folder tabs (new, duplicate,
close)
KruSearcher Search
results file list (F3 View, F4 Edit)MountMan (unmount,
format...)
- Synchronize Directories File List
+ Synchronize Folders File ListUserActions&konqueror; Right-Click actions are
shown in &krusader;Show/hide
Column HeadersBookmarks enable/disable permanent
bookmarks...Basic File ManagementExecuting FilesYou can only execute files in the Active List Panel. To
execute a file just
(double-)click on it or press &Enter; when it
is under the list cursor. &krusader; will open it
in the default application for this file type (picture,
text file...) or the file will be executed (script,
binary...). If you want to use
another application to open the file,
click with the &RMB; on the file and go to the Open
with sub-menu which will offer more options.
&krusader; is compatible with the &plasma;
default file manager for all file types except archives that
are opened inside the &krusader; panel and not in
an external application. See
the archives page in
Konfigurator for details.Copying and Moving
+
+ Copy dialog
+
+
+
+
+
+ Copy dialog
+
+
+ To copy or move files/directories just select them and
press
F5 to
copy or
F6 to
move them. &krusader; tries to preserve the time of
modification. When copying a directory owner is changed to the user which
copies the directory, group is changed to the default group of the user.
When copying a file owner is changed to the user which copies the file,
group is changed to default group of the user, and permissions are
preserved. The owner, the group and the permissions are preserved when
moving file or directory. When copying or moving files/directories a dialog
appears and allows you to choose the operation destination.
The default destination is the other-panel browsed directory. If you enter
a partial &URL;, &krusader; will use the current
panel directory as the &URL; base.
-
- Copy dialog
-
-
-
-
-
- Copy dialog
-
-
- Queue manager
The copy, move, pack and unpack operations can be queued.
After selecting copy or move, hit F2 to use it.
After selecting pack or unpack, hit F2 to use it.
Or the direct shortcuts: copy by queue &Shift;F5 ,
move by queue &Shift;F6 .
Queue manager performs actions one-by-one.
For example, if you have a pen drive (which is slow), and you want to copy 40 files onto it,
it is much better copying them one-by-one instead of starting to copy 40 files in parallel.
That is why enqueuing is important.
If you pack/unpack 40 files in parallel, you overload your computer,
but adding them to a queue, is much more useful.
It is possible to switch the Queue Manager mode by the SettingsJob Queue Mode menu item.
Deleting - move to &plasma; TrashDeleting files/directories is done by selecting them and pressing F8 or Delete.
By default it will be moved to &plasma; Trash.
You can open the &plasma; Trash with the Trash icon in the Main Toolbar or with
the trash:/ KIO slave.
Physically &plasma; Trash is located in ~/.local/share/Trash/ or Trash in the subdirectory in user home directory which can be determined using the qtpaths --paths GenericDataLocation command.
&Shift;
Delete will delete the file
permanently. A dialog will ask for your confirmation and will
warn you when deleting non-empty directories. Of course only
operations that are permitted to do by the Operating
System will be performed - you will be notified otherwise. If
you do not wish to see the confirmation dialogs, you can
disable them in the
Konfigurator advanced
page.Shred FilesShred was removed from &kde; 4 (and as consequence &krusader;-2 for &kde; 4).
The main reason is probably that shredding is filesystem dependent and even if you overwrite the file 100 times, it is not sure, that it will be deleted from the disk finally.
- Quote from the kgpg posts: The shred feature has been removed from the KDE library. Kgpg will not support this feature anymore. Moderns file systems use journalisation. So the shred feature should be implemented in the file system. Not in kgpg.
+ Quote from the &kgpg; posts: The shred feature has been removed from the &kde; library. &kgpg; will not support this feature anymore. Moderns file systems use journalisation. So the shred feature should be implemented in the file system. Not in &kgpg;.
But you might use a proper shred UserAction for your filesystem.
But keep in mind that if you want to be 100% sure that it is impossible that someone can read a deleted file, you need to destroy your harddrive hardware...
Renaming Files, Creating Directories and Link
Handling
Rename the file under the cursor with the
F2 key or with two single mouse clicks. If
only the file name needs to be renamed and not the extension,
you can configure this in the
Konfigurator General page.
- Create a new directory with the
+ Create a new folder with the
F7 key.
Right-clicking on a regular file will give
- you the option Link HandlingNew Symlink. A dialog will prompt
+ you the option Link HandlingNew Symlink.... A dialog will prompt
you to enter a symlink name. That symlink will point to the
file/directory you right-clicked on. If the file you
right-clicked on is a symlink, you will also be presented
with the Link HandlingRedirect Link option that will allow you to change
the link target.Viewing and Editing files
KrViewer has a chapter of its
own.
&archives;
diff --git a/doc/bookmarks.docbook b/doc/bookmarks.docbook
index 85b5a24c..8ca9cabf 100644
--- a/doc/bookmarks.docbook
+++ b/doc/bookmarks.docbook
@@ -1,297 +1,297 @@
BookMan: Organize your BookmarksBookmarksBookMan is &krusader;'s Bookmark tool for
bookmarking folders, local and
- remote URLs, and later
+ remote &URL;s, and later
returning to them in a click of a button. The Bookman menu is
divided into four sections:
Your personal bookmarksPopular &URL;sPermanent bookmarksManage bookmarksYou can bookmark inside a remote file system
(&FTP; or SAMBA) and later use the bookmark to
quickly connect to the remote machine, but you cannot bookmark
inside an archive.Bookmark menuBookmark menuUsing BookmarksUsually, you click on the
BookMan II button (the rightmost button to the right of
the address bar at the top of the active panel) when you are in the target
folder. For example, to bookmark
/usr/tmp, navigate
&krusader; there and click the
BookMan II button and select
Bookmark Current. When the
Add Bookmark dialog box appears, the
&URL; line will say
/usr/tmp.
Name is for the name you would like to give
to the bookmark (⪚: temporary folder). Hotkeys are supported
by adding
& to the bookmark name
⪚
&sourceforge, &home,
down&loads &etc;, so you can
quickly call the bookmark name with
&Alt;
foo. If you add the bookmark
without entering a name, the bookmarks name will be the same as
its target.
- URL
+ &URL;
is where the bookmark points to.
Create in creates bookmark folders for
organizing your bookmarks.To use your bookmarks, click the
BookMan II button and choose a bookmark.
You may also use the Key-Bindings:
&Ctrl;
B to bookmark the current item,
&Alt;
right/left arrow to
open right/left panel bookmarks list and
&Ctrl;
D to open the bookmarks of the
active panel. From the context menu of the bookmark (&RMB; click)
you can open it in a new
Folder tab.There is a quick search bar at the top of the BookMan II menu.
The search bar will always be visible in the bookmarks menu if you check the
corresponding item on the Panel Konfigurator's page.
Below are the rules to handle bookmarks:Just type letters to search: bookmarks are matched by name prefixIf multiple bookmarks are matched by the prefix, they are highlighted and the first one is selected - hit &Enter; to activate the bookmarkOnce a single bookmark is matched, it is immediately triggered. That is when you type 'h' and only one bookmark starts with 'h', it is executed immediately - no &Enter; neededAccelerators work only if the keystroke is the first one&Backspace; is supportedSearch is case insensitive unless you type a capital letter. That is typing HamBurglar will only match HamBurglar but not hamburglar or Hamburglar.Search bar is intentionally a read-only fieldPassword handlingOne of the benefits of the
bookmark manager is that the
passwords are saved using &plasma;'s services - where
⪚ your &konqueror;/&kmail;
password are saved. If you have a wallet, &plasma; will
save the passwords there. By clicking the bookmarks, a dialog
will open and ask for your username and password. Supply them
and click Save password. The passwords and usernames will be
saved securely by &plasma;'s wallet (make sure it is
enabled by your distro). The downside here is that if the system
was reinstalled and you do not backup your passwords from the wallet as
well as &krusader;'s bookmark file, something will
be lost.
- Popular URLs
+ Popular &URL;s
- Popular URLs
+ Popular &URL;sThe submenu
- Popular URLs
+ Popular &URL;s
holds persistent the most popular visited &URL;s
(local or remote). This submenu displays the top 15 popular
- URLs, sorted by ranking, so that the top &URL; is
+ &URL;s, sorted by ranking, so that the top &URL; is
the most popular. This is easy for when you need to visit
&URL;s often, but do not want to create
Bookmarks, it serves as a temporary bookmark
list for the most visited links.
- Quicksearch in Popular URLs is a fast way to
+ Quicksearch in Popular &URL;s is a fast way to
browse/select the popular &URL;s:
Open the
- Popular URLs
+ Popular &URL;s
or use
&Ctrl;
ZType a few letters to narrow the searchPress &Enter; (you will go to the &URL; from
list)Permanent bookmarksThese are hardcoded bookmarks to the top bookmark menu;
there is no need for them to be saved to the file. With the
Context Menu you can enable/disable these
permanent bookmarks. The following permanent bookmarks are
available:
Trash bin uses &plasma;'s
trash:/ protocol.Local Network uses &plasma;'s
remote:/ protocol.Virtual Filesystem Virtual file systems (VFS)
virt:/ is not a virtual folder, but a
container for &URL;s from different file
systems. It is used for ⪚ the
Feed to Listbox feature of the search
module and the synchronizer. The location toolbar will
display ⪚
virt:/Search results 1 or
virt:/Synchronise results 1.Jump back or
&Ctrl;
J brings you back to your
starting position when you did create a new tab in the
panel window. This feature is very handy if you go deep
into a directory tree, then you can return with one action
to the starting point. With
Set jump back point here or
&Ctrl;&Shift;
J sets the current directory as
a jump back point.Manage bookmarksTo edit and organize your bookmarks, by clicking the
BookMan II button and selecting the
Manage Bookmarks,
KeditBookmarks will be displayed. This is where
you can edit/remove and rearrange the bookmarks.
KeditBookmarks is a
bookmark editor for &konqueror;,
&krusader; and other applications, which use the
XBEL standard for the bookmark format. The
bookmarks are stored in
~/.local/share/krusader/krbookmarks.xml.
The default folder for the bookmarks file krusader/krbookmarks.xml is ~/.local/share. You can determine the needed folder in your system using the qtpaths --paths GenericDataLocation command in terminal.
This local file exists only if you have edited &krusader; bookmarks. It will be created after the first run of KeditBookmarks from &krusader;.
The default system bookmarks are stored in the kfileplaces/bookmarks.xml file in the directory which can be determined using the qtpaths --paths GenericDataLocation command.
KeditBookmarks is easy to use, however, if you
need more information, please read the
KeditBookmarks handbook.KeditBookmarks Bookmark ManagerKeditBookmarks Bookmark
ManagerBookmarks as action buttons on the ToolbarBookmarks can be placed as buttons on the
Main Toolbar or the
Actions Toolbar. You can even make a
key-binding for them:
Create your Bookmarks.If you want, create keybindings for the bookmarks in
the Configure Shortcuts window (SettingsConfigure Shortcuts...).Add your bookmarks as action buttons on the
Main Toolbar or the
Actions Toolbar with the
- Configure Toolbars window
+ Configure Toolbars... window
(SettingsConfigure Toolbars...).
diff --git a/doc/checksum.docbook b/doc/checksum.docbook
index e0b1798e..10667e2a 100644
--- a/doc/checksum.docbook
+++ b/doc/checksum.docbook
@@ -1,51 +1,51 @@
Checksum Creation and VerificationChecksumFile
- Create Checksum
+ Create Checksum...:
&krusader; checks which tools you have
and if those tools allow recursive operation (in case you
selected folders), you can generate a checksum by choosing a
checksum type from the list (md5,
sha, &etc;). You can then save the
checksum to a file, usually called checksum.md5
or checksum.sha1.File
- Verify Checksum
+ Verify Checksum...:
&krusader; checks if you have a tool that
supports the type of checksum you need (from your specified
checksum file) and displays the files that failed the checksum
(if any).The system abstracts over different checksum mechanisms and
Checksum Utilities. At the moment, the following checksums are
supported: md5, sha1, sha256, sha224, sha256, sha384, sha512,
tiger, whirlpool, cfv and crc. Please check your
Checksum Utilities
settings before using this function.
diff --git a/doc/compare.docbook b/doc/compare.docbook
index e2665837..e822615c 100644
--- a/doc/compare.docbook
+++ b/doc/compare.docbook
@@ -1,105 +1,105 @@
Compare&krusader; contains several compare functions:
Compare by Content,
Compare Directories and the
Synchronizer compare
function.Compare by ContentCompareContentSelect one file in each panel and use
File
- Compare by content
+ Compare by content....
&krusader; will open an external
graphical difference tool that is
configured.
&kompare;, KDiff3 and
xxdiff are supported.Compare DirectoriesCompareDirectoriesCompare the files of each panel by using
EditCompare Directories.
By default newer and single files will be selected
in each panel, this behaviour can be changed in the
Compare Setup menu.
The files are not compared by content but by their
names and dates only.EditCompare SetupConfigures the
Compare
Directories function.Select Newer and
Single (default)Select SingleSelect NewerSelect Different and
SingleSelect Different
diff --git a/doc/configuration-files.docbook b/doc/configuration-files.docbook
index 1fd23440..5ff6844a 100644
--- a/doc/configuration-files.docbook
+++ b/doc/configuration-files.docbook
@@ -1,158 +1,158 @@
Configuration FilesConfiguration filesThis appendix gives an overview of the configuration files
used by &krusader;.krusaderui.rcThis file stores the users toolbar settings and the menu
structure.Location:
/usr/share/kxmlgui5/krusader/krusaderui.rc, or
~/.local/share/kxmlgui5/krusader/krusaderui.rc, or kxmlgui5/krusader/krusaderui.rc in the directory which can be determined using the qtpaths --paths GenericDataLocation commandkrusaderrcThis file stores the &krusader;
configuration.Location:
~/.config/krusaderrcThe following settings are ⪚ stored:Actions ToolbarArchivesColorsDependenciesDiskUsageDiskUsageViewerGeneral
- HTML Settings
+ &HTML; SettingsKFileDialogKFileDialog SpeedbarKrDetailedViewLeftKrDetailedViewRightKrViewerWindowKrViewerWindow Toolbar extraToolBarLook & FeelNotification MessagesPanel ProfilesPrivateProtocolsSearchStartupSynchronizeLocateSynchronizerProfile - 1krbookmarks.xmlThis file stores the &krusader; bookmarks and
uses the XBEL standard.Location:
~/.local/share/krusader/krbookmarks.xml or krusader/krbookmarks.xml in the directory which can be determined using the qtpaths --paths GenericDataLocation commanduseractions.xmlThis file stores the UserActions
configuration.Location:
~/.local/share/krusader/useractions.xml or krusader/useractions.xml in the directory which can be determined using the qtpaths --paths GenericDataLocation commanduseraction-examples.xmlThis is the default UserActions provided by developers.Location:
$KDEDIR/share/krusader/useraction-examples.xmlfoo.keymapThis is a .ini file that holds a
Key binding profile.
Until &krusader;-1.70.0 this was a binary file.
&krusader; is backwards compatible for importing this
legacy binary format.Location:
/usr/share/krusader/foo.keymapfoo.colorThis is a binary file that holds the
Color Scheme.Location:
/usr/share/krusader/foo.color
diff --git a/doc/diskusage.docbook b/doc/diskusage.docbook
index 44e40ca6..d42a9509 100644
--- a/doc/diskusage.docbook
+++ b/doc/diskusage.docbook
@@ -1,118 +1,118 @@
Disk UsageDisk UsageThe Disk Usage is based on the code of
- Filelight. The Disk Usage shows you how your disk
+ &filelight;. The Disk Usage shows you how your disk
space is being used by a graphical representation of your
file system. The following presentations are possible:Line viewDetailed viewFilelight view: as a set of concentric
segmented-ringsChoose
Tools
- Disk Usage
+ Disk Usage...
or
&Alt;&Shift;
S to start this feature in a separate
window, or open it inside the
Sidebar.Disk Usage Keybindings, right click menu.Del: Delete&Ctrl;
E: Exclude&Shift;
Arrow Up: Up one directory&Ctrl;
N: new search&Ctrl;
R: refresh&Ctrl;
I: include all&Shift;
Arrow Down: step intoView menu:
&Ctrl;
L: Line view&Ctrl;
D: Detailed view&Ctrl;
F: Filelight view&Shift;
Arrow Right: Next view&Shift;
Arrow Left: Previous
view
diff --git a/doc/editors-note.docbook b/doc/editors-note.docbook
index 917e4b1c..8fe8c064 100644
--- a/doc/editors-note.docbook
+++ b/doc/editors-note.docbook
@@ -1,72 +1,72 @@
Note from the EditorsAs you may notice, this handbook is written by various authors.
The draft explanation of new features is done by the developers on the
krusader-devel mailinglist, the editors add this information in this handbook.
We have taken much care in ensuring technical and vocabulary consistency.
The authors write in English even though it is not their native language;
therefore, you may notice strange sentence constructions.
Do not hesitate to let us know, if something is not clear to you.An open source project's greatest strength is derived from getting user
feedback. That is why we would love to hear what you have to say.
Documentation contributors are always welcome!,
since this is a time consuming task.
If you have ideas on how to improve the content,
if you would like to write about an undocumented &krusader; feature, or
if you have comments or suggestions about the &krusader; Handbook, please let us know.
You can contact us even if you find typos!For information about the &krusader; documentation project,
please contact the &krusader; documentation coordinator, Yuri Chornoivan
yurchor@ukr.net.This handbook is available in several formats.via the Help Menu when using &krusader;the Online HandbookThe most recent version of this handbook is available when using &krusader; from Git.
If you are using a development or &git; version, it is possible that the latest
- new features are not yet in the "The &krusader; Handbook".
+ new features are not yet in the The &krusader; Handbook.
Please read the
Changelog
file online or in the &krusader;
sources to find out more about the new features.
For a brief description, please read the
NEWS
file online
or in the &krusader; sources.
User feedback and
Bug reports are always welcome!
All mentioned Trademarks and Copyrights in this handbook belong to their respective owners.
diff --git a/doc/faq.docbook b/doc/faq.docbook
index 331fcf84..21e43d22 100644
--- a/doc/faq.docbook
+++ b/doc/faq.docbook
@@ -1,1037 +1,1037 @@
Frequently Asked Questions (&FAQ;)FAQIf you have problems with &krusader; please
check the
installation
procedure, as your problem may be
caused by a bad installation.The &FAQ; is divided into three sections:
Installation
&FAQ; (this page)
Usage
&FAQ; (issues with running/using
&krusader;)
General
&FAQ; (bug reports, forum, mailing list,
...)If you feel that a &FAQ; is missing or
if something is not clear to you, please
let us know.Installation &FAQ;Does &krusader; need &plasma; to
run?No, &krusader; does not need the
&plasma; window manager to run on your
computer but &krusader;'s natural environment
is &plasma;, because it relies on services
provided by the &kf5-full; base libraries. Only
some shared libraries are needed ⪚
&kf5; libraries, &Qt; libraries,
&etc; This means that &krusader;
runs on GNOME,
AfterStep, XFce and
other window managers provided the appropriate libraries
are installed on your computer. All this is not a problem
since the apt-get world can resolve these dependencies
instantly.You do not need to switch to the &plasma;
window manager to use &krusader;; you can
still use GNOME,
AfterStep, XFce or
another window manager. However, the configuration of the
&krusader; fonts and some behavior is done by
running
systemsettings.A lot depends on what you want to do with
&krusader;. You should know that
&krusader; uses the &kf5;
KIO Slaves to access remote file
systems, and support for only a limited number of file
system types are shipped with &kf5; libraries,
most of the KIO Slave are bundled with
&kf5-full; (including fish, sftp and tar).To summarize, if you want a working
&krusader; - install &kf5-full;. If
you want a functional &krusader; then you need
&kf5-full; and some additional &plasma; packages. For maximum
functionality, &krusader; needs some &kde; Applications
(&ark;, &kdiff3;, KRename), but the
&plasma; window manager is optional.I cannot find a package for
&krusader;, what to do?Check if your distribution provides
&krusader;, if it does not then contact your
distribution creator and ask them to include
&krusader;!Did you take a look at the
installation
procedure page? If you have and
found nothing, you can always compile
&krusader; from source. Feel free
to post a help request if you encounter
problems.I am having trouble compiling and installing
&krusader;, how do I send a help
request?Please read our detailed
installation
procedure and the FAQ. If you
cannot find a solution to your problem then feel free to
post a
help request at our
&krusader; forum or use the
&krusader;-users mailing list. But before
posting a help request, please try the following:
Use the search function on the &kde; Forum, your problem
might be solved or discussed already.If you cannot find a solution, please make a
note of the following issues:
the &krusader; version
usedthe &Linux; distribution +
version useda good description of the problemWithout this information, it is very
difficult for us to help you.
If you give us the error messages
(⪚
make error messages) please start
with the FIRST error message, all the error
messages which follow the first error message are
consequences and not the cause of your
problem.Send out your help request.Thank you for your co-operation!Why does &krusader;-git show an old
version number in the about box?Because we only change the version number just
before we do a new release. &krusader;-git
will show an older version number, so ignore the version
number and check the download date. We simply have not yet
decided what the next version number will be.Usage &FAQ;Why does &krusader; freeze or hang on a
dead mountpoint?When &krusader; is ⪚
- browsing an NFS share and the NFS server goes down,
+ browsing an &NFS; share and the &NFS; server goes down,
&krusader; will freeze. This
&krusader; (and all other open internal
viewers/editors) freeze is fatal, and can only be
corrected with the
kill -9. We have no solution for this.
This is an issue not confined to file managers, or even
- the &Linux; OS! The problem is that you "hang"
+ the &Linux; OS! The problem is that you hang
on the first access to the dead share - so there is no
way around it, no check to avoid it, even
ls will freeze. Just trying to read
something - anything - is enough to get you stuck. The
one and only way around this architectural problem is
using a multi-threaded design - this way if we get stuck,
we do not hang the entire application event loop, but we
do not think that the time is right for adding threads, we
are not sure that *all* the &kf5; systems out
there are using &Qt;-mt (the multi threaded
version of the &Qt; library), and the &krusader;
Krew may not be the right people to address this major
issue in any case; so currently this is just a bug we
have to learn to live with.When I try to resize &krusader; to make
it smaller, I discover that I cannot resize it below a
certain size. Why?See the
F1, F2 (&etc;) buttons?
They are not allowing &krusader; to downsize
as they have a minimum size. Just disable them
SettingsShow FN Keys Bar
and you will be able to resize
&krusader; to your liking. Since version 1.51
we have improved this greatly: when downsizing the
buttons will look like 'F5 ..py'. When the button faces
are too small to read a tooltip will give the complete
text. The minimum width is 45 pixels for each
button.
- Samba ISO 8859-x codepage /
+ &Samba; ISO 8859-x codepage /
What to do if &krusader; does not read shared
directories containing special international
characters?&krusader; does not handle (yet)
- Samba ISO 8859-x codepages, if
+ &Samba; ISO 8859-x codepages, if
you use a codepage different than 8859-1 you will have to
do a manual configuration. Create or modify the file:
~/.smb/smb.conf[global]
workgroup = MyWorkGroup (ex. WORKGROUP)
client code page = MyCodePage (ex. 852)
character set = MyCharSet (ex. ISO8859-2)
You can try to configure smb.conf with appropriate
&systemsettings; module.
- &krusader; reports "krarc:... protocol
- not supported" error at opening an archive file, what to
+ &krusader; reports krarc:... protocol
+ not supported error at opening an archive file, what to
do?Install the krarc slave properly:Copy the
kio_krarc.so,
kio_krarc.la files into
/usr/{lib or lib64}/qt5/pluginsCopy the
krarc.protocol file into
/usr/share/servicesor the directory where the KIO slaves are placed in
your &Linux; distribution.
- I get the error message "Protocol not supported by
- Krusader: "krarc:/path/to/foo-archive", when I try to
+ I get the error message Protocol not supported by
+ Krusader: "krarc:/path/to/foo-archive", when I try to
open foo-Archive, what to do?The icons, kio_slaves and documentation must be
installed in the correct places in the &kf5;
directory tree. The
kio_krarc.* files must be in the same
directory with the other KIO slaves. Try this: locate
kio_tar.* and copy/link the
kio_krarc.* files to the same
location. Do not forget to run
# ldconfig on this directory when
you are done.What to do if an external tool does not seem to work?&krusader; uses several programs as external tools,
and sometimes they appear not to work.
Open a terminal and check if tool foo is installed.
$foo
Check if tool foo is properly configured in the Konfigurator Dependencies page.
For Archiving tools: autodetect the archives again with the Auto Configure button
in the Konfigurator archive page.
Check the Konfigurator Protocol page
If it does not work, backup your XDG_CONFIG_HOME/krusaderrc (default is $HOME/.config/krusaderc) configuration file and remove it from this location.
Restart &krusader;, &krusader; will now start the first start configuration wizard, follow these guidelines.
How to executing jar files (and not enter the jar archive)?Go to the Konfigurator Protocol page and remove application/x-jar
from the krarc node, &krusader; should no longer enter the archive.
Global file associations are handled by &plasma; and not by &krusader;.
To associate the jar extension:
Open &plasma; &systemsettings;: systemsettingsApplicationsFile AssociationsEnter jar as filename pattern
Add java as application
Why do I have trouble with my &FTP;
connection?This problem often occurs when you are behind a
firewall or proxy. Open
System SettingsNetwork SettingsConnection Preferences,
Enable Passive Mode (PASV) has to
be turned on or off, depending on its current setting.
Now try your &FTP; session again to see if it
works. Also, make sure you have no other &FTP;
sessions open (using web browsers, &etc;), they can cause
complications. More information can be found in
- Active &FTP; vs. Passive &FTP;, a Definitive Explanation.
+ Active &FTP; vs. Passive &FTP;, a Definitive Explanation.
I get
- FTP protocol not supported by
+ &FTP; protocol not supported by
&krusader; error when trying to
open a remote &FTP; directory, what to
do?The reason for this error is that '&FTP;
via &HTTP; proxy' feature is not yet supported
by &krusader;. This error may be caused by a
misconfiguration of the proxy settings in
&systemsettings;. Modify the proxy settings to
not use &HTTP; proxy and &FTP; will
work.How do not add .part suffix when copying files via &FTP;?When uploading files a .part suffix is added to the filename,
once the upload is complete the filename is renamed automagically
to remove the .part suffix.
This works great but sometimes some &FTP; servers do not allow a rename operation.
You can solve this by unchecking the checkbox
Mark partially uploaded files in &plasma; &systemsettings;.
The check box is located at
NetworkSettingsConnection Preferences.How can I close a remote connection
(⪚ a &FTP; connection)?It is explained in the
remote connections
chapter.I am experiencing problems with the media:/
protocol, why?The media:/ protocol was removed since &kde; 4. Please use mtp:/ protocol instead.How can I disable the default sounds,
⪚ when I do a delete action?Those are the default &plasma; System
sounds, and not related to &krusader;. If you
want to disable them globally open your &plasma;
&systemsettings; (
systemsettings):
PersonalizationNotificationsManage Notifications,
- Event Source: "Plasma Workspace"
+ Event Source: Plasma Workspace and uncheck sound items you
do not like.Where the remote connection manager?Use our Bookmark Manager. Use a
remote
&URL; and bookmark it.
- Why does not MIME type magic sometimes work inside
+ Why does not &MIME; type magic sometimes work inside
archives?When you enter an archive and press
F3 to view a file that has no known
extension, ⪚
README, INSTALL &etc; And
if the viewer opens in hex-mode instead of the usual
mode, than you need to configure:
- KDE System Settings
+ &kde; System SettingsFile AssociationsApplicationoctet-stream,
binary viewer needs to be
removed.Where is Konfigurator, do i need to install the &plasma; to use it?Konfigurator is &krusader;s configuration module,
if you have installed &krusader; then you have also Konfigurator.
For some reason some people think it is an other &plasma; application, but it is not, so
you do not need to install the full fledged &plasma; to use Konfigurator.
When running &krusader;, use
Settings
- Configure &krusader;
+ Configure &krusader;..., and it will start
Konfigurator.
Please read the manual, &krusader; has many many configuration options,
a lot of things can be customized to your needs with Konfigurator.
How can I set the look & feel of 2
different users to be the same?Presuming that the current setup is the good
configuration, you can copy the configuration to the
other user.
#cp ~/.config/krusaderrc /home/foo_user/.config
And when the other user is Root use:
#cp ~/.config/krusaderrc /root/.configGeneral &FAQ;How can I report a wish, a suggestion, or a
comment?An open source project's greatest strength is
derived from getting user feedback. That is why we love
- to hear what you have to say. Your "gripes" are our
+ to hear what you have to say. Your gripes are our
instructions. After about 6 months, programmers can no
longer see their own mistakes. It is natural. We want the
ideas, qritiques, and feedback because we all want to
make &krusader; the best and most useful file
manager available anywhere.The most convenient way to contact us is to use the krusader-users
mailing list. For information on what
remains to be done look at the
&krusader;-devel mailing list. We review and discuss every
submission.How can I send a patch?It is not easy to write patch guidelines, but here
are some.
Patches, new code or new features are always
welcome!Focus only on one problem at a time, so the
developers can easily understand you, and commit your patch
it works.Preferably, you can start a discussion
with the developers on the krusader-devel
mailing lists or on the
&krusader; Phabricator page. Unfortunately, we cannot apply
- a patch if the patch is in conflict with the "general
- design" of the &krusader; code (read for more
+ a patch if the patch is in conflict with the general
+ design of the &krusader; code (read for more
instructions in this FAQ).
Please send only one change request per mail, so
that the discussion is easier to follow. The
modifications should be committed step by step,
checking each line.
Submit your patch files into the &krusader; group on the Phabricator,
so that all patch proposals stay organised and do not get lost,
tar.gz archives or diffs are usually ok.
Do not copy changes into a mail. Most mailers will change the
white spaces, so that the diff will not apply or the
code snipped does not diff. In the past, patch mails went lost or disorganized in many many mails,
so please use the Phabricator, thanks!
Use portable solutions, &krusader;
should run on:
All POSIX
(&Linux;/BSD/&UNIX;-like
OSes), &Solaris;.All BSD Platforms
(FreeBSD/NetBSD/OpenBSD/&MacOS;).&kde; 3.3- &kde;
3.5 and even on GNOME with
- &kde;libs (for &krusader;-2.x) .
+ kdelibs (for &krusader;-2.x) .GCC 2.95 - GCC 5.4
Architecture changes are made by the
team only.A final note: always keep in mind a patch might
be rejected. Either it has side effects, which we
could not fix or it contradicts with the idea behind
the patched module. In this sense, a software project
differs from, let's say a wiki: a software project
has to have someone to make all the final decisions.
Otherwise the software will not work. Furthermore:
keep in mind that the examination of patches might
take time, as we all have private lives.How can I report a bug?Bugs?!?!? Well, ok.... We have an online Bug
Tracking System.Using the online bug-tracker helps us have a clear
and orderly way to know how many bugs are open, bug
priority and follow-ups. It saves us from browsing
through the entire &krusader; forum, searching
for yesterdays bug. Please use this system.Before reporting a bug, please read the following:
Check if the bug is
already posted in the online bug list
of the Bug Tracking System.If you cannot find this bug mentioned, please
submit it into the
bug tracker by clicking the
Submit New button in the
bug-tracker window. Please submit the following
issues: the &krusader; version used, the
&Linux; distribution + version used,
processor type, and as good a description of the
problem as you can manage.Thank you for your co-operation!If possible, try to do the same operation with
&konqueror; or another &kde;
application. If you encounter the same problem then it
is possibly a KIO Slaves or
&kf5-full; bug, and not a
&krusader; bug. &krusader; uses
the &kf5; libraries and the
KIO Slave for many operations. In
some cases you can encounter problems if your
distribution is incorrectly configured, please test it
first as explained above.How can i send good debug or crash reports?Usually binary packages that are been used by your distribution do not contain debug information.
Since we usually only develop and fix &krusader;-git, compile &krusader;-git in debugmode and install it, than check if the bug still exist.
$cmake
- Install valgrind, a suite of tools for debugging and profiling &Linux; programs.
+ Install valgrind, a suite of tools for debugging and profiling &Linux; programs.
Run Valgrind/&krusader;
$valgrind{foo_path}/krusader
The valgrind tool will write to stdout, what really happens.
If you could send these information before the crash, it is almost sure, that we may fix or tell you what to do.
What to do if the KDEcrashhandler sends no useful backtrace information?Usually binary packages that are been used by your distribution do not contain debug information.
Since we usually only develop and fix &krusader;-git, compile &krusader;-git in debugmode and install it, than check if the bug still exist.
$cmake
If the KDEKrashhandler still does not provide useful backtrace information, than sometimes a coredump will give better information.
Run Krusader, with disabled crashhandler.
$krusader
On a crash you will get a .core file, usually in your home directory.
Run gdb, the GNU Project Debugger
$gdbcorefile krusader
Now type bt to get the backtrace and type q to quit gdb.
Often the best debug results will be given when using the valgrind tool.
Does &krusader; have a mailing
list?Yes, currently we have 5
mailing lists. No spam, no bother, just
&krusader;. Feel free to subscribe and
unsubscribe.Tip. our mailing lists can be browsed online or
read with a newsreader, so that you do not even need to
subscribe to follow the action on the mailing lists.
&krusader;-devel is the developer
mailing list (read-only). If you want to follow the
development of &krusader; on the cutting
edge, this is the list to follow.&krusader;-users is the
&krusader; users mailing list. Here you
can ask for help and talk with the
&krusader; users and developers.Does &krusader; provide
news feeds?Yes, we do. Several news feeds in various formats
are available. krusader-devel feed, krusader-users feed.Does &krusader; have an IRC
channel?Yes, we do. Feel free to talk to the
&krusader; Krew and fellow-users via
- freenode.org servers. The server is
+ freenode.org servers. The server is
irc.freenode.org, the channel is
#krusader. Everyone is
welcome.How does the &krusader; forum
work?In the spirit of freedom of speech, everything that
is &krusader; related can be discussed in our
forum. It does not matter if you are a newcomer or an
advanced user, everyone is welcome. An open source
project's greatest strength is derived from getting user
feedback. That is why we love to hear what you have to
say. With your feedback we can make &krusader;
better and better; otherwise, we are not aware of issues
and ideas you may have. But please remember the
following, so that we can maintain some order in the
chaos.If the
Documentation,
FAQ and
&krusader;-devel (please use the search function
) cannot help you, do not hesitate to post on our forum.
The &krusader; Krew or the
&krusader; community is always available to
help you.Please use the search function of the &kde; Forum, your issue may
have been previously discussed (this allows us to
minimize the double/triple/... postings). If your issue
has already been discussed in the past there is a great
chance that you will have an instant solution to your
problem. If the issue is currently being discussed, you
can join in the discussion. Some questions are asked over
and over again, that is why we have created this
FAQ. This allows us to spend more time
developing &krusader;.Thank you for your co-operation!How can I translate &krusader; into my
native language?
- If you are interested in translating the &krusader; GUI or documentation, please contact the
+ If you are interested in translating the &krusader; &GUI; or documentation, please contact the
KDE translation team of your language.How can I support &krusader;?You can
support &krusader; in many different
ways. Please send us
feedback,
bug reports, patches,
donations,
translations, ...
- Why is &konqueror; in "midnight
- commander style" not an
+ Why is &konqueror; in Midnight
+ Commander style not an
OFM?The two panels and a commandline are available, all
the other stuff like
OFM features and the
OFM interaction with the
user is missing from this profile.Why should I use an
OFM?
- An Orthodox File Manager (OFM) is much faster than a one
+ An Orthodox File Manager (OFM) is much faster than a one
panel filemanager and faster than the command line. If
you would like to know
-
+
how &krusader; feels, there is only
one way to discover: install it on your computer and use
it for a while. If you prefer to waste time and lose
productivity, continue to use one panel filemanagers
which are based on &Windows; Explorer. Matej
Urbančič has written
a
-
+
blog on why
OFM is better than a one
panel filemanager.
diff --git a/doc/features.docbook b/doc/features.docbook
index 17f230e2..658126ae 100644
--- a/doc/features.docbook
+++ b/doc/features.docbook
@@ -1,518 +1,518 @@
FeaturesFeaturesThe most important features and improvements are
highlighted here, it would make this list too long if we were to
include all the features and improvements.
You will discover even more features in this documentation and in the
ChangeLog
and
NEWS
files.Orthodox File Manager (OFM) featuresTwo powerful and easy to use
OFM panels.Command Line and optional
Terminal emulator below.Strong
keyboard orientation and the ability to perform
all functions without the mouse.Context-dependent invocation of scripts and
programs ⪚ mouse click/&Enter; (execute or
open with the associated application), F3 (view) and F4
(edit).User Menu, create your own
customized menu.History ⪚
Folder History,
Popular
&URL;s, &etc;Virtual file systems (VFS) ⪚ for
Remote Connections,
archives, search results,
synchronizer.Powerful internal
viewer and editor via
kparts supporting almost every file format.Advanced Search module:
searching in archives and search content on remote
file systems.Several Panel view modes via the
Sidebar.&krusader; toolsRemote Connections:
&FTP;/SAMBA with SFTP/SCP support via
KIO SlavesLocate &GUI; frontend
- Synchronize Directories
+ Synchronize Folders
Mount-Manager
Disk UsageRoot mode&krusader; featuresArchive Handling: browsing, unpack, pack,
testing. Supported archives: ace,
arj, bzip2, deb, gzip, iso, lha, rar, rpm, tar, zip and
7-zip.
Checksum
Creation and Verification mechanism that supports
md5, sha1, sha256, sha224, sha256, sha384, sha512,
tiger, whirlpool, cfv, and crc.
Calculate occupied
space of files and folders, archives and remote
filesystems.
Directory
comparison and
filtering.
Compare files by
content via external diff programs like
&kompare;, KDiff3 or
xxdiff.
Rename files and
folders via KRenameCompletely supports drag'n'drop: drag from
&konqueror; straight into a .tar.gz file,
from &krusader;'s panel into the trash bin,
the desktop or into &konqueror;
Preserve date for
local targets at copy/move operations.F9 opens a
Terminal Window in the
current directory.Easy editing of
file permissions and
ownership and
Numeric
Permissions.
Selection
filters used in ⪚ Synchronizer and
KruSearcher.
Jump-Back
- MIME type-aware.
+ &MIME; type-aware.
Tabbed panels and
Tabbed
Editor/Viewer.Quick search, select and filter
File splitter
Mouse Gestures
Quick Navigation in
the Location Toolbar.WhatsThis Help function in favour
of tooltips where reasonable.Sync-browsingCustomize &krusader; to your own
needs
Konfigurator &krusader;'s
configuration center.Main Toolbar,
Actions
Toolbar for user actions and bookmarks.
Key-bindings
Colors
Panel profilesBookmark-ManagerSelection ModesMany more features can be
configured the way you
like.&krusader; ExtensionsUserActionsColor ProfilesKey-binding Profiles
Download and upload your favourite &krusader; extensions at
store.kde.org.
- New features in the &krusader;-1.80.0 "Final 3rd Stone"
+ New features in the &krusader;-1.80.0 Final 3rd Stone
releaseArchive improvements
Password support for: arj,
ace, rar and zip. Passwords can be stored in
Kwallet
7-zip support, by
external applications 7z and
7za.
Auto-detection support,
- allowing you to open "hidden archives" (⪚
+ allowing you to open hidden archives (⪚
OpenOffice documents).Packing/unpacking is now in the background.Brief View
- Many improvements of the UserAction system.
+ Many improvements of the UserActions system.Countless usability enhancements, especially in Konfigurator and the heavily reordered menubar.
Media button
Copy/Move:
preserve all attributes (time,
owner, group).
Dim the colors of the inactive
panel.Renaming a filename without extension, single instance
mode, start to system tray, check this out in
KonfiguratorConfigurable
Atomic extensions,
so that extensions like .tar.gz are shown as one part in the Ext Column.
Context menu for bookmarks and enable/disable special
bookmarks.Restyled
MenuBarTerminal emulator enhancements bringing new functions, new usages and new look.Synchronizer enhancements and parallel threads for slow
&FTP; servers.
Single instance mode,
start to system
tray
Context menu for permanent
bookmarks.
Full support for
ACL permissions, like properties, preserve attributes, synchronizer and other.Searcher-results, Locate-results, Synchronizer-results: support for dragging items and copy to clipboard (&Ctrl;C).Many bug fixes.
- New features in the &krusader;-1.90.0 "Power Stone"
+ New features in the &krusader;-1.90.0 Power Stone
releaseLast release for &kde; 3.x with a big collection of Useractions.
- New features in the &krusader;-2.0.0 "Mars Pathfinder"
+ New features in the &krusader;-2.0.0 Mars Pathfinder
releaseThe first release for the &kde; 4.x series
&krusader; works on &Windows;! (But not so useful and powerful yet as under &Linux;)
Queue manager!
Five methods in the panel!
- New features in the &krusader;-2.1.0-beta1 "Rusty Clutch"
+ New features in the &krusader;-2.1.0-beta1 Rusty Clutch
releaseFast text/hex viewer for huge filesizes.
Locked tabs.
Queued packing / unpacking.
Better trash integration.
The quick search, select and filter bar supports regular expressions for matching files.
- New features in the &krusader;-2.5.0 "Clear Skies"
+ New features in the &krusader;-2.5.0 Clear Skies
releasePorted to &kf5-full;.
The new Quickfilter bar with three different modes to operate: select, search and filter.
Reworked Queue Manager (JobMan) and the new Job Toolbar.
- New features in the &krusader;-2.7.0 "Peace of Mind"
+ New features in the &krusader;-2.7.0 Peace of Mind
releaseQuick Search in Bookmark menu.
Pinned tabs.
Tooltip with file information when you hover a file name.
Extended options for Tree Panel at the Side Bar.
If you are using a development or &git; version, it is possible that the latest
- new features are not yet in the "The &krusader; Handbook".
+ new features are not yet in the The &krusader; Handbook.
Please read the
Changelog
file online or in the &krusader; sources to find out more about the new features.
For a brief description, please read the
NEWS
file online or in the &krusader; sources.
User feedback and
Bug reports are always welcome!
diff --git a/doc/glossary.docbook b/doc/glossary.docbook
index 0e116e69..a502f317 100644
--- a/doc/glossary.docbook
+++ b/doc/glossary.docbook
@@ -1,379 +1,379 @@
GlossaryThis chapter is intended to explain the various words which
have been used throughout the &krusader;
documentation. If you believe some acronyms or terms are missing,
please do not hesitate to contact the &krusader;
documentation team.Thanks to
wikipedia.org the
free encyclopedia that anyone can edit.
ACL
Access Control List; a concept in computer security
used to enforce privilege separation. It is a means of
determining the appropriate access rights to a given object
depending on certain aspects of the process that is making
the request.
BSD
Berkeley
Software Distribution; refers to any of several free
&UNIX;-compatible operating systems, derived from
&BSD; &UNIX;.
CVS
Concurrent Versions System; an important component of
Source Configuration Management (SCM). By using it,
developers can record the history of source files and
documents.
DEB
This is a binary file format that is used by
- Debian and Debian-based
+ &Debian; and &Debian;-based
distributions. It is a suffix of a installation file
specifically built for these distributions; ⪚
krusader_1.70.1-1_amd64.deb. Simply
described it is a special archive containing all the
program files and their proposed location on the
system.
&DBus;
&DBus; is an inter-service messaging system.
Developed by &RedHat;, it was heavily influenced by &kde; 3
&DCOP;, which it supersedes.
&krusader; can use &DBus; to communicate with other applications.
On the other hand, you can use &DBus; to control &krusader; from
other applications. Just use qdbusviewer to examine the possibilities.
&DCOP;
Desktop
Communication Protocol; the interprocess
communication protocol used by &kde; 3 desktop
environment. It enables various &kde; 3 applications
to communicate with each other. Replaced with
&DBus; in &kde; 4.
FAQ
Frequently Asked Questions; a
document where questions that arise many times are answered.
If you have a question to the developers of
&krusader;, you should always have a look at the
FAQ first.&FTP;
File Transfer Protocol; it is an Internet protocol
that allows you to retrieve files from so-called
&FTP; servers.
Git
Git; a distributed version control system that replaces
Subversion. It is used by many
software projects including &kde; and
&krusader;.
GPL
GNU General
Public License; a software license created by the
Free Software
Foundation defining the terms for releasing free
software.&GUI;
Graphical User Interface.
ISO
An
ISO
image (.iso) is an informal term for a disk image of
an ISO 9660 file system. More loosely, it refers to any
optical disk image, even a UDF image.&kde;K Desktop
Environment; a project to develop a free graphical
desktop environment for &UNIX; compatible
systems.Key BindingAll features of &krusader; are available
through the menubar, but you can also bind (link) a certain
key combination to that function. You will find, however,
that using the
keyboard is remarkably
faster than using the menubar or
- GUI.
+ &GUI;.
Keyboard usage is an
important tool for
Orthodox File Managers.
&krusader; comes with several predefined
Key Bindings.KPartKPart;
KParts is the name of the component framework
for the &kde; desktop environment. KParts are
analogous to Bonobo components in GNOME,
both of which are based on the same concepts as
&Microsoft;'s Object Linking and Embedding. ⪚
- if you use &krusader;'s viewer to view a PDF file,
+ if you use &krusader;'s viewer to view a &PDF; file,
&okular; will be launched inside &krusader;'s
viewer.
KIO or kioslaveKDE
Input/Output; also known as
KIO Slaves is part of the &kde;
architecture. It provides access to files, web sites and
other resources through a single consistent API.mount
Mounting; in computer science, is the process of
making a file system ready for use by the operating system,
typically by reading certain index data structures from
storage into memory ahead of time. The term recalls a period
in the history of computing when an operator had to mount a
magnetic tape or hard disk on a spindle before using
it.
OFM
- Orthodox File Manager; also known as "Commanders".
+ Orthodox File Manager; also known as Commanders.
Members of this family of file managers use simple yet very
powerful interface that is a direct derivative of the
Norton Commander (NC) interface.RPMThis is the binary file format for distributions based
on the
RPM Package Manager,
a widely used packaging tool for the &Linux;
operating system. If you still have to get
&krusader; and your system supports RPM packages,
you should get &krusader; packages ending in
.rpm.
SSH, Secure ShellSSH;
is a set of standards and an associated network protocol that allows
establishing a secure channel between a local and a remote computer.
SVN, Subversion
Subversion; a version control system that is a
compelling replacement for
CVS. It is used by many
software projects including &kde;.Terminal emulator
Terminal emulator; simply a windowed shell; this is
known as command line window in some other environments. If
you want to use the shell and type the commands, you should
know at least a few of the system-level commands for your
operating system.
POSIX
Portable
Operating System Interface for uniX; a collective
name of a family of related standards specified by the IEEE
to define the application programming interface (API) for
software compatible with variants of the &UNIX;
operating system.
&URL;
Universal
Resource Locator; a universal resource locator is the
technical term for what is commonly referred to as a websites
address. Examples of &URL;s include
https://krusader.org and
Remote Connections.
VFS
Virtual file systems (VFS) is a basic
OFM feature, this an
abstracted layer over all kinds of archived information (ZIP
- files, &FTP; servers, TAR archives, NFS filesystems, SAMBA
- shares, ISO CD/DVD images, RPM catalogs, &etc;), which allows
+ files, &FTP; servers, TAR archives, &NFS; filesystems, SAMBA
+ shares, ISO &CD;/&DVD; images, RPM catalogs, &etc;), which allows
the user to access all the information in these divergent
types of file systems transparently - just like entering an
ordinary sub-directory! &krusader; supports
several Virtual file systems (VFS).&XML;Extensible
Markup Language; a very flexible text format derived
from SGML (ISO 8879). Originally designed to meet the
challenges of large-scale electronic publishing, &XML; is also
playing an increasingly important role in the exchange of a
wide variety of data on the Web and elsewhere.ZeroconfZeroconf;
or Zero Configuration Networking is a set of techniques that automatically
create a usable IP network without configuration or special servers.
This allows inexpert users to connect computers, networked printers,
and other items together and expect them to work automatically.
diff --git a/doc/help.docbook b/doc/help.docbook
index a1f48cb2..86dc497e 100644
--- a/doc/help.docbook
+++ b/doc/help.docbook
@@ -1,104 +1,104 @@
Help &krusader;HelpHere is your opportunity to contribute to
the &krusader; project. There are things that need to
be done, but cannot be done by us. If you feel you can help, do not
hesitate to contact us; every OpenSource can use some help.
Please also check the contribute donate &URL; page on our
website for more recent information. Thanks!To get contributor account and commit changes to &krusader; by yourselves you should follow this tutorial. Some useful advices on using &kde; Git can be found here. It is a good practice to use review board for the non-trivial patches.
DocumentationHelp is needed (we are looking for documentation writers)
for keeping the &krusader; documentation up to date.
The draft explanation of new features is done by the developers
on the krusader-devel mailing list, but we need editors to add
this information in the handbook. By playing with the new
features these editors can give valuable information to the
developers for making the new features even better!&krusader;
ExtensionsPlease upload your favourite extensions at
store.kde.org, so that they become available for the
&krusader; community. Maybe they will be shipped by
default with &krusader; at the next release :-)).Spread the Word
&krusader;If you like &krusader;,
let people know! Write articles and reviews for internet or
print publications. Encourage your friends to give
&krusader; a try. Participate in forums to help others
in the community.
- GUI Translations
+ &GUI; Translations&krusader; is available in many languages, but
sometimes translations do need an update or
translations to new languages are always welcome.
- If you are interested in translating the &krusader; GUI, please contact the
+ If you are interested in translating the &krusader; &GUI;, please contact the
&kde; translation team of your language.Documentation TranslationsIf you are interested in translating this &krusader; documentation, please contact the
&kde; translation team of your language.DonationsActually, we had not considered donations, until users asked
us for a way to Donate to the project.
&krusader; is, and always will be free, in all the
terms of the GNU Public License.PackagersWe are always in need of packagers for different distro
- rpm's, deb's, etc. All help is welcome.
+ rpm's, deb's, &etc; All help is welcome.
FAQIf you have a question that is missing in the
FAQ, we would like to hear it.Rate &krusader;On some websites like freshmeat.net or
linux-apps.com you can give a rate, if you like
&krusader; go to one of these sites and rate
&krusader;, thanks.Others
Feedback,
Bug reports, patches,
&etc; are always welcome! An open source project's
greatest strength is derived from getting user feedback.
diff --git a/doc/index.docbook b/doc/index.docbook
index 59c2b352..a43dc434 100644
--- a/doc/index.docbook
+++ b/doc/index.docbook
@@ -1,370 +1,370 @@
]>
The &krusader; HandbookDavideGianforteDeveloperdavide@gengisdave.orgToni AsensiEsteveDevelopertoni.asensi@kdemail.netAlexanderBikadorovDeveloperalex.bikadorov@kdemail.netMartinKostolnýDeveloperclearmartin@gmail.comNikitaMelnichenkoDevelopernikita+kde@melnichenko.nameYuriChornoivanDocumentationyurchor@ukr.netShieErlichAuthor and initial Handbook author (retired)erlich@users.sourceforge.netRafiYanaiAuthor and initial Handbook author (retired)yanai@users.sourceforge.netCsabaKaraiDeveloper (retired)ckarai@users.sourceforge.netHeinerEichmannDeveloper (retired)h.eichmann@gmx.deJonasBährDeveloper (retired)jonas.baehr@web.deVáclavJůzaDeveloper (retired)vaclavjuza@seznam.czSimonPerssonDeveloper (retired)simon.persson@mykolab.comJanLepperDeveloper (retired)jan_lepper@gmx.deAndreyMatveyakinDeveloper (retired)a.matveyakin@gmail.comDirkEschlerWebmaster (retired)deschler@users.sourceforge.netFrankSchoolmeestersDocumentation and Marketing coordinator (retired)frank_schoolmeesters@yahoo.comRichardHoltDocumentation and Proofing (retired)richard.holt@gmail.comMatejUrbančičMarketing and Product Research (retired)matej.urban@gmail.com2000200120022003Rafi YanaiShie Erlich2004200520062007200820092010201120122013201420152016201720182019Krusader KrewPermission is granted to copy, distribute and/or modify
this document under the terms of the
- GNU Free
+ &GNU; Free
Documentation License, Version 1.1 or any later
version published by the Free Software Foundation; with no
Invariant Sections, with no Front-Cover Texts, and with no
Back-Cover Texts. A copy of the license is included in the
&krusader; sources.2019-08-252.7.2&krusader; is an advanced, twin-panel
(commander-style) file-manager for Plasma and other desktops in
the *nix worldKDEkrusadercommanderfilemanagertwinpanellinuxfilemanagerdual panelinux-commanderkde-commander
&help;
&editors-note;
&introduction;
&features;
&user-interface;
&basic-functions;
&advanced-functions;
&menu-commands;
&keyboard-commands;
&mouse-commands;
&krusader-tools;
&konfigurator;
&faq;
&credits-and-license;
&configuration-files;
&useraction-xml;
&release-overview;
&glossary;
&documentation.index;
diff --git a/doc/introduction.docbook b/doc/introduction.docbook
index 2002764c..a6f016a4 100644
--- a/doc/introduction.docbook
+++ b/doc/introduction.docbook
@@ -1,151 +1,151 @@
IntroductionIntroductionPackage description&krusader; is a simple, easy, powerful,
twin-panel file manager (commander-style) for &plasma;
and other *nix desktops, similar to Midnight Commander or
Total Commander. It provides all the file management features
you could possibly want.Krusader also includes extensive archive handling,
mounted file system support, &FTP;, advanced search
module, viewer/editor, directory synchronization, file content
comparisons, powerful batch renaming and much, much more.
&krusader; supports archive formats: ace, arj, bzip2, deb, gzip, iso, lha,
rar, rpm, tar, zip and 7-zip and handles other
KIO Slaves such as smb:// or fish://.&krusader; is almost completely customizable and therefore
very user-friendly.Try &krusader;.&krusader; screenshot&krusader; screen shotMore &krusader; Screenshots can be viewed on
our website.Welcome to &krusader;!Our aim is to give you a simple, intuitive tool that
easily handles the most important tasks you perform on your
computer each and every day: manage and process your files the
way you want.Whether you are a &Linux; expert or a novice,
&krusader; makes routine file management tasks quick
and accurate, allowing you to focus on the big picture, not
command line syntax. This is especially helpful if you are new
to xxNIX operating systems. To do just that,
&krusader; uses a good-looking &GUI; and
- supports drag and drop as well as MIME types, making it easy to
+ supports drag and drop as well as &MIME; types, making it easy to
use.&krusader; has many useful features. It is fast, and
handles archives transparently. In addition,
&krusader; streamlines many complex file management
tasks, reducing fatigue, errors, and distraction. Basically,
&krusader; provides all the helpful features you have
come to expect from other quality file management tools like
Midnight Commander and Total Commander. &krusader; is
designed to integrate seamlessly with the &plasma;,
the desktop of choice for many programmers, network
engineers, and other power users of &Linux;. With
&krusader; even novice users can quickly access the
power, convenience, and feature rich capabilities of the
&plasma;. &krusader; is a free
open-source project, and it is released under the
&GNU; General Public License (GPL), although the developers still retain the
copyright for the project and its name, and manage the
project's continuing evolution.The &krusader; Project mission is to create
- an "all-in-one" file manager, which will do all the ordinary
+ an all-in-one file manager, which will do all the ordinary
things you would expect of it, and more. Since the principle
behind &krusader; is based on the
Orthodox File Manager (OFM), dual-pane filemanagers (Midnight Commander,
Norton Commander, &etc;), it is certain that
&krusader; is able to handle all the standard Copy,
Move, Delete, &etc; file operations.From the start, virtual file systems became the main
focus. Virtual file systems (VFS) are an abstracted layer over all
kinds of archived information (ZIP files, &FTP;
- servers, TAR archives, NFS filesystems, SAMBA shares, ISO
- CD/DVD images, RPM catalogs, &etc;), which allow the
+ servers, TAR archives, &NFS; filesystems, SAMBA shares, ISO
+ &CD;/&DVD; images, RPM catalogs, &etc;), which allow the
user to access all the information in these divergent types of
file systems transparently - just like entering an ordinary
sub-directory. Files can then be copied or moved around (except
ISO, rpm, tar.gz) between these data sources/containers
effortlessly. &krusader; currently supports VFSs for
all popular and some specialized types of archives (ace, arj,
bzip2, gzip, iso, lha, rar, tar, zip and 7-zip), configuration
packages (rpm, deb), and traditional remote file system types
- (&FTP;, NFS, Samba, FISH, SFTP).
+ (&FTP;, &NFS;, Samba, FISH, SFTP).
&krusader; also includes a built-in
Mount-Manager MountMan, which enables you to
mount or unmount file systems of all types with a click of a
mouse. The user is able to obtain usage and other property
information easily, in a consistent and understandable format
in seconds. Ease and consistency is the goal.A Bookmark-Manager for local
files/remote &URL;s and an
Advanced Search module is also included to
speed the locating of needed files. &krusader; also
allows the user to configure Toolbars in order to provide a
wide variety of additional functionality, such as File
Comparison (several user selectable methods available),
Multiple File Rename, and standard Terminal windows.Advanced users benefit greatly from being able to carry
out clerical tasks effortlessly, without distraction from the
real task at hand. Convenient shortcut keys enable the user to
navigate directory trees with ease, create multiple tabbed
directory views simultaneously, and access fully functional
history lists. Due to efficient programming and low system
overhead, &krusader; is perhaps the most responsive
all around system management tool used to access the full
potential of a computer using &plasma;, or any other
standards compliant &X-Window; window manager. Although designed
specifically for - and tightly integrated with -
&plasma;, &krusader; works equally well with
GNOME, MATE, Enlightenment, &windowmaker;, IceWM,
XFCE, &etc;, as long as the &kf5; libraries are installed.New extensibility is provided by the flexible
UserActions, a &krusader;
innovation that allows unlimited additional custom
functionality to be added to suit the specific needs of users. We
are planning to develop more modules in the near future,
thereby enhancing &krusader;. Information on what is
proposed, approved, or remains to be completed can be found in
the &krusader; Phabricator page.No other program we know of, offers so many useful,
easily accessible features in such an intuitive and simple
format. Best of all, we listen, and implement good suggestions
that are consonant with the &krusader; Project's
goal: making &krusader; the very best File Manager
available.We hope you will enjoy it - we do!
diff --git a/doc/keyboard-commands.docbook b/doc/keyboard-commands.docbook
index beaaf49a..46c7af53 100644
--- a/doc/keyboard-commands.docbook
+++ b/doc/keyboard-commands.docbook
@@ -1,2031 +1,2031 @@
Keyboard CommandsCommandsKeyboardKeyboard UsageIn this chapter you will learn how to use the keyboard
effectively, because most operations can be done more quickly
by keyboard than with the mouse. It will take some time to learn
the Key-Bindings, but mastering them saves you a
lot of time. Please note that &krusader; can use
Key-binding Profiles to swap easily to other
Key-binding setups, ⪚ of other commanders, or you can create
your own key-bindings.After starting &krusader;, the keyboard action can
begin. Use &Ctrl;L to jump to the
Location Toolbar where you can type the
- desired directory. After &Ctrl;Down arrow
+ desired directory. After &Ctrl;&Down;
you are in the
Terminal emulator and you can type any command you
- desire. Use &Ctrl;Up arrow
+ desire. Use &Ctrl;&Up;
to jump back to the active panel. If
you want to jump to a file or directory that starts with f,
then simply press f on the keyboard to use the
search bar. Use the &Enter; key to execute
the file or to open a directory that has the focus. Be sure to
remember the Function Keys - F3 to View, F4 to Edit,
F5 to Copy, &Alt;&Shift;U to Unpack, &etc;You can also perform several operations with the
Folder tabs, including several
selection operations. And at
the end you can close &krusader; with F10.Key-BindingsKey-BindingsCommandsKeyboardMost of the key-bindings (shortcuts) are configurable in
the
Settings
- Configure Shortcuts
+ Configure Shortcuts...
menu, if you like to use other key-bindings then the
default ones. You can even configure
more actions to a Key-Binding (for the actions that do not have a key-binding set by default).
Please note that some key-bindings are not &krusader; key-bindings (⪚
&plasma; key-bindings). The key-bindings that
&krusader; uses by default are listed below.Function (FN) KeysThese are the Key-Bindings of the
FN Keys Bar. These Key-Bindings are configurable
since version 1.51.F1HelpF2
Rename files.
F3
View files.
F4
Edit files.
F5
Copy files.
F6
Move files
F7
Create a new
- directory.
+ folder.
F8
Delete (or move to Trash)
files.
F9
Terminal.
F10Quit &krusader;&Shift; keys&Shift;
F1
What's this?
&Shift;
F2
Multi-rename
(Krename).
&Shift;
F3
Enter an &URL;
to view.
&Shift;
F4
Edit new file.
&Shift;
F5
Copy by queue.
&Shift;
F6
Move by queue.
&Shift;
F10
View all files.
&Shift;
F12
Custom view files.
&Shift;
- Left Arrow
+ &Left;
Change to left folder
tab.
&Shift;
- Right Arrow
+ &Right;
Change to right folder
tab.
&Alt; keys&Alt;
+
Select All.
&Alt;
-
Unselect All.
&Alt;
*
Invert Selection.
&Alt;
.
Show/Hide hidden (dot)
files.
&Alt;
/
MountMan.
&Alt;
`User Menu&Alt;
- Home
+ &Home;
- Home
+ Home.&Alt;
&Enter;
Properties.
&Alt;
- Left Arrow
+ &Left;
Left bookmarks.
&Alt;
- Right Arrow
+ &Right;
Right bookmarks.
&Alt;
- Down Arrow
+ &Down;
Sidebar.&Alt;
F1..F12Standard (&plasma;)
key-bindings.&Alt;+&Shift; keys
&Alt;&Shift;
BBrief View&Alt;&Shift;
CCompare Directories
&Alt;&Shift;
DDetailed View&Alt;&Shift;
E
Test Archive.
&Alt;&Shift;
KStart Root mode
&krusader;.&Alt;&Shift;
LPanel profiles.&Alt;&Shift;
O
- Sync panels aka "Equals Button (=)".
+ Sync panels aka Equals Button (=).
&Alt;&Shift;
P
Pack files.
&Alt;&Shift;
QQueue Manager&Alt;&Shift;
SDisk Usage.&Alt;&Shift;
U
Unpack
files.
&Ctrl; keys&Ctrl;
B
Add bookmark for the current item.
&Ctrl;
D
Open Bookmarksin the
active panel.&Ctrl;
EEdit file as root (Default Useraction).&Ctrl;
FOpen Quicksearch bar.&Ctrl;
H
Open History
list in the active panel.&Ctrl;
IOpen QuickFilter bar.&Ctrl;
JA Safari-like
Jump-Back.&Ctrl;
LGo to the Location Toolbar
(origin) as in Firefox and
&konqueror;.&Ctrl;
M
Open media
list.&Ctrl;
N
New Network
Connection dialog.&Ctrl;
OSelect directory dialog to open this directory
in the panel.&Ctrl;
P
Split file.
&Ctrl;
QQuit &krusader;.&Ctrl;
R
Reload (Refresh)
panel.
&Ctrl;
S
Search.
&Ctrl;
U
Swap panels (do not swap all folder tabs).
&Ctrl;
W
Close Current tab.
&Ctrl;
Y
- Synchronize Directories.
+ Synchronize Folders.&Ctrl;
Z
- Popular URLs.
+ Popular &URL;s.
&Ctrl;
+
Select group.
&Ctrl;
-
Unselect group.
&Ctrl;
/
Open command line history
list.
&Ctrl;
- Down arrow
+ &Down;
Go from the active panel to
the command line/terminal emulator.
&Ctrl;
- Up arrow
+ &Up;
Go from the command
line/terminal emulator to the active panel.
&Ctrl;
- Up arrow
+ &Up;
Go from the active panel to the
Location Toolbar.&Ctrl;
- Home
+ &Home;
Jump to the Home directory.&Ctrl;
- Left or
+ &Left; or
- Right arrow
+ &Right;
Focus a file or directory on the left panel,
press
&Ctrl;
- Left arrow and the right
+ &Left; and the right
panel changes:
on a file: the right panel gets the same
path as the left
panel.on a directory: refreshes the right panel
with the contents of the directory.For the right panel: press
&Ctrl;
- Right arrow and the left
+ &Right; and the left
panel will change.
&Ctrl;&Backspace;Jump to the Root directory.&Ctrl;
- PageUp
+ &PgUp;
Up one directory.&Ctrl;
=Go to the directory from other panel.&Ctrl;
ReturnWhen media menu is open (un)mounts the highlighted device.&Ctrl;+&Shift; keys
&Ctrl;&Shift;
D
Disconnect
remote connection.
&Ctrl;&Shift;
F
Activate search bar to find entries in the active tab.
&Ctrl;&Shift;
J
Set jump back
point.
&Ctrl;&Shift;
LLocate &GUI; frontend.
&Ctrl;&Shift;
OMove current tab to other side of the window.
&Ctrl;&Shift;
SOpen Quickselect bar.
&Ctrl;&Shift;
USwap Sides (also swap all folder tabs).
&Ctrl;&Shift;
- Left arrow
+ &Left;
Open left media
list.
&Ctrl;&Shift;
- Right arrow
+ &Right;
Open right media
list..
&Ctrl;&Shift;
- Up arrow
+ &Up;
Open
terminal emulator,
independently, whether the command line is shown or
not.
&Ctrl;&Shift;
- Down arrow
+ &Down;
Close
terminal emulator,
independently, whether the command line is shown or
not.
&Ctrl;&Shift;
- PageUp
+ &PgUp;
Move current tab to the left.
&Ctrl;&Shift;
- PageDown
+ &PgDn;
Move current tab to the right.&Ctrl;+&Alt; keys
&Ctrl;&Alt;
EShow/hide the
embedded terminal.
&Ctrl;&Alt;
MMount (Default Useraction).
&Ctrl;&Alt;
N
New tab.
&Ctrl;&Alt;
RToggle the List Panel between
horizontal and vertical mode.
&Ctrl;&Alt;
SCreate a new symlink.
&Ctrl;&Alt;
- Left Arrow
+ &Left;
Left History
list.
&Ctrl;&Alt;
- Right Arrow
+ &Right;
Right History
list.
&Ctrl;&Alt;
=Equal Panel Size (Default Useraction).
&Ctrl;&Alt;&Shift;
N
Duplicate a tab.
&Ctrl;&Alt;&Enter;Open current folder in a
new tab.General &Ctrl; keys&Ctrl;
ASelect all.&Ctrl;
- PageDown
+ &PgDn;
Move to the lower part in the current
directory.&Ctrl;
F1..F12Standard (&plasma;)
key-bindings.
&Ctrl;&Shift;
F1..F12Standard (&plasma;)
key-bindings.Other keysfooQuick search, quick select or quick filter. See this configuration page on how to configure the default mode.	
Switch between the
panels
&Enter;
On a
file: open/execute that file
On an archive
file: browse the archive as if it was a
directory.&Esc;
Will make the menu
bar lose the focus if it has it.
Delete
Delete (or move to
Trash).
&Shift;
Delete
Delete permanently.
- Space
+ &Space;
On a
file: toggle the selection of the file down one
position without affecting the selection of other
files/directories.&Backspace;One directory up.
- Insert
+ &Ins;
- Does the same as the Space key
+ Does the same as the &Space; key
and goes down one
position to toggle the next file.MenuRight-click menu.
- Home
+ &Home;
Cursor jumps to the top of the list.
- End
+ &End;
Cursor jumps to the last file in the
list.Command LineCommand Line keybindings.
- Up arrow and
- Down arrow
+ &Up; arrow and
+ &Down; arrow
Scroll through previously typed
commands.&Ctrl;
/Open the command line history list.&Ctrl;
- Up arrow
+ &Up;
Jump from the command line to the active
panel.&Ctrl;
- Down arrow
+ &Down;
Jump from the active panel to the command
line.
&Ctrl;&Enter;Insert current file / directory name without
path to current command line position.
&Ctrl;&Shift;&Enter;Insert current file / directory with full path
name to current command line position.Terminal emulatorTerminal emulator keybindings.&Ctrl;
FToggle between normal and full screen
Terminal emulator.&Ctrl;
VInsert from clipboard.&Ctrl;
- Up arrow
+ &Up;
Jump from the Terminal Emulator to the active
panel if the Command line is hidden.&Ctrl;
- Down arrow
+ &Down;
Jump from the active panel to the Terminal Emulator
if the Command line is hidden.&Ctrl;&Shift;
Up/Down arrowAlways focus/unfocus the Terminal Emulator independently
whether the Command Line is shown or not. &Shift;
- Insert
+ &Ins;
Insert from clipboard.SynchronizerSynchronizer keybindings.&Ctrl;
WReverse direction&Alt;
- Down arrow
+ &Down;
Exclude&Alt;
- Up arrow
+ &Up;
Restore original task&Alt;
- Left arrow
+ &Left;
Copy to left&Alt;
- Right arrow
+ &Right;
Copy to right&Alt;
DeleteMark for deleteDefault UseractionsDefault UserActions keybindings provided
by &krusader;.&Ctrl;
EEdit a file as root.
&Ctrl;&Alt;
CCopy current item to clipboard.
&Ctrl;&Alt;
MMount a new file system.
&Ctrl;&Alt;
=Equal panel-size.
- Meta
+ &Meta;
AEnqueue in &amarok;.
- Meta
+ &Meta;
1Sort by Name.
- Meta
+ &Meta;
2Sort by extension.
- Meta
+ &Meta;
3Sort the active panel by size.
- Meta
+ &Meta;
4Sort by modified.
- Meta
+ &Meta;
F5
Backup current file (Default Useraction).
Other Key-bindings
Selecting files
KrViewer
Disk UsageLocate &GUI; frontend
- &systemsettings; ->
- Common Appearance and Behavior -> Shortcuts and Gestures
+ Common Appearance and BehaviorShortcuts
+ and Gestures module in the &plasma; &systemsettings;.UserActions configurable
key-bindings
diff --git a/doc/konfigurator.docbook b/doc/konfigurator.docbook
index a38fbbfc..ae00ca72 100644
--- a/doc/konfigurator.docbook
+++ b/doc/konfigurator.docbook
@@ -1,2063 +1,2052 @@
Konfigurator: &krusader;'s Configuration
CenterConfigureKrusaderKonfigurator is &krusader;s configuration
center. When running &krusader;, use
Settings
- Configure &krusader;
+ Configure &krusader;..., and it will start Konfigurator.
There you can modify the way &krusader; works
and customize it to your own needs. At any time, pressing the
Apply button applies the changes, pressing
Close closes Konfigurator, and pressing
Defaults re-applies &krusader;'s
- "factory" settings. Konfigurator is divided into pages, each
+ factory settings. Konfigurator is divided into pages, each
containing items related to that page. For some changes to the
&GUI;, you have to close and restart
&krusader;.Since &krusader;-1.80.0 the Key-Bindings and Main Toolbar-Actions Toolbar
have received their own configuration windows and so they are not a part anymore of Konfigurator,
you can configure them now via the Settings menu.StartupStartup configurationStartup configurationThe startup page determines the way that
&krusader; looks (and works) when it is launched. It
is divided into two main parts:GeneralStartup Profile: Starts the
selected
Panel profile at
startup.
<Last
session> is a special Panel
Profile, it is saved automatically when closing
&krusader;.Show splashscreen: Displays a
splash screen when starting
&krusader;.Single Instance Mode: Allows
only one &krusader; instance to run.Fallback Icon Theme: Allows
you to configure a fallback icon theme for &krusader;.
Whenever icon is not found in system icon theme,
this theme will be used as a fallback.
If the fallback theme does not contain the icon,
Breeze or Oxygen will be used if any of these are present.User InterfaceDetermines which parts of the user interface are
visible after start-up.
Save last position, size and panel
settings: When launched,
&krusader; resizes itself to the size it
was when last shut-down. &krusader; also
appears in the same location on the screen, having
panels sorted and aligned as they were. If this
option is unchecked, you can use the menu
WindowSave Position
option to manually set
&krusader; size and position at
start-up.Update default panel settings: If checked,
the default panel settings will be updated after
start-up.
- Start to tray: if checked,
+ Start to system tray: if checked,
&krusader; starts to tray (if minimize to
tray is set), without showing the main window.Save component settings on exit: If
checked, restores the user interface components to
their condition when last shut-down.Show function keys: If checked,
the FN Keys Bar is visible after
start-up.Show statusbar: If checked, the
Statusbar is visible after
start-up. Available only if the Save component settings on exit item is unchecked.Show command line: If checked,
the Command Line is visible after
start-up. Available only if the Save component settings on exit item is unchecked.Show embedded terminal: If
checked, the Terminal emulator is visible
after start-up. Available only if the Save component settings on exit item is unchecked.PanelHere you can determine the look and feel of panel -
which means finetuning the application to your needs. The page
is divided into six tabs:
General,
View,
Buttons,
Selection Mode,
Media Menu,
and Layout:GeneralNavigator barEdit Mode by default: If checked, show editable path in Navigator bar by default.Show full path by default: If checked, always show full path in Navigator bar by default.Operation
- Autoselect Directories: When
+ Autoselect Folders: When
you select a group of
files (either by using Select Group or by using
Select All), &krusader; checks this option. If
- checked, the directories matching the select criteria are
+ checked, the folders matching the select criteria are
also selected. Otherwise, only files are selected.Rename selects extension: When
- you rename a file, the
- whole text is selected. If you want total commanderlike
- renaming of just the name, without extension, deselect
- this item.
+ you rename a file, the whole text is selected.
+ If you want Total Commander like
+ renaming of just the name, without extension, deselect this item.
Unselect files before copy/move: If checked,
&krusader; remove the selection marks from files or folders before
copying or moving them to
the new location.Filter dialog remembers settings: If checked,
the filter dialog will be opened with the last filter settings that where
applied to the panel.TabsUse fullpath tab names: If checked,
display the full path in the Folder tabs;
otherwise only the last part of the path is
displayed.Show new/close tab buttons: If checked,
&krusader; displays new and close buttons on tabs.Tab Bar position: Lets you choose Tab bar position (Bottom or Top).Show Tab Bar on single tab: If checked,
&krusader; displays the Tab Bar even if there is only one tab on the panel.Search barStart by typing: allows to select if
quick search feature is
used. When checked, you can open search bar and start searching
by typing something while viewing folder contents in the active panel.Case sensitive: When you
use the search
or filter feature:
If checked (the &UNIX; default), all files
beginning with capital letters appear before files
beginning with lower case letters; otherwise, all files
beginning with a specified letter (capital or otherwise)
will be displayed together.
- Up/Down cancels search: Pressing Arrow Up or Arrow Down cancels search bar.
+ Up/Down cancels search: Pressing &Up; or &Down; key cancels search bar.
- Directory navigation with Right Arrow: If checked, pressing the Right arrow key enters directory if no search text editing intention is captured.
+ Folder navigation with Right Arrow: If checked, pressing the &Right; key enters folder if no search text editing intention is captured.
Position: Lets you choose search
and filter bar position (Bottom or Top).Default mode: Lets you choose the search bar default mode between Search, Select
and Filter. You can change the mode later using the search bar itself.Bookmark Search
- Always show search bar: If checked,
- make bookmark search bar always visible.
+ Always show search bar: If checked, make bookmark search bar always visible.
- Search in special items: If checked,
- bookmark search is also applied to special items in bookmark menu like Trash, Popular URLs, Jump Back, &etc;
+ Search in special items: If checked, bookmark search is also applied to special items in bookmark menu like Trash, Popular &URL;s, Jump Back, &etc;
Status/Totalsbar
- Show size in bytes too: If checked,
+ Show size in bytes too: If checked,
&krusader; displays size in bytes on statusbar or totalsbar.
- Show space information: If checked,
- &krusader; displays free/total disk space in the Status-/Totalsbar.
+ Show space information: If checked,
+ &krusader; displays free/total disk space in the Status-/Totalsbar.
ViewGeneralView font: Allows you to change the
font used inside the file lists.Tooltip delay (msec): Allows you to configure the delay in milliseconds
between the moment you have stopped mouse pointer above an item in a file list and the moment when the tooltip will be shown.Use human readable file size: If
checked, the file size appears in kB, Mb
&etc;, and not in bytes (default).
- Numeric permissions: Permission
- column (PanelView tab) shows octal numbers '0755'
- instead of 'rwxr-xr-x'.
+ Numeric permissions: Permission
+ column shows octal numbers '0755' instead of 'rwxr-xr-x'.
Show hidden files: If checked,
- &krusader; displays the "dot-files" which are
+ &krusader; displays the dot-files which are
otherwise hidden.Load the user defined folder icons: If checked,
&krusader; loads the user defined folder icons.Always show current item: If checked,
&krusader; shows current item border decoration in inactive panel.Sort methodKrusader (default):
the comparison used so far. Uses comparison using locale rules (even context rules).
Alphabetical:
strings are compared character by character (no context rules from locale applied).
Alphabet characters are compared using locale rules,
special characters are compared by the character code.
Alphabetical and numbers:
the same as above, but if the names contains numbers, the numbers are compared
numerically instead of alphabetically.
Character code:
comparison by character code (quick).
Character code and numbers:
the same as above, but with numerical comparison of numbers.
Case sensitive sorting: If checked
(the &UNIX; default), all files beginning with
capital letters appear before files beginning with
non-capital letters; otherwise, all files beginning with
a specified letter (capital or otherwise) appear
together.Always sort dirs by name: Sorts
- directories by name, regardless of the sort
+ folders by name, regardless of the sort
column.
- Show directories first: If checked
- directories have precedence in folder lists.
+ Show folders first: If checked
+ folders have precedence in folder lists.
Locale aware sorting: Sorts
- files and directories according to the current locale settings.
+ files and folders according to the current locale settings.
View modesDefault view mode: Allows you to
change the default view mode. You can choose Detailed View or Brief View. On tabs of both view modes you can define the following options.Default icon size: Allows you to
change the size of the icons in the file lists. The
- available sizes are 16x16, 22x22, 32x32 and 48x48
+ available sizes are 12x12, 16x16, 22x22, 32x32, 48x48, 64x64, 128x128 and 256x256
pixels.Use icons in the filenames: If checked,
show the icons in file names and folders.Show previews by default: If checked,
show the previews of file contents.To configure the columns use the right click menu in the panel when viewing files.
The left and right panel use their own columns independently.
The following columns are available:
Name: Shows the filename without the part after the last dot,
this latter part is displayed in the Ext column. When the Ext column is made hidden,
the complete filename is shown in the Name column like ⪚ &konqueror; does.
Ext: Shows the last part of the
filename (the part after the last dot) in the Ext
column, and not as a complete filename in the Name column
like ⪚ &konqueror; does.
- Type: Shows the MIME type
+ Type: Shows the &MIME; type
field.Size: Shows the size
field.Modified: Shows the modified
date and time field.
- Perms: Shows the full permissions
- ⪚ "rwxr-xr-x" or as octal numbers
- '0755' instead with enable/disable
+ Perms: Shows the full permissions,
+ ⪚, 'rwxr-xr-x' or as octal numbers
+ '0755' instead with enable/disable
Numeric Permissions in
- Panel
- View Tab.
+ Panel View Tab.rwx: Shows only the rights of
- the current user ⪚ "-rw".
+ the current user, ⪚, -rw.
Owner: Shows the owner
field.Group: Shows the group
field.Uncheck the columns not in use. This allows more
space for columns in use.ButtonsToolbar buttons have icons: If checked,
&krusader; displays icons on toolbar buttons.Show Media Button: If checked,
&krusader; displays media button.Show Back Button: If checked,
&krusader; displays back button.Show Forward Button: If checked,
&krusader; displays forward button.Show History Button: If checked,
&krusader; displays history button.Show Bookmarks Button: If checked,
&krusader; displays bookmarks button.Show Panel Toolbar: If checked,
&krusader; displays the Panel Toolbar.You can make the buttons on the
Panel Toolbar visible or hidden:
Visible Panel Toolbar buttonsEqual button (=)Up button (..)Home button (~)Root button (/)Toggle-button for sync-browsing: If
checked, shows the Sync-browsing
button.Selection ModeHere you can configure the selection modes.
General&krusader; Mode: The way
&krusader; has worked from day one. Both mouse
keys allow selecting files. To select more than one file,
hold the &Ctrl; key and click the
&LMB;. Right-click menu appears with a short
click on the &RMB;.
- Konqueror Mode: pressing the
+ &konqueror; Mode: pressing the
&LMB; selects files --
you can click and select multiple files. Right-click menu
appears with a short click on the
&RMB;.Total commander Mode: Pressing the
&RMB; selects multiple files
and the right-click menu appears with
pressing and holding the
- &RMB;. The Left Mouse Button does not select,
+ &RMB;. The &LMB; does not select,
but sets the current file without affecting the current
selection.Ergonomic Mode:
The &LMB; does not select, but sets the current file without affecting the current selection.
The &RMB; invokes the context-menu. You can select with &Ctrl; key and the left button.Custom Selection Mode: Create your
own selection style!DetailsDouble-click selects (classic): A
single click on a file will select and focus, a double
- click opens the file or steps into the directory.
+ click opens the file or steps into the folder.Obey global selection policy:
Pressing the &LMB; selects files -- Use
- global setting: &plasma;
- System Settings -> Input Devices
- -> Mouse.
+ global setting: Input DevicesMouse
+ module in the &plasma; &systemsettings;.
Custom Selection Mode items:
Based on &plasma;'s selection mode
- Left mouse button selects
+ &LMB; selects
- Left mouse button preserves
- selection
+ &LMB; preserves selection
- &Shift;/&Ctrl;-Left mouse button
- selects
+ &Shift;/&Ctrl;left clicking selects
- Right mouse button selects
+ &RMB; selects
- Right mouse button preserves
- selection
+ &RMB; preserves selection
- &Shift;/&Ctrl;-Right mouse button
- selects
+ &Shift;/&Ctrl;right clicking selectsSpacebar moves downInsert moves downRight-clicking pops context menu
immediatelyMedia MenuUsing this tab you can select the Media button menu contents:
Show Mount Path: show the mount path of partition if checked.Show File System Type: show the file system type of partition if checked.Show Size: allows selection of the size representation in media menu. Can be Always (default, always show the size of partition), When Device has no Label (show the size for partitions with no label only) or Never (never show the size in media menu).LayoutYou can choose the layout and frame settings:
Layout: allows to define layout. The default options are Default, Compact, and Classic.Frame Color: defines frame color. Can be Defined by Layout, None, or Statusbar.
- Frame Shape: defines frame color. Can be Defined by Layout, None, or Statusbar.
+ Frame Shape: defines frame color. Can be Defined by Layout, None, Box, or Panel.
- Frame Shadow: defines frame color. Can be Defined by Layout, None, or Statusbar.
+ Frame Shadow: defines frame color. Can be Defined by Layout, None, Raised, or Sunken.
ColorsThis page configures the colors of the
List Panel and the
Synchronizer. The
- KDE default colors is the default color
+ &kde; default colors is the default color
configuration.General
- Use the default KDE colors: this
+ Use the default &kde; colors: this
is the default, it uses &plasma; color
defined in the &systemsettings;.Use Alternate Background color:
If checked, the
Background color and the
Alternate background color
alternates line by line. When you do not use the
&plasma; default colors, you can configure
the alternate colors in the
Colors box.Show current item even if not
focused: If checked, shows the last cursor
position in the non active list panel. This option is
only available when you do not use the
&plasma; default colors.Dim the colors of the inactive
panel: If checked, the colors of the
inactive panel are dimmed. These settings can be
configured in the
Inactive tab of the
Colors box. This option is only
available when you do not use the &plasma;
default colors.ColorsConfigure the colors the way you like, you can see
the result in the
Preview section. The following items
of the active and inactive panel can be
configured:Foreground
- Directory foreground
+ Folder foregroundExecutable foregroundSymbolic link foregroundInvalid symlink foregroundBackgroundAlternate backgroundSelected foregroundSelected backgroundAlternate selected backgroundCurrent foregroundSelected current foregroundCurrent backgroundThe following items of the
Synchronizer can be configured:Equals foregroundEquals backgroundDiffering foregroundDiffering backgroundCopy to left foregroundCopy to left backgroundCopy to right foregroundCopy to left backgroundDelete foregroundDelete backgroundPreviewHere you see a preview of the configured
colors.Color schemesWith the
Import Color Scheme and
Export Color Scheme buttons you can
load and save a Color Scheme profile. This allows
&krusader; to use Total Commander,
Midnight Commander, foo-commander or your own custom color
profile. The Color Schemes are stored in
/usr/share/krusader, the
foo.color is a binary file that holds
the color scheme.Midnight Commander and Total Commander Color
scheme files are provided. Please
upload your favorite
Color schemes so that they become available for
the &krusader; community. Thanks!GeneralHere you configure the basic operations. The page is divided into three tabs:
General,
Viewer/Editor,
and Atomic extensions.GeneralThe following options determine basic aspects of operation:Warn on exit: if checked, &krusader;
warns you every time when exit action is triggered.
- Minimize to tray: If checked, the &krusader;
+ Show and close to tray: If checked, the &krusader;
icon will appear in the system tray.
When you minimize &krusader;, it will not appear in the taskbar.
It also will not exit if you close the main window.
- Instead you can quit &krusader; by selecting Quit from the File menu
- or the context menu of the tray icon.
+ Instead you can quit &krusader; by selecting File
+ Quit menu item or the context menu of the tray icon.
- Use MIME type magic: MIME type magic is
+ Use &MIME; type magic: &MIME; type magic is
a mechanism which allows &krusader; to inspect
the files in the panels and determine their type even if
the file has no identifying extension. For example, if you
take an image file - image1.jpg - and rename it to
image1, &krusader; will still know it is an
image file and work with it accordingly. However, this mode
of operation is slower (while refreshing the panel, or
- changing directories), so try &krusader; with
- and without MIME type magic and decide what is best for
+ changing folders), so try &krusader; with
+ and without &MIME; type magic and decide what is best for
you.
- Temp Directory: this option selects
- the base directory for &krusader;'s temporary
+ Temp Folder: this option selects
+ the base folder for &krusader;'s temporary
files. The actual files will be created in separate
- directories under the 'Temp directory', so that each user
+ folders under the 'Temp folder', so that each user
running &krusader; will have their own temporary
- subdirectories under the chosen directory.
+ subfolders under the chosen folder.
- You must choose a temporary directory to which all
+ You must choose a temporary folder to which all
users running &krusader; have full
permissions!Delete mode (Delete files/Move to trash): when
&krusader; deletes files it can either really
delete them or move them to the trash folder, thereby
making them available via &plasma;'s trash.
External Terminal: choose which terminal
emulator will be used when &krusader; opens a
console window (via F9, or ToolsStart Terminal
menu option).
Embedded Terminal sends Chdir on panel
change: if unchecked, there will be no
cd command sent to the Terminal Emulator
if the panel folder changes.Toggle Fullscreen Embedded Terminal: if checked,
&krusader; shows fullscreen terminal in
Midnight Commander style (Terminal is shown
instead of &krusader; window).
Viewer/EditorHere you can change the viewer and editor settings:
Internal editor and viewer opens each file in separate window: check this
item if you want each file to be opened in separate window.
Default viewer mode:
Generic mode: use the systems default viewer.Text mode: view the file in text-only mode.Hex mode: view the file in hex-only mode.Lister mode: Fast text/hexadecimal viewer for huge filesizes.
&krusader; lister never loads the whole file into memory, just a little part of it, and uses caching for faster scrolling.
Remote files are downloaded, but during the download, viewing the downloaded part is possible.
If a file constantly changes, then it can also be viewed, lister will always see its current state.Use lister if the text file is bigger than: 10 MB (default value):
checks whether a text file is bigger than 10 MB (configurable), and if yes,
then &krusader; Lister is used instead of &plasma;'s default viewer.Use Okteta as Hex viewer:
if checked (default option), use &plasma; hex editor Okteta to view
raw data. To use this option you should install Okteta package first.Editor: choose what editor will be
used when editing a file (via F4). Default the internal viewer is used,
this is the &plasma;'s default viewer.Atomic extensionsAtomic extensions: predefined atomic extensions like .tar.gz
are shown as one part in the Ext Column of the List Panel.AdvancedThis page handles more advanced issues, so you should
double-check your actions here: modifying settings here
makes &krusader; a more powerful and
dangerous tool.The page is divided into three parts:GeneralAutomount filesystems: this
makes &krusader; try to mount a file system
before entering it. For example, if you click on
/mnt/cdrom (and
/mnt/cdrom appears in
/etc/fstab as a
mount point), &krusader; will check if it
is mounted. If not, it will try and mount it for you
and then enter, so that you would see the contents of
- your cdrom. Note, however, that &krusader;
+ your &CD-ROM;. Note, however, that &krusader;
will NOT unmount when exiting
/mnt/cdrom.MountMan will not (un)mount the following
mount points: If you have file systems that
you do not want to accidentally unmount (or mount)
then enter a list of mount points separated by commas
(⪚
/, /boot, /tmp) and
MountMan will not try to (un)mount
them.ConfirmationsBy checking the options in this section,
&krusader; will ask for confirmation before
doing a specific action; otherwise, the following actions
will be done without warning:
- deleting non empty directories
+ Deleting non-empty folders
- deleting file(s)
+ Deleting files
- copying file(s)
+ Copying files
- moving file(s)
+ Moving filesFine-Tuning
- Icon Cache Size:
+ Icon cache size (KB):
&krusader; uses an icon cache, so it will not
have to reload icons that have been used before. Of
course, as the cache grows bigger, it can store more
icons and further speed operations, but the memory
footprint of &krusader; will become
bigger.Arguments of updatedb: sets
additional arguments for
updatedb, please read the manpages
for more information.Archives
This page configures some aspects of archive handling in &krusader;.
krarc ioslaveEnable Write Support: this
option allows you to enable writing files into an archive.
The down side is that if a power failure occurs
during the process, the files that were moved might
already be deleted, but not yet packed into the archive.
Moving archives into themselves will delete them.
Archive handling
- Browse Archives As Directories: if checked,
- &krusader; will handle the archives transparently and let you open them as
- folders; otherwise, &krusader; will attempt to
- invoke an application which opens archives of that type.
+ Browse Archives As Folders: if checked, &krusader;
+ will handle the archives transparently and let you open them as folders;
+ otherwise, &krusader; will attempt to invoke an application which opens archives of that type.
Fine-Tuning
- Test archives after packing:
+ Test archive after packing:
this option automatically runs a test on a newly packed
archive. It is safer, but takes longer.Test archives before unpacking:
this option automatically runs a test before unpacking.
Some corrupted archives might cause a crash; therefore, it is
better to test archives before unpacking.Dependencies pageThis page configures the full path of the external
applications. It is even possible to configure the full path of
&krusader;!General tabHere you can configure the full path of the following external applications:applicationconfigurable full pathkdesu/usr/bin/kdesukget/usr/bin/kgetmailer/usr/bin/kmaildiff utility/usr/bin/komparekrename/usr/bin/krenamekrusader/usr/bin/krusaderlocate/usr/bin/locatemount/bin/mountumount/bin/umountupdatedb/usr/bin/updatedbBy default &kompare; is used as external diff utility but you can also
use your favorite diff utility ⪚
xxdiff or KDiff3, just fill
in the full path and enjoy.Packers tabIn the
Packers tab you will see a list of
archive formats. Some are filled and some are empty. The
ones that are available (filled) are supported by
&krusader;. For them, &krusader;
will handle the archives transparently and let you open them as
- folders (provided you have checked the Browse Archives As Directories
+ folders (provided you have checked the Browse Archives As Folders
item in the Archives section); otherwise, &krusader; will attempt to
invoke an application which opens archives of that type. If a
certain archive item is empty, it means that
&krusader; could not find the appropriate executables
in the configured path. The next archives are supported: ace,
arj, bzip2, deb, gzip, iso, lha, lzma, rar, rpm, tar, xz, zip and
7z.packerconfigurable full path7zusr/bin/7zarjusr/bin/arjbzip2usr/bin/bzip2cpio/bin/cpiodpkg/bin/dpkggzip/usr/bin/gziplha/usr/bin/lhalzma/usr/bin/lzmarar/usr/bin/rartar/bin/tarunace/usr/bin/unaceunarj/usr/bin/unarjunrar/usr/bin/unrarunzip/usr/bin/unzipzip/usr/bin/zipxz/usr/bin/xz&krusader; may not be compatible with ACE despite our
best efforts. Unace uses closed source and contains
additional lines that make Unace get into infinite loop if
the stdin is redirected to somewhere else. It works in the
same manner as 'su', where you cannot enter the password only
from the stdin. &krusader; >= 1-51
emulates the command line environment to enable co-operation
with Unace, but we have noticed that Unace always changes its
output format from release to release, making co-operation
almost impossible.Checksum Utilities tabHere you can configure the full path of the following
external
Checksum Utilities:
Checksum Utilitiesconfigurable full pathsupported checksumsmd5sum/usr/bin/md5summd5sha1sum/usr/bin/sha1sumsha1md5deep/usr/bin/md5deepmd5sha1deep/usr/bin/sha1deepsha1sha224sum/usr/bin/sha224sumsha224sha256sum/usr/bin/sha256sumsha256sha256deep/usr/bin/sha256deepsha256sha384sum/usr/bin/sha384sumsha384sha512sum/usr/bin/sha512sumsha512tigerdeep/usr/bin/tigerdeeptigerwhirlpooldeep/usr/bin/whirlpooldeepwhirlpoolcfv/usr/bin/cfvmd5, sha1, sfv, crcUserActionsHere you can configure the terminal for UserActions and
the font for the output-collection. The default terminal is
konsole --noclose -e. To set up, configure
and manage your UserActions use ActionMan
(UserActions &URL;).Protocols
- This page links the MIMEs to protocols. ⪚
- protocol "tar" is linked to MIME "application/x-tar".
+ This page links the &MIME;s to protocols. ⪚
+ protocol tar is linked to &MIME; application/x-tar.In the
Links you will see ⪚
Isoapplication/x-isokrarcapplication/x-aceapplication/x-arjapplication/x-bzip2application/x-cpioapplication/x-debapplication/x-debian-packageapplication/x-gzipapplication/x-jarapplication/x-lhaapplication/x-rarapplication/x-rpmapplication/x-ziptarapplication/x-tarapplication/x-tarzapplication/x-tbzapplication/x-tgz
diff --git a/doc/locate.docbook b/doc/locate.docbook
index d61ecba4..6016125d 100644
--- a/doc/locate.docbook
+++ b/doc/locate.docbook
@@ -1,131 +1,131 @@
Locate &GUI; FrontendLocate&krusader; has a &GUI; front end for
the
locate command (findutils). Locate is used for
fast file searching not from a directory but a database. The
package contains among other files,
locate and
updatedb. updatedb goes through the local
file system and stores the file entries in the database.
cron often calls
updatedb every night (set with KCron). Choose
Tools
- Locate
+ Locate...
or
&Ctrl;&Shift;
L to start this feature.
Konfigurator can set
additional arguments for
updatedb.Checkbox Options
Show only the existing files: if the
database contains entries which no longer exist any more
(deleted, moved since the last
updatedb),
locate does not list them. It checks the
existence of each file before the listing in the results
window (slow).Case Sensitive: unchecking it allows
lower and upper case search.Action buttons
Locate: executes
locate
foo foo and places its
output into the results window.Stop: stops the locating
process.UpdateDB: starts
updatedb for updating the locate database
after entering the root password.Close: closes the locate
window.Results window
Double-click on an item: steps to its directory, makes
the item visible and closes the locate dialog.Right click: edits/views/finds the menu.
F3: views the current item.F4: edits the current item.&Ctrl;
F: finds files in the results
window.&Ctrl;
N: shows the next search
result.&Ctrl;
P: shows the previous search
result.
The results window supports dragging items to other windows
and copy to clipboard (&Ctrl;C).
diff --git a/doc/menu-commands.docbook b/doc/menu-commands.docbook
index 02543dcc..116b868d 100644
--- a/doc/menu-commands.docbook
+++ b/doc/menu-commands.docbook
@@ -1,1848 +1,1848 @@
Menu CommandsCommandsMenuFile Menu&Shift;
F4File
- New Text File
+ New Text File...Creates a new text file in the current directory,
unless another directory is specified. The new file is
opened for editing after it is created.F7File
- New Directory
+ New Folder
- Creates a new directory in the current
- directory.
+ Creates a new folder in the current
+ folder.
&Alt;&Ctrl;
SFile
- New Symlink
+ New Symlink...Creates a symbolic link to the currently selected
file.F3FileView FileOpens the currently selected file for
viewing.F4FileEdit FileOpens the currently selected file for
editing.F5FileCopy to other panelCopy the currently selected
files or directories to the other panel.F6FileMoveOpens a dialog to
move the currently selected
files or directories to a specified location.&Alt;&Shift;
PFile
- Pack
+ Pack...Creates a
new archive of all the
selected files and directories in the active
panel.&Alt;&Shift;
UFile
- Unpack
+ Unpack...
Unpacks all the
selected files in the active panel.&Alt;&Shift;
EFileTest Archive
Tests archive for
corruption.File
- Compare by Content
+ Compare by Content...Compares two current files by content - one from
each panel via an external graphical diff utility. By
default &kompare; is used, but you can also use ⪚
xxdiff or KDiff3 ,
change it in the
Konfigurator Dependencies page.&Shift;
F2File
- Multi Rename
+ Multi Rename...This menu option starts Krename, a
very powerful external batch renamer.Krename FeaturesRenaming a list of files based on a set of
expressionsCopying/moving a list of files to another
directoryConvert filenames to upper/lower caseAdding numbers to filenamesFinding and replacing parts of the
filenameRenaming MP3/OGG Vorbis files based on their
ID3 tagsSetting access and modification datesChanging permissions and file ownershipA plugin API which allows you to extend
KRename's featuresRenaming directories recursivelySupport for KFilePluginsUndo renamingAnd many more....File
- Create Checksum
+ Create Checksum...
Checksum creation on
file(s) and/or folder(s).File
- Verify Checksum
+ Verify Checksum...
Verify Checksum
&Ctrl;
PFile
- Split File
+ Split File...The Split file function splits a
file up into multiple smaller files so that it can be
stored on several smaller media (like
diskettes, zip-drives, ...) or sent by
e-mail.&Ctrl;
BFile
- Combine Files
+ Combine Files...The Combine files function combines
multiple files into one file after the
Split file function was used.&Ctrl;
QFileQuitCloses &krusader; and cleans up the
temporary directory, the same as pressing
F10 key.Edit Menu&Ctrl;
XEditCut
Cuts the selected file(s)
to the clipboard to be moved to another location.&Ctrl;
CEditCopy
Copies the selected file(s)
to the clipboard to be moved to another location.&Ctrl;
VEditPaste
Pastes previously cut or
copied items from the clipboard to the current
directory.F8EditDelete
Deletes the currently
selected file(s).&Ctrl;
+Edit
- Select Group
+ Select Group...Opens a dialog which allows you to select files in
the active panel. In the
Search for dialog place the main
search criteria. Enter a filename, a wildcard (
*.o.*,
*.c &etc;)
or both - separated by a space. When using
'text', the results are the same as
'*text*'. You can exclude files from
the search with '|' (⪚
'*.cpp *.h |
*.moc.cpp'). With the
profile handler you can
manage your selections for future usage. A double-click
on a profile is the same as entering the selection and
pressing the
OK button. More options for
Select Group dialog are explained in
the
Search dialog, which
are basically almost the same dialogs.&Ctrl;
-Edit
- Unselect Group
+ Unselect Group...The opposite of
Select Group. The files that
match the pattern in the active panel will be
deselected.&Alt;
+EditSelect AllSelects all files in the active panel. You can also
select all directories by activating the
Autoselect directories option in the
Konfigurator Panel page.&Alt;
-EditUnselect AllUnselects all the files in the active panel.&Alt;
*EditInvert SelectionInverts the selection status of all the files in
the active panel (&ie; selected files will
become unselected and deselected files will become
selected).EditRestore SelectionRestore the selection status of previously unselected items.&Ctrl;
FEdit
- Find in folder
+ Find in folder...Toggles &krusader;
quick search function.&Alt;&Shift;
CEditCompare DirectoriesToggles &krusader;
Compare Directories function.EditCompare SetupConfigures the
Compare Directories function.Select Newer and Single (default)Select SingleSelect NewerSelect Different and SingleSelect DifferentEditCalculate Occupied Space
Calculates occupied
space of files and folders, archives and remote
filesystems.&Alt;
ReturnEdit
- Properties
+ Properties...Opens the properties dialog for the currently
selected file. (KP refers to Key Pad.)Go Menu&Alt;
- Up
+ &Up;
GoUpNavigates to the parent directory of the active
panel.&Alt;
- Left
+ &Left;
GoBackNavigates to the previously viewed directory in the
active panel.&Alt;
- Right
+ &Right;
GoForwardNavigates to the next viewed directory in the
active panel. Becomes available only if GoBack was used beforehand.&Alt;
- Home
+ &Home;
GoHomeNavigates to the home directory of the current
user.&Ctrl;
&Backspace;GoRootNavigates to the root directory of the
system.&Ctrl;
ZGo
- Popular URLs
+ Popular &URL;s...Displays a listing of frequently viewed directories
from which you may navigate to one by double-clicking on
it.
&Ctrl;&Shift;
JGoSet Jump Back Point
- Sets the current directory as a "jump back" point.
+ Sets the current directory as a jump back point.
To navigate to this directory quickly, select the Jump
Back command from the Go menu.&Ctrl;
JGoJump Back
- Returns to a previous "jump back" point.
+ Returns to a previous jump back point.View MenuThe action in this submenu usually affects the current
&krusader; session. If you want to make permanent
changes use Konfigurator Startup page.ViewZoom InIncrease the view scale.ViewZoom OutDecrease the view scale.ViewDefault ZoomReset the view scale.
&Alt;&Shift;
DViewDetailed ViewShows the file names, file size, creation date and time and their attributes.
&Alt;&Shift;
BViewBrief ViewShows only the file names.&Alt;
.ViewShow Hidden FilesToggles the option to display the hidden files in
the &krusader; panels.&Shift;
F10ViewAll FilesTurns off all filters and display all files.&Shift;
F12ViewCustomAllows you to install a custom filter on the
&krusader; panel. Only files that match the
filter pattern(s) and directories will be displayed. Do
not forget to deactivate the custom filter after use, or
some files may not be visible.ViewShow PreviewsIf checked, show the previews for all files and folders on the active panel.ViewSelect Remote CharsetSelects the remote charset for
Remote Connections.&Ctrl;
RViewReloadRefreshes the contents of the active panel.ViewSave settings as defaultAllows you to save the view settings of the current tab for new instances of this view type.ViewApply settings to other tabsAllows you to apply the view settings of the current tab to the other tabs.Useractions MenuYou can add your own menu entries here by defining your own UserActions.
UseractionsManage User Actions...Opens the UserActions
manager.
- Meta
+ &Meta;
AUseractionsMultimediaEnqueue in AmarokAppends selected item(s) to &amarok; playlist.
&Ctrl;&Alt;
UseractionsSamplesEqual panel-sizeSets the ratio between the two panels to
50/50.
&Ctrl;EUseractionsSamplesEdit as rootAllows you to edit a file with kwrite using root
permissions.
&Ctrl;&Alt;MUseractionsSamplesMountMounts a new filesystem.
&Ctrl;&Alt;CUseractionsSamplesCopy current item to
clipboardCopies current item name to the clipboard.
- MetaF5
+ &Meta;F5UseractionsSystemBackup currentBackups current file in current directory and asks the user for a new filename.
By default .old is appended to the original filename.
- Meta
+ &Meta;
1UseractionsUser InterfaceSort By NameWhen this action is turned on, the main sorting key
in the &krusader; panel becomes the file
name.
- Meta
+ &Meta;
2UseractionsUser InterfaceSort By ExtensionWhen this action is turned on, the main sorting key
in the &krusader; panel becomes the file
extension (the part of the filename after the last '.').
This is useful for grouping files of the same type closer
together.
- Meta
+ &Meta;
3UseractionsUser InterfaceSort By SizeWhen this action is turned on, the main sorting key
in the &krusader; panel becomes the file size.
This is useful for determining the largest files in a
particular directory.
- Meta
+ &Meta;
4UseractionsUser InterfaceSort By ModifiedWhen this action is turned on, the main sorting key
in the &krusader; panel becomes the last
modified date for each file. This is useful for finding
files you recently worked on.Tools Menu&Ctrl;
STools
- Search
+ Search...Opens
KruSearcher - the
&krusader; search module.
&Ctrl;&Shift;
LTools
- Locate
+ Locate...Opens the Locate &GUI; frontend for fast file
searching.&Ctrl;
YTools
- Synchronize Directories
+ Synchronize Folders
- The Synchronize Directories function compares the
+ The Synchronize Folders function compares the
left and right panels and shows the differences between
them. After the compare function, you can move
files/directories so that they can be
synchronized.&Alt;
/Tools
- MountMan
+ MountMan...Opens submenu with items to open
MountMan or mount/unmount
various mounting points.&Alt;&Shift;
STools
- Disk Usage
+ Disk Usage...Opens Disk Usage.&Ctrl;
NToolsNew Net ConnectionOpens the
New Network
Connection dialog to start a &FTP;, SMB,
FISH or SFTP connection to a remote host. If you leave
the user name and password fields empty, you will login as
anonymous. You can
Bookmark these remote
sessions.
&Ctrl;&Shift;
DToolsDisconnect From NetEnds the
remote
connection in the active panel and returns to the
start-up path.ToolsStart TerminalOpens a terminal window in the default directory
(usually your home directory). You can choose your
favorite terminal application in the
Konfigurator General page.&Alt;&Shift;
KToolsStart Root Mode KrusaderStarts &krusader; in Root mode at the same location.
Root mode &krusader; requires kdesu by default,
if kdesu is not available or if you prefer ⪚
gksu when using GNOME you can change this behaviour in the
Konfigurator Dependencies page.Be careful when using &krusader; with
ROOT PRIVILEGES.ToolsEmpty TrashEmpties the trash bin.Window Menu
&Ctrl;&Shift;
NWindowNew TabOpens a new tab in the active panel.WindowLock Tab/Unlock TabLocks then unlocks current tab in the active panel.
&Ctrl;&Alt;&Shift;
NWindowDuplicate Current TabOpens a new tab that is a duplicate of the active
tab in the active panel.
&Ctrl;&Shift;
OWindowMove Current Tab to Other SideMoves current tab to the other side of &krusader; window.&Ctrl;
WWindowClose Current TabCloses the current tab in the active panel. This
command is only available if there is more than one tab
in the active panel.WindowClose Inactive TabsCloses all the tabs in the active panel except for the active.WindowClose Duplicated TabsCloses the duplicated tabs in the active panel.&Ctrl;
.WindowNext TabNavigates to the next tab in the active panel. This
command is only available if there is more than one tab
in the active panel.&Ctrl;
,WindowPrevious TabNavigates to the previous tab in the active panel.
This command is only available if there is more than one
tab in the active panel.&Alt;&Shift;
LWindowProfilesOpens a menu where
Panel profiles can
be saved and restored.&Ctrl;
UWindowSwap PanelsThe left panel will become the right panel and vice
versa, only the current tabs will be swapped.
&Ctrl;&Shift;
UWindowSwap SidesThe complete left panel will become the right panel
and vice versa, and all tabs will be swapped.
&Ctrl;&Alt;
RWindowVertical ModeToggles the List Panel between
horizontal and vertical mode.&Ctrl;&Alt;
FWindowToggle Fullscreen Terminal
EmulatorToggles full screen mode of the terminal emulator.
This option is only available when Show Terminal
Emulator is activated.WindowSave PositionSaves the current size and position of the
&krusader; main window. This action can be
automated with
Save last position, size and panel settings in
Konfigurator Startup pageSettings MenuSettingsToolbarsShow Main ToolbarShows the Main Toolbar if
checked.SettingsToolbarsShow Job ToolbarShows the Job Toolbar if
checked.SettingsToolbarsShow Actions ToolbarShows the Actions Toolbar if
checked.SettingsShow StatusbarShows the
Statusbar if
chosen.SettingsShow FN Keys BarShows the FN Keys Bar if
checked.
&Ctrl;&Alt;
TSettingsShow Terminal EmulatorShow the
Terminal Emulator if
checked.SettingsShow Command LineShows the
Command Line if
checked.SettingsCommand Execution Mode SetupAllows you to choose command execution mode. You can choose one
of the following options.Start and Forget: start execution and do not wait for the results.Display Separated Standard and Error Output: show the output to stdout and stderr on the separate panels.
Display Mixed Standard and Error Output: show the output to stdout and stderr on the single panel (default).
Start in New Terminal: execute the command in the new terminal window.
Send to Embedded Terminal Emulator: send the command to the embedded terminal emulator.
SettingsJob Queue Mode
Toggles the Queue Manager mode. If checked then pressing F2 or the corresponding button in the copy/move dialog immediately starts the job even if there are running jobs in queue. If unchecked then the job will be put into the queue if the queue is not empty. Otherwise the job will be started immediately.
Settings
- Configure Shortcuts
+ Configure Shortcuts...ConfigureShortcutsOpens a dialog which allows you to configure the
&krusader; key bindings.With the
Import shortcuts and
Export shortcuts buttons you can
load and save a Key-binding profile. This allows
&krusader; to have the Total Commander,
Midnight Commander, foo-commander, or your custom
Key-bindings. The only limitation is that global
&plasma; key-bindings and some
&krusader; key-bindings cannot be changed yet,
as well as some features in foo-commander that we either
do not have or need. The Key-bindings are stored in
/usr/share/krusader,
foo.keymap.info contains a
description,
foo.keymap is an ini file that holds
the Key-bindings. Until &krusader;-1.70.1 this
was a binary file, &krusader; is backwards
compatible for importing this legacy binary format. If a
*.keymap.info text file exists,
&krusader; will display it, showing additional
information regarding the loaded Key-bindings file. Here
you have a chance to exit without importing the proposed
Key-bindings file.A Total Commander Key-bindings file is
provided. Please
upload your favorite
Key-bindings schemes so that they become
available for the &krusader; community.
Thanks!Settings
- Configure Toolbars
+ Configure Toolbars...Opens a dialog which allows you to configure the
Main Toolbar or the
Actions Toolbar. You can add action
buttons of your favourite UserActions to
the desired toolbar.SettingsConfigure
- &krusader;
+ &krusader;...
Opens
Konfigurator - the
&krusader; configuration center.Help Menu
Additionally, &krusader; has the common &kde; Help menu items, for more information read the sections about the Help Menu of the &kde; Fundamentals.
diff --git a/doc/mount.docbook b/doc/mount.docbook
index c607e280..6ff28f27 100644
--- a/doc/mount.docbook
+++ b/doc/mount.docbook
@@ -1,89 +1,89 @@
MountMan: work with your mounted file systemsMountMountMan is a tool which helps you manage your mounted file systems. Once
invoked, it displays a list of every mounted file system. For each file system,
MountMan displays its name (which is the actual device name - &ie; /dev/sda1 for a first partition on first
HDD), its type (ext4, ext3, ntfs, vfat, ReiserFS...)
and its mount point on your system (the directory on which the file system
is mounted).If you want filter out non-removable devices from the list,
just check the item Show only removable devices
at the left of the device list.
MountManMountManMountMan also displays usage information using total size,
free size, and percentage of available space free. If those
numbers say
N/A, that usually means that the file system
is not mounted. Left clicking on a file system displays a pie chart
on the left of the window, graphically displaying the usage
information for the file system. Clicking on a non-mounted
file system will display
not mounted instead of the graph.Double-clicking on a file system will close
MountMan and open that file system inside
&krusader;'s active panel.Right-clicking on a file system will open a
small menu which displays what actions can be performed on
that file system. At the moment, you can only mount, unmount
and eject (if clicking on a removable file system, ⪚, a
&CD-ROM;).We plan to expand MountMan in the next evolution of &krusader;. It will be able
to format partitions, edit /etc/fstab,
create new file systems and more.... By the way, we have started working on it,
- see "Quickmode for MountMan".
+ see Quickmode for MountMan.
Quickmode for MountManTo activate Quickmode for MountMan, click lateral button with arrow on the
MountMan button on the Main Toolbar.General idea: display a list of all possible mount points.
Each time the menu is displayed, it determines if a mount point is
mounted or not and associates the correct action (mount or
umount). This offers a quick interface to MountMan. It is
working, and currently uses KMountMan::mount and unmount. It uses
the new &kf5-full; services for fstab-reading and this will
- enable us to remove a lot of code from the "old" MountMan.
+ enable us to remove a lot of code from the old MountMan.
diff --git a/doc/release-overview.docbook b/doc/release-overview.docbook
index 36e04a9b..98f9aa2d 100644
--- a/doc/release-overview.docbook
+++ b/doc/release-overview.docbook
@@ -1,741 +1,741 @@
Release overviewRelease overviewThis appendix gives an overview of the
&krusader; releases.
Note: older 0.x beta releases are not included in this
table.
diff --git a/doc/remote-connections.docbook b/doc/remote-connections.docbook
index 3a91a2f6..b6b1fdb4 100644
--- a/doc/remote-connections.docbook
+++ b/doc/remote-connections.docbook
@@ -1,281 +1,281 @@
Remote ConnectionsRemote ConnectionsRemote connections are easily made by typing the
&URL; in the
Location Toolbar; these are
actually KIO Slaves. Please note that the
&krusader; panel does not support all
KIO Slave ⪚
http:// will not work in the panel, but will
work in the
viewer. Some examples:ftp://public.ftpserver.org/directory/fish://username@hostname/sftp://username:password@sftp.foo.org/ftp://username@my.server.org:21/directory/smb://username:password@server/shareftp://username@proxyusername:password@proxipassword@hostname/directorynfs://<host>:<port><url-path>webdav://www.server.com/path/You can bookmark these &URL;s, however, please
read the
Bookman section regarding
securely save passwords. For connecting to
multiple locations, bookmark these &URL;s and open
them one by one, or open them all together by using
Panel profiles. To switch from one to another
location, just open a Folder tabs for
each.There are three ways to start a remote connection:Type the &URL; in the
Location ToolbarSelect
ToolsNew Net Connection
which will pop-up a dialog that will ask for the
remote site details. This dialog is handy if you are not used
to type remote &URL;s in the Location Toolbar.
Leaving the password and user name fields empty will log you
in as anonymous. Note: we are planning to rewrite this dialog
window.You can bookmark a directory on a remote host and
return to this directory from the bookmark button on the top
corner of your panel just like in a web browser.After you log on to a remote server you can browse it just
like your local hard drive with the following exceptions:You cannot execute files on remote servers.Permissions cannot always be calculated on remote
servers (depends on server and access method) so you might
get a ? on the permissions columns for some files.Disk usage information is not available for most remote
filesystems.To change the charset of the remote host use
ViewSelect Remote Charset
.You can close the current Active Remote
Connection by two separate methods:Manually: Add the disconnect button to the
Main Toolbar and click on it.Automatically: Change the &URL; in the
Location Toolbar .&krusader; is a file manager that supports
remote connections via KIO Slaves, but if you
are looking for even more advanced remote connections features,
⪚ an advanced &FTP; client we
recommend you to use ⪚
LFTP or
FileZilla.LAN connections via fish:/ protocol (zeroconf)Remote LAN Connections (zeroconf)This section is contributed by Andrew Svet (z-vet),
feedback about this chapter is appreciated. Thanks!
- This works on a Debian system, so it will work on Debian and derivatives (Kubuntu &etc;), though
+ This works on a &Debian; system, so it will work on &Debian; and derivatives (&kubuntu;, &etc;), though
it should work on other Linuxes as well.
We assume that you have SSH installed, configured and working on
every machine on LAN you want to connect to/from.
There are plenty of very good tutorials about SSH on the net, ⪚
at linuxhomenetworking.com
or just google for it. We use the default SSH port (22) for this chapter.
Remember to change it if you use different one. All modifications, editing &etc; must be done as root.
Let's start with installing all the packages we need:
#apt-get install
Everything is installed, now let's do some configuration. First, we need our services to be announced on LAN.
That is why we installed avahi-daemon: it represents your machine on local network and allows other applications
to publish services they provide. Avahi-daemon comes with example ssh.service configuration
file found in /usr/share/doc/avahi-daemon/examples. In order to get the service to be
announced on LAN we need to copy this file to /etc/avahi/services directory:
#cp
Now we need fish:/ protocol to be announced too, so we use an ssh.service file as a template for fish.service:
#cp
This file is just a copy of ssh.service. Edit the fish.service file and replace
-"Remote Terminal on %h" with "Fish to %h" and "_ssh._tcp" with "_fish._tcp".
+Remote Terminal on %h with Fish to %h and _ssh._tcp with _fish._tcp.
Here is how it looks after edit:
<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<!-- $Id: remote-connections.docbook,v 1.6 2007/05/02 18:07:28 codeknight Exp $ -->
<!--
This file is part of avahi.
avahi is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
avahi is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR
<!-- See avahi.service(5) for more information about this configuration file -->
<service-group>
<name replace-wildcards="yes">FISH to %h</name>
<service>
<type>_fish._tcp</type>
<port>22</port>
</service>
</service-group>
Save the modified file.
Now we need to create a new file _fish._tcp, open a text editor and add the next lines:
Name=FISH Protocol (ssh)
Type=_fish._tcp
UserEntry=u
PathEntry=path
PasswordEntry=p
And save the file /usr/share/apps/zeroconf/_fish._tcp
Do the same on each machine on your LAN, then restart avahi-daemon:
# /etc/init.d/avahi-daemon
Then open &krusader; and type in location-toolbar-lnk: zeroconf:/ to open the
zeroconf connection.
Enter the Fish Protocol directory. Inside you will find the links to each machine that
announced fish:/ on your LAN, the location-toolbar-lnk: will point to
zeroconf:/_fish._tcp Double clicking on any of these machines,
them will bring up the password prompt, asking you for your ssh key passphrase (if password was set).
Enter your passphrase. Congratulations: you connected to remote machine using &krusader;!
diff --git a/doc/search.docbook b/doc/search.docbook
index ddda6ca3..a8d8b6f0 100644
--- a/doc/search.docbook
+++ b/doc/search.docbook
@@ -1,347 +1,347 @@
KruSearcher: find what you are looking forSearchWelcome to &krusader;'s powerful search module -
nicknamed KruSearcher. It is the most able tool (that we know of)
for &Linux;, since it allows so many different ways to
quickly find the file you are looking for. The search function is
also available on remote file systems. It is divided into two
levels, the general and the advanced. Let's take a look at the
general page.General SearchGeneral SearchThe page is divided into four parts: top (search for) part,
bottom part - titled Containing text,
left part - titled Search in and right part
which is called Do not search in.
Obviously, each part handles different aspects of the search.
Let's look at them closely.Top Part:Search for: here you enter the main
search criteria. You can enter a file name, a wildcard (
*.o.*,
*.c &etc;) or
both - separated by a space. If you type
'text' the results is the same as
'*text*'. You can exclude files from the
search with '|' (⪚
'*.cpp *.h |
*.moc.cpp'). You can use quotation marks for names
- that contain spaces. Filter "Program Files" searches
+ that contain spaces. Filter Program Files searches
out those files/directories the name of which is Program
Files. A drop-down list that is shown after clicking down arrow on the right allows you to pick some of your previously entered criteria.
It is possible to edit the list of suggestions for the Search for field. If you do not like some of its items just select it and press &Shift;Del and that useless suggestion gets deleted. You can also use the arrow keys in order to see all the history in the Search for field, and delete the entries that are needless.
Case sensitive: unchecking it will allow
lower and upper case search (&ie;:
*.c interprets as
*.c AND
*.C).Of type: this box lets you search for a
- file not only by its name, but also by its MIME type. For
+ file not only by its name, but also by its &MIME; type. For
example, you can search for all the audio files whose name
begins with B. Usually this option defaults to 'all files',
but you can choose to search for archives, directories,
images, text files, videos and audio files.Left and Right Part:Search in and
Do not search in: Using those two parts,
you can specify a search exactly the way you want it. For
example, you might want to search for a file in the whole
file system (beginning with
/), but do not want to search inside
/mnt. All you need to do is write
/ in the
Search in box, and write
/mnt in the
Do not search in box. If you want to enter
more than one directory in one of the list boxes, just type the
first name and press &Enter;. The directory name
will be copied to the bigger list box and you will be able to enter
another name.
The input line has an auto-completion feature,
corresponding to &plasma; global settings. If you
wish, you can click on the
folder icon, and browse to the directory
you wish to add.It is possible to define files and directories which will be filtered out from the search results using the Exclude Folder Names input field at the bottom of the Do not search in box.Items in the filtering list should be space-separated.Spaces in the filtering list items can be escaped or quoted. Example: .git "target build" build\ krusaderBottom Part:Text: entering text here makes
&krusader; search for it inside the files (
grep). This way you can search for all
header files (
*.h) which include the
word
'testing 123'.RegExp switch: toggle the regular expressions mode. A drop-down list that is shown after clicking down arrow on the right allows you to enter special symbols of regular expressions.
Encoding: allows you to choose the text encoding.
Match whole word only: allows you to specify that a complete match (letters and length) must be found.
Case sensitive: refers to your text
being searched for in upper and lower case or the exact
phrase you entered.Search in sub folders: perform a
recursive search and dive into every directory on the
way.Search in archives:
&krusader; will search for your files inside every
supported archive. This, however, takes longer to perform.
If you check this checkbox, you will notice you cannot
grep inside files anymore. This is done,
since looking inside archived files forces
&krusader; to extract them, which results in an
extremely time-consuming search.Follow links: if checked,
&krusader; will follow soft-links during the
search.Profiles: if you have to regularly
perform the same search operation, you can save the search
settings ⪚ include files, exclude files,
&etc;... Press the 'profile' button, and you can
add/load/save/remove search profiles.Query to clipboard: if checked,
&krusader; will place search text to clipboard when a found file is opened.The above screen shot shows a search for all the files which
end with
c, cpp or
h and include the string
'testing 123'. &krusader; will
search in
/root, /opt, /bin and
/usr, but not in
/usr/lib and
/usr/share.Clicking the
Search button starts the search and
displays the results page. During the search, you may press the
Stop button to stop the search. The
Close button is not operational during a
search, so you must first stop the search and then
Close the window. When a result is found,
double-clicking on it will take &krusader;'s active
panel point to the found files - but will not close the search
window, so you will be able to click on a different result.Sometimes, you need to narrow your search even more.
- Krusearcher allows a much finer search, and for that, let's look
+ KruSearcher allows a much finer search, and for that, let's look
at the
Advanced Page...Advanced SearchAdvanced SearchThis screen shot shows a search for files whose size is
between 10KiB and 150KiB, which were modified between October 10th
and November 1st, which belong to any user in the 'nobody' group,
and are readable and writable by anyone in the 'nobody' group, but
only readable to the rest of the world.The advanced page is divided into three parts: size, date
and ownership.SizeAllows you to choose the size range of the file you are
looking for. By checking the check boxes, you can search for a
file which is bigger than XXX bytes (or KB, MB), smaller than XXX
bytes or, by checking both search for a file which size is bigger
than XXX but smaller than YYY.DateThis part offers three different ways of defining a date
criteria:
Modified between: allows you to enter
two dates. &krusader; will search for files with a
modification date between the first date and the second one,
inclusive.
You can click on the date icon (near the input boxes)
to open a standard date window - which allows you to easily
browse through the calendar and search for the desired
date. Clicking on a date will close the window and the date
will appear in the input box.Not modified after: choosing this option
makes &krusader; search for files that were NOT
modified after a given date, which is the same as searching
for files older than that date.Modified in the last/not modified in the
last: in these input boxes, you do not enter a date
but a number. This number represents days/weeks/months (as
chosen in the near drop box). Entering the number 5 in the
upper input box, makes &krusader; search for files
that were modified in the last 5 days. Entering the number 2
in the lower input box makes &krusader; search for
files that did NOT change in the last 2 days. The combination
of both results in a search for files that were changed in
the last 5 days, but NOT in the last 2 days.OwnershipBelongs to user/group: by checking each
of the corresponding check boxes, you can search for files
which belong to a certain user and/or group. The drop box
lists all the user names and group names in the system, just
choose one and go ahead.Permissions: divided into owner, group
and all - it allows you to choose certain permissions for the
file. You can choose to specify permissions for the owner,
group, all or any combination. The question mark (?) is a
wildcard - which means that any permission is valid.To clarify, the screen shot above (the ownership part)
describes a search for files that belong to any user in group
'users', are readable, writable but not executable to any user
in the group, are readable but not writable or executable to
the rest of the world and have unknown permissions to its
owner.ResultsClicking on the
Search button to start the search and open
the Results window. Here you can see the progress and the
results of the search action. If you want you can stop the
current search action with the
Stop button. In the result list select the
file and use
F3/
F4 to view/edit or use the right-click menu. When
you click on a found item, the directory of the active panel will
change if the selected item is not in the current panel
directory. The results window supports dragging items to other windows
and copy to clipboard (&Ctrl;C).
- When you close the Krusearcher window, the selected
+ When you close the KruSearcher window, the selected
item is selected in the active panel.Feed to listboxWhen you click the
Feed to listbox button after the results
are displayed, then &krusader; ask for a Query Name,
this name will be used in the Results-Tab in the List Panel that
holds the search results. You can do whatever you want on the
files in the new tab. The location toolbar will display
⪚
virt:/Search results 1.The files in the Results-Tab are actually the original
files. if you delete a file - it is removed!
diff --git a/doc/splitter.docbook b/doc/splitter.docbook
index bbc532b5..e024f6aa 100644
--- a/doc/splitter.docbook
+++ b/doc/splitter.docbook
@@ -1,77 +1,77 @@
File SplitterFile SplitterThis function splits one (large) file up into multiple
smaller files so that they can be placed on smaller media
(⪚ ZIP drives, ...) or sent by email. The multiple
files can be combined again to recreate the original file.
&krusader; and Total Commander split/combine
functions are compatible. To split a file choose
FileSplit
or
&Ctrl;
P: a Split dialog
will open to confirm the operation.If the name of the original file is
foo, then the name of the smaller files will
be
foo.000 foo.001 foo.002 &etc;
There is no theoretical limit in the number of smaller files, but
it is recommended to limit the number to a maximum of 1023 files.
&krusader; creates a
foo.crc file. This file contains the name,
size and the crc checksum of the original file. It is possible to
combine the file without the
foo.crc file but in this case
&krusader; cannot check if the original file was
recreated correctly.An example of a
foo.crc file:
filename=foo size=432998467868 crc32=21EB719ATo combine the multiple files choose, select a partial file
foo.xxx and choose
File
- Combine files
+ Combine files...
or
&Ctrl;
B. The target directory is the
inactive panel and can be changed. The file names must be
numbered in ascending order:
foo.001, foo.002, foo.003 &etc; or
have letters in ascending order: ("
splitletter method")
fileaa, fileab, fileac &etc; If
the file
foo.crc is found in the same directory as the
partial files, &krusader; will use this file to check
the combined file for errors.
diff --git a/doc/synchronizer.docbook b/doc/synchronizer.docbook
index 9fd8f66f..490952c2 100644
--- a/doc/synchronizer.docbook
+++ b/doc/synchronizer.docbook
@@ -1,739 +1,739 @@
SynchronizerSynchronizerIntroduction
- This function compares two directories with all subdirectories and shows the differences between them.
+ This function compares two folders with all subfolders and shows the differences between them.
After selecting some options and the
Compare function you can synchronize the
- files and directories. One panel could be an &FTP;
+ files and folders. One panel could be an &FTP;
server. Do not forget the
Compare by content option if the file size
stays equal. Choose
Tools
- Synchronize Directories
+ Synchronize Folders
or
&Ctrl;
Y to start this feature. The
colors are
configurable.
The synchronizer has its own keybindings.
For local files: The synchronizer changes the date
information to the original dates.SynchronizerSynchronizerProcedure:Set the
Left directory and the
Right directory that you want to compare.Configure the optional
File Filter,
General Filters and
Advanced filters. The
General Filters includes a
Do not search in option which lets you
- exclude directories from comparison.
+ exclude folders from comparison.Set the
Checkbox
options:
- Recurse subdirectories,
+ Recurse subfolders,
Follow symlinks,
Compare by content,
Ignore Date,
Asymmetric and
Ignore Case.
Click on the
Compare button to compare the
- directories.
+ folders.By using
Show options,
you can include/exclude particular file types. The files that
are not on the list will be untouched by
synchronization.If needed, you can change the
Task operations determined by the
Comparator with the
right click
menu.When you agree with the
Compare results, click on the
Synchronize button to show the
synchronize dialog.After selecting the options of the
Synchronizer, click on
the
Start button to start the
synchronization process.
A detailed explanation of all the functions and
buttons is described in the following text.
ComparatorPanel elementsLeft Directory: The left side base
directory.Right Directory: The right side
base directory.File Filter: Filters the filenames
at synchronizing. ⪚
*.png selects only
files the names of which end with
- .png. Directories are
+ .png. Folders are
listed if the directory name ends with
.png or if the
directory contains files which end with
.png. Multiple
include/exclude example:
'*.cpp *.h |
*.moc.cpp' includes
*.cpp *.h and
exclude
*.moc.cpp.General filters: Search for,
containing textAdvanced filters: Size, date,
ownershipFilename filtering criteriaYou can make use of wild cards. Multiple patterns
are separated by space (means logical OR) and patterns
are excluded from the search using the pipe symbol. If
the pattern is ended with a slash (*pattern*/), it
means that pattern relates to recursive search of
- directories.
+ folders.
- pattern - means to search those files/directories
+ pattern - means to search those files/folders
whose name is a pattern, recursive search goes through
- all subdirectories independently of the value of the
+ all subfolders independently of the value of the
pattern.
- pattern/ - means to search all files/directories,
+ pattern/ - means to search all files/folders,
but recursive search goes through/excludes the
- directories whose name is a pattern.
+ folders whose name is a pattern.You can use quotation marks for names
- that contain spaces. Filter "Program Files" searches
- out those files/directories the name of which is Program
+ that contain spaces. Filter Program Files searches
+ out those files/folders the name of which is Program
Files.Examples:*.o*.h *.c??*.cpp *.h |
*.moc.cpp* | CVS/ .svn/Note: the search term 'text' is equivalent to
'*text*'.Checkbox options
- Recurse subdirectories: The
- Synchronizer walks through subdirectories when
+ Recurse subfolders: The
+ Synchronizer walks through subfolders when
comparing.Follow symlinks: The Synchronizer
- follows the symbolic links to directories (not the
+ follows the symbolic links to folders (not the
files!).Compare by content: The files
the sizes of which are equal will be compared by content as
well.Ignore Date: Ignores the date
information (useful for &FTP;, smb, archive,
... ) the date information is relevant *only* in the
local file system.Asymmetric: The
Left Directory is the target
directory, the
Right Directory is the source
directory. This function synchronizes the content of
the left directory to the right directory.
The files that exist only on the left side
will be deleted.The files that exist only on the right side
will be copied to left.The files considered to be equal will be
untouched.Those files considered to be different will
be copied to left. Use this feature with
care!This function is useful if the date
information is unusable, or to synchronize the left
directory to the content of a file server (like a
download). Alternatively, it is useful to make a backup
from the right directory to the left directory. NOTE:
Do NOT use this option to synchronize a desktop and a
notebook (⪚ files that exist only on the
left side will be deleted!).Scroll Results: This is for
slow &FTP; servers, ... When the
Synchronizer has finished comparing a file, it puts the
file into the end of the list at once and scrolls the
window, if necessary. It is important, if you want to
know what the Synchronizer is doing. If the
&FTP; server is slow, the comparison of a
directory may take a lot of time. By turning this
- option on, you can see that the comparator is "alive",
+ option on, you can see that the comparator is alive,
but slow. For fast file systems, it can reduce the
speed of comparing slightly.Ignore Case: Case insensitive filename compare,
this is useful when synchronizing &Windows; filesystems.Ignore hidden files: Ignores files that start with a dot.When everything mentioned above is done, click on the
- Compare button to compare the directories,
+ Compare button to compare the folders,
the results are displayed in the File List.File ListThe
File List has the following columns:
- "Left name | Left size | Left time | Task | Right time |
- Right size | Right name".
+ Left name | Left size | Left time | Task | Right time |
+ Right size | Right name.
Here you can check the compare results and modify the synchronization actions if desired.
The text color defines the default copy direction determined by the comparator.
Green: Copy from left to right.Blue: Copy from right to left or delete on the right side in asymmetric mode.Red: Files which are different by the given criteria (no copy direction).Black: Files which are identical (no copy direction).
A double click on a file calls the &krusader;s Compare by content function.
The Tasks (<=>) column defines the default copy direction, which can be modified by the user if needed.
The results window supports dragging items to other windows ( drag [left], &Shift;+drag [right] )
and copy left/right selected items to clipboard (&Ctrl;C).
File List: Tasks (<=>) columnThis column displays the task that is planned for the
Synchronizer, this task can be modified with the
right click menu.->: Copy from the
- left side to the right side. For directories:
+ left side to the right side. For folders:
mkdir in the right side.=: The files are the same, do not
do anything.!=: The file is excluded, or the
Synchronizer does not know what to do.<-: copy from the
- right side to the left side. For directories:
+ right side to the left side. For folders:
mkdir in the left sideDEL: delete files from the right
side.Show optionsHere you can include/exclude particular file types.
Those files, that are not in the list, will be untouched at
synchronization.->: Enable/Disable
the copy task from left to right.=: Enable/Disable listing the
equal files.!=: Enable/Disable listing the
- excluded / "do not know what to do" files.
+ excluded / do not know what to do files.
<-: Enable/Disable
the copy task from right to left.Trash: Enable/Disable the file
deleting from the left side task.Duplicates: Enable/Disable those
files that exist on both sides.Singles: Enable/Disable those
files that exist only on one side.Action buttonsCompare: Compares the
- directories, the results are displayed on the
+ folders, the results are displayed on the
File List.Stop: Stops comparing.Synchronize: Shows the
synchronize dialog.Close: Closes the Synchronizer
window.The Status line may contain
- The number of scanned directories while
+ The number of scanned folders while
comparing.The filename when comparing by content (for big
files).The number of files on the list.Right click menu on the
File ListThe right click menu is split up in three
sections:1. change the
Task operations determined by the
Comparator. Select one or multiple files. The change will
be applied on the selection and not only on the right
clicked item. If the selected item is a directory, the
- change will be applied on its files/subdirectories as
+ change will be applied on its files/subfolders as
well.
- Synchronize Directories: Starts
+ Synchronize Folders...: Starts
synchronization.Exclude: Excludes a file/dir
from synchronization ( task change to != ).Restore original operation: Task
change to the original result of comparison.Reverse direction: Task change (
-> to <-, and
<- to -> ).Copy from right to left: Task
change to <-.Copy from left to right: Task
change to ->.Delete ( left single ): Task
change to DEL.2. change the selectionsSelect items: Opens a dialog
which allows you to select items. This is the
Select Group dialog from the
Edit menu.Unselect items: Opens a dialog
which allows you to deselect items. This is the
Unselect Group dialog from
the Edit menu.Invert selection: Invert the
selection status of all items.3. others (note that the following operations work on the
right-clicked file and not on the selection).View left file: Starts viewer on
the left file.View right file: Starts viewer
on the right file.Compare Files: Starts the diff
utility (⪚ &kompare;) on the
files.Other buttonsProfiles: If you have to
- synchronize the same directories often, you can save the
+ synchronize the same folders often, you can save the
settings ⪚ include files, exclude files,
... Press the
Profile button, and you will be
able to add / load / save / remove synchronizer
profiles.Swap sides: Swaps the
File List.Synchronize with kgetIf you want to synchronize a local directory with an
unstable &FTP; server, kget is a much better
solution than simple file copying. After comparing you may
right click on the result list and select
Synchronize with KGet to execute
the synchronization, after that the listed files will be
downloaded with kget instead of &krusader;. Of course
kget needs to be installed on
your computer; otherwise, it will not be available.SynchronizationAfter pressing the
Synchronize button the synchronization
dialog appears.Check boxesHere you confirm the copy and delete operations of
the SynchronizerRight to left: copy X1 files ( Y1
bytes ) enable / disable the copy from right to
left.Left to right: copy X2 files ( Y2
bytes ) enable / disable the copy from left to
right.Left: delete X3 files ( Y3 bytes )
enable / disable the left side deleting.Confirm overwrites: By switching
this option on, Krusader will show the
rename, skip, overwrite, skip all, overwrite
all dialog box, before overwriting the
file.Status labelsReady: A1/A2 files, B1/B2. This
line is changed at synchronizing, showing that
synchronizer finished with A1 files from A2 ( B1 bytes
from B2 ).Progress bar: Shows the progress
on the synchronization (based on bytes).Action buttonsStart: Starts
synchronization.Pause / Resume: Pauses/resumes
the synchronization process.Close: Closes the
synchronization dialog (and stops
synchronization).Parallel synchronizationOne can give the number of the 'quasi'
threads.Can drastically increase the speed when
synchronized with slow &FTP; servers.Does not affect the speed of local
synchronization.
- Remote "compare by content" and "directory
- compare" is done in parallel.
+ Remote compare by content and directory
+ compare is done in parallel.Remote synchronization is also done in parallel,
- except the mkdir tasks (mkdir must be before
+ except the mkdir tasks (mkdir must be before
copy).
diff --git a/doc/user-interface.docbook b/doc/user-interface.docbook
index 699aa2a3..5e6ccbf5 100644
--- a/doc/user-interface.docbook
+++ b/doc/user-interface.docbook
@@ -1,821 +1,817 @@
User InterfaceUser InterfaceOFM User InterfaceThe OFM file manager concept contains
many features that make them
powerful enough to belong among the best file managers today.
The interface is simple: left panel, right panel and a command
line below. Because of interaction between these three items
the file managing will become more efficient.If you would like to know
how &krusader; works you can try it yourself,
just install it on your computer. To accept an
Orthodox File Manager (OFM) like &krusader;, the user needs
to get used to
new ideas that are actually already 20
years old. If you prefer to waste time and lose a lot of
productivity, you can always continue to use one panel file
managers that are based on &Windows;
Explorer.&krusader; Main Window&krusader; Main Window&krusader; Main WindowThe User Interface is based on Orthodox File Manager (OFM)
paradigm, a 20- year old principle that has proven its bones.
It is known as simple, easy and powerful. In the following
sections we will cover the basic functions of each part with the
exception of:The
Menu Bar which has a
chapter of its own.The
Bookmarks which has a chapter
of its own.The
Status Bar shows the
properties of the current file (that is being) in focus.
Toolbars&krusader; comes with several Toolbars.Main ToolbarToolbarMain ToolbarMain ToolbarMain ToolbarThe &krusader; Main Toolbar is a standard
&kde; toolbar that can be dragged around the
application (please unlock it first by unchecking the Lock
Toolbar Positions item in the right-click menu)
or configured via a
Right-Click menu. You can decide whether or
not you want to display it each time you start
&krusader; in the Konfigurator Startup page,
and you can toggle its use in the current session in the
Settings menu. The Main Toolbar contents can be
configured from the
- Configure Toolbars in the
+ Configure Toolbars... in the
Settings menu. Since various commands
and options in &krusader; are context-dependent,
some commands are not always available. The icon of an
inappropriate or inactive action will be deactivated
(grayed-out) disabling its use. Bookmarks
can be placed into the Main Toolbar and the Actions Toolbar
- with the mouse using "drag and drop".
+ with the mouse using drag and drop.
Job ToolbarToolbarJob ToolbarBy default, the &krusader; Job Toolbar (Queue
Manager or simply the JobMan) is located at the right part of the
Main Toolbar. This toolbar allows you to view the job progress, to pause
and resume the job list execution and to undo the last executed job.Actions ToolbarToolbarActions ToolbarUserActions and
- Bookmarks can be "plugged" into the
+ Bookmarks can be plugged into the
Actions Toolbar. To show it, use
SettingsShow Actions Toolbar
. To add user actions, use
Settings
- Configure Toolbars
+ Configure Toolbars...
and select Actions Toolbar. You can, for example,
drag the Actions Toolbar to the right side using the
mouse.Location ToolbarToolbarLocation ToolbarBelow the
Main Toolbar there is a
Location Toolbar for each panel. It
shows the path the panel is currently pointing to.
When entering archives the path will be displayed
- in the following format: "archive
+ in the following format: archive
type:/directory/archive_filename/the directory inside the
- archive". This format makes the paths uniform and easy to
+ archive. This format makes the paths uniform and easy to
read. The
Location Toolbar supports also
KIO Slaves but not all of them, some can
only be used with the
viewer and some can not be
used. The user can enter a desired path by clicking on it./mnt/cdrom/settings:/will browse and open entries of the
&systemsettings;.trash:/opens trash folder.mtp:/uses the kio_mtp to
access, upload and organize the multimedia stored on
Android-based devices.And last but not least
Remote Connections .You can copy-paste a &URL; in the
Location Toolbar or use a middle click.
With the Right-Click menu you can configure the auto-complete
function. An optional
Clear Location Toolbar button is also
available.Quick Navigation:
- &Ctrl; point with mouse in the
- middle of &URL; of the
+ &Ctrl; point with mouse in the middle of &URL; of the
Location Toolbar. A pop-up window shows
- the next &URL; location. Pressing
- &Ctrl; + Left Mouse Button shows
+ the next &URL; location. Pressing &Ctrl; + &LMB; shows
the location where the mouse was pointing to. This feature
allows faster navigation in a big directory tree.Panel ToolbarToolbarPanel ToolbarEach panel has a
configurable Panel
Toolbar. The complete Panel Toolbar or specific
buttons can be made visible or be hidden.OpenDir Button: opens the
directory browser.Equals Button (=): changes the
panel directory to the other panel directory.Up Button (..): changes the panel
directory to the parent directory.Home Button (~): changes the panel
directory to the home directory.Root Button (/): changes the panel
directory to the root directory.Sync-browsing Button: when active,
each directory change in the specific panel is performed
in the other panel as well.PanelsThe &krusader; panels are where most of the
action takes place. Currently, there are two types of panels:List Panel: shows the files and
directories.Sidebar: has several display
modes: Preview, Tree, Quickselect, View and Disk Usage for
the file or directory that has the focus. The Sidebar
may be left open or closed, as desired.
- &krusader; is a "twin-panel" file
- manager so there are two panels: the "Left" panel and the
- "Right" panel, or a more important logical distinction, the
+ &krusader; is a twin-panel file
+ manager so there are two panels: the Left panel and the
+ Right panel, or a more important logical distinction, the
*Active* panel and the *Inactive* panel. The active panel is
the one that will accept your mouse and keyboard input. If you
choose a command from the
Menu-Bar or
Toolbar the command will act upon the
selected files/directories in the active panel. You can switch
between panels using the 	 key or by clicking on
the
Information or Totals labels, or by
selecting any file in a panel with the mouse. As always,
default startup settings can be modified with the
Konfigurator Startup page, and you control the current
session with the Settings menu.List PanelList PanelList PanelPanelList PanelThis is the default panel and the one you will probably
use most of the time. This panel shows the contents of one
directory which can be local (part of your mounted file
systems, either a native file or the files inside an archive)
- or remote files (accessed via &FTP;, NFS or Samba).
+ or remote files (accessed via &FTP;, &NFS; or Samba).
There are two modes: Detailed View that shows the file names,
file size, creation date and time and their attributes.
And Brief View that shows only the file names,
the number of brief columns can be changed, by right clicking on the Name header.
File copy/paste/cut via clipboard between
&konqueror; and &krusader;
&Ctrl;
C,
&Ctrl;
V,
&Ctrl;
X is supported.
&Alt;&Ctrl;
R toggles the
List Panel between horizontal and
vertical mode.The following items are available:Information Label: shows how much free space is physically
available on the file system, the file system capacity
and where the filesystem is mounted. If the information is not
available (most often in the case of remote file system)
a message will be displayed with the reason for
unavailability instead of the information.The
Media button on the left of the
Information Label displays a list of
all available media, where you can select the desired
- media (HDD partition, DVD, USB stick, &etc;).
+ media (HDD partition, &DVD;, &USB; stick, &etc;).
Pressing &Ctrl;Return when the
Media menu
is opened mounts the highlighted media when it is unmounted,
and unmounts it when it is mounted.
The context menu of a medium gives several options like
Mount,
Open in a new tab, &etc;
The Media menu is
configurable.Column Headers: here you can change the sort order of the
files and directories as desired. The default sort order
is by
Name. The sort order can be
instantly changed by clicking on one of the
Column Headers. To reverse the sort
order, click a second time on the Column Header. An arrow
will appear on the right of the Column Header text,
showing the sort direction (Up arrow = A to Z sorting,
Down arrow = Z to A sorting). Default
UserActions set a keybinding for the
Column Headers. The default
Column Headers are:
Name, Ext,
Size, Modified, rwx.
Predefined Atomic extensions like
.tar.gz are shown as one part in the
Ext Column. More
optional Column Headers are available with the &RMB;.
The width
Column Headers can be changed with
the mouse by single clicking and moving the divider line
to the desired width (keep the mouse button pressed).
Both
List Panels remember the sort order
and column width. The
Column Headers can be changed and
saved individually to each panel.File List: displays the files and directories in the
browsed directory. The search bar
allows you to search for files by typing their names, or
the first few characters of a file name. Pressing
&Enter; or double clicking on a file will
open/execute that file. You can select/unselect files
- using the mouse, with the
- Insert key or the
+ using the mouse, with the &Ins; key or the
Edit menu.Totals Label: selecting or deselecting files will change
the
Totals Label: selecting or
deselecting files will change the Totals Labelat the bottom of the panel, which displays how many files you have
selected (and how much total disk space they use) as well as the total file and
disk usage of the current directory (as opposed to the information label that
displays information for the whole file system). If a directory contains a lot
of subdirectories, it may not be possible to drop the &URL; onto the panel (on
which only directories are visible), but the &URL; can be dropped onto the
- "Information Label" or "Totals Label" instead. When a Information Label or Totals Label instead. When a custom filter is set, it will show the setting,
example: [*.cpp].
- When using the "&kde; default
- colors", then the
+ When using the &kde; default
+ colors, then the
selected files are shown in blue and the current file is
surrounded by a fine-lined rectangle. By default an icon is
shown according to the file type. Use
Konfigurator Panel page to change the default
configuration to meet your individual needs.Some useful
List panel Key-Bindings:&Ctrl;
R will refresh the
panel.Focus a file or directory on the left panel, press
&Ctrl;
- Right arrow and the right panel
+ &Right; and the right panel
changes:
On a file: the right panel gets the same path
as the left panel.On a directory: right panel opens the directory focused on the left panel.For the right panel: press
&Ctrl;
- Left arrow and the left panel
+ &Left; and the left panel
will change.SidebarSidebarSidebar (3rd Panel)
- This is "&krusader; is 3rd Hand" or the 3rd
+ This is &krusader; is 3rd Hand or the 3rd
Panel, click on the arrow-up button on the right of the
Totals Label or
&Alt;
- Down-Arrow to open the
+ &Down; to open the
Sidebar. This panel has several
display modes which can be activated by clicking on the
appropriate button.Preview Panel: gives a preview of the file that has the
focus (currently selected file).Tree Panel: is used to quickly browse the local
directory tree. This panel behaves like the list panel
but only one directory may be selected at a time and
double clicking or pressing &Enter; on a
directory will open that directory in the active panel.
The panels fully support drag and drop (copy, move, link)
mouse actions.Quick Panel: is used to quickly select files,
⪚ enter
*.png and click on the
- Go button. The "floppy" button
- stores the current selection. The "select group dialog"
+ Go button. The floppy button
+ stores the current selection. The select group dialog
is also available.Viewer Panel: views a text file, views an image,
&etc; A thumbnail view is generated whenever
you open the
Viewer Panel.Disk Usage Panel: views the Disk Usage of a
directory.
It is possible to change the sidebar placement using the rotation button
which is located to the left of the arrow down button at the bottom part of the &krusader; tab.
- Each click on this button moves the sidebar on one position in the loop "bottom-left-top-right".
+ Each click on this button moves the sidebar on one position in the loop bottom-left-top-right.
If needed you can resize the window
⪚ to better display a picture or view a file contents. Click
on the arrow down button to close the
3rd Hand Panel.Folder HistoryBoth panels remember recently visited folders. Click on
the
Folder history button ("watch"
symbol) to open the folder history list. Here you can quickly
change to previously visited folders. The currently focused
folder is checked. On every new start of &krusader;, the
history list is populated by the items from previous run (history is saved).Command Line / Terminal Emulator
- This part of the GUI
+ This part of the &GUI;
can have four modes: Command Line, Terminal Emulator, show both and show none.
You can choose your mode of operation either on start-up with the
Konfigurator Startup page, or for the current session with the Settings menu .
Command LineCommand LineCommand lineThe traditional command line mode offers a single line of
input to enter commands, it also features three buttons:command history (down arrow) to quick open previous used commands
Useraction expander (green plus button) to add easy
Useraction placeholders
run in terminal mode (console icon) button with the next options:
Start and ForgetDisplay Separated Standard and Error OutputDisplay Mixed Standard and Error OutputStart in New TerminalSend to Embedded Terminal EmulatorWhen you start typing your commands,
the command line auto-completion feature will make its offers
according to what you choose in the
&systemsettings;. If you want to change the way
auto-complete behaves in the current &krusader;
session,
right click on the command line and change it.
To the left of the input line you can find the local path that
the active panel is currently pointing to. This path is where
your command will be executed. Typing
cd
<directory> in the command line will also cause the active
panel to point to this directory.
Click
here to view the
command line keybindings.Terminal EmulatorTerminal EmulatorTerminal emulatorThe terminal emulator mode is in fact a small console and
acts like one. You can change the active directory in the
terminal by using the
cd command. The terminal emulator will follow the
active panel directory. You can drag a file from the
List Panel and name of file will pasted
into Terminal Emulator. If you drag multiple files, the names will
pasted into Terminal Emulator. A full-screen terminal emulator can
be used when configured or
&Ctrl; &Shift;F toggles
between normal and full screen mode. If the command line is hidden,
press &Ctrl; Arrow down
to focus the terminal emulator. &Ctrl;
Arrow up brings you back down.
&Ctrl;&Enter; and
&Ctrl; &Shift; &Enter; paste the filename.
You can close the emulator by typing
exit.
Click
here to view the
Terminal emulator keybindings.Function (FN) Keys BarFunction (FN) Keys BarFunction (FN) Keys BarThis bar gets its name from the function (FN) keys it
represents. For each button on this bar there is a
corresponding function key that performs the same action. This
bar is derived from the design of the first twin-panel file
managers and the FN keys usually act the same way with two
changes: the
F2 key is used to rename files and the
F9 key will open a terminal at the last local
path that the active panel pointed to.
- Mkdir
- F7 can create whole directory trees on the fly
- ⪚
- foo/bar/test. You can choose to display
+ MkdirF7 (translated name of
+ mkdir command) can create whole directory trees
+ on the fly ⪚ foo/bar/test. You can choose to display
or not the
FN keys bar when starting up
&krusader; via the Konfigurator Startup page,
and you can toggle its use in the current session with the
Settings menu. The actions and
Key-Bindings performed by the function keys are
configurable since version 1.51, they will remain active with
or without the
FN keys bar displayed.Folder TabsFolder TabsFolder TabsWith Folder Tabs you can quickly change to
multiple folders; each panel has its own
Folder Tabs. The Folder Tabs
positions are saved when closing &krusader;. To
switch between Folder Tabs, click them with the
mouse. Squeezed Folder Tabs have tooltips to
display the full path. The following Folder Tabs
operations are available:To
open a new tab and keep the current
tab opened: Right-click on a directory and
select
Open in New Tab.To lock a tab, Right-click and
select Lock Tab.To pin a tab, Right-click and
select Pin Tab. The pinned tab is a locked tab but with temporarily changeable address. It resets to pinned address on tab reactivation. To unpin the pinned tab right-click on it and choose the Unpin Tab item.To
duplicate a tab: Right-click
on the folder tab and select
Duplicate Current Tab, or use
&Ctrl;&Alt;&Shift;
N.To
close a tab (except for the last tab):
Right-click on the tab and select
Close Current Tab, or use the &MMB;, or
use the Folder tab
red cross button, or use
&Ctrl;
W.To
- create a "home" tab: click on the
+ create a home tab: click on the
Home button.To
change tabs:
&Ctrl;
, or
&Ctrl;
..To open the current folder in a new tab: use
&Ctrl;&Alt;&Enter;.To close all other tabs, Right-click and
select Close Inactive Tabs.To close duplicated tabs, Right-click and
select Close Duplicated Tabs.To move tab on the other panel, drag it to the area of the other panel
with the &LMB; (the mouse cursor will become an arrow pointing left or right)
and drop it. You can also press &Ctrl;&Shift;
O.ButtonsSeveral buttons for fast operations are available:
Main Toolbar,
Actions Toolbar,
Panel Toolbar,
Location Toolbar,
Media,
Folder history,
Bookmarks,
Tab,
Commandline,
Function keys.
diff --git a/doc/useractions.docbook b/doc/useractions.docbook
index de3de487..9965b6e4 100644
--- a/doc/useractions.docbook
+++ b/doc/useractions.docbook
@@ -1,648 +1,647 @@
UserActionsUserActionsWith ActionMan you can set up, configure and manage
UserActions. Some general settings are configured with
Konfigurator. With
UserActions you can perform actions on files in the panel or to
access &krusader; internal functions with parameters
directly using placeholders. The actions integrate seamlessly
into &plasma; action system, which means that the
standard Edit Toolbar and Edit Shortcut dialogs will show
UserActions, too. The UserActions are stored in
~/.local/share/krusader/useractions.xml or krusader/useraction.xml in the directory which can be determined using the qtpaths --paths GenericDataLocation command.
Several
examples are included in the
documentation. UserActions can be edited / added / imported /
exported by using ActionMan. The default UserActions are stored
in
/usr/share/krusader/useraction-examples.xml.
- UserActions can appear nearly everywhere where "normal" KActions
+ UserActions can appear nearly everywhere where normal KActions
can be placed. The actions can even be placed in the menu bar, but for that the
krusaderui.rc file must be edited. A few
examples:
Useractions Menu
User MenuActions Toolbarright click menus&etc;&krusader;'s UserActions tool is very
powerful and customizable if you are familiar with writing
UserActions in general.Several UserActions are provided by default. Please
upload your favorite
UserActions so that they become available for the
&krusader; community. Thanks!ActionManActionManBasically, UserActions are a method to call external
programs with variable parameters. For example, you could have a
UserAction with the following
xmms
to
enqueue all selected items of the active panel to the current
instance of xmms. Additionally, there is limited access to
&krusader; internal functions requiring parameters.
For example,
%aPanelSize("80")% will set the width of the
active panel to 80% of the &krusader; mainwindow.
Since the parameter of placeholders can contain other
placeholders, few scripts are possible.
Managing UserActionsOpen Konfigurator and choose User ActionsStart ActionMan, in which you can add, edit, remove, import and export
UserActions.Add Action: If you add an new
action, you get an empty input mask where you can enter all
the properties you desire. The action will be added as soon
as you press
Apply. Afterwards, the name is shown
in the list on the left.To edit a UserAction: Select the UserAction on the
left. Then choose it if you want to edit its properties. The
changes will only take effect when you press
Apply.To remove a UserAction: Select the
UserAction on the left and click the button.To import a UserAction: If you
import some actions, they will be automatically added to your
list. If there are name conflicts (the names have to be
unique because these are the ID for &plasma; action
system), you are asked to resolve them. For this, the list on
the left will only show the actions where conflicts exist.
You can now give them new names or remove them.Export Action: If you export a
UserAction you have to give a filename in which to store it.
If it does not exist, it will be created. If the file already
contains UserActions, the action you are exporting will be
added to that file.All actions you have defined are now shown in the
user menu and in &plasma; dialogs for changing shortcuts
and managing the toolbar. In addition, all actions available for
the current item will also show up in the right click
menu.Basic PropertiesIdentifier, Title
and Command line are always required, all the other properties
are optional.Identifier: A unique name of
the UserAction, used to identify it for &plasma;
action system.Icon button: The icon for your
UserAction.Category: Categories are used for a
better overview. They appear as submenu items in
the Useractions menu.Title: The title displayed in
the menus or dialogs.Tooltip: A tooltip for your
UserAction, ⪚ displayed in the toolbar on
mouseover.Description: A description of
what the UserAction does. This is also displayed as
What's This if you
&Shift;
F1 click on your
UserAction.Command: The command which
- will be executed. You can add placeholder using a GUI with
- the
- add button.
+ will be executed. You can add placeholder using a &GUI; with
+ the add button.
Workdir: The working directory
for the command which will be executed.Execution mode:Normal: Normal execution
mode.Run in terminal: Runs the
command in the terminal.Run in embedded terminal emulator: Runs the
command in the embedded terminal.Collect output: Collects the
output of the executed program in a &GUI;
window.Separate standard error:
- When "Collect output" is used the stdout and stderr are
+ When Collect output is used the stdout and stderr are
separately collected.Command accepts:
- Local files (no URLs): Tells
+ Local files only (no &URL;s): Tells
the placeholder it should return local addresses.
- URLs (remote and local):
+ &URL;s (remote and local):
Tells the placeholder it should return
&URL;s.Default shortcut: Configures a default
shortcut for the UserAction.Enabled: if checked, the useraction is shown in the User Menu,
otherwise the useraction will be hidden.Command-line syntaxBasically, everything you type in the command line will get
- executed (if you type "ls -l", "ls -l" gets executed). You have
+ executed (if you type ls -l, ls -l gets executed). You have
the possibility to get a character string from
&krusader; which represents the current state of the
panel. This is done using placeholders. A placeholder begins with
a percent-sign ('%') and is followed by a panel indicator ('a'
for the active, 'o' for the other, 'l' for the left and 'r' for
the right panel. If the placeholder does not need a panel to
operate on, you have to indicate this by an underscore ('_')).
Then comes the name of the placeholder (see the list below),
which may get some parameters enclosed in quotes. Finally, again
the percent sign.This sounds very complicated, so let's make an example:
'%aList("Selected")%' is replaced by a list of all selected items
in the active panel. So a command like 'xmms --enqueue
%aList("All", " ", "", "*.mp3")%' will execute xmms with a list
of all .mp3s in the current panel, separated by a single
blank.Currently, these placeholders are implemented:Path - replaced by the panels
pathParameter (optional):
Automatic escape spaces. Default:
yesCount - replaced by the number of
<first parameter>Parameter: Which items;
- either "All", "Selected", "Files" or "Dirs"
+ either All, Selected, Files or DirsFilter - replaced by the panel's filter
maskCurrent - replaced by the current
itemParameter (optional): Omit the
current path. Default: noParameter (optional):
Automatic escape spaces. Default:
yesList - replaced by a list of all
<first parameter>Parameter: Which items;
- either "All", "Selected", "Files" or "Dirs"
+ either All, Selected, Files or DirsParameter (optional):
Separator between the items.
Default:
- " "
+ Parameter (optional): Omit the
current path. Default: noParameter (optional):
- Filtermask (for all but "Selected").
+ Filtermask (for all but Selected).
Default: *Parameter (optional):
Automatic escape spaces. Default:
yesSelect - manipulates the selection in a
panelParameter: FiltermaskParameter (optional):
- manipulate in which way; either "Set", "Add" or "Remove".
- Default: "Set"
+ manipulate in which way; either Set, Add or Remove.
+ Default: SetGoto - changes the panels' path to
<first parameter>Parameter: A relative or
- absolute path, or an URL
+ absolute path, or an &URL;
Parameter (optional): Open the
location in a new tab. Default:
noAsk - asks the user for some text and
is replaced by the answerParameter: The
QuestionParameter (optional): A
default answerParameter (optional): A
caption for the question boxClipboard - manipulates the
clipboardParameter: The text that
should go to the clipboard (you may want to use
- "%aCurrent%" here)
+ %aCurrent% here)
Parameter (optional): Append
the text to the current content of the clipboard with
this separatorCopy - copies a file, useful for quick,
local backupsParameter: What should be
copiedParameter: Where it should
be copiedSync - opens the Synchronizer with a
given profileParameter: A profile for the
SynchronizerNewSearch - opens the search windows
with a given profileParameter: A profile for the
search moduleProfile - loads a given panel
profileParameter: A panel
profileEach - splits the commandline into a
list. These commands are executed one after another.Parameter: A list item (all,
all files, all dirs, all selected).Move - move from source to
destination.Parameter: A sourceParameter: A
destinationPanelSize - change the ratio between
the two panels.Parameter (optional): A
integer value, ⪚, 80 makes the active panel use 80% of
&krusader;'s width (height in vertical mode),
omitting the parameter means 50%.Ask - cancel the execution.Parameter (optional): A string
for the cancel question.ListFile - is replaced by path/file name
of a temporary file containing a list of itemsParameter:
path/filenameColSort - set the sorting on a column
of a specific panel.Parameter: Column: Either
- "Name", "Ext", "Type", "Size", "Modified", "Perms",
- "rwx", "Owner" and "Group"
+ Name, Ext, Type, Size, Modified, Perms,
+ rwx, Owner and GroupParameter: Sort sequence:
- Either "Toggle", "Asc", "Desc"
+ Either Toggle, Asc, DescView - set the view mode.Parameter: View mode: Either
- "generic", "text", "hex"
+ generic, text, hexParameter: Window Mode:
- Either "tab", "window"
+ Either tab, window
- A GUI-based helper for placeholder adding is
+ A &GUI;-based helper for placeholder adding is
provided. Spaces in Path, Current and List are by default,
automatically escaped. There is one more important thing to know:
All placeholders that interact with &krusader;
internal functions are called at expand time (meaning directly
when the placeholders are replaced). External programs are
called at execution time (meaning after all placeholders are
replaced).Advanced PropertiesHere you can configure where your command should be visible
(for the right click menu). In addition, it is possible to change
the command executed and confirm it separately. You can also set
a user under which the command should be executed.Configures if the action is valid for a Protocol, Path,
- MIME type or File name.
+ &MIME; type or File name.Tweaking the command line before being executed.Set a different user for the execution (this has no
effect in &krusader; internal functions)
diff --git a/doc/vfs.docbook b/doc/vfs.docbook
index abb3a1a8..918ab93b 100644
--- a/doc/vfs.docbook
+++ b/doc/vfs.docbook
@@ -1,103 +1,103 @@
Virtual file systems (VFS)VFSA basic
OFM feature is VFS, this an
abstracted layer over all kinds of archived information (ZIP
- files, &FTP; servers, TAR archives, NFS filesystems, SAMBA shares,
- ISO CD/DVD images, RPM catalogs, &etc;), which allows the user to
+ files, &FTP; servers, TAR archives, &NFS; filesystems, SAMBA shares,
+ ISO &CD;/&DVD; images, RPM catalogs, &etc;), which allows the user to
access all the information in these divergent types of
filesystems transparently - just like entering an ordinary
sub-directory. &krusader; supports several virtual
file systems:
Remote connections
VFS: provides the capability of working with a remote
- connection session (&FTP;, NFS, Samba, FISH, SFTP) like with
+ connection session (&FTP;, &NFS;, Samba, FISH, SFTP) like with
local filesystems. It is perfect for complex remote operations
- and almost as powerful as most standalone GUI remote
+ and almost as powerful as most standalone &GUI; remote
clients.
Archive VFS: allows to browse
archives in VFS as it was a directory (ace, arj, bzip2, deb,
gzip, iso, lha, rar, rpm, tar, zip and 7-zip).
Search VFS:
Feed to listbox places the search
results in VFS.
Synchronizer VFS: places
the synchronizer results in VFS.Actions you perform on the files in VFS are
performed on the 'real' files. You do not just delete files from
the VFS - you delete them from your hard drive. Limitations: you
cannot create directories inside a VFS.It is possible to keep the directory structure when doing a
copy from a virtual folder to a non virtual folder, by
- selecting the "Keep virtual directory structure" check box of the
+ selecting the Keep virtual directory structure check box of the
copy dialog. Imagine the following virtual folder:
$file:/home/myhome/mydir1/myfile1$file:/home/myhome/mydir1/myfile2$file:/home/myhome/mydir2/myfile3
Then do the following steps:go to the virtual folder and select the filesselect a destination folder (non virtual!)press
F5-> copy dialog
appearsCheck
Keep virtual directory structureSelect
/home/myhome/ for base
&URL;Start copy by pressing OKThe result will be:
$destinationdir/mydir1/myfile1$destinationdir/mydir1/myfile2$destinationdir/mydir2/myfile3
diff --git a/doc/viewer-editor.docbook b/doc/viewer-editor.docbook
index 01625cf1..b8b5e1c4 100644
--- a/doc/viewer-editor.docbook
+++ b/doc/viewer-editor.docbook
@@ -1,2453 +1,2452 @@
KrViewer: &krusader;'s internal
viewer-editorViewerEditorPressing &Enter; on a selected file
opens the file with the associated
application. The editor-viewer is tabbed, configure it
on the Konfigurator General pageViewerTo view a file as fast as possible according to its type,
just put it under the cursor and press
F3. &krusader;'s internal viewer is
actually a part of &konqueror;, which can basically
view every file type viewable by &konqueror;
(⪚ display pictures, play music, show the content
of an archive). This is called the 'Generic viewer', for which
- you need to configure the MIME types.
+ you need to configure the &MIME; types.
The viewer works as follows:
It tries to view the file with the
'Generic viewer'.
- When the file type (MIME type) cannot be determined or
+ When the file type (&MIME; type) cannot be determined or
when a file (⪚ a binary) does not have an
associated action, it disables the 'generic viewer'. The
file is treated as a text file, which is the
'Text viewer'.The user can change in the
KrViewer
menu between: 'Generic viewer' (if available), 'Text
viewer' and
'Hex viewer'.You can configure the default viewer mode on the
Konfigurator General page .&Shift;
F3 views a &URL; on
demand, ⪚:
man:/views the manpages.man:/krusaderviews manpage of &krusader;.info:/views the infopages.https://krusader.orgviews a webpage.ftp://ftp.kde.org/pub/kde/views a &FTP; server.sftp://sftp.foo/views a secure &FTP; server.file:/home/frankviews the home directory of Frank.tar:/home/frank/archive.tar.gz/opens content browser window for the
tar.gz archive.KrViewer can have the following menus:
File,
Edit,
View,
Settings and
Krviewer, depending
on which file type is viewed. They will be discussed in the
Editor section. The internal
viewer can follow links on &HTML; pages. With
&Ctrl;&Shift;
E the viewer can start
&krusader;'s internal editor (which is basically the
same application).The embedded viewer is not written by us, it is
supplied via &kf5; and
KIO Slaves. We cannot and do not want to
change it, using these libraries reduces the amount of
written code. So we do not have to reinvent the wheel
;-)EditorEditor&krusader;'s internal editor has almost
everything that you can expect of an editor. Editing is similar
to viewing but with the
F4 key. The default editor is
&krusader;'s internal editor. You can change the
default editor in the Konfigurator General page, if you
prefer to use an external editor.When you use &krusader;'s internal editor
for the first time, it is recommended to look at each section
of the
Settings menu, and
configure it the way you want it.Menu overviewThere are different menus and menu items in simple and advanced mode.
The advanced mode is enabled by checking the option
Enable power user mode (&kde; 3 mode)
on the Appearance page in &kappname;s settings.The File Menu&Ctrl;SFileSave
This saves the current document. If there has already been a save of
the document then this will overwrite the previously saved file without
asking for the user's consent. If it is the first save of a new
document the save as dialog (described below) will be invoked.
FileSave As...
This allows a document to be saved with a new file name.
F5FileReload
Reloads the active file from disk. This command is useful if another program or
process has changed the file while you have it open in &kappname;.
&Ctrl;PFilePrint...
Opens a simple print dialog allowing the user to specify what, where,
and how to print.
File
-Export as HTML
+Export as &HTML;
Export your file in &HTML; format so your document can be viewed as a web page.
This item is only displayed when the plugin Exporter is loaded.
The Edit Menu&Ctrl;ZEditUndoThis is used to eliminate or reverse the most recent user action
or operation.
&Ctrl;&Shift;ZEditRedoThis will reverse the most recent change (if any) made using Undo&Ctrl;XEditCutThis command deletes the current selection and places it on the
clipboard.
-The clipboard is a feature that works invisibly to provide a way to
+The clipboard is a feature that works invisibly to provide a way to
transfer data between applications.&Ctrl;CEditCopyThis copies the currently selected text to the clipboard so that it may
-be pasted elsewhere. The clipboard is a feature that works invisibly
+be pasted elsewhere. The clipboard is a feature that works invisibly
to provide a way to transfer data between applications.&Ctrl;VEditPasteThis will insert the contents of the clipboard at the cursor position.
-The clipboard is feature that works invisibly to provide a way to
+The clipboard is a feature that works invisibly to provide a way to
transfer data between applications.EditCopy as
-HTML
+&HTML;
This copies the currently selected text to the clipboard as &HTML;.
This item is only displayed when the plugin Exporter is loaded.
&Ctrl;AEditSelect AllThis will select the entire document. This could be very useful for
copying the entire file to another application.&Ctrl;&Shift;AEditDeselectDeselects the selected text in the editor if any.&Ctrl;&Shift;BEditBlock
Selection ModeToggles Selection Mode. When the Selection Mode is BLOCK,
you can make vertical selections, ⪚ select column 5 to 10 in lines 9 to 15.
The status bar shows the current state of the Selection Mode, either BLOCK or
LINE.
-Meta&Ctrl;V
+&Meta;&Ctrl;VEditVI input
ModeSwitch to a vi-like, modal editing mode. This mode supports the most used commands
and motions from vim's normal and visual mode and has an optional vi mode statusbar.
This status bar shows commands while they are being entered, output from commands and
the current mode.The behavior of this mode can be configured in the
Vi Input Mode section of the
Editing page in &kappname;'s settings dialog.
-Ins
+&Ins;EditOverwrite
ModeToggles the Insert/Overwrite modes. When the mode is INS, you
insert characters where the cursor is. When the mode is OVR, writing
characters will replace the current characters if your cursor is positioned
before any character. The status bar shows the current state of the Overwrite
Mode, either INS or OVR.&Ctrl;FEditFind...This opens the incremental search bar at the bottom of the editor window.
On the left side of the bar is a button with an icon to close the bar, followed by a small text
box for entering the search pattern.When you start entering characters of your search pattern, the search starts
immediately. If there is a match in the text this is highlighted and the background color
of the entry field changes to light green. If the search pattern does not match any
string in the text, this is indicated by a light red background color of the entry field
and Not found is displayed at the right side of the bar.Use the Next or Previous button
to jump to the next or previous match in the document.You can choose whether the search should be case sensitive.
Selecting Match Case will limit finds to entries that match the
case (upper or lower) of each of the characters in the search pattern.
Click on the button with a green arrow icon at the right side of the incremental search bar to
switch to the power search and replace bar.
F3EditFind NextThis repeats the last find operation, if any, without calling the incremental
search bar.
&Shift;F3EditFind Previous
This repeats the last find operation, if any, without calling the incremental
search bar, and searching backwards instead of forwards through the
document.
&Ctrl;REditReplace...This command opens the power search and replace bar.
On the upper left side of the bar is a button with an icon to close the bar, followed by a small text
box for entering the search pattern.You can control the search mode by selecting Plain text,
Whole words, Escape sequences or
Regular expression from the drop down box.
If Escape sequences or Regular expression are
selected, the Add... menuitem at the bottom of the context menu of the text boxes will be enabled
and allows you to add escape sequences or regular expression items to the
search or replace pattern from predefined lists.Use the Next or Previous button to jump
to the next or previous match in the document.Enter the text to replace with in the text box labeled Replace
and click the Replace button to replace only the highlighted text or
the Replace All button to replace the search text in the whole document.
You can modify the search and replace behavior by selecting different
options at the bottom of the bar.
Selecting Match Case will limit finds to entries that match the
case (upper or lower) of each of the characters in the search pattern.
Selection Only will search and replace within the current selection only.
The Find All button highlights all matches in the document and shows the
number of found matches in a small popup.
Click on the button with a green arrow icon at the right side of the power search and replace bar to
switch to the incremental search bar.
&Ctrl;HEditFind SelectedFinds next occurrence of selected text.&Ctrl;&Shift;HEditFind Selected BackwardsFinds previous occurrence of selected text.&Ctrl;GEditGo to Line...
This opens the goto line bar at the bottom of the window which is used to have the cursor
jump to a particular line (specified by number) in the document. The
line number may be entered directly into the text box or graphically by
clicking on the up or down arrow spin controls at the side of the text
box. The little up arrow will increase the line number and the down
arrow decrease it. Close the bar with a click on the button with an icon on the left side of the bar.
The View MenuThe View menu allows you to manage settings
specific to the active editor, and to manage frames.ViewNew WindowCreate another window containing the current document. All changes to the
document in one window are reflected in the other window and vice versa.F7ViewSwitch to Command LineDisplays the Katepart command line at the bottom of the window.
In the command line, type help to get help and help list
to get a list of commands.ViewShow the Javascript ConsoleThis opens a tool view that allows you to run Javascript code
interactively. For more information, see
Extending &kate; with ScriptsViewSchemaSelect a font schema.F10ViewDynamic Word WrapThe text lines will be wrapped at the view
border on the screen.ViewDynamic Word Wrap IndicatorsChoose when and how the dynamic word wrap indicators should be
displayed. This is only available if the Dynamic Word
Wrap option is checked.ViewShow Static Word Wrap MarkerIf this option is checked, a vertical line will be drawn at the
word wrap column as defined in the SettingsConfigure Editor... in the
Editing tab. Please note that the word wrap marker is only drawn if you
use a fixed pitch font.F6ViewShow Icon BorderThis is a toggle item. Setting it on checked will make the Icon Border
visible in the left side of the active editor, and vice versa. The Icon Border
indicates the positions of the marked lines in the editor.F11ViewShow Line NumbersThis is a toggle Item. Setting it on checked will make a pane displaying
the line numbers of the document visible in the left border of the active
editor, and vice versa.ViewShow Scrollbar MarksIf this option is checked, the view will show marks on the vertical
scrollbar. The marks are equivalent to the marks on the Icon Border.F9ViewShow Folding MarkersIf this option is checked, the marks for code folding will be
shown.ViewCode FoldingThese options pertain to
code
folding:F9Show Folding MarkersToggles the display of the folding marker pane in the left
side of the view.Fold Current NodeCollapse the region that contains the cursor.Unfold Current NodeExpand the region that contains the cursor.&Ctrl;&Shift;-Fold Toplevel NodesCollapse all toplevel regions in the document.
Click on the right pointing triangle to expand all toplevel regions.Enlarge FontThis increases the display font size.Shrink FontThis decreases the display font size.The Bookmarks Menu&Ctrl;BBookmarksSet Bookmark
Sets or removes a bookmark in the current line of the active document. (If it is
there, it is removed, otherwise one is set).
BookmarksClear All Bookmarks
This command will remove all the markers from the document as well as
the list of markers which is appended at the bottom of this menu item.
&Alt;
-PgUp
+&PgUp;
BookmarksPreviousThis will move the cursor to beginning of the first above line
with a bookmark. The menuitem text will include the line number and the first
piece of text on the line. This item is only available when there is a bookmark
in a line above the cursor.&Alt;
PgDownBookmarksNextThis will move the cursor to beginning of the next line with a
bookmark. The menuitem text will include the line number and the first piece of
text on the line. This item is only available when there is a bookmark in a line
below the cursor.
At the bottom of this menu, a list of bookmarks appears if any bookmarks are
available for this window.
The Tools MenuToolsRead Only ModeSet the current document to Read Only mode. This prevents any text
addition and any changes in the document formatting.ToolsModeChoose the filetype scheme you prefer for the active document. This
overwrites the global filetype mode set in SettingsConfigure
Editor... in the Filetypes tab for your current
document only.ToolsHighlightingChoose the Highlighting scheme you prefer for the active document. This
overwrites the global highlighting mode set in SettingsConfigure
Editor... for your current document only.ToolsIndentationChoose the style of indentation you want for your active document.
This overwrites the global indentation mode set in SettingsConfigure
Editor... for your current document only.ToolsEncodingYou can overwrite the default encoding set in SettingsConfigure
Editor... in the Open/Save page
to set a different encoding for your current document. The encoding you
set here will be only valid for your current document.ToolsEnd of LineChoose your preferred end of line mode for your active
document. This overwrites the global end of line mode set in SettingsConfigure
Editor... for your current document only.ToolsAdd Byte Mark Order (BOM)Checking this action you can explicitly add a byte order mark for unicode
encoded documents. The byte order mark (BOM) is a Unicode character used to signal
the endianness (byte order) of a text file or stream, for more information see
Byte Order Mark.
-&Ctrl;Space
+&Ctrl;&Space;ToolsInvoke Code CompletionManually invoke command completion, usually by using a shortcut bound to this action.ToolsWord CompletionReuse Word Below (&Ctrl;
9) and Reuse Word Above
(&Ctrl; 8) complete the
currently typed text by searching for similar
words backward or forward from the current cursor position. Shell
Completion pops up a completion box with matching entries.&Ctrl;&Shift;OToolsAutomatic Spell CheckingWhen Automatic Spell Checking is enabled, wrong text
is underlined in the document on-the-fly.ToolsSpelling...This initiates the spellchecking program - a program
designed to help the user catch and correct any spelling errors.
Clicking on this entry will start the checker and bring up the speller dialog
box through which the user can control the process. There are four settings
lined up vertically in the center of the dialog with their corresponding labels
just to the left. Starting at the top they are:Unknown word:Here, the spellchecker indicates the word currently under
consideration. This happens when the checker encounters a word not in its
dictionary - a file containing a list of correctly spelled words against which
it compares each word in the editor.Replace with: If the checker has any similar words in its dictionary the
first one will be listed here. The user can accept the suggestion, type in his
or her own correction, or choose a different suggestion from the next
box.Language: If you have installed multiple dictionaries, here you can
select which dictionary/language should be used.On the right side of the dialog box are 6 buttons that allow the user to
control the spellcheck process. They are:Add to DictionaryPressing this button adds the Unknown word
to the checker's dictionary. This means that in the future
the checker will always consider this word to be correctly
spelled.Suggest The checker may list here a number of possible replacements for
the word under consideration. Clicking on any one of the suggestions will cause
that word to be entered in the Replace with box,
above.Replace This button has the checker replace the word under
consideration in the document with the word in the
Replace with box.Replace All This button causes the checker to replace not only the current
Unknown word: but to automatically make the same
substitution for any other occurrences of this Unknown word
in the document.IgnoreActivating this button will have the checker move on without
making any changes.Ignore All This button tells the checker to do nothing with the current
Unknown word: and to pass over any other instances of
the same word.This only applies to the current spellcheck
run. If the checker is run again later it will stop on this same
word.Three more buttons are located horizontally along the bottom of the
spellcheck dialog. They are:Help This invokes the &kde; help system with the help page
for this dialog.Finished This button ends the spellcheck process, and returns to the
document.Cancel This button cancels the spellcheck process, all modifications
are reverted, and you will return to your document.ToolsSpelling (from cursor)...This initiates the spellchecking program but it starts where your cursor
is instead of at the beginning of the document.ToolsSpellcheck Selection...Spellchecks the current selection.ToolsChange DictionaryDisplays a drop down box with all available dictionaries for spellchecking
at the bottom of the editor window. This allows easy switching of the spellcheck
dictionary ⪚ for automatic spellcheck of text in different languages.ToolsClean
IndentationThis cleans the indentation for the current selection or for the
line the cursor is currently in. Cleaning the indentation ensures that
all your selected text follows the indentation mode you choose.ToolsAlignCauses a realign of the current line or selected lines using the
indentation mode and indentation settings in the document.&Ctrl;DToolsCommentThis adds one space to the beginning of the line
where the text cursor is located or to the beginning of any
selected lines.&Ctrl;&Shift;DToolsUncommentThis removes one space (if any exist) from the beginning of the
line where the text cursor is located or from the beginning of any
selected lines.&Ctrl;UToolsUppercasePut the selected text or the letter after the cursor in
uppercase.&Ctrl;&Shift;UToolsLowercasePut the selected text or the letter after the cursor in
lowercase.&Ctrl;&Alt;UToolsCapitalizeCapitalize the selected text or the current
word.&Ctrl;JToolsJoin LinesJoins the selected lines, or the current line and the line below
with one white space character as a separator. Leading/trailing white space on
joined lines is removed in the affected ends.ToolsApply Word WrapApply static word wrapping on all the document. That means that
a new line of text will automatically start when the current
line exceeds the length specified by the Wrap words at option
in the Editing tab in SettingsConfigure
Editor...If the plugin Insert File is enabled, you will
find here an additional menu item Insert File....
The Settings MenuSettingsConfigure Editor...
This menu item opens a dialog whereby several different settings may be adjusted.
The KrViewer Menu
&Ctrl;&Shift;
GKrViewerGeneric viewer&krusader;'s internal viewer is actually
part of &konqueror;, which can basically view every file
type viewable by &konqueror; (⪚
display pictures, play music, show the content of an
archive).&Ctrl;&Shift;
TKrViewerText viewerView the file in text mode.
&Ctrl;&Shift;
HKrViewerHex viewerView the file in hex mode.
&Ctrl;&Shift;
LKrViewerListerFast text/hex viewer for huge filesizes, done by
Krusader lister.
&Ctrl;&Shift;
EKrViewerText editorEdit the file in text mode.
&Ctrl;&Shift;
DKrViewerDetach TabDetach browsing Tab and open in a new
window.
&Ctrl;
QKrViewerQuitCloses &krusader;'s viewer/editor
window.The Editor Component ConfigurationThis group contains all pages related to the editor component of
&kappname;. Most of the settings here are defaults, they can be overridden by
defining a filetype,
by Document Variables or
by changing them per document during an editing session.AppearanceGeneralDynamic Word WrapIf this option is checked, the text lines
will be wrapped at the view border on the screen.Dynamic word wrap indicators (if applicable)Choose when the Dynamic word wrap indicators
should be displayed, either Off, Follow Line
Numbers or Always on.
Align dynamically wrapped lines
to indentation depth:
Enables the start of dynamically wrapped
lines to be aligned vertically to the indentation level of the first
line. This can help to make code and markup more
readable.Additionally, this allows you to
set a maximum width of the screen, as a percentage,
after which dynamically wrapped lines will no longer be vertically aligned.
For example, at 50%, lines whose indentation levels are deeper than 50% of the
width of the screen will not have vertical alignment applied to subsequent
wrapped lines.Whitespace HighlightingHighlight tabulatorsThe editor will display a » symbol to indicate the presence
of a tab in the text.Highlight trailing spacesThe editor will display dots to indicate the presence of extra
whitespace at the end of lines.Advanced
Show indentation lines
If this is checked, the editor will display
vertical lines to help identifying indent lines.Highlight range between selected brackets
If this is enabled, the range between the selected matching brackets will be highlighted.BordersBordersShow folding markers (if available)
If this option is checked, the current view will display marks
for code folding, if code folding is available.Show icon border
If this is checked, you will see an icon border on the left
hand side. The icon border shows bookmark signs for instance.Show line numbers
If this is checked, you will see line numbers on the left
hand side.Show scrollbar marks
If this option is checked the current view
will show marks on the vertical scrollbar. These marks will
for instance show bookmarks.Sort Bookmarks Menu
By creation
Each new bookmark will be added to the bottom,
independently from where it is placed in the document.By position
The bookmarks will be ordered by the line
numbers they are placed at.Fonts & ColorsThis section of the dialog lets you configure all fonts and colors in
any color scheme you have, as well creating new schemes or deleting existing
ones. Each scheme has settings for colors, fonts and normal and highlight text
styles.
&kappname; will preselect the currently active scheme for you, if you want to
work on a different scheme start by selecting that from the
Schema combobox. With the New and Delete
button you can create a new scheme or delete existing ones.At the bottom of the page you can select the Default schema for &kappname;.ColorsText Area BackgroundNormal textThis is the default background for the editor area, it will be
the dominant color on the editor area.Selected textThis is the background for selected text. The default is
the global selection color, as set in your &plasma; color preferences.
Current lineSet the color for the current line. Setting this a bit different
from the Normal text background helps to keep focus on the current line.
BookmarkThis combobox lets you set overlay colors for various mark types.
The color is mixed into the background color of a marked line, so that a line
with more marks or a marked line that is current has a background that is a mix
of more colors. The mark colors are also used if you enable display of scrollbar
marks.Additional ElementsLeft border backgroundThis color is used for the marks, line numbers and folding
marker borders in the left side of the editor view when they are displayed.
Line numbersThis color is used to draw the line numbers on the left side of
the view when displayed.Bracket highlightThis color is used to draw the background of matching brackets.
Word wrap markersThis color is used to draw a pattern to the left of dynamically
wrapped lines when those are aligned vertically, as well as for the static word
wrap marker.Tab and space markersThis color is used to draw white space indicators when enabled.
Spelling mistake linesets the color of the line that is used to indicate spelling mistakes.
Fonts
Here you can choose the font for the schema. You can choose from
any font available on your system, and set a default size. A sample text
displays at the bottom of the dialog, so you can see the effect of your choices.
Normal Text StylesThe normal text styles are inherited by the highlight text styles,
allowing the editor to present text in a very consistent way, for example comment
text is using the same style in almost all of the text formats that &kappname; can
highlight.The name in the list of styles is using the style configured for
the item, providing you with an immediate preview when configuring a style.
Each style lets you select common attributes as well as foreground
and background colors. To unset a background color, rightclick to use the
context menu.Highlighting Text StylesHere you can edit the text styles used by a specific highlight definition.
The editor preselects the highlight used by your current document. To work on a
different highlight, select one in the Highlight combobox
above the style list.
The name in the list of styles is using the style configured for
the item, providing you with an immediate preview when configuring a style.
Each style lets you select common attributes as well as foreground
and background colors. To unset a background color, rightclick to use the
context menu. In addition you can see if a style is equal to the default style
used for the item, and set it to that if not.You will notice that many highlights contain other highlights represented
by groups in the style list. For example most highlights import the Alert
highlight, and many source code formats imports the Doxygen highlight. Editing
colors in those groups only affects the styles when used in the edited highlight
format.
EditingGeneralStatic Word Wrap
Word wrap is a feature that causes the editor to automatically start a new line
of text and move (wrap) the cursor to the beginning of that new line. &kappname;
will automatically start a new line of text when the current line reaches the
length specified by the Wrap Words
At: option.Enable static word wrapTurns static word wrap on or off.Show static word wrap markers
(if applicable)If this option is checked, a vertical line will be drawn at the word wrap
column as defined in the SettingsConfigure Editor... in the Editing tab.
Please note that the word wrap marker is only drawn if you use a fixed pitch
font.Wrap words at:If the Enable static word wrap option is selected
this entry determines the length (in characters) at which the editor will
automatically start a new line.MiscRemove trailing spaces while editing&kappname; will automatically eliminate extra spaces
at the ends of lines of text.Auto bracketsWhen
the user types a left bracket ([, (, or {) &kappname; automatically enters the
right bracket (}, ), or ]) to the right of the cursor.Copy/Cut the current line if no selectionIf this option is enabled and the text selection is empty, copy and cut
action are performed for the line of text at the actual cursor position.Allow scrolling past the end of the documentThis option lets you scroll past the end of the document. This can be used to vertically centre the bottom of the document, or put it on top of the current view.Cursor & SelectionText Cursor MovementSmart home and smart endWhen selected, pressing the home key will cause the cursor to
skip white space and go to the start of a line's text.Wrap cursor
-When on, moving the insertion cursor using the Left and Right keys will
+When on, moving the insertion cursor using the &Left; and &Right; keys will
go on to previous/next line at beginning/end of the line, similar to most
editors.When off, the insertion cursor cannot be moved left of the
line start, but it can be moved off the line end, which can be very handy for
programmers. When this option is chosen, moving the cursor with the arrow keys
off the end of a line (to the right) causes it to jump down to the beginning of
the next line. Likewise when the cursor is moved past the beginning of a line
(to the left) it jumps up to the end of the preceding line. When this option is
not selected, moving the cursor right past the end of a line merely causes it to
continue horizontally in the same line and trying to move it left past the
beginning does nothing.PageUp/PageDown moves cursorThis option changes the behavior of the cursor when the user presses
-the Page Up or Page Down key. If unselected
+the &PgUp; or &PgDn; key. If unselected
the text cursor will maintain its relative position within the visible text in
&kappname; as new text becomes visible as a result of the operation. So if the
cursor is in the middle of the visible text when the operation occurs it will
remain there (except when one reaches the beginning or end.) With this option
selected, the first key press will cause the cursor to move to either the top or
bottom of the visible text as a new page of text is displayed.Autocenter cursor (lines):Sets the number of lines to maintain visible above and below the cursor
when possible.Text Selection ModeNormalSelections will be overwritten by typed text and will be lost on
cursor movement.PersistentSelections will stay even after cursor movement and typing.IndentationDefault Indentation mode:Select the automatic indentation mode you want to use as default. It is
strongly recommended to use None or
Normal here, and use filetype configurations to set other
indentation modes for text formats like C/C++ code or &XML;.Indent usingTabulatorsWhen this is enabled the editor will insert tabulator characters when you
press the 	 key or use automatic
indentation.SpacesWhen this is enabled the editor will insert a calculated number of spaces
according to the position in the text and the setting
when you press the 	 key or use automatic
indentation.Tabulators and SpacesWhen this is enabled, the editor will insert spaces as describe above when
indenting or pressing 	 at the beginning of a line, but insert tabulators when
the 	 key is pressed in the middle or end of a line.Tab width:This configures the number of spaces that are displayed in place of a tabulator
character.Indentation width:The indentation width is the number of spaces which is used to indent a line.
If configured to indent using tabulators, a tabulator character is inserted
if the indentation is divisible by the tab width.Indentation PropertiesKeep Extra SpacesIf this option is disabled, changing the indentation
level aligns a line to a multiple of the width specified in
Indentation width.Adjust indentation of code pasted from the clipboardIf this option is selected, pasted code from the clipboard is indented.
Triggering the Undo action removes the indentation.Indentation ActionsBackspace key in leading blank space unindentsIf this option is selected, the &Backspace; key decreases the indentation level
if the cursor is located in the leading blank space of a line.Tab key action (if no selection exists)
If you want 	 to align the current line in the current code block
like in emacs, make 	 a shortcut to the action Align.
Always advance to the next tab positionIf this option is selected, the 	 key always inserts white space
so that the next tab position is reached. If the option Insert spaces instead of tabulators
on the General tab in the Editing
page is enabled, spaces are inserted; otherwise, a single tabulator is inserted.Always increase indentation levelIf this option is selected, the 	 key always indents the current
line by the number of character positions specified in Indentation width.Increase indentation level if in leading blank spaceIf this option is selected, the 	 key either indents the current line
or advances to the next tab position. If the insertion point is at or before the
first non-space character in the line, or if there is a selection, the current line
is indented by the number of character positions specified in Indentation width.
If the insertion point is located after the first non-space character in the line
and there is no selection, white space is inserted so that the next tab position is
reached: if the option Insert spaces instead of tabulators
on the General tab in the Editing
page is enabled, spaces are inserted; otherwise, a single tabulator is inserted.Auto CompletionGeneralEnable auto completionIf enabled, a word completion box automatically pops up during typing
showing a list of text entries to complete the current text under the
cursor.Minimal word length to completeWhile typing text, the word completion searches for words in the
document starting with the already typed text. This option configures the minimal
amount of characters that are needed to make the word completion active and pop
up a completion box.Vi Input ModeGeneralUse VI input modeWhen selected, the vi input mode will be enabled when opening a new view.
You can still toggle the vi input mode on/off for a particular view in the
Edit menu.Let Vi commands override Kate shortcutsWhen selected, Vi commands will override &kappname;'s built-in commands. For
example: &Ctrl;R will redo,
and override the standard action (showing the search and replace dialog).Hide the Vi mode status barBy default, an extra status bar will be used when the Vi input mode is
enabled. This status bar shows commands while they are being typed and
messages/errors produced by Vi commands.Checking this option will hide this extra status line.Key Mapping
Key mapping is used to change the meaning of typed keys. This allows you to
move commands to other keys or make special keypresses for doing a series of
commands.Example:F2 -> I-- &Esc;This will prepend I-- to a line when pressing F2.
SpellcheckThese configuration options are described in the documentation for the
&systemsettings; module Spell Checker.Open/SaveGeneralFile FormatEncoding:This defines the standard encoding to use to open/save files, if not changed
in the open/save dialog or by using a command line option.Encoding DetectionSelect an item from the drop down box, either to disable autodetection or
use Universal to enable autodetection for all encodings. But as
this may probably only detect utf-8/utf-16, selecting a region will use custom heuristics
for better results.
If neither the encoding chosen as standard above, nor the encoding specified
in the open/save dialog, nor the encoding specified on command line match
the content of the file, this detection will be run.Fallback EncodingThis defines the fallback encoding to try for opening files if neither the
encoding chosen as standard above, nor the encoding specified in the open/
save dialog, nor the encoding specified on command line match the content of
the file. Before this is used, an attempt will be made to determine the
encoding to use by looking for a byte order marker at start of file: if one
is found, the right unicode encoding will be chosen; otherwise encoding
detection will run, if both fail fallback encoding will be tried.End of line:Choose your preferred end of line mode for your active
document. You have the choice between &UNIX;, DOS/&Windows; or Macintosh.Automatic end of line detectionCheck this if you want the editor to autodetect the end of line
type. The first found end of line type will be used for the whole file.Enable byte order markerThe byte order mark is a special sequence at the beginning of unicode
encoded documents. It helps editors to open text documents with the correct
unicode encoding. For more information see Byte Order Mark.Automatic Cleanups on Load/SaveRemove trailing spacesThe editor will automatically eliminate extra spaces at the ends of lines
of text while loading/saving the file.AdvancedFolder Config FileSearch depth for config file:The editor will search the given number of folder levels upwards
for &kappname; config file and load the settings line from it.
Further information about these hidden folder config files you find in the
document variables section.
Backup on SaveBacking up on save will cause &kappname; to copy the disk file to
<prefix><filename><suffix> before saving changes.
The suffix defaults to ~ and prefix is empty by
default. Local filesCheck this if you want backups of local files when
saving.Remote filesCheck this if you want backups of remote files when saving.PrefixEnter the prefix to prepend to the backup file names.SuffixEnter the suffix to add to the backup file names.Disable swap file syncing&kappname; is able to recover (most of) what was written after last save in case
of a crash or power failure. A swap file (.swp.<filename>) is created
after the first editing action on a document. If the user doesn’t save the
changes and &kappname; crashes, the swap file remains on the disk. When opening a
file, &kappname; checks if there is a swap file for the document and if it is, it asks
the user whether he wants to recover the lost data or not. The user has the
possibility to view the differences between the original file and the recovered
one, too. The swap file is deleted after every save and on normal exit.&kappname; syncs the swap files on the disk every 15 seconds, but only if they
have changed since the last sync. The user can disable the swap files syncing if
he wants, by checking the Disable swap file syncing box,
but this can lead to more data loss.Modes & FiletypesThis page allows you to override the default configuration for documents
-of specified MIME types. When the editor loads a document, it will try if it
-matches the file masks or MIME types for one of the defined filetypes, and if so
+of specified &MIME; types. When the editor loads a document, it will try if it
+matches the file masks or &MIME; types for one of the defined filetypes, and if so
apply the variables defined. If more filetypes match, the one with the highest
priority will be used.
Filetype:The filetype with the highest priority is the one displayed in
the first drop down box. If more filetypes were found, they are
also listed.NewThis is used to create a new filetype. After
you click on this button, the fields below get empty and you
can fill the properties you want for the new filetype.DeleteTo remove an existing filetype, select it from the drop down
box and press the Delete button.Properties of current filetypeThe filetype with the highest priority is the one displayed in
the first drop down box. If more filetypes were found, they are also
listed.Name:The name of the filetype will be the text of the corresponding
menu item. This name is displayed in the
ToolsFiletypesSection:The section name is used to organize the file types in
menus. This is also used in the
ToolsFiletypes menu.Variables:This string allows you to configure &kappname;'s settings for the
-files selected by this MIME type using &kappname; variables. You can set almost any
+files selected by this &MIME; type using &kappname; variables. You can set almost any
configuration option, such as highlight, indent-mode,
-etc.
+&etc;
Press Edit to see a list of all available variables
and their descriptions. Select the checkbox on the left to enable a particular
variable and then set the value of the variable on the right. Some variables
provide a drop-down box to select possible values from while others require you
to enter a valid value manually.For complete information on these variables, see
Configuring with Document
Variables.Highlighting:If you create a new file type, this drop down box allows you to
select a filetype for highlighting.Indentation Mode:The drop down box specifies the indentation mode for new
documents.File extensions:The wildcards mask allows you to select files by filename. A
typical mask uses an asterisk and the file extension, for example
*.txt; *.text. The string is a semicolon-separated list of
masks.
-MIME types:
+&MIME; types:Displays a wizard that helps you easily select
-MIME types.
+&MIME; types.Priority:Sets a priority for this file type. If more than one file type
selects the same file, the one with the highest priority will be
used.Download Highlighting Files...
Click this button to download new or updated syntax highlight descriptions
from the &kappname; website.
ExtensionsThe Plugins tab lists all available plugins and you can check those you
want to use. Click on the Information button to open the
About dialog of this plugin.Once a configurable plugin is checked, the
Configure button is enabled and you can click it
in order to configure the highlighted plugin.Editor Component PluginsAutoBraceThe autobrace plugin supersedes the &kappname; internal
Auto Brackets feature.
It automatically inserts a closing brace } at the beginning
of the next line after ending a line with an opening one {
and pressing the &Enter; key.
-
Data ToolsEnables data tools like thesaurus and spell check (if installed).
-Data tools are only available when text is selected, or when the right mouse
-button is clicked over a word. If no data tools are offered even when text
+Data tools are only available when text is selected, or when the &RMB;
+is clicked over a word. If no data tools are offered even when text
is selected, you need to install them.
If this plugin is enabled and data tools are installed, additional items
appear at the end of the context menu.ExporterThis command allows you to export the current document with all highlighting
-information into a HTML document using FileExport
-as HTML. Additionally you can use Edit
-Copy as HTML to copy the currently selected text
-as HTML to the system clipboard.
+information into a &HTML; document using FileExport
+as &HTML;. Additionally you can use Edit
+Copy as &HTML; to copy the currently selected text
+as &HTML; to the system clipboard.
IconInserterThe icon inserter plugin is only of use for &kde; developers: It adds an item
Insert KIcon-Code into the context menu of the editor.
If activated, the &plasma;'s icon chooser opens (showing application icons, action icons &etc;..).
If you click on it, the file name without file extension will be inserted as
text. Useful only for setting icons via &kf5; through the KIcon() class.
-Insane (not ZEN) HTML coding (light edition)
+Insane (not ZEN) &HTML; coding (light edition)A plugin, which does zen-coding like selector completion.
For more information see
Zen Coding.Insert FileThis plugin allows you to insert any readable file at the cursor position.
If enabled, the Tools menu has an additional menu item
Insert File.
diff --git a/krArc/krarc.cpp b/krArc/krarc.cpp
index 331a4aea..7b49f2da 100644
--- a/krArc/krarc.cpp
+++ b/krArc/krarc.cpp
@@ -1,1938 +1,1938 @@
/*****************************************************************************
* Copyright (C) 2003 Rafi Yanai *
* Copyright (C) 2003 Shie Erlich *
* Copyright (C) 2004-2019 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#include "krarc.h"
#include "../krusader/defaults.h"
// QtCore
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "../krusader/compat.h"
#define MAX_IPC_SIZE (1024*32)
#define TRIES_WITH_PASSWORDS 3
using namespace KIO;
extern "C"
{
#ifdef KRARC_ENABLED
/* This codec is for being able to handle files which encoding differs from the current locale.
*
* Unfortunately QProcess requires QString parameters for arguments which are encoded to Local8Bit
* If we want to use unzip with ISO-8852-2 when the current locale is UTF-8, it will cause problems.
*
* Workaround:
* 1. encode the QString to QByteArray ( according to the selected remote encoding, ISO-8852-2 )
* 2. encode QByteArray to QString again
* unicode 0xE000-0xF7FF is for private use
* the byte array is mapped to 0xE000-0xE0FF unicodes
* 3. KrArcCodec maps 0xE000-0xE0FF to 0x0000-0x00FF, while calls the default encoding routine
* for other unicodes.
*/
class KrArcCodec : public QTextCodec
{
public:
KrArcCodec(QTextCodec * codec) : originalCodec(codec) {}
~KrArcCodec() override = default;
QByteArray name() const override {
return originalCodec->name();
}
QList aliases() const override {
return originalCodec->aliases();
}
int mibEnum() const override {
return originalCodec->mibEnum();
}
protected:
QString convertToUnicode(const char *in, int length, ConverterState *state) const override {
return originalCodec->toUnicode(in, length, state);
}
QByteArray convertFromUnicode(const QChar *in, int length, ConverterState *state) const override {
// the QByteArray is embedded into the unicode charset (QProcess hell)
QByteArray result;
for (int i = 0; i != length; i++) {
if (((in[ i ].unicode()) & 0xFF00) == 0xE000) // map 0xE000-0xE0FF to 0x0000-0x00FF
result.append((char)(in[ i ].unicode() & 0xFF));
else
result.append(originalCodec->fromUnicode(in + i, 1, state));
}
return result;
}
private:
QTextCodec * originalCodec;
} *krArcCodec;
#define SET_KRCODEC QTextCodec *origCodec = QTextCodec::codecForLocale(); \
QTextCodec::setCodecForLocale( krArcCodec );
#define RESET_KRCODEC QTextCodec::setCodecForLocale( origCodec );
#endif // KRARC_ENABLED
class DummySlave : public KIO::SlaveBase
{
public:
DummySlave(const QByteArray &pool_socket, const QByteArray &app_socket) :
SlaveBase("kio_krarc", pool_socket, app_socket) {
error((int)ERR_SLAVE_DEFINED, QString("krarc is disabled."));
}
};
int Q_DECL_EXPORT kdemain(int argc, char **argv) {
if (argc != 4) {
qWarning() << "Usage: kio_krarc protocol domain-socket1 domain-socket2" << endl;
exit(-1);
}
// At least, that fixes the empty name in the warning that says: Please fix the "" KIO slave
// There is more information in https://bugs.kde.org/show_bug.cgi?id=384653
QCoreApplication app(argc, argv);
app.setApplicationName(QStringLiteral("kio_krarc"));
#ifdef KRARC_ENABLED
kio_krarcProtocol slave(argv[2], argv[3]);
#else
DummySlave slave(argv[2], argv[3]);
#endif
slave.dispatchLoop();
return 0;
}
} // extern "C"
#ifdef KRARC_ENABLED
kio_krarcProtocol::kio_krarcProtocol(const QByteArray &pool_socket, const QByteArray &app_socket)
: SlaveBase("kio_krarc", pool_socket, app_socket), archiveChanged(true), arcFile(nullptr), extArcReady(false),
password(QString()), krConf("krusaderrc"), codec(nullptr)
{
KRFUNC;
confGrp = KConfigGroup(&krConf, "Dependencies");
KConfigGroup group(&krConf, "General");
QString tmpDirPath = group.readEntry("Temp Directory", _TempDirectory);
QDir tmpDir(tmpDirPath);
if(!tmpDir.exists()) {
for (int i = 1 ; i != -1 ; i = tmpDirPath.indexOf('/', i + 1))
QDir().mkdir(tmpDirPath.left(i));
QDir().mkdir(tmpDirPath);
}
arcTempDir = tmpDirPath + DIR_SEPARATOR;
QString dirName = "krArc" + QDateTime::currentDateTime().toString(Qt::ISODate);
dirName.replace(QRegExp(":"), "_");
tmpDir.mkdir(dirName);
arcTempDir = arcTempDir + dirName + DIR_SEPARATOR;
krArcCodec = new KrArcCodec(QTextCodec::codecForLocale());
}
/* ---------------------------------------------------------------------------------- */
kio_krarcProtocol::~kio_krarcProtocol()
{
KRFUNC;
// delete the temp directory
KProcess proc;
proc << fullPathName("rm") << "-rf" << arcTempDir;
proc.start();
proc.waitForFinished();
}
/* ---------------------------------------------------------------------------------- */
bool kio_krarcProtocol::checkWriteSupport()
{
KRFUNC;
krConf.reparseConfiguration();
if (KConfigGroup(&krConf, "kio_krarc").readEntry("EnableWrite", false))
return true;
else {
error(ERR_UNSUPPORTED_ACTION,
i18n("krarc: write support is disabled.\n"
"You can enable it on the 'Archives' page in Konfigurator."));
return false;
}
}
void kio_krarcProtocol::receivedData(KProcess *, QByteArray &d)
{
KRFUNC;
const QByteArray& buf(d);
data(buf);
processedSize(d.length());
decompressedLen += d.length();
}
void kio_krarcProtocol::mkdir(const QUrl &url, int permissions)
{
KRFUNC;
const QString path = getPath(url);
KRDEBUG(path);
if (!checkWriteSupport())
return;
// In case of KIO::mkpath call there is a mkdir call for every path element.
// Therefore the path all the way up to our archive needs to be checked for existence
// and reported as success.
if (QDir().exists(path)) {
finished();
return;
}
if (!setArcFile(url)) {
error(ERR_CANNOT_ENTER_DIRECTORY, path);
return;
}
if (newArchiveURL && !initDirDict(url)) {
error(ERR_CANNOT_ENTER_DIRECTORY, path);
return;
}
if (putCmd.isEmpty()) {
error(ERR_UNSUPPORTED_ACTION,
- i18n("Creating directories is not supported with %1 archives", arcType));
+ i18n("Creating folders is not supported with %1 archives", arcType));
return;
}
const QString arcFilePath = getPath(arcFile->url());
if (arcType == "arj" || arcType == "lha") {
QString arcDir = path.mid(arcFilePath.length());
if (arcDir.right(1) != DIR_SEPARATOR) arcDir = arcDir + DIR_SEPARATOR;
if (dirDict.find(arcDir) == dirDict.end())
addNewDir(arcDir);
finished();
return;
}
QString arcDir = findArcDirectory(url);
QString tempDir = arcDir.mid(1) + path.mid(path.lastIndexOf(DIR_SEPARATOR) + 1);
if (tempDir.right(1) != DIR_SEPARATOR) tempDir = tempDir + DIR_SEPARATOR;
if (permissions == -1) permissions = 0777; //set default permissions
QByteArray arcTempDirEnc = arcTempDir.toLocal8Bit();
for (int i = 0;i < tempDir.length() && i >= 0; i = tempDir.indexOf(DIR_SEPARATOR, i + 1)) {
QByteArray newDirs = encodeString(tempDir.left(i));
newDirs.prepend(arcTempDirEnc);
QT_MKDIR(newDirs, permissions);
}
if (tempDir.endsWith(DIR_SEPARATOR))
tempDir.truncate(tempDir.length() - 1);
// pack the directory
KrLinecountingProcess proc;
proc << putCmd << arcFilePath << localeEncodedString(tempDir);
infoMessage(i18n("Creating %1...", url.fileName()));
QDir::setCurrent(arcTempDir);
SET_KRCODEC
proc.start();
RESET_KRCODEC
proc.waitForFinished();
// delete the temp directory
QDir().rmdir(arcTempDir);
if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(proc.exitCode())) {
error(ERR_CANNOT_WRITE, path + "\n\n" + proc.getErrorMsg());
return;
}
// force a refresh of archive information
initDirDict(url, true);
finished();
}
void kio_krarcProtocol::put(const QUrl &url, int permissions, KIO::JobFlags flags)
{
KRFUNC;
KRDEBUG(getPath(url));
if (!checkWriteSupport())
return;
bool overwrite = !!(flags & KIO::Overwrite);
bool resume = !!(flags & KIO::Resume);
if (!setArcFile(url)) {
error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url));
return;
}
if (newArchiveURL && !initDirDict(url)) {
error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url));
return;
}
if (putCmd.isEmpty()) {
error(ERR_UNSUPPORTED_ACTION,
i18n("Writing to %1 archives is not supported", arcType));
return;
}
if (!overwrite && findFileEntry(url)) {
error(ERR_FILE_ALREADY_EXIST, getPath(url));
return;
}
QString arcDir = findArcDirectory(url);
if (arcDir.isEmpty())
KRDEBUG("arcDir is empty.");
QString tempFile = arcDir.mid(1) + getPath(url).mid(getPath(url).lastIndexOf(DIR_SEPARATOR) + 1);
QString tempDir = arcDir.mid(1);
if (tempDir.right(1) != DIR_SEPARATOR) tempDir = tempDir + DIR_SEPARATOR;
if (permissions == -1) permissions = 0777; //set default permissions
QByteArray arcTempDirEnc = arcTempDir.toLocal8Bit();
for (int i = 0;i < tempDir.length() && i >= 0; i = tempDir.indexOf(DIR_SEPARATOR, i + 1)) {
QByteArray newDirs = encodeString(tempDir.left(i));
newDirs.prepend(arcTempDirEnc);
QT_MKDIR(newDirs, 0755);
}
int fd;
if (resume) {
QByteArray ba = encodeString(tempFile);
ba.prepend(arcTempDirEnc);
fd = QT_OPEN(ba, O_RDWR); // append if resuming
QT_LSEEK(fd, 0, SEEK_END); // Seek to end
} else {
// WABA: Make sure that we keep writing permissions ourselves,
// otherwise we can be in for a surprise on NFS.
mode_t initialMode;
if (permissions != -1)
initialMode = permissions | S_IWUSR | S_IRUSR;
else
initialMode = 0666;
QByteArray ba = encodeString(tempFile);
ba.prepend(arcTempDirEnc);
fd = QT_OPEN(ba, O_CREAT | O_TRUNC | O_WRONLY, initialMode);
}
QByteArray buffer;
int readResult;
bool isIncomplete = false;
do {
dataReq();
readResult = readData(buffer);
auto bytesWritten = ::write(fd, buffer.data(), buffer.size());
if (bytesWritten < buffer.size()) {
isIncomplete = true;
break;
}
} while (readResult > 0);
::close(fd);
if (isIncomplete) {
error(ERR_CANNOT_WRITE, getPath(url));
return;
}
// pack the file
KrLinecountingProcess proc;
proc << putCmd << getPath(arcFile->url()) << localeEncodedString(tempFile);
infoMessage(i18n("Packing %1...", url.fileName()));
QDir::setCurrent(arcTempDir);
SET_KRCODEC
proc.start();
RESET_KRCODEC
proc.waitForFinished();
// remove the files
QDir().rmdir(arcTempDir);
if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(proc.exitCode())) {
error(ERR_CANNOT_WRITE, getPath(url) + "\n\n" + proc.getErrorMsg());
return;
}
// force a refresh of archive information
initDirDict(url, true);
finished();
}
void kio_krarcProtocol::get(const QUrl &url)
{
KRFUNC;
get(url, TRIES_WITH_PASSWORDS);
}
void kio_krarcProtocol::get(const QUrl &url, int tries)
{
KRFUNC;
KRDEBUG(getPath(url));
bool decompressToFile = false;
if (!setArcFile(url)) {
error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url));
return;
}
if (newArchiveURL && !initDirDict(url)) {
error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url));
return;
}
if (getCmd.isEmpty()) {
error(ERR_UNSUPPORTED_ACTION,
i18n("Retrieving data from %1 archives is not supported", arcType));
return;
}
UDSEntry* entry = findFileEntry(url);
if (!entry) {
error(KIO::ERR_DOES_NOT_EXIST, getPath(url));
return;
}
if (KFileItem(*entry, url).isDir()) {
error(KIO::ERR_IS_DIRECTORY, getPath(url));
return;
}
KIO::filesize_t expectedSize = KFileItem(*entry, url).size();
// for RPM files extract the cpio file first
if (!extArcReady && arcType == "rpm") {
KrLinecountingProcess cpio;
cpio << "rpm2cpio" << getPath(arcFile->url(), QUrl::StripTrailingSlash);
cpio.setStandardOutputFile(arcTempDir + "contents.cpio");
cpio.start();
cpio.waitForFinished();
if (cpio.exitStatus() != QProcess::NormalExit || !checkStatus(cpio.exitCode())) {
error(ERR_CANNOT_READ, getPath(url) + "\n\n" + cpio.getErrorMsg());
return;
}
extArcReady = true;
}
// for DEB files extract the tar file first
if (!extArcReady && arcType == "deb") {
KrLinecountingProcess dpkg;
dpkg << cmd << "--fsys-tarfile" << getPath(arcFile->url(), QUrl::StripTrailingSlash);
dpkg.setStandardOutputFile(arcTempDir + "contents.cpio");
dpkg.start();
dpkg.waitForFinished();
if (dpkg.exitStatus() != QProcess::NormalExit || !checkStatus(dpkg.exitCode())) {
error(ERR_CANNOT_READ, getPath(url) + "\n\n" + dpkg.getErrorMsg());
return;
}
extArcReady = true;
}
// Use the external unpacker to unpack the file
QString file = getPath(url).mid(getPath(arcFile->url()).length() + 1);
KrLinecountingProcess proc;
if (extArcReady) {
proc << getCmd << arcTempDir + "contents.cpio" << '*' + localeEncodedString(file);
} else if (arcType == "arj" || arcType == "ace" || arcType == "7z") {
proc << getCmd << getPath(arcFile->url(), QUrl::StripTrailingSlash) << localeEncodedString(file);
if (arcType == "ace" && QFile("/dev/ptmx").exists()) // Don't remove, unace crashes if missing!!!
proc.setStandardInputFile("/dev/ptmx");
file = url.fileName();
decompressToFile = true;
} else {
decompressedLen = 0;
// Determine the mimetype of the file to be retrieved, and emit it.
// This is mandatory in all slaves (for KRun/BrowserRun to work).
QMimeDatabase db;
QMimeType mt = db.mimeTypeForFile(arcTempDir + file);
if (mt.isValid())
emit mimeType(mt.name());
QString escapedFilename = file;
if(arcType == "zip") // left bracket needs to be escaped
escapedFilename.replace('[', "[[]");
proc << getCmd << getPath(arcFile->url());
if (arcType != "gzip" && arcType != "bzip2" && arcType != "lzma" && arcType != "xz") proc << localeEncodedString(escapedFilename);
connect(&proc, &KrLinecountingProcess::newOutputData, this, &kio_krarcProtocol::receivedData);
proc.setMerge(false);
}
infoMessage(i18n("Unpacking %1...", url.fileName()));
// change the working directory to our arcTempDir
QDir::setCurrent(arcTempDir);
SET_KRCODEC
proc.setTextModeEnabled(false);
proc.start();
RESET_KRCODEC
proc.waitForFinished();
if (!extArcReady && !decompressToFile) {
if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(proc.exitCode()) || (arcType != "bzip2" && arcType != "lzma" && arcType != "xz" && expectedSize != decompressedLen)) {
if (encrypted && tries) {
invalidatePassword();
get(url, tries - 1);
return;
}
error(KIO::ERR_ACCESS_DENIED, getPath(url) + "\n\n" + proc.getErrorMsg());
return;
}
} else {
if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(proc.exitCode()) || !QFileInfo(arcTempDir + file).exists()) {
if (decompressToFile)
QFile(arcTempDir + file).remove();
if (encrypted && tries) {
invalidatePassword();
get(url, tries - 1);
return;
}
error(KIO::ERR_ACCESS_DENIED, getPath(url));
return;
}
// the following block is ripped from KDE file KIO::Slave
// $Id: krarc.cpp,v 1.43 2007/01/13 13:39:51 ckarai Exp $
QByteArray _path(QFile::encodeName(arcTempDir + file));
QT_STATBUF buff;
if (QT_LSTAT(_path.data(), &buff) == -1) {
if (errno == EACCES)
error(KIO::ERR_ACCESS_DENIED, getPath(url));
else
error(KIO::ERR_DOES_NOT_EXIST, getPath(url));
return;
}
if (S_ISDIR(buff.st_mode)) {
error(KIO::ERR_IS_DIRECTORY, getPath(url));
return;
}
if (!S_ISREG(buff.st_mode)) {
error(KIO::ERR_CANNOT_OPEN_FOR_READING, getPath(url));
return;
}
int fd = QT_OPEN(_path.data(), O_RDONLY);
if (fd < 0) {
error(KIO::ERR_CANNOT_OPEN_FOR_READING, getPath(url));
return;
}
// Determine the mimetype of the file to be retrieved, and emit it.
// This is mandatory in all slaves (for KRun/BrowserRun to work).
QMimeDatabase db;
QMimeType mt = db.mimeTypeForFile(arcTempDir + file);
if (mt.isValid())
emit mimeType(mt.name());
KIO::filesize_t processed_size = 0;
QString resumeOffset = metaData("resume");
if (!resumeOffset.isEmpty()) {
bool ok;
KIO::fileoffset_t offset = resumeOffset.toLongLong(&ok);
if (ok && (offset > 0) && (offset < buff.st_size)) {
if (QT_LSEEK(fd, offset, SEEK_SET) == offset) {
canResume();
processed_size = offset;
}
}
}
totalSize(buff.st_size);
char buffer[ MAX_IPC_SIZE ];
while (1) {
int n = ::read(fd, buffer, MAX_IPC_SIZE);
if (n == -1) {
if (errno == EINTR)
continue;
error(KIO::ERR_CANNOT_READ, getPath(url));
::close(fd);
return;
}
if (n == 0)
break; // Finished
{
QByteArray array = QByteArray::fromRawData(buffer, n);
data(array);
}
processed_size += n;
}
data(QByteArray());
::close(fd);
processedSize(buff.st_size);
finished();
if (decompressToFile)
QFile(arcTempDir + file).remove();
return;
}
// send empty buffer to mark EOF
data(QByteArray());
finished();
}
void kio_krarcProtocol::del(QUrl const & url, bool isFile)
{
KRFUNC;
KRDEBUG(getPath(url));
if (!checkWriteSupport())
return;
if (!setArcFile(url)) {
error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url));
return;
}
if (newArchiveURL && !initDirDict(url)) {
error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url));
return;
}
if (delCmd.isEmpty()) {
error(ERR_UNSUPPORTED_ACTION,
i18n("Deleting files from %1 archives is not supported", arcType));
return;
}
if (!findFileEntry(url)) {
if ((arcType != "arj" && arcType != "lha") || isFile) {
error(KIO::ERR_DOES_NOT_EXIST, getPath(url));
return;
}
}
QString file = getPath(url).mid(getPath(arcFile->url()).length() + 1);
if (!isFile && file.right(1) != DIR_SEPARATOR) {
if (arcType == "zip") file = file + DIR_SEPARATOR;
}
KrLinecountingProcess proc;
proc << delCmd << getPath(arcFile->url()) << localeEncodedString(file);
infoMessage(i18n("Deleting %1...", url.fileName()));
SET_KRCODEC
proc.start();
RESET_KRCODEC
proc.waitForFinished();
if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(proc.exitCode())) {
error(ERR_CANNOT_WRITE, getPath(url) + "\n\n" + proc.getErrorMsg());
return;
}
// force a refresh of archive information
initDirDict(url, true);
finished();
}
void kio_krarcProtocol::stat(const QUrl &url)
{
KRFUNC;
KRDEBUG(getPath(url));
if (!setArcFile(url)) {
error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url));
return;
}
if (newArchiveURL && !initDirDict(url)) {
error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url));
return;
}
if (listCmd.isEmpty()) {
error(ERR_UNSUPPORTED_ACTION,
i18n("Accessing files is not supported with %1 archives", arcType));
return;
}
QString path = getPath(url, QUrl::StripTrailingSlash);
QUrl newUrl = url;
// but treat the archive itself as the archive root
if (path == getPath(arcFile->url(), QUrl::StripTrailingSlash)) {
newUrl.setPath(path + DIR_SEPARATOR);
path = getPath(newUrl);
}
// we might be stating a real file
if (QFileInfo(path).exists()) {
QT_STATBUF buff;
QT_STAT(path.toLocal8Bit(), &buff);
QString mime;
QMimeDatabase db;
QMimeType result = db.mimeTypeForFile(path);
if (result.isValid())
mime = result.name();
statEntry(KFileItem(QUrl::fromLocalFile(path), mime, buff.st_mode).entry());
finished();
return;
}
UDSEntry* entry = findFileEntry(newUrl);
if (entry) {
statEntry(*entry);
finished();
} else error(KIO::ERR_DOES_NOT_EXIST, path);
}
void kio_krarcProtocol::copy(const QUrl &url, const QUrl &dest, int, KIO::JobFlags flags)
{
KRDEBUG("source: " << url.path() << " dest: " << dest.path());
if (!checkWriteSupport())
return;
bool overwrite = !!(flags & KIO::Overwrite);
// KDE HACK: opening the password dlg in copy causes error for the COPY, and further problems
// that's why encrypted files are not allowed to copy
if (!encrypted && dest.isLocalFile())
do {
if (url.fileName() != dest.fileName())
break;
if (QTextCodec::codecForLocale()->name() != codec->name())
break;
//the file exists and we don't want to overwrite
if ((!overwrite) && (QFile(getPath(dest)).exists())) {
error((int)ERR_FILE_ALREADY_EXIST, QString(QFile::encodeName(getPath(dest))));
return;
};
if (!setArcFile(url)) {
error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url));
return;
}
if (newArchiveURL && !initDirDict(url)) {
error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url));
return;
}
UDSEntry* entry = findFileEntry(url);
if (copyCmd.isEmpty() || !entry)
break;
QString file = getPath(url).mid(getPath(arcFile->url()).length() + 1);
QString destDir = getPath(dest, QUrl::StripTrailingSlash);
if (!QDir(destDir).exists()) {
int ndx = destDir.lastIndexOf(DIR_SEPARATOR_CHAR);
if (ndx != -1)
destDir.truncate(ndx + 1);
}
QDir::setCurrent(destDir);
QString escapedFilename = file;
if(arcType == "zip") {
// left bracket needs to be escaped
escapedFilename.replace('[', "[[]");
}
KrLinecountingProcess proc;
proc << copyCmd << getPath(arcFile->url(), QUrl::StripTrailingSlash) << escapedFilename;
if (arcType == "ace" && QFile("/dev/ptmx").exists()) // Don't remove, unace crashes if missing!!!
proc.setStandardInputFile("/dev/ptmx");
proc.setOutputChannelMode(KProcess::SeparateChannels); // without this output redirection has no effect
infoMessage(i18n("Unpacking %1...", url.fileName()));
proc.start();
proc.waitForFinished();
if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(proc.exitCode())) {
error(KIO::ERR_CANNOT_WRITE, getPath(dest, QUrl::StripTrailingSlash) + "\n\n" + proc.getErrorMsg());
return;
}
if (!QFileInfo(getPath(dest, QUrl::StripTrailingSlash)).exists()) {
error(KIO::ERR_CANNOT_WRITE, getPath(dest, QUrl::StripTrailingSlash));
return;
}
processedSize(KFileItem(*entry, url).size());
finished();
QDir::setCurrent(QDir::rootPath()); /* for being able to umount devices after copying*/
return;
} while (0);
if (encrypted)
KRDEBUG("ERROR: " << url.path() << " is encrypted.");
if (!dest.isLocalFile())
KRDEBUG("ERROR: " << url.path() << " is not a local file.");
// CMD_COPY is no more in KF5 - replaced with 74 value (as stated in kio/src/core/commands_p.h, which could be found in cgit.kde.org/kio.git/tree)
error(ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, 74));
}
void kio_krarcProtocol::rename(const QUrl& src, const QUrl& dest, KIO::JobFlags flags)
{
Q_UNUSED(flags);
KRDEBUG("renaming from: " << src.path() << " to: " << dest.path());
KRDEBUG("command: " << arcPath);
if (!checkWriteSupport()) {
return;
}
if (renCmd.isEmpty()) {
error(KIO::ERR_CANNOT_RENAME, src.fileName());
return;
}
if (src.fileName() == dest.fileName()) {
return;
}
KrLinecountingProcess proc;
proc << renCmd << arcPath << src.path().remove(arcPath + '/') << dest.path().remove(arcPath + '/');
proc.start();
proc.waitForFinished();
if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(proc.exitCode())) {
error(KIO::ERR_CANNOT_RENAME, src.fileName());
return;
}
finished();
}
void kio_krarcProtocol::listDir(const QUrl &url)
{
KRFUNC;
KRDEBUG(getPath(url));
if (!setArcFile(url)) {
error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url));
return;
}
if (listCmd.isEmpty()) {
error(ERR_UNSUPPORTED_ACTION,
- i18n("Listing directories is not supported for %1 archives", arcType));
+ i18n("Listing folders is not supported for %1 archives", arcType));
return;
}
QString path = getPath(url);
if (path.right(1) != DIR_SEPARATOR) path = path + DIR_SEPARATOR;
// it might be a real dir !
if (QFileInfo(path).exists()) {
if (QFileInfo(path).isDir()) {
QUrl redir;
redir.setPath(getPath(url));
redirection(redir);
finished();
} else { // maybe it's an archive !
error(ERR_IS_FILE, path);
}
return;
}
if (!initDirDict(url)) {
error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url));
return;
}
QString arcDir = path.mid(getPath(arcFile->url()).length());
arcDir.truncate(arcDir.lastIndexOf(DIR_SEPARATOR));
if (arcDir.right(1) != DIR_SEPARATOR) arcDir = arcDir + DIR_SEPARATOR;
if (dirDict.find(arcDir) == dirDict.end()) {
error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url));
return;
}
UDSEntryList* dirList = dirDict[ arcDir ];
totalSize(dirList->size());
listEntries(*dirList);
finished();
}
bool kio_krarcProtocol::setArcFile(const QUrl &url)
{
KRFUNC;
KRDEBUG(url.fileName());
QString path = getPath(url);
time_t currTime = time(nullptr);
archiveChanged = true;
newArchiveURL = true;
// is the file already set ?
if (arcFile && getPath(arcFile->url(), QUrl::StripTrailingSlash) == path.left(getPath(arcFile->url(), QUrl::StripTrailingSlash).length())) {
newArchiveURL = false;
// Has it changed ?
KFileItem* newArcFile = new KFileItem(arcFile->url(), QString(), arcFile->mode());
if (metaData("Charset") != currentCharset || !newArcFile->cmp(*arcFile)) {
currentCharset = metaData("Charset");
codec = QTextCodec::codecForName(currentCharset.toLatin1());
if (codec == nullptr)
codec = QTextCodec::codecForMib(4 /* latin-1 */);
delete arcFile;
password.clear();
extArcReady = false;
arcFile = newArcFile;
} else { // same old file
delete newArcFile;
archiveChanged = false;
if (encrypted && password.isNull())
initArcParameters();
}
} else { // it's a new file...
extArcReady = false;
// new archive file means new dirDict, too
dirDict.clear();
if (arcFile) {
delete arcFile;
password.clear();
arcFile = nullptr;
}
QString newPath = path;
if (newPath.right(1) != DIR_SEPARATOR) newPath = newPath + DIR_SEPARATOR;
for (int pos = 0; pos >= 0; pos = newPath.indexOf(DIR_SEPARATOR, pos + 1)) {
QFileInfo qfi(newPath.left(pos));
if (qfi.exists() && !qfi.isDir()) {
QT_STATBUF stat_p;
QT_LSTAT(newPath.left(pos).toLocal8Bit(), &stat_p);
arcFile = new KFileItem(QUrl::fromLocalFile(newPath.left(pos)), QString(), stat_p.st_mode);
break;
}
}
if (!arcFile) {
// KRDEBUG("ERROR: " << path << " does not exist.");
error(ERR_DOES_NOT_EXIST, path);
return false; // file not found
}
currentCharset = metaData("Charset");
codec = QTextCodec::codecForName(currentCharset.toLatin1());
if (codec == nullptr)
codec = QTextCodec::codecForMib(4 /* latin-1 */);
}
/* FIX: file change can only be detected if the timestamp between the two consequent
changes is more than 1s. If the archive is continuously changing (check: move files
inside the archive), krarc may errorneusly think, that the archive file is unchanged,
because the timestamp is the same as the previous one. This situation can only occur
if the modification time equals with the current time. While this condition is true,
we can say, that the archive is changing, so content reread is always necessary
during that period. */
if (archiveChanging)
archiveChanged = true;
archiveChanging = (currTime == (time_t)arcFile->time(KFileItem::ModificationTime).toTime_t());
arcPath = getPath(arcFile->url(), QUrl::StripTrailingSlash);
arcType = detectArchive(encrypted, arcPath);
if (arcType == "tbz")
arcType = "bzip2";
else if (arcType == "tgz")
arcType = "gzip";
else if (arcType == "tlz")
arcType = "lzma";
else if (arcType == "txz")
arcType = "xz";
if (arcType.isEmpty()) {
arcType = arcFile->mimetype();
arcType = getShortTypeFromMime(arcType);
if (arcType == "jar")
arcType = "zip";
}
return initArcParameters();
}
bool kio_krarcProtocol::initDirDict(const QUrl &url, bool forced)
{
KRFUNC;
KRDEBUG(getPath(url));
// set the archive location
//if( !setArcFile(getPath(url)) ) return false;
// no need to rescan the archive if it's not changed
// KRDEBUG("achiveChanged: " << archiveChanged << " forced: " << forced);
if (!archiveChanged && !forced) {
// KRDEBUG("doing nothing.");
return true;
}
extArcReady = false;
if (!setArcFile(url))
return false; /* if the archive was changed refresh the file information */
// write the temp file
KrLinecountingProcess proc;
QTemporaryFile temp;
// parse the temp file
if (!temp.open()) {
error(ERR_CANNOT_READ, temp.fileName());
return false;
}
if (arcType != "bzip2" && arcType != "lzma" && arcType != "xz") {
if (arcType == "rpm") {
proc << listCmd << arcPath;
proc.setStandardOutputFile(temp.fileName());
} else {
proc << listCmd << getPath(arcFile->url(), QUrl::StripTrailingSlash);
proc.setStandardOutputFile(temp.fileName());
}
if (arcType == "ace" && QFile("/dev/ptmx").exists()) // Don't remove, unace crashes if missing!!!
proc.setStandardInputFile("/dev/ptmx");
proc.setOutputChannelMode(KProcess::SeparateChannels); // without this output redirection has no effect
proc.start();
proc.waitForFinished();
if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(proc.exitCode())) return false;
}
// clear the dir dictionary
QHashIterator< QString, KIO::UDSEntryList *> lit(dirDict);
while (lit.hasNext())
delete lit.next().value();
dirDict.clear();
// add the "/" directory
auto* root = new UDSEntryList();
dirDict.insert(DIR_SEPARATOR, root);
// and the "/" UDSEntry
UDSEntry entry;
entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_NAME, ".");
mode_t mode = parsePermString("drwxr-xr-x");
entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_FILE_TYPE, mode & S_IFMT); // keep file type only
entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_ACCESS, mode & 07777); // keep permissions only
root->append(entry);
if (arcType == "bzip2" || arcType == "lzma" || arcType == "xz")
abort();
char buf[1000];
QString line;
int lineNo = 0;
bool invalidLine = false;
// the rar list is started with a ------ line.
if (arcType == "rar" || arcType == "arj" || arcType == "lha" || arcType == "7z") {
while (temp.readLine(buf, 1000) != -1) {
line = decodeString(buf);
if (line.startsWith(QLatin1String("----------"))) break;
}
}
while (temp.readLine(buf, 1000) != -1) {
line = decodeString(buf);
if (arcType == "rar") {
// the rar list is ended with a ------ line.
if (line.startsWith(QLatin1String("----------"))) {
invalidLine = !invalidLine;
break;
}
if (invalidLine)
continue;
else {
if (line[0] == '*') // encrypted archives starts with '*'
line[0] = ' ';
}
}
if (arcType == "ace") {
// the ace list begins with a number.
if (!line[0].isDigit()) continue;
}
if (arcType == "arj") {
// the arj list is ended with a ------ line.
if (line.startsWith(QLatin1String("----------"))) {
invalidLine = !invalidLine;
continue;
}
if (invalidLine)
continue;
else {
temp.readLine(buf, 1000);
line = line + decodeString(buf);
temp.readLine(buf, 1000);
line = line + decodeString(buf);
temp.readLine(buf, 1000);
line = line + decodeString(buf);
}
}
if (arcType == "lha" || arcType == "7z") {
// the arj list is ended with a ------ line.
if (line.startsWith(QLatin1String("----------"))) break;
}
parseLine(lineNo++, line.trimmed());
}
// close and delete our file
temp.close();
archiveChanged = false;
// KRDEBUG("done.");
return true;
}
QString kio_krarcProtocol::findArcDirectory(const QUrl &url)
{
KRFUNC;
KRDEBUG(url.fileName());
QString path = getPath(url);
if (path.right(1) == DIR_SEPARATOR) path.truncate(path.length() - 1);
if (!initDirDict(url)) {
return QString();
}
QString arcDir = path.mid(getPath(arcFile->url()).length());
arcDir.truncate(arcDir.lastIndexOf(DIR_SEPARATOR));
if (arcDir.right(1) != DIR_SEPARATOR) arcDir = arcDir + DIR_SEPARATOR;
return arcDir;
}
UDSEntry* kio_krarcProtocol::findFileEntry(const QUrl &url)
{
KRFUNC;
QString arcDir = findArcDirectory(url);
if (arcDir.isEmpty()) return nullptr;
QHash::iterator itef = dirDict.find(arcDir);
if (itef == dirDict.end())
return nullptr;
UDSEntryList* dirList = itef.value();
QString name = getPath(url);
if (getPath(arcFile->url(), QUrl::StripTrailingSlash) == getPath(url, QUrl::StripTrailingSlash)) name = '.'; // the '/' case
else {
if (name.right(1) == DIR_SEPARATOR) name.truncate(name.length() - 1);
name = name.mid(name.lastIndexOf(DIR_SEPARATOR) + 1);
}
UDSEntryList::iterator entry;
for (entry = dirList->begin(); entry != dirList->end(); ++entry) {
if ((entry->contains(KIO::UDSEntry::UDS_NAME)) &&
(entry->stringValue(KIO::UDSEntry::UDS_NAME) == name))
return &(*entry);
}
return nullptr;
}
QString kio_krarcProtocol::nextWord(QString &s, char d)
{
// Note: KRFUNC was not used here in order to avoid filling the log with too much information
s = s.trimmed();
int j = s.indexOf(d, 0);
QString temp = s.left(j); // find the leftmost word.
s.remove(0, j);
return temp;
}
mode_t kio_krarcProtocol::parsePermString(QString perm)
{
KRFUNC;
mode_t mode = 0;
// file type
if (perm[0] == 'd') mode |= S_IFDIR;
#ifndef Q_OS_WIN
if (perm[0] == 'l') mode |= S_IFLNK;
#endif
if (perm[0] == '-') mode |= S_IFREG;
// owner permissions
if (perm[1] != '-') mode |= S_IRUSR;
if (perm[2] != '-') mode |= S_IWUSR;
if (perm[3] != '-') mode |= S_IXUSR;
#ifndef Q_OS_WIN
// group permissions
if (perm[4] != '-') mode |= S_IRGRP;
if (perm[5] != '-') mode |= S_IWGRP;
if (perm[6] != '-') mode |= S_IXGRP;
// other permissions
if (perm[7] != '-') mode |= S_IROTH;
if (perm[8] != '-') mode |= S_IWOTH;
if (perm[9] != '-') mode |= S_IXOTH;
#endif
return mode;
}
UDSEntryList* kio_krarcProtocol::addNewDir(const QString& path)
{
KRFUNC;
UDSEntryList* dir;
// check if the current dir exists
QHash::iterator itef = dirDict.find(path);
if (itef != dirDict.end())
return itef.value();
// set dir to the parent dir
dir = addNewDir(path.left(path.lastIndexOf(DIR_SEPARATOR, -2) + 1));
// add a new entry in the parent dir
QString name = path.mid(path.lastIndexOf(DIR_SEPARATOR, -2) + 1);
name = name.left(name.length() - 1);
if (name == "." || name == "..") { // entries with these names wouldn't be displayed
// don't translate since this is an internal error
QString err = QString("Cannot handle path: ") + path;
// KRDEBUG("ERROR: " << err);
error(KIO::ERR_INTERNAL, err);
exit();
}
UDSEntry entry;
entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_NAME, name);
mode_t mode = parsePermString("drwxr-xr-x");
entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_FILE_TYPE, mode & S_IFMT); // keep file type only
entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_ACCESS, mode & 07777); // keep permissions only
entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_SIZE, 0);
entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_MODIFICATION_TIME, arcFile->time(KFileItem::ModificationTime).toTime_t());
dir->append(entry);
// create a new directory entry and add it..
dir = new UDSEntryList();
dirDict.insert(path, dir);
return dir;
}
void kio_krarcProtocol::parseLine(int lineNo, QString line)
{
KRFUNC;
UDSEntryList* dir;
UDSEntry entry;
QString owner;
QString group;
QString symlinkDest;
QString perm;
mode_t mode = 0666;
size_t size = 0;
time_t time = ::time(nullptr);
QString fullName;
if (arcType == "zip") {
// permissions
perm = nextWord(line);
// ignore the next 2 fields
nextWord(line); nextWord(line);
// size
size = nextWord(line).toLong();
// ignore the next 2 fields
nextWord(line);nextWord(line);
// date & time
QString d = nextWord(line);
QDate qdate(d.mid(0, 4).toInt(), d.mid(4, 2).toInt(), d.mid(6, 2).toInt());
QTime qtime(d.mid(9, 2).toInt(), d.mid(11, 2).toInt(), d.mid(13, 2).toInt());
time = QDateTime(qdate, qtime).toTime_t();
// full name
fullName = nextWord(line, '\n');
if (perm.length() != 10)
perm = (perm.at(0) == 'd' || fullName.endsWith(DIR_SEPARATOR)) ? "drwxr-xr-x" : "-rw-r--r--" ;
mode = parsePermString(perm);
}
if (arcType == "rar") {
// permissions
perm = nextWord(line);
// size
size = nextWord(line).toLong();
// ignore the next 2 fields : packed size and compression ration
nextWord(line); nextWord(line);
// date & time
QString d = nextWord(line);
int year = 1900 + d.mid(6, 2).toInt();
if (year < 1930)
year += 100;
QDate qdate(year, d.mid(3, 2).toInt(), d.mid(0, 2).toInt());
QString t = nextWord(line);
QTime qtime(t.mid(0, 2).toInt(), t.mid(3, 2).toInt(), 0);
time = QDateTime(qdate, qtime).toTime_t();
// checksum : ignored
nextWord(line);
// full name
fullName = nextWord(line, '\n');
if (perm.length() == 7) { // windows rar permission format
bool isDir = (perm.at(1).toLower() == 'd');
bool isReadOnly = (perm.at(2).toLower() == 'r');
perm = isDir ? "drwxr-xr-x" : "-rw-r--r--";
if (isReadOnly)
perm[ 2 ] = '-';
}
if (perm.length() != 10) perm = (perm.at(0) == 'd') ? "drwxr-xr-x" : "-rw-r--r--" ;
mode = parsePermString(perm);
}
if (arcType == "arj") {
nextWord(line);
// full name
fullName = nextWord(line, '\n');
// ignore the next 2 fields
nextWord(line); nextWord(line);
// size
size = nextWord(line).toLong();
// ignore the next 2 fields
nextWord(line); nextWord(line);
// date & time
QString d = nextWord(line);
int year = 1900 + d.mid(0, 2).toInt();
if (year < 1930) year += 100;
QDate qdate(year, d.mid(3, 2).toInt(), d.mid(6, 2).toInt());
QString t = nextWord(line);
QTime qtime(t.mid(0, 2).toInt(), t.mid(3, 2).toInt(), 0);
time = QDateTime(qdate, qtime).toTime_t();
// permissions
perm = nextWord(line);
if (perm.length() != 10) perm = (perm.at(0) == 'd') ? "drwxr-xr-x" : "-rw-r--r--" ;
mode = parsePermString(perm);
}
if (arcType == "rpm") {
// full name
fullName = nextWord(line);
// size
size = nextWord(line).toULong();
// date & time
time = nextWord(line).toULong();
// next field is md5sum, ignore it
nextWord(line);
// permissions
mode = nextWord(line).toULong(nullptr, 8);
// Owner & Group
owner = nextWord(line);
group = nextWord(line);
// symlink destination
#ifndef Q_OS_WIN
if (S_ISLNK(mode)) {
// ignore the next 3 fields
nextWord(line); nextWord(line); nextWord(line);
symlinkDest = nextWord(line);
}
#endif
}
if (arcType == "gzip") {
if (!lineNo) return; //ignore the first line
// first field is uncompressed size - ignore it
nextWord(line);
// size
size = nextWord(line).toULong();
// ignore the next field
nextWord(line);
// full name
fullName = nextWord(line);
fullName = fullName.mid(fullName.lastIndexOf(DIR_SEPARATOR) + 1);
}
if (arcType == "lzma") {
fullName = arcFile->name();
if (fullName.endsWith(QLatin1String("lzma"))) {
fullName.truncate(fullName.length() - 5);
}
mode = arcFile->mode();
size = arcFile->size();
}
if (arcType == "xz") {
fullName = arcFile->name();
if (fullName.endsWith(QLatin1String("xz"))) {
fullName.truncate(fullName.length() - 3);
}
mode = arcFile->mode();
size = arcFile->size();
}
if (arcType == "bzip2") {
// There is no way to list bzip2 files, so we take our information from
// the archive itself...
fullName = arcFile->name();
if (fullName.endsWith(QLatin1String("bz2"))) {
fullName.truncate(fullName.length() - 4);
}
mode = arcFile->mode();
size = arcFile->size();
}
if (arcType == "lha") {
// permissions
perm = nextWord(line);
if (perm.length() != 10) perm = (perm.at(0) == 'd') ? "drwxr-xr-x" : "-rw-r--r--" ;
mode = parsePermString(perm);
// ignore the next field
nextWord(line);
// size
size = nextWord(line).toLong();
// ignore the next field
nextWord(line);
// date & time
int month = (QString("Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec").split(',')).indexOf(nextWord(line)) + 1;
int day = nextWord(line).toInt();
int year = QDate::currentDate().year();
QString third = nextWord(line);
QTime qtime;
if (third.contains(":"))
qtime = QTime::fromString(third);
else
year = third.toInt();
QDate qdate(year, month, day);
time = QDateTime(qdate, qtime).toTime_t();
// full name
fullName = nextWord(line, '\n');
}
if (arcType == "ace") {
// date & time
QString d = nextWord(line);
int year = 1900 + d.mid(6, 2).toInt();
if (year < 1930) year += 100;
QDate qdate(year, d.mid(3, 2).toInt(), d.mid(0, 2).toInt());
QString t = nextWord(line);
QTime qtime(t.mid(0, 2).toInt(), t.mid(3, 2).toInt(), 0);
time = QDateTime(qdate, qtime).toTime_t();
// ignore the next field
nextWord(line);
// size
size = nextWord(line).toLong();
// ignore the next field
nextWord(line);
// full name
fullName = nextWord(line, '\n');
if (fullName[ 0 ] == '*') // encrypted archives starts with '*'
fullName = fullName.mid(1);
}
if (arcType == "deb") {
// permissions
perm = nextWord(line);
mode = parsePermString(perm);
// Owner & Group
owner = nextWord(line, DIR_SEPARATOR_CHAR);
group = nextWord(line).mid(1);
// size
size = nextWord(line).toLong();
// date & time
QString d = nextWord(line);
QDate qdate(d.mid(0, 4).toInt(), d.mid(5, 2).toInt(), d.mid(8, 2).toInt());
QString t = nextWord(line);
QTime qtime(t.mid(0, 2).toInt(), t.mid(3, 2).toInt(), 0);
time = QDateTime(qdate, qtime).toTime_t();
// full name
fullName = nextWord(line, '\n').mid(1);
//if ( fullName.right( 1 ) == "/" ) return;
if (fullName.contains("->")) {
symlinkDest = fullName.mid(fullName.indexOf("->") + 2);
fullName = fullName.left(fullName.indexOf("->") - 1);
}
}
if (arcType == "7z") {
// date & time
QString d = nextWord(line);
QDate qdate(d.mid(0, 4).toInt(), d.mid(5, 2).toInt(), d.mid(8, 2).toInt());
QString t = nextWord(line);
QTime qtime(t.mid(0, 2).toInt(), t.mid(3, 2).toInt(), t.mid(6, 2).toInt());
time = QDateTime(qdate, qtime).toTime_t();
// permissions
perm = nextWord(line);
bool isDir = (perm.at(0).toLower() == 'd');
bool isReadOnly = (perm.at(1).toLower() == 'r');
perm = isDir ? "drwxr-xr-x" : "-rw-r--r--";
if (isReadOnly)
perm[ 2 ] = '-';
mode = parsePermString(perm);
// size
size = nextWord(line).toLong();
// ignore the next 15 characters
line = line.mid(15);
// full name
fullName = nextWord(line, '\n');
}
if (fullName.right(1) == DIR_SEPARATOR) fullName = fullName.left(fullName.length() - 1);
if (!fullName.startsWith(DIR_SEPARATOR)) fullName = DIR_SEPARATOR + fullName;
QString path = fullName.left(fullName.lastIndexOf(DIR_SEPARATOR) + 1);
// set/create the directory UDSEntryList
QHash::iterator itef = dirDict.find(path);
if (itef == dirDict.end())
dir = addNewDir(path);
else
dir = itef.value();
QString name = fullName.mid(fullName.lastIndexOf(DIR_SEPARATOR) + 1);
// file name
entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_NAME, name);
// file type
entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_FILE_TYPE, mode & S_IFMT); // keep file type only
// file permissions
entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_ACCESS, mode & 07777); // keep permissions only
// file size
entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_SIZE, size);
// modification time
entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_MODIFICATION_TIME, time);
// link destination
if (!symlinkDest.isEmpty()) {
entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_LINK_DEST, symlinkDest);
}
if (S_ISDIR(mode)) {
fullName = fullName + DIR_SEPARATOR;
if (dirDict.find(fullName) == dirDict.end())
dirDict.insert(fullName, new UDSEntryList());
else {
// try to overwrite an existing entry
UDSEntryList::iterator entryIt;
for (entryIt = dir->begin(); entryIt != dir->end(); ++entryIt) {
if (entryIt->contains(KIO::UDSEntry::UDS_NAME) &&
entryIt->stringValue(KIO::UDSEntry::UDS_NAME) == name) {
entryIt->UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_MODIFICATION_TIME, time);
entryIt->UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_ACCESS, mode);
return;
}
}
return; // there is already an entry for this directory
}
}
// multi volume archives can add a file twice, use only one
UDSEntryList::iterator dirEntryIt;
for (dirEntryIt = dir->begin(); dirEntryIt != dir->end(); ++dirEntryIt)
if (dirEntryIt->contains(KIO::UDSEntry::UDS_NAME) &&
dirEntryIt->stringValue(KIO::UDSEntry::UDS_NAME) == name)
return;
dir->append(entry);
}
bool kio_krarcProtocol::initArcParameters()
{
KRFUNC;
KRDEBUG("arcType: " << arcType);
noencoding = false;
cmd.clear();
listCmd = QStringList();
getCmd = QStringList();
copyCmd = QStringList();
delCmd = QStringList();
putCmd = QStringList();
renCmd = QStringList();
if (arcType == "zip") {
noencoding = true;
cmd = fullPathName("unzip");
listCmd << fullPathName("unzip") << "-ZTs-z-t-h";
getCmd << fullPathName("unzip") << "-p";
copyCmd << fullPathName("unzip") << "-jo";
if (QStandardPaths::findExecutable(QStringLiteral("zip")).isEmpty()) {
delCmd = QStringList();
putCmd = QStringList();
} else {
delCmd << fullPathName("zip") << "-d";
putCmd << fullPathName("zip") << "-ry";
}
if (!QStandardPaths::findExecutable(QStringLiteral("7za")).isEmpty()) {
renCmd << fullPathName("7za") << "rn";
}
if (!getPassword().isEmpty()) {
getCmd << "-P" << password;
copyCmd << "-P" << password;
putCmd << "-P" << password;
}
} else if (arcType == "rar") {
noencoding = true;
if (QStandardPaths::findExecutable(QStringLiteral("rar")).isEmpty()) {
cmd = fullPathName("unrar");
listCmd << fullPathName("unrar") << "-c-" << "-v" << "v";
getCmd << fullPathName("unrar") << "p" << "-ierr" << "-idp" << "-c-" << "-y";
copyCmd << fullPathName("unrar") << "e" << "-y";
delCmd = QStringList();
putCmd = QStringList();
} else {
cmd = fullPathName("rar");
listCmd << fullPathName("rar") << "-c-" << "-v" << "v";
getCmd << fullPathName("rar") << "p" << "-ierr" << "-idp" << "-c-" << "-y";
copyCmd << fullPathName("rar") << "e" << "-y";
delCmd << fullPathName("rar") << "d";
putCmd << fullPathName("rar") << "-r" << "a";
}
if (!getPassword().isEmpty()) {
getCmd << QString("-p%1").arg(password);
listCmd << QString("-p%1").arg(password);
copyCmd << QString("-p%1").arg(password);
if (!putCmd.isEmpty()) {
putCmd << QString("-p%1").arg(password);
delCmd << QString("-p%1").arg(password);
}
}
} else if (arcType == "rpm") {
cmd = fullPathName("rpm");
listCmd << fullPathName("rpm") << "--dump" << "-lpq";
getCmd << fullPathName("cpio") << "--force-local" << "--no-absolute-filenames" << "-iuvdF";
delCmd = QStringList();
putCmd = QStringList();
copyCmd = QStringList();
} else if (arcType == "gzip") {
cmd = fullPathName("gzip");
listCmd << fullPathName("gzip") << "-l";
getCmd << fullPathName("gzip") << "-dc";
copyCmd = QStringList();
delCmd = QStringList();
putCmd = QStringList();
} else if (arcType == "bzip2") {
cmd = fullPathName("bzip2");
listCmd << fullPathName("bzip2");
getCmd << fullPathName("bzip2") << "-dc";
copyCmd = QStringList();
delCmd = QStringList();
putCmd = QStringList();
} else if (arcType == "lzma") {
cmd = fullPathName("lzma");
listCmd << fullPathName("lzma");
getCmd << fullPathName("lzma") << "-dc";
copyCmd = QStringList();
delCmd = QStringList();
putCmd = QStringList();
} else if (arcType == "xz") {
cmd = fullPathName("xz");
listCmd << fullPathName("xz");
getCmd << fullPathName("xz") << "-dc";
copyCmd = QStringList();
delCmd = QStringList();
putCmd = QStringList();
} else if (arcType == "arj") {
cmd = fullPathName("arj");
listCmd << fullPathName("arj") << "v" << "-y" << "-v";
getCmd << fullPathName("arj") << "-jyov" << "-v" << "e";
copyCmd << fullPathName("arj") << "-jyov" << "-v" << "e";
delCmd << fullPathName("arj") << "d";
putCmd << fullPathName("arj") << "-r" << "a";
if (!getPassword().isEmpty()) {
getCmd << QString("-g%1").arg(password);
copyCmd << QString("-g%1").arg(password);
putCmd << QString("-g%1").arg(password);
}
} else if (arcType == "lha") {
cmd = fullPathName("lha");
listCmd << fullPathName("lha") << "l";
getCmd << fullPathName("lha") << "pq";
copyCmd << fullPathName("lha") << "eif";
delCmd << fullPathName("lha") << "d";
putCmd << fullPathName("lha") << "a";
} else if (arcType == "ace") {
cmd = fullPathName("unace");
listCmd << fullPathName("unace") << "v";
getCmd << fullPathName("unace") << "e" << "-o";
copyCmd << fullPathName("unace") << "e" << "-o";
delCmd = QStringList();
putCmd = QStringList();
if (!getPassword().isEmpty()) {
getCmd << QString("-p%1").arg(password);
copyCmd << QString("-p%1").arg(password);
}
} else if (arcType == "deb") {
cmd = fullPathName("dpkg");
listCmd << fullPathName("dpkg") << "-c";
getCmd << fullPathName("tar") << "xvf";
copyCmd = QStringList();
delCmd = QStringList();
putCmd = QStringList();
} else if (arcType == "7z") {
noencoding = true;
cmd = fullPathName("7z");
if (QStandardPaths::findExecutable(cmd).isEmpty())
cmd = fullPathName("7za");
listCmd << cmd << "l" << "-y";
getCmd << cmd << "e" << "-y";
copyCmd << cmd << "e" << "-y";
delCmd << cmd << "d" << "-y";
putCmd << cmd << "a" << "-y";
renCmd << cmd << "rn";
if (!getPassword().isEmpty()) {
getCmd << QString("-p%1").arg(password);
listCmd << QString("-p%1").arg(password);
copyCmd << QString("-p%1").arg(password);
if (!putCmd.isEmpty()) {
putCmd << QString("-p%1").arg(password);
delCmd << QString("-p%1").arg(password);
}
}
}
// checking if it's an absolute path
#ifdef Q_OS_WIN
if (cmd.length() > 2 && cmd[ 0 ].isLetter() && cmd[ 1 ] == ':')
return true;
#else
if (cmd.startsWith(DIR_SEPARATOR))
return true;
#endif
if (QStandardPaths::findExecutable(cmd).isEmpty()) {
error(KIO::ERR_CANNOT_LAUNCH_PROCESS,
cmd +
i18n("\nMake sure that the %1 binary is installed properly on your system.", cmd));
KRDEBUG("Failed to find cmd: " << cmd);
return false;
}
return true;
}
bool kio_krarcProtocol::checkStatus(int exitCode)
{
KRFUNC;
KRDEBUG(exitCode);
return KrArcBaseManager::checkStatus(arcType, exitCode);
}
void kio_krarcProtocol::checkIf7zIsEncrypted(bool &encrypted, QString fileName)
{
KRFUNC;
if (encryptedArchPath == fileName)
encrypted = true;
else { // we try to find whether the 7z archive is encrypted
// this is hard as the headers are also compressed
QString tester = fullPathName("7z");
if (QStandardPaths::findExecutable(tester).isEmpty()) {
KRDEBUG("A 7z program was not found");
tester = fullPathName("7za");
if (QStandardPaths::findExecutable(tester).isEmpty()) {
KRDEBUG("A 7za program was not found");
return;
}
}
QString testCmd = tester + " t -y ";
lastData = encryptedArchPath = "";
KrLinecountingProcess proc;
proc << testCmd << fileName;
connect(&proc, &KrLinecountingProcess::newOutputData, this, &kio_krarcProtocol::checkOutputForPassword);
proc.start();
proc.waitForFinished();
encrypted = this->encrypted;
if (encrypted)
encryptedArchPath = fileName;
}
}
void kio_krarcProtocol::checkOutputForPassword(KProcess * proc, QByteArray & buf)
{
KRFUNC;
QString data = QString(buf);
QString checkable = lastData + data;
QStringList lines = checkable.split('\n');
lastData = lines[ lines.count() - 1 ];
for (int i = 0; i != lines.count(); i++) {
QString line = lines[ i ].trimmed().toLower();
int ndx = line.indexOf("testing");
if (ndx >= 0)
line.truncate(ndx);
if (line.isEmpty())
continue;
if (line.contains("password") && line.contains("enter")) {
KRDEBUG("Encrypted 7z archive found!");
encrypted = true;
proc->kill();
return;
}
}
}
void kio_krarcProtocol::invalidatePassword()
{
KRFUNC;
KRDEBUG(getPath(arcFile->url(), QUrl::StripTrailingSlash) + DIR_SEPARATOR);
if (!encrypted)
return;
KIO::AuthInfo authInfo;
authInfo.caption = i18n("Krarc Password Dialog");
authInfo.username = "archive";
authInfo.readOnly = true;
authInfo.keepPassword = true;
authInfo.verifyPath = true;
QString fileName = getPath(arcFile->url(), QUrl::StripTrailingSlash);
authInfo.url = QUrl::fromLocalFile(ROOT_DIR);
authInfo.url.setHost(fileName /*.replace('/','_')*/);
authInfo.url.setScheme("krarc");
password.clear();
cacheAuthentication(authInfo);
}
QString kio_krarcProtocol::getPassword()
{
KRFUNC;
KRDEBUG("Encrypted: " << encrypted);
if (!password.isNull())
return password;
if (!encrypted)
return (password = "");
KIO::AuthInfo authInfo;
authInfo.caption = i18n("Krarc Password Dialog");
authInfo.username = "archive";
authInfo.readOnly = true;
authInfo.keepPassword = true;
authInfo.verifyPath = true;
QString fileName = getPath(arcFile->url(), QUrl::StripTrailingSlash);
authInfo.url = QUrl::fromLocalFile(ROOT_DIR);
authInfo.url.setHost(fileName /*.replace('/','_')*/);
authInfo.url.setScheme("krarc");
if (checkCachedAuthentication(authInfo) && !authInfo.password.isNull()) {
KRDEBUG(authInfo.password);
return (password = authInfo.password);
}
authInfo.password.clear();
#if KIO_VERSION_MINOR >= 24
int errCode = openPasswordDialogV2(authInfo, i18n("Accessing the file requires a password."));
if (!errCode && !authInfo.password.isNull()) {
#else
if (openPasswordDialog(authInfo, i18n("Accessing the file requires a password.")) && !authInfo.password.isNull()) {
#endif
KRDEBUG(authInfo.password);
return (password = authInfo.password);
#if KIO_VERSION_MINOR >= 24
} else {
error(errCode, QString());
#endif
}
KRDEBUG(password);
return password;
}
QString kio_krarcProtocol::detectFullPathName(QString name)
{
// Note: KRFUNC was not used here in order to avoid filling the log with too much information
KRDEBUG(name);
name = name + EXEC_SUFFIX;
QStringList path = QString::fromLocal8Bit(qgetenv("PATH")).split(':');
for (auto & it : path) {
if (QDir(it).exists(name)) {
QString dir = it;
if (!dir.endsWith(DIR_SEPARATOR))
dir += DIR_SEPARATOR;
return dir + name;
}
}
return name;
}
QString kio_krarcProtocol::fullPathName(const QString& name)
{
// Note: KRFUNC was not used here in order to avoid filling the log with too much information
KRDEBUG(name);
QString supposedName = confGrp.readEntry(name, QString());
if (supposedName.isEmpty())
supposedName = detectFullPathName(name);
return supposedName;
}
QString kio_krarcProtocol::localeEncodedString(QString str)
{
// Note: KRFUNC was not used here in order to avoid filling the log with too much information
if (noencoding)
return str;
QByteArray array = codec->fromUnicode(str);
// encoding the byte array to QString, mapping 0x0000-0x00FF to 0xE000-0xE0FF
// see KrArcCodec for more explanation
int size = array.size();
QString result;
const char *data = array.data();
for (int i = 0; i != size; i++) {
unsigned short ch = (((int)data[ i ]) & 0xFF) + 0xE000; // user defined character
result.append(QChar(ch));
}
return result;
}
QByteArray kio_krarcProtocol::encodeString(const QString& str)
{
// Note: KRFUNC was not used here in order to avoid filling the log with too much information
if (noencoding)
return QTextCodec::codecForLocale()->fromUnicode(str);
return codec->fromUnicode(str);
}
QString kio_krarcProtocol::decodeString(char * buf)
{
// Note: KRFUNC was not used here in order to avoid filling the log with too much information
if (noencoding)
return QTextCodec::codecForLocale()->toUnicode(buf);
return codec->toUnicode(buf);
}
QString kio_krarcProtocol::getPath(const QUrl &url, QUrl::FormattingOptions options)
{
// Note: KRFUNC was not used here in order to avoid filling the log with too much information
QString path = url.adjusted(options).path();
REPLACE_DIR_SEP2(path);
#ifdef Q_OS_WIN
if (path.startsWith(DIR_SEPARATOR)) {
int p = 1;
while (p < path.length() && path[ p ] == DIR_SEPARATOR_CHAR)
p++;
/* /C:/Folder */
if (p + 2 <= path.length() && path[ p ].isLetter() && path[ p + 1 ] == ':') {
path = path.mid(p);
}
}
#endif
return path;
}
#endif // KRARC_ENABLED
diff --git a/krusader/Dialogs/checksumdlg.cpp b/krusader/Dialogs/checksumdlg.cpp
index f7733b5e..010880cc 100644
--- a/krusader/Dialogs/checksumdlg.cpp
+++ b/krusader/Dialogs/checksumdlg.cpp
@@ -1,574 +1,574 @@
/*****************************************************************************
* Copyright (C) 2005 Shie Erlich *
* Copyright (C) 2007-2008 Csaba Karai *
* Copyright (C) 2008 Jonas Bähr *
* Copyright (C) 2005-2019 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#include "checksumdlg.h"
#include "../krglobal.h"
#include "../icon.h"
#include "../krservices.h"
#include "../krusader.h"
#include "../GUI/krlistwidget.h"
#include "../GUI/krtreewidget.h"
// QtCore
#include
#include
#include
#include
#include
#include
// QtWidgets
#include
#include
#include
#include
#include
#include // krazy:exclude=includes
#include
#include
#include
void Checksum::startCreationWizard(const QString &path, const QStringList &files)
{
if (files.isEmpty())
return;
QDialog *dialog = new CHECKSUM_::CreateWizard(path, files);
dialog->show();
}
void Checksum::startVerifyWizard(const QString &path, const QString &checksumFile)
{
QDialog *dialog = new CHECKSUM_::VerifyWizard(path, checksumFile);
dialog->show();
}
namespace CHECKSUM_ {
bool stopListFiles;
// async operation invoked by QtConcurrent::run in creation wizard
QStringList listFiles(const QString &path, const QStringList &fileNames)
{
const QDir baseDir(path);
QStringList allFiles;
for (const QString& fileName : fileNames) {
if (stopListFiles)
return QStringList();
QDir subDir = QDir(baseDir.filePath(fileName));
if (subDir.exists()) {
subDir.setFilter(QDir::Files);
QDirIterator it(subDir, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
while (it.hasNext()) {
if (stopListFiles)
return QStringList();
allFiles << baseDir.relativeFilePath(it.next());
}
} else {
// assume this is a file
allFiles << fileName;
}
}
return allFiles;
}
// ------------- Checksum Process
ChecksumProcess::ChecksumProcess(QObject *parent, const QString &path) : KProcess(parent),
m_tmpOutFile(QDir::tempPath() + QLatin1String("/krusader_XXXXXX.stdout")),
m_tmpErrFile(QDir::tempPath() + QLatin1String("/krusader_XXXXXX.stderr"))
{
m_tmpOutFile.open(); // necessary to create the filename
m_tmpErrFile.open(); // necessary to create the filename
setOutputChannelMode(KProcess::SeparateChannels); // without this the next 2 lines have no effect!
setStandardOutputFile(m_tmpOutFile.fileName());
setStandardErrorFile(m_tmpErrFile.fileName());
setWorkingDirectory(path);
connect(this, &ChecksumProcess::errorOccurred, this, &ChecksumProcess::slotError);
connect(this, static_cast(&QProcess::finished),
this, &ChecksumProcess::slotFinished);
}
ChecksumProcess::~ChecksumProcess()
{
disconnect(this, nullptr, this, nullptr); // QProcess emits finished() on destruction
close();
}
void ChecksumProcess::slotError(QProcess::ProcessError error)
{
if (error == QProcess::FailedToStart) {
KMessageBox::error(nullptr, i18n("Could not start %1.", program().join(" ")));
}
}
void ChecksumProcess::slotFinished(int, QProcess::ExitStatus exitStatus)
{
if (exitStatus != QProcess::NormalExit) {
KMessageBox::error(nullptr, i18n("There was an error while running %1.",
program().join(" ")));
return;
}
// parse result files
if (!KrServices::fileToStringList(&m_tmpOutFile, m_outputLines) ||
!KrServices::fileToStringList(&m_tmpErrFile, m_errorLines)) {
KMessageBox::error(nullptr, i18n("Error reading stdout or stderr"));
return;
}
emit resultReady();
}
// ------------- Generic Checksum Wizard
ChecksumWizard::ChecksumWizard(const QString &path) : QWizard(krApp), m_path(path), m_process(nullptr)
{
setAttribute(Qt::WA_DeleteOnClose);
// init the dictionary - pity it has to be manually
m_checksumTools.insert("md5", "md5sum");
m_checksumTools.insert("sha1", "sha1sum");
m_checksumTools.insert("sha256", "sha256sum");
m_checksumTools.insert("sha224", "sha224sum");
m_checksumTools.insert("sha384", "sha384sum");
m_checksumTools.insert("sha512", "sha512sum");
connect(this, &QWizard::currentIdChanged, this, &ChecksumWizard::slotCurrentIdChanged);
}
ChecksumWizard::~ChecksumWizard()
{
if (m_process) {
delete m_process;
}
}
void ChecksumWizard::slotCurrentIdChanged(int id)
{
if (id == m_introId) {
onIntroPage();
} else if (id == m_progressId) {
if (m_process) {
// we are coming from the result page;
delete m_process;
m_process = nullptr;
restart();
} else {
button(QWizard::BackButton)->hide();
button(QWizard::NextButton)->hide();
onProgressPage();
}
} else if (id == m_resultId) {
onResultPage();
}
}
QWizardPage *ChecksumWizard::createProgressPage(const QString &title)
{
auto *page = new QWizardPage;
page->setTitle(title);
page->setPixmap(QWizard::LogoPixmap,
Icon("process-working").pixmap(32));
page->setSubTitle(i18n("Please wait..."));
auto *mainLayout = new QVBoxLayout;
page->setLayout(mainLayout);
// "busy" indicator
auto *bar = new QProgressBar();
bar->setRange(0,0);
mainLayout->addWidget(bar);
return page;
}
bool ChecksumWizard::checkExists(const QString& type)
{
if (!KrServices::cmdExist(m_checksumTools[type])) {
KMessageBox::error(
this, i18n("Krusader cannot find a checksum tool that handles %1 on your system. "
"Please check the Dependencies page in Krusader's settings.",
type));
return false;
}
return true;
}
void ChecksumWizard::runProcess(const QString &type, const QStringList &args)
{
Q_ASSERT(m_process == nullptr);
m_process = new ChecksumProcess(this, m_path);
m_process->setProgram(KrServices::fullPathName(m_checksumTools[type]), args);
// show next page (with results) (only) when process is done
connect(m_process, &ChecksumProcess::resultReady, this, &QWizard::next);
// run the process
m_process->start();
}
void ChecksumWizard::addChecksumLine(KrTreeWidget *tree, const QString &line)
{
auto *item = new QTreeWidgetItem(tree);
const int hashLength = line.indexOf(' '); // delimiter is either " " or " *"
item->setText(0, line.left(hashLength));
QString fileName = line.mid(hashLength + 2);
if (fileName.endsWith('\n'))
fileName.chop(1);
item->setText(1, fileName);
}
// ------------- Create Wizard
CreateWizard::CreateWizard(const QString &path, const QStringList &_files) : ChecksumWizard(path),
m_fileNames(_files)
{
m_introId = addPage(createIntroPage());
m_progressId = addPage(createProgressPage(i18n("Creating Checksums")));
m_resultId = addPage(createResultPage());
setButton(QWizard::FinishButton,
QDialogButtonBox(QDialogButtonBox::Save).button(QDialogButtonBox::Save));
connect(&m_listFilesWatcher, &QFutureWatcher::resultReadyAt,
this, &CreateWizard::createChecksums);
}
QWizardPage *CreateWizard::createIntroPage()
{
auto *page = new QWizardPage;
page->setTitle(i18n("Create Checksums"));
page->setPixmap(QWizard::LogoPixmap,
Icon("document-edit-sign").pixmap(32));
- page->setSubTitle(i18n("About to calculate checksum for the following files or directories:"));
+ page->setSubTitle(i18n("About to calculate checksum for the following files or folders:"));
auto *mainLayout = new QVBoxLayout;
page->setLayout(mainLayout);
// file list
auto *listWidget = new KrListWidget;
listWidget->addItems(m_fileNames);
mainLayout->addWidget(listWidget);
// checksum method
auto *hLayout = new QHBoxLayout;
QLabel *methodLabel = new QLabel(i18n("Select the checksum method:"));
hLayout->addWidget(methodLabel);
m_methodBox = new KComboBox;
// -- fill the combo with available methods
for (const QString& type: m_checksumTools.keys())
m_methodBox->addItem(type);
m_methodBox->setFocus();
hLayout->addWidget(m_methodBox);
mainLayout->addLayout(hLayout);
return page;
}
QWizardPage *CreateWizard::createResultPage()
{
auto *page = new QWizardPage;
page->setTitle(i18n("Checksum Results"));
auto *mainLayout = new QVBoxLayout;
page->setLayout(mainLayout);
m_hashesTreeWidget = new KrTreeWidget(this);
m_hashesTreeWidget->setAllColumnsShowFocus(true);
m_hashesTreeWidget->setHeaderLabels(QStringList() << i18n("Hash") << i18n("File"));
mainLayout->addWidget(m_hashesTreeWidget);
m_errorLabel = new QLabel(i18n("Errors received:"));
mainLayout->addWidget(m_errorLabel);
m_errorListWidget = new KrListWidget;
mainLayout->addWidget(m_errorListWidget);
m_onePerFileBox = new QCheckBox(i18n("Save one checksum file for each source file"));
m_onePerFileBox->setChecked(false);
mainLayout->addWidget(m_onePerFileBox);
return page;
}
void CreateWizard::onIntroPage() { button(QWizard::NextButton)->show(); }
void CreateWizard::onProgressPage()
{
// first, get all files (recurse in directories) - async
stopListFiles = false; // QFuture cannot cancel QtConcurrent::run
connect(this, &CreateWizard::finished, this, [=]() { stopListFiles = true; });
QFuture listFuture = QtConcurrent::run(listFiles, m_path, m_fileNames);
m_listFilesWatcher.setFuture(listFuture);
}
void CreateWizard::createChecksums() {
const QString type = m_methodBox->currentText();
if (!checkExists(type)) {
button(QWizard::BackButton)->show();
return;
}
const QStringList &allFiles = m_listFilesWatcher.result();
if (allFiles.isEmpty()) {
KMessageBox::error(this, i18n("No files found"));
button(QWizard::BackButton)->show();
return;
}
runProcess(type, allFiles);
// set suggested filename
m_suggestedFilePath = QDir(m_path).filePath(
(m_fileNames.count() > 1 ? "checksum." : (m_fileNames[0] + '.')) + type);
}
void CreateWizard::onResultPage()
{
// hash tools display errors into stderr, so we'll use that to determine the result of the job
const QStringList outputLines = m_process->stdOutput();
const QStringList errorLines = m_process->errOutput();
bool errors = !errorLines.isEmpty();
bool successes = !outputLines.isEmpty();
QWizardPage *page = currentPage();
page->setPixmap(QWizard::LogoPixmap,
Icon(errors || !successes ? "dialog-error" : "dialog-information").pixmap(32));
page->setSubTitle(errors || !successes ?
i18n("Errors were detected while creating the checksums") :
i18n("Checksums were created successfully"));
m_hashesTreeWidget->clear();
m_hashesTreeWidget->setVisible(successes);
if (successes) {
for (const QString& line : outputLines)
addChecksumLine(m_hashesTreeWidget, line);
//m_hashesTreeWidget->sortItems(1, Qt::AscendingOrder);
}
m_errorLabel->setVisible(errors);
m_errorListWidget->setVisible(errors);
m_errorListWidget->clear();
m_errorListWidget->addItems(errorLines);
m_onePerFileBox->setEnabled(outputLines.size() > 1);
button(QWizard::FinishButton)->setEnabled(successes);
}
bool CreateWizard::savePerFile()
{
const QString type = m_suggestedFilePath.mid(m_suggestedFilePath.lastIndexOf('.'));
krApp->startWaiting(i18n("Saving checksum files..."), 0);
for (const QString& line : m_process->stdOutput()) {
const QString filename = line.mid(line.indexOf(' ') + 2) + type;
if (!saveChecksumFile(QStringList() << line, filename)) {
KMessageBox::error(this, i18n("Errors occurred while saving multiple checksums. Stopping"));
krApp->stopWait();
return false;
}
}
krApp->stopWait();
return true;
}
bool CreateWizard::saveChecksumFile(const QStringList &data, const QString &filename)
{
QString filePath = filename.isEmpty() ? m_suggestedFilePath : filename;
if (filename.isEmpty() || QFile::exists(filePath)) {
filePath = QFileDialog::getSaveFileName(this, QString(), filePath);
if (filePath.isEmpty())
return false; // user pressed cancel
}
QFile file(filePath);
if (file.open(QIODevice::WriteOnly)) {
QTextStream stream(&file);
for (const QString& line : data)
stream << line << "\n";
file.close();
}
if (file.error() != QFile::NoError) {
KMessageBox::detailedError(this, i18n("Error saving file %1", filePath), file.errorString());
return false;
}
return true;
}
void CreateWizard::accept()
{
const bool saved = m_onePerFileBox->isChecked() ? savePerFile() :
saveChecksumFile(m_process->stdOutput());
if (saved)
QWizard::accept();
}
// ------------- Verify Wizard
VerifyWizard::VerifyWizard(const QString &path, const QString &inputFile) : ChecksumWizard(path)
{
m_checksumFile = isSupported(inputFile) ? inputFile : path;
m_introId = addPage(createIntroPage()); // m_checksumFile must already be set
m_progressId = addPage(createProgressPage(i18n("Verifying Checksums")));
m_resultId = addPage(createResultPage());
}
void VerifyWizard::slotChecksumPathChanged(const QString &path)
{
m_hashesTreeWidget->clear();
button(QWizard::NextButton)->setEnabled(false);
if (!isSupported(path))
return;
m_checksumFile = path;
// parse and display checksum file content; only for the user, parsed values are not used
m_hashesTreeWidget->clear();
QFile file(m_checksumFile);
if (file.open(QFile::ReadOnly)) {
QTextStream inStream(&file);
while (!inStream.atEnd()) {
addChecksumLine(m_hashesTreeWidget, file.readLine());
}
}
file.close();
button(QWizard::NextButton)->setEnabled(true);
}
QWizardPage *VerifyWizard::createIntroPage()
{
auto *page = new QWizardPage;
page->setTitle(i18n("Verify Checksum File"));
page->setPixmap(QWizard::LogoPixmap,
Icon("document-edit-verify").pixmap(32));
page->setSubTitle(i18n("About to verify the following checksum file"));
auto *mainLayout = new QVBoxLayout;
page->setLayout(mainLayout);
// checksum file
auto *hLayout = new QHBoxLayout;
QLabel *checksumFileLabel = new QLabel(i18n("Checksum file:"));
hLayout->addWidget(checksumFileLabel);
auto *checksumFileReq = new KUrlRequester;
QString typesFilter;
for (const QString& ext: m_checksumTools.keys())
typesFilter += ("*." + ext + ' ');
checksumFileReq->setFilter(typesFilter);
checksumFileReq->setText(m_checksumFile);
checksumFileReq->setFocus();
connect(checksumFileReq, &KUrlRequester::textChanged, this,
&VerifyWizard::slotChecksumPathChanged);
hLayout->addWidget(checksumFileReq);
mainLayout->addLayout(hLayout);
// content of checksum file
m_hashesTreeWidget = new KrTreeWidget(page);
m_hashesTreeWidget->setAllColumnsShowFocus(true);
m_hashesTreeWidget->setHeaderLabels(QStringList() << i18n("Hash") << i18n("File"));
mainLayout->addWidget(m_hashesTreeWidget);
return page;
}
QWizardPage *VerifyWizard::createResultPage()
{
auto *page = new QWizardPage;
page->setTitle(i18n("Verify Result"));
auto *mainLayout = new QVBoxLayout;
page->setLayout(mainLayout);
m_outputLabel = new QLabel(i18n("Result output:"));
mainLayout->addWidget(m_outputLabel);
m_outputListWidget = new KrListWidget;
mainLayout->addWidget(m_outputListWidget);
return page;
}
void VerifyWizard::onIntroPage()
{
// cannot do this in constructor: NextButton->hide() is overridden
slotChecksumPathChanged(m_checksumFile);
}
void VerifyWizard::onProgressPage()
{
// verify checksum file...
const QString extension = QFileInfo(m_checksumFile).suffix();
if (!checkExists(extension)) {
button(QWizard::BackButton)->show();
return;
}
runProcess(extension, QStringList() << "--strict" << "-c" << m_checksumFile);
}
void VerifyWizard::onResultPage()
{
// better not only trust error output
const bool errors = m_process->exitCode() != 0 || !m_process->errOutput().isEmpty();
QWizardPage *page = currentPage();
page->setPixmap(QWizard::LogoPixmap,
Icon(errors ? "dialog-error" : "dialog-information").pixmap(32));
page->setSubTitle(errors ? i18n("Errors were detected while verifying the checksums") :
i18n("Checksums were verified successfully"));
// print everything, errors first
m_outputListWidget->clear();
m_outputListWidget->addItems(m_process->errOutput() + m_process->stdOutput());
button(QWizard::FinishButton)->setEnabled(!errors);
}
bool VerifyWizard::isSupported(const QString &path)
{
const QFileInfo fileInfo(path);
return fileInfo.isFile() && m_checksumTools.keys().contains(fileInfo.suffix());
}
} // NAMESPACE CHECKSUM_
diff --git a/krusader/DiskUsage/diskusage.cpp b/krusader/DiskUsage/diskusage.cpp
index 7269d0cc..50c4b03f 100644
--- a/krusader/DiskUsage/diskusage.cpp
+++ b/krusader/DiskUsage/diskusage.cpp
@@ -1,1135 +1,1135 @@
/*****************************************************************************
* Copyright (C) 2004 Csaba Karai *
* Copyright (C) 2004-2019 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#include "diskusage.h"
// QtCore
#include
#include
#include
#include
#include
#include
// QtGui
#include
#include
#include
#include
#include
// QtWidgets
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "dufilelight.h"
#include "dulines.h"
#include "dulistview.h"
#include "filelightParts/Config.h"
#include "../FileSystem/fileitem.h"
#include "../FileSystem/filesystemprovider.h"
#include "../FileSystem/krpermhandler.h"
#include "../Panel/krpanel.h"
#include "../Panel/panelfunc.h"
#include "../defaults.h"
#include "../krglobal.h"
#include "../filelisticon.h"
#include "../compat.h"
// these are the values that will exist in the menu
#define DELETE_ID 90
#define EXCLUDE_ID 91
#define PARENT_DIR_ID 92
#define NEW_SEARCH_ID 93
#define REFRESH_ID 94
#define STEP_INTO_ID 95
#define INCLUDE_ALL_ID 96
#define VIEW_POPUP_ID 97
#define LINES_VIEW_ID 98
#define DETAILED_VIEW_ID 99
#define FILELIGHT_VIEW_ID 100
#define NEXT_VIEW_ID 101
#define PREVIOUS_VIEW_ID 102
#define ADDITIONAL_POPUP_ID 103
#define MAX_FILENUM 100
LoaderWidget::LoaderWidget(QWidget *parent) : QScrollArea(parent), cancelled(false)
{
QPalette palette = viewport()->palette();
palette.setColor(viewport()->backgroundRole(), Qt::white);
viewport()->setPalette(palette);
widget = new QWidget(parent);
auto *loaderLayout = new QGridLayout(widget);
loaderLayout->setSpacing(0);
loaderLayout->setContentsMargins(0, 0, 0, 0);
QFrame *loaderBox = new QFrame(widget);
loaderBox->setFrameShape(QFrame::Box);
loaderBox->setFrameShadow(QFrame::Sunken);
loaderBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
loaderBox->setFrameStyle(QFrame::Panel + QFrame::Raised);
loaderBox->setLineWidth(2);
auto *synchGrid = new QGridLayout(loaderBox);
synchGrid->setSpacing(6);
synchGrid->setContentsMargins(11, 11, 11, 11);
QLabel *titleLabel = new QLabel(i18n("Loading Usage Information"), loaderBox);
titleLabel->setAlignment(Qt::AlignHCenter);
synchGrid->addWidget(titleLabel, 0, 0, 1, 2);
QLabel *filesLabel = new QLabel(i18n("Files:"), loaderBox);
filesLabel->setFrameShape(QLabel::StyledPanel);
filesLabel->setFrameShadow(QLabel::Sunken);
synchGrid->addWidget(filesLabel, 1, 0);
- QLabel *directoriesLabel = new QLabel(i18n("Directories:"), loaderBox);
+ QLabel *directoriesLabel = new QLabel(i18n("Folders:"), loaderBox);
directoriesLabel->setFrameShape(QLabel::StyledPanel);
directoriesLabel->setFrameShadow(QLabel::Sunken);
synchGrid->addWidget(directoriesLabel, 2, 0);
QLabel *totalSizeLabel = new QLabel(i18n("Total Size:"), loaderBox);
totalSizeLabel->setFrameShape(QLabel::StyledPanel);
totalSizeLabel->setFrameShadow(QLabel::Sunken);
synchGrid->addWidget(totalSizeLabel, 3, 0);
files = new QLabel(loaderBox);
files->setFrameShape(QLabel::StyledPanel);
files->setFrameShadow(QLabel::Sunken);
files->setAlignment(Qt::AlignRight);
synchGrid->addWidget(files, 1, 1);
directories = new QLabel(loaderBox);
directories->setFrameShape(QLabel::StyledPanel);
directories->setFrameShadow(QLabel::Sunken);
directories->setAlignment(Qt::AlignRight);
synchGrid->addWidget(directories, 2, 1);
totalSize = new QLabel(loaderBox);
totalSize->setFrameShape(QLabel::StyledPanel);
totalSize->setFrameShadow(QLabel::Sunken);
totalSize->setAlignment(Qt::AlignRight);
synchGrid->addWidget(totalSize, 3, 1);
int width;
searchedDirectory = new KSqueezedTextLabel(loaderBox);
searchedDirectory->setFrameShape(QLabel::StyledPanel);
searchedDirectory->setFrameShadow(QLabel::Sunken);
searchedDirectory->setMinimumWidth(width = QFontMetrics(searchedDirectory->font()).QFONTMETRICS_WIDTH("W") * 30);
searchedDirectory->setMaximumWidth(width);
synchGrid->addWidget(searchedDirectory, 4, 0, 1, 2);
QFrame *line = new QFrame(loaderBox);
line->setFrameStyle(QFrame::HLine | QFrame::Sunken);
synchGrid->addWidget(line, 5, 0, 1, 2);
QWidget *hboxWidget = new QWidget(loaderBox);
auto * hbox = new QHBoxLayout(hboxWidget);
auto* spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
hbox->addItem(spacer);
auto *cancelButton = new QPushButton(hboxWidget);
KStandardGuiItem::assign(cancelButton, KStandardGuiItem::Cancel);
hbox->addWidget(cancelButton);
synchGrid->addWidget(hboxWidget, 6, 1);
loaderLayout->addWidget(loaderBox, 0, 0);
setWidget(widget);
setAlignment(Qt::AlignCenter);
connect(cancelButton, &QPushButton::clicked, this, &LoaderWidget::slotCancelled);
}
void LoaderWidget::init()
{
cancelled = false;
}
void LoaderWidget::setCurrentURL(const QUrl &url)
{
searchedDirectory->setText(FileSystem::ensureTrailingSlash(url).toDisplayString(QUrl::PreferLocalFile));
}
void LoaderWidget::setValues(int fileNum, int dirNum, KIO::filesize_t total)
{
files->setText(QString("%1").arg(fileNum));
directories->setText(QString("%1").arg(dirNum));
totalSize->setText(QString("%1").arg(KRpermHandler::parseSize(total).trimmed()));
}
void LoaderWidget::slotCancelled()
{
cancelled = true;
}
DiskUsage::DiskUsage(QString confGroup, QWidget *parent) : QStackedWidget(parent),
currentDirectory(nullptr), root(nullptr), configGroup(std::move(confGroup)), loading(false),
abortLoading(false), clearAfterAbort(false), deleting(false), searchFileSystem(nullptr)
{
listView = new DUListView(this);
lineView = new DULines(this);
filelightView = new DUFilelight(this);
loaderView = new LoaderWidget(this);
addWidget(listView);
addWidget(lineView);
addWidget(filelightView);
addWidget(loaderView);
setView(VIEW_LINES);
Filelight::Config::read();
connect(&loadingTimer, &QTimer::timeout, this, &DiskUsage::slotLoadDirectory);
}
DiskUsage::~DiskUsage()
{
if (listView) // don't remove these lines. The module will crash at exit if removed
delete listView;
if (lineView)
delete lineView;
if (filelightView)
delete filelightView;
if (root)
delete root;
QHashIterator< File *, Properties * > lit(propertyMap);
while (lit.hasNext())
delete lit.next().value();
}
void DiskUsage::load(const QUrl &baseDir)
{
fileNum = dirNum = 0;
currentSize = 0;
emit status(i18n("Loading the disk usage information..."));
clear();
baseURL = baseDir.adjusted(QUrl::StripTrailingSlash);
root = new Directory(baseURL.fileName(), baseDir.toDisplayString(QUrl::PreferLocalFile));
directoryStack.clear();
parentStack.clear();
directoryStack.push("");
parentStack.push(root);
if (searchFileSystem) {
delete searchFileSystem;
searchFileSystem = nullptr;
}
searchFileSystem = FileSystemProvider::instance().getFilesystem(baseDir);
if (searchFileSystem == nullptr) {
qWarning() << "could not get filesystem for directory=" << baseDir;
loading = abortLoading = clearAfterAbort = false;
emit loadFinished(false);
return;
}
currentFileItem = nullptr;
if (!loading) {
viewBeforeLoad = activeView;
setView(VIEW_LOADER);
}
loading = true;
loaderView->init();
loaderView->setCurrentURL(baseURL);
loaderView->setValues(fileNum, dirNum, currentSize);
loadingTimer.setSingleShot(true);
loadingTimer.start(0);
}
void DiskUsage::slotLoadDirectory()
{
if ((currentFileItem == nullptr && directoryStack.isEmpty()) || loaderView->wasCancelled() || abortLoading) {
if (searchFileSystem)
delete searchFileSystem;
searchFileSystem = nullptr;
currentFileItem = nullptr;
setView(viewBeforeLoad);
if (clearAfterAbort)
clear();
else {
calculateSizes();
changeDirectory(root);
}
emit loadFinished(!(loaderView->wasCancelled() || abortLoading));
loading = abortLoading = clearAfterAbort = false;
} else if (loading) {
for (int counter = 0; counter != MAX_FILENUM; counter ++) {
if (currentFileItem == nullptr) {
if (directoryStack.isEmpty())
break;
dirToCheck = directoryStack.pop();
currentParent = parentStack.pop();
contentMap.insert(dirToCheck, currentParent);
QUrl url = baseURL;
if (!dirToCheck.isEmpty()) {
url = url.adjusted(QUrl::StripTrailingSlash);
url.setPath(url.path() + '/' + (dirToCheck));
}
#ifdef BSD
if (url.isLocalFile() && url.path().left(7) == "/procfs")
break;
#else
if (url.isLocalFile() && url.path().left(5) == "/proc")
break;
#endif
loaderView->setCurrentURL(url);
if (!searchFileSystem->scanDir(url))
break;
fileItems = searchFileSystem->fileItems();
dirNum++;
currentFileItem = fileItems.isEmpty() ? 0 : fileItems.takeFirst();
} else {
fileNum++;
File *newItem = nullptr;
QString mime = currentFileItem->getMime(); // fast == not using mimetype magic
if (currentFileItem->isDir() && !currentFileItem->isSymLink()) {
newItem = new Directory(currentParent, currentFileItem->getName(), dirToCheck, currentFileItem->getSize(),
currentFileItem->getMode(), currentFileItem->getOwner(), currentFileItem->getGroup(),
currentFileItem->getPerm(), currentFileItem->getModificationTime(), currentFileItem->isSymLink(),
mime);
directoryStack.push((dirToCheck.isEmpty() ? "" : dirToCheck + '/') + currentFileItem->getName());
parentStack.push(dynamic_cast(newItem));
} else {
newItem = new File(currentParent, currentFileItem->getName(), dirToCheck, currentFileItem->getSize(),
currentFileItem->getMode(), currentFileItem->getOwner(), currentFileItem->getGroup(),
currentFileItem->getPerm(), currentFileItem->getModificationTime(), currentFileItem->isSymLink(),
mime);
currentSize += currentFileItem->getSize();
}
currentParent->append(newItem);
currentFileItem = fileItems.isEmpty() ? 0 : fileItems.takeFirst();
}
}
loaderView->setValues(fileNum, dirNum, currentSize);
loadingTimer.setSingleShot(true);
loadingTimer.start(0);
}
}
void DiskUsage::stopLoad()
{
abortLoading = true;
}
void DiskUsage::close()
{
if (loading) {
abortLoading = true;
clearAfterAbort = true;
}
}
void DiskUsage::dirUp()
{
if (currentDirectory != nullptr) {
if (currentDirectory->parent() != nullptr)
changeDirectory((Directory *)(currentDirectory->parent()));
else {
QUrl up = KIO::upUrl(baseURL);
if (KMessageBox::questionYesNo(this, i18n("Stepping into the parent folder requires "
"loading the content of the \"%1\" URL. Do you wish "
"to continue?", up.toDisplayString(QUrl::PreferLocalFile)),
i18n("Krusader::DiskUsage"), KStandardGuiItem::yes(),
KStandardGuiItem::no(), "DiskUsageLoadParentDir"
) == KMessageBox::Yes)
load(up);
}
}
}
Directory * DiskUsage::getDirectory(QString dir)
{
while (dir.endsWith('/'))
dir.truncate(dir.length() - 1);
if (dir.isEmpty())
return root;
if (contentMap.find(dir) == contentMap.end())
return nullptr;
return contentMap[ dir ];
}
File * DiskUsage::getFile(const QString& path)
{
if (path.isEmpty())
return root;
QString dir = path;
int ndx = path.lastIndexOf('/');
QString file = path.mid(ndx + 1);
if (ndx == -1)
dir = "";
else
dir.truncate(ndx);
Directory *dirEntry = getDirectory(dir);
if (dirEntry == nullptr)
return nullptr;
for (Iterator it = dirEntry->iterator(); it != dirEntry->end(); ++it)
if ((*it)->name() == file)
return *it;
return nullptr;
}
void DiskUsage::clear()
{
baseURL = QUrl();
emit clearing();
QHashIterator< File *, Properties * > lit(propertyMap);
while (lit.hasNext())
delete lit.next().value();
propertyMap.clear();
contentMap.clear();
if (root)
delete root;
root = currentDirectory = nullptr;
}
int DiskUsage::calculateSizes(Directory *dirEntry, bool emitSig, int depth)
{
int changeNr = 0;
if (dirEntry == nullptr)
dirEntry = root;
KIO::filesize_t own = 0, total = 0;
for (Iterator it = dirEntry->iterator(); it != dirEntry->end(); ++it) {
File * item = *it;
if (!item->isExcluded()) {
if (item->isDir())
changeNr += calculateSizes(dynamic_cast(item), emitSig, depth + 1);
else
own += item->size();
total += item->size();
}
}
KIO::filesize_t oldOwn = dirEntry->ownSize(), oldTotal = dirEntry->size();
dirEntry->setSizes(total, own);
if (dirEntry == currentDirectory)
currentSize = total;
if (emitSig && (own != oldOwn || total != oldTotal)) {
emit changed(dirEntry);
changeNr++;
}
if (depth == 0 && changeNr != 0)
emit changeFinished();
return changeNr;
}
int DiskUsage::exclude(File *file, bool calcPercents, int depth)
{
int changeNr = 0;
if (!file->isExcluded()) {
file->exclude(true);
emit changed(file);
changeNr++;
if (file->isDir()) {
auto *dir = dynamic_cast(file);
for (Iterator it = dir->iterator(); it != dir->end(); ++it)
changeNr += exclude(*it, false, depth + 1);
}
}
if (calcPercents) {
calculateSizes(root, true);
calculatePercents(true);
createStatus();
}
if (depth == 0 && changeNr != 0)
emit changeFinished();
return changeNr;
}
int DiskUsage::include(Directory *dir, int depth)
{
int changeNr = 0;
if (dir == nullptr)
return 0;
for (Iterator it = dir->iterator(); it != dir->end(); ++it) {
File *item = *it;
if (item->isDir())
changeNr += include(dynamic_cast(item), depth + 1);
if (item->isExcluded()) {
item->exclude(false);
emit changed(item);
changeNr++;
}
}
if (depth == 0 && changeNr != 0)
emit changeFinished();
return changeNr;
}
void DiskUsage::includeAll()
{
include(root);
calculateSizes(root, true);
calculatePercents(true);
createStatus();
}
int DiskUsage::del(File *file, bool calcPercents, int depth)
{
int deleteNr = 0;
if (file == root)
return 0;
KConfigGroup gg(krConfig, "General");
bool trash = gg.readEntry("Move To Trash", _MoveToTrash);
QUrl url = QUrl::fromLocalFile(file->fullPath());
if (calcPercents) {
// now ask the user if he want to delete:
KConfigGroup ga(krConfig, "Advanced");
if (ga.readEntry("Confirm Delete", _ConfirmDelete)) {
QString s;
KGuiItem b;
if (trash && url.isLocalFile()) {
s = i18nc("singularOnly", "Do you really want to move this item to the trash?");
b = KGuiItem(i18n("&Trash"));
} else {
s = i18nc("singularOnly", "Do you really want to delete this item?");
b = KStandardGuiItem::del();
}
QStringList name;
name.append(file->fullPath());
// show message
// note: i'm using continue and not yes/no because the yes/no has cancel as default button
if (KMessageBox::warningContinueCancelList(krMainWindow, s, name, i18n("Warning"), b) != KMessageBox::Continue)
return 0;
}
emit status(i18n("Deleting %1...", file->name()));
}
if (file == currentDirectory)
dirUp();
if (file->isDir()) {
auto *dir = dynamic_cast(file);
Iterator it;
while ((it = dir->iterator()) != dir->end())
deleteNr += del(*it, false, depth + 1);
QString path;
for (const Directory *d = dynamic_cast(file); d != root && d && d->parent() != nullptr; d = d->parent()) {
if (!path.isEmpty())
path = '/' + path;
path = d->name() + path;
}
contentMap.remove(path);
}
emit deleted(file);
deleteNr++;
KIO::Job *job;
if (trash) {
job = KIO::trash(url);
} else {
job = KIO::del(QUrl::fromLocalFile(file->fullPath()), KIO::HideProgressInfo);
}
deleting = true; // during qApp->processEvent strange things can occur
grabMouse(); // that's why we disable the mouse and keyboard events
grabKeyboard();
job->exec();
delete job;
releaseMouse();
releaseKeyboard();
deleting = false;
((Directory *)(file->parent()))->remove(file);
delete file;
if (depth == 0)
createStatus();
if (calcPercents) {
calculateSizes(root, true);
calculatePercents(true);
createStatus();
emit enteringDirectory(currentDirectory);
}
if (depth == 0 && deleteNr != 0)
emit deleteFinished();
return deleteNr;
}
void * DiskUsage::getProperty(File *item, const QString& key)
{
QHash< File *, Properties *>::iterator itr = propertyMap.find(item);
if (itr == propertyMap.end())
return nullptr;
QHash::iterator it = (*itr)->find(key);
if (it == (*itr)->end())
return nullptr;
return it.value();
}
void DiskUsage::addProperty(File *item, const QString& key, void * prop)
{
Properties *props;
QHash< File *, Properties *>::iterator itr = propertyMap.find(item);
if (itr == propertyMap.end()) {
props = new Properties();
propertyMap.insert(item, props);
} else
props = *itr;
props->insert(key, prop);
}
void DiskUsage::removeProperty(File *item, const QString& key)
{
QHash< File *, Properties *>::iterator itr = propertyMap.find(item);
if (itr == propertyMap.end())
return;
(*itr)->remove(key);
if ((*itr)->count() == 0)
propertyMap.remove(item);
}
void DiskUsage::createStatus()
{
Directory *dirEntry = currentDirectory;
if (dirEntry == nullptr)
return;
QUrl url = baseURL;
if (dirEntry != root) {
url = url.adjusted(QUrl::StripTrailingSlash);
url.setPath(url.path() + '/' + (dirEntry->directory()));
}
emit status(i18n("Current folder:%1, Total size:%2, Own size:%3",
url.toDisplayString(QUrl::PreferLocalFile | QUrl::StripTrailingSlash),
' ' + KRpermHandler::parseSize(dirEntry->size()),
' ' + KRpermHandler::parseSize(dirEntry->ownSize())));
}
void DiskUsage::changeDirectory(Directory *dir)
{
currentDirectory = dir;
currentSize = dir->size();
calculatePercents(true, dir);
createStatus();
emit enteringDirectory(dir);
}
Directory* DiskUsage::getCurrentDir()
{
return currentDirectory;
}
void DiskUsage::rightClickMenu(const QPoint & pos, File *fileItem, QMenu *addPopup, const QString& addPopupName)
{
QMenu popup(this);
popup.setTitle(i18n("Disk Usage"));
QHash actionHash;
if (fileItem != nullptr) {
QAction * actDelete = popup.addAction(i18n("Delete"));
actionHash[ actDelete ] = DELETE_ID;
actDelete->setShortcut(Qt::Key_Delete);
QAction * actExclude = popup.addAction(i18n("Exclude"));
actionHash[ actExclude ] = EXCLUDE_ID;
actExclude->setShortcut(Qt::CTRL + Qt::Key_E);
popup.addSeparator();
}
QAction * myAct = popup.addAction(i18n("Up one folder"));
actionHash[ myAct ] = PARENT_DIR_ID;
myAct->setShortcut(Qt::SHIFT + Qt::Key_Up);
myAct = popup.addAction(i18n("New search"));
actionHash[ myAct ] = NEW_SEARCH_ID;
myAct->setShortcut(Qt::CTRL + Qt::Key_N);
myAct = popup.addAction(i18n("Refresh"));
actionHash[ myAct ] = REFRESH_ID;
myAct->setShortcut(Qt::CTRL + Qt::Key_R);
myAct = popup.addAction(i18n("Include all"));
actionHash[ myAct ] = INCLUDE_ALL_ID;
myAct->setShortcut(Qt::CTRL + Qt::Key_I);
myAct = popup.addAction(i18n("Step into"));
actionHash[ myAct ] = STEP_INTO_ID;
myAct->setShortcut(Qt::SHIFT + Qt::Key_Down);
popup.addSeparator();
if (addPopup != nullptr) {
QAction * menu = popup.addMenu(addPopup);
menu->setText(addPopupName);
}
QMenu viewPopup;
myAct = viewPopup.addAction(i18n("Lines"));
actionHash[ myAct ] = LINES_VIEW_ID;
myAct->setShortcut(Qt::CTRL + Qt::Key_L);
myAct = viewPopup.addAction(i18n("Detailed"));
actionHash[ myAct ] = DETAILED_VIEW_ID;
myAct->setShortcut(Qt::CTRL + Qt::Key_D);
myAct = viewPopup.addAction(i18n("Filelight"));
actionHash[ myAct ] = FILELIGHT_VIEW_ID;
myAct->setShortcut(Qt::CTRL + Qt::Key_F);
viewPopup.addSeparator();
myAct = viewPopup.addAction(i18n("Next"));
actionHash[ myAct ] = NEXT_VIEW_ID;
myAct->setShortcut(Qt::SHIFT + Qt::Key_Right);
myAct = viewPopup.addAction(i18n("Previous"));
actionHash[ myAct ] = PREVIOUS_VIEW_ID;
myAct->setShortcut(Qt::SHIFT + Qt::Key_Left);
QAction * menu = popup.addMenu(&viewPopup);
menu->setText(i18n("View"));
QAction * res = popup.exec(pos);
if (actionHash.contains(res))
executeAction(actionHash[ res ], fileItem);
}
void DiskUsage::executeAction(int action, File * fileItem)
{
// check out the user's option
switch (action) {
case DELETE_ID:
if (fileItem)
del(fileItem);
break;
case EXCLUDE_ID:
if (fileItem)
exclude(fileItem);
break;
case PARENT_DIR_ID:
dirUp();
break;
case NEW_SEARCH_ID:
emit newSearch();
break;
case REFRESH_ID:
load(baseURL);
break;
case INCLUDE_ALL_ID:
includeAll();
break;
case STEP_INTO_ID: {
QString uri;
if (fileItem && fileItem->isDir())
uri = fileItem->fullPath();
else
uri = currentDirectory->fullPath();
ACTIVE_FUNC->openUrl(QUrl::fromLocalFile(uri));
}
break;
case LINES_VIEW_ID:
setView(VIEW_LINES);
break;
case DETAILED_VIEW_ID:
setView(VIEW_DETAILED);
break;
case FILELIGHT_VIEW_ID:
setView(VIEW_FILELIGHT);
break;
case NEXT_VIEW_ID:
setView((activeView + 1) % 3);
break;
case PREVIOUS_VIEW_ID:
setView((activeView + 2) % 3);
break;
}
// currentWidget()->setFocus();
}
void DiskUsage::keyPressEvent(QKeyEvent *e)
{
if (activeView != VIEW_LOADER) {
switch (e->key()) {
case Qt::Key_E:
if (e->modifiers() == Qt::ControlModifier) {
executeAction(EXCLUDE_ID, getCurrentFile());
return;
}
break;
case Qt::Key_D:
if (e->modifiers() == Qt::ControlModifier) {
executeAction(DETAILED_VIEW_ID);
return;
}
break;
case Qt::Key_F:
if (e->modifiers() == Qt::ControlModifier) {
executeAction(FILELIGHT_VIEW_ID);
return;
}
break;
case Qt::Key_I:
if (e->modifiers() == Qt::ControlModifier) {
executeAction(INCLUDE_ALL_ID);
return;
}
break;
case Qt::Key_L:
if (e->modifiers() == Qt::ControlModifier) {
executeAction(LINES_VIEW_ID);
return;
}
break;
case Qt::Key_N:
if (e->modifiers() == Qt::ControlModifier) {
executeAction(NEW_SEARCH_ID);
return;
}
break;
case Qt::Key_R:
if (e->modifiers() == Qt::ControlModifier) {
executeAction(REFRESH_ID);
return;
}
break;
case Qt::Key_Up:
if (e->modifiers() == Qt::ShiftModifier) {
executeAction(PARENT_DIR_ID);
return;
}
break;
case Qt::Key_Down:
if (e->modifiers() == Qt::ShiftModifier) {
executeAction(STEP_INTO_ID);
return;
}
break;
case Qt::Key_Left:
if (e->modifiers() == Qt::ShiftModifier) {
executeAction(PREVIOUS_VIEW_ID);
return;
}
break;
case Qt::Key_Right:
if (e->modifiers() == Qt::ShiftModifier) {
executeAction(NEXT_VIEW_ID);
return;
}
break;
case Qt::Key_Delete:
if (!e->modifiers()) {
executeAction(DELETE_ID, getCurrentFile());
return;
}
break;
case Qt::Key_Plus:
if (activeView == VIEW_FILELIGHT) {
filelightView->zoomIn();
return;
}
break;
case Qt::Key_Minus:
if (activeView == VIEW_FILELIGHT) {
filelightView->zoomOut();
return;
}
break;
}
}
QStackedWidget::keyPressEvent(e);
}
QPixmap DiskUsage::getIcon(const QString& mime)
{
QPixmap icon;
if (!QPixmapCache::find(mime, &icon)) {
// get the icon.
if (mime == "Broken Link !") // FIXME: this doesn't work anymore - the reported mimetype for a broken link is now "unknown"
icon = FileListIcon("file-broken").pixmap();
else {
QMimeDatabase db;
QMimeType mt = db.mimeTypeForName(mime);
if (mt.isValid())
icon = FileListIcon(mt.iconName()).pixmap();
else
icon = FileListIcon("file-broken").pixmap();
}
// insert it into the cache
QPixmapCache::insert(mime, icon);
}
return icon;
}
int DiskUsage::calculatePercents(bool emitSig, Directory *dirEntry, int depth)
{
int changeNr = 0;
if (dirEntry == nullptr)
dirEntry = root;
for (Iterator it = dirEntry->iterator(); it != dirEntry->end(); ++it) {
File *item = *it;
if (!item->isExcluded()) {
int newPerc;
if (dirEntry->size() == 0 && item->size() == 0)
newPerc = 0;
else if (dirEntry->size() == 0)
newPerc = -1;
else
newPerc = (int)((double)item->size() / (double)currentSize * 10000. + 0.5);
int oldPerc = item->intPercent();
item->setPercent(newPerc);
if (emitSig && newPerc != oldPerc) {
emit changed(item);
changeNr++;
}
if (item->isDir())
changeNr += calculatePercents(emitSig, dynamic_cast(item), depth + 1);
}
}
if (depth == 0 && changeNr != 0)
emit changeFinished();
return changeNr;
}
QString DiskUsage::getToolTip(File *item)
{
QMimeDatabase db;
QMimeType mt = db.mimeTypeForName(item->mime());
QString mime;
if (mt.isValid())
mime = mt.comment();
time_t tma = item->time();
struct tm* t = localtime((time_t *) & tma);
QDateTime tmp(QDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday), QTime(t->tm_hour, t->tm_min));
QString date = QLocale().toString(tmp, QLocale::ShortFormat);
QString str = "
" + i18n("Name:") + "
" + item->name() + "
" +
"
" + i18n("Type:") + "
" + mime + "
" +
"
" + i18n("Size:") + "
" + KRpermHandler::parseSize(item->size()) + "
";
if (item->isDir())
str += "
" + i18n("Own size:") + "
" + KRpermHandler::parseSize(item->ownSize()) + "
";
str += "
" + i18n("Last modified:") + "
" + date + "
" +
"
" + i18n("Permissions:") + "
" + item->perm() + "
" +
"
" + i18n("Owner:") + "
" + item->owner() + " - " + item->group() + "
" +
"
";
str.replace(' ', " ");
return str;
}
void DiskUsage::setView(int view)
{
switch (view) {
case VIEW_LINES:
setCurrentWidget(lineView);
break;
case VIEW_DETAILED:
setCurrentWidget(listView);
break;
case VIEW_FILELIGHT:
setCurrentWidget(filelightView);
break;
case VIEW_LOADER:
setCurrentWidget(loaderView);
break;
}
// currentWidget()->setFocus();
emit viewChanged(activeView = view);
}
File * DiskUsage::getCurrentFile()
{
File * file = nullptr;
switch (activeView) {
case VIEW_LINES:
file = lineView->getCurrentFile();
break;
case VIEW_DETAILED:
file = listView->getCurrentFile();
break;
case VIEW_FILELIGHT:
file = filelightView->getCurrentFile();
break;
}
return file;
}
bool DiskUsage::event(QEvent * e)
{
if (deleting) { // if we are deleting, disable the mouse and
switch (e->type()) { // keyboard events
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
case QEvent::MouseMove:
case QEvent::KeyPress:
case QEvent::KeyRelease:
return true;
default:
break;
}
}
if (e->type() == QEvent::ShortcutOverride) {
auto* ke = dynamic_cast( e);
if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::KeypadModifier) {
switch (ke->key()) {
case Qt::Key_Delete:
case Qt::Key_Plus:
case Qt::Key_Minus:
ke->accept();
break;
}
} else if (ke->modifiers() == Qt::ShiftModifier) {
switch (ke->key()) {
case Qt::Key_Left:
case Qt::Key_Right:
case Qt::Key_Up:
case Qt::Key_Down:
ke->accept();
break;
}
} else if (ke->modifiers() & Qt::ControlModifier) {
switch (ke->key()) {
case Qt::Key_D:
case Qt::Key_E:
case Qt::Key_F:
case Qt::Key_I:
case Qt::Key_L:
case Qt::Key_N:
case Qt::Key_R:
ke->accept();
break;
}
}
}
return QStackedWidget::event(e);
}
diff --git a/krusader/Filter/generalfilter.cpp b/krusader/Filter/generalfilter.cpp
index d15199b7..0bb3131d 100644
--- a/krusader/Filter/generalfilter.cpp
+++ b/krusader/Filter/generalfilter.cpp
@@ -1,666 +1,666 @@
/*****************************************************************************
* Copyright (C) 2003 Shie Erlich *
* Copyright (C) 2003 Rafi Yanai *
* Copyright (C) 2003 Csaba Karai *
* Copyright (C) 2004-2019 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#include "generalfilter.h"
#include "filtertabs.h"
#include "../krglobal.h"
#include "../krservices.h"
#include "../FileSystem/filesystem.h"
// QtWidgets
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef struct {
const char *description;
const char *regExp;
int cursorAdjustment;
} term;
static const term items[] = {
{ I18N_NOOP("Any Character"), ".", 0 },
{ I18N_NOOP("Start of Line"), "^", 0 },
{ I18N_NOOP("End of Line"), "$", 0 },
{ I18N_NOOP("Set of Characters"), "[]", -1 },
{ I18N_NOOP("Repeats, Zero or More Times"), "*", 0 },
{ I18N_NOOP("Repeats, One or More Times"), "+", 0 },
{ I18N_NOOP("Optional"), "?", 0 },
{ I18N_NOOP("Escape"), "\\", 0 },
{ I18N_NOOP("TAB"), "\\t", 0 },
{ I18N_NOOP("Newline"), "\\n", 0 },
{ I18N_NOOP("Carriage Return"), "\\r", 0 },
{ I18N_NOOP("White Space"), "\\s", 0 },
{ I18N_NOOP("Digit"), "\\d", 0 },
};
class RegExpAction : public QAction
{
public:
RegExpAction(QObject *parent, const QString &text, const QString ®Exp, int cursor)
: QAction(text, parent), mText(text), mRegExp(regExp), mCursor(cursor) {
}
QString text() const {
return mText;
}
QString regExp() const {
return mRegExp;
}
int cursor() const {
return mCursor;
}
private:
QString mText;
QString mRegExp;
int mCursor;
};
GeneralFilter::GeneralFilter(FilterTabs *tabs, int properties, QWidget *parent,
QStringList extraOptions) :
QWidget(parent),
profileManager(nullptr), fltTabs(tabs)
{
auto *filterLayout = new QGridLayout(this);
filterLayout->setSpacing(6);
filterLayout->setContentsMargins(11, 11, 11, 11);
this->properties = properties;
// Options for name filtering
auto *nameGroup = new QGroupBox(this);
nameGroup->setTitle(i18n("File Name"));
auto *nameGroupLayout = new QGridLayout(nameGroup);
nameGroupLayout->setAlignment(Qt::AlignTop);
nameGroupLayout->setSpacing(6);
nameGroupLayout->setContentsMargins(11, 11, 11, 11);
searchForCase = new QCheckBox(nameGroup);
searchForCase->setText(i18n("&Case sensitive"));
searchForCase->setChecked(false);
nameGroupLayout->addWidget(searchForCase, 1, 2);
QLabel *searchForLabel = new QLabel(nameGroup);
searchForLabel->setText(i18n("Search &for:"));
nameGroupLayout->addWidget(searchForLabel, 0, 0);
searchFor = new KrHistoryComboBox(false, nameGroup/*, "searchFor"*/);
QSizePolicy searchForPolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
searchForPolicy.setHeightForWidth(searchFor->sizePolicy().hasHeightForWidth());
searchFor->setSizePolicy(searchForPolicy);
searchFor->setEditable(true);
searchFor->setDuplicatesEnabled(false);
searchFor->setMaxCount(25);
searchFor->setMinimumContentsLength(10);
searchForLabel->setBuddy(searchFor);
nameGroupLayout->addWidget(searchFor, 0, 1, 1, 2);
const QString s = "
"
+ i18n("
The filename filtering criteria is defined here.
"
"
You can make use of wildcards. Multiple patterns are separated by "
"space (means logical OR) and patterns are excluded from the search "
"using the pipe symbol.
"
"
If the pattern is ended with a slash (*pattern*/), "
"that means that pattern relates to recursive search of folders."
"
pattern - means to search those files/folders "
"that name is pattern, recursive search goes through all "
"subfolders independently of the value of pattern
"
"
pattern/ - means to search all files/folders, but "
"recursive search goes through/excludes the folders that name is "
"pattern
"
"
It is allowed to use quotation marks for names that contain space."
" Filter \"Program Files\" searches out those "
"files/folders that name is Program Files.
"
"
Examples:
"
"
*.o
"
"
*.h *.c\?\?
"
"
*.cpp *.h | *.moc.cpp
"
"
* | .svn/ .git/
"
"Note: the search term 'text' is equivalent to "
"'*text*'.
");
searchFor->setWhatsThis(s);
searchForLabel->setWhatsThis(s);
QLabel *searchType = new QLabel(nameGroup);
searchType->setText(i18n("&Of type:"));
nameGroupLayout->addWidget(searchType, 1, 0);
ofType = new KComboBox(false, nameGroup);
ofType->setObjectName("ofType");
QSizePolicy ofTypePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
ofTypePolicy.setHeightForWidth(ofType->sizePolicy().hasHeightForWidth());
ofType->setSizePolicy(ofTypePolicy);
ofType->setEditable(false);
searchType->setBuddy(ofType);
ofType->addItem(i18n("All Files"));
ofType->addItem(i18n("Archives"));
ofType->addItem(i18n("Folders"));
ofType->addItem(i18n("Image Files"));
ofType->addItem(i18n("Text Files"));
ofType->addItem(i18n("Video Files"));
ofType->addItem(i18n("Audio Files"));
connect(ofType, QOverload::of(&KComboBox::currentIndexChanged), this, &GeneralFilter::slotDisable);
nameGroupLayout->addWidget(ofType, 1, 1);
filterLayout->addWidget(nameGroup, 0, 0);
middleLayout = new QHBoxLayout();
middleLayout->setSpacing(6);
middleLayout->setContentsMargins(0, 0, 0, 0);
if (properties & FilterTabs::HasProfileHandler) {
// The profile handler
auto *profileHandler = new QGroupBox(this);
profileHandler->setTitle(i18n("&Profile handler"));
auto *profileLayout = new QGridLayout(profileHandler);
profileLayout->setAlignment(Qt::AlignTop);
profileLayout->setSpacing(6);
profileLayout->setContentsMargins(11, 11, 11, 11);
profileListBox = new KrListWidget(profileHandler);
profileLayout->addWidget(profileListBox, 0, 0, 4, 1);
profileAddBtn = new QPushButton(profileHandler);
KStandardGuiItem::assign(profileAddBtn, KStandardGuiItem::Add);
profileLayout->addWidget(profileAddBtn, 0, 1);
profileLoadBtn = new QPushButton(i18n("&Load"), profileHandler);
profileLoadBtn->setEnabled(false);
profileLayout->addWidget(profileLoadBtn, 1, 1);
profileOverwriteBtn = new QPushButton(profileHandler);
profileOverwriteBtn->setEnabled(false);
KStandardGuiItem::assign(profileOverwriteBtn, KStandardGuiItem::Overwrite);
profileLayout->addWidget(profileOverwriteBtn, 2, 1);
profileRemoveBtn = new QPushButton(profileHandler);
profileRemoveBtn->setEnabled(false);
KStandardGuiItem::assign(profileRemoveBtn, KStandardGuiItem::Remove);
profileLayout->addWidget(profileRemoveBtn, 3, 1);
profileManager = new ProfileManager("SelectionProfile", this);
profileManager->hide();
middleLayout->addWidget(profileHandler);
refreshProfileListBox();
}
if (properties & FilterTabs::HasSearchIn) {
// Options for search in
QGroupBox *searchGroupBox = new QGroupBox(i18n("Searc&h in"), this);
auto *searchLayout = new QGridLayout(searchGroupBox);
searchLayout->setAlignment(Qt::AlignTop);
searchLayout->setSpacing(6);
searchLayout->setContentsMargins(11, 11, 11, 11);
searchIn = new KURLListRequester(KURLListRequester::RequestDirs, searchGroupBox);
searchLayout->addWidget(searchIn, 0, 0);
connect(searchIn, &KURLListRequester::changed, this, &GeneralFilter::slotDisable);
middleLayout->addWidget(searchGroupBox);
}
if (properties & FilterTabs::HasDontSearchIn) {
// Options for don't search in
QGroupBox *searchGroupBox = new QGroupBox(i18n("&Do not search in"), this);
auto *searchLayout = new QGridLayout(searchGroupBox);
searchLayout->setAlignment(Qt::AlignTop);
searchLayout->setSpacing(6);
searchLayout->setContentsMargins(11, 11, 11, 11);
dontSearchIn = new KURLListRequester(KURLListRequester::RequestDirs, searchGroupBox);
searchLayout->addWidget(dontSearchIn, 0, 0, 1, 2);
if (properties & FilterTabs::HasRecurseOptions) {
KConfigGroup group(krConfig, "Search");
useExcludeFolderNames = createExcludeCheckBox(group);
searchLayout->addWidget(useExcludeFolderNames, 1, 0, 1, 1);
excludeFolderNames = createExcludeComboBox(group);
searchLayout->addWidget(excludeFolderNames, 1, 1, 1, 1);
if (!useExcludeFolderNames->isChecked()) {
excludeFolderNames->setDisabled(true);
}
connect(useExcludeFolderNames, &QCheckBox::toggled, excludeFolderNames, &KHistoryComboBox::setEnabled);
}
middleLayout->addWidget(searchGroupBox);
}
filterLayout->addLayout(middleLayout, 1, 0);
// Options for containing text
auto *containsGroup = new QGroupBox(this);
containsGroup->setTitle(i18n("Containing text"));
auto *containsLayout = new QGridLayout(containsGroup);
containsLayout->setAlignment(Qt::AlignTop);
containsLayout->setSpacing(6);
containsLayout->setContentsMargins(11, 11, 11, 11);
auto *containsTextLayout = new QHBoxLayout();
containsTextLayout->setSpacing(6);
containsTextLayout->setContentsMargins(0, 0, 0, 0);
containsLabel = new QLabel(containsGroup);
QSizePolicy containsLabelPolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
containsLabelPolicy.setHeightForWidth(containsLabel->sizePolicy().hasHeightForWidth());
containsLabel->setSizePolicy(containsLabelPolicy);
containsLabel->setText(i18n("&Text:"));
containsTextLayout->addWidget(containsLabel);
containsText = new KHistoryComboBox(false, containsGroup/*, "containsText"*/);
QSizePolicy containsTextPolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
containsTextPolicy.setHeightForWidth(containsText->sizePolicy().hasHeightForWidth());
containsText->setSizePolicy(containsTextPolicy);
containsText->setDuplicatesEnabled(false);
containsText->setMaxCount(25);
containsText->setMinimumContentsLength(10);
containsTextLayout->addWidget(containsText);
containsLabel->setBuddy(containsText);
containsRegExp = new QToolButton(containsGroup);
containsRegExp->setPopupMode(QToolButton::MenuButtonPopup);
containsRegExp->setCheckable(true);
containsRegExp->setText(i18n("RegExp"));
// Populate the popup menu.
auto *patterns = new QMenu(containsRegExp);
for (int i = 0; (unsigned)i < sizeof(items) / sizeof(items[0]); i++) {
patterns->addAction(new RegExpAction(patterns, i18n(items[i].description),
items[i].regExp, items[i].cursorAdjustment));
}
connect(containsRegExp, &QToolButton::toggled, this, &GeneralFilter::slotDisable);
connect(containsRegExp, &QToolButton::triggered, this, &GeneralFilter::slotRegExpTriggered);
containsRegExp->setMenu(patterns);
patterns->setEnabled(false);
containsTextLayout->addWidget(containsRegExp);
containsLayout->addLayout(containsTextLayout, 0, 0);
auto *containsCbsLayout = new QHBoxLayout();
containsCbsLayout->setSpacing(6);
containsCbsLayout->setContentsMargins(0, 0, 0, 0);
encLabel = new QLabel(i18n("Encoding:"), containsGroup);
containsCbsLayout->addWidget(encLabel);
contentEncoding = new KComboBox(containsGroup);
contentEncoding->setEditable(false);
contentEncoding->addItem(i18nc("Default encoding", "Default"));
contentEncoding->addItems(KCharsets::charsets()->descriptiveEncodingNames());
containsCbsLayout->addWidget(contentEncoding);
auto* cbSpacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
containsCbsLayout->addItem(cbSpacer);
containsWholeWord = new QCheckBox(containsGroup);
QSizePolicy containsWholeWordPolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
containsWholeWordPolicy.setHeightForWidth(containsWholeWord->sizePolicy().hasHeightForWidth());
containsWholeWord->setSizePolicy(containsWholeWordPolicy);
containsWholeWord->setText(i18n("&Match whole word only"));
containsWholeWord->setChecked(false);
containsCbsLayout->addWidget(containsWholeWord);
containsTextCase = new QCheckBox(containsGroup);
QSizePolicy containsTextCasePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
containsTextCasePolicy.setHeightForWidth(containsTextCase->sizePolicy().hasHeightForWidth());
containsTextCase->setSizePolicy(containsTextCasePolicy);
containsTextCase->setText(i18n("Cas&e sensitive"));
containsTextCase->setChecked(true);
containsCbsLayout->addWidget(containsTextCase);
containsLayout->addLayout(containsCbsLayout, 1, 0);
filterLayout->addWidget(containsGroup, 2, 0);
auto *recurseLayout = new QHBoxLayout();
recurseLayout->setSpacing(6);
recurseLayout->setContentsMargins(0, 0, 0, 0);
auto* recurseSpacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
recurseLayout->addItem(recurseSpacer);
if (properties & FilterTabs::HasRecurseOptions) {
// Options for recursive searching
searchInDirs = new QCheckBox(this);
searchInDirs->setText(i18n("Search in s&ub folders"));
searchInDirs->setChecked(true);
recurseLayout->addWidget(searchInDirs);
searchInArchives = new QCheckBox(this);
searchInArchives->setText(i18n("Search in arch&ives"));
recurseLayout->addWidget(searchInArchives);
followLinks = new QCheckBox(this);
followLinks->setText(i18n("Follow &links"));
recurseLayout->addWidget(followLinks);
}
filterLayout->addLayout(recurseLayout, 3, 0);
for(int i = 0; i < extraOptions.length(); i++) {
auto *option = new QCheckBox(this);
option->setText(extraOptions[i]);
recurseLayout->addWidget(option);
this->extraOptions.insert(extraOptions[i], option);
}
// Connection table
if (properties & FilterTabs::HasProfileHandler) {
connect(profileAddBtn, &QPushButton::clicked, this, &GeneralFilter::slotAddBtnClicked);
connect(profileLoadBtn, &QPushButton::clicked, this, &GeneralFilter::slotLoadBtnClicked);
connect(profileOverwriteBtn, &QPushButton::clicked, this, &GeneralFilter::slotOverwriteBtnClicked);
connect(profileRemoveBtn, &QPushButton::clicked, this, &GeneralFilter::slotRemoveBtnClicked);
connect(profileListBox, &KrListWidget::itemDoubleClicked, this, &GeneralFilter::slotProfileDoubleClicked);
connect(profileManager, &ProfileManager::loadFromProfile, fltTabs, &FilterTabs::loadFromProfile);
connect(profileManager, &ProfileManager::saveToProfile, fltTabs, &FilterTabs::saveToProfile);
}
connect(searchFor, QOverload::of(&KHistoryComboBox::activated), searchFor, &KHistoryComboBox::addToHistory);
connect(containsText, QOverload::of(&KHistoryComboBox::activated), containsText, &KHistoryComboBox::addToHistory);
// load the completion and history lists
// ==> search for
KConfigGroup group(krConfig, "Search");
QStringList list = group.readEntry("SearchFor Completion", QStringList());
searchFor->completionObject()->setItems(list);
list = group.readEntry("SearchFor History", QStringList());
searchFor->setHistoryItems(list);
// ==> grep
list = group.readEntry("ContainsText Completion", QStringList());
containsText->completionObject()->setItems(list);
list = group.readEntry("ContainsText History", QStringList());
containsText->setHistoryItems(list);
setTabOrder(searchFor, containsText); // search for -> content
setTabOrder(containsText, searchType); // content -> search type
slotDisable();
}
GeneralFilter::~GeneralFilter()
{
// save the history combos
// ==> search for
QStringList list = searchFor->completionObject()->items();
KConfigGroup group(krConfig, "Search");
group.writeEntry("SearchFor Completion", list);
list = searchFor->historyItems();
group.writeEntry("SearchFor History", list);
// ==> grep text
list = containsText->completionObject()->items();
group.writeEntry("ContainsText Completion", list);
list = containsText->historyItems();
group.writeEntry("ContainsText History", list);
if ((properties & FilterTabs::HasDontSearchIn) && (properties & FilterTabs::HasRecurseOptions)) {
list = excludeFolderNames->historyItems();
group.writeEntry("ExcludeFolderNamesHistory", list);
group.writeEntry("ExcludeFolderNames", excludeFolderNames->currentText());
group.writeEntry("ExcludeFolderNamesUse", static_cast(useExcludeFolderNames->checkState()));
}
krConfig->sync();
}
bool GeneralFilter::isExtraOptionChecked(const QString& name)
{
QCheckBox *option = extraOptions[name];
return option ? option->isChecked() : false;
}
void GeneralFilter::checkExtraOption(const QString& name, bool check)
{
QCheckBox *option = extraOptions[name];
if (option)
option->setChecked(check);
}
void GeneralFilter::queryAccepted()
{
searchFor->addToHistory(searchFor->currentText());
containsText->addToHistory(containsText->currentText());
if ((properties & FilterTabs::HasDontSearchIn) && (properties & FilterTabs::HasRecurseOptions)) {
excludeFolderNames->addToHistory(excludeFolderNames->currentText());
}
}
void GeneralFilter::refreshProfileListBox()
{
profileListBox->clear();
profileListBox->addItems(ProfileManager::availableProfiles("SelectionProfile"));
if (profileListBox->count() != 0) {
profileLoadBtn->setEnabled(true);
profileOverwriteBtn->setEnabled(true);
profileRemoveBtn->setEnabled(true);
} else {
profileLoadBtn->setEnabled(false);
profileOverwriteBtn->setEnabled(false);
profileRemoveBtn->setEnabled(false);
}
}
QCheckBox *GeneralFilter::createExcludeCheckBox(const KConfigGroup &group)
{
auto *excludeCheckBox = new QCheckBox(this);
excludeCheckBox->setText(i18n("Exclude Folder Names"));
- excludeCheckBox->setToolTip(i18n("Filters out specified directory names from the results."));
+ excludeCheckBox->setToolTip(i18n("Filters out specified folder names from the results."));
excludeCheckBox->setChecked(static_cast(group.readEntry("ExcludeFolderNamesUse", 0)));
return excludeCheckBox;
}
KHistoryComboBox *GeneralFilter::createExcludeComboBox(const KConfigGroup &group)
{
auto *excludeComboBox = new KHistoryComboBox(false, this);
QSizePolicy excludeFolderNamesPolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
excludeFolderNamesPolicy.setHeightForWidth(excludeComboBox->sizePolicy().hasHeightForWidth());
excludeComboBox->setSizePolicy(excludeFolderNamesPolicy);
excludeComboBox->setEditable(true);
excludeComboBox->setDuplicatesEnabled(false);
excludeComboBox->setMaxCount(25);
excludeComboBox->setMinimumContentsLength(10);
excludeComboBox->lineEdit()->setPlaceholderText(i18n("Enter space-separated folder names"));
excludeComboBox->lineEdit()->setWhatsThis(
i18n("You can insert names with escaped spaces or quoted.\nExample: .git \"target "
"build\" build\\ krusader"));
excludeComboBox->setHistoryItems(group.readEntry("ExcludeFolderNamesHistory", QStringList()));
excludeComboBox->setEditText(group.readEntry("ExcludeFolderNames", ""));
return excludeComboBox;
}
void GeneralFilter::slotAddBtnClicked()
{
profileManager->newProfile(searchFor->currentText().simplified());
refreshProfileListBox();
}
void GeneralFilter::slotOverwriteBtnClicked()
{
QListWidgetItem *item = profileListBox->currentItem();
if (item != nullptr)
profileManager->overwriteProfile(item->text());
}
void GeneralFilter::slotRemoveBtnClicked()
{
QListWidgetItem *item = profileListBox->currentItem();
if (item != nullptr) {
profileManager->deleteProfile(item->text());
refreshProfileListBox();
}
}
void GeneralFilter::slotProfileDoubleClicked(QListWidgetItem *item)
{
if (item != nullptr) {
QString profileName = item->text();
profileManager->loadProfile(profileName);
fltTabs->close(true);
}
}
void GeneralFilter::slotLoadBtnClicked()
{
QListWidgetItem *item = profileListBox->currentItem();
if (item != nullptr)
profileManager->loadProfile(item->text());
}
void GeneralFilter::slotDisable()
{
bool state = containsRegExp->isChecked();
bool global = ofType->currentText() != i18n("Folders");
bool remoteOnly = false;
if (properties & FilterTabs::HasSearchIn) {
QList urlList = searchIn->urlList();
remoteOnly = urlList.count() != 0;
foreach(const QUrl &url, urlList)
if (url.scheme() == "file")
remoteOnly = false;
}
containsWholeWord->setEnabled(!state && global);
containsRegExp->menu()->setEnabled(state && global);
encLabel->setEnabled(global);
contentEncoding->setEnabled(global);
containsTextCase->setEnabled(global);
containsRegExp->setEnabled(global);
if (properties & FilterTabs::HasRecurseOptions)
searchInArchives->setEnabled(global && !remoteOnly);
containsLabel->setEnabled(global);
containsText->setEnabled(global);
}
void GeneralFilter::slotRegExpTriggered(QAction * act)
{
if (act == nullptr)
return;
auto *regAct = dynamic_cast(act);
if (regAct == nullptr)
return;
containsText->lineEdit()->insert(regAct->regExp());
containsText->lineEdit()->setCursorPosition(containsText->lineEdit()->cursorPosition() + regAct->cursor());
containsText->lineEdit()->setFocus();
}
bool GeneralFilter::getSettings(FilterSettings &s)
{
// check that we have (at least) what to search, and where to search in
if (searchFor->currentText().simplified().isEmpty()) {
KMessageBox::error(this , i18n("No search criteria entered."));
searchFor->setFocus();
return false;
}
s.searchFor = searchFor->currentText().trimmed();
s.searchForCase = searchForCase->isChecked();
if (ofType->currentText() != i18n("All Files"))
s.mimeType = ofType->currentText();
if (containsText->isEnabled()) {
s.containsText = containsText->currentText();
s.containsTextCase = containsTextCase->isChecked();
s.containsWholeWord = containsWholeWord->isChecked();
s.containsRegExp = containsRegExp->isChecked();
}
if (contentEncoding->currentIndex() != 0)
s.contentEncoding =
KCharsets::charsets()->encodingForName(contentEncoding->currentText());
if (properties & FilterTabs::HasRecurseOptions) {
s.recursive = searchInDirs->isChecked();
s.searchInArchives = searchInArchives->isChecked();
s.followLinks = followLinks->isChecked();
}
if (properties & FilterTabs::HasSearchIn) {
s.searchIn = searchIn->urlList();
if (s.searchIn.isEmpty()) { // we need a place to search in
KMessageBox::error(this , i18n("Please specify a location to search in."));
searchIn->lineEdit()->setFocus();
return false;
}
}
if (properties & FilterTabs::HasDontSearchIn) {
s.dontSearchIn = dontSearchIn->urlList();
if (properties & FilterTabs::HasRecurseOptions) {
if (useExcludeFolderNames->isChecked()) {
s.excludeFolderNames = KShell::splitArgs(excludeFolderNames->currentText());
} else {
s.excludeFolderNames = QStringList();
}
}
}
return true;
}
void GeneralFilter::applySettings(const FilterSettings &s)
{
searchFor->setEditText(s.searchFor);
searchForCase->setChecked(s.searchForCase);
setComboBoxValue(ofType, s.mimeType);
containsText->setEditText(s.containsText);
containsTextCase->setChecked(s.containsTextCase);
containsWholeWord->setChecked(s.containsWholeWord);
containsRegExp->setChecked(s.containsRegExp);
setComboBoxValue(contentEncoding,
KCharsets::charsets()->descriptionForEncoding(s.contentEncoding));
if (properties & FilterTabs::HasRecurseOptions) {
searchInDirs->setChecked(s.recursive);
searchInArchives->setChecked(s.searchInArchives);
followLinks->setChecked(s.followLinks);
}
if (properties & FilterTabs::HasSearchIn) {
searchIn->lineEdit()->clear();
searchIn->listBox()->clear();
searchIn->listBox()->addItems(KrServices::toStringList(s.searchIn));
}
if (properties & FilterTabs::HasDontSearchIn) {
dontSearchIn->lineEdit()->clear();
dontSearchIn->listBox()->clear();
dontSearchIn->listBox()->addItems(KrServices::toStringList(s.dontSearchIn));
}
}
diff --git a/krusader/Konfigurator/kgpanel.cpp b/krusader/Konfigurator/kgpanel.cpp
index a5738dcf..12d90382 100644
--- a/krusader/Konfigurator/kgpanel.cpp
+++ b/krusader/Konfigurator/kgpanel.cpp
@@ -1,745 +1,745 @@
/*****************************************************************************
* Copyright (C) 2010 Jan Lepper *
* Copyright (C) 2010-2019 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#include "kgpanel.h"
#include "../defaults.h"
#include "../Dialogs/krdialogs.h"
// QtGui
#include
// QtWidgets
#include
#include
#include
#include
#include
#include
#include
#include "../GUI/krtreewidget.h"
#include "../Panel/krsearchbar.h"
#include "../Panel/PanelView/krselectionmode.h"
#include "../Panel/PanelView/krview.h"
#include "../Panel/PanelView/krviewfactory.h"
#include "../Panel/krlayoutfactory.h"
enum {
PAGE_GENERAL = 0,
PAGE_VIEW,
PAGE_PANELTOOLBAR,
PAGE_MOUSE,
PAGE_MEDIA_MENU,
PAGE_LAYOUT
};
KgPanel::KgPanel(bool first, QWidget* parent) :
KonfiguratorPage(first, parent)
{
tabWidget = new QTabWidget(this);
setWidget(tabWidget);
setWidgetResizable(true);
setupGeneralTab();
setupPanelTab();
setupButtonsTab();
setupMouseModeTab();
setupMediaMenuTab();
setupLayoutTab();
}
// ---------------------------------------------------------------------------------------
// ---------------------------- General TAB ----------------------------------------------
// ---------------------------------------------------------------------------------------
void KgPanel::setupGeneralTab()
{
auto *scrollArea = new QScrollArea(tabWidget);
QWidget *tab = new QWidget(scrollArea);
scrollArea->setFrameStyle(QFrame::NoFrame);
scrollArea->setWidget(tab);
scrollArea->setWidgetResizable(true);
tabWidget->addTab(scrollArea, i18n("General"));
auto *layout = new QVBoxLayout(tab);
layout->setSpacing(6);
layout->setContentsMargins(11, 11, 11, 11);
// ---------------------------------------------------------------------------------------
// ------------------------------- Navigator bar -------------------------------------
// ---------------------------------------------------------------------------------------
QGroupBox *groupBox = createFrame(i18n("Navigator bar"), tab);
QGridLayout *gridLayout = createGridLayout(groupBox);
KONFIGURATOR_CHECKBOX_PARAM navigatorbar_settings[] = {
// cfg_class, cfg_name, default, text, restart, tooltip
{"Look&Feel", "Navigator Edit Mode", false, i18n("Edit Mode by default"), true, i18n("Show editable path in Navigator bar by default") },
{"Look&Feel", "Navigator Full Path", false, i18n("Show full path by default"), true, i18n("Always show full path in Navigator bar by default.") },
};
KonfiguratorCheckBoxGroup* cbs = createCheckBoxGroup(2, 0, navigatorbar_settings, 2 /*count*/, groupBox, PAGE_GENERAL);
gridLayout->addWidget(cbs, 0, 0);
layout->addWidget(groupBox);
// ---------------------------------------------------------------------------------------
// ------------------------------- Operation ---------------------------------------------
// ---------------------------------------------------------------------------------------
groupBox = createFrame(i18n("Operation"), tab);
gridLayout = createGridLayout(groupBox);
KONFIGURATOR_CHECKBOX_PARAM operation_settings[] = { // cfg_class, cfg_name, default, text, restart, tooltip
{"Look&Feel", "Mark Dirs", _MarkDirs, i18n("Autoselect folders"), false, i18n("When matching the select criteria, not only files will be selected, but also folders.") },
{"Look&Feel", "Rename Selects Extension", true, i18n("Rename selects extension"), false, i18n("When renaming a file, the whole text is selected. If you want Total-Commander like renaming of just the name, without extension, uncheck this option.") },
{"Look&Feel", "UnselectBeforeOperation", _UnselectBeforeOperation, i18n("Unselect files before copy/move"), false, i18n("Unselect files, which are to be copied/moved, before the operation starts.") },
{"Look&Feel", "FilterDialogRemembersSettings", _FilterDialogRemembersSettings, i18n("Filter dialog remembers settings"), false, i18n("The filter dialog is opened with the last filter settings that where applied to the panel.") },
};
cbs = createCheckBoxGroup(2, 0, operation_settings, 4 /*count*/, groupBox, PAGE_GENERAL);
gridLayout->addWidget(cbs, 0, 0);
layout->addWidget(groupBox);
// ---------------------------------------------------------------------------------------
// ------------------------------ Tabs ---------------------------------------------------
// ---------------------------------------------------------------------------------------
groupBox = createFrame(i18n("Tabs"), tab);
gridLayout = createGridLayout(groupBox);
KONFIGURATOR_CHECKBOX_PARAM tabbar_settings[] = { // cfg_class cfg_name default text restart tooltip
{"Look&Feel", "Fullpath Tab Names", _FullPathTabNames, i18n("Use full path tab names"), true , i18n("Display the full path in the folder tabs. By default only the last part of the path is displayed.") },
{"Look&Feel", "Show Tab Buttons", true, i18n("Show new/close tab buttons"), true , i18n("Show the new/close tab buttons.") },
};
cbs = createCheckBoxGroup(2, 0, tabbar_settings, 2 /*count*/, groupBox, PAGE_GENERAL);
gridLayout->addWidget(cbs, 0, 0, 1, 2);
// ----------------- Tab Bar position ----------------------------------
auto *hbox = new QHBoxLayout();
hbox->addWidget(new QLabel(i18n("Tab Bar position:"), groupBox));
KONFIGURATOR_NAME_VALUE_PAIR positions[] = {
{ i18n("Top"), "top" },
{ i18n("Bottom"), "bottom" }
};
KonfiguratorComboBox *cmb = createComboBox("Look&Feel", "Tab Bar Position",
"bottom", positions, 2, groupBox, true, false, PAGE_GENERAL);
hbox->addWidget(cmb);
gridLayout->addLayout(hbox, 1, 0, Qt::AlignLeft);
// ----------------- Show Tab bar ----------------------------------
KonfiguratorCheckBox *checkBox = createCheckBox("Look&Feel", "Show Tab Bar On Single Tab", true,
i18n("Show Tab Bar on single tab"), groupBox,
true, i18n("Show the tab bar with only one tab."));
gridLayout->addWidget(checkBox, 1, 1, Qt::AlignLeft);
layout->addWidget(groupBox);
// ---------------------------------------------------------------------------------------
// ----------------------------- Search bar --------------------------------------------
// ---------------------------------------------------------------------------------------
groupBox = createFrame(i18n("Search bar"), tab);
gridLayout = createGridLayout(groupBox);
KONFIGURATOR_CHECKBOX_PARAM quicksearch[] = { // cfg_class cfg_name default text restart tooltip
{"Look&Feel", "New Style Quicksearch", _NewStyleQuicksearch, i18n("Start by typing"), false, i18n("Open search bar and start searching by typing in panel.") },
{"Look&Feel", "Case Sensitive Quicksearch", _CaseSensitiveQuicksearch, i18n("Case sensitive"), false, i18n("Search must match case.") },
{"Look&Feel", "Up/Down Cancels Quicksearch", false, i18n("Up/Down cancels search"), false, i18n("Pressing the Up/Down buttons closes the search bar (only in search mode).") },
- {"Look&Feel", "Navigation with Right Arrow Quicksearch", _NavigationWithRightArrowQuicksearch, i18n("Directory navigation with Right Arrow"), false, i18n("Pressing the Right button enters directory if no search text editing intention is captured.") },
+ {"Look&Feel", "Navigation with Right Arrow Quicksearch", _NavigationWithRightArrowQuicksearch, i18n("Folder navigation with Right Arrow"), false, i18n("Pressing the Right button enters folder if no search text editing intention is captured.") },
};
cbs = createCheckBoxGroup(2, 0, quicksearch, 4 /*count*/, groupBox, PAGE_GENERAL);
gridLayout->addWidget(cbs, 0, 0, 1, -1);
// -------------- Search bar position -----------------------
hbox = new QHBoxLayout();
hbox->addWidget(new QLabel(i18n("Position:"), groupBox));
cmb = createComboBox("Look&Feel", "Quicksearch Position",
"bottom", positions, 2, groupBox, true, false, PAGE_GENERAL);
hbox->addWidget(cmb);
hbox->addWidget(createSpacer(groupBox));
gridLayout->addLayout(hbox, 1, 0);
// -------------- Default search mode -----------------------
hbox = new QHBoxLayout();
hbox->addWidget(new QLabel(i18n("Default mode:"), groupBox));
KONFIGURATOR_NAME_VALUE_PAIR modes[] = {
{i18n("Search"), QString::number(KrSearchBar::MODE_SEARCH)},
{i18n("Select"), QString::number(KrSearchBar::MODE_SELECT)},
{i18n("Filter"), QString::number(KrSearchBar::MODE_FILTER)}};
cmb = createComboBox("Look&Feel", "Default Search Mode",
QString::number(KrSearchBar::MODE_SEARCH), modes, 3, groupBox, true, false,
PAGE_GENERAL);
cmb->setToolTip(i18n("Set the default mode on first usage"));
hbox->addWidget(cmb);
hbox->addWidget(createSpacer(groupBox));
gridLayout->addLayout(hbox, 1, 1);
layout->addWidget(groupBox);
// --------------------------------------------------------------------------------------------
// ------------------------------- Bookmark search settings ----------------------------------
// --------------------------------------------------------------------------------------------
groupBox = createFrame(i18n("Bookmark Search"), tab);
gridLayout = createGridLayout(groupBox);
KONFIGURATOR_CHECKBOX_PARAM bookmarkSearchSettings[] =
{
{"Look&Feel", "Always show search bar", true, i18n("Always show search bar"), false, i18n("Make bookmark search bar always visible") },
{"Look&Feel", "Search in special items", false, i18n("Search in special items"), false, i18n("Bookmark search is also applied to special items in bookmark menu like Trash, Popular URLs, Jump Back, etc.") },
};
KonfiguratorCheckBoxGroup *bookmarkSearchSettingsGroup = createCheckBoxGroup(2, 0, bookmarkSearchSettings,
2 /*count*/, groupBox, PAGE_GENERAL);
gridLayout->addWidget(bookmarkSearchSettingsGroup, 1, 0, 1, 2);
layout->addWidget(groupBox);
// --------------------------------------------------------------------------------------------
// ------------------------------- Status/Totalsbar settings ----------------------------------
// --------------------------------------------------------------------------------------------
groupBox = createFrame(i18n("Status/Totalsbar"), tab);
gridLayout = createGridLayout(groupBox);
KONFIGURATOR_CHECKBOX_PARAM barSettings[] =
{
{"Look&Feel", "Show Size In Bytes", false, i18n("Show size in bytes too"), true, i18n("Show size in bytes too") },
{"Look&Feel", "ShowSpaceInformation", true, i18n("Show space information"), true, i18n("Show free/total space on the device") },
};
KonfiguratorCheckBoxGroup *barSett = createCheckBoxGroup(2, 0, barSettings,
2 /*count*/, groupBox, PAGE_GENERAL);
gridLayout->addWidget(barSett, 1, 0, 1, 2);
layout->addWidget(groupBox);
}
// --------------------------------------------------------------------------------------------
// ------------------------------------ Layout Tab --------------------------------------------
// --------------------------------------------------------------------------------------------
void KgPanel::setupLayoutTab()
{
auto *scrollArea = new QScrollArea(tabWidget);
QWidget *tab = new QWidget(scrollArea);
scrollArea->setFrameStyle(QFrame::NoFrame);
scrollArea->setWidget(tab);
scrollArea->setWidgetResizable(true);
tabWidget->addTab(scrollArea, i18n("Layout"));
QGridLayout *grid = createGridLayout(tab);
QStringList layoutNames = KrLayoutFactory::layoutNames();
int numLayouts = layoutNames.count();
grid->addWidget(createSpacer(tab), 0, 2);
QLabel *l = new QLabel(i18n("Layout:"), tab);
l->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
grid->addWidget(l, 0, 0);
auto *layouts = new KONFIGURATOR_NAME_VALUE_PAIR[numLayouts];
for (int i = 0; i != numLayouts; i++) {
layouts[ i ].text = KrLayoutFactory::layoutDescription(layoutNames[i]);
layouts[ i ].value = layoutNames[i];
}
KonfiguratorComboBox *cmb = createComboBox("PanelLayout", "Layout", "default",
layouts, numLayouts, tab, true, false, PAGE_LAYOUT);
grid->addWidget(cmb, 0, 1);
delete [] layouts;
l = new QLabel(i18n("Frame Color:"), tab);
l->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
grid->addWidget(l, 1, 0);
KONFIGURATOR_NAME_VALUE_PAIR frameColor[] = {
{ i18nc("Frame color", "Defined by Layout"), "default" },
{ i18nc("Frame color", "None"), "none" },
{ i18nc("Frame color", "Statusbar"), "Statusbar" }
};
cmb = createComboBox("PanelLayout", "FrameColor",
"default", frameColor, 3, tab, true, false, PAGE_LAYOUT);
grid->addWidget(cmb, 1, 1);
l = new QLabel(i18n("Frame Shape:"), tab);
l->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
grid->addWidget(l, 2, 0);
KONFIGURATOR_NAME_VALUE_PAIR frameShape[] = {
{ i18nc("Frame shape", "Defined by Layout"), "default" },
{ i18nc("Frame shape", "None"), "NoFrame" },
{ i18nc("Frame shape", "Box"), "Box" },
{ i18nc("Frame shape", "Panel"), "Panel" },
};
cmb = createComboBox("PanelLayout", "FrameShape",
"default", frameShape, 4, tab, true, false, PAGE_LAYOUT);
grid->addWidget(cmb, 2, 1);
l = new QLabel(i18n("Frame Shadow:"), tab);
l->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
grid->addWidget(l, 3, 0);
KONFIGURATOR_NAME_VALUE_PAIR frameShadow[] = {
{ i18nc("Frame shadow", "Defined by Layout"), "default" },
{ i18nc("Frame shadow", "None"), "Plain" },
{ i18nc("Frame shadow", "Raised"), "Raised" },
{ i18nc("Frame shadow", "Sunken"), "Sunken" },
};
cmb = createComboBox("PanelLayout", "FrameShadow",
"default", frameShadow, 4, tab, true, false, PAGE_LAYOUT);
grid->addWidget(cmb, 3, 1);
}
void KgPanel::setupView(KrViewInstance *instance, QWidget *parent)
{
QGridLayout *grid = createGridLayout(parent);
// -------------------- Filelist icon size ----------------------------------
auto *hbox = new QHBoxLayout();
hbox->addWidget(new QLabel(i18n("Default icon size:"), parent));
auto *iconSizes = new KONFIGURATOR_NAME_VALUE_PAIR[KrView::iconSizes.count()];
for(int i = 0; i < KrView::iconSizes.count(); i++)
iconSizes[i].text = iconSizes[i].value = QString::number(KrView::iconSizes[i]);
KonfiguratorComboBox *cmb = createComboBox(instance->name(), "IconSize", _FilelistIconSize, iconSizes, KrView::iconSizes.count(), parent, true, true, PAGE_VIEW);
delete [] iconSizes;
cmb->lineEdit()->setValidator(new QRegExpValidator(QRegExp("[1-9]\\d{0,1}"), cmb));
hbox->addWidget(cmb);
hbox->addWidget(createSpacer(parent));
grid->addLayout(hbox, 1, 0);
//--------------------------------------------------------------------
KONFIGURATOR_CHECKBOX_PARAM iconSettings[] =
// cfg_class cfg_name default text restart tooltip
{
{instance->name(), "With Icons", _WithIcons, i18n("Use icons in the filenames"), true, i18n("Show the icons for filenames and folders.") },
{instance->name(), "ShowPreviews", false, i18n("Show previews by default"), false, i18n("Show previews of files and folders.") },
};
KonfiguratorCheckBoxGroup *iconSett = createCheckBoxGroup(2, 0, iconSettings, 2 /*count*/, parent, PAGE_VIEW);
grid->addWidget(iconSett, 2, 0, 1, 2);
}
// ----------------------------------------------------------------------------------
// ---------------------------- VIEW TAB -------------------------------------------
// ----------------------------------------------------------------------------------
void KgPanel::setupPanelTab()
{
auto *scrollArea = new QScrollArea(tabWidget);
QWidget *tab_panel = new QWidget(scrollArea);
scrollArea->setFrameStyle(QFrame::NoFrame);
scrollArea->setWidget(tab_panel);
scrollArea->setWidgetResizable(true);
tabWidget->addTab(scrollArea, i18n("View"));
auto *panelLayout = new QGridLayout(tab_panel);
panelLayout->setSpacing(6);
panelLayout->setContentsMargins(11, 11, 11, 11);
QGroupBox *panelGrp = createFrame(i18n("General"), tab_panel);
panelLayout->addWidget(panelGrp, 0, 0);
QGridLayout *panelGrid = createGridLayout(panelGrp);
// ----------------------------------------------------------------------------------
// ---------------------------- General settings -----------------------------------
// ----------------------------------------------------------------------------------
// -------------------- Panel Font ----------------------------------
auto *hbox = new QHBoxLayout();
auto *fontLayout = new QHBoxLayout();
fontLayout->addWidget(new QLabel(i18n("View font:"), panelGrp));
KonfiguratorFontChooser *chsr =
createFontChooser("Look&Feel", "Filelist Font", _FilelistFont, panelGrp, true, PAGE_VIEW);
fontLayout->addWidget(chsr);
fontLayout->addStretch(1);
hbox->addLayout(fontLayout, 1);
// -------------------- Panel Tooltip ----------------------------------
auto *tooltipLayout = new QHBoxLayout();
QLabel *tooltipLabel = new QLabel(i18n("Tooltip delay (msec):"));
tooltipLabel->setWhatsThis(i18n("The duration after a tooltip is shown for a file item, in "
"milliseconds. Set a negative value to disable tooltips."));
tooltipLayout->addWidget(tooltipLabel);
KonfiguratorSpinBox *tooltipSpinBox = createSpinBox("Look&Feel", "Panel Tooltip Delay", 1000,
-100, 5000, panelGrp, false, PAGE_VIEW);
tooltipSpinBox->setSingleStep(100);
tooltipLayout->addWidget(tooltipSpinBox);
tooltipLayout->addStretch(1);
hbox->addLayout(tooltipLayout, 1);
panelGrid->addLayout(hbox, 1, 0);
// -------------------- General options ----------------------------------
KONFIGURATOR_CHECKBOX_PARAM panelSettings[] =
// cfg_class cfg_name default text restart tooltip
{
{"Look&Feel", "Human Readable Size", _HumanReadableSize, i18n("Use human-readable file size"), true , i18n("File sizes are displayed in B, KB, MB and GB, not just in bytes.") },
{"Look&Feel", "Show Hidden", _ShowHidden, i18n("Show hidden files"), false, i18n("Display files beginning with a dot.") },
{"Look&Feel", "Numeric permissions", _NumericPermissions, i18n("Numeric Permissions"), true, i18n("Show octal numbers (0755) instead of the standard permissions (rwxr-xr-x) in the permission column.") },
{"Look&Feel", "Load User Defined Folder Icons", _UserDefinedFolderIcons, i18n("Load the user defined folder icons"), true , i18n("Load the user defined folder icons (can cause decrease in performance).") },
{"Look&Feel", "Always Show Current Item", _AlwaysShowCurrentItem, i18n("Always show current item"), false, i18n("Show current item border decoration in inactive panel.") },
};
KonfiguratorCheckBoxGroup *panelSett = createCheckBoxGroup(2, 0, panelSettings, 5 /*count*/, panelGrp, PAGE_VIEW);
panelGrid->addWidget(panelSett, 3, 0, 1, 2);
// =========================================================
panelGrid->addWidget(createLine(panelGrp), 4, 0);
// ------------------------ Sort Method ----------------------------------
hbox = new QHBoxLayout();
hbox->addWidget(new QLabel(i18n("Sort method:"), panelGrp));
KONFIGURATOR_NAME_VALUE_PAIR sortMethods[] = {{ i18n("Alphabetical"), QString::number(KrViewProperties::Alphabetical) },
{ i18n("Alphabetical and numbers"), QString::number(KrViewProperties::AlphabeticalNumbers) },
{ i18n("Character code"), QString::number(KrViewProperties::CharacterCode) },
{ i18n("Character code and numbers"), QString::number(KrViewProperties::CharacterCodeNumbers) },
{ i18nc("Krusader sort", "Krusader"), QString::number(KrViewProperties::Krusader) }
};
KonfiguratorComboBox *cmb = createComboBox("Look&Feel", "Sort method", QString::number(_DefaultSortMethod),
sortMethods, 5, panelGrp, true, false, PAGE_VIEW);
hbox->addWidget(cmb);
hbox->addWidget(createSpacer(panelGrp));
panelGrid->addLayout(hbox, 5, 0);
// ------------------------ Sort Options ----------------------------------
KONFIGURATOR_CHECKBOX_PARAM sortSettings[] =
// cfg_class, cfg_name, default, text, restart, tooltip
{
{"Look&Feel", "Case Sensative Sort", _CaseSensativeSort, i18n("Case sensitive sorting"), true,
i18n("All files beginning with capital letters appear before files beginning with non-capital letters (UNIX default).") },
{"Look&Feel", "Show Directories First", true, i18n("Show folders first"), true, nullptr },
{"Look&Feel", "Always sort dirs by name", false, i18n("Always sort dirs by name"), true,
i18n("Folders are sorted by name, regardless of the sort column.") },
{"Look&Feel", "Locale Aware Sort", true, i18n("Locale aware sorting"), true,
i18n("The sorting is performed in a locale- and also platform-dependent manner. Can be slow.") },
};
KonfiguratorCheckBoxGroup *sortSett = createCheckBoxGroup(2, 0, sortSettings,
4 /*count*/, panelGrp, PAGE_VIEW);
sortSett->find("Show Directories First")->addDep(sortSett->find("Always sort dirs by name"));
panelGrid->addWidget(sortSett, 6, 0, 1, 2);
// ----------------------------------------------------------------------------------
// ---------------------------- View modes -----------------------------------------
// ----------------------------------------------------------------------------------
panelGrp = createFrame(i18n("View modes"), tab_panel);
panelLayout->addWidget(panelGrp, 1, 0);
panelGrid = createGridLayout(panelGrp);
// -------------------- Default Panel Type ----------------------------------
hbox = new QHBoxLayout();
hbox->addWidget(new QLabel(i18n("Default view mode:"), panelGrp));
QList views = KrViewFactory::registeredViews();
const int viewsSize = views.size();
auto *panelTypes = new KONFIGURATOR_NAME_VALUE_PAIR[ viewsSize ];
QString defType = QString('0');
for (int i = 0; i != viewsSize; i++) {
KrViewInstance * inst = views[ i ];
panelTypes[ i ].text = inst->description();
panelTypes[ i ].text.remove('&');
panelTypes[ i ].value = QString("%1").arg(inst->id());
if (inst->id() == KrViewFactory::defaultViewId())
defType = QString("%1").arg(inst->id());
}
cmb = createComboBox("Look&Feel", "Default Panel Type", defType, panelTypes, viewsSize, panelGrp, false, false, PAGE_VIEW);
hbox->addWidget(cmb);
hbox->addWidget(createSpacer(panelGrp));
delete [] panelTypes;
panelGrid->addLayout(hbox, 0, 0);
// ----- Individual Settings Per View Type ------------------------
auto *tabs_view = new QTabWidget(panelGrp);
panelGrid->addWidget(tabs_view, 11, 0);
for(int i = 0; i < views.count(); i++) {
QWidget *tab = new QWidget(tabs_view);
tabs_view->addTab(tab, views[i]->description());
setupView(views[i], tab);
}
}
// -----------------------------------------------------------------------------------
// -------------------------- Panel Toolbar TAB ----------------------------------
// -----------------------------------------------------------------------------------
void KgPanel::setupButtonsTab()
{
auto *scrollArea = new QScrollArea(tabWidget);
QWidget *tab = new QWidget(scrollArea);
scrollArea->setFrameStyle(QFrame::NoFrame);
scrollArea->setWidget(tab);
scrollArea->setWidgetResizable(true);
tabWidget->addTab(scrollArea, i18n("Buttons"));
QBoxLayout * tabLayout = new QVBoxLayout(tab);
tabLayout->setSpacing(6);
tabLayout->setContentsMargins(11, 11, 11, 11);
KONFIGURATOR_CHECKBOX_PARAM buttonsParams[] =
// cfg_class cfg_name default text restart tooltip
{
{"ListPanelButtons", "Icons", false, i18n("Toolbar buttons have icons"), true, "" },
{"Look&Feel", "Media Button Visible", true, i18n("Show Media Button"), true , i18n("The media button will be visible.") },
{"Look&Feel", "Back Button Visible", false, i18n("Show Back Button"), true , "Goes back in history." },
{"Look&Feel", "Forward Button Visible", false, i18n("Show Forward Button"), true , "Goes forward in history." },
{"Look&Feel", "History Button Visible", true, i18n("Show History Button"), true , i18n("The history button will be visible.") },
{"Look&Feel", "Bookmarks Button Visible", true, i18n("Show Bookmarks Button"), true , i18n("The bookmarks button will be visible.") },
{"Look&Feel", "Panel Toolbar visible", _PanelToolBar, i18n("Show Panel Toolbar"), true, i18n("The panel toolbar will be visible.") },
};
buttonsCheckboxes = createCheckBoxGroup(1, 0, buttonsParams, 7/*count*/, tab, PAGE_PANELTOOLBAR);
connect(buttonsCheckboxes->find("Panel Toolbar visible"), &KonfiguratorCheckBox::stateChanged, this, &KgPanel::slotEnablePanelToolbar);
tabLayout->addWidget(buttonsCheckboxes, 0, nullptr);
QGroupBox * panelToolbarGrp = createFrame(i18n("Visible Panel Toolbar buttons"), tab);
QGridLayout * panelToolbarGrid = createGridLayout(panelToolbarGrp);
KONFIGURATOR_CHECKBOX_PARAM panelToolbarButtonsParams[] = {
// cfg_class cfg_name default text restart tooltip
{"Look&Feel", "Equal Button Visible", _cdOther, i18n("Equal button (=)"), true , i18n("Changes the panel folder to the other panel folder.") },
{"Look&Feel", "Up Button Visible", _cdUp, i18n("Up button (..)"), true , i18n("Changes the panel folder to the parent folder.") },
{"Look&Feel", "Home Button Visible", _cdHome, i18n("Home button (~)"), true , i18n("Changes the panel folder to the home folder.") },
{"Look&Feel", "Root Button Visible", _cdRoot, i18n("Root button (/)"), true , i18n("Changes the panel folder to the root folder.") },
{"Look&Feel", "SyncBrowse Button Visible", _syncBrowseButton, i18n("Toggle-button for sync-browsing"), true , i18n("Each folder change in the panel is also performed in the other panel.") },
};
panelToolbarButtonsCheckboxes = createCheckBoxGroup(1, 0, panelToolbarButtonsParams,
sizeof(panelToolbarButtonsParams) / sizeof(*panelToolbarButtonsParams),
panelToolbarGrp, PAGE_PANELTOOLBAR);
panelToolbarGrid->addWidget(panelToolbarButtonsCheckboxes, 0, 0);
tabLayout->addWidget(panelToolbarGrp, 1, nullptr);
// Enable panel toolbar checkboxes
slotEnablePanelToolbar();
}
// ---------------------------------------------------------------------------
// -------------------------- Mouse TAB ----------------------------------
// ---------------------------------------------------------------------------
void KgPanel::setupMouseModeTab()
{
auto *scrollArea = new QScrollArea(tabWidget);
QWidget *tab_mouse = new QWidget(scrollArea);
scrollArea->setFrameStyle(QFrame::NoFrame);
scrollArea->setWidget(tab_mouse);
scrollArea->setWidgetResizable(true);
tabWidget->addTab(scrollArea, i18n("Selection Mode"));
auto *mouseLayout = new QGridLayout(tab_mouse);
mouseLayout->setSpacing(6);
mouseLayout->setContentsMargins(11, 11, 11, 11);
// -------------- General -----------------
QGroupBox *mouseGeneralGroup = createFrame(i18n("General"), tab_mouse);
QGridLayout *mouseGeneralGrid = createGridLayout(mouseGeneralGroup);
mouseGeneralGrid->setSpacing(0);
mouseGeneralGrid->setContentsMargins(5, 5, 5, 5);
KONFIGURATOR_NAME_VALUE_TIP mouseSelection[] = {
// name value tooltip
{ i18n("Krusader Mode"), "0", i18n("Both keys allow selecting files. To select more than one file, hold the Ctrl key and click the left mouse button. Right-click menu is invoked using a short click on the right mouse button.") },
{ i18n("Konqueror Mode"), "1", i18n("Pressing the left mouse button selects files - you can click and select multiple files. Right-click menu is invoked using a short click on the right mouse button.") },
{ i18n("Total-Commander Mode"), "2", i18n("The left mouse button does not select, but sets the current file without affecting the current selection. The right mouse button selects multiple files and the right-click menu is invoked by pressing and holding the right mouse button.") },
{ i18n("Ergonomic Mode"), "4", i18n("The left mouse button does not select, but sets the current file without affecting the current selection. The right mouse button invokes the context-menu. You can select with Ctrl key and the left button.") },
{ i18n("Custom Selection Mode"), "3", i18n("Design your own selection mode.") }
};
mouseRadio = createRadioButtonGroup("Look&Feel", "Mouse Selection", "0", 1, 5, mouseSelection, 5, mouseGeneralGroup, true, PAGE_MOUSE);
mouseRadio->layout()->setContentsMargins(0, 0, 0, 0);
mouseGeneralGrid->addWidget(mouseRadio, 0, 0);
for (int i = 0; i != mouseRadio->count(); i++)
connect(mouseRadio->find(i), &QRadioButton::clicked, this, &KgPanel::slotSelectionModeChanged);
mouseLayout->addWidget(mouseGeneralGroup, 0, 0);
// -------------- Details -----------------
QGroupBox *mouseDetailGroup = createFrame(i18n("Details"), tab_mouse);
QGridLayout *mouseDetailGrid = createGridLayout(mouseDetailGroup);
mouseDetailGrid->setSpacing(0);
mouseDetailGrid->setContentsMargins(5, 5, 5, 5);
KONFIGURATOR_NAME_VALUE_TIP singleOrDoubleClick[] = {
// name value tooltip
{ i18n("Double-click selects (classic)"), "0", i18n("A single click on a file will select and focus, a double click opens the file or steps into the folder.") },
{ i18n("Obey global selection policy"), "1", i18n("
Use global setting:
Plasma System Settings -> Input Devices -> Mouse
") }
};
KonfiguratorRadioButtons *clickRadio = createRadioButtonGroup("Look&Feel", "Single Click Selects", "0", 1, 0, singleOrDoubleClick, 2, mouseDetailGroup, true, PAGE_MOUSE);
clickRadio->layout()->setContentsMargins(0, 0, 0, 0);
mouseDetailGrid->addWidget(clickRadio, 0, 0);
KONFIGURATOR_CHECKBOX_PARAM mouseCheckboxesParam[] = {
// {cfg_class, cfg_name, default
// text, restart,
// tooltip }
{"Custom Selection Mode", "QT Selection", _QtSelection,
i18n("Based on KDE's selection mode"), true,
i18n("If checked, use a mode based on KDE's style.") },
{"Custom Selection Mode", "Left Selects", _LeftSelects,
i18n("Left mouse button selects"), true,
i18n("If checked, left clicking an item will select it.") },
{"Custom Selection Mode", "Left Preserves", _LeftPreserves,
i18n("Left mouse button preserves selection"), true,
i18n("If checked, left clicking an item will select it, but will not unselect other, already selected items.") },
{"Custom Selection Mode", "ShiftCtrl Left Selects", _ShiftCtrlLeft,
i18n("Shift/Ctrl-Left mouse button selects"), true,
i18n("If checked, Shift/Ctrl left clicking will select items.\nNote: this is meaningless if 'Left Button Selects' is checked.") },
{"Custom Selection Mode", "Right Selects", _RightSelects,
i18n("Right mouse button selects"), true,
i18n("If checked, right clicking an item will select it.") },
{"Custom Selection Mode", "Right Preserves", _RightPreserves,
i18n("Right mouse button preserves selection"), true,
i18n("If checked, right clicking an item will select it, but will not unselect other, already selected items.") },
{"Custom Selection Mode", "ShiftCtrl Right Selects", _ShiftCtrlRight,
i18n("Shift/Ctrl-Right mouse button selects"), true,
i18n("If checked, Shift/Ctrl right clicking will select items.\nNote: this is meaningless if 'Right Button Selects' is checked.") },
{"Custom Selection Mode", "Space Moves Down", _SpaceMovesDown,
i18n("Spacebar moves down"), true,
i18n("If checked, pressing the spacebar will select the current item and move down.\nOtherwise, current item is selected, but remains the current item.") },
{"Custom Selection Mode", "Space Calc Space", _SpaceCalcSpace,
i18n("Spacebar calculates disk space"), true,
i18n("If checked, pressing the spacebar while the current item is a folder, will (except from selecting the folder)\ncalculate space occupied of the folder (recursively).") },
{"Custom Selection Mode", "Insert Moves Down", _InsertMovesDown,
i18n("Insert moves down"), true,
i18n("If checked, pressing Insert will select the current item, and move down to the next item.\nOtherwise, current item is not changed.") },
{"Custom Selection Mode", "Immediate Context Menu", _ImmediateContextMenu,
i18n("Right clicking pops context menu immediately"), true,
i18n("If checked, right clicking will result in an immediate showing of the context menu.\nOtherwise, user needs to click and hold the right mouse button for 500ms.") },
};
mouseCheckboxes = createCheckBoxGroup(1, 0, mouseCheckboxesParam, 11 /*count*/, mouseDetailGroup, PAGE_MOUSE);
mouseDetailGrid->addWidget(mouseCheckboxes, 1, 0);
for (int i = 0; i < mouseCheckboxes->count(); i++)
connect(mouseCheckboxes->find(i), &KonfiguratorCheckBox::clicked, this, &KgPanel::slotMouseCheckBoxChanged);
mouseLayout->addWidget(mouseDetailGroup, 0, 1, 2, 1);
// Disable the details-button if not in custom-mode
slotSelectionModeChanged();
// -------------- Preview -----------------
QGroupBox *mousePreviewGroup = createFrame(i18n("Preview"), tab_mouse);
QGridLayout *mousePreviewGrid = createGridLayout(mousePreviewGroup);
// TODO preview
mousePreview = new KrTreeWidget(mousePreviewGroup);
mousePreviewGrid->addWidget(mousePreview, 0 , 0);
mousePreviewGroup->setEnabled(false); // TODO re-enable once the preview is implemented
// ------------------------------------------
mouseLayout->addWidget(mousePreviewGroup, 1, 0);
}
// ---------------------------------------------------------------------------
// -------------------------- Media Menu TAB ----------------------------------
// ---------------------------------------------------------------------------
void KgPanel::setupMediaMenuTab()
{
auto *scrollArea = new QScrollArea(tabWidget);
QWidget *tab = new QWidget(scrollArea);
scrollArea->setFrameStyle(QFrame::NoFrame);
scrollArea->setWidget(tab);
scrollArea->setWidgetResizable(true);
tabWidget->addTab(scrollArea, i18n("Media Menu"));
QBoxLayout * tabLayout = new QVBoxLayout(tab);
tabLayout->setSpacing(6);
tabLayout->setContentsMargins(11, 11, 11, 11);
KONFIGURATOR_CHECKBOX_PARAM mediaMenuParams[] = {
// cfg_class cfg_name default text restart tooltip
{"MediaMenu", "ShowPath", true, i18n("Show Mount Path"), false, nullptr },
{"MediaMenu", "ShowFSType", true, i18n("Show File System Type"), false, nullptr },
};
KonfiguratorCheckBoxGroup *mediaMenuCheckBoxes =
createCheckBoxGroup(1, 0, mediaMenuParams,
sizeof(mediaMenuParams) / sizeof(*mediaMenuParams),
tab, PAGE_MEDIA_MENU);
tabLayout->addWidget(mediaMenuCheckBoxes, 0, nullptr);
auto *showSizeHBox = new QHBoxLayout();
showSizeHBox->addWidget(new QLabel(i18n("Show Size:"), tab));
KONFIGURATOR_NAME_VALUE_PAIR showSizeValues[] = {
{ i18nc("setting 'show size'", "Always"), "Always" },
{ i18nc("setting 'show size'", "When Device has no Label"), "WhenNoLabel" },
{ i18nc("setting 'show size'", "Never"), "Never" },
};
KonfiguratorComboBox *showSizeCmb =
createComboBox("MediaMenu", "ShowSize",
"Always", showSizeValues,
sizeof(showSizeValues) / sizeof(*showSizeValues),
tab, false, false, PAGE_MEDIA_MENU);
showSizeHBox->addWidget(showSizeCmb);
showSizeHBox->addStretch();
tabLayout->addLayout(showSizeHBox);
tabLayout->addStretch();
}
void KgPanel::slotEnablePanelToolbar()
{
bool enableTB = buttonsCheckboxes->find("Panel Toolbar visible")->isChecked();
panelToolbarButtonsCheckboxes->find("Root Button Visible")->setEnabled(enableTB);
panelToolbarButtonsCheckboxes->find("Home Button Visible")->setEnabled(enableTB);
panelToolbarButtonsCheckboxes->find("Up Button Visible")->setEnabled(enableTB);
panelToolbarButtonsCheckboxes->find("Equal Button Visible")->setEnabled(enableTB);
panelToolbarButtonsCheckboxes->find("SyncBrowse Button Visible")->setEnabled(enableTB);
}
void KgPanel::slotSelectionModeChanged()
{
KrSelectionMode *selectionMode =
KrSelectionMode::getSelectionHandlerForMode(mouseRadio->selectedValue());
if (selectionMode == nullptr) //User mode
return;
selectionMode->init();
mouseCheckboxes->find("QT Selection")->setChecked(selectionMode->useQTSelection());
mouseCheckboxes->find("Left Selects")->setChecked(selectionMode->leftButtonSelects());
mouseCheckboxes->find("Left Preserves")->setChecked(selectionMode->leftButtonPreservesSelection());
mouseCheckboxes->find("ShiftCtrl Left Selects")->setChecked(selectionMode->shiftCtrlLeftButtonSelects());
mouseCheckboxes->find("Right Selects")->setChecked(selectionMode->rightButtonSelects());
mouseCheckboxes->find("Right Preserves")->setChecked(selectionMode->rightButtonPreservesSelection());
mouseCheckboxes->find("ShiftCtrl Right Selects")->setChecked(selectionMode->shiftCtrlRightButtonSelects());
mouseCheckboxes->find("Space Moves Down")->setChecked(selectionMode->spaceMovesDown());
mouseCheckboxes->find("Space Calc Space")->setChecked(selectionMode->spaceCalculatesDiskSpace());
mouseCheckboxes->find("Insert Moves Down")->setChecked(selectionMode->insertMovesDown());
mouseCheckboxes->find("Immediate Context Menu")->setChecked(selectionMode->showContextMenu() == -1);
}
void KgPanel::slotMouseCheckBoxChanged()
{
mouseRadio->selectButton("3"); //custom selection mode
}
int KgPanel::activeSubPage()
{
return tabWidget->currentIndex();
}
diff --git a/krusader/Panel/listpanel.cpp b/krusader/Panel/listpanel.cpp
index 515a6f71..b3b92f74 100644
--- a/krusader/Panel/listpanel.cpp
+++ b/krusader/Panel/listpanel.cpp
@@ -1,1376 +1,1376 @@
/*****************************************************************************
* Copyright (C) 2000 Shie Erlich *
* Copyright (C) 2000 Rafi Yanai *
* Copyright (C) 2004-2019 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#include "listpanel.h"
// QtCore
#include
#include
#include
#include
#include
#include
#include
// QtGui
#include
#include
#include
#include
#include
#include
#include
#include
// QtWidgets
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "dirhistoryqueue.h"
#include "krcolorcache.h"
#include "krerrordisplay.h"
#include "krlayoutfactory.h"
#include "krpreviewpopup.h"
#include "krsearchbar.h"
#include "listpanelactions.h"
#include "panelcontextmenu.h"
#include "panelfunc.h"
#include "sidebar.h"
#include "viewactions.h"
#include "PanelView/krview.h"
#include "PanelView/krviewfactory.h"
#include "PanelView/krviewitem.h"
#include "../defaults.h"
#include "../icon.h"
#include "../krservices.h"
#include "../krslots.h"
#include "../krusader.h"
#include "../krusaderview.h"
#include "../Archive/krarchandler.h"
#include "../BookMan/krbookmarkbutton.h"
#include "../FileSystem/fileitem.h"
#include "../FileSystem/filesystem.h"
#include "../FileSystem/krpermhandler.h"
#include "../FileSystem/sizecalculator.h"
#include "../Dialogs/krdialogs.h"
#include "../Dialogs/krspwidgets.h"
#include "../Dialogs/krsqueezedtextlabel.h"
#include "../Dialogs/percentalsplitter.h"
#include "../Dialogs/popularurls.h"
#include "../GUI/dirhistorybutton.h"
#include "../GUI/kcmdline.h"
#include "../GUI/mediabutton.h"
#include "../MountMan/kmountman.h"
#include "../UserAction/useractionpopupmenu.h"
class ActionButton : public QToolButton
{
public:
ActionButton(QWidget *parent, ListPanel *panel, QAction *action, const QString& text = QString()) :
QToolButton(parent), panel(panel), action(action) {
setText(text);
setAutoRaise(true);
if(KConfigGroup(krConfig, "ListPanelButtons").readEntry("Icons", false) || text.isEmpty())
setIcon(action->icon());
setToolTip(action->toolTip());
}
protected:
void mousePressEvent(QMouseEvent *) override {
panel->slotFocusOnMe();
action->trigger();
}
ListPanel *panel;
QAction *action;
};
/////////////////////////////////////////////////////
// The list panel constructor //
/////////////////////////////////////////////////////
ListPanel::ListPanel(QWidget *parent, AbstractPanelManager *manager, const KConfigGroup &cfg)
: QWidget(parent), KrPanel(manager, this, new ListPanelFunc(this)), panelType(-1),
colorMask(255), compareMode(false), previewJob(nullptr), inlineRefreshJob(nullptr),
searchBar(nullptr), cdRootButton(nullptr), cdUpButton(nullptr), sidebarButton(nullptr),
sidebar(nullptr), fileSystemError(nullptr), _tabState(TabState::DEFAULT)
{
if(cfg.isValid())
panelType = cfg.readEntry("Type", -1);
if (panelType == -1)
panelType = defaultPanelType();
_actions = krApp->listPanelActions();
setAcceptDrops(true);
QHash widgets;
#define ADD_WIDGET(widget) widgets.insert(#widget, widget);
// media button
mediaButton = new MediaButton(this);
connect(mediaButton, &MediaButton::aboutToShow, this, [=]() { slotFocusOnMe(); });
connect(mediaButton, &MediaButton::openUrl, [=](const QUrl & _t1) { func->openUrl(_t1); });
connect(mediaButton, &MediaButton::newTab, this, [=](const QUrl &url) { newTab(url); });
ADD_WIDGET(mediaButton);
// status bar
status = new KrSqueezedTextLabel(this);
KConfigGroup group(krConfig, "Look&Feel");
status->setFont(group.readEntry("Filelist Font", _FilelistFont));
status->setAutoFillBackground(false);
status->setText(""); // needed for initialization code!
status->setWhatsThis(i18n("The statusbar displays information about the filesystem "
"which holds your current folder: total size, free space, "
"type of filesystem, etc."));
ADD_WIDGET(status);
// back button
backButton = new ActionButton(this, this, _actions->actHistoryBackward);
ADD_WIDGET(backButton);
// forward button
forwardButton = new ActionButton(this, this, _actions->actHistoryForward);
ADD_WIDGET(forwardButton);
// ... create the history button
historyButton = new DirHistoryButton(func->history, this);
connect(historyButton, &DirHistoryButton::aboutToShow, this, [=]() { slotFocusOnMe(); });
connect(historyButton, &DirHistoryButton::gotoPos, func, &ListPanelFunc::historyGotoPos);
ADD_WIDGET(historyButton);
// bookmarks button
bookmarksButton = new KrBookmarkButton(this);
connect(bookmarksButton, &KrBookmarkButton::aboutToShow, this, [=]() { slotFocusOnMe(); });
connect(bookmarksButton, &KrBookmarkButton::openUrl, [=](const QUrl & _t1) { func->openUrl(_t1); });
bookmarksButton->setWhatsThis(i18n("Open menu with bookmarks. You can also add "
"current location to the list, edit bookmarks "
"or add subfolder to the list."));
ADD_WIDGET(bookmarksButton);
// url input field
urlNavigator = new KUrlNavigator(new KFilePlacesModel(this), QUrl(), this);
urlNavigator->setWhatsThis(i18n("Name of folder where you are. You can also "
"enter name of desired location to move there. "
"Use of Net protocols like ftp or fish is possible."));
// handle certain key events here in event filter
urlNavigator->editor()->installEventFilter(this);
urlNavigator->setUrlEditable(isNavigatorEditModeSet());
urlNavigator->setShowFullPath(group.readEntry("Navigator Full Path", false));
connect(urlNavigator, &KUrlNavigator::returnPressed, this, [=]() { slotFocusOnMe(); });
connect(urlNavigator, &KUrlNavigator::urlChanged, this, &ListPanel::slotNavigatorUrlChanged);
connect(urlNavigator->editor()->lineEdit(), &QLineEdit::editingFinished, this, &ListPanel::resetNavigatorMode);
connect(urlNavigator, &KUrlNavigator::tabRequested, this, [=](const QUrl &url) { ListPanel::newTab(url); });
connect(urlNavigator, &KUrlNavigator::urlsDropped, this, QOverload::of(&ListPanel::handleDrop));
ADD_WIDGET(urlNavigator);
// toolbar
QWidget * toolbar = new QWidget(this);
auto * toolbarLayout = new QHBoxLayout(toolbar);
toolbarLayout->setContentsMargins(0, 0, 0, 0);
toolbarLayout->setSpacing(0);
ADD_WIDGET(toolbar);
fileSystemError = new KrErrorDisplay(this);
fileSystemError->setWordWrap(true);
fileSystemError->hide();
ADD_WIDGET(fileSystemError);
// client area
clientArea = new QWidget(this);
auto *clientLayout = new QVBoxLayout(clientArea);
clientLayout->setSpacing(0);
clientLayout->setContentsMargins(0, 0, 0, 0);
ADD_WIDGET(clientArea);
// totals label
totals = new KrSqueezedTextLabel(this);
totals->setFont(group.readEntry("Filelist Font", _FilelistFont));
totals->setAutoFillBackground(false);
totals->setWhatsThis(i18n("The totals bar shows how many files exist, "
"how many selected and the bytes math"));
ADD_WIDGET(totals);
// free space label
freeSpace = new KrSqueezedTextLabel(this);
freeSpace->setFont(group.readEntry("Filelist Font", _FilelistFont));
freeSpace->setAutoFillBackground(false);
freeSpace->setText("");
freeSpace->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
ADD_WIDGET(freeSpace);
// progress indicator and cancel button for the quick calc size
quickSizeCalcProgress = new QProgressBar(this);
quickSizeCalcProgress->hide();
ADD_WIDGET(quickSizeCalcProgress);
cancelQuickSizeCalcButton = new QToolButton(this);
cancelQuickSizeCalcButton->hide();
cancelQuickSizeCalcButton->setIcon(Icon("dialog-cancel"));
- cancelQuickSizeCalcButton->setToolTip(i18n("Cancel directory space calculation"));
+ cancelQuickSizeCalcButton->setToolTip(i18n("Cancel folder space calculation"));
ADD_WIDGET(cancelQuickSizeCalcButton);
// progress indicator for the preview job
previewProgress = new QProgressBar(this);
previewProgress->hide();
ADD_WIDGET(previewProgress);
// a cancel button for the filesystem refresh and preview job
cancelProgressButton = new QToolButton(this);
cancelProgressButton->hide();
cancelProgressButton->setIcon(Icon("dialog-cancel"));
connect(cancelProgressButton, &QToolButton::clicked, this, &ListPanel::cancelProgress);
ADD_WIDGET(cancelProgressButton);
// button for changing the panel sidebar position in the panel
sidebarPositionButton = new QToolButton(this);
sidebarPositionButton->hide();
sidebarPositionButton->setAutoRaise(true);
sidebarPositionButton->setIcon(Icon("exchange-positions"));
sidebarPositionButton->setToolTip(i18n("Move Sidebar clockwise"));
connect(sidebarPositionButton, &QToolButton::clicked, [this]() {
// moving position clockwise
setSidebarPosition((sidebarPosition() + 1) % 4); });
ADD_WIDGET(sidebarPositionButton);
// a quick button to open the sidebar
sidebarButton = new QToolButton(this);
sidebarButton->setAutoRaise(true);
sidebarButton->setIcon(Icon("arrow-up"));
connect(sidebarButton, &QToolButton::clicked, this, &ListPanel::toggleSidebar);
sidebarButton->setToolTip(i18n("Open the Sidebar"));
ADD_WIDGET(sidebarButton);
#undef ADD_WIDGET
// toolbar buttons
cdOtherButton = new ActionButton(toolbar, this, _actions->actCdToOther, "=");
toolbarLayout->addWidget(cdOtherButton);
cdUpButton = new ActionButton(toolbar, this, _actions->actDirUp, "..");
toolbarLayout->addWidget(cdUpButton);
cdHomeButton = new ActionButton(toolbar, this, _actions->actHome, "~");
toolbarLayout->addWidget(cdHomeButton);
cdRootButton = new ActionButton(toolbar, this, _actions->actRoot, "/");
toolbarLayout->addWidget(cdRootButton);
// create the button for sync-browsing
syncBrowseButton = new QToolButton(toolbar);
syncBrowseButton->setIcon(Icon("kr_syncbrowse_off"));
syncBrowseButton->setCheckable(true);
const QString syncBrowseText = i18n("This button toggles the sync-browse mode.\n"
"When active, each folder change is performed in the\n"
"active and inactive panel - if possible.");
syncBrowseButton->setText(syncBrowseText);
syncBrowseButton->setToolTip(syncBrowseText);
connect(syncBrowseButton, &QToolButton::toggled, [=](bool checked) {
syncBrowseButton->setIcon(
Icon(checked ? "kr_syncbrowse_on" : "kr_syncbrowse_off"));
});
syncBrowseButton->setAutoRaise(true);
toolbarLayout->addWidget(syncBrowseButton);
setButtons();
// create a splitter to hold the view and the sidebar
sidebarSplitter = new PercentalSplitter(clientArea);
sidebarSplitter->setChildrenCollapsible(true);
sidebarSplitter->setOrientation(Qt::Horizontal);
// expand vertical if splitter orientation is horizontal
QSizePolicy sizePolicy = sidebarSplitter->sizePolicy();
sizePolicy.setVerticalPolicy(QSizePolicy::Expanding);
sidebarSplitter->setSizePolicy(sizePolicy);
clientLayout->addWidget(sidebarSplitter);
// view
createView();
// search (in folder) bar
searchBar = new KrSearchBar(view, clientArea);
searchBar->hide();
bool top = group.readEntry("Quicksearch Position", "bottom") == "top";
clientLayout->insertWidget(top ? 0 : -1, searchBar);
// create the layout
KrLayoutFactory fact(this, widgets);
QLayout *layout = fact.createLayout();
if(!layout) { // fallback: create a layout by ourself
auto *v = new QVBoxLayout;
v->setContentsMargins(0, 0, 0, 0);
v->setSpacing(0);
auto *h = new QHBoxLayout;
h->setContentsMargins(0, 0, 0, 0);
h->setSpacing(0);
h->addWidget(urlNavigator);
h->addWidget(toolbar);
h->addStretch();
v->addLayout(h);
h = new QHBoxLayout;
h->setContentsMargins(0, 0, 0, 0);
h->setSpacing(0);
h->addWidget(mediaButton);
h->addWidget(status);
h->addWidget(backButton);
h->addWidget(forwardButton);
h->addWidget(historyButton);
h->addWidget(bookmarksButton);
v->addLayout(h);
v->addWidget(fileSystemError);
v->addWidget(clientArea);
h = new QHBoxLayout;
h->setContentsMargins(0, 0, 0, 0);
h->setSpacing(0);
h->addWidget(totals);
h->addWidget(freeSpace);
h->addWidget(quickSizeCalcProgress);
h->addWidget(cancelQuickSizeCalcButton);
h->addWidget(previewProgress);
h->addWidget(cancelProgressButton);
h->addWidget(sidebarButton);
v->addLayout(h);
layout = v;
}
setLayout(layout);
connect(&KrColorCache::getColorCache(), &KrColorCache::colorsRefreshed, this, &ListPanel::slotRefreshColors);
connect(krApp, &Krusader::shutdown, this, &ListPanel::cancelProgress);
}
ListPanel::~ListPanel()
{
cancelProgress();
delete view;
view = nullptr;
delete func;
delete status;
delete bookmarksButton;
delete totals;
delete urlNavigator;
delete cdRootButton;
delete cdHomeButton;
delete cdUpButton;
delete cdOtherButton;
delete syncBrowseButton;
// delete layout;
}
void ListPanel::reparent(QWidget *parent, AbstractPanelManager *manager)
{
setParent(parent);
_manager = manager;
}
int ListPanel::defaultPanelType()
{
KConfigGroup group(krConfig, "Look&Feel");
return group.readEntry("Default Panel Type", KrViewFactory::defaultViewId());
}
bool ListPanel::isNavigatorEditModeSet()
{
KConfigGroup group(krConfig, "Look&Feel");
return group.readEntry("Navigator Edit Mode", false);
}
void ListPanel::createView()
{
view = KrViewFactory::createView(panelType, sidebarSplitter, krConfig);
view->init();
view->setMainWindow(krApp);
// KrViewFactory may create a different view type than requested
panelType = view->instance()->id();
if(this == ACTIVE_PANEL)
view->prepareForActive();
else
view->prepareForPassive();
view->refreshColors();
sidebarSplitter->insertWidget(sidebarPosition() < 2 ? 1 : 0, view->widget());
view->widget()->installEventFilter(this);
connect(view->op(), &KrViewOperator::quickCalcSpace, func, &ListPanelFunc::quickCalcSpace);
connect(view->op(), &KrViewOperator::goHome, func, &ListPanelFunc::home);
connect(view->op(), &KrViewOperator::dirUp, func, &ListPanelFunc::dirUp);
connect(view->op(), &KrViewOperator::defaultDeleteFiles, func, &ListPanelFunc::defaultDeleteFiles);
connect(view->op(), &KrViewOperator::middleButtonClicked, this, QOverload::of(&ListPanel::newTab));
connect(view->op(), &KrViewOperator::currentChanged, this, &ListPanel::slotCurrentChanged);
connect(view->op(), &KrViewOperator::renameItem, func, QOverload::of(&ListPanelFunc::rename));
connect(view->op(), &KrViewOperator::executed, func, &ListPanelFunc::execute);
connect(view->op(), &KrViewOperator::goInside, func, &ListPanelFunc::goInside);
connect(view->op(), &KrViewOperator::needFocus, this, [=]() { slotFocusOnMe(); });
connect(view->op(), &KrViewOperator::selectionChanged, this, &ListPanel::slotUpdateTotals);
connect(view->op(), &KrViewOperator::itemDescription, krApp, &Krusader::statusBarUpdate);
connect(view->op(), &KrViewOperator::contextMenu, this, &ListPanel::popRightClickMenu);
connect(view->op(), &KrViewOperator::emptyContextMenu, this, &ListPanel::popEmptyRightClickMenu);
connect(view->op(), &KrViewOperator::letsDrag, this, &ListPanel::startDragging);
connect(view->op(), &KrViewOperator::gotDrop, this, [this](QDropEvent *event) {handleDrop(event, true); });
connect(view->op(), &KrViewOperator::previewJobStarted, this, &ListPanel::slotPreviewJobStarted);
connect(view->op(), &KrViewOperator::refreshActions, krApp->viewActions(), &ViewActions::refreshActions);
connect(view->op(), &KrViewOperator::currentChanged, func->history, &DirHistoryQueue::saveCurrentItem);
connect(view->op(), &KrViewOperator::goBack, func, &ListPanelFunc::historyBackward);
connect(view->op(), &KrViewOperator::goForward, func, &ListPanelFunc::historyForward);
view->setFiles(func->files());
func->refreshActions();
}
void ListPanel::changeType(int type)
{
if (panelType != type) {
QString current = view->getCurrentItem();
QList selection = view->selectedUrls();
bool filterApplysToDirs = view->properties()->filterApplysToDirs;
KrViewProperties::FilterSpec filter = view->filter();
FilterSettings filterSettings = view->properties()->filterSettings;
panelType = type;
KrView *oldView = view;
createView();
searchBar->setView(view);
delete oldView;
view->setFilter(filter, filterSettings, filterApplysToDirs);
view->setSelectionUrls(selection);
view->setCurrentItem(current);
view->makeItemVisible(view->getCurrentKrViewItem());
}
}
int ListPanel::getProperties()
{
int props = 0;
if (syncBrowseButton->isChecked()) {
props |= PROP_SYNC_BUTTON_ON;
}
if (isLocked()) {
props |= PROP_LOCKED;
} else if (isPinned()) {
props |= PROP_PINNED;
}
return props;
}
void ListPanel::setProperties(int prop)
{
syncBrowseButton->setChecked(prop & PROP_SYNC_BUTTON_ON);
if (prop & PROP_LOCKED) {
_tabState = TabState::LOCKED;
} else if (prop & PROP_PINNED) {
_tabState = TabState::PINNED;
} else {
_tabState = TabState::DEFAULT;
}
}
bool ListPanel::eventFilter(QObject * watched, QEvent * e)
{
if(view && watched == view->widget()) {
if(e->type() == QEvent::FocusIn && this != ACTIVE_PANEL && !isHidden())
slotFocusOnMe();
else if(e->type() == QEvent::ShortcutOverride) {
auto *ke = dynamic_cast(e);
if(ke->key() == Qt::Key_Escape && ke->modifiers() == Qt::NoModifier) {
// if the cancel refresh action has no shortcut assigned,
// we need this event ourselves to cancel refresh
if(_actions->actCancelRefresh->shortcut().isEmpty()) {
e->accept();
return true;
}
}
}
}
// handle URL navigator key events
else if(watched == urlNavigator->editor()) {
// override default shortcut for panel focus
if(e->type() == QEvent::ShortcutOverride) {
auto *ke = dynamic_cast(e);
if ((ke->key() == Qt::Key_Escape) && (ke->modifiers() == Qt::NoModifier)) {
e->accept(); // we will get the key press event now
return true;
}
} else if(e->type() == QEvent::KeyPress) {
auto *ke = dynamic_cast(e);
if ((ke->key() == Qt::Key_Down) && (ke->modifiers() == Qt::ControlModifier)) {
slotFocusOnMe();
return true;
} else if ((ke->key() == Qt::Key_Escape) && (ke->modifiers() == Qt::NoModifier)) {
// reset navigator
urlNavigator->editor()->setUrl(urlNavigator->locationUrl());
slotFocusOnMe();
return true;
}
}
}
return false;
}
void ListPanel::toggleSidebar()
{
if(!sidebar) {
sidebar = new Sidebar(sidebarSplitter);
// fix vertical grow of splitter (and entire window) if its content
// demands more space
QSizePolicy sizePolicy = sidebar->sizePolicy();
sizePolicy.setVerticalPolicy(QSizePolicy::Ignored);
sidebar->setSizePolicy(sizePolicy);
connect(this, &ListPanel::pathChanged, sidebar, &Sidebar::onPanelPathChange);
connect(sidebar, &Sidebar::urlActivated, SLOTS, &KRslots::refresh);
sidebarSplitter->insertWidget(0, sidebar);
}
if (sidebar->isHidden()) {
if (sidebarSplitterSizes.count() > 0) {
sidebarSplitter->setSizes(sidebarSplitterSizes);
} else { // on the first time, resize to 50%
QList lst;
lst << height() / 2 << height() / 2;
sidebarSplitter->setSizes(lst);
}
sidebar->show();
sidebarButton->setIcon(Icon("arrow-down"));
sidebarButton->setToolTip(i18n("Close the Sidebar"));
sidebarPositionButton->show();
} else {
sidebarSplitterSizes.clear();
sidebarSplitterSizes = sidebarSplitter->sizes();
sidebar->hide();
sidebarButton->setIcon(Icon("arrow-up"));
sidebarButton->setToolTip(i18n("Open the Sidebar"));
sidebarPositionButton->hide();
QList lst;
lst << height() << 0;
sidebarSplitter->setSizes(lst);
if (ACTIVE_PANEL)
ACTIVE_PANEL->gui->slotFocusOnMe();
}
}
QString ListPanel::lastLocalPath() const
{
return _lastLocalPath;
}
void ListPanel::setButtons()
{
KConfigGroup group(krConfig, "Look&Feel");
mediaButton->setVisible(group.readEntry("Media Button Visible", true));
backButton->setVisible(group.readEntry("Back Button Visible", false));
forwardButton->setVisible(group.readEntry("Forward Button Visible", false));
historyButton->setVisible(group.readEntry("History Button Visible", true));
bookmarksButton->setVisible(group.readEntry("Bookmarks Button Visible", true));
if (group.readEntry("Panel Toolbar visible", _PanelToolBar)) {
cdRootButton->setVisible(group.readEntry("Root Button Visible", _cdRoot));
cdHomeButton->setVisible(group.readEntry("Home Button Visible", _cdHome));
cdUpButton->setVisible(group.readEntry("Up Button Visible", _cdUp));
cdOtherButton->setVisible(group.readEntry("Equal Button Visible", _cdOther));
syncBrowseButton->setVisible(group.readEntry("SyncBrowse Button Visible", _syncBrowseButton));
} else {
cdRootButton->hide();
cdHomeButton->hide();
cdUpButton->hide();
cdOtherButton->hide();
syncBrowseButton->hide();
}
}
void ListPanel::slotUpdateTotals()
{
totals->setText(view->statistics());
}
void ListPanel::compareDirs(bool otherPanelToo)
{
// Performs a check in order to avoid that the next code is executed twice
if (otherPanelToo == true) {
// If both panels are showing the same directory
if (_manager->currentPanel()->virtualPath() == otherPanel()->virtualPath()) {
if (KMessageBox::warningContinueCancel(this,
i18n("Warning: The left and the right side are showing the same folder.")) != KMessageBox::Continue) {
return;
}
}
}
KConfigGroup pg(krConfig, "Private");
int compareMode = pg.readEntry("Compare Mode", 0);
KConfigGroup group(krConfig, "Look&Feel");
bool selectDirs = group.readEntry("Mark Dirs", false);
KrViewItem *item, *otherItem;
for (item = view->getFirst(); item != nullptr; item = view->getNext(item)) {
if (item->name() == "..")
continue;
for (otherItem = otherPanel()->view->getFirst(); otherItem != nullptr && otherItem->name() != item->name();
otherItem = otherPanel()->view->getNext(otherItem));
bool isSingle = (otherItem == nullptr), isDifferent = false, isNewer = false;
if (func->getFileItem(item)->isDir() && !selectDirs) {
item->setSelected(false);
continue;
}
if (otherItem) {
if (!func->getFileItem(item)->isDir())
isDifferent = otherPanel()->func->getFileItem(otherItem)->getSize() != func->getFileItem(item)->getSize();
isNewer = func->getFileItem(item)->getModificationTime() > otherPanel()->func->getFileItem(otherItem)->getModificationTime();
}
switch (compareMode) {
case 0:
item->setSelected(isNewer || isSingle);
break;
case 1:
item->setSelected(isNewer);
break;
case 2:
item->setSelected(isSingle);
break;
case 3:
item->setSelected(isDifferent || isSingle);
break;
case 4:
item->setSelected(isDifferent);
break;
}
}
view->updateView();
if (otherPanelToo)
otherPanel()->gui->compareDirs(false);
}
void ListPanel::slotRefreshColors()
{
view->refreshColors();
emit signalRefreshColors(this == ACTIVE_PANEL);
}
void ListPanel::slotFocusOnMe(bool focus)
{
if (focus && _manager->currentPanel() != this) {
// ignore focus request if this panel is not shown
return;
}
krApp->setUpdatesEnabled(false);
if(focus) {
emit activate();
_actions->activePanelChanged();
func->refreshActions();
slotCurrentChanged(view->getCurrentKrViewItem());
view->prepareForActive();
otherPanel()->gui->slotFocusOnMe(false);
} else {
// in case a new url was entered but not refreshed to,
// reset url navigator to the current url
setNavigatorUrl(virtualPath());
view->prepareForPassive();
}
urlNavigator->setActive(focus);
slotRefreshColors();
krApp->setUpdatesEnabled(true);
}
// this is used to start the panel
//////////////////////////////////////////////////////////////////
void ListPanel::start(const QUrl &url)
{
QUrl startUrl(url);
if (!startUrl.isValid())
startUrl = QUrl::fromLocalFile(ROOT_DIR);
_lastLocalPath = startUrl.isLocalFile() ? startUrl.path() : ROOT_DIR;
func->openUrl(startUrl);
setJumpBack(startUrl);
}
void ListPanel::slotStartUpdate(bool directoryChange)
{
if (inlineRefreshJob)
inlineRefreshListResult(nullptr);
setCursor(Qt::BusyCursor);
const QUrl currentUrl = virtualPath();
if (directoryChange) {
if (this == ACTIVE_PANEL) {
slotFocusOnMe();
}
if (currentUrl.isLocalFile())
_lastLocalPath = currentUrl.path();
setNavigatorUrl(currentUrl);
emit pathChanged(currentUrl);
krApp->popularUrls()->addUrl(currentUrl);
searchBar->hideBar();
}
if (compareMode)
otherPanel()->view->refresh();
// return cursor to normal arrow
setCursor(Qt::ArrowCursor);
slotUpdateTotals();
}
void ListPanel::updateFilesystemStats(const QString &metaInfo, const QString &fsType,
KIO::filesize_t total, KIO::filesize_t free)
{
QString statusText, mountPoint, freeSpaceText;
if (!metaInfo.isEmpty()) {
statusText = metaInfo;
mountPoint = freeSpaceText = "";
} else {
const int perc = total == 0 ? 0 : (int)(((float)free / (float)total) * 100.0);
mountPoint = func->files()->mountPoint();
statusText = i18nc("%1=free space,%2=total space,%3=percentage of usage, "
"%4=mountpoint,%5=filesystem type",
"%1 free out of %2 (%3%) on %4 [(%5)]", KIO::convertSize(free),
KIO::convertSize(total), perc, mountPoint, fsType);
freeSpaceText = " " + i18n("%1 free", KIO::convertSize(free));
}
status->setText(statusText);
freeSpace->setText(freeSpaceText);
mediaButton->updateIcon(mountPoint);
}
void ListPanel::handleDrop(QDropEvent *event, bool onView)
{
// check what was dropped
const QList urls = KUrlMimeData::urlsFromMimeData(event->mimeData());
if (urls.isEmpty()) {
event->ignore(); // not for us to handle!
return;
}
// find dropping destination
QString destinationDir = "";
const bool dragFromThisPanel = event->source() == this;
const KrViewItem *item = onView ? view->getKrViewItemAt(event->pos()) : nullptr;
if (item) {
const FileItem *file = item->getFileItem();
if (file && !file->isDir() && dragFromThisPanel) {
event->ignore(); // dragging on files in same panel, ignore
return;
} else if (!file || file->isDir()) { // item is ".." dummy or a directory
destinationDir = item->name();
}
} else if (dragFromThisPanel) {
event->ignore(); // dragged from this panel onto an empty spot in this panel, ignore
return;
}
QUrl destination = QUrl(virtualPath());
destination.setPath(destination.path() + '/' + destinationDir);
func->files()->dropFiles(destination, event);
if(KConfigGroup(krConfig, "Look&Feel").readEntry("UnselectBeforeOperation",
_UnselectBeforeOperation)) {
KrPanel *p = dragFromThisPanel ? this : otherPanel();
p->view->saveSelection();
p->view->unselectAll();
}
}
void ListPanel::handleDrop(const QUrl &destination, QDropEvent *event)
{
func->files()->dropFiles(destination, event);
}
void ListPanel::startDragging(const QStringList& names, const QPixmap& px)
{
if (names.isEmpty()) { // avoid dragging empty urls
return;
}
QList urls = func->files()->getUrls(names);
auto *drag = new QDrag(this);
auto *mimeData = new QMimeData;
drag->setPixmap(px);
mimeData->setUrls(urls);
drag->setMimeData(mimeData);
drag->exec(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction);
}
// pops a right-click menu for items
void ListPanel::popRightClickMenu(const QPoint &loc)
{
// run it, on the mouse location
int j = QFontMetrics(font()).height() * 2;
PanelContextMenu::run(QPoint(loc.x() + 5, loc.y() + j), this);
}
void ListPanel::popEmptyRightClickMenu(const QPoint &loc)
{
PanelContextMenu::run(loc, this);
}
QString ListPanel::getCurrentName() const
{
const QString name = view->getCurrentItem();
return name == ".." ? QString() : name;
}
QStringList ListPanel::getSelectedNames()
{
QStringList fileNames;
view->getSelectedItems(&fileNames);
return fileNames;
}
void ListPanel::prepareToDelete()
{
const bool skipCurrent = (view->numSelected() == 0);
view->setNameToMakeCurrent(view->firstUnmarkedBelowCurrent(skipCurrent));
}
void ListPanel::keyPressEvent(QKeyEvent *e)
{
switch (e->key()) {
case Qt::Key_Enter :
case Qt::Key_Return :
if (e->modifiers() & Qt::ControlModifier) {
if (e->modifiers() & Qt::AltModifier) {
FileItem *fileitem =
func->files()->getFileItem(view->getCurrentKrViewItem()->name());
if (fileitem && fileitem->isDir())
newTab(fileitem->getUrl(), true);
} else {
SLOTS->insertFileName((e->modifiers()&Qt::ShiftModifier)!=0);
}
} else {
e->ignore();
}
break;
case Qt::Key_Right :
case Qt::Key_Left :
if (e->modifiers() == Qt::ControlModifier) {
// user pressed CTRL+Right/Left - refresh other panel to the selected path if it's a
// directory otherwise as this one
if ((isLeft() && e->key() == Qt::Key_Right) || (!isLeft() && e->key() == Qt::Key_Left)) {
QUrl newPath;
KrViewItem *it = view->getCurrentKrViewItem();
if (it->name() == "..") {
newPath = KIO::upUrl(virtualPath());
} else {
FileItem *v = func->getFileItem(it);
// If it's a directory different from ".."
if (v && v->isDir() && v->getName() != "..") {
newPath = v->getUrl();
} else {
// If it's a supported compressed file
if (v && KRarcHandler::arcSupported(v->getMime())) {
newPath = func->browsableArchivePath(v->getUrl().fileName());
} else {
newPath = virtualPath();
}
}
}
otherPanel()->func->openUrl(newPath);
} else {
func->openUrl(otherPanel()->virtualPath());
}
return;
} else
e->ignore();
break;
case Qt::Key_Down :
if (e->modifiers() == Qt::ControlModifier) { // give the keyboard focus to the command line
if (MAIN_VIEW->cmdLine()->isVisible())
MAIN_VIEW->cmdLineFocus();
else
MAIN_VIEW->focusTerminalEmulator();
return;
} else if (e->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) { // give the keyboard focus to TE
MAIN_VIEW->focusTerminalEmulator();
} else
e->ignore();
break;
case Qt::Key_Up :
if (e->modifiers() == Qt::ControlModifier) { // give the keyboard focus to the url navigator
editLocation();
return;
} else
e->ignore();
break;
case Qt::Key_Escape:
cancelProgress();
break;
default:
// if we got this, it means that the view is not doing
// the quick search thing, so send the characters to the commandline, if normal key
if (e->modifiers() == Qt::NoModifier)
MAIN_VIEW->cmdLine()->addText(e->text());
//e->ignore();
}
}
void ListPanel::showEvent(QShowEvent *e)
{
panelVisible();
QWidget::showEvent(e);
}
void ListPanel::hideEvent(QHideEvent *e)
{
panelHidden();
QWidget::hideEvent(e);
}
void ListPanel::panelVisible()
{
func->setPaused(false);
}
void ListPanel::panelHidden()
{
func->setPaused(true);
}
void ListPanel::slotPreviewJobStarted(KJob *job)
{
previewJob = job;
connect(job, SIGNAL(percent(KJob*,ulong)), SLOT(slotPreviewJobPercent(KJob*,ulong)));
connect(job, &KJob::result, this, &ListPanel::slotPreviewJobResult);
cancelProgressButton->setMaximumHeight(sidebarButton->height());
cancelProgressButton->show();
previewProgress->setValue(0);
previewProgress->setFormat(i18n("loading previews: %p%"));
previewProgress->setMaximumHeight(cancelProgressButton->height());
previewProgress->show();
}
void ListPanel::slotPreviewJobPercent(KJob* /*job*/, unsigned long percent)
{
previewProgress->setValue(percent);
}
void ListPanel::slotPreviewJobResult(KJob* /*job*/)
{
previewJob = nullptr;
previewProgress->hide();
if(!inlineRefreshJob)
cancelProgressButton->hide();
}
void ListPanel::slotRefreshJobStarted(KIO::Job* job)
{
// disable the parts of the panel we don't want touched
status->setEnabled(false);
urlNavigator->setEnabled(false);
cdRootButton->setEnabled(false);
cdHomeButton->setEnabled(false);
cdUpButton->setEnabled(false);
cdOtherButton->setEnabled(false);
sidebarButton->setEnabled(false);
if(sidebar)
sidebar->setEnabled(false);
bookmarksButton->setEnabled(false);
historyButton->setEnabled(false);
syncBrowseButton->setEnabled(false);
// connect to the job interface to provide in-panel refresh notification
connect(job, &KIO::Job::infoMessage, this, &ListPanel::inlineRefreshInfoMessage);
connect(job, SIGNAL(percent(KJob*,ulong)),
SLOT(inlineRefreshPercent(KJob*,ulong)));
connect(job, &KIO::Job::result, this, &ListPanel::inlineRefreshListResult);
inlineRefreshJob = job;
totals->setText(i18n(">> Reading..."));
cancelProgressButton->show();
}
void ListPanel::cancelProgress()
{
if (inlineRefreshJob) {
disconnect(inlineRefreshJob, nullptr, this, nullptr);
inlineRefreshJob->kill(KJob::EmitResult);
inlineRefreshListResult(nullptr);
}
if(previewJob) {
disconnect(previewJob, nullptr, this, nullptr);
previewJob->kill(KJob::EmitResult);
slotPreviewJobResult(nullptr);
}
}
void ListPanel::setNavigatorUrl(const QUrl &url)
{
_navigatorUrl = url;
urlNavigator->setLocationUrl(url);
}
void ListPanel::inlineRefreshPercent(KJob*, unsigned long perc)
{
QString msg = i18n(">> Reading: %1 % complete...", perc);
totals->setText(msg);
}
void ListPanel::inlineRefreshInfoMessage(KJob*, const QString &msg)
{
totals->setText(i18n(">> Reading: %1", msg));
}
void ListPanel::inlineRefreshListResult(KJob*)
{
if(inlineRefreshJob)
disconnect(inlineRefreshJob, nullptr, this, nullptr);
inlineRefreshJob = nullptr;
// reenable everything
status->setEnabled(true);
urlNavigator->setEnabled(true);
cdRootButton->setEnabled(true);
cdHomeButton->setEnabled(true);
cdUpButton->setEnabled(true);
cdOtherButton->setEnabled(true);
sidebarButton->setEnabled(true);
if(sidebar)
sidebar->setEnabled(true);
bookmarksButton->setEnabled(true);
historyButton->setEnabled(true);
syncBrowseButton->setEnabled(true);
if(!previewJob)
cancelProgressButton->hide();
}
void ListPanel::jumpBack()
{
func->openUrl(_jumpBackURL);
}
void ListPanel::setJumpBack(QUrl url)
{
_jumpBackURL = std::move(url);
}
void ListPanel::slotFilesystemError(const QString& msg)
{
slotRefreshColors();
fileSystemError->setText(i18n("Error: %1", msg));
fileSystemError->show();
}
void ListPanel::showButtonMenu(QToolButton *b)
{
if(this != ACTIVE_PANEL)
slotFocusOnMe();
if(b->isHidden())
b->menu()->exec(mapToGlobal(clientArea->pos()));
else
b->click();
}
void ListPanel::openBookmarks()
{
showButtonMenu(bookmarksButton);
}
void ListPanel::openHistory()
{
showButtonMenu(historyButton);
}
void ListPanel::openMedia()
{
showButtonMenu(mediaButton);
}
void ListPanel::rightclickMenu()
{
if (view->getCurrentKrViewItem())
popRightClickMenu(mapToGlobal(view->getCurrentKrViewItem()->itemRect().topLeft()));
}
void ListPanel::toggleSyncBrowse()
{
syncBrowseButton->toggle();
}
void ListPanel::editLocation()
{
urlNavigator->setUrlEditable(true);
urlNavigator->setFocus();
urlNavigator->editor()->lineEdit()->selectAll();
}
void ListPanel::showSearchBar()
{
searchBar->showBar(KrSearchBar::MODE_SEARCH);
}
void ListPanel::showSearchBarSelection()
{
searchBar->showBar(KrSearchBar::MODE_SELECT);
}
void ListPanel::showSearchBarFilter()
{
searchBar->showBar(KrSearchBar::MODE_FILTER);
}
void ListPanel::saveSettings(KConfigGroup cfg, bool saveHistory)
{
QUrl url = virtualPath();
url.setPassword(QString()); // make sure no password is saved
cfg.writeEntry("Url", url.toString());
cfg.writeEntry("Type", getType());
cfg.writeEntry("Properties", getProperties());
cfg.writeEntry("PinnedUrl", pinnedUrl().toString());
if(saveHistory)
func->history->save(KConfigGroup(&cfg, "History"));
view->saveSettings(KConfigGroup(&cfg, "View"));
// splitter/sidebar state
if (sidebar && !sidebar->isHidden()) {
sidebar->saveSettings(KConfigGroup(&cfg, "PanelPopup"));
cfg.writeEntry("PopupPosition", sidebarPosition());
cfg.writeEntry("SplitterSizes", sidebarSplitter->saveState());
cfg.writeEntry("PopupPage", sidebar->currentPage());
} else {
cfg.deleteEntry("PopupPosition");
cfg.deleteEntry("SplitterSizes");
cfg.deleteEntry("PopupPage");
}
}
void ListPanel::restoreSettings(KConfigGroup cfg)
{
changeType(cfg.readEntry("Type", defaultPanelType()));
view->restoreSettings(KConfigGroup(&cfg, "View"));
// "locked" property must be set after URL path is restored!
// This panel can be reused when loading a profile,
// so we reset its properties before calling openUrl().
setProperties(0);
_lastLocalPath = ROOT_DIR;
if(func->history->restore(KConfigGroup(&cfg, "History"))) {
func->refresh();
} else {
QUrl url(cfg.readEntry("Url", "invalid"));
if (!url.isValid())
url = QUrl::fromLocalFile(ROOT_DIR);
func->openUrl(url);
}
setJumpBack(func->history->currentUrl());
setProperties(cfg.readEntry("Properties", 0));
if (isPinned()) {
QUrl pinnedUrl(cfg.readEntry("PinnedUrl", "invalid"));
if (!pinnedUrl.isValid()) {
pinnedUrl = func->history->currentUrl();
}
func->openUrl(pinnedUrl);
setPinnedUrl(pinnedUrl);
}
if (cfg.hasKey("PopupPosition")) { // sidebar was visible, restore
toggleSidebar(); // create and show
sidebar->restoreSettings(KConfigGroup(&cfg, "PanelPopup"));
setSidebarPosition(cfg.readEntry("PopupPosition", 42 /* dummy */));
sidebarSplitter->restoreState(cfg.readEntry("SplitterSizes", QByteArray()));
sidebar->setCurrentPage(cfg.readEntry("PopupPage", 0));
}
}
void ListPanel::slotCurrentChanged(KrViewItem *item)
{
// update status bar
if (item)
krApp->statusBarUpdate(item->description());
// update sidebar; which panel to display on?
Sidebar *p;
if (sidebar && !sidebar->isHidden()) {
p = sidebar;
} else if(otherPanel()->gui->sidebar && !otherPanel()->gui->sidebar->isHidden()) {
p = otherPanel()->gui->sidebar;
} else {
return;
}
p->update(item ? func->files()->getFileItem(item->name()) : nullptr);
}
void ListPanel::otherPanelChanged()
{
func->syncURL = QUrl();
}
void ListPanel::getFocusCandidates(QVector &widgets)
{
if(urlNavigator->editor()->isVisible())
widgets << urlNavigator->editor();
if(view->widget()->isVisible())
widgets << view->widget();
if(sidebar && sidebar->isVisible())
widgets << sidebar;
}
void ListPanel::updateButtons()
{
backButton->setEnabled(func->history->canGoBack());
forwardButton->setEnabled(func->history->canGoForward());
historyButton->setEnabled(func->history->count() > 1);
cdRootButton->setEnabled(!virtualPath().matches(QUrl::fromLocalFile(ROOT_DIR),
QUrl::StripTrailingSlash));
cdUpButton->setEnabled(!func->files()->isRoot());
cdHomeButton->setEnabled(!func->atHome());
}
void ListPanel::newTab(KrViewItem *it)
{
if (!it)
return;
else if (it->name() == "..") {
newTab(KIO::upUrl(virtualPath()), true);
} else if (func->getFileItem(it)->isDir()) {
QUrl url = virtualPath();
url = url.adjusted(QUrl::StripTrailingSlash);
url.setPath(url.path() + '/' + (it->name()));
newTab(url, true);
}
}
void ListPanel::newTab(const QUrl &url, bool nextToThis)
{
_manager->newTab(url, nextToThis ? this : nullptr);
}
void ListPanel::slotNavigatorUrlChanged(const QUrl &url)
{
if (url == _navigatorUrl)
return; // this is the URL we just set ourself
if (!isNavigatorEditModeSet()) {
urlNavigator->setUrlEditable(false);
}
func->openUrl(KrServices::escapeFileUrl(url), QString(), true);
}
void ListPanel::resetNavigatorMode()
{
if (isNavigatorEditModeSet())
return;
// set to "navigate" mode if url wasn't changed
if (urlNavigator->uncommittedUrl().matches(virtualPath(), QUrl::StripTrailingSlash)) {
// NOTE: this also sets focus to the navigator
urlNavigator->setUrlEditable(false);
slotFocusOnMe();
}
}
int ListPanel::sidebarPosition() const
{
int pos = sidebarSplitter->orientation() == Qt::Vertical ? 1 : 0;
return pos + (qobject_cast(sidebarSplitter->widget(0)) == NULL ? 2 : 0);
}
void ListPanel::setSidebarPosition(int pos)
{
sidebarSplitter->setOrientation(pos % 2 == 0 ? Qt::Horizontal : Qt::Vertical);
if ((pos < 2) != (qobject_cast(sidebarSplitter->widget(0)) != NULL)) {
sidebarSplitter->insertWidget(0, sidebarSplitter->widget(1)); // swapping widgets in splitter
}
}
void ListPanel::connectQuickSizeCalculator(SizeCalculator *sizeCalculator)
{
connect(sizeCalculator, &SizeCalculator::started, this, [=]() {
quickSizeCalcProgress->reset();
quickSizeCalcProgress->show();
cancelQuickSizeCalcButton->show();
});
connect(cancelQuickSizeCalcButton, &QToolButton::clicked, sizeCalculator, &SizeCalculator::cancel);
connect(sizeCalculator, &SizeCalculator::progressChanged, quickSizeCalcProgress, &QProgressBar::setValue);
connect(sizeCalculator, &SizeCalculator::finished, this, [=]() {
cancelQuickSizeCalcButton->hide();
quickSizeCalcProgress->hide();
});
}