diff --git a/ChangeLog b/ChangeLog index cc66c026..da8811aa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,1948 +1,1948 @@ 2.7.1 "Peace of Mind" ===================== ADDED: Default shortcut for quick selection mode = Ctrl+Shift+S FIXED: [ 150247 ] When calculating occupied space of ".." , krusader selects all directories FIXED: [ 282069 ] Bad default in the New Text File dialog FIXED: [ 372023 ] ISO files listing/extracting broken FIXED: [ 383567 ] Details section is empty in 'Do not know which files to compare.' window FIXED: [ 391946 ] Default mode in 'Find in folder' is not preserved FIXED: [ 394896 ] Files fed to listbox (and all other files in virt://) cannot be deleted FIXED: [ 394939 ] Enter key not working when cursor in search bar FIXED: [ 395285 ] The quicksearch bar is still opened after deleting a file FIXED: [ 396652 ] In the Manage User Actions dialog: the tab order is not the expected one 2.7.0 "Peace of Mind" ===================== ADDED: Ability to ignore defined directories from results in Search dialog ADDED: Bookmark quick search (type symbols in bookmark menu to activate) ADDED: Cache calculated directory sizes (last 1000 entries; not auto-updated) ADDED: Command line option "-d" to activate debug message output ADDED: New detailed tooltip for name column in panel view ADDED: Per-icon fallback logic to support custom icon themes ADDED: Popup file tree view - new "show/hide hidden folders" feature ADDED: Popup file tree view - new "start from closest Place" feature ADDED: Popup file tree view - new "start from current directory" feature ADDED: Popup file tree view - support for dropping to panel ADDED: Tab pinning - pinned tab is a locked tab with temporarily changeable address ADDED: User setting to disable border decoration for current item in inactive panel CHANGED: Default Multi Rename shortcut changed (Shift+F9 -> Shift+F2) to align with the default Rename shortcut (F2) CHANGED: Show "0 Bytes" for calculated but empty directory sizes FIXED: Activation of a found item with hash symbol in URL inside search dialog FIXED: Bug with no-match indication when only the current item matches in Quick Search FIXED: Panel columns may become invisible when settings are restored from config FIXED: Regression in "Open in new tab" from popup menu FIXED: When pressing a New Tab button the corresponding Panel is not selected FIXED: [ 108023 ] Support "Sort by..." by keyboard shortcuts: CTRL+[1-4] FIXED: [ 173655 ] Added changed and access time in detailed view FIXED: [ 195749 ] Ctrl+Tab don't switch over edited files FIXED: [ 267719 ] bookmarks shortcuts lost after opening bookmark manager FIXED: [ 267756 ] Rename tab or add prefix to tab label FIXED: [ 267765 ] Add delay before switching tabs with mouse-over FIXED: [ 270756 ] Add option to hide tab bar FIXED: [ 272108 ] Support for more KIO slaves in Network Connection FIXED: [ 274404 ] Copy file dialog - include file name in the path FIXED: [ 280270 ] Saved Locked Tabs each create extra tab on start FIXED: [ 308351 ] Cannot run MountMan from menu FIXED: [ 328928 ] Add text word wrap for all tooltips FIXED: [ 363437 ] Edit field looses focus after closing one of Editor's/Viewer's tab FIXED: [ 372964 ] At least one Oxygen icon in Krusader is not correctly seen (using Kubuntu 16.04) FIXED: [ 372966 ] Some icons are not seen using a plain Ubuntu (not Kubuntu) 16.04 FIXED: [ 376372 ] KrViewer window loses focus on closing tabs FIXED: [ 378593 ] Problems copying the names of files with apostrophes FIXED: [ 378839 ] Krusader freezes when asterisk ("*") is pressed in detailed view FIXED: [ 379170 ] 2.6.0 - Regression: "Spacebar calculates disk space" feature is missing FIXED: [ 379459 ] Krusader no longer minimizes to system tray FIXED: [ 380421 ] In some cases the vertical "Popup panel" has a very high minimum width (caused by Viewer) FIXED: [ 381179 ] Shortcut conflict: SHIFT+DEL used for cut and alternative delete FIXED: [ 383372 ] Toggle Fullscreen Embedded Terminal bug FIXED: [ 383544 ] Unable to create new folder/file if '..' item is selected in current folder FIXED: [ 383558 ] Errors after approving or canceling Useractions -> System -> Backup current for '..' panel item FIXED: [ 386217 ] Pressing Arrow keys behaves incorrectly in quicksearch FIXED: [ 386314 ] Install to a custom location doesn't work correctly FIXED: [ 388266 ] Closing calculate occupied space window does not abort the calculation FIXED: [ 389413 ] Krusader crashes when entering directories with read errors FIXED: [ 389869 ] After deletion of selected files current item moves one down FIXED: [ 390732 ] Cannot add Krusader to favorites in Gnome Dock FIXED: [ 390990 ] Current item selection is lost after exiting from tar archives FIXED: [ 390991 ] bookmark buttons on a toolbar disappear after closing Bookmark Editor FIXED: [ 390994 ] [dev] Compiler warnings with gcc-6.4.0 FIXED: [ 392218 ] Allow scrolling during filesystem changes in current directory 2.6.0 "Stiff Challenges" ========================= FIXED: [ 335993 ] save checksum does not work as expected FIXED: [ 375639 ] Allow typing special characters (e.g. with accent or acute) in search bar FIXED: [ 328068 ] Send SIGINT before own input command to embedded terminal FIXED: [ 375135 ] segfault on viewing html files with Generic viewer FIXED: [ 269820 ] Fullscreen terminal emulator shows empty window when terminal emulator was minimized FIXED: [ 374813 ] Multi rename with KRename does not work when selecting non-local files/folders (ftp, smb, virt, ...) FIXED: [ 309300 ] Esc as the default shortcut of "Set Focus to The Panel" is problematic for the embedded terminal FIXED: [ 374175 ] wrong date format parsing using date filter in search dialog FIXED: [ 293370 ] After a file deletion old file name is still shown in the status bar FIXED: [ 374322 ] Visually indicated shortcut ALT+o not working in copy/F5 and move/F6 KrDialog FIXED: [ 374238 ] Handle left/right arrow key press in brief view (previously filtered by search bar). FIXED: when dragged from list panel use correct drop action if invoked with modifier keys FIXED: added save/restore or toolbar positions in mainwindow FIXED: [ 372231 ] Added KDE's service actions again to right-click popup menu ADDED: new undo action to job manager for undoing KIO job operations FIXED: [ 372067 ] Wrong path when showing non local files and folders from search dialog in panel ADDED: job manager as replacement for queue manager. Part of cleaning VFS FIXED: [ 365105 ] Workaround for bug in KF5+QSystemTrayIcon ADDED: Reimplementation of "minimize to system tray" feature. FIXED: Krusader does not show the new file in a directory that is a symbolic link until is not refresh directory FIXED: Wrong window position after restart in fluxbox FIXED: Error on opening file folder after clicking on any file result of a remote search (FTP / smb) FIXED: Terminal opens in full window FIXED: copy location/path bar (feature request) FIXED: krusader cannot calculate size of remote directory (ftp or sftp) FIXED: Some files with weird characters (non UTF) cause krusader to miscalculate folder size FIXED: No way to focus fullscreen embedded terminal emulator. FIXED: Don't delete first letter in "new folder" dialog (F7) FIXED: Use Shift+Delete for delete or move selected files to trash FIXED: Dialog "File" -> "Verify checksum" improvement FIXED: Option for show copy/move progress in dialog (not in notifications) FIXED: Documents suddenly open as archives CHANGED: Avoiding root mode CHANGED: Duplicated tab should not be locked CHANGED: New PagePanel: do not refresh until panel becomes visible CHANGED: Change suggested command for "edit as root" user action to a more secure alternative CHANGED: Do not configure kdesu path and remove kdesudo support again CHANGED: Panel: Do not select .. in a filtered view if there are other entries CHANGED: Duplicate tab settings when duplicating tabs CHANGED: Some fixes and simpifying startup settings. 2.5.0 "Clear Skies" ========================= (this list is incomplete. Please refer to Git log and finished tasks listed at https://phabricator.kde.org/project/board/79 ) ADDED: actions: Select files with the same name / extension CHANGED: disabled build of synchronizer by default, since it is unmaintained - build togglable with cmake variable -DENABLE_SYNCHRONIZER=true|false FIXED: [ 143927 ] file search: "s" accelerator is doubled - new shortcut for "Search in" is ALT+h FIXED: [ 308386 ] Duplicate shortcut on Search window - new shortcut for "Remote content search" is ALT+n FIXED: [ 206926 ] Search doesn't work in sftp session (it returns too many results) FIXED: [ 269542 ] Krusader search - Containing text still used when disabled FIXED: [ 324737 ] symlinks with a target path length of over 255 do not work FIXED: [ 189943 ] toolbar position settings are not remembered FIXED: [ 316031 ] crash when loading previews FIXED: [ 238672 ] When saving checksums fails, they are lost. No 2nd chance to save elsewhere. FIXED: [ 315764 ] "application/x-source-rpm" isn't linked to krarc protocol by default FIXED: [ 294816 ] Krusader needs to restart to apply new color scheme to panel FIXED: [ 308727 ] external editor command isn't properly parsed FIXED: [ 304233 ] empty main view on startup FIXED: [ 315856 ] main view splitter sizes are not restored FIXED: [ 248691 ] incorrect layout / wrong buttons in queue manager FIXED: [ 315357 ] krarc silently fails to display contents of some zip files zip files containing paths with "." as a path component are still not handled, but now krarc reports an error instead silently failing FIXED: [ 310722 ] viewer crash when opening file FIXED: search result view always displays owner and group as "root" (may not work for remote search) FIXED: [ 217711 ] directory chooser dialog does not allow to choose a directory FIXED: [ 309119 ] Wrong "New directory" dialog behavior: can't clear all typed text FIXED: [ 309159 ] Crash in video files preview on F3 FIXED: [ 310191 ] krusader still installs locolor icons FIXED: [ 317510 ] icon-size-and-directory-name-mismatch 2.4.0-beta3 "Single Step" ========================= FIXED: crash when trying to open/(un)mount ejectable device via media menu 2.4.0-beta2 "Giant Steps" ========================= ADDED: options: Panel > Media Menu > Show Mount Path - Show File Sytem Type + Show File System Type Show Size (Always | When Device has no Label | Never) ADDED: pressing CTRL+RETURN when media menu is open (un)mounts the highlighted device ADDED: action: Bring Main Window to Top (global shortcut possible) ADDED: option: General > Viewer/Editor > Viewer > Use Okteta As Hex Viewer (default: on) ADDED: option: Archives > krarc > Enable Write Support ADDED: splitter option: Overwrite files without confirmation ADDED: action: Go to Other Panel's Directory - shortcut: CTRL+= CHANGED: krarc write support is disabled by default CHANGED: user action manager starts with the "Basic Properties" tab active CHANGED: detailed view: "Automatically Resize Columns" setting is remembered FIXED: [ 306472 ] Krusader fails to build when using clang as compiler - thanks to Jekyll Wu FIXED: [ 308193 ] Krusader closes the search window after file editing - thanks to Alexander FIXED: pressing the context menu key when the media menu is shown opens the context menu for a random item instead of the current FIXED: [ 300514 ] no warning if terminal emulator can't be created FIXED: [ 303209 ] passwords for remote connections are stored in config NOTE: passwords already stored in krusaderrc may still be left FIXED: [ 280946 ] viewer: incorrect tab's file names when moving tabs FIXED: user actions: "run in the embedded terminal emulator" setting is not saved FIXED: mountman: mount list is not refreshed if /etc/mtab is a symlink to /proc/mounts FIXED: [ 148866 ] create new directory: spaces are stripped out FIXED: [ 305069 ] list panel is not autoscrolled to the cursor (in brief view) FIXED: [ 173690 ] file ACLs are not displayed correctly in properties dialog - thanks to Eugeny Shkrigunov FIXED: It is impossible to select a non-default folder in the search dialog FIXED: splitter overwrites files without confirmation FIXED: [ 274483 ] crash when selecting items from popup-menu FIXED: [ 285778 ] View or edit files doesn't work FIXED: viewer tries to load obsolete libkhexedit2 part as hex viewer - use okteta part instead FIXED: crash when trying to view files with embedded KOrganizer part (avoids KOrganizer bug 205713) FIXED: "apply settings to other tab" action doesn't apply icon size FIXED: [ 198996 ] crash when closing viewer FIXED: [ 294501 ] toolbar "equal" has no shortcut FIXED: [ 108892 ] "Combine Files" overwrites existing target file without confirmation FIXED: Queue manager closed when any of the queues finished FIXED: [ 300922 ] crash when pause sftp transfer via queue on quit FIXED: [ 271265 ] krusader should search for kdesu executable in /usr/lib{64,}/kde4/libexec/ - thanks to Anssi Hannula / Ahmad Samir FIXED: [ 290304 ] Panel option "always sort dirs by name" doesn't work FIXED: [ 297926 ] state of the menu item 'Show hidden files' and the current setting is different FIXED: [ 234296 ] crash when closing disk usage view FIXED: [ 296718 ] execution of files that have spaces in their path doesn't work anymore FIXED: [ 294618 ] using "open with" on video files causes their thumbnails to be created, even when not needed FIXED: root mode action doesn't work if a panel url contains spaces FIXED: relative url completion in address-bar only works in home dir FIXED: [ 242566 ] Cannot F3-View .vcf vCard files FIXED: Root action (which opens the root dir of the local filesystem) is disabled in the root dir of nonlocal filesystems FIXED: when cutting to clipboard from virt:/ the virtual entries are immediately removed FIXED: Unselecting files before copy/move operation doesn't work for copy&paste FIXED: [ 277259 ] Unselecting files before copy/move operation doesn't work in the same panel this also fixes the selection of the other panel being cleared instead FIXED: [ 276310 ] crash when trying to delete already deleted file FIXED: [ 277578 ] Crash on cancelling calculation of occupied space on smb share FIXED: krusader hangs for some time when opening a bz2(and possibly gzip)-compressed archive FIXED: loading defaults on the Panel page in Konfigurator has no effect FIXED: changes to "Show new/close tab buttons" don't take effect immediately FIXED: when options requiring a gui restart are changed, the panel history is lost FIXED: [ 277838 ] Swap Panels no longer works 2.4.0-beta1 "Migration" ======================= ADDED: option: Panel > Status/Totalsbar > Show space information ADDED: Konfigurator: reset button ADDED: option: Startup > User Interface > Show actions toolbar ADDED: options: Panel > Layout: "Compact", "Classic" ADDED: mountman gui option: Show only removable devices ADDED: tabs have close buttons ADDED: reset button for filter dialog ADDED: option: Panel > Operation > Filter dialog remembers settings ADDED: tabs can be dragged to the other side ADDED: action: Move Current Tab to Other Side - shortcut: CTRL + SHIFT + O ADDED: view: iconsizes 64, 128, 256 ADDED: history is saved/restored ADDED: action: Restore Selection ADDED: option: Panel > Operation > Unselect files before copy/move ADDED: support for xz archives CHANGED: new default panel layout CHANGED: option: Panel > View > Show previews -> Show previews by default CHANGED: removed option "Show free disk space in the Totalsbar" since that setting is controlled by the layout chosen in Panel > Layout CHANGED: removed option "Preserve Attributes" - KIO always preserves Attributes CHANGED: option: Panel > Filelist icon size -> Default icon size CHANGED: quickfilter follows case sensivity setting of quicksearch CHANGED: quickfilter expands wildcards CHANGED: duplicate tab / open in new tab: create the new tab next to the current one. CHANGED: filter settings are saved/restored individually for each tab. CHANGED: filter settings are remembered when changing view type CHANGED: All view settings are saved/restored individually for each tab. FIXED: [ 3222819 (sf.net) ] Alt-Enter is not showing selected files' properties FIXED: [ 274083 ] Search results list shows wrong extension when dir path has a dot in it FIXED: [ 262761 ] krusader crashed on viewing text file with internal viewer this was probably already fixed in 2.3.0-beta1 FIXED: [ 229489 ] Seg fault moving ISO image files from USB Flash drive to USB SATA HD - thanks to Anssi Hannula FIXED: mountman gui might add the same mountpoint to the list multiple times FIXED: [ 3044425 (sf.net) ] Desktop freeze when opening a context menu FIXED: [ 217203 ] Krusader crashed when accessing sftp after resume from sleep FIXED: [ 243716, 270605, 270588 ] crash when moving files FIXED: [ 256794 ] crash when file is deleted while a preview is being loaded for it (and it is the only file for which a preview is being loaded) FIXED: [ 274732 ] Weird functionality after "directory doesn't exist" FIXED: [ 3216624 (sf.net) ] Krusader saves newly created files with incorrect permissions FIXED: [ 2773302 (sf.net) ] krarc can't handle brackets in file paths inside ZIP archive FIXED: [ 272876, 274269 ] crash when refreshing view FIXED: [ 3191155 (sf.net) ] Moving a symbolic link changes attributes of target file FIXED: [ 2998795 (sf.net) ] "Show actions toolbar" setting is not saved FIXED: Url commandline argument opens a new tab instead of switching to an existing one FIXED: root mode action does not work with newer versions of kdesu, thanks to CyberCastle FIXED: switching tabs sometimes doesn't switch the panel FIXED: [ 3004510 (sf.net) ] Double-clicking executables start in ~/Documents folder FIXED: [ 2996188 (sf.net) ] relative path for custom folder icon doesn't work FIXED: [ 2915020 (sf.net) ] wrong icon for directory symlink FIXED: when switching tabs, sometimes the new tab isn't set active FIXED: [ 263253 ] View displays wrong total size in some circumstances. FIXED in 2.3.0-beta1, but not recorded in Changelog at release time: [ 259495 ] crash when closing search dialog ---------------------------------------------------------------- NOTE: the default bug tracker is now bugs.kde.org (was sf.net) ---------------------------------------------------------------- 2.3.0-beta1 "New Horizons" ========================== ADDED: option: Panel > General > Flat Origin Bar ADDED: option: Panel > Buttons > Toolbar buttons have icons ADDED: listpanel buttons: Back, Forward ADDED: options: Panel > Layout > Layout / Frame Color / Frame Shape / Frame Shadow ADDED: QuickFilter - default shortcut: CTRL+i ADDED: option: Panel > View > Show directories first ADDED: actions: Back/Forward in history ADDED: action: Set Focus to the Panel - shortcut: ESC ADDED: actions: Move Focus Up/Down - shortcut: CTRL+SHIFT+Up/Down ADDED: selection dialog option: Apply selection to directories ADDED: option: Startup > User Interface > Update default panel settings ADDED: dbus interface: org.krusader.Instance.openUrl(QString url) ADDED: search dialog > feed to listbox: search parameters are saved as metadata in the virtual fs and displayed in panel's statusbar ADDED: filter option: Apply filter to directories ADDED: action: view > Apply settings to other tabs ADDED: action: view > Save settings as default (for new instances of this view type) ADDED: option: Panel > View > Locale aware sorting CHANGED: Media Button shows Solid Icon for currently opened device CHANGED: Removed options Panel > General > Status/Totalsbar > Statusbar Frame / Statusbar Background / Show Statusbar / Show Totalsbar. They are customizable in layout.xml. CHANGED: Use KrView for displaying search results, which is much faster than the previously used QTreeWidget. CHANGED: Removed default shortcuts for the Left/Right Bookmarks actions, as they conflict with the Back/Forward actions. CHANGED: After failed refresh, only focus location bar if the url was entered manually. CHANGED: Removed default shortcut for 'Cancel Refresh of View' as it conflicts with the 'Set Focus to the Panel' action. Unless a shortcut is assigned manually, ESC cancels the refresh when the panel is focused. CHANGED: Konfigurator: "apply" takes effect immediately. CHANGED: Url commandline argument: if there is already a tab open with that url, it is activated, otherwise a new tab is opened in the active panel. FIXED: When trying to close Konfigurator but canceling the "Apply changes ?" dialog, Konfigurator it is closed anyway. FIXED: [ 3073211 ] Wrong quoting when opening file in external editor FIXED: [ 3059457 ] new panel uses default columns instead of configured ones FIXED: [ 2898151 ] also in view-mode (F3) possible to edit, thanks to Kevin Kofler FIXED: panelpopup viewer: error messageboxes when file cannot be displayed FIXED: [ 2981303 ] Viewer/editor unused submenu Game, thanks to Kevin Kofler FIXED: regression making single-click mode unusable, thanks to Kevin Kofler FIXED: [ 3003338 ] Rename selects extension regression, thanks to Kevin Kofler FIXED: [ 2980201 ] KrViewer doesn't handle binary files well (this fix works only for local files !) FIXED: "sort by" useractions change sorting direction randomly FIXED: [ 3028599 ] Sorting criteria is not saved at exit FIXED: [ 2949337 ] splitter ui bug FIXED: [ 2843749 ] view item is deselected when updated FIXED: [ 268037 (bugs.kde.org) ] brief view: mouse wheel doesn't work FIXED: brief view: mouse selection doesn't work in columns > columns per page FIXED: selecting a bigger number of files is very slow FIXED: [ 2969403 ] KrViewer shows old file content if file is overwritten, thanks to Kevin Kofler FIXED: [ 246424 (bugs.kde.org) ] krusader tries to load WHOLE big file into memory on F3 FIXED: [ 2154760 ] Krusader erases files when opening for editing FIXED: changing sort direction is slow FIXED: [ 3015094 ] krusader doesn't exit at closing the application FIXED: right clicking on media button doesn't work FIXED: tabs were no longer movable, thanks to Victor (kernel_daemon) FIXED: 3 valgrind fixes by Alexander Stein FIXED: viewer would show empty menus, thanks to CtHx FIXED: crash when changing view type 2.2.0-beta1 "DeKade" ==================== ADDED: option: Panel > General > Tabs > Show new/close tab buttons ADDED: options: Panel > Buttons > Show Media/History/Bookmarks Button ADDED: options: Panel > General > Status/Totalsbar settings > Show Statusbar, Show Totalsbar, Show Size In Bytes, Show free disk space in the Totalsbar ADDED: option: Look&Feel > Quicksearch > "Up/Down cancels Quicksearch" ADDED: dbus interface: org.krusader.PanelManager.newTab(QString url) / newTabs(QStringList) ADDED: url command-line argument ADDED: action "Show View Options Menu" ADDED: detailed view context-menu option "Automatically Resize Columns" ADDED: action "cancel refresh" triggered by ESC by default ADDED: change icon size individually per view ADDED: thumbnails - toggleable by mainmenu > view > Show Previews ADDED: 128x128 pixel versions of the application icon, needed by Mac OS X ADDED: Konfigurator options: Look&Feel > Panel > Status/Totalsbar settings > Draw frame / Fill background ADDED: Konfigurator option: Colors > Colors > Other > Statusbar ADDED: Konfigurator option: Look&Feel > Panel > Panel layout > Quicksearch position / Tab Bar position ADDED: buttons "(un)mount" and "eject" in mountman gui ADDED: KMountMan::removable(), KMountMan::networkFilesystem() CHANGED: reorganize Konfigurator: "Look & Feel" page becomes "Panel" / move several options to new places CHANGED: when open/refresh of a dir fails, don't annoy the user with a message box, but display the error embedded into the panel CHANGED: icon size, icons/previews on/off are set separately per view type CHANGED: dim icons in unfocused panel (if dim colors is activated) CHANGED: mountman gui: retrieve icons from Solid CHANGED: mountman gui: change mount check interval from 3000 to 500 ms CHANGED: mountman gui: current selection persists refresh of mountlist, mountlist is focused after refresh CHANGED: dont't execute a process if the correct working dir cannot be set CHANGED: dont't retrieve working dir of the cmdline from the label which might get truncated - store it in a string instead FIXED: brief view: clicking on the space below a column selects the first item of the next column FIXED: if refresh has failed, the origin bar is focused even if the panel is not active FIXED: if the path of an inactive panel changes, the embedded cmdline is set to that path FIXED: useraction commands, or those entered in the embedded cmdline, are sometimes not executed in the correct working dir FIXED: when multiple commands are entered in the embedded cmdline or a useraction, and execution mode is set to terminal, only the first command is executed in a new terminal and the others in the same terminal (if any) as krusader FIXED: commands entered via command line are mixed up with history FIXED: [ 2790819, 2892768, 2915192 ] Can't resize columns properly FIXED: disk usage dialog layout problem FIXED: [ 2907607 ] crash while closing FIXED: if a panel is focused by clicking on the header, the colors/actions are not updated FIXED: mountman: unmounting is not possible if currently opened dir is below the mountpoint FIXED: [ 2860400 ] Drag'n'drop to kmail broken FIXED: [ 2904850 ] panels are not repainted FIXED: deadlock when trying to display error message after failed mount FIXED: [ 2858133 ] wrong background color in listviews 2.1.0-beta1 "Rusty Clutch" ========================== ADDED: file regex in quick search, thanks to GregC ADDED: lister: a fast text/hex viewer for Krusader ADDED: service menu, thanks to Tomasz Kalkosinski ADDED: queued packing / unpacking ADDED: lock tabs, close inactive tabs, close duplicated tabs ADDED: better trash integration CHANGED: the packer/unpacker/archive tester are job based now CHANGED: the old views were replaced by the interviews FIXED: [ 2857663 ] deadlock when trying to display error message after failed unmount FIXED: problem with autorefresh in the new interviews FIXED: [ 2609505 ] problem with directory refresh FIXED: [ 2793916 ] KHistoryComboBox content can change the window width FIXED: [ 2805624 ] ctrl-left/right arrow with locked tabs on the other panel FIXED: panels sometimes lose focus FIXED: directory compare modes don't work FIXED: [ 2609483 ] unpacking to directories with international characters 2.0.0 "Mars Pathfinder" ======================= ADDED: [ 2466695 ] Archive dialog now remembers Compression level FIXED: [ 2671702 ] wrong file size for files with currupt encoding FIXED: sync-browse fails if the name contains spaces FIXED: Compile error with Qt-4.5 (patch by Marc Schiffbauer) FIXED: tab change at dragging doesn't work FIXED: [ 2543170 ] Crashes on mouse wheel in brief view FIXED: [ 2553396 ] Krusader exits after closing KrViewer FIXED: [ 2563664 ] Krusader always trashes (not deletes) files FIXED: tar.bz2 doesn't always detected automatically FIXED: panel freezes if the inactive path is invalid FIXED: problem when splitter sizes are 0, 0 FIXED: iso protocol problems with images bigger than 4GByte FIXED: Windows: iso protocol works well now FIXED: Windows: slow start FIXED: Windows: the root directory is C:\ FIXED: MountMan saves its last size FIXED: [ 1535954 ] krviewer hex view endian dependent FIXED: [ 1550740 ] Wrong placeholder replacement FIXED: [ 1988452 ] "Open the popup panel" button hides files from the file pane FIXED: [ 1965317 ] Return to panel when pressing Escape in kcmdline/panel path FIXED: [ 2265338 ] Copy from rar files broken FIXED: [ 2484665 ] Crash when deleting modified user action FIXED: MountMan: mount/umount/eject uses Solid if possible FIXED: [ 2381505 ] Ctrl+Shift+D in editor (KWrite) not work FIXED: Krusader fails to edit files containing international chars with Shift+F4 CHANGED: Changed default Alt+letter shortcuts because of [ 2564684 ]. See the details in SVNNEWS CHANGED: Initial Konfigurator size is now 900x680 ARCH: view properties for detailed/brief/interviews are merged into one I18N: Updated Italian translation (thanks Giuseppe Bordoni) I18N: Updated French translation (thanks to Henry-Nicolas Tourneur and Stanislas Zeller) I18N: Updated Catalan translation (thanks to Joaquim Perez) I18N: Updated Slovak translation (thanks to Zdenko Podobný and Ondrej Pačay "Yogi" ) I18N: Updated Hungarian translation I18N: Updated Slovenian translation I18N: Updated Swedish translation (thanks Peter Landgren) REMOVED: CVSNEWS, SVNNEWS is the successor (extension to this ChangeLog) 2.0.0-beta2 "Space Odyssey" =========================== ADDED: shortcuts: copy by queue (SHIFT+F5), move by queue (SHIFT+F6) ADDED: Krusader support for tar.lzma (KDE's tar protocol doesn't support it yet) ADDED: Possibility to choose one of five sorting methods (thanks to Jacek Jaworski) ADDED: compare by content for search / locate ADDED: New mouse selection mode ADDED: Evolution can be used as the default e-mail sender (thanks to Agustin Henze) ADDED: enqueue operation for copy / move ADDED: Konfigurator mouse selection mode: Possibility to select a predefined mode and change a detail. ADDED: [ 1704953 ] highlight quick search match ADDED: Useractions: added checkbox "enabled" and run mode option "Run in embedded terminal emulator" ADDED: the description of a dir contains its size if it is known ARCH: MediaButton uses Solid for medium detection ARCH: QuickSearch is moved to KrView from Detailed/Brief views ARCH: Keyboard handling is moved to KrView from Detailed/Brief views FIXED: version number under Windows FIXED: the Win shortcuts doesn't work in the UserAction examples FIXED: [ 2091314 ] krviewer does not remember its window size FIXED: [ 2219012 ] user action icons are not saved FIXED: [ 2116505 ] Total Commander selection behavior broken FIXED: [ 2227421 ] Mount cdrom no longer needs root permission FIXED: Krusader steps into wrong directory, when a file changes in an inactive tab FIXED: When neither "kompare", "kdiff3" nor "xxdiff" in PATH, the program set in "diff utility" was ignored. Under Windows, look for them with ".exe" suffix FIXED: [ 2243628 ] Synchronizer overlooks files FIXED: [ 2202522 ] newly created hidden files are shown for a short time FIXED: calc space doesn't work on remote file systems FIXED: searcher doesn't start because of corrupt config files FIXED: Konfigurator doesn't detect every mimetype for "zip" files FIXED: Konfigurator keeps its original size FIXED: Konfigurator has scrollbars if necessary. FIXED: [ 2027518 ] Does not build with -DBUILD_SHARED_LIBS:BOOL=ON (thanks to Funda Wang) FIXED: [ 2041732 ] Krusader 2.0.0 beta1 missing title bar under Compiz (thanks to Danny Baumann for the patch) FIXED: [ 2023623 ] Krusader kept running after closing the main window FIXED: [ 1671543 ] horizontal/vertical mode fix in the Window menu FIXED: [ 1845105 ] mimetype magic can be disabled again FIXED: [ 2062651 ] Ctrl+Up selects the URL in the origin editbox FIXED: [ 1988893 ] konsole is started in a wrong directory please set "konsole --workdir %d" for the terminal (Konfigurator) as Krusader won't fix your config automatically FIXED: KDE4 workaround: no colors for synchronizer FIXED: MediaButton doesn't notice unmounted pen drives+CD/DVD-s FIXED: "local network" bookmark didn't work FIXED: bookmark menu was not always closed after opening a bookmark FIXED: [ 2017011 ] Crash when changing the Qt theme FIXED: icons for symlinks are corrupted FIXED: [ 2023599 ] start root mode Krusader works again (thanks to gladiac) FIXED: [ 1980765 ] error at creating ../dir directory FIXED: [ 2014344 ] CTRL-C (copy) does not work in internal editor FIXED: Viewing directories are disabled to prevent KDE 4 crash FIXED: [Debian: 492955] useraction's availability section was dumped to "command" element. (thanks Iván Forcada Atienza) FIXED: Do not duplicate menu entries in UserAction menu while still not crashing when configuring toolbars. I18N: Added Korean translation (thanks Seongnam Jee) I18N: Updated Bulgarian translation (thanks Milen Ivanov) I18N: Updated German translation I18N: Updated Dutch translation I18N: Updated Czech translation I18N: Updated Ukrainian translation (thanks Yuri Chornoivan) I18N: Updated Slovenian translation (thanks Matej Urbancic) 2.0.0-beta1 "Phoenix Egg" ========================= ADDED: [ 1962519 ] searching by regexp ADDED: [ 1172426 ] loading user defined folder icons (can be turned off) ADDED: Posibility to remove default useractions ADDED: Thunderbird can be used as the default e-mail sender ADDED: Sending more than one file in e-mail is possible ADDED: Submenus for categories in UserAction menu and context menu ADDED: Character encoding for content search ADDED: Select remote encoding for krarc ADDED: New synchronizer shortcuts for modifying the synchronizer tasks ARCH: Ported to KDE4! ARCH: Removed all dependencies to the Qt3 support libs ARCH: Codebase in sync with last KDE3 release (krusader-1.90.0) ARCH: Added experimental support for the Windows platform FIXED: [ 1506205 ] krviewer crash at urls with non-existing redirection FIXED: [ 1854760 ] [ 1516619 ] inconsistent search FIXED: [ 1920084 ] kdiff3 is allowed to handle remote URL-s FIXED: [ 1638817 ] toolbar loses orientation when modified FIXED: [ 1578310 ] can't open ISO image by symbolic link FIXED: Enabled KRename on remote files FIXED: Right arrow in the detailed view can now go even inside iso files FIXED: Konfigurator: Dependency lists are now scrollable FIXED: Filter: Don't list comments in user/group chooser FIXED: Current working directory not returned in populateVfsList FIXED: Eject DVD with right-click menu FIXED: Actionman, sometimes the command field is empty (the text was rolled) FIXED: GCC 4.3: missing #includes (thanks to Fathi Boudra) FIXED: Searcher doesn't always find content in binary files FIXED: [ 1619452 ] Profile doesn't save status of sync-browse mode FIXED: [ 1681270 ] right clicking pops context menu immediately FIXED: [ 1645179 ] shortcut keys are not sent to the terminal FIXED: [ 1736496 ] always sort dirs by name not working I18N: Merged krarc.pot and iso.pot into krusader.pot (thanks Vaclav Juza) I18N: Updated Hungarian translation I18N: Updated French translation (thanks Henry Nicolas) I18N: Fixed [ 1725003 ] bad spanish translation I18N: Fixed untranslatable strings (thanks Vaclav Juza) I18N: Updated Ukrainian translation (thanks Yuri Chornoivan) I18N: Updated Catalan translation (thanks Joaquim Perez) I18N: Updated French translation (thanks Tourneur Henry-Nicolas) REMOVED: Clear location button (in KDE4 it is part of the KLineEdit) (thanks Fathi Boudra) 1.90.0 "Power Stone" ==================== ADDED: Useraction, Unpack multiple zip archives (thanks Ernest Beinrohr [OERNii] and Jonas) ADDED: Useraction, uuencode and uudecode (thanks Andrew Svet) ADDED: Useraction, Unpack current tar.7z ADDED: Useraction, tar.7z selected files ADDED: Useraction, Unpack current tar.lzma ADDED: Useraction, tar.lzma selected files ADDED: Useraction, Unpack current lzma ADDED: Useraction, Lzma current file ADDED: Useraction, 7zip current (thanks Vaclav Juza) ADDED: Javascript useraction, select from file ADDED: Useraction, tar.gz selected files (thanks Fathi Boudra) ADDED: Useraction, gzip current (thanks Vaclav Juza) ADDED: Useraction, Eject cd/dvd (thanks Andrew Svet) ADDED: Javascript useraction, calculator ADDED: Javascript useraction, Mount as root ADDED: Javascript useraction, Recode files using GNU recode (thanks Vaclav Juza) ADDED: Javascript useraction, Recode files using iconv (thanks Vaclav Juza) ADDED: Useraction, (Un)Pack an ar archive (.a, .deb,...) (thanks Vaclav Juza) ADDED: Useraction, Verify signature with kgpg ADDED: Useraction, Sign with kgpg ADDED: Useraction, Decrypt with kgpg ADDED: Useraction, Encrypt with kgpg ADDED: Useraction, Split large mp3 (thanks Andrew Svet) ADDED: Useraction, Archive to Dir ADDED: Useraction, Copy as root (thanks Andrew Svet and MaxiPunkt) ADDED: Useraction, Unmount (thanks Stefan Endrullis) ADDED: Useraction, Search and Replace in file ADDED: Midnight commander keymap (thanks Alejandro Hamann) ADDED: Alpa-yellow color scheme (thanks Aldo Palmeri [alpa]) ADDED: Bash color scheme (thanks Alejandro Hamann) ADDED: Improved midnight commander color scheme (thanks Alejandro Hamann) ADDED: Pleasent total commander color scheme ADDED: DOS Navigator color scheme (thanks to Vovan [Koqep]) FIXED: Useractions, after pwd command current workdir was not changed (thanks Vaclav Juza ) FIXED: Eject DVD with right-click menu FIXED: Actionman, sometimes the command field is empty, (thanks Vaclav Juza) FIXED: GCC 4.3: missing #includes (thanks Fathi Boudra) FIXED: krpermhandler.cpp didn't compile on kde 3.2.x I18N: Updated Catalan translation (thanks Joaquim Perez) I18N: Updated French translation (thanks Tourneur Henry-Nicolas) 1.80.0 "Final 3rd Stone" ======================== FIXED: searcher doesn't always find content in binary files FIXED: [ 1619452 ] Profile doesn't save status of sync-browse mode FIXED: [ 1681270 ] right clicking pops context menu immediately FIXED: [ 1645179 ] shortcut keys are not sent to the terminal FIXED: [ 1736496 ] always sort dirs by name not working I18N: Updated Hungarian translation I18N: Updated French translation (thanks Henry Nicolas) I18N: Fixed [ 1725003 ] bad spanish translation I18N: Fixed untranslatable strings, patch by Vaclav Juza, thanks 1.80.0-beta2 "Last Unstable Stone" ================================== ADDED: Terminal Emulator, paste with SHIFT+INSERT and CTRL+V ADDED: Vaclav's checksum patches (added sha* tools, fixed bugs etc...) ADDED: Synchronizer: ignore hidden files option ADDED: Synchronizer-results: drag [left], SHIFT+drag [right], Copy left/right selected items to clipboard ADDED: Locate-results: dragging items, copy to clipboard (CTRL+C) ADDED: Searcher-results: dragging items, copy to clipboard (CTRL+C) ADDED: Support for useraction placeholders in Krusader's commandline patches by Jiri Palacek and Vaclav Juza, thanks a lot! ADDED: New default user action "Backup current" http://www.kde-files.org/content/show.php?content=29801 ADDED: ALT+C as default shortcut for compare directories ADDED: Brief view ADDED: GUI for configuring the atomic extensions in Konfigurator CHANGED: Useractions: much better handling of the Each-placeholder patch by Jiri Palacek, thanks! CHANGED: Icons in the 3rd hand (preview, quick and view) FIXED: [ 1684478 ] buggy configure check for klineedit FIXED: Krusader wouldn't start after the "first time wizard" was launched FIXED: krarc, problem with application/x-zip-compressed mime FIXED: [ 1665209 ] can't see the modified flag (*) if many tabs are used FIXED: [ 1678927 ] archive operation - copy to relative path fails FIXED: [ 1659215 ] does not Quit when using Mac Menu style FIXED: [ 1629447 ] can not view file in an archive with perm 600 FIXED: KrServices::separateArgs bug, thanks to Jiri Palacek FIXED: Broken 3rd hand disk usage icon on systems with basic installation FIXED: [ 1649705 ] "Deleting non-empty directories" confirmation bug FIXED: keyboard problems in synchronizer, locate, searcher FIXED: [ 1601632 ] Esc don't work in KrViewer on SVG files FIXED: 'preserve attributes' sometimes fails setting the file mode FIXED: clicking on the 3rd hand widget's header, doesn't set focus FIXED: [ 1647279 ] out-of-bounds array access in the Filelight widget FIXED: Broken view panel icon in 3rd hand when Crystal icon theme is used FIXED: [ 1629450 ] Editing files in a separate window FIXED: Valgrind: Invalid Read at switching to a panel profile FIXED: [ 1631578 ] Config error (caused by italian handbook) FIXED: Problems with zip file names containing '[' character FIXED: Autoconfigure doesn't tell that packing is enabled by 7z FIXED: Problem with unpacking passworded ZIP files FIXED: Compile problem with automake-1.10 (thanks to Sausi at the forums) FIXED: FTP crash at slow servers FIXED: ACL compile problem on FreeBSD FIXED: in pack dialog, if two passwords are empty, a message would say "passwords are equal" I18N: Fixed [ 1650677 ] German: Wrong apostrophs I18N: Broke and fixed the plurals again! (in the latter case, thanks to Vaclav Juza for the help ;)) I18N: Updated a feature description in Konfigurator to match the new menubar (thanks Doutor Zero) REMOVED: Outdated and unused Italian handbook translation 1.80.0-beta1 "The Last Krusade" =============================== ADDED: quotation mark handling at search (ex. "Program Files") ADDED: full support for ACL permissions (properties, preserve attrs, synchronizer) ADDED: credit for Vaclav Juza and Jiri Palecek in the about box ADDED: Experimental input method support in quick search (patch by Jiri Palecek) ADDED: TerminalEmulator: Ctrl+F switches between full-widget TE, normal TE (thanks to Vaclav Juza) ADDED: Ctrl+Up from panel focuses the origin editbox, Ctrl+Down from origin editbox focuses the panel (thanks to Vaclav Juza) ADDED: TerminalEmulator: Ctrl+Shift+Up/Down always focus/unfocus TE independently whether the command line is shown or not ADDED: TerminalEmulator: if the command line is hidden, TE receives Ctrl+Up / Ctrl+Down (thanks to Vaclav Juza) ADDED: Pimped KDE's KeyDialog in order to provide import/export abilities ADDED: UserAction: Outputcollectionwindow can now save the buffer ADDED: UserAction: Outputcollection now supports fonts with fixed or variable width ADDED: synchronizer: double click on a file calls the diff utility (kompare) ADDED: terminal emulator: Ctrl+Enter,Ctrl+Shift+Enter paste the filename ADDED: atomic extensions (see CVSNEWS) ADDED: archive packing / unpacking are now in the background ADDED: renaming of just the filename, without extension ADDED: full screen terminal window (mc-style) ADDED: Inactive panel color dimming (thanks to Heiner) ADDED: ActionMan for useraction configuration ADDED: single instance mode ADDED: start to system tray ADDED: right click menu for bookmarks ADDED: enable/disable special bookmarks by right clicking on them ADDED: keeping the directory structures for virt folders at copy/move ADDED: synchronizer, parallel threads for slow FTP servers ADDED: an option for directories to be always sorted by name ADDED: packing with encryption, multiple volume archives, compress level ADDED: krarc, 7z, 7za handling ADDED: media button ADDED: swap panels / swap sides ADDED: synchronizer, threshold for equality, time offset between sides ADDED: synchronizer, faster "compare by content" for local files ADDED: synchronizer, Feed to listbox ADDED: searcher, synchronizer: directory name filters (ex. '* | CVS/') ADDED: searcher is able to search content on remote URLs ADDED: panel splitter shows the percent values at moving ADDED: Copy/Move: preserve all attributes (time, owner, group) ADDED: viewer, print + copy actions ADDED: new krarc (password handling, type autodetection, writing out archiver error messages, step into hidden archives,...) ARCH: refactoring in the useractions, see CVSNEWS CHANGED: atomic extensions are configurable through krusaderrc CHANGED: Better quick navigation: first move mouse over subdir, then press ctrl + left mouse button (patch by Jiri Palecek) CHANGED: Better subdir calculation on quick navigation CHANGED: Color cache redesigned. Konfigurator preview and actual colors should now match CHANGED: Heavily extended and reordered menubar (honouring the KDE HIG where possible). All available actions are connected to the menus now. CHANGED: Konfigurator: MouseMode got now it's own Tab in Look&Feel CHANGED: Shortcut- and Toolbardialogs are removed from Konfigurator CHANGED: Shortcuts are now exported in as plaintext, legacy import still works. CHANGED: UserActions are now managed with ActionMan. In Konfigurator you can change settings _about_ useractions. FIXED: problems at starting maximized, without splash screen FIXED: [ 1500411 ] Crash when R-click on free space and drag on files FIXED: [ 1579847 ] launch command line in console not saved FIXED: media button would display encoded paths (http://krusader.sourceforge.net/phpBB/viewtopic.php?t=1789) FIXED: crash when viewing file properties due to class name clash (thanks to Stephan Binner) FIXED: .tar.bz2 was not treated as atomic extension, while .tar.gz.test was FIXED: disk usage: other filelight bugfixes FIXED: disk usage: filelight crash because of missing null pointer checks FIXED: media button always writes out the mounted location FIXED: [ 1495465 ] packing dialog, 'MIN' and 'MAX' labels below the slider FIXED: [ 1436725 ] Status bar is not updated after RIGHT-ARROW is pressed FIXED: [ 1578768 ] Wrong sorting by Date column in search dialog FIXED: [ 1599142 ] problem with "Rename selects extension" and directories FIXED: wrong name after cancelling inplace rename by Esc FIXED: locate jumps onto the file after double click FIXED: When a refresh fails, the attempted URL is kept in the origin bar, and focus remains there for the user to fix. Idea by Vaclav Juza FIXED: TerminalEmulator didn't hide for all shortcuts FIXED: Konfigurator layout: should fit into 800x600 again FIXED: KeyDialog: alternative shortcuts are ex-/imported as well FIXED: KeyDialog: canceling the dialog undoes import FIXED: ActionMan: creating a new actions doesn't seem to modify the current FIXED: ActionMan: Save modifications on current action FIXED: [Debian: 378138] Changed the location of the .desktop-files to match freedesktop.org's standards FIXED: Useractions: outputcollections works again FIXED: inconsistences and possible memoryleaks in useractions (thanks to Jiri Palacek) FIXED: Nice shutdown at SIGTERM,SIGHUP,SIGQUIT (thanks toJiri Palacek) FIXED: QLayout warnings in ListPanel (patch by Jiri Palecek) FIXED: memory leaks in KRpermHandler (patch by Jiri Palecek) FIXED: shutdown bugs (thanks to Jiri Palacek) FIXED: const char * compiler warnings removed (patch by Jiri Palecek) FIXED: memory leaks in KrDetailedView (patch by Jiri Palecek) FIXED: terminal emulator sends the CD commands too frequently FIXED: terminal emulator scrolls up its content after hide/show FIXED: [ 1501740 ] can not link from a search result's virtfs FIXED: rare compile problem where exit() isn't defined FIXED: [ 1519955 ] wrong permission handling in vfs::vfs_calcSpaceLocal FIXED: viewer gives back the focus to the search/locate widgets after ESC FIXED: problems with local directory names containing '@' character FIXED: security: sometimes the passwords are stored in cleartext in bookmarks.xml FIXED: cannot close Krusader when "menubar on top of the screen" is chosen FIXED: URL duplication is disabled in the virtual URL collection FIXED: cut/copy/paste also works for virtual URLs FIXED: [ 1483172 ] crash at refreshing the view during rename FIXED: [ 1144729 ] Krusader doesn't remember popup panel splitter position FIXED: [ 1479034 ] Crashes after clicking home button, when quicksearch is active (patch by Heiner Eichmann) FIXED: wrong character set is used on the radial map labels FIXED: TC style rename does not work with "Obey KDE's global selection policy" FIXED: [ 1189341 ] minimize to tray problems with GNOME FIXED: set duplicate exclusion and maximum count for all KHistoryCombos FIXED: [ 984936 ] Wrong file cursor position when entering protected directory FIXED: [ 1232507 ] panel focus change problems at using the keyboard FIXED: bookmark separators get corrupted after adding a new bookmark FIXED: [ 1116161 ] more detailed error message at opening FTP URLs via HTTP proxy FIXED: [ 1103646 ] MountMan exits after umount and a fast click on the device FIXED: single click doesn't work in TC selection mode FIXED: disk usage crash at deleting files FIXED: valgrind: Free Memory Read - KMountManGUI::clicked() FIXED: valgrind: Free Memory Read - SynchronizerGUI::loadFromProfile() FIXED: valgrind: Free Memory Read - RadialMap::Widget::paintExplodedLabels() FIXED: valgrind: Free Memory Read - DULines::slotChanged() FIXED: valgrind: Free Memory Read - DULines::slotDeleted() FIXED: valgrind: Free Memory Read - KrDetailedView::contentsMousePressEvent() FIXED: valgrind: Mismatched delete/delete[]- RadialMap::Builder::Builder() FIXED: valgrind: Uninitialized Memory Read - DUFileLight::slotAboutToShow() FIXED: valgrind: Free Memory Read - KViewer::tabCloseRequest() FIXED: valgrind: Uninitialized Memory Read - KViewer::tabChanged() FIXED: valgrind: Free Memory Read - PanelManager::slotCloseTab() FIXED: [ 1435352 ] crash after NewPanel->Ctrl+U->DeletePanel FIXED: HTML tags cause problem to the searcher FIXED: [ 1415250 ] searching large directories, doesn't process UI events FIXED: search by content goes into infinite loop if the file cannot be opened FIXED: after exiting the pending jobs stall FIXED: [ 1193239 ] crash at 'Closing Current Session' FIXED: synchronizer is always on the top of the panels FIXED: [Debian: 352367] useractions with terminal output ignores configured terminal FIXED: last tabs are not saved, if an old config value is present FIXED: panel popup gets focus at opening, gives focus to panel at hiding FIXED: viewer, detaching tab changes 'Editing' to 'Viewing' I18N: Added a russian handbook (translation is work in progress) (thanks to Roman Batejkin) I18N: Fixed clash with unpack shortcut in useractions string (Alt+U) (thanks Hideki Kimura) I18N: Updated Japanese translation (thanks Hideki Kimura) I18N: Renamed remaining instances of 'mark' to 'select' I18N: Many consistency changes in the menu names I18N: Fixed [ 1480646 ] Home button tooltip has a wrong default translation I18N: Updated Russian translation (thanks Dmitry A. Bugay) I18N: Updated Swedish translation (thanks Peter Landgren) I18N: Updated Serbian translations (thanks Sasa Tomic) I18N: Updated Brazilian Portuguese translation (thanks Doutor Zero) I18N: Updated French translation (thanks Guillerm David) I18N: Updated Polish translation (thanks Tomek Grzejszczyk and Marcin Garski) I18N: Updated Lithuanian translation (thanks Dovydas Sankauskas) I18N: Menu items which open a new window, indicate that with trailing dots (KDE standard) I18N: Plural fixes in Synchronizer I18N: Updated Dutch translation I18N: Updated Slovenian translation (thanks Matej Urbancic) I18N: Added Turkish translation (thanks Bekir Sonat) I18N: Updated Greek translation (thanks Spiros Georgaras) I18N: Updated Czech translation (thanks Vaclav Juza) I18N: Updated Spanish translation (thanks Alejandro Araiza Alvarado) I18N: Updated German translation I18N: viewer: 'Editing', 'Viewing' can be translated I18N: Don't omit paragraphs and close all tags in strings to avoid errors in translation tools (based on patch by Giuseppe Bordoni) 1.70.0 "Round Robin" ========================== ADDED: new splashscreen + button to disable it in the look&feel section ADDED: winning icons, SVGs and fixed code to use them ADDED: DUMMY splash screen (krusader/splash.jpg) which will be replaced later CHANGED: UserActions: addPlaceholderButton now only adds a space after an executable. Not after normal placeholders. FIXED: [ 1413503 ] detach tab shortcut changed Ctrl+Shift+D FIXED: [ 1407656 ] bookmark problem with identical names in different folders FIXED: [ 1421473 ] viewer doesn't notice that the URL was changed FIXED: [ 1235959 ] problems at viewing 600 permission files FIXED: cannot umount devices because of a watcher bug (thanks to vaclavj) FIXED: 1076857 & 1384529 - thanks to heiner FIXED: [ 1409160 ] Edited bookmarks require restart to become fully updated FIXED: missing dpkg from Konfigurator-Dependencies FIXED: [ 1234213 ] synchronizer keeps owner,group if possible FIXED: [ 1365423 ] synchronizer does not copy symlinks FIXED: [ 1393227 ] KURLListRequester uses url completion instead of shell completion (caused problems at spaces) FIXED: [ 1391892 ] problem with international characters in the destination of a symlink FIXED: [ 1393215 ] searcher, synchronizer: ~,$HOME,... is accepted now FIXED: [ 1413503 ] viewer: detach wasn't disabled when 1 tab remained FIXED: [ 1417969 ] Keybindings: reset to default keybinding fails FIXED: Konfigurator 'Defaults' button works only on the actual subpage FIXED: [ 1411561 ] renaming bug (thanks Heiner Eichmann) FIXED: [ 1381770 ] Status bar is not updated after TAB is pressed (thanks Heiner Eichmann) FIXED: [ 1365053 ] krservices.h: invalid member function declaration (thanks Heiner Eichmann) FIXED: [ 1400642 ] possible data loss (thanks Heiner Eichmann) FIXED: [ 1352107 ] File search "as you type" (thanks Heiner Eichmann) FIXED: [ 1401005 ] F10 doesn't close KrViewer FIXED: [ 1390116 ] CTRL+G duplicate action in viewer FIXED: [ 1362632 ] Ctrl-Alt-C does not work FIXED: [Debian: 343960] outdated libtool prevents from building (thanks to Aurelien Jarno ) FIXED: [ 1398540 ] wrong font in the new network connection dialog FIXED: [ 1398442 ] Column 'rwx' wrong data when column 'Type' is on (thanks Spiros Georgaras) FIXED: UserActions: addPlaceholderButton's popup-position FIXED: 'match whole word only' flag doesn't work in search FIXED: [ 1352107 ] File search "as you type" FIXED: [ 1351641 ] Krusader 1.70.0-beta2 on Sparc/Solaris: checksumdlg.h FIXED: terminal emulator saves its size from now FIXED: hiding the full size terminal emulator cannot restore the panels FIXED: terminal emulator has no focus after toggling it on FIXED: preserve dates doesn't copy the dates of folders I18N: [ 1397828 ] i18n: "dir" is not translated I18N: Added Greek translation (thanks Spiros Georgaras) I18N: Updated French translation (thanks Guillerm David) I18N: Updated Danish translation (thanks Peter H. Sorensen) I18N: Updated Hungarian translation (thanks Arpad Biro) 1.70.0-beta2 "Afterburner" ========================== ADDED: you can now cancel creating and verifying checksums ADDED: a (missing) shortcut to bookmark current item (ctrl-shift-d) ADDED: you can turn off sending CDs to the terminal emulator (general tab) ADDED: unpacking from RPM packages (much faster than using krarc) CHANGED: our write-enabled tar KIO-slave is only build when --with-kiotar is passed to ./configure. In this case the KDE-version will may be overwritten! FIXED: [ 1345220 ] bookmarks: separators shown as folders FIXED: new viewer tabs were sometimes added to windows different from the previously used ones FIXED: [ 1323613 ] SECURITY!!! PopularUrls stores cleartext passwords in krusaderrc FIXED: [ 1329044 ] krarc, missed similar file names belonging to different rpm-s FIXED: krarc doesn't notice the change of the rpm file to create new contents.cpio FIXED: iso protocol cannot step into files larger than 2 GByte FIXED: KDE 3.4, starting from profile misses the active tab which causes inconsistent state FIXED: krarc reports 000 permission for bz2 files FIXED: bug in checksum module regarding names with spaces FIXED: konfigurator minor fixes FIXED: viewer, the tabs were identified by its page index, which can change FIXED: searcher: space means logical OR "text1 text2" == "*text1* || *text2*" FIXED: krarc cannot step into those archives which name contains '#' FIXED: viewer doesn't warning to save the window at close, and ignores "Cancel" button FIXED: locate dialog doesn't close when exiting krusader FIXED: UserAction: Crash when a programm wrote to stderr but only stdout was collected (Thanks to Shao Lo) FIXED: searcher crash when clicking onto an empty field after the results FIXED: disk usage crash on remote vfs because of recursion FIXED: [ 1262907 ] crash when closing an sftp tab which is loading I18N: Added Lithuanian translation (thanks Dovydas Sankauskas) 1.70.0-beta1 "Hellfire" ========================== ADDED: KrSqueezedTextLabel can now specify the area in the string to be always visible ADDED: when searching for text inside file, the first line containing the text is displayed ADDED: checksum module now supports the cfv tool (for md5 and sha1) ADDED: QuickNavigation: hold ctrl and move the mouse over the url bar to see! ADDED: new checksum creation/verification mechanism (see mail titled "new checksum feature" to krusader-devel) ADDED: alt-ctrl-s creates a new symlink ADDED: ctrl-h opens history on the current panel ADDED: Nicer application search results ADDED: right click menu -> trash, delete, shred options ADDED: column types can be changed and saved individually to each panel (each side) ADDED: select remote encoding menu for fish, ftp and sftp protocols ADDED: clear-location-bar button a-la konqueror (configurable) ADDED: permissions column as octal numbers ADDED: right-click menu now has a "create new..." submenu ADDED: ctrl-alt-enter opens the current folder in a new tab ADDED: calculate space in archives and remote FS (KDE >= 3.3.0) ADDED: experimental support for mimetype-on-demand ADDED: experimental support for icon-on-demand ADDED: when custom filter is set, the Totals line will show the filter. example: [*.cpp] ADDED: useraction: Drop a warning on JavaScript-errors ADDED: set krusaders icon according to the users privileges ADDED: preserve date for local targets at copy / move ADDED: useraction: For JS-extensions the global variable scriptDir is available, indicating the location of the current script ADDED: synchronize selected files ADDED: colorful synchronizer :-) ADDED: starting more tabs with --left=tab1,tab2,tab3 --right=tab4,tab5 ADDED: vertical mode is saved with 'ui save settings' or 'save position' and restored ADDED: A Safari-like Jump-Back feature (Ctrl-J and in the bookmark-menu) ADDED: CTRL-L shortcut to go to the location bar (origin) as in firefox and konqueror ADDED: filters for selecting files ADDED: New zip/tar slave - based on KDE's but support writing to archive ARCH: refactoring in the view. enforcement of getVfile and getMutableVfile ARCH: removed a lot of KrViewItem's API ARCH: right-click menu code moved to a new class KrPopupMenu ARCH: moved JavaScript-stuff into it's own module KrJS ARCH: Makefile.am's for /krusader and /pics revised CHANGED: Use WhatsThis in favour of tooltips where reasonable CHANGED: the panel startup is profile based instead of directory based FIXED: krarc error, when the filename contains '$' or '&' FIXED: synchronizer, compare by content can be terminated by FIXED: preserve date fails at moving FIXED: bookmark issues (http://www.krusader.org/phpBB/viewtopic.php?p=6357#6357) FIXED: [ 1278534 ] Krusader hangs when packing search results FIXED: [ 1169980 ] User Actions Titles are not stored in system encoding (thanks Vaclav Juza) FIXED: '-icon' as well as '--icon' as command-line arguments are handled FIXED: [ 1272583 ] fixes on the .desktop files, thanks Marcin Garski FIXED: [ 1253323 ] middle click crash on ".." directory FIXED: burst refresh if FAM is enabled FIXED: crash when "run in terminal mode" was active on a directory with insufficient permissions (thanks Oleksandr Shneyder) FIXED: [ 1213137 ] javascript self.close() causes crash in the viewer FIXED: Control+Delete can be used in those distributions where Shift+Delete doesn't work FIXED: [ 1186534 ] problems with the new network connection (port, path, password, username) FIXED: renaming does not change the view, until VFS sends a signal about the rename actually being done FIXED: [ 1174273 ] updating the status bar at pressing the arrow keys FIXED: calcspace and diskusage shows the same size FIXED: [ 1180202 ] calcspace calculates wrong size for symbolic links FIXED: [ 1196779 ] searcher, sorting by size is broken FIXED: changing the 'show hidden files' sets the active tab to right, untouches the inactive ones FIXED: the default value of moving to trash is wrong in Konfigurator FIXED: problems with moving to trash at virt_fs and diskusage module FIXED: gcc 2.95 compiler fix FIXED: changed locate-gui shortcut from ctrl-l to shift+ctrl+l FIXED: bookmark icons were not saved correctly FIXED: clicking a search result won't jump to it, if it's in the current directory (patch by Thomas Jarosch) I18N: [ 1201586 ] Wrong encoding of slovenian translation I18N: [ 1243409 ] Encoding problem and bad plural in trash files dialog I18N: [ 1217697 ] Can't translate some Bookman II menu entries I18N: Added multiple plural support (thanks Vaclav Juza for all the help) I18N: Added Serbian translation (thanks Sasa Tomic) I18N: Added Brazilian Portuguese translation (thanks Doutor Zero) I18N: Updated Russian translation (thanks Denis Koryavov) I18N: Updated Portuguese translation (thanks Bruno Queiros) I18N: Updated Czech translation (thanks Vaclav Juza) I18N: Updated Dutch translation I18N: Updated French translation (thanks David Guillerm) I18N: Updated Spanish translation (thanks Alejandro Araiza Alvarado) I18N: Updated Swedish translation (thanks Peter Landgren) I18N: Updated Chinese Simplified translation (thanks Jinghua Luo) I18N: Updated Italian translation (thanks Giuseppe Bordoni) I18N: Updated Polish translation (thanks Pawel Salawa) I18N: Updated Slovenian translation (thanks Matej Urbancic) I18N: Updated German translation 1.60.0 ====================== ADDED: New Gorilla-style icon by www.OnExige.com FIXED: Crash if the useractions.xml contains invalid data FIXED: quick selection doesn't work FIXED: synchronizer, content filter doesn't work FIXED: synchronizer, consistency bug of the filter combos FIXED: advanced filter hides the searcher window at errors FIXED: combiner, smoother interoperability with Total Commander FIXED: UserActionMenu gets updated after Konfigurator applies FIXED: can't sort by extension when "Case Sensitive sort" is on FIXED: move to trash didn't work on kde 3.4.0 FIXED: [ 1123995 ] custom selection mode misfunction UPDATED: Italian translation (thanks Giuseppe Bordoni) UPDATED: Hungarian translation (thanks Arpad Biro) UPDATED: Chinese Simplified translation (thanks Jinghua Luo) UPDATED: Bulgarian translation (thanks Milen Ivanov) 1.60.0-beta2 ====================== FIXED: devices:/ is changed to media:/ in 3.4 FIXED: konfigurator crash on KDE 3.4 at checking 'save settings' FIXED: no refresh after splitting files FIXED: splitter doesn't handle sizes bigger than 2 GB properly FIXED: problem at restart if virtual folders were saved at last exit FIXED: locate / search feed to listbox number generation 1.60.0-beta1 ====================== ADDED: useraction: new placeholder: %_ListFile()% ADDED: total commander color scheme ADDED: Custom Selection Mode. dirk: a dream comming true? ;-) ADDED: synchronizer, exclude directories from the comparation ADDED: some nice sample useractions ADDED: PopularUrls was rewritten for a nice-like algorithm ADDED: Useractions in the menubar (need an update of krusaderui.rc) ADDED: searcher: ask for a collection-name on feed to listbox ADDED: popular urls is now persistent ADDED: popular-urls - krusader's answer to google-ranking ;-) ADDED: better completion in the origin box: constructs such as ~/src and $QTDIR/bin should work now. ADDED: Slovenian translation (thanks Matej Urbancic) ADDED: bookmarks can now be placed into toolbars ADDED: searcher, feed to listbox (with virtual folders) ADDED: Primitive scripting support; Warning: very alpha!! ADDED: new toolbar for actions. use view->show actions toolbar. you'll need to remove ~/.kde/share/apps/krusaderui.rc to see it ADDED: refresh-in-the-background for remote urls and for archives ADDED: changing the coloumns by right clicking on the panel's header ADDED: color scheme export/import ADDED: an other .desktop-file with the red icon that starts krusader as root ADDED: useraction: now every placeholder can cancel the execution. (-> %_ask(..)%) ADDED: useraction: new placeholder: %_PanelSize(percent)% ADDED: Synchronizer, pause/resume button for synchronize with kget ADDED: disk usage (tools menu + 3rd panel) ADDED: useraction: new placeholder: %_Move(src, dest)% ADDED: useraction: new placeholder: %_Each% ADDED: full viewer in the 3rd hand ADDED: shift-del deletes and doesn't move to trash ADDED: splitter: pre-defined 650MB and 700MB CD-R ADDED: more Konfigurator Tooltips ADDED: usermenu: entry to open konfigurator with the useraction-page directly ADDED: import/export of keyboard shortcuts ADDED: mouse selection modes are back! thanks to heiner for doing the work ADDED: virtual VFS (try virt:/somthing/) ARCH: KChooseDir was rewritten. plz have a look at the code/email ARCH: move listpanel from qstring to kurl. plz read email before continuing! FIXED: useraction: cancel a useraction now works for recursive expansion too FIXED: useraction: problems with international characters FIXED: panel profiles sometimes hang FIXED: new ftp dialog was broken FIXED: [ 1073940 ] no refresh after the exclusion filter is modified FIXED: [ 1108444 ] no error message if copy or move fails FIXED: auto filesystems cannot be mounted FIXED: krusader fails to refresh at copying to the source directory on different name FIXED: color "Inactive Marked Current Foreground" was ignored (thx heiner) FIXED: searcher gets behind the main window, if file browse is pressed FIXED: [ 1120827 ] dir copy / move with F5 / F6 doesn't work FIXED: [ 1064578 ] remote URL-s are saved in panel profiles FIXED: Creatring dir-trees on the fly (mkdir /foo/bar/test) is working again FIXED: Syncbrowse is working again and is deactivated automaticly if no longer possible FIXED: [ 1107141 ] view throws error at editing new files on remote fs FIXED: [ 1110507 ] cannot open rpm package if path contains space FIXED: command line alters its height at opening/closing the popup panel FIXED: [ 1037003 ] konqueror style drag and drop FIXED: [ 1076865 ] the default search text is '*' FIXED: [ 976598 ] krusader occasionally crashes at closing the viewer FIXED: [ 1033319 ] Relative paths dont get auto-completed FIXED: [ 971831 ] space calculation failure if the file is bigger than 4 GByte FIXED: [ 1089450 ] synchronizer copies the date information for local files FIXED: [ 1109249 ] drag and drop doesn't work with international characters FIXED: viewer cannot open 600 files, when the owner column is enabled FIXED: ftp_vfs overloads the CPU at stepping into a slow server on the network FIXED: krusader's detection of old or incompatible versions FIXED: dirk's patch for better looking icons FIXED: cannot open FTP proxy bookmarks FIXED: [ 1101237 ] the reload shortcut is always set to Ctrl+R at startup FIXED: rename extension bug in kde 3.3 FIXED: crash on startup due to restoring of last size and position FIXED: couldn't sort case sensative on some systems (see KDE bug #40131) FIXED: resizing of the main window produces strange effects FIXED: double dragging in Krusader and Konqueror selection modes FIXED: right click menu and user action ID turmoil FIXED: [ 1074393 ] Crashes sometimes on startup (thanks Heiner) FIXED: custom icons in bookmarks weren't shown FIXED: All openUrl() calls are now delayed to avoid deadlocks... UPDATED: remoteman was disabled. from now on, bookmark manager only UPDATED: Hungarian translation (thanks Arpad Biro) UPDATED: Catalan translation (thanks Quim Perez Noguer) UPDATED: Portuguese translation (thanks Bruno Queiros) UPDATED: Dutch translation UPDATED: Swedish translation (thanks Peter Landgren) UPDATED: Russian translation UPDATED: German translation 1.51 ====================== ADDED: Portuguese translation (thanks Bruno Queiros) ADDED: Fn keys can have custom shortcuts ADDED: krusader can be resized to a small size even with Fn keys showing ADDED: Total-commander style refresh (at last) ADDED: ctrl-up arrow (from the panel) goes up to the origin bar ADDED: New commandline option: --profile ADDED: Heiner's selection mode patch. Still alpha. ADDED: Ukrainian translation (thanks Ivan Petrouchtchak) ADDED: disk usage tool (alpha version) ADDED: vertical krusader: hit alt+ctrl+v to test ADDED: extra information in the totals bar FIXED: separators were not displayed in the bookmarks list FIXED: deleting a folder didn't update the bottom stats correctly FIXED: useraction: parse the default-value "__goto" again FIXED: useraction: Crash when filename contained brackets '(...)' FIXED: world-class-annoying-bug when sometimes while using quicksearch, the file that was selected by quicksearch got hidden beneath the bar FIXED: mime types are shown only in english FIXED: when using quicksearch, current item wasn't visible FIXED: a crash when packing/unpacking to partial URL UPDATED: Dutch translation (thanks Frank Schoolmeesters) UPDATED: Hungarian translation (thanks Arpad Biro) UPDATED: German translation 1.50 ====================== FIXED: mountman now blocks and wait for mount/umount to complete FIXED: sorting got borked because locale-aware-compare isn't handling files that start with '.' well FIXED: possible opendir leakage, fish works only when moving the mouse FIXED: taken KDE's KDiskFreeSp class to optimize DF handling FIXED: Krusader overloads the CPU with panel refreshing FIXED: Wrong Danish language code (dk.po->da.po) UPDATED: Catalan translation (thanks Quim Perez) UPDATED: Italian translation (thanks Giuseppe Bordoni) UPDATED: Bulgarian translation (thanks Milen Ivanov) UPDATED: Slovak translation (thanks Zdenko Podobny) UPDATED: Hungarian translation (thanks Arpad Biro) UPDATED: German translation UPDATED: Dutch translation (thanks Frank Schoolmeesters) 1.50-beta1 ====================== ADDED: if view is human-readable, status bar is normal (bytes) and vice versa ADDED: Human-readable file sizes is implemented (located in look&feel->panel) ADDED: useraction: available via rightclick-menu ADDED: importing the right click menu of konqueror ADDED: cut(CTRL+X), copy(CTRL+C), paste(CTRL+V) ADDED: useraction: new Placeholder %_Profile("panel-profile")% ADDED: useraction: new Placeholder %_NewSearch("search-profile")% ADDED: useraction: run as different user ADDED: alt-O now sync the panels (like ctrl-left/right arrows) ADDED: new shortcut (ctrl-d) to open bookmarks on current panel ADDED: panel costum colors: new Current Marked Foreground ADDED: compare by content: the action is now smarter in finding the right files ADDED: profiles for the panels ADDED: mkdir (F7) can now create whole trees on the fly ("foo/bar/test") ADDED: synchronizer uses the search filters ADDED: search profiles ADDED: searcher: TC like search ( 'text' == '*text*' ) excluding files with '|' (ex. '*.cpp *.h | *.moc.cpp' ) ADDED: search on remote file systems ADDED: konfigurator|advanced has a new entry: just enter mountpoints there, and mountman won't try to mount/unmount them. ADDED: mountman got a big nose-job ;-) plz test ADDED: dropping on the tree panel (copy,move,link) ADDED: packing / unpacking to/from remote URL-s ADDED: short tab names ADDED: compare directories (mark menu) ADDED: shift+left/right changes tabs (thanks to Dmitry Suzdalev) ADDED: linking mimes and protocols ADDED: new delete dialog box: lists the file names to be deleted (thanks to dirk for the idea) ADDED: iso protocol for viewing .iso cd/dvd images (thanks to Szombathelyi Gyorgy) ADDED: full handling of arj, ace and lha packers ADDED: useraction: new Placeholder %_Sync("synchronizer-profile")% ADDED: synchronizer: profile handling ADDED: synchronizer: swap sides ADDED: useraction: new Placeholder %_Copy("from", "to")% ADDED: 3rd hand: new panel that does quick selection ADDED: 3rd hand: look n feel changed to fit krusader ADDED: credit for jonas in the about box ADDED: panels now save the tabs at shutdown (thanks to Donat Martin) ADDED: dropping URL-s onto the status / totals line ADDED: Bosnian translation ADDED: synchronizer: excluding files with '|' in the file filter (ex. '*.cpp *.h | *.moc.cpp' ) ADDED: tooltips for squeezed tabs ADDED: sync-browse mode (if on, a directory-change in the active is also performed in the inactive panel) ADDED: beta-state incremental refresh. test it with fam enabled! ADDED: synchronizer: ability to give more files in the file filter (ex. '*.cpp *.h') ADDED: Two single click rename (Total Commander rename) ADDED: The 3rd hand of krusader. click the litle arrow below the panel's scrollbar to see.. ADDED: showing suid, sgid and sticky bits in the permissions column ADDED: New useraction-system (partly based on Shies usermenu-prototype) REACTIVATED: usermenu (now using the new useraction-system) FIXED: synchronizer fails at case insensitive (Windows) file systems FIXED: crash when deleting an useraction created in the same session FIXED: locale aware ABC sorting (for non-english languages) FIXED: useraction: startpath is now working FIXED: useraction: i18n is now working in the add-placeholder-menu FIXED: searcher corrupts international characters FIXED: searcher cannot open remote URL-s for editing/viewing (archives) FIXED: the File/Properties function writes incorrect group name FIXED: krarc doesn't keep the date/time information at extracting to local fs FIXED: jar files aren't handled + problems with dirs in windows zips FIXED: problem with the windows created rar permissions FIXED: performance increasing: faster sorting, directory leaving FIXED: compare content error at remote urls (problem with sleep 2) FIXED: totals bar didn't update when an incremental refresh happened FIXED: locate doesn't report the errors occured during the search FIXED: the viewer size is forgotten in maximized mode (KDE hack) FIXED: internationalization bugs, illegal usage of QString::latin1() FIXED: krarc, ignores the packer dependencies FIXED: krarc, rar: mkdir does not work, illegal time and permission info FIXED: krarc, problem with copying / moving inside the archive FIXED: krarc, problem with international characters in put/mkdir FIXED: krarc, problems at copying subdirectories from the archive FIXED: [ 1005533 ] stepping onto a subfs device crashes krusader FIXED: [ 988835 ] window size of synchronize dirs is not stored FIXED: [ 946567 ] krusader minimizes to tray on desktop change FIXED: mountman changes... read the email ;-) REMOVED: Dupe Japanese translation (ja.po is used nowadays) UPDATED: Bosnian translation (thanks Asim Husanovic) UPDATED: Chinese Simplified translation (thanks Jinghua Luo) UPDATED: Hungarian translation (thanks Kukk Zolt�) UPDATED: German translation 1.40 ====================== ADDED: when searching in files (grep), push the string we're searching for into the clipboard when pressing F3 or F4. this saves an extra copy when searching inside the file ADDED: Catalan translation DISABLED: usermenu for 1.40 FIXED: [ 962340 ] Alt-T broken to call Tools menu FIXED: [ 980252 ] Compare by Content: right/left position swapped FIXED: [ 990141 ] F3/F4 in root mode trouble with permissions FIXED: [ 959916 ] Krusader window too large on startup FIXED: username and group information are wrong for ftp_vfs FIXED: UMR (uninitialized memory read) in vfs::fromPathOrURL UPDATED: Polish translation 1.40-beta2 ====================== ADDED: Chinese Simplified translation FIXED: the new ftp dialog URLs are saved into a stochastic configuration group FIXED: [ 960003 ] Swapped letters in quick-search FIXED: KIO::Slave url redirection handling (e.g. now devices:/ and settings:/ works !) FIXED: [ 962598 ] viewer didn't display XML files FIXED: [ 960595 ] problem with paths containing more '@' characters (FTP proxy hack) FIXED: [ 957145 ] krusader closes editor without asking FIXED: ports cannot be added for fish, sftp in the new connection GUI FIXED: [ 943962 ] the summary status is not updated after calc space FIXED: [ 950762 ] missing pemission check on entering a folder FIXED: setting "xterm -e vim" as editor didn't work... FIXED: [ 953874 ] allowing editors which are not url-aware to be used as default editor FIXED: [ 948315 ] security hole, krusader changes its temp directory's rights to 0777 FIXED: the UI settings are not saved at exit FIXED: [ 951274 ] shift+home and shift+end does not work FIXED: [ 948726 ] problem with ctrl+left from the left panel and ctrl+right from the right panel FIXED: extension is separated from the dirname after renaming directories containing '.' FIXED: locate does not call kdesu any more FIXED: [ 950052 ] synchronizer: the left and right side depends of the active panel FIXED: [ 770676 ] krarc does not handle password zips FIXED: [ 928746 ] symlinks pointing to directories using fish protocol fail FIXED: [ 939214 ] synchronizer, wrong behaviour of compare by content FIXED: moving into archives is dangerous. it is disabled (for now at least) FIXED: synchronizer gui size policy bugs FIXED: [ 934498 ] problem at dropping files into the '..' directory FIXED: [ 939612 ] F9 moves file, if new name already exists as directory FIXED: krusader does not handle filenames containing '#' character FIXED: krusader exits at viewing dvi files (missing arguments from KPart). FIXED: drag line remains visible after dropping an URL FIXED: panel swapping corrupts ctrl+arrow and alt+arrow FIXED: error at dropping URLs containing non-english characters from konqueror FIXED: KDE 3.2, right justified tabs bug FIXED: dragging over a new tab changes active tab FIXED: crash at pressing space on the '..' directory UPDATED: Bulgarian translation UPDATED: Czech translation UPDATED: Danish translation UPDATED: Dutch translation UPDATED: French translation UPDATED: German translation UPDATED: Hungarian translation UPDATED: Italian translation UPDATED: Slovak translation 1.40-beta1 ====================== ADDED: configuring the colors of the panel ADDED: (a bug fix really) ability to "not test archives before unpacking" ADDED: new icons (thanks to adios for providing them) ADDED: quickmode for mountman. press and HOLD the mountman icon for new functionality ADDED: Bulgarian translation (thanks to Milen Ivanov) ADDED: krusader restart is not necessary from now after changing the configuration ADDED: ability to give arguments for the terminal ADDED: enable/disable icons in the filenames ADDED: ability to configure the fields of the panel (Ext, Size, Perm, ...) ADDED: single click selects / executes ADDED: panel level toolbar ('..', '/', '~', '=' buttons), thanks to David Harel ADDED: Locate (integrating the findutils-locate package of GNU into Krusader). TEST IT ADDED: Heiner's patch for 'logical selection mode' is applied and used as default. TEST IT ADDED: application dependency setting in konfigurator ADDED: Csaba's new konfigurator is here, boys and girls! ADDED: heiner's quicksearch patch ADDED: calculate occupied space prints the directory's size (wincmd-style) - thanks heiner! ADDED: current directory in history menu is checked ADDED: a working user menu (try alt+~), but a bit rough on the edges ADDED: KrSearch edit/view file in the result list window (F3, F4, right click) ADDED: a folder-history button, a-la-total commander. thanks to Hans Loffler! ADDED: selectall at rename ADDED: new shortcuts to search dialog (heiner) ADDED: directory synchronizer ADDED: file splitter ADDED: a missing credit for Frank in the about box FIXED: krusader exits at closing the viewer when minimized to tray FIXED: KDE 3.2 terminal exit at Ctrl+C FIXED: bug [ 906386 ] regarding refreshes of dirwatch with fam enabled FIXED: bug [ 906538 ] which now makes a faster unpacking process FIXED: bug [ 894771 ] regarding over-expanding window due to long command line FIXED: edit new file on KDE 3.2 FIXED: permission handling for FTP URL-s FIXED: calc space crash at vfs refresh (thanks to Heiner) FIXED: krarc created non-executable directories (0666) FIXED: reimplementing the 'allow move into archive' setting FIXED: no restart at changing the icon tray's state in konfigurator FIXED: krusader freezes if the `df` process does not terminate (at network errors, IO wait) FIXED: krusaderui.rc bug, new menuitems does not appear after a krusader update FIXED: sort by EXT did not obey the 'case sensative sort' flag FIXED: 2 items on the view menu had the same shortcuts FIXED: increased speed of search, by emitting lesssignals (thanks to Lars) FIXED: statusbar updated only on mouse clicks, not on keyboard FIXED: translation: forcing non-english languages with a strange structure FIXED: freeze at modal dialogs and icon tray FIXED: crash at rename if the directory is refreshed by the watcher FIXED: stepping to the file below after delete (heiner) FIXED: window size and position saving at maximized mode FIXED: more freedom to give FTP proxy URL-s in "New FTP Connection" menu FIXED: crash at ftp://user@server@proxy:port FTP URL-s FIXED: no parent directory at tar://... and zip://... URL-s FIXED: font size problems in KCmdLine and KrMaskChoice FIXED: internal editor quits without notification even if the edited file was not saved FIXED: no i18n for Name, Ext, Size, Modified FIXED: obsolete QT header files FIXED: crash at closing the progressbar window at packing FIXED: no or uninformative error message at packing to a readonly directory FIXED: crash at middle clicking on the last tab FIXED: KrSearch permissions panel placing bug FIXED: ftp port limit changed from 999 to 65535 REMOVED: arc_vfs support completly replaced with KIO:Slave technolegy. UPDATED: new package description - Thanks to Jonas B�r UPDATED: Krusader Handbook (read ./doc/ChangeLog for more info) UPDATED: Japanese translation UPDATED: Dutch translation UPDATED: Czech translation (thanks to Martin Sixta) UPDATED: Spanish translation UPDATED: Krename url http://www.krename.net 1.30 ====================== ADDED: middle mouse button: click on a folder, and create a new tab. ADDED: middle mouse button: click on a tab, and close it FIXED: krarc QByteArray buffer freeing bug FIXED: mountman watches 'mount' instead of the directories FIXED: keyboard-shortcuts issues for new-tab(alt+ctrl+n), close-tab(alt+ctrl+c) and duplicate-tab(alt+ctrl+shift+n) FIXED: mountman FreeBSD bug (/etc/mtab does not exist in FreeBSD) FIXED: All files / Custom files. Executable was removed. FIXED: when selecting something from the combobox in "mark files" dialog, combo doesn't close immediatly FIXED: mark files dialog added the same selection more than once FIXED: disabled panel-types in konfigurator FIXED: font size problems with the Select dialog, and New Net Connection FIXED: mountman detects those devices as supermount, which are mounted and missing from fstab FIXED: mountman inserts '/dev/' before NFS shares and mounted devices which are missing from fstab FIXED: mountman does not watch readonly directories (mount can change its permissions!) FIXED: mountman does not stop dirwatch after close + memory leak FIXED: compare fix at directories with escape characters FIXED: Sorry - Archive test passed FIXED: FTP proxy bug (more than one @ characters in the URL) REMOVED: SortByExtention menu item (which did nothing) REMOVED: KrSearch-Help + Pack-Move into archive (did nothing) UPDATED: Dutch translation UPDATED: Danish translation UPDATED: Hungarian translation UPDATED: Italian translation UPDATED: Slovak translation 1.29-beta ====================== ADDED: KrSearch Match whole word only feature ADDED: Tab-browsing shortens tabs when more tabs are created ADDED: Starting Krusader with root privileges by pressing Alt+K ADDED: Open-in-a-new-tab available in right-click menu ADDED: Creating new files with SHIFT+F4 ADDED: Russian translation (thanks to Dmitry Chernyak) ADDED: Ctrl+Enter and Ctrl+Shift+Enter keyboard shortcuts ADDED: default shortcut for refreshing the panel is Ctrl+R ADDED: ctrl-left/right arrow checks if we're on a folder, if so it refreshes the other panel with the contents of the folder, otherwise to the same path as current one (Wincmd style) ADDED: tabbed-browsing beta ADDED: SHIFT-F3 view dialog. ADDED: The internal viewer follow links on HTML pages. ADDED: panel swapping by Ctrl+U ADDED: command line improvments: ctrl+/ opens history list, up&down keys work again, and general usability ADDED: krusader can now be started from commandline with new options: try: krusader --left=/mnt/cdrom --right=ftp://downloads@myserver.net! ADDED: new command line widget. should fix some issues and requests ADDED: Missing WhatsThis information (thanks to Mikolaj!) ADDED: a new shortcut for 'show hidden files' - ctrl+. (ctrl plus dot) ADDED: rar support to krArc KIO slave. ADDED: open with in the right click menu for multiple files with the same mimetype. ADDED: Patch by Heiner which adds a cancel button to the calculate space action. FIXED: KrSearch does not find texts at the last row FIXED: Strange KrSearch GUI (SearchIn and DontSearchIn adding) FIXED: KrSearch crash at pressing Escape or Closing the window during search FIXED: cmdline would start-up focused on the wrong panel FIXED: when pressing ctrl-enter (or ctrl-shift-enter), focus goes to command line FIXED: Terminal Emulator bug at ` and Backspace keys FIXED: internal editor / viewer crash at invalid symlinks FIXED: run-in-terminal would cause the terminal to close prematuraly and results would be lost. FIXED: free disk capacity miscalculation for Ext2 and Ext3 file systems. FIXED: crash when editing a file with # in the filename FIXED: inplace renaming bug with extension when pressing ctrl+click FIXED: whenever the folder gets refreshed, the current file would be lost FIXED: problematic behavior when trying to SPACE a folder without permissions FIXED: Ctrl-A didn't work properly FIXED: crash when unmounting a busy mountpoint FIXED: date-time sorting bug FIXED: changed pop-up delay of the history button on the command line to zero FIXED: right-click menu via keyboard appeared in the wrong place FIXED: crash when using spacebar on the ".." (thanks to heiner) FIXED: automark directories didn't work (thanks to Anarky) FIXED: bug when using space to calculate space of directory FIXED: crash when viewing files with # in their name. FIXED: compilation problem with GCC >= 3.3 (thanks to Adios) FIXED: Force refresh when creating a new directory. FIXED: a crash when trying to repaint when the VFS was deleted. REMOVED: Device Manager action UPDATED: many usability issues (thanks to Mikolaj) UPDATED: German translation UPDATED: Hungarian translation UPDATED: Dutch translation UPDATED: Spanish translation 1.25-beta1 ====================== ADDED: Finally, the new bookmark system is here! courtasy of Jan Halasa ADDED: new Hungarian translation, thanks to Kukk Zolt� FIXED: mountMan bug - didn't allow to umount/mount filesystem with trailing / FIXED: width of modified column for i18n (thanks to heiner) FIXED: dirUp() bug - selection goes to top. FIXED: the @ in ftp passwords bug. UPDATED: Slovak translation UPDATED: Dutch translation 1.21-beta1 ====================== ADDED: Opening left/right bookmarks (alt+left/right arrow) is now an action, and can be remapped. ADDED: In-place renaming (thanks to Heiner Eichmann) ADDED: New KIO slaves to handle archives. ADDED: multi-file properties. ADDED: Krusader now obeys KDE's date time format ADDED: Total-Commander style directory selection. Press SPACE to check it out! Thanks goes (again) to Heiner Eichmann! FIXED: column sizes are saved when doing 'save postion', or if 'save settings' is set in konfigurator. FIXED: double-catching of the ~ (tilda) key FIXED: double-catching of the backspace key FIXED: closing krusader using Alt-F4 or clicking X didn't save settings FIXED: Wrong focus after renaming FIXED: Error using KRename with filenames containing spaces (thanks to Tobias Vogele) FIXED: FreeBSD compatability in KrARC (thanks to Heiner Eichmann) FIXED: a crash in the dirUp() function. FIXED: when opening bookmarks using keyboard, active panel didn't change properly FIXED: in search dialog - you can now simply click text, and press ENTER. no need to click Search FIXED: a lot of usability issues (thanks to Mikolaj Machowski) FIXED: double-click in search dialog bug (thanks to heiner eichmann for the patch) FIXED: i18n issues - thanks to Frank Schoolmeesters FIXED: Panel flicker patch (thanks to Gabor Takacs for the patch) FIXED: Krusader failed to report permission errors while deleting files FIXED: issue with Japanesse translation FIXED: ctrl+arrows is caught by panel and not the view FIXED: removed unsafe debug messages FIXED: proper properties and owner/group for non-local files UPDATED: Dutch translation UPDATED: German translation BUG: krArc slow when unpacking large files 1.20 - KDE 3 ====================== ADDED: Clicking on the status or totals bars (above and below file list) changes focus ADDED: Each panel remembers the way it was sorted (might be different for each) ADDED: Each panel remembers the column width (might be different for each) ADDED: Dutch translation, thanks to Frank Schoolmeesters FIXED: Crash when saying NO to "really exit krusader?" UPDATED: German translation UPDATED: Polish translation 1.20 ====================== ADDED: Japanese translation, thanks to UTUMI Hirosi ADDED: error window when attempting to drag-n-drop to a target without enough permissions FIXED: crash when viewing/editing a file without permissions to read FIXED: icon touchup - to make the thing look more consistent FIXED: removed the ftp disconnect and root actions from the toolbar FIXED: updated polish translation FIXED: date sorting with files older than the year 2000 FIXED: crash on remote connections if there is a @ in the password FIXED: the remote connections rename function FIXED: blank hex viewer with short text files FIXED: anonymous checkbox in remote-man not respected 1.12 beta2 ====================== ADDED: Introducing extension column ADDED: Italian translation (thanks to Giuseppe Bordoni) ADDED: Preview to the right-click menu. FIXED: minimize to tray didn't behave correctly FIXED: crash when mounting failed (no cdrom in drive) FIXED: icon too big when minimized to tray FIXED: origin bar now accepts local urls (file:/) gracefully FIXED: origin bug, which caused the focus to go to the panel too soon. FIXED: right click menu in mountman (thanx to Heiner). FIXED: new 'admin' folder (support automake 1.7). FIXED: ESC key close the viewer. FIXED: crash when trying to open non-existing directory. FIXED: directory sorting. TODO: automark directories won't work in 1.12!!! TODO: can we add a krProgress to normal-vfs refreshes ? TODO: dragn'drop quirky. TODO: add progressbar to totals (?) TODO: COMPAREMODE 1.12 beta1 ====================== ADDED: some GUI touch-ups: make buttons smaller, and bars leaner. all in all, the thing should look better. ADDED: FreeBSD compatability issues - patchs by Heiner, thanks man! ADDED: move to next-gen view (at last) FIXED: popup-menu poping out of place. FIXED: Panel & PanelFunc permission clean up. FIXED: krBack() clean up. FIXED: moved all the logic from ListPanel to ListPanelFunc FIXED: integrated the openUrl() API. FIXED: minor bug in mountman FIXED: bug in arc_vfs, concerning full-paths in tars (thanks Heiner) FIXED: right align size column REMOVED: Tree & Quickview panels. 1.11 KDE 3 ====================== ADDED: updated Swedish translation, thanks to Anders Linden. ADDED: new Spanish translation, thanks to Rafa Munoz. ADDED: new Polish translation, thanks to Lukasz Janyst. FIXED: Changed the internal viewer default from Hex to Text. FIXED: Crash when Krusader is called with open viewer/internal editor. FIXED: Keyboard shortcuts not saved in Konfigurator. 1.10 - KDE 3 ====================== ADDED: new and improved viewer. ADDED: Krename support ! (more info at: http://krename.sf.net ) ADDED: you can now use the command line to "cd" into konqi-supported urls. ( try: cd audiocd:/?dev=/dev/cdrom ) ADDED: you can try to execute files in remote filesystem. ADDED: new command detection function instead of using 'which' FIXED: rewritten the panel sorting function, it should be better and faster now. FIXED: back to KRDirWatch, since KDirWatch crashed us on systems with FAM enabled. FIXED: removed the "panel start path is invalid" error message. if the start path is invalid try to find the closest path (the previous solution was '/'); FIXED: don't watch read-only/not-readable directories - this should improve performance and avoid a loooong wait time on super-mounted cdroms. FIXED: multiple selctions modes are no-more. default mode is Konqueror. the multi-mode become unstable after the kde3 porting and we had to disable it. FIXED: memory leak when starting konfigurator. 1.0.2 - KDE 3 ====================== ADDED: new icon. ADDED: sftp & scp support. ADDED: multi-protocol and history to the new connection dialog. FIXED: normal_vfs now uses the KDE dir watch, in other words: better directory refresh. FIXED: new 'admin' folder. 1.0.1 - KDE 3 ====================== ADDED: Krusader now compiles on KDE 3 (tested with RC3). ADDED: New ftp/smb vfs due to KDE 3 API changes. 1.0.1 ====================== ADDED: When compare-mode is active, pressing the 'Select Files' icon (or the equivalent keyboard shortcut), will open the usual dialog with 4 new options in the predefined selections. This allows automatic selection of files according to their compare-mode status - newer, older, etc. ADDED: Terminal emulator now "follows mouse" - konqueror style. ADDED: French translation. ADDED: A new icon for Krusader. new we've got krusader.png and krusader2.png! FIXED: errors compiling on kde 2.1 - convertSizeFromKB FIXED: compatability issue with installing to debian FIXED: compatability issue with Solaris FIXED: keyboard settings are not saved. FIXED: a small bug causing 'rrr' to show instead of 'rwx'. 1/1/02 - 1.00 ===================== diff --git a/krArc/krarc.cpp b/krArc/krarc.cpp index 91a549f4..588454ec 100644 --- a/krArc/krarc.cpp +++ b/krArc/krarc.cpp @@ -1,1934 +1,1934 @@ /***************************************************************************** * Copyright (C) 2003 Rafi Yanai * * Copyright (C) 2003 Shie Erlich * * Copyright (C) 2004-2018 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 #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) {} virtual ~KrArcCodec() {} virtual QByteArray name() const { return originalCodec->name(); } virtual QList aliases() const { return originalCodec->aliases(); } virtual int mibEnum() const { return originalCodec->mibEnum(); } protected: virtual QString convertToUnicode(const char *in, int length, ConverterState *state) const { return originalCodec->toUnicode(in, length, state); } virtual QByteArray convertFromUnicode(const QChar *in, int length, ConverterState *state) const { // 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); } #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(0L), extArcReady(false), password(QString()), krConf("krusaderrc"), codec(0) { 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; 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)); 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_COULD_NOT_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_COULD_NOT_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_COULD_NOT_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_COULD_NOT_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_COULD_NOT_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, SIGNAL(newOutputData(KProcess*,QByteArray&)), this, SLOT(receivedData(KProcess*,QByteArray&))); 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_COULD_NOT_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_COULD_NOT_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_COULD_NOT_WRITE, getPath(dest, QUrl::StripTrailingSlash) + "\n\n" + proc.getErrorMsg()); return; } if (!QFileInfo(getPath(dest, QUrl::StripTrailingSlash)).exists()) { error(KIO::ERR_COULD_NOT_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)); 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(0); 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 == 0) 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 = 0L; } 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 == 0) 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 erronously think, that the archive file is unchanged, + 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_COULD_NOT_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 UDSEntryList* root = new UDSEntryList(); dirDict.insert(DIR_SEPARATOR, root); // and the "/" UDSEntry UDSEntry entry; entry.insert(KIO::UDSEntry::UDS_NAME, "."); mode_t mode = parsePermString("drwxr-xr-x"); entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, mode & S_IFMT); // keep file type only 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 0; QHash::iterator itef = dirDict.find(arcDir); if (itef == dirDict.end()) return 0; 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 0; } 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_WS_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_WS_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(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.insert(KIO::UDSEntry::UDS_NAME, name); mode_t mode = parsePermString("drwxr-xr-x"); entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, mode & S_IFMT); // keep file type only entry.insert(KIO::UDSEntry::UDS_ACCESS, mode & 07777); // keep permissions only entry.insert(KIO::UDSEntry::UDS_SIZE, 0); 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(0); 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(0, 8); // Owner & Group owner = nextWord(line); group = nextWord(line); // symlink destination #ifndef Q_WS_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.insert(KIO::UDSEntry::UDS_NAME, name); // file type entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, mode & S_IFMT); // keep file type only // file permissions entry.insert(KIO::UDSEntry::UDS_ACCESS, mode & 07777); // keep permissions only // file size entry.insert(KIO::UDSEntry::UDS_SIZE, size); // modification time entry.insert(KIO::UDSEntry::UDS_MODIFICATION_TIME, time); // link destination if (!symlinkDest.isEmpty()) { 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->insert(KIO::UDSEntry::UDS_MODIFICATION_TIME, time); entryIt->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_WS_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, SIGNAL(newOutputData(KProcess*,QByteArray&)), this, SLOT(checkOutputForPassword(KProcess*,QByteArray&))); 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 (QStringList::Iterator it = path.begin(); it != path.end(); ++it) { 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(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(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_WS_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/krArc/krarc.h b/krArc/krarc.h index 8dbadf2f..de5029f1 100644 --- a/krArc/krarc.h +++ b/krArc/krarc.h @@ -1,145 +1,145 @@ /***************************************************************************** * Copyright (C) 2003 Rafi Yanai * * Copyright (C) 2003 Shie Erlich * * Copyright (C) 2004-2018 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/]. * *****************************************************************************/ #ifndef KRARC_H #define KRARC_H // QtCore #include #include #include #include #include #include #include #include #include #include "krarcbasemanager.h" #include "krlinecountingprocess.h" #include "../krusader/krdebuglogger.h" class KFileItem; class QByteArray; class QTextCodec; class kio_krarcProtocol : public QObject, public KIO::SlaveBase, public KrArcBaseManager { Q_OBJECT public: kio_krarcProtocol(const QByteArray &pool_socket, const QByteArray &app_socket); virtual ~kio_krarcProtocol(); virtual void stat(const QUrl &url) Q_DECL_OVERRIDE; virtual void get(const QUrl &url) Q_DECL_OVERRIDE; virtual void put(const QUrl &url, int permissions, KIO::JobFlags flags) Q_DECL_OVERRIDE; virtual void mkdir(const QUrl &url, int permissions) Q_DECL_OVERRIDE; virtual void listDir(const QUrl &url) Q_DECL_OVERRIDE; virtual void del(QUrl const & url, bool isFile) Q_DECL_OVERRIDE; virtual void copy(const QUrl &src, const QUrl &dest, int permissions, KIO::JobFlags flags) Q_DECL_OVERRIDE; virtual void rename(const QUrl &src, const QUrl & dest, KIO::JobFlags flags) Q_DECL_OVERRIDE; public slots: void receivedData(KProcess *, QByteArray &); void checkOutputForPassword(KProcess *, QByteArray &); protected: virtual bool initDirDict(const QUrl &url, bool forced = false); virtual bool initArcParameters(); void checkIf7zIsEncrypted(bool &, QString); virtual void parseLine(int lineNo, QString line); virtual bool setArcFile(const QUrl &url); virtual QString getPassword(); virtual void invalidatePassword(); QString getPath(const QUrl &url, QUrl::FormattingOptions options = 0); QString localeEncodedString(QString str); QByteArray encodeString(QString); QString decodeString(char *); // archive specific commands QString cmd; ///< the archiver name. QStringList listCmd; ///< list files. QStringList getCmd; ///< unpack files command. QStringList delCmd; ///< delete files command. QStringList putCmd; ///< add file command. QStringList copyCmd; ///< copy to file command. QStringList renCmd; ///< rename file command. private: void get(const QUrl &url, int tries); /** checks if a returned status ("exit code") of an archiving-related process is OK. */ bool checkStatus(int exitCode); /** service function for parseLine. */ QString nextWord(QString &s, char d = ' '); - /** translate permittion string to mode_t. */ + /** translate permission string to mode_t. */ mode_t parsePermString(QString perm); /** return the name of the directory inside the archive. */ QString findArcDirectory(const QUrl &url); /** find the UDSEntry of a file in a directory. */ KIO::UDSEntry* findFileEntry(const QUrl &url); /** add a new directory (file list container). */ KIO::UDSEntryList* addNewDir(QString path); QString fullPathName(QString name); static QString detectFullPathName(QString name); bool checkWriteSupport(); - QHash dirDict; //< the directoris data structure. + QHash dirDict; //< the directories data structure. bool encrypted; //< tells whether the archive is encrypted bool archiveChanged; //< true if the archive was changed. bool archiveChanging; //< true if the archive is currently changing. bool newArchiveURL; //< true if new archive was entered for the protocol bool noencoding; //< 7z files use UTF-16, so encoding is unnecessary KIO::filesize_t decompressedLen; //< the number of the decompressed bytes KFileItem* arcFile; //< the archive file item. QString arcPath; //< the archive location QString arcTempDir; //< the currently used temp directory. QString arcType; //< the archive type. bool extArcReady; //< Used for RPM & DEB files. QString password; //< Password for the archives KConfig krConf; //< The configuration file for krusader KConfigGroup confGrp; //< the 'Dependencies' config group QString lastData; QString encryptedArchPath; QString currentCharset; QTextCodec * codec; }; #ifdef Q_WS_WIN #define DIR_SEPARATOR "/" #define DIR_SEPARATOR2 "\\" #define DIR_SEPARATOR_CHAR '/' #define DIR_SEPARATOR_CHAR2 '\\' #define REPLACE_DIR_SEP2(x) x = x.replace( DIR_SEPARATOR2, DIR_SEPARATOR ); #define ROOT_DIR "C:\\" #define EXEC_SUFFIX ".exe" #else #define DIR_SEPARATOR "/" #define DIR_SEPARATOR2 "/" #define DIR_SEPARATOR_CHAR '/' #define DIR_SEPARATOR_CHAR2 '/' #define REPLACE_DIR_SEP2(x) #define ROOT_DIR "/" #define EXEC_SUFFIX "" #endif #endif diff --git a/krusader/ActionMan/addplaceholderpopup.h b/krusader/ActionMan/addplaceholderpopup.h index 561597ac..b20ab31c 100644 --- a/krusader/ActionMan/addplaceholderpopup.h +++ b/krusader/ActionMan/addplaceholderpopup.h @@ -1,348 +1,348 @@ /***************************************************************************** * Copyright (C) 2004 Shie Erlich * * Copyright (C) 2004 Rafi Yanai * * Copyright (C) 2004 Jonas Bähr * * Copyright (C) 2004-2018 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/]. * *****************************************************************************/ #ifndef ADDPLACEHOLDERPOPUP_H #define ADDPLACEHOLDERPOPUP_H // QtCore #include #include // QtWidgets #include #include #include "../UserAction/expander.h" class KLineEdit; class QToolButton; class QCheckBox; class KComboBox; class QSpinBox; /** * This reads Expander::placeholder[] and * fills a popup for easy access to the UserAction Placeholder */ class AddPlaceholderPopup : public QMenu { public: explicit AddPlaceholderPopup(QWidget *parent); /** * Use this to exec the popup. * @param pos Position where the popup should appear * @return the expression which can be placed in the UserAction commandline */ QString getPlaceholder(const QPoint& pos); protected: /** - * This is calles when a Placeholder got parameter. + * This is called when a Placeholder got parameter. * @param currentPlaceholder A pointer to the Placeholder the user has chosen * @return a parameter-string */ QString getParameter(exp_placeholder* currentPlaceholder); private: QMenu *_activeSub, *_otherSub, *_leftSub, *_rightSub, *_independentSub; }; //////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////// Parameter Widgets /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// /** * abstract baseclass for all Parameter widgets */ class ParameterBase : public QWidget { public: inline ParameterBase(const exp_parameter& parameter, QWidget* parent) : QWidget(parent) { _necessary = parameter.necessary(); } /** * @return the text for the parameter */ virtual QString text() = 0; /** * @return the default of the parameter */ virtual QString preset() = 0; /** * re-init the parameter with the default */ virtual void reset() = 0; /** * @return true if the Parameter as a valid value */ virtual bool valid() = 0; /** * @return true if the Placeholder really needs this parameter */ inline bool necessary() { return _necessary; } private: bool _necessary; }; /** * The simple Parameter widgets: a line-edit with the description above * used by default */ class ParameterText : public ParameterBase { public: ParameterText(const exp_parameter& parameter, QWidget* parent); QString text(); QString preset(); void reset(); bool valid(); private: KLineEdit * _lineEdit; QString _preset; }; /** * A line-edit with the "addPlaceholder"-button * used with default = "__placeholder" */ class ParameterPlaceholder : public ParameterBase { Q_OBJECT public: ParameterPlaceholder(const exp_parameter& parameter, QWidget* parent); QString text(); QString preset(); void reset(); bool valid(); private: KLineEdit * _lineEdit; QToolButton* _button; private slots: void addPlaceholder(); }; /** * A Checkbox, default: checked; retuns "No" if unchecked * used with default = "__yes" */ class ParameterYes : public ParameterBase { public: ParameterYes(const exp_parameter& parameter, QWidget* parent); QString text(); QString preset(); void reset(); bool valid(); private: QCheckBox* _checkBox; }; /** * A Checkbox, default: unchecked; retuns "Yes" if checked * used with default = "__no" */ class ParameterNo : public ParameterBase { public: ParameterNo(const exp_parameter& parameter, QWidget* parent); QString text(); QString preset(); void reset(); bool valid(); private: QCheckBox* _checkBox; }; /** * A line-edit with the "file open"-button * used with default = "__file" */ class ParameterFile : public ParameterBase { Q_OBJECT public: ParameterFile(const exp_parameter& parameter, QWidget* parent); QString text(); QString preset(); void reset(); bool valid(); private: KLineEdit * _lineEdit; QToolButton* _button; private slots: void addFile(); }; /** * A ComboBox with the description above * used with default = "__choose:item1;item2;..." */ class ParameterChoose : public ParameterBase { public: ParameterChoose(const exp_parameter& parameter, QWidget* parent); QString text(); QString preset(); void reset(); bool valid(); private: KComboBox * _combobox; }; /** - * An editable ComboBox with the predifined selections + * An editable ComboBox with the predefined selections * used with default = "__select" */ class ParameterSelect : public ParameterBase { public: ParameterSelect(const exp_parameter& parameter, QWidget* parent); QString text(); QString preset(); void reset(); bool valid(); private: KComboBox * _combobox; }; /** * A line-edit with a "choose dir"- and a bookmark-button * used with default = "__goto" */ class ParameterGoto : public ParameterBase { Q_OBJECT public: ParameterGoto(const exp_parameter& parameter, QWidget* parent); QString text(); QString preset(); void reset(); bool valid(); private: KLineEdit * _lineEdit; QToolButton* _dirButton, *_placeholderButton; private slots: void setDir(); void addPlaceholder(); }; /** * A ComboBox with all profiles available for the Synchronizer * used with default = "__syncprofile" */ class ParameterSyncprofile : public ParameterBase { public: ParameterSyncprofile(const exp_parameter& parameter, QWidget* parent); QString text(); QString preset(); void reset(); bool valid(); private: KComboBox * _combobox; }; /** * A ComboBox with all profiles available for the panels * used with default = "__panelprofile" */ class ParameterPanelprofile : public ParameterBase { public: ParameterPanelprofile(const exp_parameter& parameter, QWidget* parent); QString text(); QString preset(); void reset(); bool valid(); private: KComboBox * _combobox; }; /** * A ComboBox with all profiles available for the Searchmodule * used with default = "__searchprofile" */ class ParameterSearch : public ParameterBase { public: ParameterSearch(const exp_parameter& parameter, QWidget* parent); QString text(); QString preset(); void reset(); bool valid(); private: KComboBox * _combobox; }; /** * A SpinBox for integer * used with default = "__int:min;max;step;value" */ class ParameterInt : public ParameterBase { public: ParameterInt(const exp_parameter& parameter, QWidget* parent); QString text(); QString preset(); void reset(); bool valid(); private: QSpinBox * _spinbox; int _default; }; //////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////// ParameterDialog //////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// /** - * Opens a dialog for the parameter. Depending on the default (preset) a differend widget is used. + * Opens a dialog for the parameter. Depending on the default (preset) a different widget is used. * See Parameter-Classes for details */ class ParameterDialog : public QDialog { Q_OBJECT public: ParameterDialog(const exp_placeholder* currentPlaceholder, QWidget *parent); /** * Use this to execute the dialog. - * @return a QString with all paremeters; omitting the optional ones if they have the default-value. + * @return a QString with all parameters; omitting the optional ones if they have the default-value. */ QString getParameter(); private: typedef QList ParameterList; ParameterList _parameter; int _parameterCount; private slots: void reset(); void slotOk(); }; #endif // ADDPLACEHOLDERPOPUP_H diff --git a/krusader/ActionMan/useractionlistview.cpp b/krusader/ActionMan/useractionlistview.cpp index d89a2ec3..b1dea26d 100644 --- a/krusader/ActionMan/useractionlistview.cpp +++ b/krusader/ActionMan/useractionlistview.cpp @@ -1,255 +1,255 @@ /***************************************************************************** * Copyright (C) 2006 Jonas Bähr * * Copyright (C) 2006-2018 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 "useractionlistview.h" // QtCore #include // QtXml #include #include #include "../krglobal.h" #include "../icon.h" #include "../UserAction/kraction.h" #include "../UserAction/useraction.h" #define COL_TITLE 0 // UserActionListView UserActionListView::UserActionListView(QWidget * parent) : KrTreeWidget(parent) { setHeaderLabel(i18n("Title")); setRootIsDecorated(true); - setSelectionMode(QAbstractItemView::ExtendedSelection); // normaly select single items but one may use Ctrl or Shift to select multiple + setSelectionMode(QAbstractItemView::ExtendedSelection); // normally select single items but one may use Ctrl or Shift to select multiple setSortingEnabled(true); sortItems(COL_TITLE, Qt::AscendingOrder); connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(slotCurrentItemChanged(QTreeWidgetItem*))); update(); } UserActionListView::~UserActionListView() { } QSize UserActionListView::sizeHint() const { return QSize(200, 400); } void UserActionListView::update() { clear(); UserAction::KrActionList list = krUserAction->actionList(); QListIterator it(list); while (it.hasNext()) insertAction(it.next()); } void UserActionListView::update(KrAction* action) { UserActionListViewItem* item = findActionItem(action); if (item) { - // deleting & re-inserting is _much_easyer then tracking all possible cases of category changes! + // deleting & re-inserting is _much_easier then tracking all possible cases of category changes! bool current = (item == currentItem()); bool selected = item->isSelected(); delete item; item = insertAction(action); if (current) setCurrentItem(item); if (selected) item->setSelected(true); } } UserActionListViewItem* UserActionListView::insertAction(KrAction* action) { if (! action) return 0; UserActionListViewItem* item; if (action->category().isEmpty()) item = new UserActionListViewItem(this, action); else { QTreeWidgetItem* categoryItem = findCategoryItem(action->category()); if (! categoryItem) { categoryItem = new QTreeWidgetItem(this); // create the new category item it not already present categoryItem->setText(0, action->category()); categoryItem->setFlags(Qt::ItemIsEnabled); } item = new UserActionListViewItem(categoryItem, action); } item->setAction(action); return item; } QTreeWidgetItem* UserActionListView::findCategoryItem(const QString& category) { QTreeWidgetItemIterator it(this); while (*it) { if ((*it)->text(COL_TITLE) == category && !((*it)->flags() & Qt::ItemIsSelectable)) return *it; it++; } return 0; } UserActionListViewItem* UserActionListView::findActionItem(const KrAction* action) { QTreeWidgetItemIterator it(this); while (*it) { if (UserActionListViewItem* item = dynamic_cast(*it)) { if (item->action() == action) return item; } it++; } return 0; } KrAction * UserActionListView::currentAction() const { if (UserActionListViewItem* item = dynamic_cast(currentItem())) return item->action(); else return 0; } void UserActionListView::setCurrentAction(const KrAction* action) { UserActionListViewItem* item = findActionItem(action); if (item) { setCurrentItem(item); } } void UserActionListView::setFirstActionCurrent() { QTreeWidgetItemIterator it(this); while (*it) { if (UserActionListViewItem* item = dynamic_cast(*it)) { setCurrentItem(item); break; } it++; } } void UserActionListView::slotCurrentItemChanged(QTreeWidgetItem* item) { if (! item) return; scrollTo(indexOf(item)); } QDomDocument UserActionListView::dumpSelectedActions(QDomDocument* mergeDoc) const { QList list = selectedItems(); QDomDocument doc; if (mergeDoc) doc = *mergeDoc; else doc = UserAction::createEmptyDoc(); QDomElement root = doc.documentElement(); for (int i = 0; i < list.size(); ++i) { QTreeWidgetItem* item = list.at(i); if (UserActionListViewItem* actionItem = dynamic_cast(item)) root.appendChild(actionItem->action()->xmlDump(doc)); } return doc; } void UserActionListView::removeSelectedActions() { QList list = selectedItems(); for (int i = 0; i < list.size(); ++i) { QTreeWidgetItem* item = list.at(i); if (UserActionListViewItem* actionItem = dynamic_cast(item)) { delete actionItem->action(); // remove the action itself delete actionItem; // remove the action from the list } // if } } // UserActionListViewItem UserActionListViewItem::UserActionListViewItem(QTreeWidget* view, KrAction* action) : QTreeWidgetItem(view) { setAction(action); } UserActionListViewItem::UserActionListViewItem(QTreeWidgetItem* item, KrAction * action) : QTreeWidgetItem(item) { setAction(action); } UserActionListViewItem::~UserActionListViewItem() { } void UserActionListViewItem::setAction(KrAction * action) { if (! action) return; _action = action; update(); } KrAction * UserActionListViewItem::action() const { return _action; } void UserActionListViewItem::update() { if (! _action) return; if (! _action->icon().isNull()) setIcon(COL_TITLE, Icon(_action->iconName())); setText(COL_TITLE, _action->text()); } bool UserActionListViewItem::operator<(const QTreeWidgetItem &other) const { // FIXME some how this only produces bullshit :-/ // if ( i->text( COL_NAME ).isEmpty() ) { // categories only have titles // //qDebug() << "this->title: " << text(COL_TITLE) << " |=| i->title: " << i->text(COL_TITLE); // return ( ascending ? -1 : 1 ); // <0 means this is smaller then i // } // else return QTreeWidgetItem::operator<(other); } diff --git a/krusader/ActionMan/useractionpage.cpp b/krusader/ActionMan/useractionpage.cpp index fb064e68..97c2be8c 100644 --- a/krusader/ActionMan/useractionpage.cpp +++ b/krusader/ActionMan/useractionpage.cpp @@ -1,356 +1,356 @@ /***************************************************************************** * Copyright (C) 2006 Shie Erlich * * Copyright (C) 2006 Rafi Yanai * * Copyright (C) 2006-2018 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 "useractionpage.h" // QtWidgets #include #include #include #include #include #include // QtGui #include // QtXml #include #include #include #include #include #include "actionproperty.h" #include "useractionlistview.h" #include "../UserAction/useraction.h" #include "../UserAction/kraction.h" #include "../krusader.h" #include "../krglobal.h" #include "../icon.h" //This is the filter in the QFileDialog of Import/Export: static const char* FILE_FILTER = I18N_NOOP("*.xml|XML files\n*|All files"); UserActionPage::UserActionPage(QWidget* parent) : QWidget(parent) { QVBoxLayout* layout = new QVBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(6); // 0px margin, 6px item-spacing // ======== pseudo-toolbar start ======== QHBoxLayout* toolbarLayout = new QHBoxLayout; // neither margin nor spacing for the toolbar with autoRaise toolbarLayout->setSpacing(0); toolbarLayout->setContentsMargins(0, 0, 0, 0); newButton = new QToolButton(this); newButton->setIcon(Icon("document-new")); newButton->setAutoRaise(true); newButton->setToolTip(i18n("Create new useraction")); importButton = new QToolButton(this); importButton->setIcon(Icon("document-import")); importButton->setAutoRaise(true); importButton->setToolTip(i18n("Import useractions")); exportButton = new QToolButton(this); exportButton->setIcon(Icon("document-export")); exportButton->setAutoRaise(true); exportButton->setToolTip(i18n("Export useractions")); copyButton = new QToolButton(this); copyButton->setIcon(Icon("edit-copy")); copyButton->setAutoRaise(true); copyButton->setToolTip(i18n("Copy useractions to clipboard")); pasteButton = new QToolButton(this); pasteButton->setIcon(Icon("edit-paste")); pasteButton->setAutoRaise(true); pasteButton->setToolTip(i18n("Paste useractions from clipboard")); removeButton = new QToolButton(this); removeButton->setIcon(Icon("edit-delete")); removeButton->setAutoRaise(true); removeButton->setToolTip(i18n("Delete selected useractions")); toolbarLayout->addWidget(newButton); toolbarLayout->addWidget(importButton); toolbarLayout->addWidget(exportButton); toolbarLayout->addWidget(copyButton); toolbarLayout->addWidget(pasteButton); toolbarLayout->addSpacing(6); // 6 pixel nothing toolbarLayout->addWidget(removeButton); toolbarLayout->addStretch(1000); // some very large stretch-factor // ======== pseudo-toolbar end ======== /* This seems obsolete now! // Display some help KMessageBox::information( this, // parent i18n( "When you apply changes to an action, the modifications " "become available in the current session immediately.\n" "When closing ActionMan, you will be asked to save the changes permanently." ), QString(), // caption "show UserAction help" //dontShowAgainName for the config ); */ layout->addLayout(toolbarLayout); QSplitter *split = new QSplitter(this); layout->addWidget(split, 1000); // again a very large stretch-factor to fix the height of the toolbar actionTree = new UserActionListView(split); actionTree->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); actionProperties = new ActionProperty(split); actionProperties->setEnabled(false); // if there are any actions in the list, the first is displayed and this widget is enabled connect(actionTree, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(slotChangeCurrent())); connect(newButton, SIGNAL(clicked()), SLOT(slotNewAction())); connect(removeButton, SIGNAL(clicked()), SLOT(slotRemoveAction())); connect(importButton, SIGNAL(clicked()), SLOT(slotImport())); connect(exportButton, SIGNAL(clicked()), SLOT(slotExport())); connect(copyButton, SIGNAL(clicked()), SLOT(slotToClip())); connect(pasteButton, SIGNAL(clicked()), SLOT(slotFromClip())); // forwards the changed signal of the properties connect(actionProperties, SIGNAL(changed()), SIGNAL(changed())); actionTree->setFirstActionCurrent(); actionTree->setFocus(); } UserActionPage::~UserActionPage() { } bool UserActionPage::continueInSpiteOfChanges() { if (! actionProperties->isModified()) return true; int answer = KMessageBox::questionYesNoCancel(this, i18n("The current action has been modified. Do you want to apply these changes?") ); if (answer == KMessageBox::Cancel) { disconnect(actionTree, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(slotChangeCurrent())); actionTree->setCurrentAction(actionProperties->action()); connect(actionTree, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(slotChangeCurrent())); return false; } if (answer == KMessageBox::Yes) { if (! actionProperties->validProperties()) { disconnect(actionTree, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(slotChangeCurrent())); actionTree->setCurrentAction(actionProperties->action()); connect(actionTree, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(slotChangeCurrent())); return false; } slotUpdateAction(); } // if Yes return true; } void UserActionPage::slotChangeCurrent() { if (! continueInSpiteOfChanges()) return; KrAction* action = actionTree->currentAction(); if (action) { actionProperties->setEnabled(true); - // the discinct name is used as ID it is not allowd to change it afterwards because it is may referenced anywhere else + // the distinct name is used as ID it is not allowed to change it afterwards because it is may referenced anywhere else actionProperties->leDistinctName->setEnabled(false); actionProperties->updateGUI(action); } else { - // If the current item in the tree is no action (i.e. a cathegory), disable the properties + // If the current item in the tree is no action (i.e. a category), disable the properties actionProperties->clear(); actionProperties->setEnabled(false); } emit applied(); // to disable the apply-button } void UserActionPage::slotUpdateAction() { // check that we have a command line, title and a name if (! actionProperties->validProperties()) return; if (actionProperties->leDistinctName->isEnabled()) { // := new entry KrAction* action = new KrAction(krApp->actionCollection(), actionProperties->leDistinctName->text()); krUserAction->addKrAction(action); actionProperties->updateAction(action); UserActionListViewItem* item = actionTree->insertAction(action); actionTree->setCurrentItem(item); } else { // := edit an existing actionProperties->updateAction(); actionTree->update(actionProperties->action()); // update the listviewitem as well... } apply(); } void UserActionPage::slotNewAction() { if (continueInSpiteOfChanges()) { actionTree->clearSelection(); // else the user may think that he is overwriting the selected action actionProperties->clear(); actionProperties->setEnabled(true); // it may be disabled because the tree has the focus on a category actionProperties->leDistinctName->setEnabled(true); actionProperties->leDistinctName->setFocus(); } } void UserActionPage::slotRemoveAction() { if (! dynamic_cast(actionTree->currentItem())) return; int messageDelete = KMessageBox::warningContinueCancel(this, //parent i18n("Are you sure that you want to remove all selected actions?"), //text i18n("Remove Selected Actions?"), //caption KStandardGuiItem::remove(), //Label for the continue-button KStandardGuiItem::cancel(), "Confirm Remove UserAction", //dontAskAgainName (for the config-file) KMessageBox::Dangerous | KMessageBox::Notify); if (messageDelete != KMessageBox::Continue) return; actionProperties->clear(); actionProperties->setEnabled(false); actionTree->removeSelectedActions(); apply(); } void UserActionPage::slotImport() { QString filename = QFileDialog::getOpenFileName(this, QString(), QString(), i18n(FILE_FILTER)); if (filename.isEmpty()) return; UserAction::KrActionList newActions; krUserAction->readFromFile(filename, UserAction::renameDoublicated, &newActions); QListIterator it(newActions); while (it.hasNext()) actionTree->insertAction(it.next()); if (newActions.count() > 0) { apply(); } } void UserActionPage::slotExport() { if (! dynamic_cast(actionTree->currentItem())) return; QString filename = QFileDialog::getSaveFileName(this, QString(), QString(), i18n(FILE_FILTER)); if (filename.isEmpty()) return; QDomDocument doc = QDomDocument(ACTION_DOCTYPE); QFile file(filename); int answer = 0; if (file.open(QIODevice::ReadOnly)) { // getting here, means the file already exists an can be read if (doc.setContent(&file)) // getting here means the file exists and already contains an UserAction-XML-tree answer = KMessageBox::warningYesNoCancel(this, //parent i18n("This file already contains some useractions.\nDo you want to overwrite it or should it be merged with the selected actions?"), //text i18n("Overwrite or Merge?"), //caption KStandardGuiItem::overwrite(), //label for Yes-Button KGuiItem(i18n("Merge")) //label for No-Button ); file.close(); } if (answer == 0 && file.exists()) answer = KMessageBox::warningContinueCancel(this, //parent i18n("This file already exists. Do you want to overwrite it?"), //text i18n("Overwrite Existing File?"), //caption KStandardGuiItem::overwrite() //label for Continue-Button ); if (answer == KMessageBox::Cancel) return; if (answer == KMessageBox::No) // that means the merge-button doc = actionTree->dumpSelectedActions(&doc); // merge else // Yes or Continue means overwrite doc = actionTree->dumpSelectedActions(); bool success = UserAction::writeToFile(doc, filename); if (! success) KMessageBox::error(this, i18n("Cannot open %1 for writing.\nNothing exported.", filename), i18n("Export Failed") ); } void UserActionPage::slotToClip() { if (! dynamic_cast(actionTree->currentItem())) return; QDomDocument doc = actionTree->dumpSelectedActions(); QApplication::clipboard()->setText(doc.toString()); } void UserActionPage::slotFromClip() { QDomDocument doc(ACTION_DOCTYPE); if (doc.setContent(QApplication::clipboard()->text())) { QDomElement root = doc.documentElement(); UserAction::KrActionList newActions; krUserAction->readFromElement(root, UserAction::renameDoublicated, &newActions); QListIterator it(newActions); while (it.hasNext()) actionTree->insertAction(it.next()); if (newActions.count() > 0) { apply(); } } // if ( doc.setContent ) } bool UserActionPage::readyToQuit() { // Check if the current UserAction has changed if (! continueInSpiteOfChanges()) return false; krUserAction->writeActionFile(); return true; } void UserActionPage::apply() { krUserAction->writeActionFile(); emit applied(); } void UserActionPage::applyChanges() { slotUpdateAction(); } diff --git a/krusader/ActionMan/useractionpage.h b/krusader/ActionMan/useractionpage.h index 7c59f1cc..1f3b833c 100644 --- a/krusader/ActionMan/useractionpage.h +++ b/krusader/ActionMan/useractionpage.h @@ -1,82 +1,82 @@ /***************************************************************************** * Copyright (C) 2006 Shie Erlich * * Copyright (C) 2006 Rafi Yanai * * Copyright (C) 2006-2018 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/]. * *****************************************************************************/ #ifndef USERACTIONPAGE_H #define USERACTIONPAGE_H // QtWidgets #include class UserActionListView; class ActionProperty; class QToolButton; class UserActionPage : public QWidget { Q_OBJECT public: explicit UserActionPage(QWidget* parent); ~UserActionPage(); /** * Be sure to call this function before you delete this page!! * @return true if this page can be closed */ bool readyToQuit(); void applyChanges(); signals: void changed(); ///< emitted on changes to an action (used to enable the apply-button) void applied(); ///< emitted when changes are applied to an action (used to disable the apply-button) private: /** * If there are modifications in the property-widget, the user is asked * what to do. Apply, discard or continue editing. In the first case, * saving is done in this function. * @return true if a new action can be loaded in the property-widget. */ bool continueInSpiteOfChanges(); /** - * applyes all changes by writing the actionfile and emits "applied" + * applies all changes by writing the actionfile and emits "applied" */ void apply(); //bool _modified; ///< true if the action-tree was changed (= changes were applied to an action) UserActionListView *actionTree; ActionProperty *actionProperties; QToolButton *importButton, *exportButton; QToolButton *copyButton, *pasteButton; QToolButton *removeButton, *newButton; private slots: void slotChangeCurrent(); //loads a new action into the detail-view void slotUpdateAction(); //updates the action to the xml-file void slotNewAction(); void slotRemoveAction(); void slotImport(); void slotExport(); void slotToClip(); void slotFromClip(); }; #endif diff --git a/krusader/Dialogs/krspecialwidgets.cpp b/krusader/Dialogs/krspecialwidgets.cpp index fabe0d6b..8ed7936b 100644 --- a/krusader/Dialogs/krspecialwidgets.cpp +++ b/krusader/Dialogs/krspecialwidgets.cpp @@ -1,218 +1,218 @@ /***************************************************************************** * Copyright (C) 2000 Shie Erlich * * Copyright (C) 2000 Rafi Yanai * * Copyright (C) 2004-2018 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 "krspecialwidgets.h" #include "krmaskchoice.h" #include "newftpgui.h" #include "../krglobal.h" // QtGui #include #include ///////////////////////////////////////////////////////////////////////////// /////////////////////// Pie related widgets ///////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // The pie-related widgets use hard-coded coordinates to create the look. // This is ok since the whole widget is fitted into an existing view and thus // no re-alignments are needed. #define LEFT 10 #define BOTTOM 150 #define WIDTH 120 #define HEIGHT 40 #define Z_HEIGHT 10 #define STARTANGLE 0 #define DEG(x) (16*(x)) QColor KRPie::colors[ 12 ] = {Qt::red, Qt::blue, Qt::green, Qt::cyan, Qt::magenta, Qt::gray, Qt::black, Qt::white, Qt::darkRed, Qt::darkBlue, Qt::darkMagenta, Qt::darkCyan }; ////////////////////////////////////////////////////////////////////////////// /////////////// KRFSDisplay - Filesystem / Freespace Display ///////////////// ////////////////////////////////////////////////////////////////////////////// // This is the full constructor: use it for a mounted filesystem KRFSDisplay::KRFSDisplay(QWidget *parent, QString _alias, QString _realName, KIO::filesize_t _total, KIO::filesize_t _free) : QWidget(parent), totalSpace(_total), freeSpace(_free), alias(_alias), realName(_realName), mounted(true), empty(false), supermount(false) { int leftMargin, topMargin, rightMargin, bottomMargin; getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin); resize(150 + leftMargin + rightMargin, 200 + topMargin + bottomMargin); setMinimumSize(150 + leftMargin + rightMargin, 200 + topMargin + bottomMargin); show(); } // Use this one for an unmounted filesystem KRFSDisplay::KRFSDisplay(QWidget *parent, QString _alias, QString _realName, bool sm) : QWidget(parent), alias(_alias), realName(_realName), mounted(false), empty(false), supermount(sm) { int leftMargin, topMargin, rightMargin, bottomMargin; getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin); resize(150 + leftMargin + rightMargin, 200 + topMargin + bottomMargin); setMinimumSize(150 + leftMargin + rightMargin, 200 + topMargin + bottomMargin); show(); } // This is used only when an empty widget needs to be displayed (for example: // when filesystem statistics haven't been calculated yet) KRFSDisplay::KRFSDisplay(QWidget *parent) : QWidget(parent), empty(true) { int leftMargin, topMargin, rightMargin, bottomMargin; getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin); resize(150 + leftMargin + rightMargin, 200 + topMargin + bottomMargin); setMinimumSize(150 + leftMargin + rightMargin, 200 + topMargin + bottomMargin); show(); } // The main painter! void KRFSDisplay::paintEvent(QPaintEvent *) { QPainter paint(this); if (!empty) { int leftMargin, topMargin, rightMargin, bottomMargin; getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin); // create the text // first, name and location QFont font = paint.font(); font.setWeight(QFont::Bold); paint.setFont(font); paint.drawText(leftMargin + 10, topMargin + 20, alias); font.setWeight(QFont::Normal); paint.setFont(font); paint.drawText(leftMargin + 10, topMargin + 37, '(' + realName + ')'); if (mounted) { // incase the filesystem is already mounted // second, the capacity paint.drawText(leftMargin + 10, topMargin + 70, i18n("Capacity: %1", KIO::convertSizeFromKiB(totalSpace))); // third, the 2 boxes (used, free) QPen systemPen = paint.pen(); paint.setPen(Qt::black); paint.drawRect(leftMargin + 10, topMargin + 90, 10, 10); paint.fillRect(leftMargin + 11, topMargin + 91, 8, 8, QBrush(Qt::gray)); paint.drawRect(leftMargin + 10, topMargin + 110, 10, 10); paint.fillRect(leftMargin + 11, topMargin + 111, 8, 8, QBrush(Qt::white)); // now, the text for the boxes paint.setPen(systemPen); paint.drawText(leftMargin + 25, topMargin + 100, i18n("Used: %1", KIO::convertSizeFromKiB(totalSpace - freeSpace))); paint.drawText(leftMargin + 25, topMargin + 120, i18n("Free: %1", KIO::convertSizeFromKiB(freeSpace))); // first, create the empty pie // bottom... paint.setPen(Qt::black); paint.setBrush(Qt::white); paint.drawPie(leftMargin + LEFT, topMargin + BOTTOM, WIDTH, HEIGHT, STARTANGLE, DEG(360)); // body... paint.setPen(Qt::lightGray); for (int i = 1; i < Z_HEIGHT; ++i) paint.drawPie(leftMargin + LEFT, topMargin + BOTTOM - i, WIDTH, HEIGHT, STARTANGLE, DEG(360)); // side lines... paint.setPen(Qt::black); paint.drawLine(leftMargin + LEFT, topMargin + BOTTOM + HEIGHT / 2, LEFT, BOTTOM + HEIGHT / 2 - Z_HEIGHT); paint.drawLine(leftMargin + LEFT + WIDTH, topMargin + BOTTOM + HEIGHT / 2, LEFT + WIDTH, BOTTOM + HEIGHT / 2 - Z_HEIGHT); // top of the pie paint.drawPie(leftMargin + LEFT, topMargin + BOTTOM - Z_HEIGHT, WIDTH, HEIGHT, STARTANGLE, DEG(360)); // the "used space" slice float i = ((float)(totalSpace - freeSpace) / (totalSpace)) * 360.0; paint.setBrush(Qt::gray); paint.drawPie(leftMargin + LEFT, topMargin + BOTTOM - Z_HEIGHT, WIDTH, HEIGHT, STARTANGLE, (int) DEG(i)); // if we need to draw a 3d stripe ... if (i > 180.0) { for (int j = 1; j < Z_HEIGHT; ++j) paint.drawArc(leftMargin + LEFT, topMargin + BOTTOM - j, WIDTH, HEIGHT, STARTANGLE - 16 * 180, (int)(DEG(i - 180.0))); } } else { // if the filesystem is unmounted... font.setWeight(QFont::Bold); paint.setFont(font); paint.drawText(leftMargin + 10, topMargin + 60, i18n("Not mounted.")); } } else { // if the widget is in empty situation... } } //////////////////////////////////////////////////////////////////////////////// KRPie::KRPie(KIO::filesize_t _totalSize, QWidget *parent) : QWidget(parent), totalSize(_totalSize) { slices.push_back(KRPieSlice(100, Qt::yellow, "DEFAULT")); sizeLeft = totalSize; resize(300, 300); } void KRPie::paintEvent(QPaintEvent *) { QPainter paint(this); // now create the slices float sAngle = STARTANGLE; for (int ndx = 0; ndx != slices.count(); ndx++) { paint.setBrush(slices[ndx].getColor()); paint.setPen(slices[ndx].getColor()); // angles are negative to create a clock-wise drawing of slices float angle = -(slices[ndx].getPerct() / 100 * 360) * 16; for (int i = 1; i < Z_HEIGHT; ++i) paint.drawPie(LEFT, BOTTOM + i, WIDTH, HEIGHT, (int) sAngle, (int) angle); sAngle += angle; } paint.setPen(Qt::yellow); // pen paint.setBrush(Qt::yellow); // fill // for (int i=1; i * * Copyright (C) 2004-2018 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/]. * *****************************************************************************/ #ifndef FILETREE_H #define FILETREE_H #include #include #include #include #include // TODO these are pointlessly general purpose now, make them incredibly specific typedef KIO::filesize_t FileSize; template class Iterator; template class ConstIterator; template class Chain; template class Link { public: explicit Link(T* const t) : prev(this), next(this), data(t) {} Link() : prev(this), next(this), data(0) {} //TODO unlinking is slow and you don't use it very much in this context. // ** Perhaps you can make a faster deletion system that doesn't bother tidying up first // ** and then you MUST call some kind of detach() function when you remove elements otherwise ~Link() { delete data; unlink(); } friend class Iterator; friend class ConstIterator; friend class Chain; private: void unlink() { prev->next = next; next->prev = prev; prev = next = this; } Link* prev; Link* next; T* data; //ensure only iterators have access to this }; template class Iterator { public: - Iterator() : link(0) { } //**** remove this, remove this REMOVE THIS!!! dangerous as your implementation doesn't test for null links, always assumes they can be derefenced + Iterator() : link(0) { } //**** remove this, remove this REMOVE THIS!!! dangerous as your implementation doesn't test for null links, always assumes they can be dereferenced explicit Iterator(Link *p) : link(p) { } bool operator==(const Iterator& it) const { return link == it.link; } bool operator!=(const Iterator& it) const { return link != it.link; } bool operator!=(const Link *p) const { return p != link; } //here we have a choice, really I should make two classes one const the other not const T* operator*() const { return link->data; } T* operator*() { return link->data; } Iterator& operator++() { link = link->next; return *this; } //**** does it waste time returning in places where we don't use the retval? bool isNull() const { return (link == 0); } //REMOVE WITH ABOVE REMOVAL you don't want null iterators to be possible void transferTo(Chain &chain) { chain.append(remove()); } T* remove() { //remove from list, delete Link, data is returned NOT deleted T* const d = link->data; Link* const p = link->prev; link->data = 0; delete link; link = p; //make iterator point to previous element, YOU must check this points to an element return d; } private: Link *link; }; template class ConstIterator { public: explicit ConstIterator(Link *p) : link(p) { } bool operator==(const Iterator& it) const { return link == it.link; } bool operator!=(const Iterator& it) const { return link != it.link; } bool operator!=(const Link *p) const { return p != link; } const T* operator*() const { return link->data; } ConstIterator& operator++() { link = link->next; return *this; } private: const Link *link; }; //**** try to make a generic list class and then a brief full list template that inlines // thus reducing code bloat template class Chain { public: Chain() { } virtual ~Chain() { empty(); } void append(T* const data) { Link* const link = new Link(data); link->prev = head.prev; link->next = &head; head.prev->next = link; head.prev = link; } void transferTo(Chain &c) { if (isEmpty()) return; Link* const first = head.next; Link* const last = head.prev; head.unlink(); first->prev = c.head.prev; c.head.prev->next = first; last->next = &c.head; c.head.prev = last; } void empty() { while (head.next != &head) { delete head.next; } } Iterator iterator() const { return Iterator(head.next); } ConstIterator constIterator() const { return ConstIterator(head.next); } const Link *end() const { return &head; } bool isEmpty() const { return (head.next == &head); } private: Link head; void operator=(const Chain&) {} }; class Directory; class File { protected: Directory *m_parent; //0 if this is treeRoot QString m_name; //< file name QString m_directory;//< the directory of the file FileSize m_size; //< size with subdirectories FileSize m_ownSize; //< size without subdirectories mode_t m_mode; //< file mode QString m_owner; //< file owner name QString m_group; //< file group name QString m_perm; //< file permissions string time_t m_time; //< file modification in time_t format bool m_symLink; //< true if the file is a symlink QString m_mimeType; //< file mimetype bool m_excluded; //< flag if the file is excluded from du int m_percent; //< percent flag public: File(Directory *parentIn, const QString &nameIn, const QString &dir, FileSize sizeIn, mode_t modeIn, const QString &ownerIn, const QString &groupIn, const QString &permIn, time_t timeIn, bool symLinkIn, const QString &mimeTypeIn) : m_parent(parentIn), m_name(nameIn), m_directory(dir), m_size(sizeIn), m_ownSize(sizeIn), m_mode(modeIn), m_owner(ownerIn), m_group(groupIn), m_perm(permIn), m_time(timeIn), m_symLink(symLinkIn), m_mimeType(mimeTypeIn), m_excluded(false), m_percent(-1) {} File(const QString &nameIn, FileSize sizeIn) : m_parent(0), m_name(nameIn), m_directory(QString()), m_size(sizeIn), m_ownSize(sizeIn), m_mode(0), m_owner(QString()), m_group(QString()), m_perm(QString()), m_time(-1), m_symLink(false), m_mimeType(QString()), m_excluded(false), m_percent(-1) { } virtual ~File() {} inline const QString & name() const { return m_name; } inline const QString & directory() const { return m_directory; } inline FileSize size() const { return m_excluded ? 0 : m_size; } inline FileSize ownSize() const { return m_excluded ? 0 : m_ownSize; } inline mode_t mode() const { return m_mode; } inline const QString & owner() const { return m_owner; } inline const QString & group() const { return m_group; } inline const QString & perm() const { return m_perm; } inline time_t time() const { return m_time; } inline const QString & mime() const { return m_mimeType; } inline bool isSymLink() const { return m_symLink; } virtual bool isDir() const { return false; } inline bool isExcluded() const { return m_excluded; } inline void exclude(bool flag) { m_excluded = flag; } inline int intPercent() const { return m_percent; } inline const QString percent() const { if (m_percent < 0) return "INV"; QString buf; buf.sprintf("%d.%02d%%", m_percent / 100, m_percent % 100); return buf; } inline void setPercent(int p) { m_percent = p; } inline const Directory* parent() const { return m_parent; } inline void setSizes(KIO::filesize_t totalSize, KIO::filesize_t ownSize) { m_ownSize = ownSize; m_size = totalSize; } enum UnitPrefix { kilo, mega, giga, tera }; static const FileSize DENOMINATOR[4]; static const char PREFIX[5][2]; QString fullPath(const Directory* = 0) const; QString humanReadableSize(UnitPrefix key = mega) const; static QString humanReadableSize(FileSize size, UnitPrefix Key = mega); friend class Directory; }; //TODO when you modify this to take into account hardlinks you should make the Chain layered not inherited class Directory : public Chain, public File { public: Directory(Directory *parentIn, const QString &nameIn, const QString &dir, FileSize sizeIn, mode_t modeIn, const QString &ownerIn, const QString &groupIn, const QString &permIn, time_t timeIn, bool symLinkIn, const QString &mimeTypeIn) : File(parentIn, nameIn, dir, sizeIn, modeIn, ownerIn, groupIn, permIn, timeIn, symLinkIn, mimeTypeIn), m_fileCount(0) {} Directory(const QString &name, QString url) : File(name, 0), m_fileCount(0) { m_directory = url; } virtual ~Directory() {} virtual bool isDir() const { return true; } void append(File *p) { ++m_fileCount; Directory *parent = m_parent; while (parent) { parent->m_fileCount++; parent = parent->m_parent; } Chain::append(p); p->m_parent = this; } void remove(File *p) { for (Iterator it = Chain::iterator(); it != Chain::end(); ++it) if ((*it) == p) { --m_fileCount; Directory *parent = m_parent; while (parent) { parent->m_fileCount--; parent = parent->m_parent; } it.remove(); break; } } uint fileCount() const { return m_fileCount; } private: Directory(const Directory&); void operator=(const Directory&); uint m_fileCount; }; #endif diff --git a/krusader/DiskUsage/radialMap/labels.cpp b/krusader/DiskUsage/radialMap/labels.cpp index ae4b2a1f..765e8a9e 100644 --- a/krusader/DiskUsage/radialMap/labels.cpp +++ b/krusader/DiskUsage/radialMap/labels.cpp @@ -1,366 +1,366 @@ /***************************************************************************** * Copyright (C) 2003-2004 Max Howell * * Copyright (C) 2004-2018 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/]. * *****************************************************************************/ // QtCore #include // QtGui #include #include #include #include #include "Config.h" #include "fileTree.h" #include "radialMap.h" #include "sincos.h" #include "widget.h" namespace RadialMap { struct Label { Label(const RadialMap::Segment *s, int l) : segment(s), lvl(l), a(segment->start() + (segment->length() / 2)) { } bool tooClose(const int &aa) const { return (a > aa - LABEL_ANGLE_MARGIN && a < aa + LABEL_ANGLE_MARGIN); } const RadialMap::Segment *segment; const unsigned int lvl; const int a; int x1, y1, x2, y2, x3; int tx, ty; QString qs; }; class LabelList : public QList