summaryrefslogtreecommitdiffstats
path: root/krusader
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-22 18:58:28 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-22 18:58:28 +0000
commit83b9bf0e3bfb1d842b10b80bbe749095b2c661a1 (patch)
treeb05b1793361693ae88106648c2a953bed988f423 /krusader
downloadkrusader-83b9bf0e3bfb1d842b10b80bbe749095b2c661a1.tar.gz
krusader-83b9bf0e3bfb1d842b10b80bbe749095b2c661a1.zip
Added old KDE3 version of Krusader
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/krusader@1094427 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'krusader')
-rw-r--r--krusader/ActionMan/Makefile.am14
-rw-r--r--krusader/ActionMan/actionman.cpp60
-rw-r--r--krusader/ActionMan/actionman.h36
-rw-r--r--krusader/ActionMan/actionproperty.cpp470
-rw-r--r--krusader/ActionMan/actionproperty.h146
-rw-r--r--krusader/ActionMan/actionpropertybase.cpp463
-rw-r--r--krusader/ActionMan/actionpropertybase.ui1125
-rw-r--r--krusader/ActionMan/addplaceholderpopup.cpp582
-rw-r--r--krusader/ActionMan/addplaceholderpopup.h318
-rw-r--r--krusader/ActionMan/useractionlistview.cpp232
-rw-r--r--krusader/ActionMan/useractionlistview.h81
-rw-r--r--krusader/ActionMan/useractionpage.cpp317
-rw-r--r--krusader/ActionMan/useractionpage.h73
-rw-r--r--krusader/BookMan/Makefile.am11
-rw-r--r--krusader/BookMan/kraddbookmarkdlg.cpp117
-rw-r--r--krusader/BookMan/kraddbookmarkdlg.h39
-rw-r--r--krusader/BookMan/krbookmark.cpp92
-rw-r--r--krusader/BookMan/krbookmark.h45
-rw-r--r--krusader/BookMan/krbookmarkbutton.cpp38
-rw-r--r--krusader/BookMan/krbookmarkbutton.h23
-rw-r--r--krusader/BookMan/krbookmarkhandler.cpp576
-rw-r--r--krusader/BookMan/krbookmarkhandler.h63
-rw-r--r--krusader/Dialogs/Makefile.am22
-rw-r--r--krusader/Dialogs/checksumdlg.cpp603
-rw-r--r--krusader/Dialogs/checksumdlg.h54
-rw-r--r--krusader/Dialogs/krdialogs.cpp255
-rw-r--r--krusader/Dialogs/krdialogs.h115
-rw-r--r--krusader/Dialogs/krkeydialog.cpp157
-rw-r--r--krusader/Dialogs/krkeydialog.h37
-rw-r--r--krusader/Dialogs/krmaskchoice.cpp179
-rw-r--r--krusader/Dialogs/krmaskchoice.h76
-rw-r--r--krusader/Dialogs/krpleasewait.cpp153
-rw-r--r--krusader/Dialogs/krpleasewait.h82
-rw-r--r--krusader/Dialogs/krprogress.cpp270
-rw-r--r--krusader/Dialogs/krprogress.h86
-rw-r--r--krusader/Dialogs/krspecialwidgets.cpp239
-rw-r--r--krusader/Dialogs/krspecialwidgets.h126
-rw-r--r--krusader/Dialogs/krspwidgets.cpp316
-rw-r--r--krusader/Dialogs/krspwidgets.h110
-rw-r--r--krusader/Dialogs/krsqueezedtextlabel.cpp80
-rw-r--r--krusader/Dialogs/krsqueezedtextlabel.h44
-rw-r--r--krusader/Dialogs/kurllistrequester.cpp202
-rw-r--r--krusader/Dialogs/kurllistrequester.h76
-rw-r--r--krusader/Dialogs/newftpgui.cpp185
-rw-r--r--krusader/Dialogs/newftpgui.h54
-rw-r--r--krusader/Dialogs/packgui.cpp120
-rw-r--r--krusader/Dialogs/packgui.h53
-rw-r--r--krusader/Dialogs/packguibase.cpp468
-rw-r--r--krusader/Dialogs/packguibase.h109
-rw-r--r--krusader/Dialogs/percentalsplitter.cpp193
-rw-r--r--krusader/Dialogs/percentalsplitter.h58
-rw-r--r--krusader/Dialogs/popularurls.cpp307
-rw-r--r--krusader/Dialogs/popularurls.h84
-rw-r--r--krusader/DiskUsage/Makefile.am17
-rw-r--r--krusader/DiskUsage/diskusage.cpp1147
-rw-r--r--krusader/DiskUsage/diskusage.h204
-rw-r--r--krusader/DiskUsage/diskusagegui.cpp227
-rw-r--r--krusader/DiskUsage/diskusagegui.h89
-rw-r--r--krusader/DiskUsage/dufilelight.cpp236
-rw-r--r--krusader/DiskUsage/dufilelight.h80
-rw-r--r--krusader/DiskUsage/dulines.cpp522
-rw-r--r--krusader/DiskUsage/dulines.h78
-rw-r--r--krusader/DiskUsage/dulistview.cpp293
-rw-r--r--krusader/DiskUsage/dulistview.h144
-rw-r--r--krusader/DiskUsage/filelightParts/Config.cpp50
-rw-r--r--krusader/DiskUsage/filelightParts/Config.h37
-rw-r--r--krusader/DiskUsage/filelightParts/Makefile.am9
-rw-r--r--krusader/DiskUsage/filelightParts/debug.h14
-rw-r--r--krusader/DiskUsage/filelightParts/fileTree.cpp78
-rw-r--r--krusader/DiskUsage/filelightParts/fileTree.h299
-rw-r--r--krusader/DiskUsage/radialMap/Makefile.am14
-rw-r--r--krusader/DiskUsage/radialMap/builder.cpp139
-rw-r--r--krusader/DiskUsage/radialMap/builder.h37
-rw-r--r--krusader/DiskUsage/radialMap/labels.cpp342
-rw-r--r--krusader/DiskUsage/radialMap/map.cpp432
-rw-r--r--krusader/DiskUsage/radialMap/radialMap.h71
-rw-r--r--krusader/DiskUsage/radialMap/segmentTip.cpp163
-rw-r--r--krusader/DiskUsage/radialMap/segmentTip.h33
-rw-r--r--krusader/DiskUsage/radialMap/sincos.h17
-rw-r--r--krusader/DiskUsage/radialMap/widget.cpp199
-rw-r--r--krusader/DiskUsage/radialMap/widget.h110
-rw-r--r--krusader/DiskUsage/radialMap/widgetEvents.cpp241
-rw-r--r--krusader/Filter/Makefile.am11
-rw-r--r--krusader/Filter/advancedfilter.cpp711
-rw-r--r--krusader/Filter/advancedfilter.h115
-rw-r--r--krusader/Filter/filterbase.h51
-rw-r--r--krusader/Filter/filterdialog.cpp87
-rw-r--r--krusader/Filter/filterdialog.h60
-rw-r--r--krusader/Filter/filtertabs.cpp133
-rw-r--r--krusader/Filter/filtertabs.h80
-rw-r--r--krusader/Filter/generalfilter.cpp536
-rw-r--r--krusader/Filter/generalfilter.h106
-rw-r--r--krusader/GUI/Makefile.am18
-rw-r--r--krusader/GUI/dirhistorybutton.cpp82
-rw-r--r--krusader/GUI/dirhistorybutton.h56
-rw-r--r--krusader/GUI/dirhistoryqueue.cpp87
-rw-r--r--krusader/GUI/dirhistoryqueue.h47
-rw-r--r--krusader/GUI/kcmdline.cpp253
-rw-r--r--krusader/GUI/kcmdline.h99
-rw-r--r--krusader/GUI/kcmdmodebutton.cpp74
-rw-r--r--krusader/GUI/kcmdmodebutton.h52
-rw-r--r--krusader/GUI/kfnkeys.cpp133
-rw-r--r--krusader/GUI/kfnkeys.h54
-rw-r--r--krusader/GUI/krremoteencodingmenu.cpp207
-rw-r--r--krusader/GUI/krremoteencodingmenu.h67
-rw-r--r--krusader/GUI/krusaderstatus.cpp46
-rw-r--r--krusader/GUI/krusaderstatus.h56
-rw-r--r--krusader/GUI/mediabutton.cpp692
-rw-r--r--krusader/GUI/mediabutton.h106
-rw-r--r--krusader/GUI/profilemanager.cpp198
-rw-r--r--krusader/GUI/profilemanager.h69
-rw-r--r--krusader/GUI/syncbrowsebutton.cpp72
-rw-r--r--krusader/GUI/syncbrowsebutton.h66
-rw-r--r--krusader/KViewer/Makefile.am11
-rw-r--r--krusader/KViewer/diskusageviewer.cpp129
-rw-r--r--krusader/KViewer/diskusageviewer.h68
-rw-r--r--krusader/KViewer/kimagefilepreview.cpp136
-rw-r--r--krusader/KViewer/kimagefilepreview.h70
-rw-r--r--krusader/KViewer/krviewer.cpp702
-rw-r--r--krusader/KViewer/krviewer.h128
-rw-r--r--krusader/KViewer/panelviewer.cpp307
-rw-r--r--krusader/KViewer/panelviewer.h88
-rw-r--r--krusader/Konfigurator/Makefile.am23
-rw-r--r--krusader/Konfigurator/kgadvanced.cpp133
-rw-r--r--krusader/Konfigurator/kgadvanced.h44
-rw-r--r--krusader/Konfigurator/kgarchives.cpp155
-rw-r--r--krusader/Konfigurator/kgarchives.h54
-rw-r--r--krusader/Konfigurator/kgcolors.cpp633
-rw-r--r--krusader/Konfigurator/kgcolors.h139
-rw-r--r--krusader/Konfigurator/kgdependencies.cpp169
-rw-r--r--krusader/Konfigurator/kgdependencies.h58
-rw-r--r--krusader/Konfigurator/kggeneral.cpp213
-rw-r--r--krusader/Konfigurator/kggeneral.h54
-rw-r--r--krusader/Konfigurator/kglookfeel.cpp373
-rw-r--r--krusader/Konfigurator/kglookfeel.h69
-rw-r--r--krusader/Konfigurator/kgprotocols.cpp418
-rw-r--r--krusader/Konfigurator/kgprotocols.h86
-rw-r--r--krusader/Konfigurator/kgstartup.cpp117
-rw-r--r--krusader/Konfigurator/kgstartup.h52
-rw-r--r--krusader/Konfigurator/kguseractions.cpp106
-rw-r--r--krusader/Konfigurator/kguseractions.h51
-rw-r--r--krusader/Konfigurator/kgwelcome.cpp50
-rw-r--r--krusader/Konfigurator/kgwelcome.h44
-rw-r--r--krusader/Konfigurator/konfigurator.cpp220
-rw-r--r--krusader/Konfigurator/konfigurator.h81
-rw-r--r--krusader/Konfigurator/konfiguratoritems.cpp815
-rw-r--r--krusader/Konfigurator/konfiguratoritems.h418
-rw-r--r--krusader/Konfigurator/konfiguratorpage.cpp334
-rw-r--r--krusader/Konfigurator/konfiguratorpage.h522
-rw-r--r--krusader/Konfigurator/krresulttable.cpp377
-rw-r--r--krusader/Konfigurator/krresulttable.h140
-rw-r--r--krusader/Konfigurator/krresulttabledialog.cpp97
-rw-r--r--krusader/Konfigurator/krresulttabledialog.h84
-rw-r--r--krusader/Konfigurator/searchobject.cpp106
-rw-r--r--krusader/Konfigurator/searchobject.h131
-rw-r--r--krusader/KrJS/Makefile.am13
-rw-r--r--krusader/KrJS/krjs.cpp89
-rw-r--r--krusader/KrJS/krjs.h32
-rw-r--r--krusader/Locate/Makefile.am7
-rwxr-xr-xkrusader/Locate/locate.cpp613
-rwxr-xr-xkrusader/Locate/locate.h100
-rw-r--r--krusader/Makefile.am192
-rw-r--r--krusader/MountMan/Makefile.am10
-rw-r--r--krusader/MountMan/kdiskfreesp.cpp168
-rw-r--r--krusader/MountMan/kdiskfreesp.h88
-rw-r--r--krusader/MountMan/kmountman.cpp327
-rw-r--r--krusader/MountMan/kmountman.h102
-rw-r--r--krusader/MountMan/kmountmangui.cpp396
-rw-r--r--krusader/MountMan/kmountmangui.h198
-rw-r--r--krusader/Panel/Makefile.am29
-rw-r--r--krusader/Panel/krbriefview.cpp1461
-rw-r--r--krusader/Panel/krbriefview.h172
-rw-r--r--krusader/Panel/krbriefviewitem.cpp225
-rw-r--r--krusader/Panel/krbriefviewitem.h79
-rw-r--r--krusader/Panel/krcalcspacedialog.cpp187
-rw-r--r--krusader/Panel/krcalcspacedialog.h106
-rw-r--r--krusader/Panel/krcolorcache.cpp761
-rw-r--r--krusader/Panel/krcolorcache.h101
-rw-r--r--krusader/Panel/krdetailedview.cpp1587
-rw-r--r--krusader/Panel/krdetailedview.h180
-rw-r--r--krusader/Panel/krdetailedviewitem.cpp313
-rw-r--r--krusader/Panel/krdetailedviewitem.h73
-rw-r--r--krusader/Panel/krdrag.cpp103
-rw-r--r--krusader/Panel/krdrag.h62
-rw-r--r--krusader/Panel/krpopupmenu.cpp354
-rw-r--r--krusader/Panel/krpopupmenu.h77
-rw-r--r--krusader/Panel/krpreviewpopup.cpp68
-rw-r--r--krusader/Panel/krpreviewpopup.h48
-rw-r--r--krusader/Panel/krselectionmode.cpp61
-rw-r--r--krusader/Panel/krselectionmode.h97
-rw-r--r--krusader/Panel/krview.cpp332
-rw-r--r--krusader/Panel/krview.h245
-rw-r--r--krusader/Panel/krviewitem.cpp105
-rw-r--r--krusader/Panel/krviewitem.h76
-rw-r--r--krusader/Panel/listpanel.cpp1115
-rw-r--r--krusader/Panel/listpanel.h211
-rwxr-xr-xkrusader/Panel/panelfunc.cpp1186
-rw-r--r--krusader/Panel/panelfunc.h105
-rw-r--r--krusader/Panel/panelpopup.cpp400
-rw-r--r--krusader/Panel/panelpopup.h73
-rw-r--r--krusader/Queue/Makefile.am10
-rw-r--r--krusader/Queue/queue.cpp22
-rw-r--r--krusader/Queue/queue.h32
-rw-r--r--krusader/Queue/queue_mgr.cpp31
-rw-r--r--krusader/Queue/queue_mgr.h26
-rw-r--r--krusader/Queue/queuewidget.cpp10
-rw-r--r--krusader/Queue/queuewidget.h14
-rw-r--r--krusader/RemoteMan/Makefile.am9
-rw-r--r--krusader/RemoteMan/remoteman.cpp385
-rw-r--r--krusader/RemoteMan/remoteman.h70
-rw-r--r--krusader/RemoteMan/remotemanbase.cpp331
-rw-r--r--krusader/RemoteMan/remotemanbase.h82
-rw-r--r--krusader/Search/Makefile.am9
-rw-r--r--krusader/Search/krsearchdialog.cpp628
-rw-r--r--krusader/Search/krsearchdialog.h183
-rw-r--r--krusader/Search/krsearchmod.cpp253
-rw-r--r--krusader/Search/krsearchmod.h85
-rw-r--r--krusader/Splitter/Makefile.am11
-rw-r--r--krusader/Splitter/combiner.cpp328
-rw-r--r--krusader/Splitter/combiner.h92
-rwxr-xr-xkrusader/Splitter/crc32.cpp69
-rwxr-xr-xkrusader/Splitter/crc32.h48
-rw-r--r--krusader/Splitter/splitter.cpp252
-rw-r--r--krusader/Splitter/splitter.h83
-rw-r--r--krusader/Splitter/splittergui.cpp213
-rw-r--r--krusader/Splitter/splittergui.h178
-rwxr-xr-xkrusader/Synchronizer/Makefile.am13
-rw-r--r--krusader/Synchronizer/feedtolistboxdialog.cpp200
-rw-r--r--krusader/Synchronizer/feedtolistboxdialog.h65
-rwxr-xr-xkrusader/Synchronizer/synchronizedialog.cpp199
-rwxr-xr-xkrusader/Synchronizer/synchronizedialog.h91
-rwxr-xr-xkrusader/Synchronizer/synchronizer.cpp1493
-rwxr-xr-xkrusader/Synchronizer/synchronizer.h204
-rw-r--r--krusader/Synchronizer/synchronizerdirlist.cpp216
-rw-r--r--krusader/Synchronizer/synchronizerdirlist.h72
-rw-r--r--krusader/Synchronizer/synchronizerfileitem.h170
-rwxr-xr-xkrusader/Synchronizer/synchronizergui.cpp2478
-rwxr-xr-xkrusader/Synchronizer/synchronizergui.h224
-rw-r--r--krusader/Synchronizer/synchronizertask.cpp343
-rw-r--r--krusader/Synchronizer/synchronizertask.h167
-rw-r--r--krusader/UserAction/Makefile.am17
-rw-r--r--krusader/UserAction/expander.cpp1224
-rw-r--r--krusader/UserAction/expander.h245
-rw-r--r--krusader/UserAction/kraction.cpp586
-rw-r--r--krusader/UserAction/kraction.h167
-rw-r--r--krusader/UserAction/kractionbase.cpp77
-rw-r--r--krusader/UserAction/kractionbase.h97
-rw-r--r--krusader/UserAction/tstring.h113
-rw-r--r--krusader/UserAction/useraction.cpp210
-rw-r--r--krusader/UserAction/useraction.h145
-rw-r--r--krusader/UserAction/useractionpopupmenu.cpp26
-rw-r--r--krusader/UserAction/useractionpopupmenu.h25
-rw-r--r--krusader/UserMenu/Makefile.am7
-rw-r--r--krusader/UserMenu/usermenu.cpp85
-rw-r--r--krusader/UserMenu/usermenu.h46
-rw-r--r--krusader/VFS/Makefile.am19
-rwxr-xr-xkrusader/VFS/arc_vfs.cpp866
-rw-r--r--krusader/VFS/arc_vfs.h130
-rw-r--r--krusader/VFS/ftp_vfs.cpp297
-rw-r--r--krusader/VFS/ftp_vfs.h79
-rw-r--r--krusader/VFS/krarchandler.cpp756
-rw-r--r--krusader/VFS/krarchandler.h148
-rw-r--r--krusader/VFS/krdirwatch.cpp124
-rw-r--r--krusader/VFS/krdirwatch.h79
-rw-r--r--krusader/VFS/krpermhandler.cpp355
-rw-r--r--krusader/VFS/krpermhandler.h89
-rw-r--r--krusader/VFS/krquery.cpp653
-rw-r--r--krusader/VFS/krquery.h208
-rw-r--r--krusader/VFS/krvfshandler.cpp71
-rw-r--r--krusader/VFS/krvfshandler.h40
-rw-r--r--krusader/VFS/normal_vfs.cpp437
-rw-r--r--krusader/VFS/normal_vfs.h92
-rw-r--r--krusader/VFS/preservingcopyjob.cpp319
-rw-r--r--krusader/VFS/preservingcopyjob.h84
-rw-r--r--krusader/VFS/temp_vfs.cpp127
-rw-r--r--krusader/VFS/temp_vfs.h57
-rw-r--r--krusader/VFS/vfile.cpp311
-rw-r--r--krusader/VFS/vfile.h166
-rw-r--r--krusader/VFS/vfs.cpp393
-rw-r--r--krusader/VFS/vfs.h186
-rw-r--r--krusader/VFS/virt_vfs.cpp341
-rw-r--r--krusader/VFS/virt_vfs.h76
-rw-r--r--krusader/VFS/virtualcopyjob.cpp316
-rw-r--r--krusader/VFS/virtualcopyjob.h125
-rw-r--r--krusader/alpa-yellow.colorbin0 -> 2468 bytes
-rw-r--r--krusader/bash.colorbin0 -> 2650 bytes
-rw-r--r--krusader/calc.js64
-rw-r--r--krusader/calc.ui267
-rw-r--r--krusader/cr16-app-krusader_blue.pngbin0 -> 910 bytes
-rw-r--r--krusader/cr16-app-krusader_red.pngbin0 -> 935 bytes
-rw-r--r--krusader/cr16-app-krusader_root.pngbin0 -> 210 bytes
-rw-r--r--krusader/cr16-app-krusader_user.pngbin0 -> 184 bytes
-rw-r--r--krusader/cr22-app-krusader_blue.pngbin0 -> 1377 bytes
-rw-r--r--krusader/cr22-app-krusader_red.pngbin0 -> 1436 bytes
-rw-r--r--krusader/cr22-app-krusader_root.pngbin0 -> 579 bytes
-rw-r--r--krusader/cr22-app-krusader_shield.pngbin0 -> 1256 bytes
-rw-r--r--krusader/cr22-app-krusader_user.pngbin0 -> 568 bytes
-rw-r--r--krusader/cr32-app-krusader_blue.pngbin0 -> 2453 bytes
-rw-r--r--krusader/cr32-app-krusader_red.pngbin0 -> 2523 bytes
-rw-r--r--krusader/cr32-app-krusader_root.pngbin0 -> 846 bytes
-rw-r--r--krusader/cr32-app-krusader_shield.pngbin0 -> 2024 bytes
-rw-r--r--krusader/cr32-app-krusader_user.pngbin0 -> 922 bytes
-rw-r--r--krusader/cr48-app-krusader_blue.pngbin0 -> 4528 bytes
-rw-r--r--krusader/cr48-app-krusader_red.pngbin0 -> 4497 bytes
-rw-r--r--krusader/cr48-app-krusader_root.pngbin0 -> 2002 bytes
-rw-r--r--krusader/cr48-app-krusader_shield.pngbin0 -> 3302 bytes
-rw-r--r--krusader/cr48-app-krusader_user.pngbin0 -> 2105 bytes
-rw-r--r--krusader/cr64-app-krusader_blue.pngbin0 -> 6469 bytes
-rw-r--r--krusader/cr64-app-krusader_red.pngbin0 -> 6585 bytes
-rw-r--r--krusader/cr64-app-krusader_root.pngbin0 -> 2731 bytes
-rw-r--r--krusader/cr64-app-krusader_shield.pngbin0 -> 4794 bytes
-rw-r--r--krusader/cr64-app-krusader_user.pngbin0 -> 2826 bytes
-rw-r--r--krusader/defaults.h306
-rw-r--r--krusader/dos_navigator.colorbin0 -> 2674 bytes
-rw-r--r--krusader/kicons.cpp377
-rw-r--r--krusader/kicons.h29
-rw-r--r--krusader/krservices.cpp216
-rw-r--r--krusader/krservices.h78
-rw-r--r--krusader/krslots.cpp944
-rw-r--r--krusader/krslots.h187
-rw-r--r--krusader/krusader.cpp1248
-rw-r--r--krusader/krusader.desktop86
-rw-r--r--krusader/krusader.h274
-rw-r--r--krusader/krusader_root-mode.desktop90
-rw-r--r--krusader/krusaderapp.h31
-rw-r--r--krusader/krusaderui.rc193
-rw-r--r--krusader/krusaderview.cpp415
-rw-r--r--krusader/krusaderview.h110
-rw-r--r--krusader/lo16-app-krusader.pngbin0 -> 814 bytes
-rw-r--r--krusader/lo32-app-krusader.pngbin0 -> 3742 bytes
-rw-r--r--krusader/lo32-app-krusader2.pngbin0 -> 680 bytes
-rw-r--r--krusader/main.cpp248
-rw-r--r--krusader/midnight_cmd_AHamann.colorbin0 -> 2732 bytes
-rw-r--r--krusader/midnight_commander.colorbin0 -> 1776 bytes
-rw-r--r--krusader/midnight_commander.keymapbin0 -> 1375 bytes
-rw-r--r--krusader/midnight_commander.keymap.info42
-rw-r--r--krusader/mount.js37
-rw-r--r--krusader/mount.ui208
-rw-r--r--krusader/panelmanager.cpp352
-rw-r--r--krusader/panelmanager.h78
-rw-r--r--krusader/paneltabbar.cpp262
-rw-r--r--krusader/paneltabbar.h99
-rw-r--r--krusader/recode.js202
-rw-r--r--krusader/recode.ui297
-rw-r--r--krusader/resources.h42
-rw-r--r--krusader/select_from_file.js13
-rw-r--r--krusader/splash.pngbin0 -> 67168 bytes
-rw-r--r--krusader/total_cmd_pleasent.colorbin0 -> 2652 bytes
-rw-r--r--krusader/total_commander.colorbin0 -> 1760 bytes
-rw-r--r--krusader/total_commander.keymap112
-rw-r--r--krusader/total_commander.keymap.info10
-rw-r--r--krusader/useraction_examples.xml406
-rw-r--r--krusader/x-ace.desktop7
353 files changed, 66645 insertions, 0 deletions
diff --git a/krusader/ActionMan/Makefile.am b/krusader/ActionMan/Makefile.am
new file mode 100644
index 0000000..e71563a
--- /dev/null
+++ b/krusader/ActionMan/Makefile.am
@@ -0,0 +1,14 @@
+noinst_LIBRARIES = libActionMan.a
+
+INCLUDES = $(all_includes)
+
+libActionMan_a_METASOURCES = AUTO
+
+libActionMan_a_SOURCES = \
+ actionman.cpp \
+ actionpropertybase.ui \
+ actionproperty.cpp \
+ addplaceholderpopup.cpp \
+ useractionlistview.cpp \
+ useractionpage.cpp
+noinst_HEADERS = useractionpage.h
diff --git a/krusader/ActionMan/actionman.cpp b/krusader/ActionMan/actionman.cpp
new file mode 100644
index 0000000..10b604b
--- /dev/null
+++ b/krusader/ActionMan/actionman.cpp
@@ -0,0 +1,60 @@
+//
+// C++ Implementation: actionman
+//
+// Description: This manages all useractions
+//
+//
+// Author: Jonas Bähr (C) 2006
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include "actionman.h"
+
+#include <klocale.h>
+#include <kmessagebox.h>
+
+#include "useractionpage.h"
+#include "../krusader.h"
+#include "../UserAction/useraction.h"
+
+
+ActionMan::ActionMan( QWidget * parent )
+ : KDialogBase( parent, "ActionMan", true /*modal*/, "ActionMan - Manage your useractions", KDialogBase::Apply | KDialogBase::Close )
+{
+ setPlainCaption(i18n("ActionMan - Manage Your Useractions"));
+
+ userActionPage = new UserActionPage( this );
+ setMainWidget( userActionPage );
+
+ connect( userActionPage, SIGNAL( changed() ), SLOT( slotEnableApplyButton() ) );
+ connect( userActionPage, SIGNAL( applied() ), SLOT( slotDisableApplyButton() ) );
+ enableButtonApply( false );
+
+ exec();
+}
+
+ActionMan::~ActionMan() {
+}
+
+void ActionMan::slotClose() {
+ if ( userActionPage->readyToQuit() )
+ reject();
+}
+
+void ActionMan::slotApply() {
+ userActionPage->applyChanges();
+}
+
+void ActionMan::slotEnableApplyButton() {
+ enableButtonApply( true );
+}
+
+void ActionMan::slotDisableApplyButton() {
+ enableButtonApply( false );
+}
+
+
+
+#include "actionman.moc"
diff --git a/krusader/ActionMan/actionman.h b/krusader/ActionMan/actionman.h
new file mode 100644
index 0000000..bbfe33f
--- /dev/null
+++ b/krusader/ActionMan/actionman.h
@@ -0,0 +1,36 @@
+//
+// C++ Interface: actionman
+//
+// Description: This manages all useractions
+//
+//
+// Author: Jonas B�r (C) 2006
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#ifndef ACTIONMAN_H
+#define ACTIONMAN_H
+
+#include <kdialogbase.h>
+
+class UserActionPage;
+
+class ActionMan : public KDialogBase {
+Q_OBJECT
+public:
+ ActionMan( QWidget* parent=0 );
+ ~ActionMan();
+
+protected slots:
+ void slotClose();
+ void slotApply();
+ void slotEnableApplyButton();
+ void slotDisableApplyButton();
+
+private:
+ UserActionPage* userActionPage;
+};
+
+#endif // ifndef ACTIONMAN_H
diff --git a/krusader/ActionMan/actionproperty.cpp b/krusader/ActionMan/actionproperty.cpp
new file mode 100644
index 0000000..077b035
--- /dev/null
+++ b/krusader/ActionMan/actionproperty.cpp
@@ -0,0 +1,470 @@
+//
+// C++ Implementation: actionproperty
+//
+// Description:
+//
+//
+// Author: Jonas B�r (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include "actionproperty.h"
+#include "addplaceholderpopup.h"
+
+#include "../UserAction/useraction.h"
+#include "../UserAction/kraction.h"
+#include "../krusader.h"
+
+#include <qtoolbutton.h>
+#include <qcheckbox.h>
+#include <qradiobutton.h>
+#include <qbuttongroup.h>
+#include <klocale.h>
+#include <kfiledialog.h>
+#include <klineedit.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kinputdialog.h>
+#include <kkeybutton.h>
+#include <kcombobox.h>
+#include <kicondialog.h>
+#include <ktextedit.h>
+#include <kiconloader.h>
+
+#define ICON(N) KGlobal::iconLoader()->loadIcon(N, KIcon::Small)
+
+ActionProperty::ActionProperty( QWidget *parent, const char *name, KrAction *action )
+ : ActionPropertyBase( parent, name ), _modified(false)
+ {
+ if ( action ) {
+ _action = action;
+ updateGUI( _action );
+ }
+
+ ButtonAddPlaceholder->setPixmap( ICON("add") );
+ ButtonAddStartpath->setPixmap( ICON("fileopen") );
+
+ // fill with all existing categories
+ cbCategory->insertStringList( krUserAction->allCategories() );
+
+ connect( ButtonAddPlaceholder, SIGNAL( clicked() ), this, SLOT( addPlaceholder() ) );
+ connect( ButtonAddStartpath, SIGNAL( clicked() ), this, SLOT( addStartpath() ) );
+ connect( ButtonNewProtocol, SIGNAL( clicked() ), this, SLOT( newProtocol() ) );
+ connect( ButtonEditProtocol, SIGNAL( clicked() ), this, SLOT( editProtocol() ) );
+ connect( ButtonRemoveProtocol, SIGNAL( clicked() ), this, SLOT( removeProtocol() ) );
+ connect( ButtonAddPath, SIGNAL( clicked() ), this, SLOT( addPath() ) );
+ connect( ButtonEditPath, SIGNAL( clicked() ), this, SLOT( editPath() ) );
+ connect( ButtonRemovePath, SIGNAL( clicked() ), this, SLOT( removePath() ) );
+ connect( ButtonAddMime, SIGNAL( clicked() ), this, SLOT( addMime() ) );
+ connect( ButtonEditMime, SIGNAL( clicked() ), this, SLOT( editMime() ) );
+ connect( ButtonRemoveMime, SIGNAL( clicked() ), this, SLOT( removeMime() ) );
+ connect( ButtonNewFile, SIGNAL( clicked() ), this, SLOT( newFile() ) );
+ connect( ButtonEditFile, SIGNAL( clicked() ), this, SLOT( editFile() ) );
+ connect( ButtonRemoveFile, SIGNAL( clicked() ), this, SLOT( removeFile() ) );
+ connect( KeyButtonShortcut, SIGNAL( capturedShortcut(const KShortcut&) ), this, SLOT( changedShortcut(const KShortcut&) ) );
+ // track modifications:
+ connect( leDistinctName, SIGNAL( textChanged(const QString&) ), SLOT( setModified() ) );
+ connect( leTitle, SIGNAL( textChanged(const QString&) ), SLOT( setModified() ) );
+ connect( ButtonIcon, SIGNAL( iconChanged(QString) ), SLOT( setModified() ) );
+ connect( cbCategory, SIGNAL( textChanged(const QString&) ), SLOT( setModified() ) );
+ connect( leTooltip, SIGNAL( textChanged(const QString&) ), SLOT( setModified() ) );
+ connect( textDescription, SIGNAL( textChanged() ), SLOT( setModified() ) );
+ connect( leDistinctName, SIGNAL( textChanged(const QString&) ), SLOT( setModified() ) );
+ connect( leCommandline, SIGNAL( textChanged(const QString&) ), SLOT( setModified() ) );
+ connect( leStartpath, SIGNAL( textChanged(const QString&) ), SLOT( setModified() ) );
+ connect( bgExecType, SIGNAL( clicked(int) ), SLOT( setModified() ) );
+ connect( bgAccept, SIGNAL( clicked(int) ), SLOT( setModified() ) );
+ connect( KeyButtonShortcut, SIGNAL( capturedShortcut(const KShortcut&) ), SLOT( setModified() ) );
+ connect( leDifferentUser, SIGNAL( textChanged(const QString&) ), SLOT( setModified() ) );
+ connect( chkDifferentUser, SIGNAL( clicked() ), SLOT( setModified() ) );
+ connect( chkConfirmExecution, SIGNAL( clicked() ), SLOT( setModified() ) );
+ // The modified-state of the ShowOnly-lists is tracked in the access-functions below
+}
+
+ActionProperty::~ActionProperty() {
+}
+
+void ActionProperty::changedShortcut( const KShortcut& shortcut ) {
+ KeyButtonShortcut->setShortcut( shortcut, false );
+}
+
+
+void ActionProperty::clear() {
+ _action = 0;
+
+ // This prevents the changed-signal from being emited during the GUI-update
+ _modified = true; // The real state is set at the end of this function.
+
+ leDistinctName->clear();
+ cbCategory->clearEdit();
+ leTitle->clear();
+ leTooltip->clear();
+ textDescription->clear();
+ leCommandline->clear();
+ leStartpath->clear();
+ KeyButtonShortcut->setShortcut( KShortcut(), false );
+
+ lbShowonlyProtocol->clear();
+ lbShowonlyPath->clear();
+ lbShowonlyMime->clear();
+ lbShowonlyFile->clear();
+
+ chkSeparateStdError->setChecked( false );
+ radioNormal->setChecked( true );
+
+ radioLocal->setChecked( true );
+
+ chkConfirmExecution->setChecked( false );
+
+ ButtonIcon->resetIcon();
+
+ leDifferentUser->clear();
+ chkDifferentUser->setChecked( false );
+
+ setModified( false );
+}
+
+void ActionProperty::updateGUI( KrAction *action ) {
+ if ( action )
+ _action = action;
+ if ( ! _action )
+ return;
+
+ // This prevents the changed-signal from being emited during the GUI-update.
+ _modified = true; // The real state is set at the end of this function.
+
+ leDistinctName->setText( _action->name() );
+ cbCategory->setCurrentText( _action->category() );
+ leTitle->setText( _action->text() );
+ leTooltip->setText( _action->toolTip() );
+ textDescription->setText( _action->whatsThis() );
+ leCommandline->setText( _action->command() );
+ leCommandline->home(false);
+ leStartpath->setText( _action->startpath() );
+ KeyButtonShortcut->setShortcut( _action->shortcut(), false );
+
+ lbShowonlyProtocol->clear();
+ lbShowonlyProtocol->insertStringList( _action->showonlyProtocol() );
+ lbShowonlyPath->clear();
+ lbShowonlyPath->insertStringList( _action->showonlyPath() );
+ lbShowonlyMime->clear();
+ lbShowonlyMime->insertStringList( _action->showonlyMime() );
+ lbShowonlyFile->clear();
+ lbShowonlyFile->insertStringList( _action->showonlyFile() );
+
+ chkSeparateStdError->setChecked( false );
+ switch ( _action->execType() ) {
+ case KrAction::CollectOutputSeparateStderr:
+ chkSeparateStdError->setChecked( true );
+ radioCollectOutput->setChecked( true );
+ break;
+ case KrAction::CollectOutput:
+ radioCollectOutput->setChecked( true );
+ break;
+ case KrAction::Terminal:
+ radioTerminal->setChecked( true );
+ break;
+ default: // case KrAction::Normal:
+ radioNormal->setChecked( true );
+ break;
+ }
+
+ if ( _action->acceptURLs() )
+ radioUrl->setChecked( true );
+ else
+ radioLocal->setChecked( true );
+
+ chkConfirmExecution->setChecked( _action->confirmExecution() );
+
+ if ( ! _action->icon().isEmpty() )
+ ButtonIcon->setIcon( _action->icon() );
+ else
+ ButtonIcon->resetIcon();
+
+ leDifferentUser->setText( _action->user() );
+ if ( _action->user().isEmpty() )
+ chkDifferentUser->setChecked( false );
+ else
+ chkDifferentUser->setChecked( true );
+
+ setModified( false );
+}
+
+void ActionProperty::updateAction( KrAction *action ) {
+ if ( action )
+ _action = action;
+ if ( ! _action )
+ return;
+
+ if ( _action->category() != cbCategory->currentText() ) {
+ _action->setCategory( cbCategory->currentText() );
+ // Update the category-list
+ cbCategory->clear();
+ cbCategory->insertStringList( krUserAction->allCategories() );
+ cbCategory->setCurrentText( _action->category() );
+ }
+
+ _action->setName( leDistinctName->text().latin1() );
+ _action->setText( leTitle->text() );
+ _action->setToolTip( leTooltip->text() );
+ _action->setWhatsThis( textDescription->text() );
+ _action->setCommand( leCommandline->text() );
+ _action->setStartpath( leStartpath->text() );
+ _action->setShortcut( KeyButtonShortcut->shortcut() );
+
+ QListBoxItem* lbi = lbShowonlyProtocol->firstItem();
+ QStringList list;
+ while ( lbi ) {
+ list << lbi->text();
+ lbi = lbi->next();
+ }
+ _action->setShowonlyProtocol( list );
+
+ lbi = lbShowonlyPath->firstItem();
+ list = QStringList();
+ while ( lbi ) {
+ list << lbi->text();
+ lbi = lbi->next();
+ }
+ _action->setShowonlyPath( list );
+
+ lbi = lbShowonlyMime->firstItem();
+ list = QStringList();
+ while ( lbi ) {
+ list << lbi->text();
+ lbi = lbi->next();
+ }
+ _action->setShowonlyMime( list );
+
+ lbi = lbShowonlyFile->firstItem();
+ list = QStringList();
+ while ( lbi ) {
+ list << lbi->text();
+ lbi = lbi->next();
+ }
+ _action->setShowonlyFile( list );
+
+ if ( radioCollectOutput->isChecked() && chkSeparateStdError->isChecked() )
+ _action->setExecType( KrAction::CollectOutputSeparateStderr );
+ else if ( radioCollectOutput->isChecked() && ! chkSeparateStdError->isChecked() )
+ _action->setExecType( KrAction::CollectOutput );
+ else if ( radioTerminal->isChecked() )
+ _action->setExecType( KrAction::Terminal );
+ else
+ _action->setExecType( KrAction::Normal );
+
+ if ( radioUrl->isChecked() )
+ _action->setAcceptURLs( true );
+ else
+ _action->setAcceptURLs( false );
+
+ _action->setConfirmExecution( chkConfirmExecution->isChecked() );
+
+ _action->setIcon( ButtonIcon->icon() );
+
+ _action->setUser( leDifferentUser->text() );
+
+ setModified( false );
+}
+
+void ActionProperty::addPlaceholder() {
+ AddPlaceholderPopup popup( this );
+ QString exp = popup.getPlaceholder( mapToGlobal(
+ QPoint(
+ ButtonAddPlaceholder->pos().x() + ButtonAddPlaceholder->width()+6, // 6 is the default margin
+ ButtonAddPlaceholder->pos().y()
+ )
+ ) );
+ leCommandline->insert( exp );
+}
+
+
+void ActionProperty::addStartpath() {
+ QString folder = KFileDialog::getExistingDirectory(QString::null, this);
+ if (folder != QString::null) {
+ leStartpath->setText( folder );
+ }
+}
+
+
+void ActionProperty::newProtocol() {
+ bool ok;
+ QString text = KInputDialog::getText(
+ i18n( "New protocol" ),
+ i18n( "Set a protocol:" ),
+ lbShowonlyProtocol->currentText(),
+ &ok, this );
+ if ( ok && !text.isEmpty() ) {
+ lbShowonlyProtocol->insertStringList( QStringList::split( ";", text ) );
+ setModified();
+ }
+}
+
+void ActionProperty::editProtocol() {
+ if (lbShowonlyProtocol->currentItem() == -1)
+ return;
+
+ bool ok;
+ QString text = KInputDialog::getText(
+ i18n( "Edit protocol" ),
+ i18n( "Set another protocol:" ),
+ lbShowonlyProtocol->currentText(),
+ &ok, this );
+ if ( ok && !text.isEmpty() ) {
+ lbShowonlyProtocol->changeItem( text, lbShowonlyProtocol->currentItem() );
+ setModified();
+ }
+}
+
+void ActionProperty::removeProtocol() {
+ if (lbShowonlyProtocol->currentItem() != -1) {
+ lbShowonlyProtocol->removeItem( lbShowonlyProtocol->currentItem() );
+ setModified();
+ }
+}
+
+void ActionProperty::addPath() {
+ QString folder = KFileDialog::getExistingDirectory(QString::null, this);
+ if (folder != QString::null) {
+ lbShowonlyPath->insertItem( folder );
+ setModified();
+ }
+}
+
+void ActionProperty::editPath() {
+ if (lbShowonlyPath->currentItem() == -1)
+ return;
+
+ bool ok;
+ QString text = KInputDialog::getText(
+ i18n( "Edit path" ),
+ i18n( "Set another path:" ),
+ lbShowonlyPath->currentText(),
+ &ok, this );
+ if ( ok && !text.isEmpty() ) {
+ lbShowonlyPath->changeItem( text, lbShowonlyPath->currentItem() );
+ setModified();
+ }
+}
+
+void ActionProperty::removePath() {
+ if (lbShowonlyPath->currentItem() != -1) {
+ lbShowonlyPath->removeItem( lbShowonlyPath->currentItem() );
+ setModified();
+ }
+}
+
+void ActionProperty::addMime() {
+ bool ok;
+ QString text = KInputDialog::getText(
+ i18n( "New mime-type" ),
+ i18n( "Set a mime-type:" ),
+ lbShowonlyMime->currentText(),
+ &ok, this );
+ if ( ok && !text.isEmpty() ) {
+ lbShowonlyMime->insertStringList( QStringList::split( ";", text ) );
+ setModified();
+ }
+}
+
+void ActionProperty::editMime() {
+ if (lbShowonlyMime->currentItem() == -1)
+ return;
+
+ bool ok;
+ QString text = KInputDialog::getText(
+ i18n( "Edit mime-type" ),
+ i18n( "Set another mime-type:" ),
+ lbShowonlyMime->currentText(),
+ &ok, this );
+ if ( ok && !text.isEmpty() ) {
+ lbShowonlyMime->changeItem( text, lbShowonlyMime->currentItem() );
+ setModified();
+ }
+}
+
+void ActionProperty::removeMime() {
+ if (lbShowonlyMime->currentItem() != -1) {
+ lbShowonlyMime->removeItem( lbShowonlyMime->currentItem() );
+ setModified();
+ }
+}
+
+void ActionProperty::newFile() {
+ bool ok;
+ QString text = KInputDialog::getText(
+ i18n( "New filename" ),
+ i18n( "Set a filename:" ),
+ lbShowonlyFile->currentText(),
+ &ok, this );
+ if ( ok && !text.isEmpty() ) {
+ lbShowonlyFile->insertStringList( QStringList::split( ";", text ) );
+ setModified();
+ }
+}
+
+void ActionProperty::editFile() {
+ if (lbShowonlyFile->currentItem() == -1)
+ return;
+
+ bool ok;
+ QString text = KInputDialog::getText(
+ i18n( "Edit filename" ),
+ i18n( "Set another filename:" ),
+ lbShowonlyFile->currentText(),
+ &ok, this );
+ if ( ok && !text.isEmpty() ) {
+ lbShowonlyFile->changeItem( text, lbShowonlyFile->currentItem() );
+ setModified();
+ }
+}
+
+void ActionProperty::removeFile() {
+ if (lbShowonlyFile->currentItem() != -1) {
+ lbShowonlyFile->removeItem( lbShowonlyFile->currentItem() );
+ setModified();
+ }
+}
+
+
+bool ActionProperty::validProperties() {
+ if ( leDistinctName->text().simplifyWhiteSpace().isEmpty() ) {
+ KMessageBox::error( this, i18n("Please set a unique name for the useraction") );
+ leDistinctName->setFocus();
+ return false;
+ }
+ if ( leTitle->text().simplifyWhiteSpace().isEmpty() ) {
+ KMessageBox::error( this, i18n("Please set a title for the menu entry") );
+ leTitle->setFocus();
+ return false;
+ }
+ if ( leCommandline->text().simplifyWhiteSpace().isEmpty() ) {
+ KMessageBox::error( this, i18n("Command line is empty") );
+ leCommandline->setFocus();
+ return false;
+ }
+ if ( leDistinctName->isEnabled() )
+ if ( krApp->actionCollection()->action( leDistinctName->text().latin1() ) ) {
+ KMessageBox::error( this,
+ i18n("There already is an action with this name\n"
+ "If you don't have such an useraction the name is used by Krusader for an internal action")
+ );
+ leDistinctName->setFocus();
+ return false;
+ }
+
+ return true;
+}
+
+void ActionProperty::setModified( bool m )
+{
+ if ( m && !_modified ) { // emit only when the state _changes_to_true_,
+ emit changed();
+ }
+ _modified = m;
+}
+
+
+#include "actionproperty.moc"
diff --git a/krusader/ActionMan/actionproperty.h b/krusader/ActionMan/actionproperty.h
new file mode 100644
index 0000000..41cc564
--- /dev/null
+++ b/krusader/ActionMan/actionproperty.h
@@ -0,0 +1,146 @@
+//
+// C++ Interface: actionproperty
+//
+// Description:
+//
+//
+// Author: Jonas Bähr (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#ifndef ACTIONPROPERTY_H
+#define ACTIONPROPERTY_H
+
+#include "actionpropertybase.h"
+
+class KrAction;
+class KShortcut;
+
+/**
+ * Use this widget where ever you need to manipulate a UserAction
+ * @author Jonas Bähr (http://www.jonas-baehr.de)
+ */
+class ActionProperty : public ActionPropertyBase {
+ Q_OBJECT
+public:
+ ActionProperty( QWidget *parent=0, const char *name=0, KrAction *action=0 );
+ ~ActionProperty();
+
+ /**
+ * @return the currently displayed action
+ */
+ KrAction* action() { return _action; };
+
+ /**
+ * This inits the widget with the actions properties.
+ * If no action is provided, the last used will be taken!
+ * It also resets the changed() state.
+ * @param action the action which should be displayd
+ */
+ void updateGUI( KrAction *action = 0 );
+
+ /**
+ * This writes the displayed properties back into the action.
+ * If no action is provided, the last used will be taken!
+ * It also resets the changed() state.
+ * @param action the action which should be manipulated
+ */
+ void updateAction( KrAction *action = 0 );
+
+ /**
+ * clears everything
+ */
+ void clear();
+
+ /**
+ * @return true if all properties got valid values
+ */
+ bool validProperties();
+
+ /**
+ * @return true if any property got changed
+ */
+ bool isModified() { return _modified; };
+
+signals:
+ /**
+ * emited when any actionproperty changed. This signal is only emited when
+ * the _modified attribute changes to true. If there are changes made and
+ * _modified is already true, no signal is emited!
+ */
+ void changed();
+
+protected slots:
+ void setModified( bool m = true );
+ /**
+ * executes the AddPlaceholderPopup
+ */
+ void addPlaceholder();
+ /**
+ * asks for an existing path
+ */
+ void addStartpath();
+ /**
+ * (availability) asks for a new protocol
+ */
+ void newProtocol();
+ /**
+ * (availability) changes a protocol of the list
+ */
+ void editProtocol();
+ /**
+ * (availability) removes a protocol from the list
+ */
+ void removeProtocol();
+ /**
+ * (availability) asks for a new path
+ */
+ void addPath();
+ /**
+ * (availability) edits a path of the list
+ */
+ void editPath();
+ /**
+ * (availability) removes a path from the list
+ */
+ void removePath();
+ /**
+ * (availability) asks for a new mime-type
+ */
+ void addMime();
+ /**
+ * (availability) changes a mime-type of the list
+ */
+ void editMime();
+ /**
+ * (availability) removes a mime-type from the list
+ */
+ void removeMime();
+ /**
+ * (availability) asks for a new file-filter
+ */
+ void newFile();
+ /**
+ * (availability) edits a file-filter of the list
+ */
+ void editFile();
+ /**
+ * (availability) removes a file-filter from the lsit
+ */
+ void removeFile();
+
+private:
+ KrAction *_action;
+ bool _modified;
+
+private slots:
+ /**
+ * This updates the ShortcutButton
+ * @internal
+ */
+ void changedShortcut(const KShortcut& shortcut);
+};
+
+#endif
diff --git a/krusader/ActionMan/actionpropertybase.cpp b/krusader/ActionMan/actionpropertybase.cpp
new file mode 100644
index 0000000..639f6fd
--- /dev/null
+++ b/krusader/ActionMan/actionpropertybase.cpp
@@ -0,0 +1,463 @@
+#include <kdialog.h>
+#include <klocale.h>
+/****************************************************************************
+** Form implementation generated from reading ui file './actionpropertybase.ui'
+**
+** Created: Sat Mar 15 11:41:43 2008
+** by: The User Interface Compiler ($Id: qt/main.cpp 3.3.8 edited Jan 11 14:47 $)
+**
+** WARNING! All changes made in this file will be lost!
+****************************************************************************/
+
+#include "actionpropertybase.h"
+
+#include <qvariant.h>
+#include <qpushbutton.h>
+#include <qtabwidget.h>
+#include <qtoolbutton.h>
+#include <qlabel.h>
+#include <qbuttongroup.h>
+#include <qradiobutton.h>
+#include <klineedit.h>
+#include <kcombobox.h>
+#include <kicondialog.h>
+#include <ktextedit.h>
+#include <kkeybutton.h>
+#include <qcheckbox.h>
+#include <qgroupbox.h>
+#include <klistbox.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include "klineedit.h"
+#include "kcombobox.h"
+#include "kicondialog.h"
+#include "ktextedit.h"
+#include "kkeybutton.h"
+#include "klistbox.h"
+
+/*
+ * Constructs a ActionPropertyBase as a child of 'parent', with the
+ * name 'name' and widget flags set to 'f'.
+ */
+ActionPropertyBase::ActionPropertyBase( QWidget* parent, const char* name, WFlags fl )
+ : QWidget( parent, name, fl )
+{
+ if ( !name )
+ setName( "ActionPropertyBase" );
+ ActionPropertyBaseLayout = new QGridLayout( this, 1, 1, 0, 0, "ActionPropertyBaseLayout");
+
+ tabWidget3 = new QTabWidget( this, "tabWidget3" );
+
+ tab = new QWidget( tabWidget3, "tab" );
+ tabLayout = new QGridLayout( tab, 1, 1, 11, 6, "tabLayout");
+
+ ButtonAddStartpath = new QToolButton( tab, "ButtonAddStartpath" );
+
+ tabLayout->addWidget( ButtonAddStartpath, 8, 3 );
+
+ LabelDescription = new QLabel( tab, "LabelDescription" );
+ LabelDescription->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)1, 0, 0, LabelDescription->sizePolicy().hasHeightForWidth() ) );
+
+ tabLayout->addWidget( LabelDescription, 4, 0 );
+
+ bgAccept = new QButtonGroup( tab, "bgAccept" );
+ bgAccept->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)1, 0, 0, bgAccept->sizePolicy().hasHeightForWidth() ) );
+ bgAccept->setColumnLayout(0, Qt::Vertical );
+ bgAccept->layout()->setSpacing( 6 );
+ bgAccept->layout()->setMargin( 11 );
+ bgAcceptLayout = new QGridLayout( bgAccept->layout() );
+ bgAcceptLayout->setAlignment( Qt::AlignTop );
+
+ radioLocal = new QRadioButton( bgAccept, "radioLocal" );
+ radioLocal->setChecked( TRUE );
+
+ bgAcceptLayout->addWidget( radioLocal, 0, 0 );
+
+ radioUrl = new QRadioButton( bgAccept, "radioUrl" );
+
+ bgAcceptLayout->addWidget( radioUrl, 1, 0 );
+
+ tabLayout->addMultiCellWidget( bgAccept, 9, 9, 2, 3 );
+
+ leTitle = new KLineEdit( tab, "leTitle" );
+
+ tabLayout->addMultiCellWidget( leTitle, 2, 2, 1, 3 );
+
+ LabelTitle = new QLabel( tab, "LabelTitle" );
+ LabelTitle->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0, LabelTitle->sizePolicy().hasHeightForWidth() ) );
+
+ tabLayout->addWidget( LabelTitle, 2, 0 );
+
+ layout3 = new QHBoxLayout( 0, 0, 6, "layout3");
+
+ layout2 = new QVBoxLayout( 0, 0, 6, "layout2");
+
+ leDistinctName = new KLineEdit( tab, "leDistinctName" );
+ layout2->addWidget( leDistinctName );
+
+ cbCategory = new KComboBox( FALSE, tab, "cbCategory" );
+ cbCategory->setEditable( TRUE );
+ layout2->addWidget( cbCategory );
+ layout3->addLayout( layout2 );
+
+ ButtonIcon = new KIconButton( tab, "ButtonIcon" );
+ ButtonIcon->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)0, (QSizePolicy::SizeType)0, 0, 0, ButtonIcon->sizePolicy().hasHeightForWidth() ) );
+ ButtonIcon->setMinimumSize( QSize( 50, 50 ) );
+ ButtonIcon->setMaximumSize( QSize( 50, 50 ) );
+ layout3->addWidget( ButtonIcon );
+
+ tabLayout->addMultiCellLayout( layout3, 0, 1, 1, 3 );
+
+ LabelDistinctName = new QLabel( tab, "LabelDistinctName" );
+ LabelDistinctName->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0, LabelDistinctName->sizePolicy().hasHeightForWidth() ) );
+
+ tabLayout->addWidget( LabelDistinctName, 0, 0 );
+
+ LabelCommandline = new QLabel( tab, "LabelCommandline" );
+ LabelCommandline->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)0, (QSizePolicy::SizeType)0, 0, 0, LabelCommandline->sizePolicy().hasHeightForWidth() ) );
+
+ tabLayout->addWidget( LabelCommandline, 7, 0 );
+
+ leTooltip = new KLineEdit( tab, "leTooltip" );
+
+ tabLayout->addMultiCellWidget( leTooltip, 3, 3, 1, 3 );
+
+ leStartpath = new KLineEdit( tab, "leStartpath" );
+
+ tabLayout->addMultiCellWidget( leStartpath, 8, 8, 1, 2 );
+
+ LabelTooltip = new QLabel( tab, "LabelTooltip" );
+ LabelTooltip->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0, LabelTooltip->sizePolicy().hasHeightForWidth() ) );
+
+ tabLayout->addWidget( LabelTooltip, 3, 0 );
+
+ leCommandline = new KLineEdit( tab, "leCommandline" );
+
+ tabLayout->addMultiCellWidget( leCommandline, 7, 7, 1, 2 );
+
+ LabelCategory = new QLabel( tab, "LabelCategory" );
+ LabelCategory->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0, LabelCategory->sizePolicy().hasHeightForWidth() ) );
+
+ tabLayout->addWidget( LabelCategory, 1, 0 );
+
+ ButtonAddPlaceholder = new QToolButton( tab, "ButtonAddPlaceholder" );
+ ButtonAddPlaceholder->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)0, (QSizePolicy::SizeType)0, 0, 0, ButtonAddPlaceholder->sizePolicy().hasHeightForWidth() ) );
+ ButtonAddPlaceholder->setMinimumSize( QSize( 0, 0 ) );
+
+ tabLayout->addWidget( ButtonAddPlaceholder, 7, 3 );
+
+ textDescription = new KTextEdit( tab, "textDescription" );
+ textDescription->setWordWrap( KTextEdit::WidgetWidth );
+
+ tabLayout->addMultiCellWidget( textDescription, 4, 6, 1, 3 );
+
+ LabelStartpath = new QLabel( tab, "LabelStartpath" );
+ LabelStartpath->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)0, (QSizePolicy::SizeType)0, 0, 0, LabelStartpath->sizePolicy().hasHeightForWidth() ) );
+
+ tabLayout->addWidget( LabelStartpath, 8, 0 );
+ spacer = new QSpacerItem( 80, 19, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ tabLayout->addItem( spacer, 6, 0 );
+
+ layout4 = new QHBoxLayout( 0, 0, 6, "layout4");
+
+ LabelShortcut = new QLabel( tab, "LabelShortcut" );
+ layout4->addWidget( LabelShortcut );
+ spacer6_2 = new QSpacerItem( 161, 21, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ layout4->addItem( spacer6_2 );
+
+ KeyButtonShortcut = new KKeyButton( tab, "KeyButtonShortcut" );
+ layout4->addWidget( KeyButtonShortcut );
+
+ tabLayout->addMultiCellLayout( layout4, 10, 10, 2, 3 );
+
+ bgExecType = new QButtonGroup( tab, "bgExecType" );
+ bgExecType->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)1, 0, 0, bgExecType->sizePolicy().hasHeightForWidth() ) );
+ bgExecType->setColumnLayout(0, Qt::Vertical );
+ bgExecType->layout()->setSpacing( 6 );
+ bgExecType->layout()->setMargin( 11 );
+ bgExecTypeLayout = new QGridLayout( bgExecType->layout() );
+ bgExecTypeLayout->setAlignment( Qt::AlignTop );
+
+ radioCollectOutput = new QRadioButton( bgExecType, "radioCollectOutput" );
+
+ bgExecTypeLayout->addWidget( radioCollectOutput, 2, 0 );
+
+ chkSeparateStdError = new QCheckBox( bgExecType, "chkSeparateStdError" );
+ chkSeparateStdError->setEnabled( FALSE );
+
+ bgExecTypeLayout->addWidget( chkSeparateStdError, 3, 0 );
+
+ radioNormal = new QRadioButton( bgExecType, "radioNormal" );
+ radioNormal->setChecked( TRUE );
+
+ bgExecTypeLayout->addWidget( radioNormal, 0, 0 );
+
+ radioTerminal = new QRadioButton( bgExecType, "radioTerminal" );
+
+ bgExecTypeLayout->addWidget( radioTerminal, 1, 0 );
+
+ tabLayout->addMultiCellWidget( bgExecType, 9, 10, 0, 1 );
+ tabWidget3->insertTab( tab, QString::fromLatin1("") );
+
+ tab_2 = new QWidget( tabWidget3, "tab_2" );
+ tabLayout_2 = new QGridLayout( tab_2, 1, 1, 11, 6, "tabLayout_2");
+
+ gbShowonly = new QGroupBox( tab_2, "gbShowonly" );
+ gbShowonly->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7, (QSizePolicy::SizeType)7, 0, 0, gbShowonly->sizePolicy().hasHeightForWidth() ) );
+ gbShowonly->setColumnLayout(0, Qt::Vertical );
+ gbShowonly->layout()->setSpacing( 6 );
+ gbShowonly->layout()->setMargin( 11 );
+ gbShowonlyLayout = new QGridLayout( gbShowonly->layout() );
+ gbShowonlyLayout->setAlignment( Qt::AlignTop );
+
+ tabShowonly = new QTabWidget( gbShowonly, "tabShowonly" );
+ tabShowonly->setTabPosition( QTabWidget::Top );
+ tabShowonly->setTabShape( QTabWidget::Triangular );
+
+ TabPage = new QWidget( tabShowonly, "TabPage" );
+ TabPageLayout = new QGridLayout( TabPage, 1, 1, 11, 6, "TabPageLayout");
+
+ ButtonNewProtocol = new QToolButton( TabPage, "ButtonNewProtocol" );
+ ButtonNewProtocol->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0, ButtonNewProtocol->sizePolicy().hasHeightForWidth() ) );
+ ButtonNewProtocol->setMinimumSize( QSize( 0, 0 ) );
+ ButtonNewProtocol->setMaximumSize( QSize( 32767, 32767 ) );
+
+ TabPageLayout->addWidget( ButtonNewProtocol, 0, 1 );
+
+ ButtonEditProtocol = new QToolButton( TabPage, "ButtonEditProtocol" );
+ ButtonEditProtocol->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0, ButtonEditProtocol->sizePolicy().hasHeightForWidth() ) );
+ ButtonEditProtocol->setMinimumSize( QSize( 0, 0 ) );
+ ButtonEditProtocol->setMaximumSize( QSize( 32767, 32767 ) );
+
+ TabPageLayout->addWidget( ButtonEditProtocol, 1, 1 );
+ spacer6_3 = new QSpacerItem( 21, 58, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ TabPageLayout->addItem( spacer6_3, 3, 1 );
+
+ ButtonRemoveProtocol = new QToolButton( TabPage, "ButtonRemoveProtocol" );
+ ButtonRemoveProtocol->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0, ButtonRemoveProtocol->sizePolicy().hasHeightForWidth() ) );
+ ButtonRemoveProtocol->setMinimumSize( QSize( 0, 0 ) );
+ ButtonRemoveProtocol->setMaximumSize( QSize( 32767, 32767 ) );
+
+ TabPageLayout->addWidget( ButtonRemoveProtocol, 2, 1 );
+
+ lbShowonlyProtocol = new KListBox( TabPage, "lbShowonlyProtocol" );
+
+ TabPageLayout->addMultiCellWidget( lbShowonlyProtocol, 0, 3, 0, 0 );
+ tabShowonly->insertTab( TabPage, QString::fromLatin1("") );
+
+ tab_3 = new QWidget( tabShowonly, "tab_3" );
+ tabLayout_3 = new QGridLayout( tab_3, 1, 1, 11, 6, "tabLayout_3");
+
+ lbShowonlyPath = new KListBox( tab_3, "lbShowonlyPath" );
+
+ tabLayout_3->addMultiCellWidget( lbShowonlyPath, 0, 3, 0, 0 );
+
+ ButtonAddPath = new QToolButton( tab_3, "ButtonAddPath" );
+ ButtonAddPath->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0, ButtonAddPath->sizePolicy().hasHeightForWidth() ) );
+ ButtonAddPath->setMinimumSize( QSize( 0, 0 ) );
+ ButtonAddPath->setMaximumSize( QSize( 32767, 32767 ) );
+
+ tabLayout_3->addWidget( ButtonAddPath, 0, 1 );
+
+ ButtonEditPath = new QToolButton( tab_3, "ButtonEditPath" );
+ ButtonEditPath->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0, ButtonEditPath->sizePolicy().hasHeightForWidth() ) );
+ ButtonEditPath->setMinimumSize( QSize( 0, 0 ) );
+ ButtonEditPath->setMaximumSize( QSize( 32767, 32767 ) );
+
+ tabLayout_3->addWidget( ButtonEditPath, 1, 1 );
+
+ ButtonRemovePath = new QToolButton( tab_3, "ButtonRemovePath" );
+ ButtonRemovePath->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0, ButtonRemovePath->sizePolicy().hasHeightForWidth() ) );
+ ButtonRemovePath->setMinimumSize( QSize( 0, 0 ) );
+ ButtonRemovePath->setMaximumSize( QSize( 32767, 32767 ) );
+
+ tabLayout_3->addWidget( ButtonRemovePath, 2, 1 );
+ spacer4 = new QSpacerItem( 21, 61, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ tabLayout_3->addItem( spacer4, 3, 1 );
+ tabShowonly->insertTab( tab_3, QString::fromLatin1("") );
+
+ tab_4 = new QWidget( tabShowonly, "tab_4" );
+ tabLayout_4 = new QGridLayout( tab_4, 1, 1, 11, 6, "tabLayout_4");
+
+ lbShowonlyMime = new KListBox( tab_4, "lbShowonlyMime" );
+
+ tabLayout_4->addMultiCellWidget( lbShowonlyMime, 0, 3, 0, 0 );
+
+ ButtonAddMime = new QToolButton( tab_4, "ButtonAddMime" );
+ ButtonAddMime->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0, ButtonAddMime->sizePolicy().hasHeightForWidth() ) );
+ ButtonAddMime->setMinimumSize( QSize( 0, 0 ) );
+ ButtonAddMime->setMaximumSize( QSize( 32767, 32767 ) );
+
+ tabLayout_4->addWidget( ButtonAddMime, 0, 1 );
+
+ ButtonEditMime = new QToolButton( tab_4, "ButtonEditMime" );
+ ButtonEditMime->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0, ButtonEditMime->sizePolicy().hasHeightForWidth() ) );
+ ButtonEditMime->setMinimumSize( QSize( 0, 0 ) );
+ ButtonEditMime->setMaximumSize( QSize( 32767, 32767 ) );
+
+ tabLayout_4->addWidget( ButtonEditMime, 1, 1 );
+
+ ButtonRemoveMime = new QToolButton( tab_4, "ButtonRemoveMime" );
+ ButtonRemoveMime->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0, ButtonRemoveMime->sizePolicy().hasHeightForWidth() ) );
+ ButtonRemoveMime->setMinimumSize( QSize( 0, 0 ) );
+ ButtonRemoveMime->setMaximumSize( QSize( 32767, 32767 ) );
+
+ tabLayout_4->addWidget( ButtonRemoveMime, 2, 1 );
+ spacer5 = new QSpacerItem( 21, 41, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ tabLayout_4->addItem( spacer5, 3, 1 );
+ tabShowonly->insertTab( tab_4, QString::fromLatin1("") );
+
+ TabPage_2 = new QWidget( tabShowonly, "TabPage_2" );
+ TabPageLayout_2 = new QGridLayout( TabPage_2, 1, 1, 11, 6, "TabPageLayout_2");
+
+ lbShowonlyFile = new KListBox( TabPage_2, "lbShowonlyFile" );
+
+ TabPageLayout_2->addMultiCellWidget( lbShowonlyFile, 0, 3, 0, 0 );
+
+ ButtonNewFile = new QToolButton( TabPage_2, "ButtonNewFile" );
+ ButtonNewFile->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0, ButtonNewFile->sizePolicy().hasHeightForWidth() ) );
+ ButtonNewFile->setMinimumSize( QSize( 0, 0 ) );
+ ButtonNewFile->setMaximumSize( QSize( 32767, 32767 ) );
+
+ TabPageLayout_2->addWidget( ButtonNewFile, 0, 1 );
+
+ ButtonEditFile = new QToolButton( TabPage_2, "ButtonEditFile" );
+ ButtonEditFile->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0, ButtonEditFile->sizePolicy().hasHeightForWidth() ) );
+ ButtonEditFile->setMinimumSize( QSize( 0, 0 ) );
+ ButtonEditFile->setMaximumSize( QSize( 32767, 32767 ) );
+
+ TabPageLayout_2->addWidget( ButtonEditFile, 1, 1 );
+
+ ButtonRemoveFile = new QToolButton( TabPage_2, "ButtonRemoveFile" );
+ ButtonRemoveFile->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0, ButtonRemoveFile->sizePolicy().hasHeightForWidth() ) );
+ ButtonRemoveFile->setMinimumSize( QSize( 0, 0 ) );
+ ButtonRemoveFile->setMaximumSize( QSize( 32767, 32767 ) );
+
+ TabPageLayout_2->addWidget( ButtonRemoveFile, 2, 1 );
+ spacer6 = new QSpacerItem( 21, 41, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ TabPageLayout_2->addItem( spacer6, 3, 1 );
+ tabShowonly->insertTab( TabPage_2, QString::fromLatin1("") );
+
+ gbShowonlyLayout->addWidget( tabShowonly, 0, 0 );
+
+ tabLayout_2->addMultiCellWidget( gbShowonly, 0, 0, 0, 1 );
+
+ chkConfirmExecution = new QCheckBox( tab_2, "chkConfirmExecution" );
+
+ tabLayout_2->addMultiCellWidget( chkConfirmExecution, 1, 1, 0, 1 );
+
+ chkDifferentUser = new QCheckBox( tab_2, "chkDifferentUser" );
+
+ tabLayout_2->addWidget( chkDifferentUser, 2, 0 );
+
+ leDifferentUser = new KLineEdit( tab_2, "leDifferentUser" );
+ leDifferentUser->setEnabled( FALSE );
+
+ tabLayout_2->addWidget( leDifferentUser, 2, 1 );
+ spacer3 = new QSpacerItem( 161, 102, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ tabLayout_2->addMultiCell( spacer3, 3, 3, 0, 1 );
+ tabWidget3->insertTab( tab_2, QString::fromLatin1("") );
+
+ ActionPropertyBaseLayout->addWidget( tabWidget3, 0, 0 );
+ languageChange();
+ resize( QSize(485, 470).expandedTo(minimumSizeHint()) );
+ clearWState( WState_Polished );
+
+ // signals and slots connections
+ connect( radioCollectOutput, SIGNAL( toggled(bool) ), chkSeparateStdError, SLOT( setEnabled(bool) ) );
+ connect( chkDifferentUser, SIGNAL( toggled(bool) ), leDifferentUser, SLOT( setEnabled(bool) ) );
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+ActionPropertyBase::~ActionPropertyBase()
+{
+ // no need to delete child widgets, Qt does it all for us
+}
+
+/*
+ * Sets the strings of the subwidgets using the current
+ * language.
+ */
+void ActionPropertyBase::languageChange()
+{
+ setCaption( tr2i18n( "Action Property" ) );
+ ButtonAddStartpath->setText( tr2i18n( "..." ) );
+ LabelDescription->setText( tr2i18n( "Description:" ) );
+ QWhatsThis::add( LabelDescription, tr2i18n( "A detailed description of the <b>Useraction</b>. It is only displayed in the <i>Konfigurator</i> and via <code>Shift-F1</code>." ) );
+ bgAccept->setTitle( tr2i18n( "Command accepts" ) );
+ radioLocal->setText( tr2i18n( "Local files only (no URL's)" ) );
+ QWhatsThis::add( radioLocal, tr2i18n( "Substitute the <b>Placeholders</b> with local filenames." ) );
+ radioUrl->setText( tr2i18n( "URL's (remote and local)" ) );
+ QWhatsThis::add( radioUrl, tr2i18n( "Substitute the <b>Placeholders</b> with valid URL's." ) );
+ QWhatsThis::add( leTitle, tr2i18n( "The title displayed in the <b>Usermenu</b>." ) );
+ LabelTitle->setText( tr2i18n( "Title:" ) );
+ QWhatsThis::add( LabelTitle, tr2i18n( "The title displayed in the <b>Usermenu</b>." ) );
+ QWhatsThis::add( leDistinctName, tr2i18n( "Unique name of the <b>Useraction</b>. It is only used in the <i>Konfigurator</i> and doesn't appear in any other menu.<p><b>Note</b>: The <i>Title</i> shown in the <b>Usermenu</b> can be set below." ) );
+ QWhatsThis::add( cbCategory, tr2i18n( "<b>Useractions</b> can be grouped in categories for better distinction. Choose a existing <i>Category</i> or create a new one by entering a name." ) );
+ ButtonIcon->setText( tr2i18n( "Icon" ) );
+ QWhatsThis::add( ButtonIcon, tr2i18n( "Each <b>Useraction</b> can have its own icon. It will appear in front of the title in the <b>Usermenu</b>." ) );
+ LabelDistinctName->setText( tr2i18n( "Identifier:" ) );
+ QWhatsThis::add( LabelDistinctName, tr2i18n( "<p>Unique name of the <b>Useraction</b>. It is only used in the <i>Konfigurator</i> and doesn't appear in any other menu.</p><p><b>Note</b>: The <i>Title</i> shown in the <b>Usermenu</b> can be set below.</p>" ) );
+ LabelCommandline->setText( tr2i18n( "Command:" ) );
+ QWhatsThis::add( LabelCommandline, tr2i18n( "<p>The <i>Command</i> defines the command that will be executed when the <b>Useraction</b> is used. It can be a simple shell command or a complex sequence of multiple commands with <b>Placeholders</b>.</p><p>Examples:<ul><code><li>eject /mnt/cdrom</li><li>amarok --append %aList(\"Selected\")%</li></code></ul>\n"
+"Please consult the handbook to learn more about the syntax.</p>" ) );
+ QWhatsThis::add( leTooltip, tr2i18n( "The <i>Tooltip</i> is shown when the mouse cursor is hold over an entry of the <b>Useraction Toolbar</b>." ) );
+ QWhatsThis::add( leStartpath, tr2i18n( "The <i>Workdir</i> defines in which directory the <i>Command</i> will be executed." ) );
+ LabelTooltip->setText( tr2i18n( "Tooltip:" ) );
+ QWhatsThis::add( LabelTooltip, tr2i18n( "The <i>Tooltip</i> is shown when the mouse cursor is hold over an entry of the <b>Useraction Toolbar</b>." ) );
+ leCommandline->setText( QString::null );
+ QWhatsThis::add( leCommandline, tr2i18n( "The <i>Command</i> defines the command that will be executed when the <b>Useraction</b> is used. It can be a simple shell command or a complex sequence of multiple commands with <b>Placeholders</b>.<p>\n"
+"Examples:<ul><code><li>eject /mnt/cdrom</li><li>amarok --append %aList(\"Selected\")%</li></code></ul>\n"
+"Please consult the handbook to learn more about the syntax." ) );
+ LabelCategory->setText( tr2i18n( "Category:" ) );
+ QWhatsThis::add( LabelCategory, tr2i18n( "<b>Useractions</b> can be grouped in categories for better distinction. Choose a existing <i>Category</i> or create a new one by entering a name." ) );
+ ButtonAddPlaceholder->setText( tr2i18n( "&Add" ) );
+ QWhatsThis::add( ButtonAddPlaceholder, tr2i18n( "Add <b>Placeholders</b> for the selected files in the panel." ) );
+ QWhatsThis::add( textDescription, tr2i18n( "A detailed description of the <b>Useraction</b>. It is only displayed in the <i>Konfigurator</i> and via <code>Shift-F1</code>." ) );
+ LabelStartpath->setText( tr2i18n( "Workdir:" ) );
+ QWhatsThis::add( LabelStartpath, tr2i18n( "The <i>Workdir</i> defines in which directory the <i>Command</i> will be executed." ) );
+ LabelShortcut->setText( tr2i18n( "Default shortcut:" ) );
+ KeyButtonShortcut->setText( tr2i18n( "None" ) );
+ QWhatsThis::add( KeyButtonShortcut, tr2i18n( "Set a default keyboard shortcut." ) );
+ bgExecType->setTitle( tr2i18n( "Execution mode" ) );
+ radioCollectOutput->setText( tr2i18n( "Collect output" ) );
+ QWhatsThis::add( radioCollectOutput, tr2i18n( "Collect the output of the executed program." ) );
+ chkSeparateStdError->setText( tr2i18n( "Separate standard error" ) );
+ QWhatsThis::add( chkSeparateStdError, tr2i18n( "Separate standard out and standard error in the output collection." ) );
+ radioNormal->setText( tr2i18n( "Normal" ) );
+ radioTerminal->setText( tr2i18n( "Run in terminal" ) );
+ QWhatsThis::add( radioTerminal, tr2i18n( "Run the command in a terminal." ) );
+ tabWidget3->changeTab( tab, tr2i18n( "Basic Properties" ) );
+ gbShowonly->setTitle( tr2i18n( "The Useraction is only available for" ) );
+ ButtonNewProtocol->setText( tr2i18n( "&New..." ) );
+ ButtonEditProtocol->setText( tr2i18n( "Chan&ge..." ) );
+ ButtonRemoveProtocol->setText( tr2i18n( "De&lete" ) );
+ QWhatsThis::add( lbShowonlyProtocol, tr2i18n( "Show the <b>Useraction</b> only for the values defined here." ) );
+ tabShowonly->changeTab( TabPage, tr2i18n( "Protocol" ) );
+ QWhatsThis::add( lbShowonlyPath, tr2i18n( "Show the <b>Useraction</b> only for the values defined here." ) );
+ ButtonAddPath->setText( tr2i18n( "&New..." ) );
+ ButtonEditPath->setText( tr2i18n( "Chan&ge..." ) );
+ ButtonRemovePath->setText( tr2i18n( "De&lete" ) );
+ tabShowonly->changeTab( tab_3, tr2i18n( "Path" ) );
+ QWhatsThis::add( lbShowonlyMime, tr2i18n( "Show the <b>Useraction</b> only for the values defined here." ) );
+ ButtonAddMime->setText( tr2i18n( "&New..." ) );
+ ButtonEditMime->setText( tr2i18n( "Chan&ge..." ) );
+ ButtonRemoveMime->setText( tr2i18n( "De&lete" ) );
+ tabShowonly->changeTab( tab_4, tr2i18n( "Mime-type" ) );
+ QWhatsThis::add( lbShowonlyFile, tr2i18n( "Show the <b>Useraction</b> only for the filenames defined here. The wildcards '<code>?</code>' and '<code>*</code>' can be used." ) );
+ ButtonNewFile->setText( tr2i18n( "&New..." ) );
+ ButtonEditFile->setText( tr2i18n( "Chan&ge..." ) );
+ ButtonRemoveFile->setText( tr2i18n( "De&lete" ) );
+ tabShowonly->changeTab( TabPage_2, tr2i18n( "Filename" ) );
+ chkConfirmExecution->setText( tr2i18n( "Confirm each program call separately" ) );
+ QWhatsThis::add( chkConfirmExecution, tr2i18n( "Allows to tweak the <i>Command</i> before it is executed." ) );
+ chkDifferentUser->setText( tr2i18n( "Run as different user:" ) );
+ QWhatsThis::add( chkDifferentUser, tr2i18n( "Execute the <i>Command</i> under a different user-id." ) );
+ QWhatsThis::add( leDifferentUser, tr2i18n( "Execute the <i>Command</i> under a different user-id." ) );
+ tabWidget3->changeTab( tab_2, tr2i18n( "Advanced Properties" ) );
+}
+
+#include "actionpropertybase.moc"
diff --git a/krusader/ActionMan/actionpropertybase.ui b/krusader/ActionMan/actionpropertybase.ui
new file mode 100644
index 0000000..9079e85
--- /dev/null
+++ b/krusader/ActionMan/actionpropertybase.ui
@@ -0,0 +1,1125 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>ActionPropertyBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ActionPropertyBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>485</width>
+ <height>470</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Action Property</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tabWidget3</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Basic Properties</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QToolButton" row="8" column="3">
+ <property name="name">
+ <cstring>ButtonAddStartpath</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="0">
+ <property name="name">
+ <cstring>LabelDescription</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Description:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>A detailed description of the &lt;b&gt;Useraction&lt;/b&gt;. It is only displayed in the &lt;i&gt;Konfigurator&lt;/i&gt; and via &lt;code&gt;Shift-F1&lt;/code&gt;.</string>
+ </property>
+ </widget>
+ <widget class="QButtonGroup" row="9" column="2" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>bgAccept</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Command accepts</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>radioLocal</cstring>
+ </property>
+ <property name="text">
+ <string>Local files only (no URL's)</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Substitute the &lt;b&gt;Placeholders&lt;/b&gt; with local filenames.</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>radioUrl</cstring>
+ </property>
+ <property name="text">
+ <string>URL's (remote and local)</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Substitute the &lt;b&gt;Placeholders&lt;/b&gt; with valid URL's.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="KLineEdit" row="2" column="1" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>leTitle</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The title displayed in the &lt;b&gt;Usermenu&lt;/b&gt;.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>LabelTitle</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Title:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The title displayed in the &lt;b&gt;Usermenu&lt;/b&gt;.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="1" rowspan="2" colspan="3">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>leDistinctName</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Unique name of the &lt;b&gt;Useraction&lt;/b&gt;. It is only used in the &lt;i&gt;Konfigurator&lt;/i&gt; and doesn't appear in any other menu.&lt;p&gt;&lt;b&gt;Note&lt;/b&gt;: The &lt;i&gt;Title&lt;/i&gt; shown in the &lt;b&gt;Usermenu&lt;/b&gt; can be set below.</string>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>cbCategory</cstring>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;b&gt;Useractions&lt;/b&gt; can be grouped in categories for better distinction. Choose a existing &lt;i&gt;Category&lt;/i&gt; or create a new one by entering a name.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="KIconButton">
+ <property name="name">
+ <cstring>ButtonIcon</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>50</width>
+ <height>50</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>50</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Icon</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Each &lt;b&gt;Useraction&lt;/b&gt; can have its own icon. It will appear in front of the title in the &lt;b&gt;Usermenu&lt;/b&gt;.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>LabelDistinctName</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Identifier:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;Unique name of the &lt;b&gt;Useraction&lt;/b&gt;. It is only used in the &lt;i&gt;Konfigurator&lt;/i&gt; and doesn't appear in any other menu.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Note&lt;/b&gt;: The &lt;i&gt;Title&lt;/i&gt; shown in the &lt;b&gt;Usermenu&lt;/b&gt; can be set below.&lt;/p&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="7" column="0">
+ <property name="name">
+ <cstring>LabelCommandline</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Command:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;The &lt;i&gt;Command&lt;/i&gt; defines the command that will be executed when the &lt;b&gt;Useraction&lt;/b&gt; is used. It can be a simple shell command or a complex sequence of multiple commands with &lt;b&gt;Placeholders&lt;/b&gt;.&lt;/p&gt;&lt;p&gt;Examples:&lt;ul&gt;&lt;code&gt;&lt;li&gt;eject /mnt/cdrom&lt;/li&gt;&lt;li&gt;amarok --append %aList("Selected")%&lt;/li&gt;&lt;/code&gt;&lt;/ul&gt;
+Please consult the handbook to learn more about the syntax.&lt;/p&gt;</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="3" column="1" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>leTooltip</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The &lt;i&gt;Tooltip&lt;/i&gt; is shown when the mouse cursor is hold over an entry of the &lt;b&gt;Useraction Toolbar&lt;/b&gt;.</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="8" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>leStartpath</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The &lt;i&gt;Workdir&lt;/i&gt; defines in which directory the &lt;i&gt;Command&lt;/i&gt; will be executed.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="0">
+ <property name="name">
+ <cstring>LabelTooltip</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Tooltip:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The &lt;i&gt;Tooltip&lt;/i&gt; is shown when the mouse cursor is hold over an entry of the &lt;b&gt;Useraction Toolbar&lt;/b&gt;.</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="7" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>leCommandline</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The &lt;i&gt;Command&lt;/i&gt; defines the command that will be executed when the &lt;b&gt;Useraction&lt;/b&gt; is used. It can be a simple shell command or a complex sequence of multiple commands with &lt;b&gt;Placeholders&lt;/b&gt;.&lt;p&gt;
+Examples:&lt;ul&gt;&lt;code&gt;&lt;li&gt;eject /mnt/cdrom&lt;/li&gt;&lt;li&gt;amarok --append %aList("Selected")%&lt;/li&gt;&lt;/code&gt;&lt;/ul&gt;
+Please consult the handbook to learn more about the syntax.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>LabelCategory</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Category:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;b&gt;Useractions&lt;/b&gt; can be grouped in categories for better distinction. Choose a existing &lt;i&gt;Category&lt;/i&gt; or create a new one by entering a name.</string>
+ </property>
+ </widget>
+ <widget class="QToolButton" row="7" column="3">
+ <property name="name">
+ <cstring>ButtonAddPlaceholder</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&amp;Add</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Add &lt;b&gt;Placeholders&lt;/b&gt; for the selected files in the panel.</string>
+ </property>
+ </widget>
+ <widget class="KTextEdit" row="4" column="1" rowspan="3" colspan="3">
+ <property name="name">
+ <cstring>textDescription</cstring>
+ </property>
+ <property name="wordWrap">
+ <enum>WidgetWidth</enum>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>A detailed description of the &lt;b&gt;Useraction&lt;/b&gt;. It is only displayed in the &lt;i&gt;Konfigurator&lt;/i&gt; and via &lt;code&gt;Shift-F1&lt;/code&gt;.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="8" column="0">
+ <property name="name">
+ <cstring>LabelStartpath</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Workdir:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The &lt;i&gt;Workdir&lt;/i&gt; defines in which directory the &lt;i&gt;Command&lt;/i&gt; will be executed.</string>
+ </property>
+ </widget>
+ <spacer row="6" column="0">
+ <property name="name">
+ <cstring>spacer</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>80</width>
+ <height>19</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget" row="10" column="2" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>LabelShortcut</cstring>
+ </property>
+ <property name="text">
+ <string>Default shortcut:</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer6_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>161</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KKeyButton">
+ <property name="name">
+ <cstring>KeyButtonShortcut</cstring>
+ </property>
+ <property name="text">
+ <string>None</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Set a default keyboard shortcut.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QButtonGroup" row="9" column="0" rowspan="2" colspan="2">
+ <property name="name">
+ <cstring>bgExecType</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Execution mode</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton" row="2" column="0">
+ <property name="name">
+ <cstring>radioCollectOutput</cstring>
+ </property>
+ <property name="text">
+ <string>Collect output</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Collect the output of the executed program.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="3" column="0">
+ <property name="name">
+ <cstring>chkSeparateStdError</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Separate standard error</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Separate standard out and standard error in the output collection.</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>radioNormal</cstring>
+ </property>
+ <property name="text">
+ <string>Normal</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>radioTerminal</cstring>
+ </property>
+ <property name="text">
+ <string>Run in terminal</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Run the command in a terminal.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Advanced Properties</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>gbShowonly</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>The Useraction is only available for</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tabShowonly</cstring>
+ </property>
+ <property name="tabPosition">
+ <enum>Top</enum>
+ </property>
+ <property name="tabShape">
+ <enum>Triangular</enum>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>Protocol</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QToolButton" row="0" column="1">
+ <property name="name">
+ <cstring>ButtonNewProtocol</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&amp;New...</string>
+ </property>
+ </widget>
+ <widget class="QToolButton" row="1" column="1">
+ <property name="name">
+ <cstring>ButtonEditProtocol</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Chan&amp;ge...</string>
+ </property>
+ </widget>
+ <spacer row="3" column="1">
+ <property name="name">
+ <cstring>spacer6_3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>58</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QToolButton" row="2" column="1">
+ <property name="name">
+ <cstring>ButtonRemoveProtocol</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>De&amp;lete</string>
+ </property>
+ </widget>
+ <widget class="KListBox" row="0" column="0" rowspan="4" colspan="1">
+ <property name="name">
+ <cstring>lbShowonlyProtocol</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Show the &lt;b&gt;Useraction&lt;/b&gt; only for the values defined here.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Path</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KListBox" row="0" column="0" rowspan="4" colspan="1">
+ <property name="name">
+ <cstring>lbShowonlyPath</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Show the &lt;b&gt;Useraction&lt;/b&gt; only for the values defined here.</string>
+ </property>
+ </widget>
+ <widget class="QToolButton" row="0" column="1">
+ <property name="name">
+ <cstring>ButtonAddPath</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&amp;New...</string>
+ </property>
+ </widget>
+ <widget class="QToolButton" row="1" column="1">
+ <property name="name">
+ <cstring>ButtonEditPath</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Chan&amp;ge...</string>
+ </property>
+ </widget>
+ <widget class="QToolButton" row="2" column="1">
+ <property name="name">
+ <cstring>ButtonRemovePath</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>De&amp;lete</string>
+ </property>
+ </widget>
+ <spacer row="3" column="1">
+ <property name="name">
+ <cstring>spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>61</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Mime-type</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KListBox" row="0" column="0" rowspan="4" colspan="1">
+ <property name="name">
+ <cstring>lbShowonlyMime</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Show the &lt;b&gt;Useraction&lt;/b&gt; only for the values defined here.</string>
+ </property>
+ </widget>
+ <widget class="QToolButton" row="0" column="1">
+ <property name="name">
+ <cstring>ButtonAddMime</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&amp;New...</string>
+ </property>
+ </widget>
+ <widget class="QToolButton" row="1" column="1">
+ <property name="name">
+ <cstring>ButtonEditMime</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Chan&amp;ge...</string>
+ </property>
+ </widget>
+ <widget class="QToolButton" row="2" column="1">
+ <property name="name">
+ <cstring>ButtonRemoveMime</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>De&amp;lete</string>
+ </property>
+ </widget>
+ <spacer row="3" column="1">
+ <property name="name">
+ <cstring>spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>41</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>Filename</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KListBox" row="0" column="0" rowspan="4" colspan="1">
+ <property name="name">
+ <cstring>lbShowonlyFile</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Show the &lt;b&gt;Useraction&lt;/b&gt; only for the filenames defined here. The wildcards '&lt;code&gt;?&lt;/code&gt;' and '&lt;code&gt;*&lt;/code&gt;' can be used.</string>
+ </property>
+ </widget>
+ <widget class="QToolButton" row="0" column="1">
+ <property name="name">
+ <cstring>ButtonNewFile</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&amp;New...</string>
+ </property>
+ </widget>
+ <widget class="QToolButton" row="1" column="1">
+ <property name="name">
+ <cstring>ButtonEditFile</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Chan&amp;ge...</string>
+ </property>
+ </widget>
+ <widget class="QToolButton" row="2" column="1">
+ <property name="name">
+ <cstring>ButtonRemoveFile</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>De&amp;lete</string>
+ </property>
+ </widget>
+ <spacer row="3" column="1">
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>41</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>chkConfirmExecution</cstring>
+ </property>
+ <property name="text">
+ <string>Confirm each program call separately</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Allows to tweak the &lt;i&gt;Command&lt;/i&gt; before it is executed.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0">
+ <property name="name">
+ <cstring>chkDifferentUser</cstring>
+ </property>
+ <property name="text">
+ <string>Run as different user:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Execute the &lt;i&gt;Command&lt;/i&gt; under a different user-id.</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="2" column="1">
+ <property name="name">
+ <cstring>leDifferentUser</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Execute the &lt;i&gt;Command&lt;/i&gt; under a different user-id.</string>
+ </property>
+ </widget>
+ <spacer row="3" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>161</width>
+ <height>102</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>radioCollectOutput</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>chkSeparateStdError</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>chkDifferentUser</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>leDifferentUser</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kicondialog.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>ktextedit.h</includehint>
+ <includehint>kkeybutton.h</includehint>
+ <includehint>klistbox.h</includehint>
+ <includehint>klistbox.h</includehint>
+ <includehint>klistbox.h</includehint>
+ <includehint>klistbox.h</includehint>
+ <includehint>klineedit.h</includehint>
+</includehints>
+</UI>
diff --git a/krusader/ActionMan/addplaceholderpopup.cpp b/krusader/ActionMan/addplaceholderpopup.cpp
new file mode 100644
index 0000000..1dc2ef1
--- /dev/null
+++ b/krusader/ActionMan/addplaceholderpopup.cpp
@@ -0,0 +1,582 @@
+//
+// C++ Implementation: addplaceholderpopup
+//
+// Description:
+//
+//
+// Author: Shie Erlich and Rafi Yanai <>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include "addplaceholderpopup.h"
+
+#include "../UserAction/expander.h"
+
+#include <klocale.h>
+#include <kfiledialog.h>
+#include <kmessagebox.h>
+
+// for ParameterDialog
+#include "../krusader.h" // for konfig-access
+#include "../BookMan/krbookmarkbutton.h"
+#include "../GUI/profilemanager.h"
+
+#include <qlayout.h>
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qtoolbutton.h>
+#include <klineedit.h>
+#include <qcheckbox.h>
+#include <kiconloader.h>
+#include <kcombobox.h>
+#include <kurlcompletion.h>
+#include <knuminput.h>
+
+#include <kdebug.h>
+
+#define ACTIVE_MASK 0x0100
+#define OTHER_MASK 0x0200
+#define LEFT_MASK 0x0400
+#define RIGHT_MASK 0x0800
+#define INDEPENDENT_MASK 0x1000
+#define EXECUTABLE_ID 0xFFFF
+
+
+AddPlaceholderPopup::AddPlaceholderPopup( QWidget *parent ) : KPopupMenu( parent ) {
+
+ _activeSub = new KPopupMenu( this );
+ _otherSub = new KPopupMenu( this );
+ _leftSub = new KPopupMenu( this );
+ _rightSub = new KPopupMenu( this );
+ _independentSub = new KPopupMenu( this );
+
+ insertItem( i18n( "Active panel" ), _activeSub );
+ insertItem( i18n( "Other panel" ), _otherSub );
+ insertItem( i18n( "Left panel" ), _leftSub );
+ insertItem( i18n( "Right panel" ), _rightSub );
+ insertItem( i18n( "Panel independent" ), _independentSub );
+ _independentSub->insertItem( i18n( "Choose executable..." ), EXECUTABLE_ID );
+ _independentSub->insertSeparator();
+
+ // read the expressions array from the user menu and populate menus
+ Expander expander;
+ for ( int i = 0; i < expander.placeholderCount(); ++i ) {
+ if ( expander.placeholder( i )->expression().isEmpty() ) {
+ if ( expander.placeholder( i )->needPanel() ) {
+ _activeSub->insertSeparator();
+ _otherSub->insertSeparator();
+ _leftSub->insertSeparator();
+ _rightSub->insertSeparator();
+ }
+ else
+ _independentSub->insertSeparator();
+ }
+ else {
+ if ( expander.placeholder( i )->needPanel() ) {
+ _activeSub->insertItem( i18n( expander.placeholder( i )->description().utf8() ), ( i | ACTIVE_MASK ) );
+ _otherSub->insertItem( i18n( expander.placeholder( i )->description().utf8() ), ( i | OTHER_MASK ) );
+ _leftSub->insertItem( i18n( expander.placeholder( i )->description().utf8() ), ( i | LEFT_MASK ) );
+ _rightSub->insertItem( i18n( expander.placeholder( i )->description().utf8() ), ( i | RIGHT_MASK ) );
+ }
+ else
+ _independentSub->insertItem( i18n( expander.placeholder( i )->description().utf8() ), ( i | INDEPENDENT_MASK ) );
+ }
+ }
+
+}
+
+
+QString AddPlaceholderPopup::getPlaceholder( const QPoint& pos ) {
+ int res = exec( pos );
+ if ( res == -1 )
+ return QString::null;
+
+ // add the selected flag to the command line
+ if ( res == EXECUTABLE_ID ) { // did the user need an executable ?
+ // select an executable
+ QString filename = KFileDialog::getOpenFileName(QString::null, QString::null, this);
+ if (filename != QString::null)
+ return filename + " "; // with extra space
+ //return filename; // without extra space
+ } else { // user selected something from the menus
+ Expander expander;
+ const exp_placeholder* currentPlaceholder = expander.placeholder( res & ~( ACTIVE_MASK | OTHER_MASK | LEFT_MASK | RIGHT_MASK | INDEPENDENT_MASK ) );
+// if ( &currentPlaceholder->expFunc == 0 ) {
+// KMessageBox::sorry( this, "BOFH Excuse #93:\nFeature not yet implemented" );
+// return QString::null;
+// }
+ ParameterDialog* parameterDialog = new ParameterDialog( currentPlaceholder, this );
+ QString panel, parameter = parameterDialog->getParameter();
+ delete parameterDialog;
+ // indicate the panel with 'a' 'o', 'l', 'r' or '_'.
+ if ( res & ACTIVE_MASK )
+ panel = "a";
+ else if ( res & OTHER_MASK )
+ panel = "o";
+ else if ( res & LEFT_MASK )
+ panel = "l";
+ else if ( res & RIGHT_MASK )
+ panel = "r";
+ else if ( res & INDEPENDENT_MASK )
+ panel = "_";
+ //return "%" + panel + currentPlaceholder->expression() + parameter + "% "; // with extra space
+ return "%" + panel + currentPlaceholder->expression() + parameter + "%"; // without extra space
+ }
+ return QString::null;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////// ParameterDialog ////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+
+ParameterDialog::ParameterDialog( const exp_placeholder* currentPlaceholder, QWidget *parent ) : KDialogBase( Plain, i18n("User Action Parameter Dialog"), Default | Ok, Ok, parent ) {
+ _parameter.clear();
+ _parameterCount = currentPlaceholder->parameterCount();
+
+ QVBoxLayout* layout = new QVBoxLayout( plainPage() );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 11 );
+
+ new QLabel( i18n("This placeholder allows some parameter:"), plainPage(), "intro" );
+
+ for (int i = 0; i < _parameterCount; ++i ) {
+ if ( currentPlaceholder->parameter( i ).preset() == "__placeholder" )
+ _parameter.append( new ParameterPlaceholder( currentPlaceholder->parameter( i ), plainPage() ) );
+ else if ( currentPlaceholder->parameter( i ).preset() == "__yes" )
+ _parameter.append( new ParameterYes( currentPlaceholder->parameter( i ), plainPage() ) );
+ else if ( currentPlaceholder->parameter( i ).preset() == "__no" )
+ _parameter.append( new ParameterNo( currentPlaceholder->parameter( i ), plainPage() ) );
+ else if ( currentPlaceholder->parameter( i ).preset() == "__file" )
+ _parameter.append( new ParameterFile( currentPlaceholder->parameter( i ), plainPage() ) );
+ else if ( currentPlaceholder->parameter( i ).preset().find( "__choose" ) != -1 )
+ _parameter.append( new ParameterChoose( currentPlaceholder->parameter( i ), plainPage() ) );
+ else if ( currentPlaceholder->parameter( i ).preset() == "__select" )
+ _parameter.append( new ParameterSelect( currentPlaceholder->parameter( i ), plainPage() ) );
+ else if ( currentPlaceholder->parameter( i ).preset() == "__goto" )
+ _parameter.append( new ParameterGoto( currentPlaceholder->parameter( i ), plainPage() ) );
+ else if ( currentPlaceholder->parameter( i ).preset() == "__syncprofile" )
+ _parameter.append( new ParameterSyncprofile( currentPlaceholder->parameter( i ), plainPage() ) );
+ else if ( currentPlaceholder->parameter( i ).preset() == "__searchprofile" )
+ _parameter.append( new ParameterSearch( currentPlaceholder->parameter( i ), plainPage() ) );
+ else if ( currentPlaceholder->parameter( i ).preset() == "__panelprofile" )
+ _parameter.append( new ParameterPanelprofile( currentPlaceholder->parameter( i ), plainPage() ) );
+ else if ( currentPlaceholder->parameter( i ).preset().find( "__int" ) != -1 )
+ _parameter.append( new ParameterInt( currentPlaceholder->parameter( i ), plainPage() ) );
+ else
+ _parameter.append( new ParameterText( currentPlaceholder->parameter( i ), plainPage() ) );
+ }
+
+ QFrame * line = new QFrame( plainPage() );
+ line->setFrameShape( QFrame::HLine );
+ line->setFrameShadow( QFrame::Sunken );
+
+ connect( this, SIGNAL(defaultClicked()), this, SLOT(reset()) );
+}
+
+QString ParameterDialog::getParameter() {
+ if ( _parameterCount == 0 ) // meaning no parameters
+ return QString::null;
+
+ if ( exec() == -1 )
+ return QString::null;
+
+ int lastParameter = _parameterCount;
+ while ( --lastParameter > -1 ) {
+ if ( _parameter[ lastParameter ]->text() != _parameter[ lastParameter ]->preset() || _parameter[ lastParameter ]->nessesary() )
+ break;
+ }
+
+ if ( lastParameter < 0) // all parameters have default-values
+ return QString::null;
+
+ QString parameter = "(";
+ for ( int i = 0; i <= lastParameter; ++i ) {
+ if ( i > 0 )
+ parameter += ", ";
+ parameter += "\"" + _parameter[ i ]->text().replace( "\"", "\\\"" ) + "\"";
+ }
+ parameter += ")";
+ return parameter;
+}
+
+void ParameterDialog::reset() {
+ for ( int i = 0; i < _parameterCount; ++i )
+ _parameter[ i ]->reset();
+}
+
+void ParameterDialog::slotOk() {
+ bool valid = true;
+ for (int i = 0; i < _parameterCount; ++i ) {
+ if ( _parameter[ i ]->nessesary() && ! _parameter[ i ]->valid() )
+ valid = false;
+ }
+
+ if ( valid )
+ accept();
+}
+
+///////////// ParameterText
+ParameterText::ParameterText( const exp_parameter& parameter, QWidget* parent ) : ParameterBase( parameter, parent ) {
+ QVBoxLayout* layout = new QVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ new QLabel( i18n( parameter.description().utf8() ), this );
+ _lineEdit = new KLineEdit( parameter.preset(), this );
+ _preset = parameter.preset();
+}
+
+QString ParameterText::text() {
+ return _lineEdit->text();
+}
+QString ParameterText::preset() {
+ return _preset;
+}
+void ParameterText::reset() {
+ _lineEdit->setText( _preset );
+}
+bool ParameterText::valid() {
+ if ( _lineEdit->text().isEmpty() )
+ return false;
+ else
+ return true;
+}
+
+///////////// ParameterPlaceholder
+ParameterPlaceholder::ParameterPlaceholder( const exp_parameter& parameter, QWidget* parent ) : ParameterBase( parameter, parent ) {
+ QVBoxLayout* layout = new QVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ new QLabel( i18n( parameter.description().utf8() ), this );
+ QHBox * hbox = new QHBox( this );
+ hbox->setSpacing( 6 );
+ _lineEdit = new KLineEdit( hbox );
+ _button = new QToolButton( hbox);
+ _button->setText( i18n("add") );
+ connect( _button, SIGNAL(clicked()), this, SLOT(addPlaceholder()) );
+}
+
+QString ParameterPlaceholder::text() {
+ return _lineEdit->text();
+}
+QString ParameterPlaceholder::preset() {
+ return QString::null;
+}
+void ParameterPlaceholder::reset() {
+ _lineEdit->setText( QString::null );
+}
+bool ParameterPlaceholder::valid() {
+ if ( _lineEdit->text().isEmpty() )
+ return false;
+ else
+ return true;
+}
+void ParameterPlaceholder::addPlaceholder() {
+ AddPlaceholderPopup* popup = new AddPlaceholderPopup( this );
+ QString exp = popup->getPlaceholder( mapToGlobal( QPoint( _button->pos().x() + _button->width() + 6, _button->pos().y() + _button->height() / 2 ) ) );
+ _lineEdit->insert( exp );
+ delete popup;
+}
+
+///////////// ParameterYes
+ParameterYes::ParameterYes( const exp_parameter& parameter, QWidget* parent ) : ParameterBase( parameter, parent ) {
+ QVBoxLayout* layout = new QVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ _checkBox = new QCheckBox( i18n( parameter.description().utf8() ), this );
+ _checkBox->setChecked( true );
+}
+
+QString ParameterYes::text() {
+ if ( _checkBox->isChecked() )
+ return QString::null;
+ else
+ return "No";
+}
+QString ParameterYes::preset() {
+ return QString::null;
+}
+void ParameterYes::reset() {
+ _checkBox->setChecked( true );
+}
+bool ParameterYes::valid() {
+ return true;
+}
+
+///////////// ParameterNo
+ParameterNo::ParameterNo( const exp_parameter& parameter, QWidget* parent ) : ParameterBase( parameter, parent ) {
+ QVBoxLayout* layout = new QVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ _checkBox = new QCheckBox( i18n( parameter.description().utf8() ), this );
+ _checkBox->setChecked( false );
+}
+
+QString ParameterNo::text() {
+ if ( _checkBox->isChecked() )
+ return "Yes";
+ else
+ return QString::null;
+}
+QString ParameterNo::preset() {
+ return QString::null;
+}
+void ParameterNo::reset() {
+ _checkBox->setChecked( false );
+}
+bool ParameterNo::valid() {
+ return true;
+}
+
+///////////// ParameterFile
+ParameterFile::ParameterFile( const exp_parameter& parameter, QWidget* parent ) : ParameterBase( parameter, parent ) {
+ QVBoxLayout* layout = new QVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ new QLabel( i18n( parameter.description().utf8() ), this );
+ QHBox * hbox = new QHBox( this );
+ hbox->setSpacing( 6 );
+ _lineEdit = new KLineEdit( hbox );
+ _button = new QToolButton( hbox);
+ KIconLoader *iconLoader = new KIconLoader();
+ _button->setPixmap( iconLoader->loadIcon( "fileopen", KIcon::Toolbar, 16 ) );
+ connect( _button, SIGNAL(clicked()), this, SLOT(addFile()) );
+}
+
+QString ParameterFile::text() {
+ return _lineEdit->text();
+}
+QString ParameterFile::preset() {
+ return QString::null;
+}
+void ParameterFile::reset() {
+ _lineEdit->setText( QString::null );
+}
+bool ParameterFile::valid() {
+ if ( _lineEdit->text().isEmpty() )
+ return false;
+ else
+ return true;
+}
+void ParameterFile::addFile() {
+ QString filename = KFileDialog::getOpenFileName(QString::null, QString::null, this);
+ _lineEdit->insert( filename );
+}
+
+///////////// ParameterChoose
+ParameterChoose::ParameterChoose( const exp_parameter& parameter, QWidget* parent ) : ParameterBase( parameter, parent ) {
+ QVBoxLayout* layout = new QVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ new QLabel( i18n( parameter.description().utf8() ), this );
+ _combobox = new KComboBox( this );
+ _combobox->insertStringList( QStringList::split( ";", parameter.preset().section(":", 1) ) );
+}
+
+QString ParameterChoose::text() {
+ return _combobox->currentText();
+}
+QString ParameterChoose::preset() {
+ return _combobox->text( 0 );
+}
+void ParameterChoose::reset() {
+ _combobox->setCurrentItem( 0 );
+}
+bool ParameterChoose::valid() {
+ return true;
+}
+
+///////////// ParameterSelect
+ParameterSelect::ParameterSelect( const exp_parameter& parameter, QWidget* parent ) : ParameterBase( parameter, parent ) {
+ QVBoxLayout* layout = new QVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ new QLabel( i18n( parameter.description().utf8() ), this );
+ _combobox = new KComboBox( this );
+ _combobox->setEditable( true );
+
+ krConfig->setGroup( "Private" );
+ QStrList lst;
+ int i = krConfig->readListEntry( "Predefined Selections", lst );
+ if ( i > 0 )
+ _combobox->insertStrList( lst );
+
+ _combobox->setCurrentText( "*" );
+}
+
+QString ParameterSelect::text() {
+ return _combobox->currentText();
+}
+QString ParameterSelect::preset() {
+ return "*";
+}
+void ParameterSelect::reset() {
+ _combobox->setCurrentText( "*" );
+}
+bool ParameterSelect::valid() {
+ return true;
+}
+
+///////////// ParameterGoto
+ParameterGoto::ParameterGoto( const exp_parameter& parameter, QWidget* parent ) : ParameterBase( parameter, parent ) {
+ QVBoxLayout* layout = new QVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ new QLabel( i18n( parameter.description().utf8() ), this );
+ QHBox * hbox = new QHBox( this );
+ hbox->setSpacing( 6 );
+ _lineEdit = new KLineEdit( hbox );
+ _lineEdit->setCompletionObject( new KURLCompletion( KURLCompletion::DirCompletion ) );
+ _dirButton = new QToolButton( hbox );
+ KIconLoader *iconLoader = new KIconLoader();
+ _dirButton->setPixmap( iconLoader->loadIcon( "fileopen", KIcon::Toolbar, 16 ) );
+ connect( _dirButton, SIGNAL(clicked()), this, SLOT(setDir()) );
+ _placeholderButton = new QToolButton( hbox);
+ _placeholderButton->setText( i18n("add") );
+ connect( _placeholderButton, SIGNAL(clicked()), this, SLOT(addPlaceholder()) );
+}
+
+QString ParameterGoto::text() {
+ return _lineEdit->text();
+}
+QString ParameterGoto::preset() {
+ return QString::null;
+}
+void ParameterGoto::reset() {
+ _lineEdit->setText( QString::null );
+}
+bool ParameterGoto::valid() {
+ if ( _lineEdit->text().isEmpty() )
+ return false;
+ else
+ return true;
+}
+void ParameterGoto::setDir() {
+ QString folder = KFileDialog::getExistingDirectory(QString::null, this);
+ _lineEdit->setText( folder );
+}
+void ParameterGoto::addPlaceholder() {
+ AddPlaceholderPopup* popup = new AddPlaceholderPopup( this );
+ QString exp = popup->getPlaceholder( mapToGlobal( QPoint( _placeholderButton->pos().x() + _placeholderButton->width() + 6, _placeholderButton->pos().y() + _placeholderButton->height() / 2 ) ) );
+ _lineEdit->insert( exp );
+ delete popup;
+}
+
+///////////// ParameterSyncprofile
+ParameterSyncprofile::ParameterSyncprofile( const exp_parameter& parameter, QWidget* parent ) : ParameterBase( parameter, parent ) {
+ QVBoxLayout* layout = new QVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ new QLabel( i18n( parameter.description().utf8() ), this );
+ _combobox = new KComboBox( this );
+
+ _combobox->insertStringList( ProfileManager::availableProfiles("SynchronizerProfile") );
+}
+
+QString ParameterSyncprofile::text() {
+ return _combobox->currentText();
+}
+QString ParameterSyncprofile::preset() {
+ return _combobox->text( 0 );
+}
+void ParameterSyncprofile::reset() {
+ _combobox->setCurrentItem( 0 );
+}
+bool ParameterSyncprofile::valid() {
+ return true;
+}
+
+///////////// ParameterSearch
+ParameterSearch::ParameterSearch( const exp_parameter& parameter, QWidget* parent ) : ParameterBase( parameter, parent ) {
+ QVBoxLayout* layout = new QVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ new QLabel( i18n( parameter.description().utf8() ), this );
+ _combobox = new KComboBox( this );
+
+ _combobox->insertStringList( ProfileManager::availableProfiles("SearcherProfile") );
+}
+
+QString ParameterSearch::text() {
+ return _combobox->currentText();
+}
+QString ParameterSearch::preset() {
+ return _combobox->text( 0 );
+}
+void ParameterSearch::reset() {
+ _combobox->setCurrentItem( 0 );
+}
+bool ParameterSearch::valid() {
+ return true;
+}
+
+///////////// ParameterPanelprofile
+ParameterPanelprofile::ParameterPanelprofile( const exp_parameter& parameter, QWidget* parent ) : ParameterBase( parameter, parent ) {
+ QVBoxLayout* layout = new QVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ new QLabel( i18n( parameter.description().utf8() ), this );
+ _combobox = new KComboBox( this );
+
+ _combobox->insertStringList( ProfileManager::availableProfiles("Panel") );
+}
+
+QString ParameterPanelprofile::text() {
+ return _combobox->currentText();
+}
+QString ParameterPanelprofile::preset() {
+ return _combobox->text( 0 );
+}
+void ParameterPanelprofile::reset() {
+ _combobox->setCurrentItem( 0 );
+}
+bool ParameterPanelprofile::valid() {
+ return true;
+}
+
+///////////// ParameterInt
+ParameterInt::ParameterInt( const exp_parameter& parameter, QWidget* parent ) : ParameterBase( parameter, parent ) {
+ QHBoxLayout* layout = new QHBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ new QLabel( i18n( parameter.description().utf8() ), this );
+ _spinbox = new KIntSpinBox( this );
+ QStringList para = QStringList::split( ";", parameter.preset().section(":", 1) );
+
+ _spinbox->setMinValue( para[0].toInt() );
+ _spinbox->setMaxValue( para[1].toInt() );
+ _spinbox->setLineStep( para[2].toInt() );
+ _spinbox->setValue( para[3].toInt() );
+
+ _default = _spinbox->value();
+}
+
+QString ParameterInt::text() {
+ return _spinbox->text();
+}
+QString ParameterInt::preset() {
+ return QString( "%1" ).arg( _default );
+}
+void ParameterInt::reset() {
+ return _spinbox->setValue( _default );
+}
+bool ParameterInt::valid() {
+ return true;
+}
+
+
+#include "addplaceholderpopup.moc"
diff --git a/krusader/ActionMan/addplaceholderpopup.h b/krusader/ActionMan/addplaceholderpopup.h
new file mode 100644
index 0000000..285d6a4
--- /dev/null
+++ b/krusader/ActionMan/addplaceholderpopup.h
@@ -0,0 +1,318 @@
+//
+// C++ Interface: addplaceholderpopup
+//
+// Description:
+//
+//
+// Author: Shie Erlich and Rafi Yanai <>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#ifndef ADDPLACEHOLDERPOPUP_H
+#define ADDPLACEHOLDERPOPUP_H
+
+#include <kpopupmenu.h>
+#include <kdialogbase.h>
+#include "../UserAction/expander.h"
+
+class QString;
+class KLineEdit;
+class QToolButton;
+class QCheckBox;
+class KComboBox;
+class KrBookmarkButton;
+class KURL;
+class KIntSpinBox;
+
+
+/**
+ * This reads Expander::placeholder[] and fills a popup for easy access to the UserAction Placeholder
+ * @author Jonas Bhr (http://www.jonas-baehr.de), Shie Erlich
+ */
+class AddPlaceholderPopup : public KPopupMenu {
+
+public:
+ 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.
+ * @param currentPlaceholder A pointer to the Placeholder the user has choosen
+ * @return a parameter-string
+ */
+ QString getParameter( exp_placeholder* currentPlaceholder );
+
+private:
+ KPopupMenu *_activeSub, *_otherSub, *_leftSub, *_rightSub, *_independentSub;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////// Parameter Widgets ///////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * abstract baseclass for all Parameter widgets
+ * @author Jonas Bhr (http://www.jonas-baehr.de)
+ */
+class ParameterBase : public QWidget {
+public:
+ inline ParameterBase( const exp_parameter& parameter, QWidget* parent ) : QWidget( parent ) { _nessesary = parameter.nessesary(); }
+ /**
+ * @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 realy needs this parameter
+ */
+ inline bool nessesary() { return _nessesary; }
+private:
+ bool _nessesary;
+};
+
+/**
+ * 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
+ * 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:
+ KIntSpinBox * _spinbox;
+ int _default;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////// ParameterDialog ////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Opens a dialog for the parameter. Depending on the default (preset) a differend widget is used.
+ * See Parameter-Classes for details
+ */
+class ParameterDialog : public KDialogBase {
+Q_OBJECT
+public:
+ ParameterDialog( const exp_placeholder* currentPlaceholder, QWidget *parent );
+
+ /**
+ * Use this to execute the dialog.
+ * @return a QString with all paremeters; ommiting the optional ones if they have the default-value.
+ */
+ QString getParameter();
+
+private:
+ typedef QValueList<ParameterBase*> 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
new file mode 100644
index 0000000..0534027
--- /dev/null
+++ b/krusader/ActionMan/useractionlistview.cpp
@@ -0,0 +1,232 @@
+//
+// C++ Implementation: useractionlistview
+//
+// Description:
+//
+//
+// Author: Jonas Bähr, (C) 2006
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#include "useractionlistview.h"
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <qptrlist.h>
+#include <qdom.h>
+
+#include "../krusader.h"
+#include "../UserAction/kraction.h"
+#include "../UserAction/useraction.h"
+
+#define COL_TITLE 0
+#define COL_NAME 1
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////// UserActionListView /////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+UserActionListView::UserActionListView( QWidget * parent, const char * name )
+ : KListView( parent, name )
+{
+ addColumn( i18n("Title") );
+ //addColumn( i18n("Identifier") );
+ setResizeMode( QListView::AllColumns );
+
+ setRootIsDecorated( true );
+ setSelectionMode( QListView::Extended ); // normaly select single items but one may use Ctrl or Shift to select multiple
+ setSorting( COL_TITLE );
+
+ update();
+}
+
+UserActionListView::~UserActionListView()
+{
+}
+
+QSize UserActionListView::sizeHint() const {
+ return QSize(200, 400);
+}
+
+
+void UserActionListView::update() {
+ clear();
+ UserAction::KrActionList list = krUserAction->actionList();
+ for ( KrAction* action = list.first(); action; action = list.next() )
+ insertAction( action );
+ //sort(); // this is done automaticly
+}
+
+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!
+ bool current = ( item == currentItem() );
+ bool selected = item->isSelected();
+ delete item;
+ item = insertAction( action );
+ if ( current )
+ setCurrentItem( item );
+ if ( selected )
+ setSelected( item, true );
+ }
+}
+
+UserActionListViewItem* UserActionListView::insertAction( KrAction* action ) {
+ if ( ! action )
+ return 0;
+
+ UserActionListViewItem* item;
+
+ if ( action->category().isEmpty() )
+ item = new UserActionListViewItem( this, action );
+ else {
+ QListViewItem* categoryItem = findCategoryItem( action->category() );
+ if ( ! categoryItem ) {
+ categoryItem = new KListViewItem( this, action->category() ); // create the new category item it not already present
+ categoryItem->setSelectable( false );
+ }
+ item = new UserActionListViewItem( categoryItem, action );
+ }
+
+ item->setAction( action );
+ return item;
+}
+
+QListViewItem* UserActionListView::findCategoryItem( const QString& category ) {
+ for ( QListViewItem* item = firstChild(); item; item = item->nextSibling() )
+ if ( item->text( COL_TITLE ) == category && item->text( COL_NAME ).isEmpty() ) // because actions must have a name, items without name haveto be categories
+ return item;
+
+ return 0;
+}
+
+UserActionListViewItem* UserActionListView::findActionItem( const KrAction* action ) {
+ for ( QListViewItemIterator it( this ); it.current(); ++it ) {
+ if ( UserActionListViewItem* item = dynamic_cast<UserActionListViewItem*>( it.current() ) ) {
+ if ( item->action() == action )
+ return item;
+ }
+ } //for
+ return 0;
+}
+
+KrAction * UserActionListView::currentAction() const {
+ if ( UserActionListViewItem* item = dynamic_cast<UserActionListViewItem*>( currentItem() ) )
+ return item->action();
+ else
+ return 0;
+}
+
+void UserActionListView::setCurrentAction( const KrAction* action) {
+ UserActionListViewItem* item = findActionItem( action );
+ if ( item ) {
+ setCurrentItem( item );
+// setSelected( item, true );
+// repaintItem( item );
+ }
+}
+
+void UserActionListView::setFirstActionCurrent() {
+ for ( QListViewItemIterator it( this ); it.current(); ++it ) {
+ if ( UserActionListViewItem* item = dynamic_cast<UserActionListViewItem*>( it.current() ) ) {
+ setCurrentItem( item );
+ break;
+ }
+ } //for
+}
+
+void UserActionListView::setCurrentItem( QListViewItem* item ) {
+ if ( ! item )
+ return;
+ ensureItemVisible( item );
+ QListView::setCurrentItem( item );
+}
+
+QDomDocument UserActionListView::dumpSelectedActions( QDomDocument* mergeDoc ) const {
+ QPtrList<QListViewItem> list = selectedItems();
+ QDomDocument doc;
+ if ( mergeDoc )
+ doc = *mergeDoc;
+ else
+ doc = UserAction::createEmptyDoc();
+ QDomElement root = doc.documentElement();
+
+ for ( QListViewItem* item = list.first(); item; item = list.next() )
+ if ( UserActionListViewItem* actionItem = dynamic_cast<UserActionListViewItem*>( item ) )
+ root.appendChild( actionItem->action()->xmlDump( doc ) );
+
+ return doc;
+}
+
+void UserActionListView::removeSelectedActions() {
+ QPtrList<QListViewItem> list = selectedItems();
+
+ for ( QListViewItem* item = list.first(); item; item = list.next() )
+ if ( UserActionListViewItem* actionItem = dynamic_cast<UserActionListViewItem*>( item ) ) {
+ delete actionItem->action(); // remove the action itself
+ delete actionItem; // remove the action from the list
+ } // if
+
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////// UserActionListViewItem ////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+UserActionListViewItem::UserActionListViewItem( QListView* view, KrAction* action )
+ : KListViewItem( view )
+{
+ setAction( action );
+}
+
+UserActionListViewItem::UserActionListViewItem( QListViewItem* item, KrAction * action )
+ : KListViewItem( item )
+{
+ setAction( action );
+}
+
+UserActionListViewItem::~UserActionListViewItem() {
+/* // remove category-item if the last member ofthiscategory disappears
+ if ( QListViewItem* item = dynamic_cast<QListViewItem*>( parent() ) ) {
+ if ( item->childCount() <= 1 )
+ item->deleteLater(); // not possible since not inherited from QObject
+ }*/
+}
+
+
+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().isEmpty() )
+ setPixmap( COL_TITLE, KGlobal::iconLoader()->loadIcon( _action->icon(), KIcon::Small ) );
+ setText( COL_TITLE, _action->text() );
+ setText( COL_NAME, _action->name() );
+}
+
+int UserActionListViewItem::compare( QListViewItem* i, int col, bool ascending ) const {
+// FIXME some how this only produces bullshit :-/
+// if ( i->text( COL_NAME ).isEmpty() ) { // categories only have titles
+// //kdDebug() << "this->title: " << text(COL_TITLE) << " |=| i->title: " << i->text(COL_TITLE) << endl;
+// return ( ascending ? -1 : 1 ); // <0 means this is smaller then i
+// }
+// else
+ return QListViewItem::compare( i, col, ascending );
+}
+
+
diff --git a/krusader/ActionMan/useractionlistview.h b/krusader/ActionMan/useractionlistview.h
new file mode 100644
index 0000000..e0a57f6
--- /dev/null
+++ b/krusader/ActionMan/useractionlistview.h
@@ -0,0 +1,81 @@
+//
+// C++ Interface: useractionlistview
+//
+// Description:
+//
+//
+// Author: Jonas Bähr, (C) 2006
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef USERACTIONLISTVIEW_H
+#define USERACTIONLISTVIEW_H
+
+#include <klistview.h>
+
+class KrAction;
+class QString;
+class UserActionListViewItem;
+class QDomDocument;
+
+/**
+ * @author Jonas Bähr
+ */
+class UserActionListView : public KListView {
+public:
+ UserActionListView( QWidget* parent = 0, const char* name = 0 );
+ ~UserActionListView();
+ virtual QSize sizeHint() const;
+
+ void update();
+ void update( KrAction* action );
+ UserActionListViewItem* insertAction( KrAction* action );
+
+ KrAction* currentAction() const;
+ void setCurrentAction( const KrAction* );
+
+ QDomDocument dumpSelectedActions( QDomDocument* mergeDoc = 0 ) const;
+
+ void removeSelectedActions();
+
+ /**
+ * makes the first action in the list current
+ */
+ void setFirstActionCurrent();
+
+ /**
+ * makes @e item current and ensures its visibility
+ */
+ virtual void setCurrentItem( QListViewItem* item );
+
+protected:
+ QListViewItem* findCategoryItem( const QString& category );
+ UserActionListViewItem* findActionItem( const KrAction* action );
+};
+
+
+/**
+ * @author Jonas Bähr
+ */
+class UserActionListViewItem : public KListViewItem {
+public:
+ UserActionListViewItem( QListView* view, KrAction* action );
+ UserActionListViewItem( QListViewItem* item, KrAction* action );
+ ~UserActionListViewItem();
+
+ void setAction( KrAction* action );
+ KrAction* action() const;
+ void update();
+
+ /**
+ * This reimplements qt's compare-function in order to have categories on the top of the list
+ */
+ int compare ( QListViewItem * i, int col, bool ascending ) const;
+
+private:
+ KrAction* _action;
+};
+
+
+#endif //USERACTIONLISTVIEW_H
diff --git a/krusader/ActionMan/useractionpage.cpp b/krusader/ActionMan/useractionpage.cpp
new file mode 100644
index 0000000..c4c91e7
--- /dev/null
+++ b/krusader/ActionMan/useractionpage.cpp
@@ -0,0 +1,317 @@
+//
+// C++ Implementation: useractionpage
+//
+// Description:
+//
+//
+// Author: Shie Erlich and Rafi Yanai <>, (C) 2006
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#include "useractionpage.h"
+
+#include <qsplitter.h>
+#include <qlayout.h>
+#include <qtoolbutton.h>
+#include <qtooltip.h>
+#include <klineedit.h>
+#include <kmessagebox.h>
+#include <kfiledialog.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kclipboard.h>
+
+#include "actionproperty.h"
+#include "useractionlistview.h"
+#include "../UserMenu/usermenu.h" //FIXME this should not be needed here!
+#include "../UserAction/useraction.h"
+#include "../UserAction/kraction.h"
+#include "../krusader.h"
+
+#define ICON(N) KGlobal::iconLoader()->loadIcon(N, KIcon::Toolbar)
+//This is the filter in the KFileDialog of Import/Export:
+static const char* FILE_FILTER = I18N_NOOP("*.xml|xml-files\n*|all files");
+
+
+UserActionPage::UserActionPage( QWidget* parent )
+ : QWidget( parent, "UserActionPage" )
+{
+ QVBoxLayout* layout = new QVBoxLayout( this, 0, 6, "UserActionPageLayout" ); // 0px margin, 6px item-spacing
+
+ // ======== pseudo-toolbar start ========
+ QHBoxLayout* toolbarLayout = new QHBoxLayout( layout, 0, 0 ); // neither margin nor spacing for the toolbar with autoRaise
+
+ newButton = new QToolButton( this, "newButton" );
+ newButton->setPixmap( ICON("filenew") );
+ newButton->setAutoRaise(true);
+ QToolTip::add( newButton, i18n("Create new useraction") );
+
+ importButton = new QToolButton( this, "importButton" );
+ importButton->setPixmap( ICON("fileimport") );
+ importButton->setAutoRaise(true);
+ QToolTip::add( importButton, i18n("Import useractions") );
+
+ exportButton = new QToolButton( this, "exportButton" );
+ exportButton->setPixmap( ICON("fileexport") );
+ exportButton->setAutoRaise(true);
+ QToolTip::add( exportButton, i18n("Export useractions") );
+
+ copyButton = new QToolButton( this, "copyButton" );
+ copyButton->setPixmap( ICON("editcopy") );
+ copyButton->setAutoRaise(true);
+ QToolTip::add( copyButton, i18n("Copy useractions to clipboard") );
+
+ pasteButton = new QToolButton( this, "pasteButton" );
+ pasteButton->setPixmap( ICON("editpaste") );
+ pasteButton->setAutoRaise(true);
+ QToolTip::add( pasteButton, i18n("Paste useractions from clipboard") );
+
+ removeButton = new QToolButton( this, "removeButton" );
+ removeButton->setPixmap( ICON("editdelete") );
+ removeButton->setAutoRaise(true);
+ QToolTip::add( removeButton, 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::null, // caption
+ "show UserAction help" //dontShowAgainName for the config
+ );
+*/
+ QSplitter *split = new QSplitter( this, "useractionpage splitter");
+ layout->addWidget( split, 1000 ); // again a very large stretch-factor to fix the height of the toolbar
+
+ actionTree = new UserActionListView( split, "actionTree" );
+ actionProperties = new ActionProperty( split, "actionProperties" );
+ actionProperties->setEnabled( false ); // if there are any actions in the list, the first is displayed and this widget is enabled
+
+ connect( actionTree, SIGNAL( currentChanged(QListViewItem*) ), 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( currentChanged(QListViewItem*) ), this, SLOT( slotChangeCurrent() ) );
+ actionTree->setCurrentAction( actionProperties->action() );
+ connect( actionTree, SIGNAL( currentChanged(QListViewItem*) ), SLOT( slotChangeCurrent() ) );
+ return false;
+ }
+ if ( answer == KMessageBox::Yes ) {
+ if ( ! actionProperties->validProperties() ) {
+ disconnect( actionTree, SIGNAL( currentChanged(QListViewItem*) ), this, SLOT( slotChangeCurrent() ) );
+ actionTree->setCurrentAction( actionProperties->action() );
+ connect( actionTree, SIGNAL( currentChanged(QListViewItem*) ), 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
+ 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
+ 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().latin1() );
+ krUserAction->addKrAction( action );
+ actionProperties->updateAction( action );
+ UserActionListViewItem* item = actionTree->insertAction( action );
+ actionTree->setCurrentItem( item );
+ krApp->userMenu->update();
+ }
+ 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<UserActionListViewItem*>( 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
+ i18n("Remove"), //Label for the continue-button
+ "Confirm Remove UserAction", //dontAskAgainName (for the config-file)
+ KMessageBox::Dangerous) ;
+
+ if ( messageDelete != KMessageBox::Continue )
+ return;
+
+ actionTree->removeSelectedActions();
+
+ apply();
+}
+
+void UserActionPage::slotImport() {
+ QString filename = KFileDialog::getOpenFileName(QString::null, i18n(FILE_FILTER), this);
+ if ( filename.isEmpty() )
+ return;
+
+ UserAction::KrActionList newActions;
+ krUserAction->readFromFile( filename, UserAction::renameDoublicated, &newActions );
+ for ( KrAction* action = newActions.first(); action; action = newActions.next() )
+ actionTree->insertAction( action );
+
+ if ( newActions.count() > 0 ) {
+ apply();
+ }
+}
+
+void UserActionPage::slotExport() {
+ if ( ! dynamic_cast<UserActionListViewItem*>( actionTree->currentItem() ) )
+ return;
+
+ QString filename = KFileDialog::getSaveFileName(QString::null, i18n(FILE_FILTER), this);
+ if ( filename.isEmpty() )
+ return;
+
+ QDomDocument doc = QDomDocument( ACTION_DOCTYPE );
+ QFile file( filename );
+ int answer = 0;
+ if( file.open( IO_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
+ i18n("Overwrite"), //label for Yes-Button
+ 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
+ i18n("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("Can't open %1 for writing!\nNothing exported.").arg(filename),
+ i18n("Export failed!")
+ );
+}
+
+void UserActionPage::slotToClip() {
+ if ( ! dynamic_cast<UserActionListViewItem*>( actionTree->currentItem() ) )
+ return;
+
+ QDomDocument doc = actionTree->dumpSelectedActions();
+ KApplication::clipboard()->setText( doc.toString() );
+}
+
+void UserActionPage::slotFromClip() {
+ QDomDocument doc( ACTION_DOCTYPE );
+ if ( doc.setContent( KApplication::clipboard()->text() ) ) {
+ QDomElement root = doc.documentElement();
+ UserAction::KrActionList newActions;
+ krUserAction->readFromElement( root, UserAction::renameDoublicated, &newActions );
+ for ( KrAction* action = newActions.first(); action; action = newActions.next() )
+ actionTree->insertAction( action );
+ 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();
+}
+
+
+#include "useractionpage.moc"
diff --git a/krusader/ActionMan/useractionpage.h b/krusader/ActionMan/useractionpage.h
new file mode 100644
index 0000000..cda2dfc
--- /dev/null
+++ b/krusader/ActionMan/useractionpage.h
@@ -0,0 +1,73 @@
+//
+// C++ Interface: useractionpage
+//
+// Description:
+//
+//
+// Author: Shie Erlich and Rafi Yanai <>, (C) 2006
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef USERACTIONPAGE_H
+#define USERACTIONPAGE_H
+
+#include <qwidget.h>
+
+class UserActionListView;
+class ActionProperty;
+class QToolButton;
+
+/**
+ * @author Jonas Bähr
+*/
+class UserActionPage : public QWidget {
+Q_OBJECT
+public:
+ 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(); ///< emited on changes to an action (used to enable the apply-button)
+ void applied(); ///< emited 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"
+ */
+ 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 //USERACTIONPAGE_H
diff --git a/krusader/BookMan/Makefile.am b/krusader/BookMan/Makefile.am
new file mode 100644
index 0000000..3f602d3
--- /dev/null
+++ b/krusader/BookMan/Makefile.am
@@ -0,0 +1,11 @@
+noinst_LIBRARIES = libBookMan.a
+
+INCLUDES = $(all_includes)
+
+libBookMan_a_METASOURCES = AUTO
+
+libBookMan_a_SOURCES = \
+ krbookmark.cpp \
+ krbookmarkbutton.cpp \
+ krbookmarkhandler.cpp \
+ kraddbookmarkdlg.cpp
diff --git a/krusader/BookMan/kraddbookmarkdlg.cpp b/krusader/BookMan/kraddbookmarkdlg.cpp
new file mode 100644
index 0000000..c5ecfd4
--- /dev/null
+++ b/krusader/BookMan/kraddbookmarkdlg.cpp
@@ -0,0 +1,117 @@
+#include "kraddbookmarkdlg.h"
+#include "../krusader.h"
+#include "krbookmarkhandler.h"
+#include <klocale.h>
+#include <qheader.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <kinputdialog.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+
+KrAddBookmarkDlg::KrAddBookmarkDlg(QWidget *parent, KURL url):
+ KDialogBase(KDialogBase::Swallow, i18n("Add Bookmark"),
+ KDialogBase::User1 | KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, parent) {
+ // create the 'new folder' button
+ setButtonText(KDialogBase::User1, i18n("New Folder"));
+ showButton(KDialogBase::User1, false); // hide it until _createIn is shown
+ connect(this, SIGNAL(user1Clicked()), this, SLOT(newFolder()));
+
+ // create the main widget
+ QWidget *page = new QWidget(this);
+ setMainWidget(page);
+
+ QGridLayout *layout = new QGridLayout(page, 1, 1, 0, spacingHint()); // expanding
+ // name and url
+ QLabel *lb1 = new QLabel(i18n("Name:"), page);
+ _name = new KLineEdit(page);
+ _name->setText(url.prettyURL()); // default name is the url
+ _name->selectAll(); // make the text selected
+ layout->addWidget(lb1, 0, 0);
+ layout->addWidget(_name, 0, 1);
+
+ QLabel *lb2 = new QLabel(i18n("URL:"), page);
+ _url = new KLineEdit(page);
+ layout->addWidget(lb2, 1, 0);
+ layout->addWidget(_url, 1, 1);
+ _url->setText(url.prettyURL()); // set the url in the field
+
+ // create in linedit and button
+ QLabel *lb3 = new QLabel(i18n("Create in:"), page);
+ _folder = new KLineEdit(page);
+ layout->addWidget(lb3, 2, 0);
+ layout->addWidget(_folder, 2, 1);
+ _folder->setReadOnly(true);
+
+ _createInBtn = new QToolButton(page);
+ _createInBtn->setPixmap(krLoader->loadIcon("down", KIcon::Small));
+ _createInBtn->setToggleButton(true);
+ connect(_createInBtn, SIGNAL(toggled(bool)), this, SLOT(toggleCreateIn(bool )));
+ layout->addWidget(_createInBtn, 2, 2);
+
+ setDetailsWidget(createInWidget());
+
+ _name->setFocus();
+}
+
+void KrAddBookmarkDlg::toggleCreateIn(bool show) {
+ _createInBtn->setPixmap(krLoader->loadIcon(show ? "up" :"down", KIcon::Small));
+ showButton(KDialogBase::User1, show);
+ setDetails(show);
+}
+
+// creates the widget that lets you decide where to put the new bookmark
+QWidget *KrAddBookmarkDlg::createInWidget() {
+ _createIn = new KListView(this);
+ _createIn->addColumn("Folders");
+ _createIn->header()->hide();
+ _createIn->setRootIsDecorated(true);
+ _createIn->setAlternateBackground(QColor()); // disable alternate coloring
+
+ KListViewItem *item = new KListViewItem(_createIn, i18n("Bookmarks"));
+ item->setOpen(true);
+ item->setSelected(true);
+ _xr[item] = krBookMan->_root;
+
+ populateCreateInWidget(krBookMan->_root, item);
+ _createIn->setCurrentItem(item);
+ createInSelection(item);
+ connect(_createIn, SIGNAL(selectionChanged(QListViewItem*)), this, SLOT(createInSelection(QListViewItem*)));
+
+ return _createIn;
+}
+
+void KrAddBookmarkDlg::createInSelection(QListViewItem *item) {
+ if (item) {
+ _folder->setText(_xr[static_cast<KListViewItem*>(item)]->text());
+ }
+}
+
+void KrAddBookmarkDlg::populateCreateInWidget(KrBookmark *root, KListViewItem *parent) {
+ for (KrBookmark *bm = root->children().first(); bm; bm = root->children().next()) {
+ if (bm->isFolder()) {
+ KListViewItem *item = new KListViewItem(parent, bm->text());
+ item->setOpen(true);
+ _xr[item] = bm;
+ populateCreateInWidget(bm, item);
+ }
+ }
+}
+
+void KrAddBookmarkDlg::newFolder() {
+ // get the name
+ QString newFolder = KInputDialog::getText(i18n("New Folder"), i18n("Folder name:"), QString::null, 0, this);
+ if (newFolder == QString::null)
+ return;
+ // add to the list in bookman
+ KrBookmark *bm = new KrBookmark(newFolder);
+ krBookMan->addBookmark(bm, _xr[static_cast<KListViewItem*>(_createIn->selectedItem())]);
+ // fix the gui
+ KListViewItem *item = new KListViewItem(_createIn->selectedItem(), bm->text());
+ _xr[item] = bm;
+
+ _createIn->setCurrentItem(item);
+ item->setSelected(true);
+}
+
+#include "kraddbookmarkdlg.moc"
diff --git a/krusader/BookMan/kraddbookmarkdlg.h b/krusader/BookMan/kraddbookmarkdlg.h
new file mode 100644
index 0000000..d9db75c
--- /dev/null
+++ b/krusader/BookMan/kraddbookmarkdlg.h
@@ -0,0 +1,39 @@
+#ifndef KRADDBOOKMARKDLG_H
+#define KRADDBOOKMARKDLG_H
+
+#include "krbookmark.h"
+#include "../VFS/vfs.h"
+#include <kdialogbase.h>
+#include <kurl.h>
+#include <klineedit.h>
+#include <qmap.h>
+#include <klistview.h>
+#include <qtoolbutton.h>
+
+class KrAddBookmarkDlg: public KDialogBase {
+ Q_OBJECT
+public:
+ KrAddBookmarkDlg(QWidget *parent, KURL url = 0);
+ KURL url() const { return vfs::fromPathOrURL(_url->text()); }
+ QString name() const { return _name->text(); }
+ KrBookmark *folder() const { return _xr[static_cast<KListViewItem*>(_createIn->selectedItem())]; }
+
+protected:
+ QWidget *createInWidget();
+ void populateCreateInWidget(KrBookmark *root, KListViewItem *parent);
+
+protected slots:
+ void toggleCreateIn(bool show);
+ void createInSelection(QListViewItem *item);
+ void newFolder();
+
+private:
+ KLineEdit *_name;
+ KLineEdit *_url;
+ KLineEdit *_folder;
+ KListView *_createIn;
+ QMap<KListViewItem*, KrBookmark*> _xr;
+ QToolButton *_createInBtn;
+};
+
+#endif // KRADDBOOKMARKDLG_H
diff --git a/krusader/BookMan/krbookmark.cpp b/krusader/BookMan/krbookmark.cpp
new file mode 100644
index 0000000..f0708d3
--- /dev/null
+++ b/krusader/BookMan/krbookmark.cpp
@@ -0,0 +1,92 @@
+#include "krbookmark.h"
+#include "../krusader.h"
+#include "../VFS/krarchandler.h"
+#include <kactioncollection.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#define BM_NAME(X) (QString("Bookmark:")+X)
+
+#if KDE_IS_VERSION(3,4,0)
+static const char* NAME_DEVICES = I18N_NOOP("Media");
+#else
+static const char* NAME_DEVICES = I18N_NOOP("Devices");
+#endif
+static const char* NAME_VIRTUAL = I18N_NOOP("Virtual Filesystem");
+static const char* NAME_LAN = I18N_NOOP("Local Network");
+
+KrBookmark::KrBookmark(QString name, KURL url, KActionCollection *parent, QString icon, QString actionName ):
+ KAction(name, 0, 0, 0, parent, actionName.isNull() ? BM_NAME(name).latin1() : BM_NAME(actionName).latin1()),
+ _url(url), _folder(false), _separator(false) {
+ connect(this, SIGNAL(activated()), this, SLOT(activatedProxy()));
+ // do we have an icon?
+ if (!icon.isEmpty())
+ setIcon(icon);
+ else {
+ // what kind of a url is it?
+ if (_url.isLocalFile()) {
+ setIcon("folder");
+ } else { // is it an archive?
+ if (KRarcHandler::isArchive(_url))
+ setIcon("tar");
+ else setIcon("folder_html");
+ }
+ }
+
+ _children.setAutoDelete(true);
+}
+
+KrBookmark::KrBookmark(QString name, QString icon):
+ KAction(name, 0, 0, 0, 0), _folder(true), _separator(false) {
+ setIcon(icon=="" ? "folder" : icon);
+}
+
+KrBookmark* KrBookmark::getExistingBookmark(QString actionName, KActionCollection *collection) {
+ return static_cast<KrBookmark*>(collection->action(BM_NAME(actionName).latin1()));
+}
+
+KrBookmark* KrBookmark::devices(KActionCollection *collection) {
+ KrBookmark *bm = getExistingBookmark(i18n(NAME_DEVICES), collection);
+ if (!bm) {
+#if KDE_IS_VERSION(3,4,0)
+ bm = new KrBookmark(i18n(NAME_DEVICES), "media:/", collection);
+#else
+ bm = new KrBookmark(i18n(NAME_DEVICES), "devices:/", collection);
+#endif
+ bm->setIconSet(krLoader->loadIcon("blockdevice", KIcon::Small));
+ }
+ return bm;
+}
+
+KrBookmark* KrBookmark::virt(KActionCollection *collection) {
+ KrBookmark *bm = getExistingBookmark(i18n(NAME_VIRTUAL), collection);
+ if (!bm) {
+ bm = new KrBookmark(i18n(NAME_VIRTUAL), "virt:/", collection);
+ bm->setIconSet(krLoader->loadIcon("pipe", KIcon::Small));
+ }
+ return bm;
+}
+
+KrBookmark* KrBookmark::lan(KActionCollection *collection) {
+ KrBookmark *bm = getExistingBookmark(i18n(NAME_LAN), collection);
+ if (!bm) {
+ bm = new KrBookmark(i18n(NAME_LAN), "lan:/", collection);
+ bm->setIconSet(krLoader->loadIcon("network", KIcon::Small));
+ }
+ return bm;
+}
+
+KrBookmark* KrBookmark::separator() {
+ KrBookmark *bm = new KrBookmark("");
+ bm->_separator = true;
+ bm->_folder = false;
+ return bm;
+}
+
+
+void KrBookmark::activatedProxy() {
+ emit activated(url());
+}
+
+#include "krbookmark.moc"
diff --git a/krusader/BookMan/krbookmark.h b/krusader/BookMan/krbookmark.h
new file mode 100644
index 0000000..fda39ce
--- /dev/null
+++ b/krusader/BookMan/krbookmark.h
@@ -0,0 +1,45 @@
+#ifndef KRBOOKMARK_H
+#define KRBOOKMARK_H
+
+#include <kaction.h>
+#include <qptrlist.h>
+#include <kurl.h>
+
+class KActionCollection;
+
+class KrBookmark: public KAction {
+ Q_OBJECT
+public:
+ KrBookmark(QString name, KURL url, KActionCollection *parent, QString icon = "", QString actionName = QString::null );
+ KrBookmark(QString name, QString icon = ""); // creates a folder
+ // text() and setText() to change the name of the bookmark
+ // icon() and setIcon() to change icons (by name)
+ inline const KURL& url() const { return _url; }
+ inline void setURL(const KURL& url) { _url = url; }
+ inline bool isFolder() const { return _folder; }
+ inline bool isSeparator() const { return _separator; }
+ QPtrList<KrBookmark>& children() { return _children; }
+
+ static KrBookmark* getExistingBookmark(QString actionName, KActionCollection *collection);
+ // ----- special bookmarks
+ static KrBookmark* devices(KActionCollection *collection);
+ static KrBookmark* virt(KActionCollection *collection);
+ static KrBookmark* lan(KActionCollection *collection);
+ static KrBookmark* separator();
+
+signals:
+ void activated(const KURL& url);
+
+protected slots:
+ void activatedProxy();
+
+
+private:
+ KURL _url;
+ QString _icon;
+ bool _folder;
+ bool _separator;
+ QPtrList<KrBookmark> _children;
+};
+
+#endif // KRBOOKMARK_H
diff --git a/krusader/BookMan/krbookmarkbutton.cpp b/krusader/BookMan/krbookmarkbutton.cpp
new file mode 100644
index 0000000..08d13a5
--- /dev/null
+++ b/krusader/BookMan/krbookmarkbutton.cpp
@@ -0,0 +1,38 @@
+#include "krbookmarkbutton.h"
+#include "krbookmarkhandler.h"
+#include "../krusader.h"
+#include <qpixmap.h>
+#include <kiconloader.h>
+#include <kaction.h>
+#include <klocale.h>
+#include <kpopupmenu.h>
+#include <kdebug.h>
+
+KrBookmarkButton::KrBookmarkButton(QWidget *parent): QToolButton(parent) {
+ QPixmap icon = krLoader->loadIcon("bookmark", KIcon::Toolbar, 16);
+ setFixedSize(icon.width() + 4, icon.height() + 4);
+ setPixmap(icon);
+ setTextLabel(i18n("BookMan II"), true);
+ setPopupDelay(10); // 0.01 seconds press
+ setAcceptDrops(false);
+
+ acmBookmarks = new KActionMenu(i18n("Bookmarks"), "bookmark", 0, 0);
+ acmBookmarks->setDelayed(false);
+ acmBookmarks->popupMenu()->setKeyboardShortcutsEnabled(true);
+ acmBookmarks->popupMenu()->setKeyboardShortcutsExecute(true);
+
+ setPopup(acmBookmarks->popupMenu());
+ connect(this, SIGNAL(pressed()), this, SLOT(populate()));
+ populate();
+}
+
+void KrBookmarkButton::populate() {
+ krBookMan->populate(static_cast<KPopupMenu*>(popup()));
+}
+
+void KrBookmarkButton::openPopup() {
+ populate();
+ popup()->exec(mapToGlobal(QPoint(0, height())));
+}
+
+#include "krbookmarkbutton.moc"
diff --git a/krusader/BookMan/krbookmarkbutton.h b/krusader/BookMan/krbookmarkbutton.h
new file mode 100644
index 0000000..1267871
--- /dev/null
+++ b/krusader/BookMan/krbookmarkbutton.h
@@ -0,0 +1,23 @@
+#ifndef KRBOOKMARK_BUTTON_H
+#define KRBOOKMARK_BUTTON_H
+
+#include <qtoolbutton.h>
+#include "krbookmarkhandler.h"
+
+class KrBookmarkButton: public QToolButton {
+ Q_OBJECT
+public:
+ KrBookmarkButton(QWidget *parent);
+ void openPopup();
+
+signals:
+ void openUrl(const KURL &url);
+
+protected slots:
+ void populate();
+
+private:
+ KActionMenu *acmBookmarks;
+};
+
+#endif // KRBOOKMARK_BUTTON_H
diff --git a/krusader/BookMan/krbookmarkhandler.cpp b/krusader/BookMan/krbookmarkhandler.cpp
new file mode 100644
index 0000000..9f1413b
--- /dev/null
+++ b/krusader/BookMan/krbookmarkhandler.cpp
@@ -0,0 +1,576 @@
+#include "krbookmarkhandler.h"
+#include "kraddbookmarkdlg.h"
+#include "../krusader.h"
+#include "../krslots.h"
+#include "../Dialogs/popularurls.h"
+#include "../VFS/vfs.h"
+#include <kiconloader.h>
+#include <kmessagebox.h>
+#include <qptrlist.h>
+#include <kactioncollection.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kbookmarkmanager.h>
+#include <kstandarddirs.h>
+#include <qfile.h>
+#include <qcursor.h>
+
+#define SPECIAL_BOOKMARKS true
+
+// ------------------------ for internal use
+#define BOOKMARKS_FILE "krusader/krbookmarks.xml"
+#define CONNECT_BM(X) { disconnect(X, SIGNAL(activated(const KURL&)), 0, 0); connect(X, SIGNAL(activated(const KURL&)), this, SLOT(slotActivated(const KURL&))); }
+
+KrBookmarkHandler::KrBookmarkHandler(): QObject(0), _middleClick(false), _mainBookmarkPopup( 0 ), _specialBookmarkIDs(), _bookmarkIDTable() {
+ // create our own action collection and make the shortcuts apply only to parent
+ _privateCollection = new KActionCollection(krApp, "private collection");
+ _collection = krApp->actionCollection();
+
+ // create _root: father of all bookmarks. it is a dummy bookmark and never shown
+ _root = new KrBookmark(i18n("Bookmarks"));
+
+ _bookmarkIDTable.setAutoDelete( true );
+
+ // load bookmarks
+ importFromFile();
+
+ // hack
+ manager = KBookmarkManager::managerForFile(locateLocal( "data", BOOKMARKS_FILE ), false);
+ connect(manager, SIGNAL(changed(const QString&, const QString& )), this, SLOT(bookmarksChanged(const QString&, const QString& )));
+}
+
+KrBookmarkHandler::~KrBookmarkHandler() {
+ delete manager;
+ delete _privateCollection;
+}
+
+void KrBookmarkHandler::menuOperation(int id) {
+ switch (id) {
+ case BookmarkCurrent:
+ bookmarkCurrent(ACTIVE_PANEL->virtualPath());
+ break;
+ case ManageBookmarks:
+ manager->slotEditBookmarks();
+ break;
+ }
+}
+
+void KrBookmarkHandler::bookmarkCurrent(KURL url) {
+ KrAddBookmarkDlg dlg(krApp, url);
+ if (dlg.exec() == KDialog::Accepted) {
+ KrBookmark *bm = new KrBookmark(dlg.name(), dlg.url(), _collection);
+ addBookmark(bm, dlg.folder());
+ }
+}
+
+void KrBookmarkHandler::addBookmark(KrBookmark *bm, KrBookmark *folder) {
+ if (folder == 0)
+ folder = _root;
+
+ // add to the list (bottom)
+ folder->children().append(bm);
+
+ exportToFile();
+}
+
+void KrBookmarkHandler::deleteBookmark(KrBookmark *bm) {
+ if( bm->isFolder() )
+ clearBookmarks( bm ); // remove the child bookmarks
+ removeReferences( _root, bm );
+ bm->unplugAll();
+ delete bm;
+
+ exportToFile();
+}
+
+void KrBookmarkHandler::removeReferences( KrBookmark *root, KrBookmark *bmToRemove ) {
+ int index = root->children().find( bmToRemove );
+ if( index >= 0 )
+ root->children().take( index );
+
+ KrBookmark *bm = root->children().first();
+ while (bm) {
+ if (bm->isFolder())
+ removeReferences(bm, bmToRemove);
+ bm = root->children().next();
+ }
+}
+
+void KrBookmarkHandler::exportToFileBookmark(QDomDocument &doc, QDomElement &where, KrBookmark *bm) {
+ if( bm->isSeparator() ) {
+ QDomElement bookmark = doc.createElement("separator");
+ where.appendChild(bookmark);
+ }
+ else {
+ QDomElement bookmark = doc.createElement("bookmark");
+ // url
+ bookmark.setAttribute("href", bm->url().prettyURL());
+ // icon
+ bookmark.setAttribute("icon", bm->icon());
+ // title
+ QDomElement title = doc.createElement("title");
+ title.appendChild(doc.createTextNode(bm->text()));
+ bookmark.appendChild(title);
+
+ where.appendChild(bookmark);
+ }
+}
+
+void KrBookmarkHandler::exportToFileFolder(QDomDocument &doc, QDomElement &parent, KrBookmark *folder) {
+ for (KrBookmark *bm = folder->children().first(); bm; bm = folder->children().next()) {
+ if (bm->isFolder()) {
+ QDomElement newFolder = doc.createElement("folder");
+ newFolder.setAttribute("icon", bm->icon());
+ parent.appendChild(newFolder);
+ QDomElement title = doc.createElement("title");
+ title.appendChild(doc.createTextNode(bm->text()));
+ newFolder.appendChild(title);
+ exportToFileFolder(doc, newFolder, bm);
+ } else {
+ exportToFileBookmark(doc, parent, bm);
+ }
+ }
+}
+
+// export to file using the xbel standard
+//
+// <xbel>
+// <bookmark href="http://developer.kde.org"><title>Developer Web Site</title></bookmark>
+// <folder folded="no">
+// <title>Title of this folder</title>
+// <bookmark icon="kde" href="http://www.kde.org"><title>KDE Web Site</title></bookmark>
+// <folder toolbar="yes">
+// <title>My own bookmarks</title>
+// <bookmark href="http://www.koffice.org"><title>KOffice Web Site</title></bookmark>
+// <separator/>
+// <bookmark href="http://www.kdevelop.org"><title>KDevelop Web Site</title></bookmark>
+// </folder>
+// </folder>
+// </xbel>
+void KrBookmarkHandler::exportToFile() {
+ QDomDocument doc( "xbel" );
+ QDomElement root = doc.createElement( "xbel" );
+ doc.appendChild( root );
+
+ exportToFileFolder(doc, root, _root);
+ if (!doc.firstChild().isProcessingInstruction()) {
+ // adding: <?xml version="1.0" encoding="UTF-8" ?> if not already present
+ QDomProcessingInstruction instr = doc.createProcessingInstruction( "xml",
+ "version=\"1.0\" encoding=\"UTF-8\" ");
+ doc.insertBefore( instr, doc.firstChild() );
+ }
+
+
+ QString filename = locateLocal( "data", BOOKMARKS_FILE );
+ QFile file(filename);
+ if ( file.open( IO_WriteOnly ) ) {
+ QTextStream stream( &file );
+ stream.setEncoding(stream.UnicodeUTF8);
+ stream << doc.toString();
+ file.close();
+ } else {
+ KMessageBox::error(krApp, i18n("Unable to write to %1").arg(filename), i18n("Error"));
+ }
+}
+
+bool KrBookmarkHandler::importFromFileBookmark(QDomElement &e, KrBookmark *parent, QString path, QString *errorMsg) {
+ QString url, name, icon;
+ // verify tag
+ if (e.tagName() != "bookmark") {
+ *errorMsg = e.tagName() + i18n(" instead of ")+"bookmark";
+ return false;
+ }
+ // verify href
+ if (!e.hasAttribute("href")) {
+ *errorMsg = i18n("missing tag ")+ "href";
+ return false;
+ } else url = e.attribute("href");
+ // verify title
+ QDomElement te = e.firstChild().toElement();
+ if (te.tagName() != "title") {
+ *errorMsg = i18n("missing tag ")+"title";
+ return false;
+ } else name = te.text();
+ // do we have an icon?
+ if (e.hasAttribute("icon")) {
+ icon=e.attribute("icon");
+ }
+ // ok: got name and url, let's add a bookmark
+ KrBookmark *bm = KrBookmark::getExistingBookmark(path+name, _collection);
+ if (!bm) {
+ bm = new KrBookmark(name, vfs::fromPathOrURL( url ), _collection, icon, path+name);
+ parent->children().append(bm);
+ }
+
+ return true;
+}
+
+bool KrBookmarkHandler::importFromFileFolder(QDomNode &first, KrBookmark *parent, QString path, QString *errorMsg) {
+ QString name;
+ QDomNode n = first;
+ while (!n.isNull()) {
+ QDomElement e = n.toElement();
+ if (e.tagName() == "bookmark") {
+ if (!importFromFileBookmark(e, parent, path, errorMsg))
+ return false;
+ } else if (e.tagName() == "folder") {
+ QString iconName = "";
+ if (e.hasAttribute("icon")) iconName=e.attribute("icon");
+ // the title is the first child of the folder
+ QDomElement tmp = e.firstChild().toElement();
+ if (tmp.tagName() != "title") {
+ *errorMsg = i18n("missing tag ")+"title";
+ return false;
+ } else name = tmp.text();
+ KrBookmark *folder = new KrBookmark(name, iconName);
+ parent->children().append(folder);
+
+ QDomNode nextOne = tmp.nextSibling();
+ if (!importFromFileFolder(nextOne, folder, path + name + "/", errorMsg))
+ return false;
+ } else if (e.tagName() == "separator") {
+ parent->children().append(KrBookmark::separator());
+ }
+ n = n.nextSibling();
+ }
+ return true;
+}
+
+
+void KrBookmarkHandler::importFromFile() {
+ clearBookmarks(_root);
+
+ QString filename = locateLocal( "data", BOOKMARKS_FILE );
+ QFile file( filename );
+ if ( !file.open(IO_ReadOnly))
+ return; // no bookmarks file
+
+ QString errorMsg;
+ QDomNode n;
+ QDomElement e;
+ QDomDocument doc( "xbel" );
+ if ( !doc.setContent( &file, &errorMsg ) ) {
+ goto ERROR;
+ }
+ // iterate through the document: first child should be "xbel" (skip all until we find it)
+ n = doc.firstChild();
+ while (!n.isNull() && n.toElement().tagName()!="xbel")
+ n = n.nextSibling();
+
+ if (n.isNull() || n.toElement().tagName()!="xbel") {
+ errorMsg = i18n("%1 doesn't seem to be a valid Bookmarks file").arg(filename);
+ goto ERROR;
+ } else n = n.firstChild(); // skip the xbel part
+ importFromFileFolder(n, _root, "", &errorMsg);
+ goto SUCCESS;
+
+ERROR:
+ KMessageBox::error(krApp, i18n("Error reading bookmarks file: %1").arg(errorMsg), i18n( "Error" ));
+
+SUCCESS:
+ file.close();
+}
+
+void KrBookmarkHandler::populate(KPopupMenu *menu) {
+ _mainBookmarkPopup = menu;
+ menu->clear();
+ _bookmarkIDTable.clear();
+ _specialBookmarkIDs.clear();
+ buildMenu(_root, menu);
+}
+
+void KrBookmarkHandler::buildMenu(KrBookmark *parent, KPopupMenu *menu) {
+ static int inSecondaryMenu = 0; // used to know if we're on the top menu
+
+ // run the loop twice, in order to put the folders on top. stupid but easy :-)
+ // note: this code drops the separators put there by the user
+ for (KrBookmark *bm = parent->children().first(); bm; bm = parent->children().next()) {
+ if (!bm->isFolder()) continue;
+ KPopupMenu *newMenu = new KPopupMenu(menu);
+ int id = menu->insertItem(QIconSet(krLoader->loadIcon(bm->icon(), KIcon::Small)),
+ bm->text(), newMenu, -1 /* dummy id */, -1 /* end of list */);
+
+ if( !_bookmarkIDTable.find( menu ) )
+ _bookmarkIDTable.insert( menu, new QMap<int, KrBookmark *> );
+ (*_bookmarkIDTable[ menu ])[ id ] = bm;
+
+ ++inSecondaryMenu;
+ buildMenu(bm, newMenu);
+ --inSecondaryMenu;
+ }
+ for (KrBookmark *bm = parent->children().first(); bm; bm = parent->children().next()) {
+ if (bm->isFolder()) continue;
+ if (bm->isSeparator() ) {
+ menu->insertSeparator();
+ continue;
+ }
+ int itemIndex = bm->plug(menu, -1 /* end of list */);
+ CONNECT_BM(bm);
+
+ int id = bm->itemId( itemIndex );
+ if( !_bookmarkIDTable.find( menu ) )
+ _bookmarkIDTable.insert( menu, new QMap<int, KrBookmark *> );
+ (*_bookmarkIDTable[ menu ])[ id ] = bm;
+ }
+
+ if (!inSecondaryMenu) {
+ krConfig->setGroup( "Private" );
+ bool hasPopularURLs = krConfig->readBoolEntry( "BM Popular URLs", true );
+ bool hasDevices = krConfig->readBoolEntry( "BM Devices", true );
+ bool hasLan = krConfig->readBoolEntry( "BM Lan", true );
+ bool hasVirtualFS = krConfig->readBoolEntry( "BM Virtual FS", true );
+ bool hasJumpback = krConfig->readBoolEntry( "BM Jumpback", true );
+
+ int itemIndex;
+
+ if( hasPopularURLs ) {
+ menu->insertSeparator();
+
+ // add the popular links submenu
+ KPopupMenu *newMenu = new KPopupMenu(menu);
+ itemIndex = menu->insertItem(QIconSet(krLoader->loadIcon("bookmark_folder", KIcon::Small)),
+ i18n("Popular URLs"), newMenu, -1 /* dummy id */, -1 /* end of list */);
+ _specialBookmarkIDs.append( itemIndex );
+ // add the top 15 urls
+ #define MAX 15
+ KURL::List list = krApp->popularUrls->getMostPopularUrls(MAX);
+ KURL::List::Iterator it;
+ for (it = list.begin(); it != list.end(); ++it) {
+ QString name;
+ if ((*it).isLocalFile()) name = (*it).path();
+ else name = (*it).prettyURL();
+ // note: these bookmark are put into the private collection
+ // as to not spam the general collection
+ KrBookmark *bm = KrBookmark::getExistingBookmark(name, _privateCollection);
+ if (!bm)
+ bm = new KrBookmark(name, *it, _privateCollection);
+ bm->plug(newMenu);
+ CONNECT_BM(bm);
+ }
+
+ newMenu->insertSeparator();
+ krPopularUrls->plug(newMenu);
+ newMenu->installEventFilter(this);
+ }
+
+ // do we need to add special bookmarks?
+ if (SPECIAL_BOOKMARKS) {
+ if( hasDevices || hasLan || hasVirtualFS || hasJumpback )
+ menu->insertSeparator();
+
+ KrBookmark *bm;
+
+ // note: special bookmarks are not kept inside the _bookmarks list and added ad-hoc
+ if( hasDevices ) {
+ bm = KrBookmark::devices(_collection);
+ itemIndex = bm->plug(menu);
+ _specialBookmarkIDs.append( bm->itemId( itemIndex ) );
+ CONNECT_BM(bm);
+ }
+
+ if( hasLan ) {
+ bm = KrBookmark::lan(_collection);
+ itemIndex = bm->plug(menu);
+ _specialBookmarkIDs.append( bm->itemId( itemIndex ) );
+ CONNECT_BM(bm);
+ }
+
+ if( hasVirtualFS ) {
+ bm = KrBookmark::virt(_collection);
+ itemIndex = bm->plug(menu);
+ _specialBookmarkIDs.append( bm->itemId( itemIndex ) );
+ CONNECT_BM(bm);
+ }
+
+ if( hasJumpback ) {
+ // add the jump-back button
+ itemIndex = krJumpBack->plug(menu);
+ _specialBookmarkIDs.append( krJumpBack->itemId( itemIndex ) );
+ menu->insertSeparator();
+ itemIndex = krSetJumpBack->plug(menu);
+ _specialBookmarkIDs.append( krSetJumpBack->itemId( itemIndex ) );
+ }
+ }
+
+ if( !hasJumpback )
+ menu->insertSeparator();
+
+ itemIndex = menu->insertItem(krLoader->loadIcon("bookmark_add", KIcon::Small),
+ i18n("Bookmark Current"), BookmarkCurrent);
+ _specialBookmarkIDs.append( itemIndex );
+ itemIndex = menu->insertItem(krLoader->loadIcon("bookmark", KIcon::Small),
+ i18n("Manage Bookmarks"), ManageBookmarks);
+ _specialBookmarkIDs.append( itemIndex );
+
+ // make sure the menu is connected to us
+ disconnect(menu, SIGNAL(activated(int)), 0, 0);
+ connect(menu, SIGNAL(activated(int)), this, SLOT(menuOperation(int)));
+ }
+
+ menu->installEventFilter(this);
+}
+
+void KrBookmarkHandler::clearBookmarks(KrBookmark *root) {
+ KrBookmark *bm = root->children().first();
+ while (bm) {
+ if (bm->isFolder())
+ clearBookmarks(bm);
+ else {
+ bm->unplugAll();
+ delete bm;
+ }
+
+ bm = root->children().next();
+ }
+ root->children().clear();
+}
+
+void KrBookmarkHandler::bookmarksChanged(const QString&, const QString&) {
+ importFromFile();
+}
+
+bool KrBookmarkHandler::eventFilter( QObject *obj, QEvent *ev ) {
+ if (ev->type() == QEvent::MouseButtonRelease) {
+ switch (static_cast<QMouseEvent*>(ev)->button()) {
+ case RightButton:
+ _middleClick = false;
+ if( obj->inherits( "QPopupMenu" ) ) {
+ int id = static_cast<QPopupMenu*>(obj)->idAt( static_cast<QMouseEvent*>(ev)->pos() );
+
+ if( obj == _mainBookmarkPopup && _specialBookmarkIDs.contains( id ) ) {
+ rightClickOnSpecialBookmark();
+ return true;
+ }
+
+ if( _bookmarkIDTable.find( obj ) ) {
+ QMap<int, KrBookmark*> * table = _bookmarkIDTable[ obj ];
+ if( table && table->count( id ) ) {
+ KrBookmark *bm = (*table)[ id ];
+ rightClicked( static_cast<QPopupMenu*>(obj), id, bm );
+ return true;
+ }
+ }
+ }
+ case LeftButton:
+ _middleClick = false;
+ break;
+ case MidButton:
+ _middleClick = true;
+ break;
+ default:
+ break;
+ }
+ }
+ return QObject::eventFilter(obj, ev);
+}
+
+#define POPULAR_URLS_ID 100100
+#define DEVICES_ID 100101
+#define LAN_ID 100103
+#define VIRTUAL_FS_ID 100102
+#define JUMP_BACK_ID 100104
+
+void KrBookmarkHandler::rightClickOnSpecialBookmark() {
+ krConfig->setGroup( "Private" );
+ bool hasPopularURLs = krConfig->readBoolEntry( "BM Popular URLs", true );
+ bool hasDevices = krConfig->readBoolEntry( "BM Devices", true );
+ bool hasLan = krConfig->readBoolEntry( "BM Lan", true );
+ bool hasVirtualFS = krConfig->readBoolEntry( "BM Virtual FS", true );
+ bool hasJumpback = krConfig->readBoolEntry( "BM Jumpback", true );
+
+ QPopupMenu menu( _mainBookmarkPopup );
+ menu.setCaption( i18n( "Enable special bookmarks" ) );
+ menu.setCheckable( true );
+
+ menu.insertItem( i18n( "Popular URLs" ), POPULAR_URLS_ID );
+ menu.setItemChecked( POPULAR_URLS_ID, hasPopularURLs );
+ menu.insertItem( i18n( "Devices" ), DEVICES_ID );
+ menu.setItemChecked( DEVICES_ID, hasDevices );
+ menu.insertItem( i18n( "Local Network" ), LAN_ID );
+ menu.setItemChecked( LAN_ID, hasLan );
+ menu.insertItem( i18n( "Virtual Filesystem" ), VIRTUAL_FS_ID );
+ menu.setItemChecked( VIRTUAL_FS_ID, hasVirtualFS );
+ menu.insertItem( i18n( "Jump back" ), JUMP_BACK_ID );
+ menu.setItemChecked( JUMP_BACK_ID, hasJumpback );
+
+ connect( _mainBookmarkPopup, SIGNAL( highlighted( int ) ), &menu, SLOT( close() ) );
+ connect( _mainBookmarkPopup, SIGNAL( activated( int ) ), &menu, SLOT( close() ) );
+
+ int result = menu.exec( QCursor::pos() );
+ bool doCloseMain = true;
+
+ krConfig->setGroup( "Private" );
+
+ switch( result ) {
+ case POPULAR_URLS_ID:
+ krConfig->writeEntry( "BM Popular URLs", !hasPopularURLs );
+ break;
+ case DEVICES_ID:
+ krConfig->writeEntry( "BM Devices", !hasDevices );
+ break;
+ case LAN_ID:
+ krConfig->writeEntry( "BM Lan", !hasLan );
+ break;
+ case VIRTUAL_FS_ID:
+ krConfig->writeEntry( "BM Virtual FS", !hasVirtualFS );
+ break;
+ case JUMP_BACK_ID:
+ krConfig->writeEntry( "BM Jumpback", !hasJumpback );
+ break;
+ default:
+ doCloseMain = false;
+ break;
+ }
+
+ menu.close();
+
+ if( doCloseMain && _mainBookmarkPopup )
+ _mainBookmarkPopup->close();
+}
+
+#define OPEN_ID 100200
+#define OPEN_NEW_TAB_ID 100201
+#define DELETE_ID 100202
+
+void KrBookmarkHandler::rightClicked( QPopupMenu *menu, int /*id*/, KrBookmark * bm ) {
+ QPopupMenu popup( _mainBookmarkPopup );
+
+ popup.insertItem( krLoader->loadIcon( "fileopen", KIcon::Panel ), i18n( "Open" ), OPEN_ID );
+ popup.insertItem( krLoader->loadIcon( "tab_new", KIcon::Panel ), i18n( "Open in a new tab" ), OPEN_NEW_TAB_ID );
+ popup.insertSeparator();
+ popup.insertItem( krLoader->loadIcon( "editdelete", KIcon::Panel ), i18n( "Delete" ), DELETE_ID );
+
+ connect( menu, SIGNAL( highlighted( int ) ), &popup, SLOT( close() ) );
+ connect( menu, SIGNAL( activated( int ) ), &popup, SLOT( close() ) );
+
+ int result = popup.exec( QCursor::pos() );
+
+ popup.close();
+ if( _mainBookmarkPopup && result >= OPEN_ID && result <= DELETE_ID ) {
+ _mainBookmarkPopup->close();
+ }
+
+ switch( result ) {
+ case OPEN_ID:
+ SLOTS->refresh( bm->url() );
+ break;
+ case OPEN_NEW_TAB_ID:
+ SLOTS->newTab( bm->url() );
+ break;
+ case DELETE_ID:
+ deleteBookmark( bm );
+ break;
+ }
+}
+
+// used to monitor middle clicks. if mid is found, then the
+// bookmark is opened in a new tab. ugly, but easier than overloading
+// KAction and KActionCollection.
+void KrBookmarkHandler::slotActivated(const KURL& url) {
+ if (_middleClick)
+ SLOTS->newTab(url);
+ else SLOTS->refresh(url);
+}
+
+
+#include "krbookmarkhandler.moc"
diff --git a/krusader/BookMan/krbookmarkhandler.h b/krusader/BookMan/krbookmarkhandler.h
new file mode 100644
index 0000000..c6bd9d9
--- /dev/null
+++ b/krusader/BookMan/krbookmarkhandler.h
@@ -0,0 +1,63 @@
+#ifndef KRBOOKMARK_HANDLER_H
+#define KRBOOKMARK_HANDLER_H
+
+#include "krbookmark.h"
+#include <qobject.h>
+#include <qguardedptr.h>
+#include <kpopupmenu.h>
+#include <kurl.h>
+#include <qptrdict.h>
+#include <qvaluelist.h>
+#include <qdom.h>
+#include <qmap.h>
+
+class KActionCollection;
+class KBookmarkManager;
+
+class KrBookmarkHandler: public QObject {
+ Q_OBJECT
+ friend class KrAddBookmarkDlg;
+ enum Actions { BookmarkCurrent=0, ManageBookmarks };
+public:
+ KrBookmarkHandler();
+ ~KrBookmarkHandler();
+ void populate(KPopupMenu *menu);
+ void addBookmark(KrBookmark *bm, KrBookmark *parent = 0);
+ void bookmarkCurrent(KURL url);
+
+protected:
+ void deleteBookmark(KrBookmark *bm);
+ void importFromFile();
+ bool importFromFileBookmark(QDomElement &e, KrBookmark *parent, QString path, QString *errorMsg);
+ bool importFromFileFolder(QDomNode &first, KrBookmark *parent, QString path, QString *errorMsg);
+ void exportToFile();
+ void exportToFileFolder(QDomDocument &doc, QDomElement &parent, KrBookmark *folder);
+ void exportToFileBookmark(QDomDocument &doc, QDomElement &where, KrBookmark *bm);
+ void clearBookmarks(KrBookmark *root);
+ void buildMenu(KrBookmark *parent, KPopupMenu *menu);
+
+ bool eventFilter( QObject *obj, QEvent *ev );
+
+ void rightClicked( QPopupMenu *menu, int id, KrBookmark *bm );
+ void rightClickOnSpecialBookmark();
+
+ void removeReferences( KrBookmark *root, KrBookmark *bmToRemove );
+
+protected slots:
+ void menuOperation(int id);
+ void bookmarksChanged(const QString&, const QString&);
+ void slotActivated(const KURL& url);
+
+private:
+ KActionCollection *_collection, *_privateCollection;
+ KrBookmark *_root;
+ // the whole KBookmarkManager is an ugly hack. use it until we have our own
+ KBookmarkManager *manager;
+ bool _middleClick; // if true, the user clicked the middle button to open the bookmark
+
+ QGuardedPtr<KPopupMenu> _mainBookmarkPopup; // main bookmark popup menu
+ QValueList<int> _specialBookmarkIDs; // the ID list of the special bookmarks
+ QPtrDict<QMap<int,KrBookmark*> > _bookmarkIDTable; // the IDs of the bookmarks
+};
+
+#endif // KRBOOKMARK_HANDLER_H
diff --git a/krusader/Dialogs/Makefile.am b/krusader/Dialogs/Makefile.am
new file mode 100644
index 0000000..83cc13d
--- /dev/null
+++ b/krusader/Dialogs/Makefile.am
@@ -0,0 +1,22 @@
+noinst_LIBRARIES = libDialogs.a
+
+INCLUDES = $(all_includes)
+
+libDialogs_a_METASOURCES = AUTO
+
+libDialogs_a_SOURCES = \
+ krsqueezedtextlabel.cpp \
+ krprogress.cpp \
+ packgui.cpp \
+ packguibase.cpp \
+ newftpgui.cpp \
+ krspwidgets.cpp \
+ krspecialwidgets.cpp \
+ krpleasewait.cpp \
+ krmaskchoice.cpp \
+ krdialogs.cpp \
+ kurllistrequester.cpp \
+ popularurls.cpp \
+ checksumdlg.cpp \
+ percentalsplitter.cpp \
+ krkeydialog.cpp
diff --git a/krusader/Dialogs/checksumdlg.cpp b/krusader/Dialogs/checksumdlg.cpp
new file mode 100644
index 0000000..c79a66e
--- /dev/null
+++ b/krusader/Dialogs/checksumdlg.cpp
@@ -0,0 +1,603 @@
+#include "checksumdlg.h"
+#include "../krusader.h"
+#include <klocale.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <klineedit.h>
+#include <klistview.h>
+#include <qpixmap.h>
+#include <kcursor.h>
+#include <kmessagebox.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <kfiledialog.h>
+#include <qframe.h>
+#include <kiconloader.h>
+#include <kcombobox.h>
+#include <qfileinfo.h>
+#include <kurlrequester.h>
+#include "../krservices.h"
+#include <qptrlist.h>
+#include <qmap.h>
+#include <ktempfile.h>
+#include <kstandarddirs.h>
+
+class CS_Tool; // forward
+typedef void PREPARE_PROC_FUNC(KProcess& proc, CS_Tool *self, const QStringList& files,
+ const QString checksumFile, bool recursive, const QString& stdoutFileName,
+ const QString& stderrFileName, const QString& type=QString::null);
+typedef QStringList GET_FAILED_FUNC(const QStringList& stdOut, const QStringList& stdErr);
+
+class CS_Tool {
+public:
+ enum Type {
+ MD5=0, SHA1, SHA256, TIGER, WHIRLPOOL, SFV, CRC,
+ SHA224, SHA384, SHA512,
+ NumOfTypes
+ };
+
+ Type type;
+ QString binary;
+ bool recursive;
+ bool standardFormat;
+ PREPARE_PROC_FUNC *create, *verify;
+ GET_FAILED_FUNC *failed;
+};
+
+class CS_ToolByType {
+public:
+ QPtrList<CS_Tool> tools, r_tools; // normal and recursive tools
+};
+
+// handles md5sum and sha1sum
+void sumCreateFunc(KProcess& proc, CS_Tool *self, const QStringList& files,
+ const QString, bool recursive, const QString& stdoutFileName,
+ const QString& stderrFileName, const QString&) {
+ proc.setUseShell(true, "/bin/bash");
+ proc << KrServices::fullPathName( self->binary );
+ Q_ASSERT(!recursive);
+ proc << files << "1>" << stdoutFileName << "2>" << stderrFileName;
+}
+
+void sumVerifyFunc(KProcess& proc, CS_Tool *self, const QStringList& /* files */,
+ const QString checksumFile, bool recursive, const QString& stdoutFileName,
+ const QString& stderrFileName, const QString& /* type */) {
+ proc.setUseShell(true, "/bin/bash");
+ proc << KrServices::fullPathName( self->binary );
+ Q_ASSERT(!recursive);
+ proc << "-c" << checksumFile << "1>" << stdoutFileName << "2>" << stderrFileName;
+}
+
+QStringList sumFailedFunc(const QStringList& stdOut, const QStringList& stdErr) {
+ // md5sum and sha1sum print "...: FAILED" for failed files and display
+ // the number of failures to stderr. so if stderr is empty, we'll assume all is ok
+ QStringList result;
+ if (stdErr.size()==0) return result;
+ result += stdErr;
+ // grep for the ":FAILED" substring
+ const QString tmp = QString(": FAILED").local8Bit();
+ for (uint i=0; i<stdOut.size();++i) {
+ if (stdOut[i].find(tmp) != -1)
+ result += stdOut[i];
+ }
+
+ return result;
+}
+
+// handles *deep binaries
+void deepCreateFunc(KProcess& proc, CS_Tool *self, const QStringList& files,
+ const QString, bool recursive, const QString& stdoutFileName,
+ const QString& stderrFileName, const QString&) {
+ proc.setUseShell(true, "/bin/bash");
+ proc << KrServices::fullPathName( self->binary );
+ if (recursive) proc << "-r";
+ proc << "-l" << files << "1>" << stdoutFileName << "2>" << stderrFileName;
+}
+
+void deepVerifyFunc(KProcess& proc, CS_Tool *self, const QStringList& files,
+ const QString checksumFile, bool recursive, const QString& stdoutFileName,
+ const QString& stderrFileName, const QString&) {
+ proc.setUseShell(true, "/bin/bash");
+ proc << KrServices::fullPathName( self->binary );
+ if (recursive) proc << "-r";
+ proc << "-x" << checksumFile << files << "1>" << stdoutFileName << "2>" << stderrFileName;
+}
+
+QStringList deepFailedFunc(const QStringList& stdOut, const QStringList&/* stdErr */) {
+ // *deep dumps (via -x) all failed hashes to stdout
+ return stdOut;
+}
+
+// handles cfv binary
+void cfvCreateFunc(KProcess& proc, CS_Tool *self, const QStringList& files,
+ const QString, bool recursive, const QString& stdoutFileName,
+ const QString& stderrFileName, const QString& type) {
+ proc.setUseShell(true, "/bin/bash");
+ proc << KrServices::fullPathName( self->binary ) << "-C" << "-VV";
+ if (recursive) proc << "-rr";
+ proc << "-t" << type << "-f-" << "-U" << files << "1>" << stdoutFileName << "2>" << stderrFileName;
+}
+
+void cfvVerifyFunc(KProcess& proc, CS_Tool *self, const QStringList& /* files */,
+ const QString checksumFile, bool recursive, const QString& stdoutFileName,
+ const QString& stderrFileName, const QString&type) {
+ proc.setUseShell(true, "/bin/bash");
+ proc << KrServices::fullPathName( self->binary ) << "-M";
+ if (recursive) proc << "-rr";
+ proc << "-U" << "-VV" << "-t" << type << "-f" << checksumFile << "1>" << stdoutFileName << "2>" << stderrFileName;// << files;
+}
+
+QStringList cfvFailedFunc(const QStringList& /* stdOut */, const QStringList& stdErr) {
+ // cfv dumps all failed hashes to stderr
+ return stdErr;
+}
+
+// important: this table should be ordered like so that all md5 tools should be
+// one after another, and then all sha1 and so on and so forth. they tools must be grouped,
+// since the code in getTools() counts on it!
+CS_Tool cs_tools[] = {
+ // type binary recursive stdFmt create_func verify_func failed_func
+ {CS_Tool::MD5, "md5sum", false, true, sumCreateFunc, sumVerifyFunc, sumFailedFunc},
+ {CS_Tool::MD5, "md5deep", true, true, deepCreateFunc, deepVerifyFunc, deepFailedFunc},
+ {CS_Tool::MD5, "cfv", true, true, cfvCreateFunc, cfvVerifyFunc, cfvFailedFunc},
+ {CS_Tool::SHA1, "sha1sum", false, true, sumCreateFunc, sumVerifyFunc, sumFailedFunc},
+ {CS_Tool::SHA1, "sha1deep", true, true, deepCreateFunc, deepVerifyFunc, deepFailedFunc},
+ {CS_Tool::SHA1, "cfv", true, true, cfvCreateFunc, cfvVerifyFunc, cfvFailedFunc},
+ {CS_Tool::SHA224, "sha224sum", false, true, sumCreateFunc, sumVerifyFunc, sumFailedFunc},
+ {CS_Tool::SHA256, "sha256sum", false, true, sumCreateFunc, sumVerifyFunc, sumFailedFunc},
+ {CS_Tool::SHA256, "sha256deep", true, true, deepCreateFunc, deepVerifyFunc, deepFailedFunc},
+ {CS_Tool::SHA384, "sha384sum", false, true, sumCreateFunc, sumVerifyFunc, sumFailedFunc},
+ {CS_Tool::SHA512, "sha512sum", false, true, sumCreateFunc, sumVerifyFunc, sumFailedFunc},
+ {CS_Tool::TIGER, "tigerdeep", true, true, deepCreateFunc, deepVerifyFunc, deepFailedFunc},
+ {CS_Tool::WHIRLPOOL, "whirlpooldeep", true, true, deepCreateFunc, deepVerifyFunc, deepFailedFunc},
+ {CS_Tool::SFV, "cfv", true, false, cfvCreateFunc, cfvVerifyFunc, cfvFailedFunc},
+ {CS_Tool::CRC, "cfv", true, false, cfvCreateFunc, cfvVerifyFunc, cfvFailedFunc},
+};
+
+QMap<QString, CS_Tool::Type> cs_textToType;
+QMap<CS_Tool::Type, QString> cs_typeToText;
+
+void initChecksumModule() {
+ // prepare the dictionaries - pity it has to be manually
+ cs_textToType["md5"]=CS_Tool::MD5;
+ cs_textToType["sha1"]=CS_Tool::SHA1;
+ cs_textToType["sha256"]=CS_Tool::SHA256;
+ cs_textToType["sha224"]=CS_Tool::SHA224;
+ cs_textToType["sha384"]=CS_Tool::SHA384;
+ cs_textToType["sha512"]=CS_Tool::SHA512;
+ cs_textToType["tiger"]=CS_Tool::TIGER;
+ cs_textToType["whirlpool"]=CS_Tool::WHIRLPOOL;
+ cs_textToType["sfv"]=CS_Tool::SFV;
+ cs_textToType["crc"]=CS_Tool::CRC;
+
+ cs_typeToText[CS_Tool::MD5]="md5";
+ cs_typeToText[CS_Tool::SHA1]="sha1";
+ cs_typeToText[CS_Tool::SHA256]="sha256";
+ cs_typeToText[CS_Tool::SHA224]="sha224";
+ cs_typeToText[CS_Tool::SHA384]="sha384";
+ cs_typeToText[CS_Tool::SHA512]="sha512";
+ cs_typeToText[CS_Tool::TIGER]="tiger";
+ cs_typeToText[CS_Tool::WHIRLPOOL]="whirlpool";
+ cs_typeToText[CS_Tool::SFV]="sfv";
+ cs_typeToText[CS_Tool::CRC]="crc";
+
+ // build the checksumFilter (for usage in KRQuery)
+ QMap<QString, CS_Tool::Type>::Iterator it;
+ for (it=cs_textToType.begin(); it!=cs_textToType.end(); ++it)
+ MatchChecksumDlg::checksumTypesFilter += ("*."+it.key()+" ");
+}
+
+// --------------------------------------------------
+
+// returns a list of tools which can work with recursive or non-recursive mode and are installed
+// note: only 1 tool from each type is suggested
+static QPtrList<CS_Tool> getTools(bool folders) {
+ QPtrList<CS_Tool> result;
+ uint i;
+ for (i=0; i < sizeof(cs_tools)/sizeof(CS_Tool); ++i) {
+ if (result.last() && result.last()->type == cs_tools[i].type) continue; // 1 from each type please
+ if (folders && !cs_tools[i].recursive) continue;
+ if (KrServices::cmdExist(cs_tools[i].binary))
+ result.append(&cs_tools[i]);
+ }
+
+ return result;
+}
+
+// ------------- CreateChecksumDlg
+
+CreateChecksumDlg::CreateChecksumDlg(const QStringList& files, bool containFolders, const QString& path):
+ KDialogBase(Plain, i18n("Create Checksum"), Ok | Cancel, Ok, krApp) {
+
+ QPtrList<CS_Tool> tools = getTools(containFolders);
+
+ if (tools.count() == 0) { // nothing was suggested?!
+ QString error = i18n("<qt>Can't calculate checksum since no supported tool was found. "
+ "Please check the <b>Dependencies</b> page in Krusader's settings.</qt>");
+ if (containFolders)
+ error += i18n("<qt><b>Note</b>: you've selected directories, and probably have no recursive checksum tool installed."
+ " Krusader currently supports <i>md5deep, sha1deep, sha256deep, tigerdeep and cfv</i></qt>");
+ KMessageBox::error(0, error);
+ return;
+ }
+
+ QGridLayout *layout = new QGridLayout( plainPage(), 1, 1,
+ KDialogBase::marginHint(), KDialogBase::spacingHint());
+
+ int row=0;
+
+ // title (icon+text)
+ QHBoxLayout *hlayout = new QHBoxLayout(layout, KDialogBase::spacingHint());
+ QLabel *p = new QLabel(plainPage());
+ p->setPixmap(krLoader->loadIcon("binary", KIcon::Desktop, 32));
+ hlayout->addWidget(p);
+ QLabel *l1 = new QLabel(i18n("About to calculate checksum for the following files") +
+ (containFolders ? i18n(" and folders:") : ":"), plainPage());
+ hlayout->addWidget(l1);
+ layout->addMultiCellLayout(hlayout, row, row, 0, 1, Qt::AlignLeft);
+ ++row;
+
+ // file list
+ KListBox *lb = new KListBox(plainPage());
+ lb->insertStringList(files);
+ layout->addMultiCellWidget(lb, row, row, 0, 1);
+ ++row;
+
+ // checksum method
+ QHBoxLayout *hlayout2 = new QHBoxLayout(layout, KDialogBase::spacingHint());
+ QLabel *l2 = new QLabel(i18n("Select the checksum method:"), plainPage());
+ hlayout2->addWidget(l2);
+ KComboBox *method = new KComboBox(plainPage());
+ // -- fill the combo with available methods
+ uint i;
+ for ( i=0; i<tools.count(); ++i )
+ method->insertItem( cs_typeToText[tools.at(i)->type], i);
+ method->setFocus();
+ hlayout2->addWidget(method);
+ layout->addMultiCellLayout(hlayout2, row, row, 0, 1, Qt::AlignLeft);
+ ++row;
+
+ if (exec() != Accepted) return;
+ // else implied: run the process
+ tmpOut = new KTempFile(locateLocal("tmp", "krusader"), ".stdout" );
+ tmpErr = new KTempFile(locateLocal("tmp", "krusader"), ".stderr" );
+ KProcess proc;
+ CS_Tool *mytool = tools.at(method->currentItem());
+ mytool->create(proc, mytool, KrServices::quote(files), QString::null, containFolders,
+ tmpOut->name(), tmpErr->name(), method->currentText());
+
+ krApp->startWaiting(i18n("Calculating checksums ..."), 0, true);
+ QApplication::setOverrideCursor( KCursor::waitCursor() );
+ bool r = proc.start(KProcess::NotifyOnExit, KProcess::AllOutput);
+ if (r) while ( proc.isRunning() ) {
+ usleep( 500 );
+ qApp->processEvents();
+ if (krApp->wasWaitingCancelled()) { // user cancelled
+ proc.kill();
+ QApplication::restoreOverrideCursor();
+ return;
+ }
+ };
+ krApp->stopWait();
+ QApplication::restoreOverrideCursor();
+ if (!r || !proc.normalExit()) {
+ KMessageBox::error(0, i18n("<qt>There was an error while running <b>%1</b>.</qt>").arg(mytool->binary));
+ return;
+ }
+
+ // suggest a filename
+ QString suggestedFilename = path + '/';
+ if (files.count() > 1) suggestedFilename += ("checksum." + cs_typeToText[mytool->type]);
+ else suggestedFilename += (files[0] + '.' + cs_typeToText[mytool->type]);
+ // send both stdout and stderr
+ QStringList stdOut, stdErr;
+ if (!KrServices::fileToStringList(tmpOut->textStream(), stdOut) ||
+ !KrServices::fileToStringList(tmpErr->textStream(), stdErr)) {
+ KMessageBox::error(krApp, i18n("Error reading stdout or stderr"));
+ return;
+ }
+
+ ChecksumResultsDlg dlg( stdOut, stdErr, suggestedFilename, mytool->binary, cs_typeToText[mytool->type], mytool->standardFormat);
+ tmpOut->unlink(); delete tmpOut;
+ tmpErr->unlink(); delete tmpErr;
+}
+
+// ------------- MatchChecksumDlg
+
+QString MatchChecksumDlg::checksumTypesFilter;
+
+MatchChecksumDlg::MatchChecksumDlg(const QStringList& files, bool containFolders,
+ const QString& path, const QString& checksumFile):
+ KDialogBase(Plain, i18n("Verify Checksum"), Ok | Cancel, Ok, krApp) {
+
+ QPtrList<CS_Tool> tools = getTools(containFolders);
+
+ if (tools.count() == 0) { // nothing was suggested?!
+ QString error = i18n("<qt>Can't verify checksum since no supported tool was found. "
+ "Please check the <b>Dependencies</b> page in Krusader's settings.</qt>");
+ if (containFolders)
+ error += i18n("<qt><b>Note</b>: you've selected directories, and probably have no recursive checksum tool installed."
+ " Krusader currently supports <i>md5deep, sha1deep, sha256deep, tigerdeep and cfv</i></qt>");
+ KMessageBox::error(0, error);
+ return;
+ }
+
+ QGridLayout *layout = new QGridLayout( plainPage(), 1, 1,
+ KDialogBase::marginHint(), KDialogBase::spacingHint());
+
+ int row=0;
+
+ // title (icon+text)
+ QHBoxLayout *hlayout = new QHBoxLayout(layout, KDialogBase::spacingHint());
+ QLabel *p = new QLabel(plainPage());
+ p->setPixmap(krLoader->loadIcon("binary", KIcon::Desktop, 32));
+ hlayout->addWidget(p);
+ QLabel *l1 = new QLabel(i18n("About to verify checksum for the following files") +
+ (containFolders ? i18n(" and folders:") : ":"), plainPage());
+ hlayout->addWidget(l1);
+ layout->addMultiCellLayout(hlayout, row, row, 0, 1, Qt::AlignLeft);
+ ++row;
+
+ // file list
+ KListBox *lb = new KListBox(plainPage());
+ lb->insertStringList(files);
+ layout->addMultiCellWidget(lb, row, row, 0, 1);
+ ++row;
+
+ // checksum file
+ QHBoxLayout *hlayout2 = new QHBoxLayout(layout, KDialogBase::spacingHint());
+ QLabel *l2 = new QLabel(i18n("Checksum file:"), plainPage());
+ hlayout2->addWidget(l2);
+ KURLRequester *checksumFileReq = new KURLRequester( plainPage() );
+ if (!checksumFile.isEmpty())
+ checksumFileReq->setURL(checksumFile);
+ checksumFileReq->fileDialog()->setURL(path);
+ checksumFileReq->setFocus();
+ hlayout2->addWidget(checksumFileReq);
+ layout->addMultiCellLayout(hlayout2, row, row, 0, 1, Qt::AlignLeft);
+
+ if (exec() != Accepted) return;
+ QString file = checksumFileReq->url();
+ QString extension;
+ if (!verifyChecksumFile(file, extension)) {
+ KMessageBox::error(0, i18n("<qt>Error reading checksum file <i>%1</i>.<br />Please specify a valid checksum file.</qt>").arg(file));
+ return;
+ }
+
+ // do we have a tool for that extension?
+ uint i;
+ CS_Tool *mytool = 0;
+ for ( i=0; i < tools.count(); ++i )
+ if (cs_typeToText[tools.at(i)->type] == extension.lower()) {
+ mytool = tools.at(i);
+ break;
+ }
+ if (!mytool) {
+ KMessageBox::error(0, i18n("<qt>Krusader can't find a checksum tool that handles %1 on your system. Please check the <b>Dependencies</b> page in Krusader's settings.</qt>").arg(extension));
+ return;
+ }
+
+ // else implied: run the process
+ tmpOut = new KTempFile(locateLocal("tmp", "krusader"), ".stdout" );
+ tmpErr = new KTempFile(locateLocal("tmp", "krusader"), ".stderr" );
+ KProcess proc;
+ mytool->verify(proc, mytool, KrServices::quote(files), KrServices::quote(file), containFolders, tmpOut->name(), tmpErr->name(), extension);
+ krApp->startWaiting(i18n("Verifying checksums ..."), 0, true);
+ QApplication::setOverrideCursor( KCursor::waitCursor() );
+ bool r = proc.start(KProcess::NotifyOnExit, KProcess::AllOutput);
+ if (r) while ( proc.isRunning() ) {
+ usleep( 500 );
+ qApp->processEvents();
+ if (krApp->wasWaitingCancelled()) { // user cancelled
+ proc.kill();
+ QApplication::restoreOverrideCursor();
+ return;
+ }
+ };
+ if (!r || !proc.normalExit()) {
+ KMessageBox::error(0, i18n("<qt>There was an error while running <b>%1</b>.</qt>").arg(mytool->binary));
+ return;
+ }
+ QApplication::restoreOverrideCursor();
+ krApp->stopWait();
+ // send both stdout and stderr
+ QStringList stdOut,stdErr;
+ if (!KrServices::fileToStringList(tmpOut->textStream(), stdOut) ||
+ !KrServices::fileToStringList(tmpErr->textStream(), stdErr)) {
+ KMessageBox::error(krApp, i18n("Error reading stdout or stderr"));
+ return;
+ }
+ VerifyResultDlg dlg(mytool->failed(stdOut, stdErr));
+ tmpOut->unlink(); delete tmpOut;
+ tmpErr->unlink(); delete tmpErr;
+}
+
+bool MatchChecksumDlg::verifyChecksumFile(QString path, QString& extension) {
+ QFileInfo f(path);
+ if (!f.exists() || f.isDir()) return false;
+ // find the extension
+ extension = path.mid(path.findRev(".")+1);
+
+ // TODO: do we know the extension? if not, ask the user for one
+
+
+ return true;
+}
+
+// ------------- VerifyResultDlg
+VerifyResultDlg::VerifyResultDlg(const QStringList& failed):
+ KDialogBase(Plain, i18n("Verify Checksum"), Close, Close, krApp) {
+ QGridLayout *layout = new QGridLayout( plainPage(), 1, 1,
+ KDialogBase::marginHint(), KDialogBase::spacingHint());
+
+ bool errors = failed.size()>0;
+ int row = 0;
+
+ // create the icon and title
+ QHBoxLayout *hlayout = new QHBoxLayout(layout, KDialogBase::spacingHint());
+ QLabel p(plainPage());
+ p.setPixmap(krLoader->loadIcon(errors ? "messagebox_critical" : "messagebox_info", KIcon::Desktop, 32));
+ hlayout->addWidget(&p);
+
+ QLabel *l1 = new QLabel((errors ? i18n("Errors were detected while verifying the checksums") :
+ i18n("Checksums were verified successfully")), plainPage());
+ hlayout->addWidget(l1);
+ layout->addMultiCellLayout(hlayout,row,row,0,1, Qt::AlignLeft);
+ ++row;
+
+ if (errors) {
+ QLabel *l3 = new QLabel(i18n("The following files have failed:"), plainPage());
+ layout->addMultiCellWidget(l3, row, row, 0, 1);
+ ++row;
+ KListBox *lb2 = new KListBox(plainPage());
+ lb2->insertStringList(failed);
+ layout->addMultiCellWidget(lb2, row, row, 0, 1);
+ ++row;
+ }
+
+ exec();
+}
+
+// ------------- ChecksumResultsDlg
+
+ChecksumResultsDlg::ChecksumResultsDlg(const QStringList& stdOut, const QStringList& stdErr,
+ const QString& suggestedFilename, const QString& binary, const QString& /* type */, bool standardFormat):
+ KDialogBase(Plain, i18n("Create Checksum"), Ok | Cancel, Ok, krApp), _binary(binary) {
+ QGridLayout *layout = new QGridLayout( plainPage(), 1, 1,
+ KDialogBase::marginHint(), KDialogBase::spacingHint());
+
+ // md5 tools display errors into stderr, so we'll use that to determine the result of the job
+ bool errors = stdErr.size()>0;
+ bool successes = stdOut.size()>0;
+ int row = 0;
+
+ // create the icon and title
+ QHBoxLayout *hlayout = new QHBoxLayout(layout, KDialogBase::spacingHint());
+ QLabel p(plainPage());
+ p.setPixmap(krLoader->loadIcon(errors ? "messagebox_critical" : "messagebox_info", KIcon::Desktop, 32));
+ hlayout->addWidget(&p);
+
+ QLabel *l1 = new QLabel((errors ? i18n("Errors were detected while creating the checksums") :
+ i18n("Checksums were created successfully")), plainPage());
+ hlayout->addWidget(l1);
+ layout->addMultiCellLayout(hlayout,row,row,0,1, Qt::AlignLeft);
+ ++row;
+
+ if (successes) {
+ if (errors) {
+ QLabel *l2 = new QLabel(i18n("Here are the calculated checksums:"), plainPage());
+ layout->addMultiCellWidget(l2, row, row, 0, 1);
+ ++row;
+ }
+ KListView *lv = new KListView(plainPage());
+ if(standardFormat){
+ lv->addColumn(i18n("Hash"));
+ lv->addColumn(i18n("File"));
+ lv->setAllColumnsShowFocus(true);
+ } else {
+ lv->addColumn(i18n("File and hash"));
+ }
+ for ( QStringList::ConstIterator it = stdOut.begin(); it != stdOut.end(); ++it ) {
+ QString line = (*it);
+ if(standardFormat) {
+ int space = line.find(' ');
+ new KListViewItem(lv, line.left(space), line.mid(space+2));
+ } else {
+ new KListViewItem(lv, line);
+ }
+ }
+ layout->addMultiCellWidget(lv, row, row, 0, 1);
+ ++row;
+ }
+
+ if (errors) {
+ QFrame *line1 = new QFrame( plainPage() );
+ line1->setGeometry( QRect( 60, 210, 501, 20 ) );
+ line1->setFrameShape( QFrame::HLine );
+ line1->setFrameShadow( QFrame::Sunken );
+ layout->addMultiCellWidget(line1, row, row, 0, 1);
+ ++row;
+
+ QLabel *l3 = new QLabel(i18n("Here are the errors received:"), plainPage());
+ layout->addMultiCellWidget(l3, row, row, 0, 1);
+ ++row;
+ KListBox *lb = new KListBox(plainPage());
+ lb->insertStringList(stdErr);
+ layout->addMultiCellWidget(lb, row, row, 0, 1);
+ ++row;
+ }
+
+ // save checksum to disk, if any hashes are found
+ KURLRequester *checksumFile=0;
+ QCheckBox *saveFileCb=0;
+ if (successes) {
+ QHBoxLayout *hlayout2 = new QHBoxLayout(layout, KDialogBase::spacingHint());
+ saveFileCb = new QCheckBox(i18n("Save checksum to file:"), plainPage());
+ saveFileCb->setChecked(true);
+ hlayout2->addWidget(saveFileCb);
+
+ checksumFile = new KURLRequester( suggestedFilename, plainPage() );
+ hlayout2->addWidget(checksumFile, Qt::AlignLeft);
+ layout->addMultiCellLayout(hlayout2, row, row,0,1, Qt::AlignLeft);
+ ++row;
+ connect(saveFileCb, SIGNAL(toggled(bool)), checksumFile, SLOT(setEnabled(bool)));
+ checksumFile->setFocus();
+ }
+
+ QCheckBox *onePerFile=0;
+ if (stdOut.size() > 1 && standardFormat) {
+ onePerFile = new QCheckBox(i18n("Checksum file for each source file"), plainPage());
+ onePerFile->setChecked(false);
+ // clicking this, disables the 'save as' part
+ connect(onePerFile, SIGNAL(toggled(bool)), saveFileCb, SLOT(toggle()));
+ connect(onePerFile, SIGNAL(toggled(bool)), saveFileCb, SLOT(setDisabled(bool)));
+ connect(onePerFile, SIGNAL(toggled(bool)), checksumFile, SLOT(setDisabled(bool)));
+ layout->addMultiCellWidget(onePerFile, row, row,0,1, Qt::AlignLeft);
+ ++row;
+ }
+
+ if (exec() == Accepted && successes) {
+ if (stdOut.size()>1 && standardFormat && onePerFile->isChecked()) {
+ savePerFile(stdOut, suggestedFilename.mid(suggestedFilename.findRev('.')));
+ } else if (saveFileCb->isEnabled() && saveFileCb->isChecked() && !checksumFile->url().simplifyWhiteSpace().isEmpty()) {
+ saveChecksum(stdOut, checksumFile->url());
+ }
+ }
+}
+
+bool ChecksumResultsDlg::saveChecksum(const QStringList& data, QString filename) {
+ if (QFile::exists(filename) &&
+ KMessageBox::warningContinueCancel(this,
+ i18n("File %1 already exists.\nAre you sure you want to overwrite it?").arg(filename),
+ i18n("Warning"), i18n("Overwrite")) != KMessageBox::Continue) {
+ // find a better name to save to
+ filename = KFileDialog::getSaveFileName(QString::null, "*", 0, i18n("Select a file to save to"));
+ if (filename.simplifyWhiteSpace().isEmpty()) return false;
+ }
+ QFile file(filename);
+ if (!file.open(IO_WriteOnly)) {
+ KMessageBox::detailedError(0, i18n("Error saving file %1").arg(filename),
+ file.errorString());
+ return false;
+ }
+ QTextStream stream(&file);
+ for ( QStringList::ConstIterator it = data.constBegin(); it != data.constEnd(); ++it)
+ stream << *it << "\n";
+ file.close();
+ return true;
+}
+
+void ChecksumResultsDlg::savePerFile(const QStringList& data, const QString& type) {
+ krApp->startWaiting(i18n("Saving checksum files..."), 0);
+ for ( QStringList::ConstIterator it = data.begin(); it != data.end(); ++it ) {
+ QString line = (*it);
+ QString filename = line.mid(line.find(' ')+2)+type;
+ if (!saveChecksum(*it, filename)) {
+ KMessageBox::error(0, i18n("Errors occured while saving multiple checksums. Stopping"));
+ krApp->stopWait();
+ return;
+ }
+ }
+ krApp->stopWait();
+}
diff --git a/krusader/Dialogs/checksumdlg.h b/krusader/Dialogs/checksumdlg.h
new file mode 100644
index 0000000..41bb1ad
--- /dev/null
+++ b/krusader/Dialogs/checksumdlg.h
@@ -0,0 +1,54 @@
+#ifndef CHECKSUMDLG_H
+#define CHECKSUMDLG_H
+
+#include <kdialogbase.h>
+#include <qvaluelist.h>
+
+class KTempFile;
+extern void initChecksumModule();
+
+class CreateChecksumDlg: public KDialogBase {
+public:
+ CreateChecksumDlg(const QStringList& files, bool containFolders, const QString& path);
+
+private:
+ KTempFile *tmpOut, *tmpErr;
+};
+
+
+class MatchChecksumDlg: public KDialogBase {
+public:
+ MatchChecksumDlg(const QStringList& files, bool containFolders,
+ const QString& path, const QString& checksumFile=QString::null);
+
+ static QString checksumTypesFilter;
+
+protected:
+ bool verifyChecksumFile(QString path, QString& extension);
+
+private:
+ KTempFile *tmpOut, *tmpErr;
+};
+
+
+class ChecksumResultsDlg: public KDialogBase {
+public:
+ ChecksumResultsDlg(const QStringList& stdOut, const QStringList& stdErr,
+ const QString& suggestedFilename, const QString& binary, const QString& type,
+ bool standardFormat);
+
+protected:
+ bool saveChecksum(const QStringList& data, QString filename);
+ void savePerFile(const QStringList& data, const QString& type);
+
+private:
+ QString _binary;
+};
+
+
+class VerifyResultDlg: public KDialogBase {
+public:
+ VerifyResultDlg(const QStringList& failed);
+};
+
+#endif // CHECKSUMDLG_H
diff --git a/krusader/Dialogs/krdialogs.cpp b/krusader/Dialogs/krdialogs.cpp
new file mode 100644
index 0000000..cbcc294
--- /dev/null
+++ b/krusader/Dialogs/krdialogs.cpp
@@ -0,0 +1,255 @@
+/***************************************************************************
+ krdialogs.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+// Krusader includes
+#include "krdialogs.h"
+// QT includes
+#include <qmessagebox.h>
+#include <qwidget.h>
+#include <qapplication.h>
+#include <qfontmetrics.h>
+#include <qtooltip.h>
+// KDE includes
+#include <klocale.h>
+#include <kurlcompletion.h>
+#include <kapplication.h>
+#include <kstandarddirs.h>
+#include <klineedit.h>
+#include <kurlrequester.h>
+#include <kstandarddirs.h>
+#include <kdeversion.h>
+#include <qcheckbox.h>
+#include <krecentdocument.h>
+#include <qhbox.h>
+// Krusader includes
+#include "../krusader.h"
+#include "../resources.h"
+#include "../VFS/vfs.h"
+#include "../defaults.h"
+#include <qdir.h>
+
+KURL KChooseDir::getDir(QString text,const KURL& url, const KURL& cwd) {
+ KURLRequesterDlg *dlg = new KURLRequesterDlg( vfs::pathOrURL( url, 1 ),text,krApp,"");
+ dlg->urlRequester()->completionObject()->setDir(cwd.url());
+ KURL u;
+ if (dlg->exec() == QDialog::Accepted) {
+ u = vfs::fromPathOrURL(dlg->urlRequester()->completionObject()->replacedPath(
+ dlg->urlRequester()->lineEdit()->text()));
+ if (u.isRelativeURL(u.url())) {
+ KURL temp = u;
+ u = cwd;
+ u.addPath(temp.url());
+ u.cleanPath();
+ if( u.protocol() == "zip" || u.protocol() == "krarc" || u.protocol() == "tar" || u.protocol() == "iso" ) {
+ if( QDir( u.path() ).exists() )
+ u.setProtocol( "file" );
+ }
+ }
+ }
+ delete dlg;
+ return u;
+}
+
+KURL KChooseDir::getDir(QString text,const KURL& url, const KURL& cwd, bool &preserveAttrs ) {
+ KURLRequesterDlgForCopy *dlg = new KURLRequesterDlgForCopy( vfs::pathOrURL( url, 1 ),text, preserveAttrs, krApp,"" );
+ dlg->urlRequester()->completionObject()->setDir(cwd.url());
+ KURL u;
+ if (dlg->exec() == QDialog::Accepted) {
+ u = vfs::fromPathOrURL(dlg->urlRequester()->completionObject()->replacedPath(
+ dlg->urlRequester()->lineEdit()->text()));
+ if (u.isRelativeURL(u.url())) {
+ KURL temp = u;
+ u = cwd;
+ u.addPath(temp.url());
+ u.cleanPath();
+ if( u.protocol() == "zip" || u.protocol() == "krarc" || u.protocol() == "tar" || u.protocol() == "iso" ) {
+ if( QDir( u.path() ).exists() )
+ u.setProtocol( "file" );
+ }
+ }
+ }
+ preserveAttrs = dlg->preserveAttrs();
+ delete dlg;
+ return u;
+}
+
+KURL KChooseDir::getDir(QString text,const KURL& url, const KURL& cwd, bool &preserveAttrs, KURL &baseURL ) {
+ KURLRequesterDlgForCopy *dlg = new KURLRequesterDlgForCopy( vfs::pathOrURL( url, 1 ),text, preserveAttrs, krApp,"", true, baseURL );
+ dlg->urlRequester()->completionObject()->setDir(cwd.url());
+ KURL u;
+ if (dlg->exec() == QDialog::Accepted) {
+ u = vfs::fromPathOrURL(dlg->urlRequester()->completionObject()->replacedPath(
+ dlg->urlRequester()->lineEdit()->text()));
+ if (u.isRelativeURL(u.url())) {
+ KURL temp = u;
+ u = cwd;
+ u.addPath(temp.url());
+ u.cleanPath();
+ if( u.protocol() == "zip" || u.protocol() == "krarc" || u.protocol() == "tar" || u.protocol() == "iso" ) {
+ if( QDir( u.path() ).exists() )
+ u.setProtocol( "file" );
+ }
+ }
+
+ if( dlg->copyDirStructure() ) {
+ baseURL = dlg->baseURL();
+ } else {
+ baseURL = KURL();
+ }
+ }
+ preserveAttrs = dlg->preserveAttrs();
+ delete dlg;
+ return u;
+}
+
+KURLRequesterDlgForCopy::KURLRequesterDlgForCopy( const QString& urlName, const QString& _text, bool presAttrs, QWidget *parent,
+ const char *name, bool modal, KURL baseURL )
+ : KDialogBase( Plain, QString::null, Ok|Cancel|User1, Ok, parent, name, modal, true, KStdGuiItem::clear() ),
+ baseUrlCombo( 0 ), copyDirStructureCB( 0 ) {
+
+ QVBoxLayout * topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() );
+
+ QLabel * label = new QLabel( _text, plainPage() );
+ topLayout->addWidget( label );
+
+ urlRequester_ = new KURLRequester( urlName, plainPage(), "urlRequester" );
+ urlRequester_->setMinimumWidth( urlRequester_->sizeHint().width() * 3 );
+ topLayout->addWidget( urlRequester_ );
+ preserveAttrsCB = new QCheckBox(i18n("Preserve attributes (only for local targets)"), plainPage());
+ preserveAttrsCB->setChecked( presAttrs );
+ topLayout->addWidget( preserveAttrsCB );
+ if( !baseURL.isEmpty() ) {
+ QFrame *line = new QFrame( plainPage(), "sepLine" );
+ line->setFrameStyle( QFrame::HLine | QFrame::Sunken );
+ topLayout->addWidget( line );
+ copyDirStructureCB = new QCheckBox(i18n("Keep virtual directory structure"), plainPage());
+ connect( copyDirStructureCB, SIGNAL( toggled( bool ) ), this, SLOT( slotDirStructCBChanged() ) );
+ copyDirStructureCB->setChecked( false );
+ topLayout->addWidget( copyDirStructureCB );
+ QHBox * hbox = new QHBox( plainPage(), "copyDirStructure" );
+ new QLabel( i18n("Base URL:"), hbox, "baseURLLabel" );
+
+ baseUrlCombo = new QComboBox( hbox, "baseUrlRequester" );
+ baseUrlCombo->setMinimumWidth( baseUrlCombo->sizeHint().width() * 3 );
+ baseUrlCombo->setEnabled( copyDirStructureCB->isChecked() );
+ KURL temp = baseURL, tempOld;
+ do {
+ QString baseURLText = vfs::pathOrURL( temp );
+ baseUrlCombo->insertItem( baseURLText );
+ tempOld = temp;
+ temp = temp.upURL();
+ }while( !tempOld.equals( temp, true ) );
+ baseUrlCombo->setCurrentItem( 0 );
+
+ topLayout->addWidget( hbox );
+ }
+ urlRequester_->setFocus();
+ connect( urlRequester_->lineEdit(), SIGNAL(textChanged(const QString&)),
+ SLOT(slotTextChanged(const QString&)) );
+ bool state = !urlName.isEmpty();
+ enableButtonOK( state );
+ enableButton( KDialogBase::User1, state );
+ connect( this, SIGNAL( user1Clicked() ), SLOT( slotClear() ) );
+}
+
+KURLRequesterDlgForCopy::KURLRequesterDlgForCopy() {
+}
+
+bool KURLRequesterDlgForCopy::preserveAttrs() {
+ return preserveAttrsCB->isChecked();
+}
+
+bool KURLRequesterDlgForCopy::copyDirStructure() {
+ if( copyDirStructureCB == 0 )
+ return false;
+ return copyDirStructureCB->isChecked();
+}
+
+void KURLRequesterDlgForCopy::slotTextChanged(const QString & text) {
+ bool state = !text.stripWhiteSpace().isEmpty();
+ enableButtonOK( state );
+ enableButton( KDialogBase::User1, state );
+}
+
+void KURLRequesterDlgForCopy::slotClear() {
+ urlRequester_->clear();
+}
+
+void KURLRequesterDlgForCopy::slotDirStructCBChanged() {
+ baseUrlCombo->setEnabled( copyDirStructureCB->isChecked() );
+}
+
+KURL KURLRequesterDlgForCopy::selectedURL() const {
+ if ( result() == QDialog::Accepted ) {
+ KURL url = KURL::fromPathOrURL( urlRequester_->url() );
+ if( url.isValid() )
+ KRecentDocument::add(url);
+ return url;
+ }
+ else
+ return KURL();
+}
+
+KURLRequester * KURLRequesterDlgForCopy::urlRequester() {
+ return urlRequester_;
+}
+
+KURL KURLRequesterDlgForCopy::baseURL() const {
+ if( baseUrlCombo == 0 )
+ return KURL();
+ return vfs::fromPathOrURL( baseUrlCombo->currentText() );
+}
+
+KRGetDate::KRGetDate(QDate date, QWidget *parent, const char *name) : KDialog(parent, name,true,WStyle_DialogBorder) {
+ dateWidget = new KDatePicker(this, date);
+ dateWidget->resize(dateWidget->sizeHint());
+ setMinimumSize(dateWidget->sizeHint());
+ setMaximumSize(dateWidget->sizeHint());
+ resize(minimumSize());
+ connect(dateWidget, SIGNAL(dateSelected(QDate)), this, SLOT(setDate(QDate)));
+ connect(dateWidget, SIGNAL(dateEntered(QDate)), this, SLOT(setDate(QDate)));
+
+ // keep the original date - incase ESC is pressed
+ originalDate = date;
+}
+
+QDate KRGetDate::getDate() {
+ if (exec() == QDialog::Rejected) chosenDate.setYMD(0,0,0);
+ hide();
+ return chosenDate;
+}
+
+void KRGetDate::setDate(QDate date) {
+ chosenDate = date;
+ accept();
+}
+
+#include "krdialogs.moc"
diff --git a/krusader/Dialogs/krdialogs.h b/krusader/Dialogs/krdialogs.h
new file mode 100644
index 0000000..9f85131
--- /dev/null
+++ b/krusader/Dialogs/krdialogs.h
@@ -0,0 +1,115 @@
+/***************************************************************************
+ krdialogs.h
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KCHOSEDIR_H
+#define KCHOSEDIR_H
+
+// KDE includes
+#include <kdialog.h>
+#include <kanimwidget.h>
+#include <kurlrequesterdlg.h>
+#include <kdatepicker.h>
+#include <kdialogbase.h>
+// QT includes
+#include <qlineedit.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qdatetime.h>
+#include <qpixmap.h>
+#include <qprogressdialog.h>
+#include <qsemimodal.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+
+/** \class KChooseDir
+ * Used for asking the user for a folder.
+ * example:
+ * \code
+ * KURL u = KChooseDir::getDir("target folder", "/suggested/path", ACTIVE_PANEL->virtualPath());
+ * if (u.isEmpty()) {
+ * // user canceled (either by pressing cancel, or esc
+ * } else {
+ * // do you thing here: you've got a safe url to use
+ * }
+ * \endcode
+ */
+class KChooseDir {
+public:
+ /**
+ * \param text - description of the info requested from the user
+ * \param url - a suggested url to appear in the box as a default choice
+ * \param cwd - a path which is the current working directory (usually ACTIVE_PANEL->virtualPath()).
+ * this is used for completion of partial urls
+ */
+ static KURL getDir(QString text,const KURL& url, const KURL& cwd);
+ static KURL getDir(QString text,const KURL& url, const KURL& cwd, bool & preserveAttrs );
+ static KURL getDir(QString text,const KURL& url, const KURL& cwd, bool & preserveAttrs, KURL &baseURL );
+};
+
+class KURLRequesterDlgForCopy : public KDialogBase {
+ Q_OBJECT
+public:
+ KURLRequesterDlgForCopy( const QString& url, const QString& text, bool presAttrs,
+ QWidget *parent, const char *name, bool modal=true, KURL baseURL = KURL() );
+ KURLRequesterDlgForCopy();
+
+ KURL selectedURL() const;
+ KURL baseURL() const;
+ bool preserveAttrs();
+ bool copyDirStructure();
+
+ KURLRequester *urlRequester();
+private slots:
+ void slotClear();
+ void slotTextChanged(const QString &);
+ void slotDirStructCBChanged();
+private:
+ KURLRequester *urlRequester_;
+ QComboBox *baseUrlCombo;
+ QCheckBox *preserveAttrsCB;
+ QCheckBox *copyDirStructureCB;
+};
+
+class KRGetDate : public KDialog {
+ Q_OBJECT
+public:
+ KRGetDate(QDate date=QDate::currentDate(), QWidget *parent = 0, const char *name = 0);
+ QDate getDate();
+
+private slots:
+ void setDate(QDate);
+
+private:
+ KDatePicker *dateWidget;
+ QDate chosenDate, originalDate;
+};
+
+#endif
diff --git a/krusader/Dialogs/krkeydialog.cpp b/krusader/Dialogs/krkeydialog.cpp
new file mode 100644
index 0000000..70e6273
--- /dev/null
+++ b/krusader/Dialogs/krkeydialog.cpp
@@ -0,0 +1,157 @@
+//
+// C++ Implementation: krkeydialog
+//
+// Description:
+//
+//
+// Author: Jonas Bähr <http://jonas-baehr.de/>, (C) 2006
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#include "krkeydialog.h"
+
+#include <qlayout.h>
+#include <qwhatsthis.h>
+#include <klocale.h>
+#include <kpushbutton.h>
+#include <kmessagebox.h>
+#include <kfiledialog.h>
+#include <kglobal.h>
+#include <kstandarddirs.h>
+#include <kconfig.h>
+#include <kactionshortcutlist.h>
+#include <kdebug.h>
+
+#include "../krusader.h"
+
+//This is the filter in the KFileDialog of Import/Export:
+static const char* FILE_FILTER = I18N_NOOP("*.keymap|Krusader keymaps\n*|all files");
+
+
+KrKeyDialog::KrKeyDialog( QWidget * parent ) : KKeyDialog( false /* allow letter shortcuts */, parent ) {
+ insert( krApp->actionCollection() );
+
+ // HACK This fetches the layout of the buttonbox from KDialogBase, although it is not accessable with KDialogBase's API
+ // None the less it's quite save to use since this implementation hasn't changed since KDE-3.3 (I haven't looked at earlier
+ // versions since we don't support them) and now all work is done in KDE-4.
+ QWidget* buttonBox = static_cast<QWidget*>( actionButton(KDialogBase::Ok)->parent() );
+ QBoxLayout* buttonBoxLayout = static_cast<QBoxLayout*>( buttonBox->layout() );
+
+ KPushButton* importButton = new KPushButton( i18n("Import shortcuts"), buttonBox );
+ QWhatsThis::add( importButton, i18n( "Load a keybinding profile, e.g., total_commander.keymap" ) );
+ buttonBoxLayout->insertWidget( 1, importButton ); // the defaults-button should stay on position 0
+ connect( importButton, SIGNAL( clicked() ), SLOT( slotImportShortcuts() ) );
+
+ KPushButton* exportButton = new KPushButton( i18n("Export shortcuts"), buttonBox );
+ QWhatsThis::add( exportButton, i18n( "Save current keybindings in a keymap file." ) );
+ buttonBoxLayout->insertWidget( 2, exportButton );
+ connect( exportButton, SIGNAL( clicked() ), SLOT( slotExportShortcuts() ) );
+
+ // Also quite HACK 'isch but unfortunately KKeyDialog don't giveus access to this widget
+ _chooser = static_cast<KKeyChooser*>( mainWidget() );
+
+ configure( true /* SaveSettings */ ); // this runs the dialog
+}
+
+KrKeyDialog::~KrKeyDialog() {
+}
+
+void KrKeyDialog::slotImportShortcuts() {
+ // find $KDEDIR/share/apps/krusader
+ QString basedir = KGlobal::dirs()->findResourceDir("appdata", "total_commander.keymap");
+ // let the user select a file to load
+ QString filename = KFileDialog::getOpenFileName(basedir, i18n(FILE_FILTER), 0, i18n("Select a keymap file"));
+ if ( filename.isEmpty() )
+ return;
+
+ KConfig conf( filename, true /*read only*/, false /*no KDEGlobal*/ );
+ if ( ! conf.hasGroup("Shortcuts") ) {
+ int answer = KMessageBox::warningContinueCancel( this, //parent
+ i18n("This file does not seem to be a valid keymap.\n"
+ "It may be a keymap using a legacy format. The import can't be undone!"), //text
+ i18n("Try to import legacy format?"), //caption
+ i18n("Import anyway"), //Label for the continue-button
+ "Confirm Import Legacy Shortcuts" //dontAskAgainName (for the config-file)
+ );
+ if ( answer == KMessageBox::Continue )
+ importLegacyShortcuts( filename );
+ else
+ return;
+ }
+ else
+ _chooser->syncToConfig( "Shortcuts", &conf, false /* don't delete shortcuts of actions not listed in conf */ );
+}
+
+void KrKeyDialog::importLegacyShortcuts( const QString& file ) {
+/*
+ * This is basicaly Shie's code. It's copied from Kronfigurator's loog&feel page and adapted to the dialog
+ */
+ // check if there's an info file with the keymap
+ QFile info(file+".info");
+ if (info.open(IO_ReadOnly)) {
+ QTextStream stream(&info);
+ QStringList infoText = QStringList::split("\n", stream.read());
+ if (KMessageBox::questionYesNoList(krApp, i18n("The following information was attached to the keymap. Do you really want to import this keymap?"), infoText)!=KMessageBox::Yes)
+ return;
+ }
+
+ // ok, import away
+ QFile f(file);
+ if (!f.open(IO_ReadOnly)) {
+ krOut << "Error opening " << file << endl;
+ return;
+ }
+ char *actionName;
+ QDataStream stream(&f);
+ int key;
+ KAction *action;
+ while (!stream.atEnd()) {
+ stream >> actionName >> key;
+ action = krApp->actionCollection()->action(actionName);
+ if (action) {
+ action->setShortcut(key);
+// krOut << "set shortcut for " << actionName <<endl;
+ } else {
+ krOut << "unknown action " << actionName << endl;
+ }
+ }
+ f.close();
+
+ KMessageBox::information( this, // parent
+ i18n("Please restart this dialog in order to see the changes"), // text
+ i18n("Legacy import completed") // caption
+ );
+}
+
+void KrKeyDialog::slotExportShortcuts() {
+ QString filename = KFileDialog::getSaveFileName( QString::null, i18n(FILE_FILTER), 0, i18n("Select a keymap file") );
+ if ( filename.isEmpty() )
+ return;
+ QFile f( filename );
+ if ( f.exists() &&
+ KMessageBox::warningContinueCancel( this,
+ i18n("<qt>File <b>%1</b> already exists. Do you really want to overwrite it?</qt>").arg(filename),
+ i18n("Warning"), i18n("Overwrite") )
+ != KMessageBox::Continue)
+ return;
+ if ( f.open( IO_WriteOnly ) )
+ // This is the only way to detect if the file is writable since we don't get feetback from KConfig's sync
+ // Additionaly this prevents merging if the file already contains some shortcuts
+ f.close();
+ else {
+ KMessageBox::error( this, i18n("<qt>Can't open <b>%1</b> for writing!</qt>").arg(filename) );
+ return;
+ }
+
+ KConfig conf( filename, false /*read only*/, false /*no KDEGlobal*/ );
+
+ // unfortunately we can't use this function since it only writes the actions which are different from default.
+ //krApp->actionCollection()->writeShortcutSettings( "Shortcuts", &conf );
+ KActionShortcutList list( krApp->actionCollection() );
+ list.writeSettings( "Shortcuts", &conf, true /* write all actions */ );
+ // That does KActionShortcutList::writeSettings for us
+ //conf.sync(); // write back all changes
+}
+
+#include "krkeydialog.moc"
diff --git a/krusader/Dialogs/krkeydialog.h b/krusader/Dialogs/krkeydialog.h
new file mode 100644
index 0000000..3731ce5
--- /dev/null
+++ b/krusader/Dialogs/krkeydialog.h
@@ -0,0 +1,37 @@
+//
+// C++ Interface: krkeydialog
+//
+// Description:
+//
+//
+// Author: Jonas Bähr <http://jonas-baehr.de/>, (C) 2006
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef KRKEYDIALOG_H
+#define KRKEYDIALOG_H
+
+#include <kkeydialog.h>
+
+/**
+ * @short KDE's KKeyDialog extended by the ability to export/import shortcuts
+ * @author Jonas Bähr
+ */
+class KrKeyDialog : protected KKeyDialog
+{
+Q_OBJECT
+public:
+ KrKeyDialog( QWidget* parent = 0 );
+ ~KrKeyDialog();
+
+private slots:
+ void slotImportShortcuts();
+ void slotExportShortcuts();
+
+private:
+ void importLegacyShortcuts( const QString& file );
+ KKeyChooser* _chooser;
+};
+
+#endif
diff --git a/krusader/Dialogs/krmaskchoice.cpp b/krusader/Dialogs/krmaskchoice.cpp
new file mode 100644
index 0000000..6e55518
--- /dev/null
+++ b/krusader/Dialogs/krmaskchoice.cpp
@@ -0,0 +1,179 @@
+/***************************************************************************
+ krmaskchoice.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#include "krmaskchoice.h"
+
+#include <qcombobox.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlistbox.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qvariant.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qmessagebox.h>
+#include <klocale.h>
+#include <qlineedit.h>
+
+/*
+ * Constructs a KRMaskChoice which is a child of 'parent', with the
+ * name 'name' and widget flags set to 'f'
+ *
+ * The dialog will by default be modeless, unless you set 'modal' to
+ * TRUE to construct a modal dialog.
+ */
+KRMaskChoice::KRMaskChoice( QWidget* parent, const char* name, bool modal, WFlags fl )
+ : QDialog( parent, name, modal, fl )
+{
+ if ( !name )
+ setName( "KRMaskChoice" );
+ resize( 401, 314 );
+ setCaption( i18n( "Choose Files" ) );
+ setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)5 ) );
+
+ selection = new QComboBox( FALSE, this, "selection" );
+ int height = QFontMetrics( selection->font() ).height();
+ height = height + 5*(height > 14) + 6;
+ selection->setGeometry( QRect( 12, 48, 377, height) );
+ selection->setEditable( TRUE );
+ selection->setInsertionPolicy( QComboBox::AtTop );
+ selection->setAutoCompletion( TRUE );
+
+ QWidget* Layout7 = new QWidget( this, "Layout7" );
+ Layout7->setGeometry( QRect( 10, 10, 380, 30 ) );
+ hbox = new QHBoxLayout( Layout7 );
+ hbox->setSpacing( 6 );
+ hbox->setMargin( 0 );
+
+ PixmapLabel1 = new QLabel( Layout7, "PixmapLabel1" );
+ PixmapLabel1->setScaledContents( TRUE );
+ PixmapLabel1->setMaximumSize( QSize( 31, 31 ) );
+ // now, add space for the pixmap
+ hbox->addWidget( PixmapLabel1 );
+
+ label = new QLabel( Layout7, "label" );
+ label->setText( i18n( "Select the following files:" ) );
+ hbox->addWidget( label );
+
+ GroupBox1 = new QGroupBox( this, "GroupBox1" );
+ GroupBox1->setGeometry( QRect( 11, 77, 379, 190 ) );
+ GroupBox1->setTitle( i18n( "Predefined Selections" ) );
+
+ QWidget* Layout6 = new QWidget( GroupBox1, "Layout6" );
+ Layout6->setGeometry( QRect( 10, 20, 360, 160 ) );
+ hbox_2 = new QHBoxLayout( Layout6 );
+ hbox_2->setSpacing( 6 );
+ hbox_2->setMargin( 0 );
+
+ preSelections = new QListBox( Layout6, "preSelections" );
+ preSelections->setVScrollBarMode( QListBox::AlwaysOn );
+ QWhatsThis::add( preSelections, i18n( "A predefined selection is a file-mask which you use often.\nSome examples are: \"*.c, *.h\", \"*.c, *.o\", etc.\nYou can add these masks to the list by typing them and pressing the Add button.\nDelete removes a predefined selection and Clear removes all of them.\nNotice that the line in which you edit the mask has it's own history, you can scroll it, if needed." ) );
+ hbox_2->addWidget( preSelections );
+
+ vbox = new QVBoxLayout;
+ vbox->setSpacing( 6 );
+ vbox->setMargin( 0 );
+
+ PushButton7 = new QPushButton( Layout6, "PushButton7" );
+ PushButton7->setText( i18n( "Add" ) );
+ QToolTip::add( PushButton7, i18n( "Adds the selection in the line-edit to the list" ) );
+ vbox->addWidget( PushButton7 );
+
+ PushButton7_2 = new QPushButton( Layout6, "PushButton7_2" );
+ PushButton7_2->setText( i18n( "Delete" ) );
+ QToolTip::add( PushButton7_2, i18n( "Delete the marked selection from the list" ) );
+ vbox->addWidget( PushButton7_2 );
+
+ PushButton7_3 = new QPushButton( Layout6, "PushButton7_3" );
+ PushButton7_3->setText( i18n( "Clear" ) );
+ QToolTip::add( PushButton7_3, i18n( "Clears the entire list of selections" ) );
+ vbox->addWidget( PushButton7_3 );
+ QSpacerItem* spacer = new QSpacerItem( 20, 54, QSizePolicy::Fixed, QSizePolicy::Expanding );
+ vbox->addItem( spacer );
+ hbox_2->addLayout( vbox );
+
+ QWidget* Layout18 = new QWidget( this, "Layout18" );
+ Layout18->setGeometry( QRect( 10, 280, 379, 30 ) );
+ hbox_3 = new QHBoxLayout( Layout18 );
+ hbox_3->setSpacing( 6 );
+ hbox_3->setMargin( 0 );
+ QSpacerItem* spacer_2 = new QSpacerItem( 205, 20, QSizePolicy::Expanding, QSizePolicy::Fixed );
+ hbox_3->addItem( spacer_2 );
+
+ PushButton3 = new QPushButton( Layout18, "PushButton3" );
+ PushButton3->setText( i18n( "OK" ) );
+ hbox_3->addWidget( PushButton3 );
+
+ PushButton3_2 = new QPushButton( Layout18, "PushButton3_2" );
+ PushButton3_2->setText( i18n( "Cancel" ) );
+ hbox_3->addWidget( PushButton3_2 );
+
+ // signals and slots connections
+ connect( PushButton3_2, SIGNAL( clicked() ), this, SLOT( reject() ) );
+ connect( PushButton3, SIGNAL( clicked() ), this, SLOT( accept() ) );
+ connect( PushButton7, SIGNAL( clicked() ), this, SLOT( addSelection() ) );
+ connect( PushButton7_2, SIGNAL( clicked() ), this, SLOT( deleteSelection() ) );
+ connect( PushButton7_3, SIGNAL( clicked() ), this, SLOT( clearSelections() ) );
+ connect( selection, SIGNAL( activated(const QString&) ), selection, SLOT( setEditText(const QString &) ) );
+ connect( selection->lineEdit(), SIGNAL( returnPressed() ), this, SLOT( accept() ));
+ connect( preSelections, SIGNAL( doubleClicked(QListBoxItem*) ), this, SLOT( acceptFromList(QListBoxItem *) ) );
+ connect( preSelections, SIGNAL( highlighted(const QString&) ), selection, SLOT( setEditText(const QString &) ) );
+ connect( preSelections, SIGNAL( returnPressed(QListBoxItem*) ), this, SLOT( acceptFromList(QListBoxItem *) ) );
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+KRMaskChoice::~KRMaskChoice()
+{
+ // no need to delete child widgets, Qt does it all for us
+}
+
+void KRMaskChoice::addSelection()
+{
+ qWarning( "KRMaskChoice::addSelection(): Not implemented yet!" );
+}
+
+void KRMaskChoice::clearSelections()
+{
+ qWarning( "KRMaskChoice::clearSelections(): Not implemented yet!" );
+}
+
+void KRMaskChoice::deleteSelection()
+{
+ qWarning( "KRMaskChoice::deleteSelection(): Not implemented yet!" );
+}
+
+void KRMaskChoice::acceptFromList(QListBoxItem *)
+{
+ qWarning( "KRMaskChoice::acceptFromList(QListBoxItem *): Not implemented yet!" );
+}
+
+#include "krmaskchoice.moc"
diff --git a/krusader/Dialogs/krmaskchoice.h b/krusader/Dialogs/krmaskchoice.h
new file mode 100644
index 0000000..16be845
--- /dev/null
+++ b/krusader/Dialogs/krmaskchoice.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+ krmaskchoice.h
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef KRMASKCHOICE_H
+#define KRMASKCHOICE_H
+
+#include <qdialog.h>
+class QVBoxLayout;
+class QHBoxLayout;
+class QGridLayout;
+class QComboBox;
+class QGroupBox;
+class QLabel;
+class QListBox;
+class QListBoxItem;
+class QPushButton;
+
+class KRMaskChoice : public QDialog
+{
+ Q_OBJECT
+
+public:
+ KRMaskChoice( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 );
+ ~KRMaskChoice();
+
+ QComboBox* selection;
+ QLabel* PixmapLabel1;
+ QLabel* label;
+ QGroupBox* GroupBox1;
+ QListBox* preSelections;
+ QPushButton* PushButton7;
+ QPushButton* PushButton7_2;
+ QPushButton* PushButton7_3;
+ QPushButton* PushButton3;
+ QPushButton* PushButton3_2;
+
+public slots:
+ virtual void addSelection();
+ virtual void clearSelections();
+ virtual void deleteSelection();
+ virtual void acceptFromList(QListBoxItem *);
+
+protected:
+ QHBoxLayout* hbox;
+ QHBoxLayout* hbox_2;
+ QHBoxLayout* hbox_3;
+ QVBoxLayout* vbox;
+};
+
+#endif // KRMASKCHOICE_H
diff --git a/krusader/Dialogs/krpleasewait.cpp b/krusader/Dialogs/krpleasewait.cpp
new file mode 100644
index 0000000..c61b61a
--- /dev/null
+++ b/krusader/Dialogs/krpleasewait.cpp
@@ -0,0 +1,153 @@
+/***************************************************************************
+ krpleasewait.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "krpleasewait.h"
+#include <qtimer.h>
+#include <qdatetime.h>
+#include <qapplication.h>
+#include <qpushbutton.h>
+#include <unistd.h>
+#include "../krusader.h"
+#include "klocale.h"
+#include <kcursor.h>
+
+KRPleaseWait::KRPleaseWait( QString msg, int count, bool cancel ):
+ QProgressDialog( cancel ? 0 : krApp,0, !cancel) , inc(true) {
+
+ timer = new QTimer(this);
+ setCaption( i18n( "Krusader::Wait" ) );
+
+ setMinimumDuration(500);
+ setAutoClose(false);
+ setAutoReset(false);
+
+ connect( timer,SIGNAL(timeout()), this, SLOT(cycleProgress()));
+
+ QProgressBar* progress = new QProgressBar(count,this);
+ progress->setCenterIndicator(true);
+ setBar(progress);
+
+ QLabel* label = new QLabel(this);
+ setLabel(label);
+
+ QPushButton* btn = new QPushButton(i18n("&Cancel"),this);
+ setCancelButton(btn);
+
+ btn->setEnabled(canClose = cancel);
+ setLabelText(msg);
+
+ show();
+}
+
+void KRPleaseWait::closeEvent ( QCloseEvent * e )
+{
+ if( canClose ) {
+ emit cancelled();
+ e->accept();
+ } else /* if cancel is not allowed, we disable */
+ e->ignore(); /* the window closing [x] also */
+}
+
+void KRPleaseWait::incProgress(int howMuch){
+ setProgress(progress()+howMuch);
+}
+
+void KRPleaseWait::cycleProgress(){
+ if (inc) setProgress(progress()+1);
+ else setProgress(progress()-1);
+ if ( progress() >= 9 ) inc = false;
+ if ( progress() <= 0 ) inc = true;
+}
+
+KRPleaseWaitHandler::KRPleaseWaitHandler() : QObject(), job(), dlg( 0 ) {
+}
+
+void KRPleaseWaitHandler::stopWait(){
+ if( dlg != 0 ) delete dlg;
+ dlg=0;
+ cycleMutex=incMutex=false;
+ // return cursor to normal arrow
+ krApp->setCursor(KCursor::arrowCursor());
+}
+
+
+void KRPleaseWaitHandler::startWaiting( QString msg, int count , bool cancel){
+ if ( dlg == 0 ){
+ dlg = new KRPleaseWait( msg , count, cancel);
+ connect( dlg,SIGNAL(cancelled()),this,SLOT(killJob()) );
+ }
+ incMutex=cycleMutex=_wasCancelled=false;
+ dlg->setProgress(0);
+
+ dlg->setLabelText(msg);
+ if ( count == 0) {
+ dlg->setTotalSteps(10);
+ cycle = true ;
+ cycleProgress();
+ }
+ else {
+ dlg->setTotalSteps(count);
+ cycle = false;
+ }
+}
+
+void KRPleaseWaitHandler::cycleProgress(){
+ if (cycleMutex) return;
+ cycleMutex=true;
+ if (dlg) dlg->cycleProgress();
+ if (cycle) QTimer::singleShot(2000,this,SLOT(cycleProgress()));
+ cycleMutex=false;
+}
+
+void KRPleaseWaitHandler::killJob(){
+ if( !job.isNull() ) job->kill(false);
+ stopWait();
+ _wasCancelled = true;
+}
+
+void KRPleaseWaitHandler::setJob(KIO::Job* j){ job=j; }
+
+void KRPleaseWaitHandler::incProgress(int i){
+ if (incMutex) return;
+ incMutex=true;
+ if(dlg) dlg->incProgress(i);
+ incMutex=false;
+}
+
+void KRPleaseWaitHandler::incProgress( KProcess *, char *buffer, int buflen ) {
+ int howMuch = 0;
+ for ( int i = 0 ; i < buflen; ++i )
+ if ( buffer[ i ] == '\n' )
+ ++howMuch;
+
+ incProgress( howMuch );
+}
+
+#include "krpleasewait.moc"
diff --git a/krusader/Dialogs/krpleasewait.h b/krusader/Dialogs/krpleasewait.h
new file mode 100644
index 0000000..30b19f8
--- /dev/null
+++ b/krusader/Dialogs/krpleasewait.h
@@ -0,0 +1,82 @@
+/***************************************************************************
+ krpleasewait.h
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KRPLEASEWAIT_H
+#define KRPLEASEWAIT_H
+
+#include <qprogressdialog.h>
+#include <qtimer.h>
+#include <qguardedptr.h>
+#include <kio/jobclasses.h>
+
+class KProcess;
+class KRPleaseWait;
+
+class KRPleaseWaitHandler : public QObject {
+ Q_OBJECT
+
+public:
+ KRPleaseWaitHandler();
+
+public slots:
+
+ void startWaiting(QString msg, int count = 0, bool cancel = false);
+ void stopWait();
+ void cycleProgress();
+ void incProgress(int i);
+ void incProgress( KProcess *, char *buffer, int buflen );
+ void killJob();
+ void setJob(KIO::Job* j);
+ bool wasCancelled() const { return _wasCancelled; }
+
+private:
+ QGuardedPtr<KIO::Job> job;
+ KRPleaseWait * dlg;
+ bool cycle, cycleMutex, incMutex, _wasCancelled;
+};
+
+
+class KRPleaseWait : public QProgressDialog {
+ Q_OBJECT
+public:
+ KRPleaseWait( QString msg, int count = 0 ,bool cancel = false );
+
+public slots:
+ void incProgress(int howMuch);
+ void cycleProgress();
+
+protected:
+ bool inc;
+ QTimer* timer;
+ virtual void closeEvent ( QCloseEvent * e );
+ bool canClose;
+};
+
+#endif
diff --git a/krusader/Dialogs/krprogress.cpp b/krusader/Dialogs/krprogress.cpp
new file mode 100644
index 0000000..94f8c8c
--- /dev/null
+++ b/krusader/Dialogs/krprogress.cpp
@@ -0,0 +1,270 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Matej Koss <koss@miesto.sk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qtimer.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qdatetime.h>
+
+#include <kapplication.h>
+#include <kdialog.h>
+#include <kstringhandler.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kpushbutton.h>
+#include <kstdguiitem.h>
+#include <kwin.h>
+
+#include <kio/jobclasses.h>
+
+#include "krprogress.h"
+#include "../krusader.h"
+
+KrProgress::KrProgress( KIO::Job* job )
+ : ProgressBase( krApp ),
+ m_iTotalSize(0), m_iTotalFiles(0), m_iTotalDirs(0),
+ m_iProcessedSize(0), m_iProcessedDirs(0), m_iProcessedFiles(0){
+
+#ifdef Q_WS_X11 //FIXME(E): Remove once all the KWin::foo calls have been ported to QWS
+ // Set a useful icon for this window!
+ KWin::setIcons( winId(),
+ KGlobal::iconLoader()->loadIcon( "filesave", KIcon::NoGroup, 32 ),
+ KGlobal::iconLoader()->loadIcon( "filesave", KIcon::NoGroup, 16 ) );
+#endif
+
+ QVBoxLayout *topLayout = new QVBoxLayout( this, KDialog::marginHint(),
+ KDialog::spacingHint() );
+ topLayout->addStrut( 360 ); // makes dlg at least that wide
+
+ QGridLayout *grid = new QGridLayout( 2, 3 );
+ topLayout->addLayout(grid);
+ grid->addColSpacing(1, KDialog::spacingHint());
+ // filenames or action name
+ grid->addWidget(new QLabel(i18n("Source:"), this), 0, 0);
+
+ sourceLabel = new KSqueezedTextLabel(this);
+ grid->addWidget(sourceLabel, 0, 2);
+
+ destInvite = new QLabel(i18n("Destination:"), this);
+ grid->addWidget(destInvite, 1, 0);
+
+ destLabel = new KSqueezedTextLabel(this);
+ grid->addWidget(destLabel, 1, 2);
+
+ m_pProgressBar = new KProgress(this);
+ topLayout->addWidget( m_pProgressBar );
+
+ // processed info
+ QHBoxLayout *hBox = new QHBoxLayout();
+ topLayout->addLayout(hBox);
+
+ sizeLabel = new QLabel(this);
+ hBox->addWidget(sizeLabel);
+
+ resumeLabel = new QLabel(this);
+ hBox->addWidget(resumeLabel);
+
+ progressLabel = new QLabel( this );
+/* progressLabel->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding,
+ QSizePolicy::Preferred ) );*/
+ progressLabel->setAlignment( QLabel::AlignRight );
+ hBox->addWidget( progressLabel );
+
+ hBox = new QHBoxLayout();
+ topLayout->addLayout(hBox);
+
+ speedLabel = new QLabel(this);
+ hBox->addWidget(speedLabel, 1);
+
+ QFrame *line = new QFrame( this );
+ line->setFrameShape( QFrame::HLine );
+ line->setFrameShadow( QFrame::Sunken );
+ topLayout->addWidget( line );
+
+ hBox = new QHBoxLayout();
+ topLayout->addLayout(hBox);
+
+ hBox->addStretch(1);
+
+ KPushButton *pb = new KPushButton( KStdGuiItem::cancel(), this );
+ connect( pb, SIGNAL( clicked() ), SLOT( slotStop() ) );
+ hBox->addWidget( pb );
+
+ resize( sizeHint() );
+ setMaximumHeight(sizeHint().height());
+
+ setCaption(i18n("Krusader Progress")); // show something better than kio_uiserver
+
+ setJob(job);
+ setOnlyClean(false);
+ setStopOnClose(true);
+ // Connect global progress info signals
+ connect( job, SIGNAL( percent( KIO::Job*, unsigned long ) ),
+ SLOT( slotPercent( KIO::Job*, unsigned long ) ) );
+ connect( job, SIGNAL( infoMessage( KIO::Job*, const QString & ) ),
+ SLOT( slotInfoMessage( KIO::Job*, const QString & ) ) );
+ connect( job, SIGNAL( totalSize( KIO::Job*, KIO::filesize_t ) ),
+ SLOT( slotTotalSize( KIO::Job*, KIO::filesize_t ) ) );
+ connect( job, SIGNAL( processedSize( KIO::Job*, KIO::filesize_t ) ),
+ SLOT( slotProcessedSize( KIO::Job*, KIO::filesize_t ) ) );
+ connect( job, SIGNAL( speed( KIO::Job*, unsigned long ) ),
+ SLOT( slotSpeed( KIO::Job*, unsigned long ) ) );
+
+ // change to modal & move to Krusader's center
+ QPoint center((krApp->width()-width())/2,(krApp->height()-height())/2);
+ center = center+(krApp->pos());
+ reparent(krApp,WType_Modal,center);
+ //setWFlags(WType_Modal);
+ //move((krApp->width()-width())/2,(krApp->height()-height())/2);
+ show();
+}
+
+KrProgress::~KrProgress(){}
+
+void KrProgress::slotTotalSize( KIO::Job*, KIO::filesize_t bytes ){
+ m_iTotalSize = bytes;
+}
+
+
+void KrProgress::slotTotalFiles( KIO::Job*, unsigned long files ){
+ m_iTotalFiles = files;
+ showTotals();
+}
+
+
+void KrProgress::slotTotalDirs( KIO::Job*, unsigned long dirs ){
+ m_iTotalDirs = dirs;
+ showTotals();
+}
+
+void KrProgress::showTotals(){
+ // Show the totals in the progress label, if we still haven't
+ // processed anything. This is useful when the stat'ing phase
+ // of CopyJob takes a long time (e.g. over networks).
+ if ( m_iProcessedFiles == 0 && m_iProcessedDirs == 0 )
+ {
+ QString tmps;
+ if ( m_iTotalDirs > 1 )
+ // that we have a singular to translate looks weired but is only logical
+ tmps = i18n("%n directory", "%n directories", m_iTotalDirs) + " ";
+ tmps += i18n("%n file", "%n files", m_iTotalFiles);
+ progressLabel->setText( tmps );
+ }
+}
+
+void KrProgress::slotPercent( KIO::Job*, unsigned long percent ){
+ QString tmp(i18n( "%1% of %2 ").arg( percent ).arg( KIO::convertSize(m_iTotalSize)));
+ m_pProgressBar->setValue( percent );
+ tmp.append(i18n(" (Reading)"));
+
+ setCaption( tmp );
+}
+
+
+void KrProgress::slotInfoMessage( KIO::Job*, const QString & msg )
+{
+ speedLabel->setText( msg );
+ speedLabel->setAlignment( speedLabel->alignment() & ~Qt::WordBreak );
+}
+
+
+void KrProgress::slotProcessedSize( KIO::Job*, KIO::filesize_t bytes ) {
+ m_iProcessedSize = bytes;
+
+ QString tmp;
+ tmp = i18n( "%1 of %2 complete").arg( KIO::convertSize(bytes) ).arg( KIO::convertSize(m_iTotalSize));
+ sizeLabel->setText( tmp );
+}
+
+
+void KrProgress::slotProcessedDirs( KIO::Job*, unsigned long dirs )
+{
+ m_iProcessedDirs = dirs;
+
+ QString tmps;
+ tmps = i18n("%1 / %n directory", "%1 / %n directories", m_iTotalDirs).arg( m_iProcessedDirs );
+ tmps += " ";
+ tmps += i18n("%1 / %n file", "%1 / %n files", m_iTotalFiles).arg( m_iProcessedFiles );
+ progressLabel->setText( tmps );
+}
+
+
+void KrProgress::slotProcessedFiles( KIO::Job*, unsigned long files )
+{
+ m_iProcessedFiles = files;
+
+ QString tmps;
+ if ( m_iTotalDirs > 1 ) {
+ tmps = i18n("%1 / %n directory", "%1 / %n directories", m_iTotalDirs).arg( m_iProcessedDirs );
+ tmps += " ";
+ }
+ tmps += i18n("%1 / %n file", "%1 / %n files", m_iTotalFiles).arg( m_iProcessedFiles );
+ progressLabel->setText( tmps );
+}
+
+
+void KrProgress::slotSpeed( KIO::Job*, unsigned long bytes_per_second )
+{
+ if ( bytes_per_second == 0 ) {
+ speedLabel->setText( i18n( "Working") );
+ } else {
+#if KDE_IS_VERSION(3,4,0)
+ unsigned int seconds = KIO::calculateRemainingSeconds( m_iTotalSize, m_iProcessedSize, bytes_per_second );
+ QString remaining = KIO::convertSeconds(seconds);
+#else
+ QString remaining = KIO::calculateRemaining( m_iTotalSize, m_iProcessedSize, bytes_per_second ).toString();
+#endif
+ speedLabel->setText( i18n( "%1/s ( %2 remaining )").arg( KIO::convertSize( bytes_per_second )).arg( remaining ) );
+ }
+}
+
+
+void KrProgress::setDestVisible( bool visible )
+{
+ // We can't hide the destInvite/destLabel labels,
+ // because it screws up the QGridLayout.
+ if (visible)
+ {
+ destInvite->setText( i18n("Destination:") );
+ }
+ else
+ {
+ destInvite->setText( QString::null );
+ destLabel->setText( QString::null );
+ }
+}
+
+void KrProgress::virtual_hook( int id, void* data ){
+ ProgressBase::virtual_hook( id, data );
+}
+
+void KrProgress::slotStop(){
+ if ( m_pJob ) {
+ m_pJob->kill(false); // this will call slotFinished
+ m_pJob = 0L;
+ } else {
+ slotFinished( 0 ); // here we call it ourselves
+ }
+
+ emit stopped();
+}
+
+void KrProgress::closeEvent( QCloseEvent* ) { hide(); slotStop(); }
+
+#include "krprogress.moc"
diff --git a/krusader/Dialogs/krprogress.h b/krusader/Dialogs/krprogress.h
new file mode 100644
index 0000000..a8731b1
--- /dev/null
+++ b/krusader/Dialogs/krprogress.h
@@ -0,0 +1,86 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Matej Koss <koss@miesto.sk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/** This file was modified for Krusader by Shie Erlich & Rafi Yanai **/
+
+#ifndef __kr_progress_h__
+#define __kr_progress_h__
+
+#include <qlabel.h>
+
+#include <kio/global.h>
+
+#include <kprogress.h>
+#include <ksqueezedtextlabel.h>
+
+#include <kio/progressbase.h>
+
+#include <qobject.h>
+
+class KrProgress : public KIO::ProgressBase {
+ Q_OBJECT
+public:
+
+ KrProgress(KIO::Job* job);
+ virtual ~KrProgress();
+
+public slots:
+ virtual void slotTotalSize( KIO::Job*, KIO::filesize_t bytes );
+ virtual void slotTotalFiles( KIO::Job*, unsigned long files );
+ virtual void slotTotalDirs( KIO::Job*, unsigned long dirs );
+
+ virtual void slotProcessedSize( KIO::Job*, KIO::filesize_t bytes );
+ virtual void slotProcessedFiles( KIO::Job*, unsigned long files );
+ virtual void slotProcessedDirs( KIO::Job*, unsigned long dirs );
+
+ virtual void slotSpeed( KIO::Job*, unsigned long bytes_per_second );
+ virtual void slotPercent( KIO::Job*, unsigned long percent );
+ virtual void slotInfoMessage( KIO::Job*, const QString & msg );
+
+ virtual void slotStop();
+ virtual void closeEvent( QCloseEvent* );
+
+protected:
+ void showTotals();
+ void setDestVisible( bool visible );
+
+ KSqueezedTextLabel* sourceLabel;
+ KSqueezedTextLabel* destLabel;
+ QLabel* progressLabel;
+ QLabel* destInvite;
+ QLabel* speedLabel;
+ QLabel* sizeLabel;
+ QLabel* resumeLabel;
+
+ KProgress* m_pProgressBar;
+
+ KIO::filesize_t m_iTotalSize;
+ unsigned long m_iTotalFiles;
+ unsigned long m_iTotalDirs;
+
+ KIO::filesize_t m_iProcessedSize;
+ unsigned long m_iProcessedDirs;
+ unsigned long m_iProcessedFiles;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+};
+
+
+#endif // __kr_progress_h__
+
diff --git a/krusader/Dialogs/krspecialwidgets.cpp b/krusader/Dialogs/krspecialwidgets.cpp
new file mode 100644
index 0000000..f7027de
--- /dev/null
+++ b/krusader/Dialogs/krspecialwidgets.cpp
@@ -0,0 +1,239 @@
+/***************************************************************************
+ krspecialwidgets.cpp
+ -------------------
+copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+e-mail : krusader@users.sourceforge.net
+web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+Description
+***************************************************************************
+
+A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+
+
+#include "krspecialwidgets.h"
+#include "krmaskchoice.h"
+#include "newftpgui.h"
+#include "../krusader.h"
+#include "../MountMan/kmountman.h"
+#include <math.h>
+#include <kfileitem.h>
+#include <klocale.h>
+#include <klineedit.h>
+#include <kdebug.h>
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////// 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 ) {
+ resize( 150, 200 );
+ 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 ) {
+ resize( 150, 200 );
+ 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 ) {
+ resize( 150, 200 );
+ show();
+}
+
+
+// The main painter!
+void KRFSDisplay::paintEvent( QPaintEvent * ) {
+ QPainter paint( this );
+ if ( !empty ) {
+ // create the text
+ // first, name and location
+ paint.setFont( QFont( "helvetica", 12, QFont::Bold ) );
+ paint.drawText( 10, 20, alias );
+ paint.setFont( QFont( "helvetica", 12, QFont::Normal ) );
+ paint.drawText( 10, 37, "(" + realName + ")" );
+ if ( mounted ) { // incase the filesystem is already mounted
+ // second, the capacity
+ paint.drawText( 10, 70, i18n( "Capacity: " ) + KIO::convertSizeFromKB( totalSpace ) );
+ // third, the 2 boxes (used, free)
+ QPen systemPen = paint.pen();
+ paint.setPen( Qt::black );
+ paint.drawRect( 10, 90, 10, 10 );
+ paint.fillRect( 11, 91, 8, 8, QBrush( Qt::gray ) );
+ paint.drawRect( 10, 110, 10, 10 );
+ paint.fillRect( 11, 111, 8, 8, QBrush( Qt::white ) );
+ // now, the text for the boxes
+ paint.setPen( systemPen );
+ paint.drawText( 25, 100, i18n( "Used: " ) + KIO::convertSizeFromKB( totalSpace - freeSpace ) );
+ paint.drawText( 25, 120, i18n( "Free: " ) + KIO::convertSizeFromKB( freeSpace ) );
+ // first, create the empty pie
+ // bottom...
+ paint.setPen( Qt::black );
+ paint.setBrush( Qt::white );
+ paint.drawPie( LEFT, BOTTOM, WIDTH, HEIGHT, STARTANGLE, DEG( 360 ) );
+ // body...
+ paint.setPen( Qt::lightGray );
+ for ( int i = 1; i < Z_HEIGHT; ++i )
+ paint.drawPie( LEFT, BOTTOM - i, WIDTH, HEIGHT, STARTANGLE, DEG( 360 ) );
+ // side lines...
+ paint.setPen( Qt::black );
+ paint.drawLine( LEFT, BOTTOM + HEIGHT / 2, LEFT, BOTTOM + HEIGHT / 2 - Z_HEIGHT );
+ paint.drawLine( LEFT + WIDTH, BOTTOM + HEIGHT / 2, LEFT + WIDTH, BOTTOM + HEIGHT / 2 - Z_HEIGHT );
+ // top of the pie
+ paint.drawPie( LEFT, 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( LEFT, 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( LEFT, BOTTOM - j, WIDTH, HEIGHT, STARTANGLE - 16 * 180, ( int ) ( DEG( i - 180.0 ) ) );
+ }
+ } else { // if the filesystem is unmounted...
+ paint.setFont( QFont( "helvetica", 12, QFont::Bold ) );
+ paint.drawText( 10, 60, i18n( "Not mounted." ) );
+ }
+ } else { // if the widget is in empty situation...
+
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+KRPie::KRPie( KIO::filesize_t _totalSize, QWidget *parent ) : QWidget( parent, 0 ), totalSize( _totalSize ) {
+ slices.setAutoDelete( true ); // kill items when they are removed
+ slices.append( new KRPieSlice( 100, Qt::yellow, "DEFAULT" ) );
+ sizeLeft = totalSize;
+ resize( 300, 300 );
+}
+
+void KRPie::paintEvent( QPaintEvent * ) {
+ QPainter paint( this );
+ // now create the slices
+ KRPieSlice *slice;
+ float sAngle = STARTANGLE;
+ for ( slice = slices.first(); slice != 0; slice = slices.next() ) {
+ paint.setBrush( slice->getColor() );
+ paint.setPen( slice->getColor() );
+ // angles are negative to create a clock-wise drawing of slices
+ float angle = -( slice->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<Z_HEIGHT; ++i)
+ // paint.drawPie(LEFT,BOTTOM+i,WIDTH,HEIGHT,sAngle,360*16-(STARTANGLE-sAngle));
+ sAngle = STARTANGLE;
+ for ( slice = slices.first(); slice != 0; slice = slices.next() ) {
+ paint.setBrush( slice->getColor() );
+ paint.setPen( slice->getColor() );
+ // angles are negative to create a clock-wise drawing of slices
+ float angle = -( slice->getPerct() / 100 * 360 ) * 16;
+ paint.drawPie( LEFT, BOTTOM, WIDTH, HEIGHT, ( int ) sAngle, ( int ) angle );
+ sAngle += angle;
+ }
+
+
+ paint.setPen( Qt::black );
+ // the pie
+ // paint.drawPie(LEFT,BOTTOM,WIDTH,HEIGHT,STARTANGLE,360*16);
+ ///////////////////////// end of empty pie /////////////////////////
+ // now, the pie is ready to draw slices on...
+ // to make a good look on the perimiter, draw another black circle
+ paint.setPen( Qt::black );
+ paint.drawArc( LEFT, BOTTOM, WIDTH, HEIGHT, STARTANGLE, 360 * 16 );
+
+}
+
+void KRPie::addSlice( KIO::filesize_t size, QString label ) {
+ int i = ( slices.count() % 12 );
+ slices.removeLast();
+ slices.append( new KRPieSlice( size * 100 / totalSize, colors[ i ], label ) );
+ sizeLeft -= size;
+ slices.append( new KRPieSlice( sizeLeft * 100 / totalSize, Qt::yellow, "DEFAULT" ) );
+}
+
+////////////////////////////////////////////////////
+/////////////////// KrQuickSearch /////////////////
+////////////////////////////////////////////////////
+KrQuickSearch::KrQuickSearch( QWidget *parent, const char * name ) : KLineEdit( parent, name ) {}
+
+void KrQuickSearch::myKeyPressEvent( QKeyEvent *e ) {
+ switch ( e->key() ) {
+ case Key_Escape:
+ emit stop( 0 );
+ break;
+ case Key_Return:
+ case Key_Enter:
+ case Key_Tab:
+ case Key_Right:
+ case Key_Left:
+ emit stop( e );
+ break;
+ case Key_Down:
+ otherMatching( text(), 1 );
+ break;
+ case Key_Up:
+ otherMatching( text(), -1 );
+ break;
+ case Key_Insert:
+ case Key_Home:
+ case Key_End:
+ process( e );
+ break;
+ default:
+ keyPressEvent( e );
+ }
+}
+
+
+
+#include "krspecialwidgets.moc"
diff --git a/krusader/Dialogs/krspecialwidgets.h b/krusader/Dialogs/krspecialwidgets.h
new file mode 100644
index 0000000..9d0a36a
--- /dev/null
+++ b/krusader/Dialogs/krspecialwidgets.h
@@ -0,0 +1,126 @@
+/***************************************************************************
+ krspecialwidgets.h
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+Description
+***************************************************************************
+
+A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+
+#ifndef KRSPECIALWIDGETS_H
+#define KRSPECIALWIDGETS_H
+
+#include <qwidget.h>
+#include <qpainter.h>
+#include <qcolor.h>
+#include <qptrlist.h>
+#include <klineedit.h>
+#include <qevent.h>
+#include <kio/global.h>
+
+class KRPieSlice;
+
+class KRPie : public QWidget {
+ Q_OBJECT
+ public:
+ KRPie( KIO::filesize_t _totalSize, QWidget *parent = 0 );
+ void addSlice( KIO::filesize_t size, QString label );
+
+ protected:
+ void paintEvent( QPaintEvent * );
+
+ private:
+ QList<KRPieSlice> slices;
+ KIO::filesize_t totalSize, sizeLeft;
+ static QColor colors[ 12 ];
+};
+
+class KRFSDisplay : public QWidget {
+ Q_OBJECT
+ public:
+ // this constructor is used for a mounted filesystem
+ KRFSDisplay( QWidget *parent, QString _alias, QString _realName,
+ KIO::filesize_t _total, KIO::filesize_t _free );
+ // this one is for an unmounted/supermount file system
+ KRFSDisplay( QWidget *parent, QString _alias, QString _realName, bool sm = false );
+ // the last one is used inside MountMan(R), when no filesystem is selected
+ KRFSDisplay( QWidget *parent );
+ inline void setTotalSpace( KIO::filesize_t t ) { totalSpace = t; }
+ inline void setFreeSpace( KIO::filesize_t t ) { freeSpace = t; }
+ inline void setAlias( QString a ) { alias = a; }
+ inline void setRealName( QString r ) { realName = r; }
+ inline void setMounted( bool m ) { mounted = m; }
+ inline void setEmpty( bool e ) { empty = e; }
+ inline void setSupermount( bool s ) { supermount = s; }
+
+ protected:
+ void paintEvent( QPaintEvent * );
+
+ private:
+ KIO::filesize_t totalSpace, freeSpace;
+ QString alias, realName;
+ bool mounted, empty, supermount;
+};
+
+class KRPieSlice {
+ public:
+ KRPieSlice( float _perct, QColor _color, QString _label ) :
+ perct( _perct ), color( _color ), label( _label ) {}
+ inline QColor getColor() { return color; }
+ inline float getPerct() { return perct; }
+ inline QString getLabel() { return label; }
+ inline void setPerct( float _perct ) { perct = _perct; }
+ inline void setLabel( QString _label ) { label = _label; }
+
+ private:
+ float perct;
+ QColor color;
+ QString label;
+};
+
+class KrQuickSearch: public KLineEdit {
+ Q_OBJECT
+ public:
+ KrQuickSearch(QWidget *parent, const char * name = 0);
+ void addText(const QString &str) { setText(text()+str); }
+ void myKeyPressEvent(QKeyEvent *e);
+ void myIMStartEvent(QIMEvent* e) {
+ imStartEvent(e);
+ }
+ void myIMEndEvent(QIMEvent* e) {
+ imEndEvent(e);
+ }
+ void myIMComposeEvent(QIMEvent* e) {
+ imComposeEvent(e);
+ }
+
+ signals:
+ void stop(QKeyEvent *e);
+ void process(QKeyEvent *e);
+ void otherMatching(const QString &, int);
+
+};
+
+#endif
diff --git a/krusader/Dialogs/krspwidgets.cpp b/krusader/Dialogs/krspwidgets.cpp
new file mode 100644
index 0000000..64da41f
--- /dev/null
+++ b/krusader/Dialogs/krspwidgets.cpp
@@ -0,0 +1,316 @@
+/***************************************************************************
+ krspwidgets.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "krspwidgets.h"
+#include "../krusader.h"
+#include "../krusaderview.h"
+#include "../Panel/listpanel.h"
+#include "../kicons.h"
+#include "../Filter/filtertabs.h"
+#include <qcombobox.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include <qlistbox.h>
+#include <qspinbox.h>
+#include <klocale.h>
+#include <kcombobox.h>
+#include <kiconloader.h>
+#include <kcursor.h>
+#include <qbitmap.h>
+#include "../resources.h"
+
+///////////////////// initiation of the static members ////////////////////////
+QStrList KRSpWidgets::maskList;
+
+///////////////////////////////////////////////////////////////////////////////
+
+KRSpWidgets::KRSpWidgets(){
+}
+
+KRQuery KRSpWidgets::getMask(QString caption, bool nameOnly ) {
+ if( !nameOnly ) {
+ return FilterTabs::getQuery();
+ }
+ else {
+ KRMaskChoiceSub *p=new KRMaskChoiceSub();
+ p->setCaption(caption);
+ p->exec();
+ if (p->selection->currentText()=="") return KRQuery();
+ else return KRQuery( p->selection->currentText() );
+ }
+}
+
+/////////////////////////// newFTP ////////////////////////////////////////
+KURL KRSpWidgets::newFTP() {
+ newFTPSub *p=new newFTPSub();
+ p->exec();
+ if (p->url->currentText()=="") return KURL(); // empty url
+ KURL url;
+
+ QString protocol = p->prefix->currentText();
+ protocol.truncate(protocol.length() - 3); // remove the trailing ://
+ QString username = p->username->text().simplifyWhiteSpace();
+ QString password = p->password->text().simplifyWhiteSpace();
+ QString uri = p->url->currentText();
+
+ int uriStart = uri.findRev( '@' ); /* lets the user enter user and password in the URI field */
+ if( uriStart != -1 ) {
+ QString uriUser = uri.left( uriStart );
+ QString uriPsw = QString::null;
+ uri = uri.mid( uriStart + 1 );
+
+ int pswStart = uriUser.find( ':' ); /* getting the password name from the URL */
+ if( pswStart != -1 ) {
+ uriPsw = uriUser.mid( pswStart + 1 );
+ uriUser = uriUser.left( pswStart );
+ }
+
+ if( !uriUser.isEmpty() ) /* handling the ftp proxy username and password also */
+ username = username.isEmpty() ? uriUser : username + "@" + uriUser;
+
+ if( !uriPsw.isEmpty() ) /* handling the ftp proxy username and password also */
+ password = password.isEmpty() ? uriPsw : password + "@" + uriPsw;
+ }
+
+ QString host = uri; /* separating the hostname and path from the uri */
+ QString path = QString::null;
+ int pathStart = uri.find( "/" );
+ if( pathStart != -1 ) {
+ path = host.mid( pathStart );
+ host = host.left( pathStart );
+ }
+
+ /* setting the parameters of the URL */
+ url.setProtocol(protocol);
+ url.setHost( host );
+ url.setPath( path );
+ if ( protocol == "ftp" || protocol == "fish" || protocol == "sftp" )
+ url.setPort(p->port->cleanText().toInt());
+ if (!username.isEmpty())
+ url.setUser( username );
+ if (!password.isEmpty())
+ url.setPass( password );
+
+ return url;
+}
+
+newFTPSub::newFTPSub() : newFTPGUI(0,0,true) {
+ url->setFocus();
+ setGeometry(krApp->x()+krApp->width()/2-width()/2,krApp->y()+krApp->height()/2-height()/2,width(),height());
+}
+
+void newFTPSub::accept() {
+ url->addToHistory( url->currentText() );
+ // save the history and completion list when the history combo is
+ // destroyed
+ krConfig->setGroup("Private");
+ QStringList list = url->completionObject()->items();
+ krConfig->writeEntry( "newFTP Completion list", list );
+ list = url->historyItems();
+ krConfig->writeEntry( "newFTP History list", list );
+
+ newFTPGUI::accept();
+}
+
+void newFTPSub::reject() {
+ url->setCurrentText("");
+ newFTPGUI::reject();
+}
+
+/////////////////////////// KRMaskChoiceSub ///////////////////////////////
+KRMaskChoiceSub::KRMaskChoiceSub() : KRMaskChoice(0,0,true) {
+ PixmapLabel1->setPixmap(krLoader->loadIcon("kr_select", KIcon::Desktop, 32));
+ label->setText(i18n("Enter a selection:"));
+ // the predefined selections list
+ krConfig->setGroup("Private");
+ QStrList lst;
+ int i=krConfig->readListEntry("Predefined Selections",lst);
+ if (i>0) preSelections->insertStrList(lst);
+ // the combo-box tweaks
+ selection->setDuplicatesEnabled(false);
+ selection->insertStrList(KRSpWidgets::maskList);
+ selection->lineEdit()->setText("*");
+ selection->lineEdit()->selectAll();
+ selection->setFocus();
+}
+
+void KRMaskChoiceSub::reject() {
+ selection->clear();
+ KRMaskChoice::reject();
+}
+
+void KRMaskChoiceSub::accept() {
+ bool add = true;
+ char *tmp;
+ // make sure we don't have that already
+ for ( tmp = KRSpWidgets::maskList.first(); tmp ; tmp = KRSpWidgets::maskList.next() )
+ if (QString(tmp).simplifyWhiteSpace() == selection->currentText().simplifyWhiteSpace()) {
+ // break if we found one such as this
+ add = false;
+ break;
+ }
+
+ if (add)
+ KRSpWidgets::maskList.insert(0,selection->currentText().local8Bit());
+ // write down the predefined selections list
+ QStrList list;
+ QListBoxItem *i=preSelections->firstItem();
+ while (i!=0) {
+ if (i->text().find(i18n("compare mode"))==-1)
+ list.append(i->text().local8Bit());
+ i=i->next();
+ }
+ krConfig->setGroup("Private");
+ krConfig->writeEntry("Predefined Selections",list);
+ KRMaskChoice::accept();
+}
+
+void KRMaskChoiceSub::addSelection() {
+ QString temp=selection->currentText();
+ bool itemExists=false;
+ QListBoxItem *i=preSelections->firstItem();
+ // check if the selection already exists
+ while (i!=0)
+ if (i->text()==temp) {
+ itemExists=true;
+ break;
+ } else i=i->next();
+ if (temp!="" && !itemExists) {
+ preSelections->insertItem(selection->currentText());
+ preSelections->update();
+ }
+}
+
+void KRMaskChoiceSub::deleteSelection() {
+ if (preSelections->currentItem()!=-1 &&
+ preSelections->currentText().find(i18n("compare mode"))==-1) {
+ preSelections->removeItem(preSelections->currentItem());
+ preSelections->update();
+ }
+}
+
+void KRMaskChoiceSub::clearSelections() {
+ preSelections->clear();
+ preSelections->update();
+}
+
+void KRMaskChoiceSub::acceptFromList(QListBoxItem *i) {
+ selection->insertItem(i->text(),0);
+ accept();
+}
+
+////////////////////////// QuickNavLineEdit ////////////////////
+
+QuickNavLineEdit::QuickNavLineEdit(const QString &string, QWidget *parent, const char *name):
+ KLineEdit(string, parent, name) { init(); }
+
+QuickNavLineEdit::QuickNavLineEdit(QWidget *parent, const char *name):
+ KLineEdit(parent, name) { init(); }
+
+int QuickNavLineEdit::findCharFromPos(const QString & str, const QFontMetrics & metrics, int pos)
+{
+ if (pos < 0)
+ return -1;
+ for (int i = 1; i <= (int)str.length(); ++i)
+ if (metrics.width(str, i) > pos)
+ return i;
+ return str.length();
+}
+
+void QuickNavLineEdit::init() {
+ _numOfSelectedChars=0;
+ _dummyDisplayed=false;
+ _pop=0;
+ //setCompletionMode( KGlobalSettings::CompletionPopupAuto ); ==> removed by public demand
+}
+
+void QuickNavLineEdit::leaveEvent(QEvent *) {
+ clearAll();
+}
+
+void QuickNavLineEdit::mousePressEvent( QMouseEvent *m ) {
+ if (m->state()!=ControlButton) clearAll();
+ else
+ {
+ if (!_numOfSelectedChars)
+ {
+ _numOfSelectedChars = charCount(m);
+ if (_numOfSelectedChars < 0)
+ _numOfSelectedChars = 0;
+ }
+ if (_numOfSelectedChars)
+ emit returnPressed(text().left(_numOfSelectedChars));
+ }
+ KLineEdit::mousePressEvent(m);
+}
+
+int QuickNavLineEdit::charCount(const QMouseEvent * const m,QString * const str) {
+ // find how much of the string we've selected (approx)
+ // and select from from the start to the closet slash (on the right)
+ const QString tx = text().simplifyWhiteSpace();
+ if (tx.isEmpty()) {
+ clearAll();
+ return -1;
+ }
+
+ int numOfChars = findCharFromPos(tx, fontMetrics(), m->x() - 5);
+ if(str) *str=tx;
+ return tx.find('/', numOfChars);
+}
+
+void QuickNavLineEdit::mouseMoveEvent( QMouseEvent *m) {
+ if (m->state()!=ControlButton) { // works only with ctrl pressed
+ clearAll();
+ KLineEdit::mouseMoveEvent(m);
+ return;
+ }
+ QString tx;
+ int idx=charCount(m,&tx);
+ if (idx == -1 && !_dummyDisplayed) { // pointing on or after the current directory
+ if (_pop) delete _pop;
+ _pop = KPassivePopup::message( i18n("Quick Navigation"),
+ "<qt>" + i18n("Already at <i>%1</i>").arg(tx.left(idx)) + "</qt>",
+ *(KCursor::handCursor().bitmap()), this);
+
+ _dummyDisplayed=true;
+ _numOfSelectedChars=0;
+ } else if (idx>0 && idx!=_numOfSelectedChars) {
+ _numOfSelectedChars=idx;
+ if (_pop) delete _pop;
+ _dummyDisplayed=false;
+
+ _pop = KPassivePopup::message( i18n("Quick Navigation"),
+ "<qt>" + i18n("Click to go to <i>%1</i>").arg(tx.left(idx)) + "</qt>",
+ *(KCursor::handCursor().bitmap()), this );
+ }
+ KLineEdit::mouseMoveEvent(m);
+}
+
diff --git a/krusader/Dialogs/krspwidgets.h b/krusader/Dialogs/krspwidgets.h
new file mode 100644
index 0000000..d1466cb
--- /dev/null
+++ b/krusader/Dialogs/krspwidgets.h
@@ -0,0 +1,110 @@
+/***************************************************************************
+ krspwidgets.h
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef KRSPWIDGETS_H
+#define KRSPWIDGETS_H
+
+#include <qstrlist.h>
+#include <kurl.h>
+#include "krmaskchoice.h"
+#include "newftpgui.h"
+#include "../VFS/krquery.h"
+#include <klineedit.h>
+#include <kpassivepopup.h>
+
+class newFTPGUI;
+
+class KRMaskChoiceSub;
+
+class KRSpWidgets {
+ friend class KRMaskChoiceSub;
+
+public:
+ KRSpWidgets();
+
+ static KRQuery getMask( QString caption, bool nameOnly=false ); // get file-mask for (un)selecting files
+ static KURL newFTP();
+
+private:
+ static QStrList maskList; // used by KRMaskChoiceSub
+};
+
+/////////////////////////// newFTPSub ///////////////////////////////////////
+class newFTPSub : public newFTPGUI {
+public:
+ newFTPSub();
+
+protected:
+ void reject();
+ void accept();
+};
+
+/////////////////////////// KRMaskChoiceSub /////////////////////////////////
+// Inherits KRMaskChoice's generated code to fully implement the functions //
+/////////////////////////////////////////////////////////////////////////////
+class KRMaskChoiceSub : public KRMaskChoice {
+public:
+ KRMaskChoiceSub();
+
+public slots:
+ void addSelection();
+ void deleteSelection();
+ void clearSelections();
+ void acceptFromList(QListBoxItem *i);
+
+protected:
+ void reject();
+ void accept();
+};
+
+/////////////////////////// QuickNavLineEdit //////////////////////////
+// same as line edit, but hold ctrl while pointing to it... and see! //
+///////////////////////////////////////////////////////////////////////
+
+class QuickNavLineEdit: public KLineEdit {
+public:
+ QuickNavLineEdit(const QString &string, QWidget *parent, const char *name=0);
+ QuickNavLineEdit(QWidget *parent=0, const char *name=0);
+ virtual ~QuickNavLineEdit() {}
+ static int findCharFromPos(const QString &, const QFontMetrics &, int pos);
+protected:
+ void mouseMoveEvent( QMouseEvent *m);
+ void leaveEvent( QEvent * );
+ void mousePressEvent( QMouseEvent *m );
+ inline void clearAll() { _numOfSelectedChars = 0; if (_pop) delete _pop; _dummyDisplayed=false; }
+ void init();
+
+private:
+ int charCount(const QMouseEvent * const , QString* const =0) ;
+ int _numOfSelectedChars;
+ bool _dummyDisplayed;
+ QGuardedPtr<KPassivePopup> _pop;
+};
+
+#endif
diff --git a/krusader/Dialogs/krsqueezedtextlabel.cpp b/krusader/Dialogs/krsqueezedtextlabel.cpp
new file mode 100644
index 0000000..5d93269
--- /dev/null
+++ b/krusader/Dialogs/krsqueezedtextlabel.cpp
@@ -0,0 +1,80 @@
+#include "krsqueezedtextlabel.h"
+#include <kstringhandler.h>
+#include <kurldrag.h>
+#include <qtooltip.h>
+
+KrSqueezedTextLabel::KrSqueezedTextLabel(QWidget *parent, const char *name):
+ KSqueezedTextLabel(parent, name), acceptDrops( false ), _index(-1), _length(-1) {
+}
+
+
+KrSqueezedTextLabel::~KrSqueezedTextLabel() {
+}
+
+void KrSqueezedTextLabel::mousePressEvent(QMouseEvent *) {
+ emit clicked();
+
+}
+
+void KrSqueezedTextLabel::enableDrops( bool flag )
+{
+ setAcceptDrops( acceptDrops = flag );
+}
+
+void KrSqueezedTextLabel::dropEvent(QDropEvent *e) {
+ emit dropped(e);
+}
+
+void KrSqueezedTextLabel::dragEnterEvent(QDragEnterEvent *e) {
+ if( acceptDrops )
+ e->accept( KURLDrag::canDecode( e ) );
+ else
+ KSqueezedTextLabel::dragEnterEvent( e );
+}
+
+void KrSqueezedTextLabel::squeezeTextToLabel(int index, int length) {
+ if (index==-1 || length==-1)
+ KSqueezedTextLabel::squeezeTextToLabel();
+ else {
+ QString sqtext=fullText;
+ QFontMetrics fm(fontMetrics());
+ int labelWidth = size().width();
+ int textWidth = fm.width(sqtext);
+ if (textWidth > labelWidth) {
+ int avgCharSize = textWidth / sqtext.length();
+ int numOfExtraChars = (textWidth-labelWidth)/avgCharSize;
+ int delta;
+
+ // remove as much as possible from the left, and then from the right
+ if (index>3) {
+ delta=QMIN(index, numOfExtraChars);
+ numOfExtraChars -= delta;
+ sqtext.replace(0, delta, "...");
+ }
+
+ if (numOfExtraChars>0 && ((int)sqtext.length() > length+3)) {
+ delta = QMIN(numOfExtraChars, (int)sqtext.length() - (length+3));
+ sqtext.replace(sqtext.length()-delta, delta, "...");
+ }
+ QLabel::setText(sqtext);
+
+ QToolTip::remove( this );
+ QToolTip::add( this, fullText );
+ } else {
+ QLabel::setText(fullText);
+
+ QToolTip::remove( this );
+ QToolTip::hide();
+ }
+ }
+}
+
+void KrSqueezedTextLabel::setText( const QString &text, int index, int length ) {
+ _index=index;
+ _length=length;
+ fullText = text;
+ squeezeTextToLabel(_index,_length);
+}
+
+#include "krsqueezedtextlabel.moc"
+
diff --git a/krusader/Dialogs/krsqueezedtextlabel.h b/krusader/Dialogs/krsqueezedtextlabel.h
new file mode 100644
index 0000000..8f81389
--- /dev/null
+++ b/krusader/Dialogs/krsqueezedtextlabel.h
@@ -0,0 +1,44 @@
+#ifndef KRSQUEEZEDTEXTLABEL_H
+#define KRSQUEEZEDTEXTLABEL_H
+
+#include <ksqueezedtextlabel.h>
+
+class QMouseEvent;
+class QDropEvent;
+class QDragEnterEvent;
+
+/**
+This class overloads KSqueezedTextLabel and simply adds a clicked signal,
+so that users will be able to click the label and switch focus between panels.
+
+NEW: a special setText() method allows to choose which part of the string should
+ be displayed (example: make sure that search results won't be cut out)
+*/
+class KrSqueezedTextLabel : public KSqueezedTextLabel {
+Q_OBJECT
+ public:
+ KrSqueezedTextLabel(QWidget *parent = 0, const char *name = 0);
+ ~KrSqueezedTextLabel();
+
+ void enableDrops( bool flag );
+
+ public slots:
+ void setText( const QString &text, int index=-1, int length=-1 );
+
+ signals:
+ void clicked(); /**< emitted when someone clicks on the label */
+ void dropped(QDropEvent *); /**< emitted when someone drops URL onto the label */
+
+ protected:
+ void resizeEvent( QResizeEvent * ) { squeezeTextToLabel(_index, _length); }
+ virtual void mousePressEvent(QMouseEvent *e);
+ virtual void dropEvent(QDropEvent *e);
+ virtual void dragEnterEvent(QDragEnterEvent *e);
+ void squeezeTextToLabel(int index=-1, int length=-1);
+
+ private:
+ bool acceptDrops;
+ int _index, _length;
+};
+
+#endif
diff --git a/krusader/Dialogs/kurllistrequester.cpp b/krusader/Dialogs/kurllistrequester.cpp
new file mode 100644
index 0000000..4575555
--- /dev/null
+++ b/krusader/Dialogs/kurllistrequester.cpp
@@ -0,0 +1,202 @@
+/***************************************************************************
+ kurllistrequester.cpp - description
+ -------------------
+ copyright : (C) 2005 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "kurllistrequester.h"
+#include "../VFS/vfs.h"
+#include <qpixmap.h>
+#include <qcursor.h>
+#include <qlayout.h>
+#include <kfiledialog.h>
+#include <kpopupmenu.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+#define DELETE_ITEM_ID 100
+
+KURLListRequester::KURLListRequester( QWidget *parent, const char * name ) : QWidget( parent, name )
+{
+ KIconLoader *iconLoader = new KIconLoader();
+ QPixmap imageAdd = iconLoader->loadIcon( "1downarrow", KIcon::Panel, 16 );
+ QPixmap imageFolder = iconLoader->loadIcon( "folder", KIcon::Panel, 16 );
+
+ // Creating the widget
+
+ QGridLayout *urlListRequesterGrid = new QGridLayout( this );
+ urlListRequesterGrid->setSpacing( 0 );
+ urlListRequesterGrid->setMargin( 0 );
+
+ urlLineEdit = new KLineEdit( this, "urlLineEdit" );
+ urlListRequesterGrid->addWidget( urlLineEdit, 0, 0 );
+
+ urlListBox = new QListBox( this, "urlListBox" );
+ urlListBox->setSelectionMode( QListBox::Extended );
+ urlListRequesterGrid->addMultiCellWidget( urlListBox, 1, 1, 0, 2 );
+
+ urlAddBtn = new QToolButton( this, "urlAddBtn" );
+ urlAddBtn->setText( "" );
+ urlAddBtn->setPixmap( imageAdd );
+ urlListRequesterGrid->addWidget( urlAddBtn, 0, 1 );
+
+ urlBrowseBtn = new QToolButton( this, "urlBrowseBtn" );
+ urlBrowseBtn->setText( "" );
+ urlBrowseBtn->setPixmap( imageFolder );
+ urlListRequesterGrid->addWidget( urlBrowseBtn, 0, 2 );
+
+ // add shell completion
+
+ completion.setMode( KURLCompletion::FileCompletion );
+ urlLineEdit->setCompletionObject( &completion );
+
+ // connection table
+
+ connect( urlAddBtn, SIGNAL( clicked() ), this, SLOT( slotAdd() ) );
+ connect( urlBrowseBtn, SIGNAL( clicked() ), this, SLOT( slotBrowse() ) );
+ connect( urlLineEdit, SIGNAL( returnPressed(const QString&) ), this, SLOT( slotAdd() ) );
+ connect( urlListBox, SIGNAL( rightButtonClicked ( QListBoxItem *, const QPoint & ) ), this,
+ SLOT( slotRightClicked( QListBoxItem * ) ) );
+}
+
+void KURLListRequester::slotAdd()
+{
+ QString text = urlLineEdit->text().simplifyWhiteSpace();
+ if( text.length() )
+ {
+ QString error = QString::null;
+ emit checkValidity( text, error );
+
+ if( !error.isNull() )
+ KMessageBox::error( this, error );
+ else
+ {
+ urlListBox->insertItem( text );
+ urlLineEdit->clear();
+ }
+ }
+}
+
+void KURLListRequester::slotBrowse()
+{
+ KURL url = KFileDialog::getExistingURL( QString::null, this );
+ if( !url.isEmpty())
+ urlLineEdit->setText( vfs::pathOrURL( url ) );
+ urlLineEdit->setFocus();
+}
+
+void KURLListRequester::keyPressEvent(QKeyEvent *e)
+{
+ if( e->key() == Key_Delete )
+ {
+ if( urlListBox->hasFocus() )
+ {
+ deleteSelectedItems();
+ return;
+ }
+ }
+
+ QWidget::keyPressEvent( e );
+}
+
+void KURLListRequester::deleteSelectedItems()
+{
+ int i=0;
+ QListBoxItem *item;
+
+ while( (item = urlListBox->item(i)) )
+ {
+ if( item->isSelected() )
+ {
+ urlListBox->removeItem( i );
+ continue;
+ }
+ i++;
+ }
+}
+
+void KURLListRequester::slotRightClicked( QListBoxItem *item )
+{
+ if( item == 0 )
+ return;
+
+ KPopupMenu popupMenu( this );
+ popupMenu.insertItem( i18n( "Delete" ), DELETE_ITEM_ID );
+
+ switch( popupMenu.exec( QCursor::pos() ) )
+ {
+ case DELETE_ITEM_ID:
+ if( item->isSelected() )
+ deleteSelectedItems();
+ else
+ urlListBox->removeItem( urlListBox->index( item ) );
+ break;
+ }
+}
+
+KURL::List KURLListRequester::urlList()
+{
+ KURL::List urls;
+
+ QString text = urlLineEdit->text().simplifyWhiteSpace();
+ if (!text.isEmpty())
+ {
+ QString error = QString::null;
+ emit checkValidity( text, error );
+ if( error.isNull() )
+ urls.append( vfs::fromPathOrURL( text ) );
+ }
+
+ QListBoxItem *item = urlListBox->firstItem();
+ while ( item )
+ {
+ QString text = item->text().simplifyWhiteSpace();
+
+ QString error = QString::null;
+ emit checkValidity( text, error );
+ if( error.isNull() )
+ urls.append( vfs::fromPathOrURL( text ) );
+
+ item = item->next();
+ }
+
+ return urls;
+}
+
+void KURLListRequester::setUrlList( KURL::List urlList )
+{
+ urlLineEdit->clear();
+ urlListBox->clear();
+
+ KURL::List::iterator it;
+
+ for ( it = urlList.begin(); it != urlList.end(); ++it )
+ urlListBox->insertItem( vfs::pathOrURL(*it) );
+}
+
+#include "kurllistrequester.moc"
diff --git a/krusader/Dialogs/kurllistrequester.h b/krusader/Dialogs/kurllistrequester.h
new file mode 100644
index 0000000..06afe52
--- /dev/null
+++ b/krusader/Dialogs/kurllistrequester.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+ kurllistrequester.h - description
+ -------------------
+ copyright : (C) 2005 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __KURLLISTREQUESTER_H__
+#define __KURLLISTREQUESTER_H__
+
+#include <qwidget.h>
+#include <qlistbox.h>
+#include <qtoolbutton.h>
+#include <klineedit.h>
+#include <kurl.h>
+#include <kurlcompletion.h>
+
+class KURLListRequester : public QWidget
+{
+ Q_OBJECT
+
+public:
+ KURLListRequester( QWidget *parent = 0, const char * name = 0 );
+
+ KURL::List urlList();
+ void setUrlList( KURL::List );
+
+ KLineEdit *lineEdit() {return urlLineEdit;}
+ QListBox *listBox() {return urlListBox;}
+
+ void setCompletionDir( QString dir ) { completion.setDir( dir ); }
+
+signals:
+ void checkValidity( QString &text, QString &error );
+
+protected slots:
+ void slotAdd();
+ void slotBrowse();
+ void slotRightClicked( QListBoxItem * );
+
+protected:
+ virtual void keyPressEvent(QKeyEvent *e);
+ void deleteSelectedItems();
+
+ KLineEdit *urlLineEdit;
+ QListBox *urlListBox;
+ QToolButton *urlAddBtn;
+ QToolButton *urlBrowseBtn;
+
+ KURLCompletion completion;
+};
+
+#endif /* __KURLLISTREQUESTER_H__ */
diff --git a/krusader/Dialogs/newftpgui.cpp b/krusader/Dialogs/newftpgui.cpp
new file mode 100644
index 0000000..1e8c3ed
--- /dev/null
+++ b/krusader/Dialogs/newftpgui.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+** Form implementation generated from reading ui file 'newftpgui.ui'
+**
+** Created: Fri Oct 27 23:47:10 2000
+** by: The User Interface Compiler (uic)
+**
+** WARNING! All changes made in this file will be lost!
+****************************************************************************/
+#include "newftpgui.h"
+
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qspinbox.h>
+#include <qlayout.h>
+#include <qhbox.h>
+#include <qgrid.h>
+#include <qvariant.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qimage.h>
+#include <qpixmap.h>
+#include <klocale.h>
+#include <kprotocolinfo.h>
+#include <kcombobox.h>
+#include <kiconloader.h>
+#include "../krusader.h"
+
+
+/*
+ * Constructs a newFTPGUI which is a child of 'parent', with the
+ * name 'name' and widget flags set to 'f'
+ *
+ * The dialog will by default be modeless, unless you set 'modal' to
+ * TRUE to construct a modal dialog.
+ */
+
+ #define SIZE_MINIMUM QSizePolicy( (QSizePolicy::SizeType)0, (QSizePolicy::SizeType)0 )
+
+newFTPGUI::newFTPGUI( QWidget* parent, const char* name, bool modal, WFlags fl )
+ : QDialog( parent, name, modal, fl ){
+
+ QVBoxLayout * layout = new QVBoxLayout( this, 11, 6, "newFTPGUI_layout" );
+ layout->setAutoAdd(true);
+
+ if ( !name )
+ setName( "newFTPGUI" );
+ resize( 342, 261 );
+ setCaption( i18n( "New Network Connection" ) );
+// setSizeGripEnabled( TRUE );
+ setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)5, sizePolicy().hasHeightForWidth() ) );
+ setMinimumSize( QSize( 342, 261 ) );
+
+
+ QHBox* hbox_image = new QHBox( this, "hbox_image" );
+ hbox_image->setSpacing( 6 );
+
+ PixmapLabel1 = new QLabel( hbox_image, "PixmapLabel1" );
+ PixmapLabel1->setPixmap( krLoader->loadIcon("network", KIcon::Desktop, 32) );
+ PixmapLabel1->setSizePolicy( SIZE_MINIMUM );
+
+ TextLabel3 = new QLabel( i18n( "About to connect to..." ), hbox_image, "TextLabel3" );
+ QFont TextLabel3_font( TextLabel3->font() );
+ TextLabel3_font.setBold( TRUE );
+ TextLabel3->setFont( TextLabel3_font );
+
+
+ QGrid* grid_host = new QGrid( 3, this, "grid_host" );
+
+ TextLabel1 = new QLabel( i18n( "Protocol:" ), grid_host, "TextLabel1" );
+ TextLabel1_22 = new QLabel( i18n( "Host:"), grid_host, "TextLabel_2" );
+ TextLabel1_3 = new QLabel( i18n( "Port:" ), grid_host, "TextLabel1_3" );
+
+ QStringList protocols = KProtocolInfo::protocols();
+
+ prefix = new KComboBox( FALSE, grid_host, "protocol" );
+ if( protocols.contains("ftp") )
+ prefix->insertItem( i18n( "ftp://" ) );
+ if( protocols.contains("smb") )
+ prefix->insertItem( i18n( "smb://" ) );
+ if( protocols.contains("fish") )
+ prefix->insertItem( i18n( "fish://" ));
+ if( protocols.contains("sftp") )
+ prefix->insertItem( i18n( "sftp://" ));
+ prefix->setAcceptDrops( FALSE );
+ prefix->setEnabled( TRUE );
+ prefix->setSizePolicy( SIZE_MINIMUM );
+ connect( prefix,SIGNAL(activated(const QString& )),
+ this,SLOT(slotTextChanged(const QString& )));
+
+ url = new KHistoryCombo( grid_host, "url" );
+ url->setMaximumHeight( 20 );
+ url->setMaxCount( 25 );
+ url->setDuplicatesEnabled( false );
+ connect( url, SIGNAL( activated( const QString& )),
+ url, SLOT( addToHistory( const QString& )));
+ // load the history and completion list after creating the history combo
+ krConfig->setGroup("Private");
+ QStringList list = krConfig->readListEntry( "newFTP Completion list" );
+ url->completionObject()->setItems( list );
+ list = krConfig->readListEntry( "newFTP History list" );
+ url->setHistoryItems( list );
+
+ port = new QSpinBox( grid_host, "port" );
+ port->setMaxValue( 65535 );
+#if QT_VERSION < 300
+ port->setFrameShadow( QSpinBox::Sunken );
+#endif
+ port->setValue( 21 );
+ port->setSizePolicy( SIZE_MINIMUM );
+
+
+ TextLabel1_2 = new QLabel( i18n( "Username:" ), this, "TextLabel1_2" );
+ username = new QLineEdit( this, "username" );
+ TextLabel1_2_2 = new QLabel( i18n( "Password:" ), this, "TextLabel1_2_2" );
+ password = new QLineEdit( this, "password" );
+ password->setEchoMode( QLineEdit::Password );
+
+
+ QWidget* Layout6 = new QWidget( this, "Layout6" );
+ hbox = new QHBoxLayout( Layout6 );
+ hbox->setSpacing( 6 );
+ hbox->setMargin( 0 );
+
+ hbox->addItem(new QSpacerItem(1,1,QSizePolicy::Expanding));
+
+ connectBtn = new QPushButton( i18n( "&Connect" ), Layout6, "connectBtn" );
+ connectBtn->setAutoDefault( TRUE );
+ connectBtn->setDefault( TRUE );
+ hbox->addWidget( connectBtn );
+
+ //saveBtn = new QPushButton( i18n( "&Save" ), Layout6, "saveBtn" );
+ //saveBtn->setAutoDefault( TRUE );
+ //hbox->addWidget( saveBtn );
+
+ cancelBtn = new QPushButton( i18n( "&Cancel" ), Layout6, "cancelBtn" );
+ cancelBtn->setAutoDefault( TRUE );
+ hbox->addWidget( cancelBtn );
+
+ // signals and slots connections
+ connect( connectBtn, SIGNAL( clicked() ), this, SLOT( accept() ) );
+ connect( cancelBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
+
+ // tab order
+ setTabOrder( url, username );
+ setTabOrder( username, password );
+ setTabOrder( password, connectBtn );
+ setTabOrder( connectBtn, cancelBtn );
+ setTabOrder( cancelBtn, prefix );
+ setTabOrder( prefix, url );
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+newFTPGUI::~newFTPGUI(){
+ // no need to delete child widgets, Qt does it all for us
+}
+
+void newFTPGUI::slotTextChanged(const QString& string){
+ if( string.startsWith("ftp") || string.startsWith("sftp") || string.startsWith("fish") )
+ {
+ if( port->value() == 21 || port->value() == 22 )
+ port->setValue( string.startsWith("ftp") ? 21 : 22 );
+ port->setEnabled(true);
+ }
+ else
+ port->setEnabled(false);
+}
+
+/*
+ * Main event handler. Reimplemented to handle application
+ * font changes
+ */
+bool newFTPGUI::event( QEvent* ev ) {
+ bool ret = QDialog::event( ev );
+ if ( ev->type() == QEvent::ApplicationFontChange ) {
+ QFont TextLabel3_font( TextLabel3->font() );
+ TextLabel3_font.setBold( TRUE );
+ TextLabel3->setFont( TextLabel3_font );
+ }
+ return ret;
+}
+
+#include "newftpgui.moc"
diff --git a/krusader/Dialogs/newftpgui.h b/krusader/Dialogs/newftpgui.h
new file mode 100644
index 0000000..2291d4f
--- /dev/null
+++ b/krusader/Dialogs/newftpgui.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+** Form interface generated from reading ui file 'newftpgui.ui'
+**
+** Created: Fri Oct 27 23:47:08 2000
+** by: The User Interface Compiler (uic)
+**
+** WARNING! All changes made in this file will be lost!
+****************************************************************************/
+#ifndef NEWFTPGUI_H
+#define NEWFTPGUI_H
+
+#include <qvariant.h>
+#include <qdialog.h>
+class QVBoxLayout;
+class QHBoxLayout;
+class QGridLayout;
+class QLabel;
+class QLineEdit;
+class QPushButton;
+class QSpinBox;
+class KComboBox;
+class KHistoryCombo;
+
+class newFTPGUI : public QDialog {
+ Q_OBJECT
+public:
+ newFTPGUI( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 );
+ ~newFTPGUI();
+
+ QLabel* TextLabel1;
+ KComboBox* prefix;
+ QLabel* TextLabel1_2_2;
+ QLabel* TextLabel1_22;
+ QLabel* TextLabel1_2;
+ QLabel* TextLabel1_3;
+ QSpinBox* port;
+ QLineEdit* password;
+ QPushButton* connectBtn;
+ QPushButton* saveBtn;
+ QPushButton* cancelBtn;
+ QLabel* PixmapLabel1;
+ QLabel* TextLabel3;
+ QLineEdit* username;
+ KHistoryCombo* url;
+
+public slots:
+ void slotTextChanged(const QString& string);
+
+protected:
+ QHBoxLayout* hbox;
+ bool event( QEvent* );
+};
+
+#endif // NEWFTPGUI_H
diff --git a/krusader/Dialogs/packgui.cpp b/krusader/Dialogs/packgui.cpp
new file mode 100644
index 0000000..7036a3e
--- /dev/null
+++ b/krusader/Dialogs/packgui.cpp
@@ -0,0 +1,120 @@
+/***************************************************************************
+ packgui.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "packgui.h"
+#include <kfiledialog.h>
+#include "../krusader.h"
+#include "../defaults.h"
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include <qstringlist.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+
+#define PS(x) lst.contains(x)>0
+
+// clear the statics first
+QString PackGUI::filename=0;
+QString PackGUI::destination=0;
+QString PackGUI::type=0;
+QMap<QString, QString> PackGUI::extraProps;
+
+PackGUI::PackGUI(QString defaultName, QString defaultPath, int noOfFiles, QString filename) :
+ PackGUIBase(0,0,true) {
+ // first, fill the WhatToPack textfield with information
+ if(noOfFiles == 1)
+ TextLabel1->setText( i18n("Pack %1").arg(filename) );
+ else
+ TextLabel1->setText( i18n("Pack %n file", "Pack %n files", noOfFiles) );
+
+ // now, according to the Konfigurator, fill the combobox with the information
+ // about what kind of packing we can do
+ krConfig->setGroup("Archives");
+ QStringList lst=krConfig->readListEntry("Supported Packers");
+ // now, clear the type combo and begin...
+ typeData->clear();
+ if (PS("tar")) typeData->insertItem("tar");
+ if (PS("tar") && PS("gzip")) typeData->insertItem("tar.gz");
+ if (PS("tar") && PS("bzip2")) typeData->insertItem("tar.bz2");
+ if (PS("zip")) typeData->insertItem("zip");
+ if (PS("rar")) typeData->insertItem("rar");
+ if (PS("lha")) typeData->insertItem("lha");
+ if (PS("arj")) typeData->insertItem("arj");
+ if (PS("7z")) typeData->insertItem("7z");
+ // set the last used packer as the top one
+ QString tmp=krConfig->readEntry("lastUsedPacker",QString::null);
+ if (tmp!=QString::null) {
+ for (unsigned int i=0; i< typeData->listBox()->count(); ++i)
+ if (typeData->listBox()->item(i)->text() == tmp) {
+ typeData->listBox()->removeItem(i);
+ typeData->listBox()->insertItem(tmp,0);
+ break;
+ }
+ }
+ checkConsistency();
+
+ // and go on with the normal stuff
+ dirData->setText(defaultPath);
+ nameData->setText(defaultName);
+ nameData->setFocus();
+ if (typeData->listBox()->count()==0) // if no packers are availble
+ okButton->setEnabled(false);
+ setGeometry(krApp->x()+krApp->width()/2-width()/2,krApp->y()+krApp->height()/2-height()/2,width(),height());
+ exec();
+}
+
+void PackGUI::browse() {
+ QString temp=KFileDialog::getExistingDirectory(dirData->text(),0,i18n("Please select a directory"));
+ if (temp != QString::null)
+ dirData->setText(temp);
+}
+
+void PackGUI::accept() {
+ if( !extraProperties( extraProps ) )
+ return;
+
+ filename=nameData->text();
+ destination=dirData->text();
+ type=typeData->currentText();
+ // write down the packer chosen, to be lastUsedPacker
+ krConfig->setGroup("Archives");
+ krConfig->writeEntry("lastUsedPacker",type);
+ krConfig->sync();
+ PackGUIBase::accept();
+}
+
+void PackGUI::reject() {
+ filename=QString::null;
+ destination=QString::null;
+ type=QString::null;
+ PackGUIBase::reject();
+}
+
+#include "packgui.moc"
diff --git a/krusader/Dialogs/packgui.h b/krusader/Dialogs/packgui.h
new file mode 100644
index 0000000..d88c831
--- /dev/null
+++ b/krusader/Dialogs/packgui.h
@@ -0,0 +1,53 @@
+/***************************************************************************
+ packgui.h
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef PACKGUI_H
+#define PACKGUI_H
+
+#include "packguibase.h"
+
+class PackGUI : public PackGUIBase {
+ Q_OBJECT
+public:
+ PackGUI(QString defaultName, QString defaultPath, int noOfFiles, QString filename="");
+
+public slots:
+ void browse();
+
+protected slots:
+ void accept();
+ void reject();
+
+public:
+ static QString filename, destination, type;
+ static QMap<QString, QString> extraProps;
+};
+
+#endif
diff --git a/krusader/Dialogs/packguibase.cpp b/krusader/Dialogs/packguibase.cpp
new file mode 100644
index 0000000..ace6078
--- /dev/null
+++ b/krusader/Dialogs/packguibase.cpp
@@ -0,0 +1,468 @@
+/***************************************************************************
+ packguibase.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#include "packguibase.h"
+
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qtoolbutton.h>
+#include <qlayout.h>
+#include <qvariant.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qimage.h>
+#include <qpixmap.h>
+#include <qspinbox.h>
+#include <qslider.h>
+#include <qhbox.h>
+#include <qvbox.h>
+#include <kiconloader.h>
+#include <kglobalsettings.h>
+#include <kcombobox.h>
+#include <kmessagebox.h>
+#include <kio/global.h>
+#include "../krusader.h"
+
+/*
+ * Constructs a PackGUIBase which is a child of 'parent', with the
+ * name 'name' and widget flags set to 'f'
+ *
+ * The dialog will by default be modeless, unless you set 'modal' to
+ * TRUE to construct a modal dialog.
+ */
+PackGUIBase::PackGUIBase( QWidget* parent, const char* name, bool modal, WFlags fl )
+ : QDialog( parent, name, modal, fl ), expanded( false )
+{
+ if ( !name )
+ setName( "PackGUIBase" );
+ resize( 430, 140 );
+ setCaption( i18n( "Pack" ) );
+ grid = new QGridLayout( this );
+ grid->setSpacing( 6 );
+ grid->setMargin( 11 );
+
+ hbox = new QHBoxLayout;
+ hbox->setSpacing( 6 );
+ hbox->setMargin( 0 );
+
+ TextLabel3 = new QLabel( this, "TextLabel3" );
+ TextLabel3->setText( i18n( "To archive" ) );
+ hbox->addWidget( TextLabel3 );
+
+ nameData = new QLineEdit( this, "nameData" );
+ hbox->addWidget( nameData );
+
+ typeData = new QComboBox( FALSE, this, "typeData" );
+ typeData->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0 ) );
+ connect( typeData, SIGNAL( activated( const QString & ) ), this, SLOT( checkConsistency() ) );
+ connect( typeData, SIGNAL( highlighted( const QString & ) ), this, SLOT( checkConsistency() ) );
+ hbox->addWidget( typeData );
+
+ grid->addLayout( hbox, 1, 0 );
+
+ hbox_2 = new QHBoxLayout;
+ hbox_2->setSpacing( 6 );
+ hbox_2->setMargin( 0 );
+
+ TextLabel5 = new QLabel( this, "TextLabel5" );
+ TextLabel5->setText( i18n( "In directory" ) );
+ hbox_2->addWidget( TextLabel5 );
+
+ dirData = new QLineEdit( this, "dirData" );
+ hbox_2->addWidget( dirData );
+
+ browseButton = new QToolButton( this, "browseButton" );
+ browseButton->setIconSet( SmallIcon( "fileopen" ) );
+ hbox_2->addWidget( browseButton );
+ QSpacerItem* spacer = new QSpacerItem( 48, 20, QSizePolicy::Fixed, QSizePolicy::Fixed );
+ hbox_2->addItem( spacer );
+
+ grid->addLayout( hbox_2, 2, 0 );
+
+ hbox_3 = new QHBoxLayout;
+ hbox_3->setSpacing( 6 );
+ hbox_3->setMargin( 0 );
+
+ PixmapLabel1 = new QLabel( this, "PixmapLabel1" );
+ PixmapLabel1->setPixmap( krLoader->loadIcon("package", KIcon::Desktop, 32) );
+ PixmapLabel1->setScaledContents( TRUE );
+ PixmapLabel1->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)0, (QSizePolicy::SizeType)0 ) );
+ hbox_3->addWidget( PixmapLabel1 );
+
+ TextLabel1 = new QLabel( this, "TextLabel1" );
+ TextLabel1->setText( i18n( "Pack" ) );
+ hbox_3->addWidget( TextLabel1 );
+
+ grid->addLayout( hbox_3, 0, 0 );
+
+
+ hbox_4 = new QHBoxLayout;
+ hbox_4->setSpacing( 6 );
+ hbox_4->setMargin( 0 );
+
+ QSpacerItem* spacer_3 = new QSpacerItem( 20, 26, QSizePolicy::Fixed, QSizePolicy::Expanding );
+ hbox_4->addItem( spacer_3 );
+ grid->addLayout( hbox_4, 3, 0 );
+
+ advancedWidget = new QWidget( this, "advancedWidget" );
+
+ hbox_5 = new QGridLayout( advancedWidget );
+ hbox_5->setSpacing( 6 );
+ hbox_5->setMargin( 0 );
+
+
+ QVBoxLayout *compressLayout = new QVBoxLayout;
+ compressLayout->setSpacing( 6 );
+ compressLayout->setMargin( 0 );
+
+ multipleVolume = new QCheckBox( i18n( "Multiple volume archive" ), advancedWidget, "multipleVolume" );
+ connect( multipleVolume, SIGNAL( toggled( bool ) ), this, SLOT( checkConsistency() ) );
+ compressLayout->addWidget( multipleVolume, 0, 0 );
+
+ QHBoxLayout * volumeHbox = new QHBoxLayout;
+
+ QSpacerItem* spacer_5 = new QSpacerItem( 20, 26, QSizePolicy::Fixed, QSizePolicy::Fixed );
+ volumeHbox->addItem( spacer_5 );
+
+ TextLabel7 = new QLabel( i18n("Size:" ), advancedWidget, "TextLabel7" );
+ volumeHbox->addWidget( TextLabel7 );
+
+ volumeSpinBox = new QSpinBox( advancedWidget, "volumeSpinBox" );
+ volumeSpinBox->setMinValue( 1 );
+ volumeSpinBox->setMaxValue( 9999 );
+ volumeSpinBox->setValue( 1440 );
+ volumeHbox->addWidget( volumeSpinBox );
+
+ volumeUnitCombo = new QComboBox( FALSE, advancedWidget, "volumeUnitCombo" );
+ volumeUnitCombo->insertItem( "B" );
+ volumeUnitCombo->insertItem( "KB" );
+ volumeUnitCombo->insertItem( "MB" );
+ volumeUnitCombo->setCurrentItem( 1 );
+ volumeHbox->addWidget( volumeUnitCombo );
+
+ compressLayout->addLayout ( volumeHbox );
+
+ setCompressionLevel = new QCheckBox( i18n( "Set compression level" ), advancedWidget, "multipleVolume" );
+ connect( setCompressionLevel, SIGNAL( toggled( bool ) ), this, SLOT( checkConsistency() ) );
+ compressLayout->addWidget( setCompressionLevel, 0, 0 );
+
+ QHBoxLayout * sliderHbox = new QHBoxLayout;
+
+ QSpacerItem* spacer_6 = new QSpacerItem( 20, 26, QSizePolicy::Fixed, QSizePolicy::Fixed );
+ sliderHbox->addItem( spacer_6 );
+
+ QVBox * sliderVBox = new QVBox( advancedWidget );
+
+ compressionSlider = new QSlider( 1, 9, 1, 5, Qt::Horizontal, sliderVBox, "compressionSlider" );
+ compressionSlider->setTickmarks( QSlider::Below );
+
+ QHBox * minmaxHBox = new QHBox( sliderVBox );
+ minLabel = new QLabel( i18n("MIN"), minmaxHBox );
+ maxLabel = new QLabel( i18n("MAX"), minmaxHBox );
+ maxLabel->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
+
+ sliderHbox->addWidget( sliderVBox );
+
+ compressLayout->addLayout( sliderHbox );
+
+ compressLayout->addStretch( 0 );
+ hbox_5->addLayout( compressLayout, 0, 0 );
+
+ QFrame *vline = new QFrame( advancedWidget, "vline" );
+ vline->setFrameStyle( QFrame::VLine | QFrame::Sunken );
+ vline->setMinimumWidth( 20 );
+ hbox_5->addWidget( vline, 0, 1 );
+
+
+ QGridLayout * passwordGrid = new QGridLayout;
+ passwordGrid->setSpacing( 6 );
+ passwordGrid->setMargin( 0 );
+
+ TextLabel4 = new QLabel( advancedWidget, "TextLabel4" );
+ TextLabel4->setText( i18n( "Password" ) );
+ passwordGrid->addWidget( TextLabel4, 0, 0 );
+
+ password = new QLineEdit( advancedWidget, "password" );
+ password->setEchoMode( QLineEdit::Password );
+ connect( password, SIGNAL( textChanged ( const QString & ) ), this, SLOT( checkConsistency() ) );
+
+ passwordGrid->addWidget( password, 0, 1 );
+
+ TextLabel6 = new QLabel( advancedWidget, "TextLabel6" );
+ TextLabel6->setText( i18n( "Again" ) );
+ passwordGrid->addWidget( TextLabel6, 1, 0 );
+
+ passwordAgain = new QLineEdit( advancedWidget, "password" );
+ passwordAgain->setEchoMode( QLineEdit::Password );
+ connect( passwordAgain, SIGNAL( textChanged ( const QString & ) ), this, SLOT( checkConsistency() ) );
+
+ passwordGrid->addWidget( passwordAgain, 1, 1 );
+
+ QHBoxLayout *consistencyHbox = new QHBoxLayout;
+
+ QSpacerItem* spacer_cons = new QSpacerItem( 48, 20, QSizePolicy::Expanding, QSizePolicy::Fixed );
+ consistencyHbox->addItem( spacer_cons );
+
+ passwordConsistencyLabel = new QLabel( advancedWidget, "passwordConsistencyLabel" );
+ consistencyHbox->addWidget( passwordConsistencyLabel );
+ passwordGrid->addMultiCellLayout ( consistencyHbox, 2, 2, 0, 1 );
+
+ encryptHeaders = new QCheckBox( i18n( "Encrypt headers" ), advancedWidget, "encryptHeaders" );
+ passwordGrid->addMultiCellWidget ( encryptHeaders, 3, 3, 0, 1 );
+
+ QSpacerItem* spacer_psw = new QSpacerItem( 20, 20, QSizePolicy::Fixed, QSizePolicy::Expanding );
+ passwordGrid->addItem( spacer_psw, 4, 0 );
+
+ hbox_5->addLayout( passwordGrid, 0, 2 );
+
+ hbox_7 = new QHBoxLayout;
+ hbox_7->setSpacing( 6 );
+ hbox_7->setMargin( 0 );
+
+ TextLabel8 = new QLabel( i18n( "Command line switches:" ), advancedWidget, "TextLabel8" );
+ TextLabel8->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ hbox_7->addWidget( TextLabel8 );
+
+ commandLineSwitches = new KHistoryCombo( advancedWidget, "commandLineSwitches" );
+ commandLineSwitches->setMaxCount(25); // remember 25 items
+ commandLineSwitches->setDuplicatesEnabled(false);
+ krConfig->setGroup("Archives");
+ QStringList list = krConfig->readListEntry("Command Line Switches");
+ commandLineSwitches->setHistoryItems(list);
+
+ hbox_7->addWidget( commandLineSwitches );
+
+ hbox_5->addMultiCellLayout( hbox_7, 1, 1, 0, 2 );
+
+
+ advancedWidget->hide();
+ checkConsistency();
+
+ grid->addWidget( advancedWidget, 4, 0 );
+
+ hbox_6 = new QHBoxLayout;
+ hbox_6->setSpacing( 6 );
+ hbox_6->setMargin( 0 );
+
+ advancedButton = new QPushButton( this, "advancedButton" );
+ advancedButton->setText( i18n( "&Advanced" ) + " >>" );
+ hbox_6->addWidget( advancedButton );
+
+ QSpacerItem* spacer_2 = new QSpacerItem( 140, 20, QSizePolicy::Expanding, QSizePolicy::Fixed );
+ hbox_6->addItem( spacer_2 );
+
+ okButton = new QPushButton( this, "okButton" );
+ okButton->setText( i18n( "Ok" ) );
+ okButton->setDefault( true );
+ hbox_6->addWidget( okButton );
+
+ cancelButton = new QPushButton( this, "cancelButton" );
+ cancelButton->setText( i18n( "Cancel" ) );
+ hbox_6->addWidget( cancelButton );
+
+ grid->addLayout( hbox_6, 6, 0 );
+
+ // signals and slots connections
+ connect( okButton, SIGNAL( clicked() ), this, SLOT( accept() ) );
+ connect( advancedButton, SIGNAL( clicked() ), this, SLOT( expand() ) );
+ connect( cancelButton, SIGNAL( clicked() ), this, SLOT( reject() ) );
+ connect( browseButton, SIGNAL( clicked() ), this, SLOT( browse() ) );
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+PackGUIBase::~PackGUIBase()
+{
+ // no need to delete child widgets, Qt does it all for us
+}
+
+void PackGUIBase::browse()
+{
+ qWarning( "PackGUIBase::browse(): Not implemented yet!" );
+}
+
+void PackGUIBase::expand() {
+ expanded = !expanded;
+
+ advancedButton->setText( i18n( "&Advanced" ) + ( expanded ? " <<" : " >>" ) );
+
+ if( expanded )
+ advancedWidget->show();
+ else {
+ advancedWidget->hide();
+ layout()->activate();
+ QSize minSize = minimumSize();
+ resize( width(), minSize.height() );
+ }
+ show();
+}
+
+void PackGUIBase::checkConsistency() {
+ if( password->text().isEmpty() && passwordAgain->text().isEmpty()) {
+ passwordConsistencyLabel->setPaletteForegroundColor( KGlobalSettings::textColor() );
+ passwordConsistencyLabel->setText( i18n( "No password specified" ) );
+ }
+ else
+ if( password->text() == passwordAgain->text() ) {
+ passwordConsistencyLabel->setPaletteForegroundColor( KGlobalSettings::textColor() );
+ passwordConsistencyLabel->setText( i18n( "The passwords are equal" ) );
+ }
+ else {
+ passwordConsistencyLabel->setPaletteForegroundColor( Qt::red );
+ passwordConsistencyLabel->setText( i18n( "The passwords are different" ) );
+ }
+
+ QString packer = typeData->currentText();
+
+ bool passworded = false;
+ if( packer == "7z" || packer == "rar" || packer == "zip" || packer == "arj" )
+ passworded = true;
+
+ passwordConsistencyLabel->setEnabled( passworded );
+ password->setEnabled( passworded );
+ passwordAgain->setEnabled( passworded );
+ TextLabel4->setEnabled( passworded );
+ TextLabel6->setEnabled( passworded );
+
+ encryptHeaders->setEnabled( packer == "rar" );
+
+ multipleVolume->setEnabled( packer == "rar" || packer == "arj" );
+ bool volumeEnabled = multipleVolume->isEnabled() && multipleVolume->isChecked();
+ volumeSpinBox->setEnabled( volumeEnabled );
+ volumeUnitCombo->setEnabled( volumeEnabled );
+ TextLabel7->setEnabled( volumeEnabled );
+
+ /* TODO */
+ setCompressionLevel->setEnabled( packer == "rar" || packer == "arj" || packer == "zip" ||
+ packer == "7z" );
+ bool sliderEnabled = setCompressionLevel->isEnabled() && setCompressionLevel->isChecked();
+ compressionSlider->setEnabled( sliderEnabled );
+ minLabel->setEnabled( sliderEnabled );
+ maxLabel->setEnabled( sliderEnabled );
+}
+
+bool PackGUIBase::extraProperties( QMap<QString,QString> & inMap ) {
+ inMap.clear();
+
+ if( password->isEnabled() && passwordAgain->isEnabled() ) {
+ if( password->text() != passwordAgain->text() ) {
+ KMessageBox::error( this, i18n( "Cannot pack! The passwords are different!" ) );
+ return false;
+ }
+
+ if( !password->text().isEmpty() ) {
+ inMap[ "Password" ] = password->text();
+
+ if( encryptHeaders->isEnabled() && encryptHeaders->isChecked() )
+ inMap[ "EncryptHeaders" ] = "1";
+ }
+ }
+
+ if( multipleVolume->isEnabled() && multipleVolume->isChecked() ) {
+ KIO::filesize_t size = volumeSpinBox->value();
+
+ switch( volumeUnitCombo->currentItem() ) {
+ case 2:
+ size *= 1000;
+ case 1:
+ size *= 1000;
+ default:
+ break;
+ }
+
+ if( size < 10000 ) {
+ KMessageBox::error( this, i18n( "Invalid volume size!" ) );
+ return false;
+ }
+
+ QString sbuffer;
+ sbuffer.sprintf("%llu",size);
+
+ inMap[ "VolumeSize" ] = sbuffer;
+ }
+
+ if( setCompressionLevel->isEnabled() && setCompressionLevel->isChecked() ) {
+ inMap[ "CompressionLevel" ] = QString("%1").arg( compressionSlider->value() );
+ }
+
+ QString cmdArgs = commandLineSwitches->currentText().stripWhiteSpace();
+ if( !cmdArgs.isEmpty() ) {
+ bool firstChar = true;
+ QChar quote = '\0';
+
+ for( unsigned i=0; i < cmdArgs.length(); i++ ) {
+ QChar ch( cmdArgs[ i ] );
+ if( ch.isSpace() )
+ continue;
+
+ if( ch == quote ) {
+ quote = '\0';
+ continue;
+ }
+
+ if( firstChar && ch != '-' ) {
+ KMessageBox::error( this, i18n( "Invalid command line switch!\nSwitch must start with '-'!" ) );
+ return false;
+ }
+
+ firstChar = false;
+
+ if( quote == '"' )
+ continue;
+ if( quote == '\0' && ( ch == '\'' || ch == '"' ) )
+ quote = ch;
+ if( ch == '\\' ) {
+ if( i == cmdArgs.length() - 1 ) {
+ KMessageBox::error( this, i18n( "Invalid command line switch!\nBackslash cannot be the last character" ) );
+ return false;
+ }
+ i++;
+ }
+ }
+
+ if( quote != '\0' ) {
+ KMessageBox::error( this, i18n( "Invalid command line switch!\nUnclosed quotation mark!" ) );
+ return false;
+ }
+
+ commandLineSwitches->addToHistory( cmdArgs );
+ QStringList list = commandLineSwitches->historyItems();
+ krConfig->setGroup("Archives");
+ krConfig->writeEntry("Command Line Switches", list);
+
+ inMap[ "CommandLineSwitches" ] = cmdArgs;
+ }
+ return true;
+}
+
+#include "packguibase.moc"
diff --git a/krusader/Dialogs/packguibase.h b/krusader/Dialogs/packguibase.h
new file mode 100644
index 0000000..74364a6
--- /dev/null
+++ b/krusader/Dialogs/packguibase.h
@@ -0,0 +1,109 @@
+/***************************************************************************
+ packguibase.h
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef PACKGUIBASE_H
+#define PACKGUIBASE_H
+
+#include <klocale.h>
+#include <qdialog.h>
+#include <qmap.h>
+
+
+class QVBoxLayout;
+class QHBoxLayout;
+class QGridLayout;
+class QCheckBox;
+class QComboBox;
+class QLabel;
+class QLineEdit;
+class QPushButton;
+class QToolButton;
+class QSpinBox;
+class QSlider;
+class KHistoryCombo;
+
+class PackGUIBase : public QDialog
+{
+ Q_OBJECT
+
+public:
+ PackGUIBase( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 );
+ ~PackGUIBase();
+
+ QLabel* TextLabel3;
+ QLineEdit* nameData;
+ QComboBox* typeData;
+ QLabel* TextLabel5;
+ QLineEdit* dirData;
+ QToolButton* browseButton;
+ QWidget* advancedWidget;
+ QLabel* PixmapLabel1;
+ QLabel* TextLabel1;
+ QLabel* TextLabel4;
+ QLabel* TextLabel6;
+ QLabel* TextLabel7;
+ QLabel* TextLabel8;
+ QLabel* minLabel;
+ QLabel* maxLabel;
+ QLineEdit* password;
+ QLineEdit* passwordAgain;
+ QLabel* passwordConsistencyLabel;
+ QPushButton* okButton;
+ QPushButton* cancelButton;
+ QPushButton* advancedButton;
+ QCheckBox* encryptHeaders;
+ QCheckBox* multipleVolume;
+ QSpinBox* volumeSpinBox;
+ QComboBox* volumeUnitCombo;
+ QCheckBox* setCompressionLevel;
+ QSlider* compressionSlider;
+ KHistoryCombo *commandLineSwitches;
+
+public slots:
+ virtual void browse();
+ virtual bool extraProperties( QMap<QString,QString> & );
+
+ void expand();
+ void checkConsistency();
+
+protected:
+ QHBoxLayout* hbox;
+ QHBoxLayout* hbox_2;
+ QHBoxLayout* hbox_3;
+ QHBoxLayout* hbox_4;
+ QGridLayout* hbox_5;
+ QHBoxLayout* hbox_6;
+ QHBoxLayout* hbox_7;
+ QGridLayout* grid;
+
+private:
+ bool expanded;
+};
+
+#endif // PACKGUIBASE_H
diff --git a/krusader/Dialogs/percentalsplitter.cpp b/krusader/Dialogs/percentalsplitter.cpp
new file mode 100644
index 0000000..3a1354f
--- /dev/null
+++ b/krusader/Dialogs/percentalsplitter.cpp
@@ -0,0 +1,193 @@
+/***************************************************************************
+ percentalsplitter.h - description
+ -------------------
+ copyright : (C) 2006 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "percentalsplitter.h"
+#include <qtooltip.h>
+#include <qpainter.h>
+#include <qapplication.h>
+
+class PercentalSplitterToolTip : public QToolTip {
+public:
+ PercentalSplitterToolTip( QWidget * parent ) : QToolTip( parent ) {
+ }
+
+ virtual ~PercentalSplitterToolTip() {
+ remove( parentWidget() );
+ }
+
+ void maybeTip( const QPoint & point ) {
+ if( parentWidget()->inherits( "PercentalSplitter" ) ) {
+ PercentalSplitter *splitter = (PercentalSplitter *)parentWidget();
+
+ QString tipString = splitter->toolTipString();
+ QRect rect = QRect( parentWidget()->rect() );
+
+ if( splitter->orientation() == Qt::Vertical ) {
+ rect.setY( splitter->sizes()[ 0 ] );
+ rect.setHeight( splitter->handleWidth() );
+ }
+ else {
+ rect.setX( splitter->sizes()[ 0 ] );
+ rect.setWidth( splitter->handleWidth() );
+ }
+ if( rect.contains( point ) )
+ tip( rect, tipString );
+ }
+ }
+};
+
+PercentalSplitter::PercentalSplitter( QWidget * parent, const char * name ) : QSplitter( parent, name ), label( 0 ), opaqueOldPos( -1 ) {
+ toolTip = new PercentalSplitterToolTip( this );
+}
+
+PercentalSplitter::~PercentalSplitter() {
+ delete toolTip;
+}
+
+QString PercentalSplitter::toolTipString( int p ) {
+ QValueList<int> values = sizes();
+ if( values.count() == 2 && ( values[ 0 ] + values[ 1 ] != 0 ) ) {
+ if( p < 0 )
+ p = values[ 0 ];
+ int percent = (int)(((double)p / (double)( values[ 0 ] + values[ 1 ] )) * 10000. + 0.5);
+ return QString( "%1.%2%3" ).arg( percent / 100 ).arg( ( percent / 10 )%10 ).arg( percent % 10 ) + "%";
+ }
+ return QString::null;
+}
+
+void PercentalSplitter::setRubberband ( int p ) {
+ if( p == opaqueOldPos )
+ return;
+
+ QPainter paint( this );
+ paint.setPen( gray );
+ paint.setBrush( gray );
+ paint.setRasterOp( XorROP );
+ QRect r = contentsRect();
+ const int rBord = 3; // customizable?
+ int hw = handleWidth();
+
+ if( orientation() == Qt::Horizontal ) {
+ if ( opaqueOldPos >= 0 ) {
+ if( label == 0 )
+ paint.drawRect( opaqueOldPos + hw / 2 - rBord, r.y(), 2 * rBord, r.height() );
+ else {
+ QPoint labelLoc = mapFromGlobal( labelLocation );
+ if( labelLoc.y() > r.y() )
+ paint.drawRect( opaqueOldPos + hw / 2 - rBord, r.y(), 2 * rBord, labelLoc.y() );
+ if( labelLoc.y() + label->height() < r.height() )
+ paint.drawRect( opaqueOldPos + hw / 2 - rBord, labelLoc.y() + label->height(), 2 * rBord, r.height() - labelLoc.y() - label->height() );
+ }
+ }
+ } else {
+ if ( opaqueOldPos >= 0 ) {
+ if( label == 0 )
+ paint.drawRect( r.x(), opaqueOldPos + hw / 2 - rBord, r.width(), 2 * rBord );
+ else {
+ QPoint labelLoc = mapFromGlobal( labelLocation );
+ if( labelLoc.x() > r.x() )
+ paint.drawRect( r.x(), opaqueOldPos + hw / 2 - rBord, labelLoc.x(), 2 * rBord );
+ if( labelLoc.x() + label->width() < r.width() )
+ paint.drawRect( labelLoc.x() + label->width(), opaqueOldPos + hw / 2 - rBord, r.width() - labelLoc.x() - label->width(), 2 * rBord );
+ }
+ }
+ }
+
+ if( p < 0 ) {
+ if( label ) {
+ delete label;
+ label = 0;
+ }
+ }
+ else {
+ int scr = QApplication::desktop()->screenNumber( this );
+
+ if( label == 0 ) {
+ label = new QLabel( QApplication::desktop()->screen( scr ), "SplitterPercent", WStyle_StaysOnTop |
+ WStyle_Customize | WStyle_NoBorder | WStyle_Tool | WX11BypassWM );
+ label->setMargin(1);
+ label->setAutoMask( FALSE );
+ label->setFrameStyle( QFrame::Plain | QFrame::Box );
+ label->setLineWidth( 1 );
+ label->setAlignment( AlignAuto | AlignTop );
+ label->setIndent(0);
+
+ QFontMetrics fm = label->fontMetrics();
+ label->setMinimumWidth( fm.width( "99.99%" ) + 5 );
+
+ label->polish();
+ }
+
+ label->setText( toolTipString( p ) );
+ label->adjustSize();
+
+ if( orientation() == Qt::Horizontal ) {
+ labelLocation = mapToGlobal( QPoint( p - label->width()/2, r.y() + r.height()/2 ) );
+ if( labelLocation.x() < 0 )
+ labelLocation.setX( 0 );
+ } else {
+ labelLocation = mapToGlobal( QPoint( r.x() + r.width()/2, p - label->height()/2 ) );
+ if( labelLocation.y() < 0 )
+ labelLocation.setY( 0 );
+ }
+
+#ifdef Q_WS_MAC
+ QRect screen = QApplication::desktop()->availableGeometry( scr );
+#else
+ QRect screen = QApplication::desktop()->screenGeometry( scr );
+#endif
+
+ QPoint labelLoc = mapFromGlobal( labelLocation );
+ if( orientation() == Qt::Horizontal ) {
+ if( labelLocation.x() + label->width() > screen.width() )
+ labelLocation.setX( screen.width() - label->width() );
+ label->move( labelLocation );
+ label->show();
+
+ if( labelLoc.y() > r.y() )
+ paint.drawRect( p + hw / 2 - rBord, r.y(), 2 * rBord, labelLoc.y() );
+ if( labelLoc.y() + label->height() < r.height() )
+ paint.drawRect( p + hw / 2 - rBord, labelLoc.y() + label->height(), 2 * rBord, r.height() - labelLoc.y() - label->height() );
+ } else {
+ if( labelLocation.y() + label->height() > screen.height() )
+ labelLocation.setY( screen.height() - label->height() );
+ label->move( labelLocation );
+ label->show();
+
+ if( labelLoc.x() > r.x() )
+ paint.drawRect( r.x(), p + hw / 2 - rBord, labelLoc.x(), 2 * rBord );
+ if( labelLoc.x() + label->width() < r.width() )
+ paint.drawRect( labelLoc.x() + label->width(), p + hw / 2 - rBord, r.width() - labelLoc.x() - label->width(), 2 * rBord );
+ }
+ }
+ opaqueOldPos = p;
+}
+
+#include "percentalsplitter.moc"
diff --git a/krusader/Dialogs/percentalsplitter.h b/krusader/Dialogs/percentalsplitter.h
new file mode 100644
index 0000000..cdbfb4d
--- /dev/null
+++ b/krusader/Dialogs/percentalsplitter.h
@@ -0,0 +1,58 @@
+/***************************************************************************
+ percentalsplitter.h - description
+ -------------------
+ copyright : (C) 2006 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __PERCENTAL_SPLITTER__
+#define __PERCENTAL_SPLITTER__
+
+#include <qsplitter.h>
+#include <qlabel.h>
+
+class PercentalSplitterToolTip;
+
+class PercentalSplitter : public QSplitter {
+ Q_OBJECT
+
+public:
+ PercentalSplitter( QWidget * parent = 0, const char * name = 0 );
+ virtual ~PercentalSplitter();
+
+ QString toolTipString( int p = -1 );
+
+protected:
+ virtual void setRubberband ( int p );
+
+private:
+ PercentalSplitterToolTip * toolTip;
+ QLabel * label;
+ int opaqueOldPos;
+ QPoint labelLocation;
+};
+
+#endif /* __PERCENTAL_SPLITTER__ */
diff --git a/krusader/Dialogs/popularurls.cpp b/krusader/Dialogs/popularurls.cpp
new file mode 100644
index 0000000..45b6162
--- /dev/null
+++ b/krusader/Dialogs/popularurls.cpp
@@ -0,0 +1,307 @@
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <qpushbutton.h>
+#include <klistview.h>
+#include <kiconloader.h>
+#include <klistviewsearchline.h>
+#include <qheader.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <ktoolbarbutton.h>
+#include "../krusader.h"
+#include "../krslots.h"
+#include "popularurls.h"
+
+#define STARTING_RANK 20
+#define INCREASE 2
+#define DECREASE 1
+
+PopularUrls::PopularUrls(QObject *parent, const char *name) : QObject(parent, name),
+ head(0), tail(0), count(0) {
+ dlg = new PopularUrlsDlg();
+}
+
+PopularUrls::~PopularUrls() {
+ clearList();
+ delete dlg;
+}
+
+void PopularUrls::clearList() {
+ if (head) {
+ UrlNodeP p=head, tmp;
+ while (p) {
+ tmp = p;
+ p=p->next;
+ delete tmp;
+ }
+ }
+ ranks.clear();
+ head = tail = 0;
+}
+
+void PopularUrls::save() {
+ KConfigGroupSaver svr(krConfig, "Private");
+ // prepare the string list containing urls and int list with ranks
+ QStringList urlList;
+ QValueList<int> rankList;
+ UrlNodeP p = head;
+ while (p) {
+ urlList << p->url.prettyURL();
+ rankList << p->rank;
+ p = p->next;
+ }
+ krConfig->writeEntry("PopularUrls", urlList);
+ krConfig->writeEntry("PopularUrlsRank", rankList);
+}
+
+void PopularUrls::load() {
+ KConfigGroupSaver svr(krConfig, "Private");
+ QStringList urlList = krConfig->readListEntry("PopularUrls");
+ QValueList<int> rankList = krConfig->readIntListEntry("PopularUrlsRank");
+ if (urlList.count() != rankList.count()) {
+ KMessageBox::error(krApp, i18n("Saved 'Popular Urls' are invalid. List will be cleared"));
+ return;
+ }
+ clearList();
+ count = 0;
+ // iterate through both lists and
+ QStringList::Iterator uit;
+ QValueList<int>::Iterator rit;
+ for (uit=urlList.begin(), rit=rankList.begin(); uit!=urlList.end() && rit!=rankList.end(); ++uit, ++rit) {
+ UrlNodeP node = new UrlNode;
+ node->url = KURL::fromPathOrURL( *uit );
+ node->rank = *rit;
+ appendNode(node);
+ ranks.insert(*uit, node);
+ }
+}
+
+
+// returns a url list with the 'max' top popular urls
+KURL::List PopularUrls::getMostPopularUrls(int max) {
+ // get at most 'max' urls
+ KURL::List list;
+ UrlNodeP p = head;
+ int tmp = 0;
+ if (maxUrls < max) max = maxUrls; // don't give more than maxUrls
+ while (p && tmp < max) {
+ list << p->url;
+ p = p->next;
+ ++tmp;
+ }
+
+ return list;
+}
+
+// adds a url to the list, or increase rank of an existing url, making
+// sure to bump it up the list if needed
+void PopularUrls::addUrl(const KURL& url) {
+ KURL tmpurl = url;
+ tmpurl.adjustPath(1); // make a uniform trailing slash policy
+ UrlNodeP pnode;
+
+ decreaseRanks();
+ if (!head) { // if the list is empty ... (assumes dict to be empty as well)
+ pnode = new UrlNode;
+ pnode->rank = STARTING_RANK;
+ pnode->url = tmpurl;
+ appendNode(pnode);
+ ranks.insert(tmpurl.url(), head);
+ } else {
+ pnode = ranks.find(tmpurl.url());
+ if (!pnode) { // is the added url new? if so, append it
+ pnode = new UrlNode;
+ pnode->rank = STARTING_RANK;
+ pnode->url = tmpurl;
+ appendNode(pnode);
+ ranks.insert(tmpurl.url(), pnode);
+ } else {
+ pnode->rank += INCREASE;
+ }
+ }
+
+ // do we need to change location for this one?
+ relocateIfNeeded(pnode);
+
+ // too many urls?
+ if (count > maxUrls) removeNode(tail);
+
+ //dumpList();
+}
+
+// checks if 'node' needs to be bumped-up the ranking list and does it if needed
+void PopularUrls::relocateIfNeeded(UrlNodeP node) {
+ if (node->prev && (node->prev->rank < node->rank)) {
+ // iterate until we find the correct place to put it
+ UrlNodeP tmp = node->prev->prev;
+ while (tmp) {
+ if (tmp->rank >= node->rank)
+ break; // found it!
+ else tmp = tmp->prev;
+ }
+ // now, if tmp isn't null, we need to move node to tmp->next
+ // else move it to become head
+ removeNode(node);
+ insertNode(node, tmp);
+ }
+}
+
+
+// iterate over the list, decreasing each url's rank
+// this is very naive, but a 1..30 for loop is acceptable (i hope)
+void PopularUrls::decreaseRanks() {
+ if (head) {
+ UrlNodeP p=head;
+ while (p) {
+ if (p->rank-DECREASE>=0)
+ p->rank -= DECREASE;
+ else p->rank = 0;
+ p=p->next;
+ }
+ }
+}
+
+// removes a node from the list, but doesn't free memory!
+// note: this will be buggy in case the list becomes empty (which should never happen)
+void PopularUrls::removeNode(UrlNodeP node) {
+ if (node->prev) {
+ if (tail == node) tail = node->prev;
+ node->prev->next = node->next;
+ }
+ if (node->next) {
+ if (head == node) head = node->next;
+ node->next->prev = node->prev;
+ }
+ --count;
+}
+
+void PopularUrls::insertNode(UrlNodeP node, UrlNodeP after) {
+ if (!after) { // make node head
+ node->next = head;
+ node->prev = 0;
+ head->prev = node;
+ head = node;
+ } else {
+ if (tail == after) tail = node;
+ node->prev = after;
+ node->next = after->next;
+ if( node->next ) {
+ after->next->prev = node;
+ after->next = node;
+ }
+ }
+ ++count;
+}
+
+// appends 'node' to the end of the list, collecting garbage if needed
+void PopularUrls::appendNode(UrlNodeP node) {
+ if (!tail) { // creating the first element
+ head = tail = node;
+ node->prev = node->next = 0;
+ } else {
+ node->next = 0;
+ node->prev = tail;
+ tail->next = node;
+ tail = node;
+ }
+ ++count;
+}
+
+void PopularUrls::dumpList() {
+ UrlNodeP p = head;
+ printf("====start %d====\n",count);
+ while (p) {
+ printf("%d : %s\n", p->rank, p->url.url().latin1());
+ p = p->next;
+ }
+ fflush(stdout);
+}
+
+void PopularUrls::showDialog() {
+ KURL::List list = getMostPopularUrls(maxUrls);
+ dlg->run(list);
+ if (dlg->result() == -1) return;
+ SLOTS->refresh(list[dlg->result()]);
+ //printf("running %s\n", list[dlg->result()].url().latin1());fflush(stdout);
+}
+
+// ===================================== PopularUrlsDlg ======================================
+PopularUrlsDlg::PopularUrlsDlg():
+ KDialogBase(Plain, i18n("Popular Urls"), Close, KDialogBase::NoDefault, krApp) {
+ QGridLayout *layout = new QGridLayout( plainPage(), 0, KDialog::spacingHint() );
+
+ // listview to contain the urls
+ urls = new KListView(plainPage());
+ urls->header()->hide();
+ urls->addColumn("");
+ urls->setSorting(-1);
+ urls->setVScrollBarMode(QScrollView::AlwaysOn);
+
+ // quick search
+ QToolButton *btn = new QToolButton(plainPage());
+ btn->setIconSet(SmallIcon("locationbar_erase"));
+ search = new KListViewSearchLine(plainPage(), urls);
+ search->setTrapReturnKey(true);
+ QLabel *lbl = new QLabel(search, i18n(" &Search: "), plainPage());
+
+ layout->addWidget(btn,0,0);
+ layout->addWidget(lbl,0,1);
+ layout->addWidget(search,0,2);
+ layout->addMultiCellWidget(urls,1,1,0,2);
+ setMaximumSize(600, 500);
+
+ setTabOrder(search, urls);
+ setTabOrder(urls, actionButton(Close));
+
+ connect(urls, SIGNAL(executed(QListViewItem*)),
+ this, SLOT(slotItemSelected(QListViewItem*)));
+ connect(urls, SIGNAL(returnPressed(QListViewItem*)),
+ this, SLOT(slotItemSelected(QListViewItem*)));
+ connect(btn, SIGNAL(clicked()), search, SLOT(clear()));
+ connect(search, SIGNAL(returnPressed(const QString&)),
+ this, SLOT(slotSearchReturnPressed(const QString&)));
+}
+
+void PopularUrlsDlg::slotItemSelected(QListViewItem *it) {
+ selection = urls->itemIndex(it);
+ accept();
+}
+
+void PopularUrlsDlg::slotSearchReturnPressed(const QString&) {
+ urls->setFocus();
+ // select the first visible item
+ QListViewItemIterator it( urls );
+ while ( it.current() ) {
+ if ( it.current()->isVisible() ) {
+ urls->setSelected(it.current(), true);
+ urls->setCurrentItem(it.current());
+ break;
+ } else ++it;
+ }
+}
+
+PopularUrlsDlg::~PopularUrlsDlg() {
+ delete search;
+ delete urls;
+}
+
+void PopularUrlsDlg::run(KURL::List list) {
+ // populate the listview
+ urls->clear();
+ KURL::List::Iterator it;
+ for (it = list.begin(); it!=list.end(); ++it) {
+ KListViewItem *item = new KListViewItem(urls, urls->lastItem());
+ item->setText(0, (*it).isLocalFile() ? (*it).path() : (*it).prettyURL());
+ item->setPixmap(0, (*it).isLocalFile() ? SmallIcon("folder") : SmallIcon("folder_html"));
+ }
+ //urls->setCurrentItem(urls->firstChild());
+ //urls->setSelected(urls->firstChild(), true);
+ setMinimumSize(urls->sizeHint().width()+45, 400);
+
+ search->clear();
+ search->setFocus();
+ selection = -1;
+ exec();
+}
+
+#include "popularurls.moc"
diff --git a/krusader/Dialogs/popularurls.h b/krusader/Dialogs/popularurls.h
new file mode 100644
index 0000000..4b908ab
--- /dev/null
+++ b/krusader/Dialogs/popularurls.h
@@ -0,0 +1,84 @@
+#ifndef POPULARURLS_H
+#define POPULARURLS_H
+
+#include <qobject.h>
+#include <kurl.h>
+#include <qdict.h>
+#include <kdialogbase.h>
+
+// the class holds a list of most popular links in a dual data structure
+// * linked list, with head and tail: for fast append/prepend support
+// * dictionary that maps urls to list nodes: to save the need to iterate
+// over the list in order to find the correct node for each new url
+//
+// also, the class holds a maximum number of urls. two variables affect this:
+// * maxUrls - the num. of urls the user can see
+// * hardLimit - the actual number of urls kept.
+// when the number of urls reaches hardLimit, a garbage collection is done and
+// the bottom (hardLimit-maxUrls) entries are removed from the list
+typedef struct _UrlNode* UrlNodeP;
+typedef struct _UrlNode {
+ UrlNodeP prev;
+ KURL url;
+ int rank;
+ UrlNodeP next;
+} UrlNode;
+
+class PopularUrlsDlg;
+
+class PopularUrls : public QObject {
+ Q_OBJECT
+public:
+ PopularUrls(QObject *parent = 0, const char *name = 0);
+ ~PopularUrls();
+ void save();
+ void load();
+ void addUrl(const KURL& url);
+ KURL::List getMostPopularUrls(int max);
+
+public slots:
+ void showDialog();
+
+protected:
+ // NOTE: the following methods append/insert/remove a node to the list
+ // but NEVER free memory or allocate memory!
+ void appendNode(UrlNodeP node);
+ void insertNode(UrlNodeP node, UrlNodeP after);
+ void removeNode(UrlNodeP node);
+ void relocateIfNeeded(UrlNodeP node);
+ void clearList();
+ void dumpList();
+ void decreaseRanks();
+
+private:
+ UrlNodeP head, tail;
+ QDict<UrlNode> ranks; // actually holds UrlNode*
+ int count;
+ static const int maxUrls = 30;
+ PopularUrlsDlg *dlg;
+};
+
+class KListView;
+class KListViewSearchLine;
+
+class PopularUrlsDlg: public KDialogBase {
+ Q_OBJECT
+public:
+ PopularUrlsDlg();
+ ~PopularUrlsDlg();
+ void run(KURL::List list); // use this to open the dialog
+ inline int result() const { return selection; } // returns index 0 - topmost, or -1
+
+
+protected slots:
+ void slotSearchReturnPressed(const QString&);
+ void slotItemSelected(QListViewItem *it);
+
+private:
+ KListView *urls;
+ KListViewSearchLine *search;
+ int selection;
+};
+
+
+#endif
diff --git a/krusader/DiskUsage/Makefile.am b/krusader/DiskUsage/Makefile.am
new file mode 100644
index 0000000..691d045
--- /dev/null
+++ b/krusader/DiskUsage/Makefile.am
@@ -0,0 +1,17 @@
+SUBDIRS = \
+ radialMap \
+ filelightParts
+
+
+noinst_LIBRARIES = libDiskUsage.a
+
+INCLUDES = $(all_includes)
+
+libDiskUsage_a_METASOURCES = AUTO
+
+libDiskUsage_a_SOURCES = \
+ diskusagegui.cpp \
+ diskusage.cpp \
+ dulistview.cpp \
+ dulines.cpp \
+ dufilelight.cpp
diff --git a/krusader/DiskUsage/diskusage.cpp b/krusader/DiskUsage/diskusage.cpp
new file mode 100644
index 0000000..b58f2d6
--- /dev/null
+++ b/krusader/DiskUsage/diskusage.cpp
@@ -0,0 +1,1147 @@
+/***************************************************************************
+ diskusage.cpp - description
+ -------------------
+ copyright : (C) 2004 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <time.h>
+#include <qlayout.h>
+#include <klocale.h>
+#include <kpopupmenu.h>
+#include <kmimetype.h>
+#include <kmessagebox.h>
+#include <kglobalsettings.h>
+#include <kio/job.h>
+#include <qpushbutton.h>
+#include <qhbox.h>
+#include <qapplication.h>
+#include <qcursor.h>
+#include <qpixmapcache.h>
+#include <qgroupbox.h>
+#include <qguardedptr.h>
+#include "diskusage.h"
+#include "../VFS/krpermhandler.h"
+#include "../VFS/krvfshandler.h"
+#include "../kicons.h"
+#include "../defaults.h"
+#include "../krusader.h"
+#include "../krusaderview.h"
+#include "../Panel/listpanel.h"
+#include "../Panel/panelfunc.h"
+#include "filelightParts/Config.h"
+
+#include "dulines.h"
+#include "dulistview.h"
+#include "dufilelight.h"
+
+// these are the values that will exist in the menu
+#define DELETE_ID 90
+#define EXCLUDE_ID 91
+#define PARENT_DIR_ID 92
+#define NEW_SEARCH_ID 93
+#define REFRESH_ID 94
+#define STEP_INTO_ID 95
+#define INCLUDE_ALL_ID 96
+#define VIEW_POPUP_ID 97
+#define LINES_VIEW_ID 98
+#define DETAILED_VIEW_ID 99
+#define FILELIGHT_VIEW_ID 100
+#define NEXT_VIEW_ID 101
+#define PREVIOUS_VIEW_ID 102
+#define ADDITIONAL_POPUP_ID 103
+
+#define MAX_FILENUM 100
+
+LoaderWidget::LoaderWidget( QWidget *parent, const char *name ) : QScrollView( parent, name ), cancelled( false )
+{
+ viewport()->setEraseColor( Qt::white );
+ widget = new QWidget( parent );
+
+ QGridLayout *loaderLayout = new QGridLayout( widget );
+ loaderLayout->setSpacing( 0 );
+ loaderLayout->setMargin( 0 );
+
+ QGroupBox *loaderBox = new QGroupBox( widget, "loaderGroupBox" );
+ loaderBox->setFrameShape( QGroupBox::Box );
+ loaderBox->setFrameShadow( QGroupBox::Sunken );
+ loaderBox->setColumnLayout(0, Qt::Vertical );
+ loaderBox->layout()->setSpacing( 0 );
+ loaderBox->layout()->setMargin( 0 );
+ loaderBox->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ loaderBox->setFrameStyle( QFrame::Panel + QFrame::Raised );
+ loaderBox->setLineWidth( 2 );
+
+ QGridLayout *synchGrid = new QGridLayout( loaderBox->layout() );
+ synchGrid->setSpacing( 6 );
+ synchGrid->setMargin( 11 );
+
+ QLabel *titleLabel = new QLabel( i18n( "Loading Usage Information" ), loaderBox, "titleLabel" );
+ titleLabel->setAlignment( Qt::AlignHCenter );
+ synchGrid->addMultiCellWidget( titleLabel, 0, 0, 0, 1 );
+
+ QLabel *filesLabel = new QLabel( i18n( "Files:" ), loaderBox, "filesLabel" );
+ filesLabel->setFrameShape( QLabel::StyledPanel );
+ filesLabel->setFrameShadow( QLabel::Sunken );
+ synchGrid->addWidget( filesLabel, 1, 0 );
+
+ QLabel *directoriesLabel = new QLabel( i18n( "Directories:" ), loaderBox, "directoriesLabel" );
+ directoriesLabel->setFrameShape( QLabel::StyledPanel );
+ directoriesLabel->setFrameShadow( QLabel::Sunken );
+ synchGrid->addWidget( directoriesLabel, 2, 0 );
+
+ QLabel *totalSizeLabel = new QLabel( i18n( "Total Size:" ), loaderBox, "totalSizeLabel" );
+ totalSizeLabel->setFrameShape( QLabel::StyledPanel );
+ totalSizeLabel->setFrameShadow( QLabel::Sunken );
+ synchGrid->addWidget( totalSizeLabel, 3, 0 );
+
+ files = new QLabel( loaderBox, "files" );
+ files->setFrameShape( QLabel::StyledPanel );
+ files->setFrameShadow( QLabel::Sunken );
+ files->setAlignment( Qt::AlignRight );
+ synchGrid->addWidget( files, 1, 1 );
+
+ directories = new QLabel( loaderBox, "directories" );
+ directories->setFrameShape( QLabel::StyledPanel );
+ directories->setFrameShadow( QLabel::Sunken );
+ directories->setAlignment( Qt::AlignRight );
+ synchGrid->addWidget( directories, 2, 1 );
+
+ totalSize = new QLabel( loaderBox, "totalSize" );
+ totalSize->setFrameShape( QLabel::StyledPanel );
+ totalSize->setFrameShadow( QLabel::Sunken );
+ totalSize->setAlignment( Qt::AlignRight );
+ synchGrid->addWidget( totalSize, 3, 1 );
+
+ int width;
+ searchedDirectory = new KSqueezedTextLabel( loaderBox, "searchedDirectory" );
+ searchedDirectory->setFrameShape( QLabel::StyledPanel );
+ searchedDirectory->setFrameShadow( QLabel::Sunken );
+ searchedDirectory->setMinimumWidth( width = QFontMetrics(searchedDirectory->font()).width("W") * 30 );
+ searchedDirectory->setMaximumWidth( width );
+ synchGrid->addMultiCellWidget( searchedDirectory, 4, 4, 0, 1 );
+
+ QFrame *line = new QFrame( loaderBox, "duLine" );
+ line->setFrameStyle( QFrame::HLine | QFrame::Sunken );
+ synchGrid->addMultiCellWidget( line, 5, 5, 0, 1 );
+
+ QHBox *hbox = new QHBox( loaderBox, "hbox" );
+ QSpacerItem* spacer = new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ hbox->layout()->addItem( spacer );
+ QPushButton *cancelButton = new QPushButton( hbox, "cancelButton" );
+ cancelButton->setText( i18n( "Cancel" ) );
+ synchGrid->addWidget( hbox, 6, 1 );
+
+ loaderLayout->addWidget( loaderBox, 0, 0 );
+
+ addChild( widget );
+
+ connect( cancelButton, SIGNAL( clicked() ), this, SLOT( slotCancelled() ) );
+}
+
+void LoaderWidget::resizeEvent ( QResizeEvent *e )
+{
+ QScrollView::resizeEvent( e );
+
+ int x = ( viewport()->width() - widget->width() ) / 2;
+ int y = ( viewport()->height() - widget->height() ) / 2;
+ if( x < 0 ) x=0;
+ if( y < 0 ) y=0;
+
+ moveChild( widget, x, y );
+}
+
+void LoaderWidget::init()
+{
+ cancelled = false;
+}
+
+void LoaderWidget::setCurrentURL( KURL url )
+{
+ searchedDirectory->setText( vfs::pathOrURL( url, 1) );
+}
+
+void LoaderWidget::setValues( int fileNum, int dirNum, KIO::filesize_t total )
+{
+ files->setText( QString("%1").arg( fileNum ) );
+ directories->setText( QString("%1").arg( dirNum ) );
+ totalSize->setText( QString("%1").arg( KRpermHandler::parseSize( total ).stripWhiteSpace() ) );
+}
+
+void LoaderWidget::slotCancelled()
+{
+ cancelled = true;
+}
+
+DiskUsage::DiskUsage( QString confGroup, QWidget *parent, char *name ) : QWidgetStack( parent, name ),
+ currentDirectory( 0 ), root( 0 ), configGroup( confGroup ), loading( false ),
+ abortLoading( false ), clearAfterAbort( false ), deleting( false ), searchVfs( 0 )
+{
+ listView = new DUListView( this, "DU ListView" );
+ lineView = new DULines( this, "DU LineView" );
+ filelightView = new DUFilelight( this, "Filelight canvas" );
+ loaderView = new LoaderWidget( this, "Loading view" );
+
+ addWidget( listView );
+ addWidget( lineView );
+ addWidget( filelightView );
+ addWidget( loaderView );
+
+ setView( VIEW_LINES );
+
+ Filelight::Config::read();
+ propertyMap.setAutoDelete( true );
+
+ connect( &loadingTimer, SIGNAL( timeout() ), this, SLOT( slotLoadDirectory() ) );
+}
+
+DiskUsage::~DiskUsage()
+{
+ if( root )
+ delete root;
+
+ if( listView ) // don't remove these lines. The module will crash at exit if removed
+ delete listView;
+ if( lineView )
+ delete lineView;
+ if( filelightView )
+ delete filelightView;
+}
+
+void DiskUsage::load( KURL baseDir )
+{
+ if( searchVfs && !searchVfs->vfs_canDelete() ) {
+ return;
+ }
+
+ fileNum = dirNum = 0;
+ currentSize = 0;
+
+ emit status( i18n( "Loading the disk usage information..." ) );
+
+ clear();
+
+ baseURL = baseDir;
+ baseURL.setPath( baseDir.path( -1 ) );
+
+ root = new Directory( baseURL.fileName(), vfs::pathOrURL( baseDir ) );
+
+ directoryStack.clear();
+ parentStack.clear();
+
+ directoryStack.push( "" );
+ parentStack.push( root );
+
+ if( searchVfs )
+ {
+ delete searchVfs;
+ searchVfs = 0;
+ }
+ searchVfs = KrVfsHandler::getVfs( baseDir );
+ if( searchVfs == 0 )
+ {
+ loading = abortLoading = clearAfterAbort = false;
+ emit loadFinished( false );
+ return;
+ }
+
+ searchVfs->vfs_setQuiet( true );
+ currentVfile = 0;
+
+ if( !loading )
+ {
+ viewBeforeLoad = activeView;
+ setView( VIEW_LOADER );
+ }
+
+ loading = true;
+
+ loaderView->init();
+ loaderView->setCurrentURL( baseURL );
+ loaderView->setValues( fileNum, dirNum, currentSize );
+
+ loadingTimer.start( 0, true );
+}
+
+void DiskUsage::slotLoadDirectory()
+{
+ if( searchVfs && !searchVfs->vfs_canDelete() ) { // recursive call from slotLoadDirectory?
+ loadingTimer.start( 100, true ); // as it can cause crash, ignore it and wait while
+ return; // the recursion finishes
+ }
+ if( ( currentVfile == 0 && directoryStack.isEmpty() ) || loaderView->wasCancelled() || abortLoading )
+ {
+ if( searchVfs )
+ delete searchVfs;
+
+ searchVfs = 0;
+ currentVfile = 0;
+
+ setView( viewBeforeLoad );
+
+ if( clearAfterAbort )
+ clear();
+ else {
+ calculateSizes();
+ changeDirectory( root );
+ }
+
+ emit loadFinished( !( loaderView->wasCancelled() || abortLoading ) );
+
+ loading = abortLoading = clearAfterAbort = false;
+ }
+ else if( loading )
+ {
+ for( int counter = 0; counter != MAX_FILENUM; counter ++ )
+ {
+ if( currentVfile == 0 )
+ {
+ if( directoryStack.isEmpty() )
+ break;
+
+ dirToCheck = directoryStack.pop();
+ currentParent = parentStack.pop();
+
+ contentMap.insert( dirToCheck, currentParent );
+
+ KURL url = baseURL;
+
+ if( !dirToCheck.isEmpty() )
+ url.addPath( dirToCheck );
+
+#if defined(BSD)
+ if ( url.isLocalFile() && url.path().left( 7 ) == "/procfs" )
+ break;
+#else
+ if ( url.isLocalFile() && url.path().left( 5 ) == "/proc" )
+ break;
+#endif
+
+ loaderView->setCurrentURL( url );
+
+ if( !searchVfs->vfs_refresh( url ) )
+ break;
+
+ dirNum++;
+
+ currentVfile = searchVfs->vfs_getFirstFile();
+ }
+ else
+ {
+ fileNum++;
+ File *newItem = 0;
+
+ QString mime = currentVfile->vfile_getMime(true); // fast == not using mimetype magic
+
+ if( currentVfile->vfile_isDir() && !currentVfile->vfile_isSymLink() )
+ {
+ newItem = new Directory( currentParent, currentVfile->vfile_getName(), dirToCheck, currentVfile->vfile_getSize(),
+ currentVfile->vfile_getMode(), currentVfile->vfile_getOwner(), currentVfile->vfile_getGroup(),
+ currentVfile->vfile_getPerm(), currentVfile->vfile_getTime_t(), currentVfile->vfile_isSymLink(),
+ mime );
+ directoryStack.push( (dirToCheck.isEmpty() ? "" : dirToCheck + "/" )+ currentVfile->vfile_getName() );
+ parentStack.push( dynamic_cast<Directory *>( newItem ) );
+ }
+ else
+ {
+ newItem = new File( currentParent, currentVfile->vfile_getName(), dirToCheck, currentVfile->vfile_getSize(),
+ currentVfile->vfile_getMode(), currentVfile->vfile_getOwner(), currentVfile->vfile_getGroup(),
+ currentVfile->vfile_getPerm(), currentVfile->vfile_getTime_t(), currentVfile->vfile_isSymLink(),
+ mime );
+ currentSize += currentVfile->vfile_getSize();
+ }
+ currentParent->append( newItem );
+
+ currentVfile = searchVfs->vfs_getNextFile();
+ }
+ }
+
+ loaderView->setValues( fileNum, dirNum, currentSize );
+ loadingTimer.start( 0, true );
+ }
+}
+
+void DiskUsage::stopLoad()
+{
+ abortLoading = true;
+}
+
+void DiskUsage::close()
+{
+ if( loading )
+ {
+ abortLoading = true;
+ clearAfterAbort = true;
+ }
+}
+
+void DiskUsage::dirUp()
+{
+ if( currentDirectory != 0 )
+ {
+ if ( currentDirectory->parent() != 0 )
+ changeDirectory( (Directory *)(currentDirectory->parent()) );
+ else
+ {
+ KURL up = baseURL.upURL();
+
+ if( KMessageBox::questionYesNo( this, i18n( "Stepping into the parent directory requires "
+ "loading the content of the \"%1\" URL. Do you wish "
+ "to continue?" )
+ .arg( vfs::pathOrURL( up ) ),
+ i18n( "Krusader::DiskUsage" ), KStdGuiItem::yes(),
+ KStdGuiItem::no(), "DiskUsageLoadParentDir"
+ ) == KMessageBox::Yes )
+ load( up );
+ }
+ }
+}
+
+Directory * DiskUsage::getDirectory( QString dir )
+{
+ while( dir.endsWith( "/" ) )
+ dir.truncate( dir.length() - 1 );
+
+ if( dir.isEmpty() )
+ return root;
+
+ return contentMap.find( dir );
+}
+
+File * DiskUsage::getFile( QString path )
+{
+ if( path == "" )
+ return root;
+
+ QString dir = path;
+
+ int ndx = path.findRev( '/' );
+ QString file = path.mid( ndx + 1 );
+
+ if( ndx == -1 )
+ dir = "";
+ else
+ dir.truncate( ndx );
+
+ Directory *dirEntry = getDirectory( dir );
+ if( dirEntry == 0 )
+ return 0;
+
+ for( Iterator<File> it = dirEntry->iterator(); it != dirEntry->end(); ++it )
+ if( (*it)->name() == file )
+ return *it;
+
+ return 0;
+}
+
+void DiskUsage::clear()
+{
+ baseURL = KURL();
+ emit clearing();
+ propertyMap.clear();
+ contentMap.clear();
+ if( root )
+ delete root;
+ root = currentDirectory = 0;
+}
+
+int DiskUsage::calculateSizes( Directory *dirEntry, bool emitSig, int depth )
+{
+ int changeNr = 0;
+
+ if( dirEntry == 0 )
+ dirEntry = root;
+
+ KIO::filesize_t own = 0, total = 0;
+
+ for( Iterator<File> it = dirEntry->iterator(); it != dirEntry->end(); ++it )
+ {
+ File * item = *it;
+
+ if( !item->isExcluded() )
+ {
+ if( item->isDir() )
+ changeNr += calculateSizes( dynamic_cast<Directory *>( item ), emitSig, depth + 1 );
+ else
+ own += item->size();
+
+ total += item->size();
+ }
+ }
+
+ KIO::filesize_t oldOwn = dirEntry->ownSize(), oldTotal = dirEntry->size();
+ dirEntry->setSizes( total, own );
+
+ if( dirEntry == currentDirectory )
+ currentSize = total;
+
+ if( emitSig && ( own != oldOwn || total != oldTotal ) ) {
+ emit changed( dirEntry );
+ changeNr++;
+ }
+
+ if( depth == 0 && changeNr != 0 )
+ emit changeFinished();
+ return changeNr;
+}
+
+int DiskUsage::exclude( File *file, bool calcPercents, int depth )
+{
+ int changeNr = 0;
+
+ if( !file->isExcluded() )
+ {
+ file->exclude( true );
+ emit changed( file );
+ changeNr++;
+
+ if( file->isDir() )
+ {
+ Directory *dir = dynamic_cast<Directory *>( file );
+ for( Iterator<File> it = dir->iterator(); it != dir->end(); ++it )
+ changeNr += exclude( *it, false, depth + 1 );
+ }
+ }
+
+ if( calcPercents )
+ {
+ calculateSizes( root, true );
+ calculatePercents( true );
+ createStatus();
+ }
+
+ if( depth == 0 && changeNr != 0 )
+ emit changeFinished();
+
+ return changeNr;
+}
+
+int DiskUsage::include( Directory *dir, int depth )
+{
+ int changeNr = 0;
+
+ if( dir == 0 )
+ return 0;
+
+ for( Iterator<File> it = dir->iterator(); it != dir->end(); ++it )
+ {
+ File *item = *it;
+
+ if( item->isDir() )
+ changeNr += include( dynamic_cast<Directory *>( item ), depth + 1 );
+
+ if( item->isExcluded() )
+ {
+ item->exclude( false );
+ emit changed( item );
+ changeNr++;
+ }
+ }
+
+ if( depth == 0 && changeNr != 0 )
+ emit changeFinished();
+
+ return changeNr;
+}
+
+void DiskUsage::includeAll()
+{
+ include( root );
+ calculateSizes( root, true );
+ calculatePercents( true );
+ createStatus();
+}
+
+int DiskUsage::del( File *file, bool calcPercents, int depth )
+{
+ int deleteNr = 0;
+
+ if( file == root )
+ return 0;
+
+ krConfig->setGroup( "General" );
+ bool trash = krConfig->readBoolEntry( "Move To Trash", _MoveToTrash );
+ KURL url = vfs::fromPathOrURL( file->fullPath() );
+
+ if( calcPercents )
+ {
+ // now ask the user if he want to delete:
+ krConfig->setGroup( "Advanced" );
+ if ( krConfig->readBoolEntry( "Confirm Delete", _ConfirmDelete ) ) {
+ QString s, b;
+ if ( trash && url.isLocalFile() ) {
+ s = i18n( "Do you really want to move this item to the trash?" );
+ b = i18n( "&Trash" );
+ } else {
+ s = i18n( "Do you really want to delete this item?" );
+ b = i18n( "&Delete" );
+ }
+
+ QStringList name;
+ name.append( file->fullPath() );
+ // show message
+ // note: i'm using continue and not yes/no because the yes/no has cancel as default button
+ if ( KMessageBox::warningContinueCancelList( krApp, s, name, i18n( "Warning" ), b ) != KMessageBox::Continue )
+ return 0;
+ }
+
+ emit status( i18n( "Deleting %1..." ).arg( file->name() ) );
+ }
+
+ if( file == currentDirectory )
+ dirUp();
+
+ if( file->isDir() )
+ {
+ Directory *dir = dynamic_cast<Directory *>( file );
+
+ Iterator<File> it;
+ while( ( it = dir->iterator() ) != dir->end() )
+ deleteNr += del( *it, false, depth + 1 );
+
+ QString path;
+ for( const Directory *d = (Directory*)file; d != root && d && d->parent() != 0; d = d->parent() )
+ {
+ if( !path.isEmpty() )
+ path = "/" + path;
+
+ path = d->name() + path;
+ }
+
+ contentMap.remove( path );
+ }
+
+ emit deleted( file );
+ deleteNr++;
+
+ QGuardedPtr<KIO::Job> job;
+
+ if( trash )
+ {
+#if KDE_IS_VERSION(3,4,0)
+ job = KIO::trash( url, true );
+#else
+ job = new KIO::CopyJob( url,KGlobalSettings::trashPath(),KIO::CopyJob::Move,false,true );
+#endif
+ connect(job,SIGNAL(result(KIO::Job*)),krApp,SLOT(changeTrashIcon()));
+ }
+ else
+ {
+ job = new KIO::DeleteJob( vfs::fromPathOrURL( file->fullPath() ), false, false);
+ }
+
+ deleting = true; // during qApp->processEvent strange things can occur
+ grabMouse(); // that's why we disable the mouse and keyboard events
+ grabKeyboard();
+
+ while( !job.isNull() )
+ qApp->processEvents();
+
+ releaseMouse();
+ releaseKeyboard();
+ deleting = false;
+
+ ((Directory *)(file->parent()))->remove( file );
+ delete file;
+
+ if( depth == 0 )
+ createStatus();
+
+ if( calcPercents )
+ {
+ calculateSizes( root, true );
+ calculatePercents( true );
+ createStatus();
+ emit enteringDirectory( currentDirectory );
+ }
+
+ if( depth == 0 && deleteNr != 0 )
+ emit deleteFinished();
+
+ return deleteNr;
+}
+
+void * DiskUsage::getProperty( File *item, QString key )
+{
+ Properties * props = propertyMap.find( item );
+ if( props == 0 )
+ return 0;
+ return props->find( key );
+}
+
+void DiskUsage::addProperty( File *item, QString key, void * prop )
+{
+ Properties * props = propertyMap.find( item );
+ if( props == 0 )
+ {
+ props = new Properties();
+ propertyMap.insert( item, props );
+ }
+ props->insert( key, prop );
+}
+
+void DiskUsage::removeProperty( File *item, QString key )
+{
+ Properties * props = propertyMap.find( item );
+ if( props == 0 )
+ return;
+ props->remove( key );
+ if( props->count() == 0 )
+ propertyMap.remove( item );
+}
+
+void DiskUsage::createStatus()
+{
+ Directory *dirEntry = currentDirectory;
+
+ if( dirEntry == 0 )
+ return;
+
+ KURL url = baseURL;
+ if( dirEntry != root )
+ url.addPath( dirEntry->directory() );
+
+ emit status( i18n( "Current directory:%1, Total size:%2, Own size:%3" )
+ .arg( vfs::pathOrURL( url, -1 ) )
+ .arg( " "+KRpermHandler::parseSize( dirEntry->size() ) )
+ .arg( " "+KRpermHandler::parseSize( dirEntry->ownSize() ) ) );
+}
+
+void DiskUsage::changeDirectory( Directory *dir )
+{
+ currentDirectory = dir;
+
+ currentSize = dir->size();
+ calculatePercents( true, dir );
+
+ createStatus();
+ emit enteringDirectory( dir );
+}
+
+Directory* DiskUsage::getCurrentDir()
+{
+ return currentDirectory;
+}
+
+void DiskUsage::rightClickMenu( File *fileItem, KPopupMenu *addPopup, QString addPopupName )
+{
+ KPopupMenu popup( this );
+
+ popup.insertTitle( i18n("Disk Usage"));
+
+ if( fileItem != 0 )
+ {
+ popup.insertItem( i18n("Delete"), DELETE_ID);
+ popup.setAccel( Key_Delete, DELETE_ID );
+ popup.insertItem( i18n("Exclude"), EXCLUDE_ID);
+ popup.setAccel( CTRL + Key_E, EXCLUDE_ID );
+ popup.insertSeparator();
+ }
+
+ popup.insertItem( i18n("Up one directory"), PARENT_DIR_ID);
+ popup.setAccel( SHIFT + Key_Up, PARENT_DIR_ID );
+ popup.insertItem( i18n("New search"), NEW_SEARCH_ID);
+ popup.setAccel( CTRL + Key_N, NEW_SEARCH_ID );
+ popup.insertItem( i18n("Refresh"), REFRESH_ID);
+ popup.setAccel( CTRL + Key_R, REFRESH_ID );
+ popup.insertItem( i18n("Include all"), INCLUDE_ALL_ID);
+ popup.setAccel( CTRL + Key_I, INCLUDE_ALL_ID );
+ popup.insertItem( i18n("Step into"), STEP_INTO_ID);
+ popup.setAccel( SHIFT + Key_Down, STEP_INTO_ID );
+ popup.insertSeparator();
+
+
+ if( addPopup != 0 )
+ {
+ popup.insertItem( QPixmap(), addPopup, ADDITIONAL_POPUP_ID );
+ popup.changeItem( ADDITIONAL_POPUP_ID, addPopupName );
+ }
+
+ KPopupMenu viewPopup;
+ viewPopup.insertItem(i18n("Lines"), LINES_VIEW_ID);
+ viewPopup.setAccel( CTRL + Key_L, LINES_VIEW_ID );
+ viewPopup.insertItem(i18n("Detailed"), DETAILED_VIEW_ID);
+ viewPopup.setAccel( CTRL + Key_D, DETAILED_VIEW_ID );
+ viewPopup.insertItem(i18n("Filelight"), FILELIGHT_VIEW_ID);
+ viewPopup.setAccel( CTRL + Key_F, FILELIGHT_VIEW_ID );
+ viewPopup.insertSeparator();
+ viewPopup.insertItem(i18n("Next"), NEXT_VIEW_ID);
+ viewPopup.setAccel( SHIFT + Key_Right, NEXT_VIEW_ID );
+ viewPopup.insertItem(i18n("Previous"), PREVIOUS_VIEW_ID);
+ viewPopup.setAccel( SHIFT + Key_Left, PREVIOUS_VIEW_ID );
+
+ popup.insertItem( QPixmap(), &viewPopup, VIEW_POPUP_ID );
+ popup.changeItem( VIEW_POPUP_ID, i18n( "View" ) );
+
+ int result=popup.exec(QCursor::pos());
+
+ executeAction( result, fileItem );
+}
+
+void DiskUsage::executeAction( int action, File * fileItem )
+{
+ // check out the user's option
+ switch ( action )
+ {
+ case DELETE_ID:
+ if( fileItem )
+ del( fileItem );
+ break;
+ case EXCLUDE_ID:
+ if( fileItem )
+ exclude( fileItem );
+ break;
+ case PARENT_DIR_ID:
+ dirUp();
+ break;
+ case NEW_SEARCH_ID:
+ emit newSearch();
+ break;
+ case REFRESH_ID:
+ load( baseURL );
+ break;
+ case INCLUDE_ALL_ID:
+ includeAll();
+ break;
+ case STEP_INTO_ID:
+ {
+ QString uri;
+ if( fileItem && fileItem->isDir() )
+ uri = fileItem->fullPath();
+ else
+ uri = currentDirectory->fullPath();
+ ACTIVE_FUNC->openUrl(vfs::fromPathOrURL( uri ));
+ }
+ break;
+ case LINES_VIEW_ID:
+ setView( VIEW_LINES );
+ break;
+ case DETAILED_VIEW_ID:
+ setView( VIEW_DETAILED );
+ break;
+ case FILELIGHT_VIEW_ID:
+ setView( VIEW_FILELIGHT );
+ break;
+ case NEXT_VIEW_ID:
+ setView( ( activeView + 1 ) % 3 );
+ break;
+ case PREVIOUS_VIEW_ID:
+ setView( ( activeView + 2 ) % 3 );
+ break;
+ }
+ visibleWidget()->setFocus();
+}
+
+void DiskUsage::keyPressEvent( QKeyEvent *e )
+{
+ if( activeView != VIEW_LOADER )
+ {
+ switch ( e->key() )
+ {
+ case Key_E:
+ if( e->state() == ControlButton )
+ {
+ executeAction( EXCLUDE_ID, getCurrentFile() );
+ return;
+ }
+ case Key_D:
+ if( e->state() == ControlButton )
+ {
+ executeAction( DETAILED_VIEW_ID );
+ return;
+ }
+ case Key_F:
+ if( e->state() == ControlButton )
+ {
+ executeAction( FILELIGHT_VIEW_ID );
+ return;
+ }
+ case Key_I:
+ if( e->state() == ControlButton )
+ {
+ executeAction( INCLUDE_ALL_ID );
+ return;
+ }
+ break;
+ case Key_L:
+ if( e->state() == ControlButton )
+ {
+ executeAction( LINES_VIEW_ID );
+ return;
+ }
+ case Key_N:
+ if( e->state() == ControlButton )
+ {
+ executeAction( NEW_SEARCH_ID );
+ return;
+ }
+ break;
+ case Key_R:
+ if( e->state() == ControlButton )
+ {
+ executeAction( REFRESH_ID );
+ return;
+ }
+ break;
+ case Key_Up:
+ if( e->state() == ShiftButton )
+ {
+ executeAction( PARENT_DIR_ID );
+ return;
+ }
+ break;
+ case Key_Down:
+ if( e->state() == ShiftButton )
+ {
+ executeAction( STEP_INTO_ID );
+ return;
+ }
+ break;
+ case Key_Left:
+ if( e->state() == ShiftButton )
+ {
+ executeAction( PREVIOUS_VIEW_ID );
+ return;
+ }
+ break;
+ case Key_Right:
+ if( e->state() == ShiftButton )
+ {
+ executeAction( NEXT_VIEW_ID );
+ return;
+ }
+ break;
+ case Key_Delete:
+ if( !e->state() )
+ {
+ executeAction( DELETE_ID, getCurrentFile() );
+ return;
+ }
+ case Key_Plus:
+ if( activeView == VIEW_FILELIGHT )
+ {
+ filelightView->zoomIn();
+ return;
+ }
+ break;
+ case Key_Minus:
+ if( activeView == VIEW_FILELIGHT )
+ {
+ filelightView->zoomOut();
+ return;
+ }
+ break;
+ }
+ }
+ QWidgetStack::keyPressEvent( e );
+}
+
+QPixmap DiskUsage::getIcon( QString mime )
+{
+ QPixmap icon;
+
+ if ( !QPixmapCache::find( mime, icon ) )
+ {
+ // get the icon.
+ if ( mime == "Broken Link !" )
+ icon = FL_LOADICON( "file_broken" );
+ else
+ icon = FL_LOADICON( KMimeType::mimeType( mime ) ->icon( QString::null, true ) );
+
+ // insert it into the cache
+ QPixmapCache::insert( mime, icon );
+ }
+ return icon;
+}
+
+int DiskUsage::calculatePercents( bool emitSig, Directory *dirEntry, int depth )
+{
+ int changeNr = 0;
+
+ if( dirEntry == 0 )
+ dirEntry = root;
+
+ for( Iterator<File> it = dirEntry->iterator(); it != dirEntry->end(); ++it )
+ {
+ File *item = *it;
+
+ if( !item->isExcluded() )
+ {
+ int newPerc;
+
+ if( dirEntry->size() == 0 && item->size() == 0 )
+ newPerc = 0;
+ else if( dirEntry->size() == 0 )
+ newPerc = -1;
+ else
+ newPerc = (int)((double)item->size() / (double)currentSize * 10000. + 0.5);
+
+ int oldPerc = item->intPercent();
+ item->setPercent( newPerc );
+
+ if( emitSig && newPerc != oldPerc ) {
+ emit changed( item );
+ changeNr++;
+ }
+
+ if( item->isDir() )
+ changeNr += calculatePercents( emitSig, dynamic_cast<Directory *>( item ), depth + 1 );
+ }
+ }
+
+ if( depth == 0 && changeNr != 0 )
+ emit changeFinished();
+ return changeNr;
+}
+
+QString DiskUsage::getToolTip( File *item )
+{
+ KMimeType::Ptr mimePtr = KMimeType::mimeType( item->mime() );
+ QString mime = mimePtr->comment();
+
+ time_t tma = item->time();
+ struct tm* t=localtime((time_t *)&tma);
+ QDateTime tmp(QDate(t->tm_year+1900, t->tm_mon+1, t->tm_mday), QTime(t->tm_hour, t->tm_min));
+ QString date = KGlobal::locale()->formatDateTime(tmp);
+
+ QString str = "<qt><h5><table><tr><td>" + i18n( "Name:" ) + "</td><td>" + item->name() + "</td></tr>"+
+ "<tr><td>" + i18n( "Type:" ) + "</td><td>" + mime + "</td></tr>"+
+ "<tr><td>" + i18n( "Size:" ) + "</td><td>" + KRpermHandler::parseSize( item->size() ) + "</td></tr>";
+
+ if( item->isDir() )
+ str += "<tr><td>" + i18n( "Own size:" ) + "</td><td>" + KRpermHandler::parseSize( item->ownSize() ) + "</td></tr>";
+
+ str += "<tr><td>" + i18n( "Last modified:" ) + "</td><td>" + date + "</td></tr>"+
+ "<tr><td>" + i18n( "Permissions:" ) + "</td><td>" + item->perm() + "</td></tr>"+
+ "<tr><td>" + i18n( "Owner:" ) + "</td><td>" + item->owner() + " - " + item->group() + "</td></tr>"+
+ "</table></h5></qt>";
+ str.replace( " ", "&nbsp;" );
+ return str;
+}
+
+void DiskUsage::setView( int view )
+{
+ switch( view )
+ {
+ case VIEW_LINES:
+ raiseWidget( lineView );
+ break;
+ case VIEW_DETAILED:
+ raiseWidget( listView );
+ break;
+ case VIEW_FILELIGHT:
+ raiseWidget( filelightView );
+ break;
+ case VIEW_LOADER:
+ raiseWidget( loaderView );
+ break;
+ }
+
+ visibleWidget()->setFocus();
+ emit viewChanged( activeView = view );
+}
+
+File * DiskUsage::getCurrentFile()
+{
+ File * file = 0;
+
+ switch( activeView )
+ {
+ case VIEW_LINES:
+ file = lineView->getCurrentFile();
+ break;
+ case VIEW_DETAILED:
+ file = listView->getCurrentFile();
+ break;
+ case VIEW_FILELIGHT:
+ file = filelightView->getCurrentFile();
+ break;
+ }
+
+ return file;
+}
+
+bool DiskUsage::event( QEvent * e )
+{
+ if( deleting ) { // if we are deleting, disable the mouse and
+ switch( e->type() ) { // keyboard events
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseMove:
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ return true;
+ default:
+ break;
+ }
+ }
+
+ if ( e->type() == QEvent::AccelOverride )
+ {
+ QKeyEvent* ke = (QKeyEvent*) e;
+
+ if ( ke->state() == NoButton || ke->state() == Keypad )
+ {
+ switch ( ke->key() )
+ {
+ case Key_Delete:
+ case Key_Plus:
+ case Key_Minus:
+ ke->accept();
+ break;
+ }
+ }else if( ke->state() == ShiftButton )
+ {
+ switch ( ke->key() )
+ {
+ case Key_Left:
+ case Key_Right:
+ case Key_Up:
+ case Key_Down:
+ ke->accept();
+ break;
+ }
+ }else if ( ke->state() & ControlButton )
+ {
+ switch ( ke->key() )
+ {
+ case Key_D:
+ case Key_E:
+ case Key_F:
+ case Key_I:
+ case Key_L:
+ case Key_N:
+ case Key_R:
+ ke->accept();
+ break;
+ }
+ }
+ }
+ return QWidgetStack::event( e );
+}
+
+#include "diskusage.moc"
diff --git a/krusader/DiskUsage/diskusage.h b/krusader/DiskUsage/diskusage.h
new file mode 100644
index 0000000..da5160e
--- /dev/null
+++ b/krusader/DiskUsage/diskusage.h
@@ -0,0 +1,204 @@
+/***************************************************************************
+ diskusage.h - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __DISK_USAGE_H__
+#define __DISK_USAGE_H__
+
+#include "../VFS/vfs.h"
+#include "filelightParts/fileTree.h"
+
+#include <qdialog.h>
+#include <qlabel.h>
+#include <qdict.h>
+#include <qptrlist.h>
+#include <qptrdict.h>
+#include <qvaluestack.h>
+#include <qptrstack.h>
+#include <kurl.h>
+#include <ksqueezedtextlabel.h>
+#include <qwidgetstack.h>
+#include <qscrollview.h>
+#include <qtimer.h>
+
+#define VIEW_LINES 0
+#define VIEW_DETAILED 1
+#define VIEW_FILELIGHT 2
+#define VIEW_LOADER 3
+
+typedef QDict<void> Properties;
+
+class DUListView;
+class DULines;
+class DUFilelight;
+class KPopupMenu;
+class LoaderWidget;
+
+class DiskUsage : public QWidgetStack
+{
+ Q_OBJECT
+
+public:
+ DiskUsage( QString confGroup, QWidget *parent = 0, char *name = 0);
+ ~DiskUsage();
+
+ void load( KURL dirName );
+ void close();
+ void stopLoad();
+ bool isLoading() { return loading; }
+
+ void setView( int view );
+ int getActiveView() { return activeView; }
+
+ Directory* getDirectory( QString path );
+ File * getFile( QString path );
+
+ QString getConfigGroup() { return configGroup; }
+
+ void * getProperty( File *, QString );
+ void addProperty( File *, QString, void * );
+ void removeProperty( File *, QString );
+
+ int exclude( File *file, bool calcPercents = true, int depth = 0 );
+ void includeAll();
+
+ int del( File *file, bool calcPercents = true, int depth = 0 );
+
+ QString getToolTip( File * );
+
+ void rightClickMenu( File *, KPopupMenu * = 0, QString = QString::null );
+
+ void changeDirectory( Directory *dir );
+
+ Directory* getCurrentDir();
+ File* getCurrentFile();
+
+ QPixmap getIcon( QString mime );
+
+ KURL getBaseURL() { return baseURL; }
+
+public slots:
+ void dirUp();
+ void clear();
+
+signals:
+ void enteringDirectory( Directory * );
+ void clearing();
+ void changed( File * );
+ void changeFinished();
+ void deleted( File * );
+ void deleteFinished();
+ void status( QString );
+ void viewChanged( int );
+ void loadFinished( bool );
+ void newSearch();
+
+protected slots:
+ void slotLoadDirectory();
+
+protected:
+ QDict< Directory > contentMap;
+ QPtrDict<Properties> propertyMap;
+
+ Directory* currentDirectory;
+ KIO::filesize_t currentSize;
+
+ virtual void keyPressEvent( QKeyEvent * );
+ virtual bool event( QEvent * );
+
+ int calculateSizes( Directory *dir = 0, bool emitSig = false, int depth = 0 );
+ int calculatePercents( bool emitSig = false, Directory *dir = 0 , int depth = 0 );
+ int include( Directory *dir, int depth = 0 );
+ void createStatus();
+ void executeAction( int, File * = 0 );
+
+ KURL baseURL; //< the base URL of loading
+
+ DUListView *listView;
+ DULines *lineView;
+ DUFilelight *filelightView;
+ LoaderWidget *loaderView;
+
+ Directory *root;
+
+ int activeView;
+
+ QString configGroup;
+
+ bool first;
+ bool loading;
+ bool abortLoading;
+ bool clearAfterAbort;
+ bool deleting;
+
+ QValueStack<QString> directoryStack;
+ QPtrStack<Directory> parentStack;
+
+ vfs * searchVfs;
+ vfile * currentVfile;
+ Directory * currentParent;
+ QString dirToCheck;
+
+ int fileNum;
+ int dirNum;
+ int viewBeforeLoad;
+
+ QTimer loadingTimer;
+};
+
+
+class LoaderWidget : public QScrollView
+{
+ Q_OBJECT
+
+public:
+ LoaderWidget( QWidget *parent = 0, const char *name = 0 );
+
+ void init();
+ void setCurrentURL( KURL url );
+ void setValues( int fileNum, int dirNum, KIO::filesize_t total );
+ bool wasCancelled() { return cancelled; }
+
+public slots:
+ void slotCancelled();
+
+protected:
+ virtual void resizeEvent ( QResizeEvent *e );
+
+ QLabel *totalSize;
+ QLabel *files;
+ QLabel *directories;
+
+ KSqueezedTextLabel *searchedDirectory;
+ QWidget *widget;
+
+ bool cancelled;
+};
+
+#endif /* __DISK_USAGE_GUI_H__ */
diff --git a/krusader/DiskUsage/diskusagegui.cpp b/krusader/DiskUsage/diskusagegui.cpp
new file mode 100644
index 0000000..f2bc140
--- /dev/null
+++ b/krusader/DiskUsage/diskusagegui.cpp
@@ -0,0 +1,227 @@
+/***************************************************************************
+ diskusagegui.cpp - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "diskusagegui.h"
+#include "../kicons.h"
+#include "../krusader.h"
+#include "../VFS/vfs.h"
+#include "../Dialogs/krdialogs.h"
+
+#include <qtimer.h>
+#include <qhbox.h>
+#include <klocale.h>
+#include <qtooltip.h>
+
+DiskUsageGUI::DiskUsageGUI( KURL openDir, QWidget* parent, const char *name )
+ : QDialog( parent, name, false, 0 ), exitAtFailure( true )
+{
+ setCaption( i18n("Krusader::Disk Usage") );
+
+ baseDirectory = openDir;
+ if( !newSearch() )
+ return;
+
+ QGridLayout *duGrid = new QGridLayout( this );
+ duGrid->setSpacing( 6 );
+ duGrid->setMargin( 11 );
+
+ QHBox *duTools = new QHBox( this, "duTools" );
+ duTools->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
+
+ btnNewSearch = new QToolButton( duTools, "btnNewSearch" );
+ btnNewSearch->setIconSet( QIconSet(krLoader->loadIcon("fileopen",KIcon::Desktop)) );
+ QToolTip::add( btnNewSearch, i18n( "Start new disk usage search" ) );
+
+ btnRefresh = new QToolButton( duTools, "btnRefresh" );
+ btnRefresh->setIconSet( QIconSet(krLoader->loadIcon("reload",KIcon::Desktop)) );
+ QToolTip::add( btnRefresh, i18n( "Refresh" ) );
+
+ btnDirUp = new QToolButton( duTools, "btnDirUp" );
+ btnDirUp->setIconSet( QIconSet(krLoader->loadIcon("up",KIcon::Desktop)) );
+ QToolTip::add( btnDirUp, i18n( "Parent directory" ) );
+
+ QWidget * separatorWidget = new QWidget( duTools, "separatorWidget" );
+ separatorWidget->setMinimumWidth( 10 );
+
+ btnLines = new QToolButton( duTools, "btnLines" );
+ btnLines->setIconSet( QIconSet(krLoader->loadIcon("leftjust",KIcon::Desktop)) );
+ btnLines->setToggleButton( true );
+ QToolTip::add( btnLines, i18n( "Line view" ) );
+
+ btnDetailed = new QToolButton( duTools, "btnDetailed" );
+ btnDetailed->setIconSet( QIconSet(krLoader->loadIcon("view_detailed",KIcon::Desktop)) );
+ btnDetailed->setToggleButton( true );
+ QToolTip::add( btnDetailed, i18n( "Detailed view" ) );
+
+ btnFilelight = new QToolButton( duTools, "btnFilelight" );
+ btnFilelight->setIconSet( QIconSet(krLoader->loadIcon("kr_diskusage",KIcon::Desktop)) );
+ btnFilelight->setToggleButton( true );
+ QToolTip::add( btnFilelight, i18n( "Filelight view" ) );
+
+ QWidget *spacerWidget = new QWidget( duTools, "spacerWidget" );
+ QHBoxLayout *hboxlayout = new QHBoxLayout( spacerWidget );
+ QSpacerItem* spacer = new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed );
+ hboxlayout->addItem( spacer );
+
+ duGrid->addWidget( duTools, 0, 0 );
+
+ diskUsage = new DiskUsage( "DiskUsage", this );
+ duGrid->addWidget( diskUsage, 1, 0 );
+
+ status = new KSqueezedTextLabel( this );
+ status->setFrameShape( QLabel::StyledPanel );
+ status->setFrameShadow( QLabel::Sunken );
+ duGrid->addWidget( status, 2, 0 );
+
+ connect( diskUsage, SIGNAL( status( QString ) ), this, SLOT( setStatus( QString ) ) );
+ connect( diskUsage, SIGNAL( viewChanged( int ) ), this, SLOT( slotViewChanged( int ) ) );
+ connect( diskUsage, SIGNAL( newSearch() ), this, SLOT( newSearch() ) );
+ connect( diskUsage, SIGNAL( loadFinished( bool ) ), this, SLOT( slotLoadFinished( bool ) ) );
+ connect( btnNewSearch, SIGNAL( clicked() ), this, SLOT( newSearch() ) );
+ connect( btnRefresh, SIGNAL( clicked() ), this, SLOT( loadUsageInfo() ) );
+ connect( btnDirUp, SIGNAL( clicked() ), diskUsage, SLOT( dirUp() ) );
+ connect( btnLines, SIGNAL( clicked() ), this, SLOT( selectLinesView() ) );
+ connect( btnDetailed, SIGNAL( clicked() ), this, SLOT( selectListView() ) );
+ connect( btnFilelight, SIGNAL( clicked() ), this, SLOT( selectFilelightView() ) );
+
+ krConfig->setGroup( "DiskUsage" );
+
+ int view = krConfig->readNumEntry( "View", VIEW_LINES );
+ if( view < VIEW_LINES || view > VIEW_FILELIGHT )
+ view = VIEW_LINES;
+ diskUsage->setView( view );
+
+ sizeX = krConfig->readNumEntry( "Window Width", QFontMetrics(font()).width("W") * 70 );
+ sizeY = krConfig->readNumEntry( "Window Height", QFontMetrics(font()).height() * 25 );
+ resize( sizeX, sizeY );
+
+ if( krConfig->readBoolEntry( "Window Maximized", false ) )
+ showMaximized();
+ else
+ show();
+
+ exec();
+}
+
+DiskUsageGUI::~DiskUsageGUI()
+{
+}
+
+void DiskUsageGUI::slotLoadFinished( bool result )
+{
+ if( exitAtFailure && !result )
+ reject();
+ else
+ exitAtFailure = false;
+}
+
+void DiskUsageGUI::enableButtons( bool isOn )
+{
+ btnNewSearch->setEnabled( isOn );
+ btnRefresh->setEnabled( isOn );
+ btnDirUp->setEnabled( isOn );
+ btnLines->setEnabled( isOn );
+ btnDetailed->setEnabled( isOn );
+ btnFilelight->setEnabled( isOn );
+}
+
+void DiskUsageGUI::resizeEvent( QResizeEvent *e )
+{
+ if( !isMaximized() )
+ {
+ sizeX = e->size().width();
+ sizeY = e->size().height();
+ }
+ QDialog::resizeEvent( e );
+}
+
+void DiskUsageGUI::reject()
+{
+ krConfig->setGroup( "DiskUsage" );
+ krConfig->writeEntry("Window Width", sizeX );
+ krConfig->writeEntry("Window Height", sizeY );
+ krConfig->writeEntry("Window Maximized", isMaximized() );
+ krConfig->writeEntry("View", diskUsage->getActiveView() );
+
+ QDialog::reject();
+}
+
+void DiskUsageGUI::loadUsageInfo()
+{
+ diskUsage->load( baseDirectory );
+}
+
+void DiskUsageGUI::setStatus( QString stat )
+{
+ status->setText( stat );
+}
+
+void DiskUsageGUI::slotViewChanged( int view )
+{
+ if( view == VIEW_LOADER )
+ {
+ enableButtons( false );
+ return;
+ }
+ enableButtons( true );
+
+ btnLines->setOn( false );
+ btnDetailed->setOn( false );
+ btnFilelight->setOn( false );
+
+ switch( view )
+ {
+ case VIEW_LINES:
+ btnLines->setOn( true );
+ break;
+ case VIEW_DETAILED:
+ btnDetailed->setOn( true );
+ break;
+ case VIEW_FILELIGHT:
+ btnFilelight->setOn( true );
+ break;
+ case VIEW_LOADER:
+ break;
+ }
+}
+
+bool DiskUsageGUI::newSearch()
+{
+ // ask the user for the copy dest
+
+ KURL tmp = KChooseDir::getDir(i18n( "Viewing the usage of directory:" ), baseDirectory, baseDirectory);
+ if (tmp.isEmpty()) return false;
+ baseDirectory = tmp;
+
+ QTimer::singleShot( 0, this, SLOT( loadUsageInfo() ) );
+ return true;
+}
+
+#include "diskusagegui.moc"
diff --git a/krusader/DiskUsage/diskusagegui.h b/krusader/DiskUsage/diskusagegui.h
new file mode 100644
index 0000000..d243307
--- /dev/null
+++ b/krusader/DiskUsage/diskusagegui.h
@@ -0,0 +1,89 @@
+/***************************************************************************
+ diskusagegui.h - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __DISK_USAGE_GUI_H__
+#define __DISK_USAGE_GUI_H__
+
+#include <qdialog.h>
+#include <qlayout.h>
+#include <qtoolbutton.h>
+#include <kurl.h>
+#include <ksqueezedtextlabel.h>
+
+#include "diskusage.h"
+
+class DiskUsageGUI : public QDialog
+{
+ Q_OBJECT
+
+public:
+ DiskUsageGUI( KURL openDir, QWidget* parent=0, const char *name = 0 );
+ ~DiskUsageGUI();
+
+
+public slots:
+ void loadUsageInfo();
+ bool newSearch();
+ void setStatus( QString );
+
+ void selectLinesView() { diskUsage->setView( VIEW_LINES ); }
+ void selectListView() { diskUsage->setView( VIEW_DETAILED ); }
+ void selectFilelightView() { diskUsage->setView( VIEW_FILELIGHT ); }
+
+protected slots:
+ virtual void reject();
+ void slotViewChanged( int view );
+ void enableButtons( bool );
+ void slotLoadFinished( bool );
+
+protected:
+ virtual void resizeEvent( QResizeEvent *e );
+
+ DiskUsage *diskUsage;
+ KURL baseDirectory;
+
+ KSqueezedTextLabel *status;
+
+ QToolButton *btnNewSearch;
+ QToolButton *btnRefresh;
+ QToolButton *btnDirUp;
+
+ QToolButton *btnLines;
+ QToolButton *btnDetailed;
+ QToolButton *btnFilelight;
+
+ int sizeX;
+ int sizeY;
+
+ bool exitAtFailure;
+};
+
+#endif /* __DISK_USAGE_GUI_H__ */
+
diff --git a/krusader/DiskUsage/dufilelight.cpp b/krusader/DiskUsage/dufilelight.cpp
new file mode 100644
index 0000000..6a6bee9
--- /dev/null
+++ b/krusader/DiskUsage/dufilelight.cpp
@@ -0,0 +1,236 @@
+/***************************************************************************
+ dufilelight.cpp - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "dufilelight.h"
+#include "radialMap/radialMap.h"
+#include <kpopupmenu.h>
+#include <klocale.h>
+#include <kinputdialog.h>
+
+#define SCHEME_POPUP_ID 6730
+
+DUFilelight::DUFilelight( DiskUsage *usage, const char *name )
+ : RadialMap::Widget( usage, name ), diskUsage( usage ), currentDir( 0 ), refreshNeeded( true )
+{
+ setFocusPolicy( QWidget::StrongFocus );
+
+ connect( diskUsage, SIGNAL( enteringDirectory( Directory * ) ), this, SLOT( slotDirChanged( Directory * ) ) );
+ connect( diskUsage, SIGNAL( clearing() ), this, SLOT( clear() ) );
+ connect( diskUsage, SIGNAL( changed( File * ) ), this, SLOT( slotChanged( File * ) ) );
+ connect( diskUsage, SIGNAL( deleted( File * ) ), this, SLOT( slotChanged( File * ) ) );
+ connect( diskUsage, SIGNAL( changeFinished() ), this, SLOT( slotRefresh() ) );
+ connect( diskUsage, SIGNAL( deleteFinished() ), this, SLOT( slotRefresh() ) );
+ connect( diskUsage, SIGNAL( aboutToShow( QWidget * ) ), this, SLOT( slotAboutToShow( QWidget * ) ) );
+}
+
+void DUFilelight::slotDirChanged( Directory *dir )
+{
+ if( diskUsage->visibleWidget() != this )
+ return;
+
+ if( currentDir != dir )
+ {
+ currentDir = dir;
+
+ invalidate( false );
+ create( dir );
+ refreshNeeded = false;
+ }
+}
+
+void DUFilelight::clear()
+{
+ invalidate( false );
+ currentDir = 0;
+}
+
+File * DUFilelight::getCurrentFile()
+{
+ const RadialMap::Segment * focus = focusSegment();
+
+ if( !focus || focus->isFake() || focus->file() == currentDir )
+ return 0;
+
+ return (File *)focus->file();
+}
+
+void DUFilelight::mousePressEvent( QMouseEvent *event )
+{
+ if( event->button() == Qt::RightButton )
+ {
+ File * file = 0;
+
+ const RadialMap::Segment * focus = focusSegment();
+
+ if( focus && !focus->isFake() && focus->file() != currentDir )
+ file = (File *)focus->file();
+
+ KPopupMenu filelightPopup;
+ filelightPopup.insertItem( i18n("Zoom In"), this, SLOT( zoomIn() ), Key_Plus );
+ filelightPopup.insertItem( i18n("Zoom Out"), this, SLOT( zoomOut() ), Key_Minus );
+
+ KPopupMenu schemePopup;
+ schemePopup.insertItem( i18n("Rainbow"), this, SLOT( schemeRainbow() ) );
+ schemePopup.insertItem( i18n("High Contrast"), this, SLOT( schemeHighContrast() ) );
+ schemePopup.insertItem( i18n("KDE"), this, SLOT( schemeKDE() ) );
+
+ filelightPopup.insertItem( QPixmap(), &schemePopup, SCHEME_POPUP_ID );
+ filelightPopup.changeItem( SCHEME_POPUP_ID, i18n( "Scheme" ) );
+
+ filelightPopup.insertItem( i18n("Increase contrast"), this, SLOT( increaseContrast() ) );
+ filelightPopup.insertItem( i18n("Decrease contrast"), this, SLOT( decreaseContrast() ) );
+
+ int aid = filelightPopup.insertItem( i18n("Use anti-aliasing" ), this, SLOT( changeAntiAlias() ) );
+ filelightPopup.setItemChecked( aid, Filelight::Config::antiAliasFactor > 1 );
+
+ int sid = filelightPopup.insertItem( i18n("Show small files" ), this, SLOT( showSmallFiles() ) );
+ filelightPopup.setItemChecked( sid, Filelight::Config::showSmallFiles );
+
+ int vid = filelightPopup.insertItem( i18n("Vary label font sizes" ), this, SLOT( varyLabelFontSizes() ) );
+ filelightPopup.setItemChecked( vid, Filelight::Config::varyLabelFontSizes );
+
+ filelightPopup.insertItem( i18n("Minimum font size"), this, SLOT( minFontSize() ) );
+
+ diskUsage->rightClickMenu( file, &filelightPopup, i18n( "Filelight" ) );
+ return;
+ }else if( event->button() == Qt::LeftButton )
+ {
+ const RadialMap::Segment * focus = focusSegment();
+
+ if( focus && !focus->isFake() && focus->file() == currentDir )
+ {
+ diskUsage->dirUp();
+ return;
+ }
+ else if( focus && !focus->isFake() && focus->file()->isDir() )
+ {
+ diskUsage->changeDirectory( (Directory *)focus->file() );
+ return;
+ }
+ }
+
+ RadialMap::Widget::mousePressEvent( event );
+}
+
+void DUFilelight::setScheme( Filelight::MapScheme scheme )
+{
+ Filelight::Config::scheme = scheme;
+ Filelight::Config::write();
+ slotRefresh();
+}
+
+void DUFilelight::increaseContrast()
+{
+ if( ( Filelight::Config::contrast += 10 ) > 100 )
+ Filelight::Config::contrast = 100;
+
+ Filelight::Config::write();
+ slotRefresh();
+}
+
+void DUFilelight::decreaseContrast()
+{
+ if( ( Filelight::Config::contrast -= 10 ) > 100 )
+ Filelight::Config::contrast = 0;
+
+ Filelight::Config::write();
+ slotRefresh();
+}
+
+void DUFilelight::changeAntiAlias()
+{
+ Filelight::Config::antiAliasFactor = 1 + ( Filelight::Config::antiAliasFactor == 1 );
+ Filelight::Config::write();
+ slotRefresh();
+}
+
+void DUFilelight::showSmallFiles()
+{
+ Filelight::Config::showSmallFiles = !Filelight::Config::showSmallFiles;
+ Filelight::Config::write();
+ slotRefresh();
+}
+
+void DUFilelight::varyLabelFontSizes()
+{
+ Filelight::Config::varyLabelFontSizes = !Filelight::Config::varyLabelFontSizes;
+ Filelight::Config::write();
+ slotRefresh();
+}
+
+void DUFilelight::minFontSize()
+{
+ bool ok = false;
+
+ int result = KInputDialog::getInteger( i18n( "Krusader::Filelight" ),
+ i18n( "Minimum font size" ), (int)Filelight::Config::minFontPitch, 1, 100, 1, &ok, this );
+
+ if ( ok )
+ {
+ Filelight::Config::minFontPitch = (uint)result;
+
+ Filelight::Config::write();
+ slotRefresh();
+ }
+}
+
+void DUFilelight::slotAboutToShow( QWidget *widget )
+{
+ if( widget == this && ( diskUsage->getCurrentDir() != currentDir || refreshNeeded ) )
+ {
+ refreshNeeded = false;
+ if( ( currentDir = diskUsage->getCurrentDir() ) != 0 )
+ {
+ invalidate( false );
+ create( currentDir );
+ }
+ }
+}
+
+void DUFilelight::slotRefresh()
+{
+ if( diskUsage->visibleWidget() != this )
+ return;
+
+ refreshNeeded = false;
+ if( currentDir && currentDir == diskUsage->getCurrentDir() )
+ {
+ invalidate( false );
+ create( currentDir );
+ }
+}
+
+void DUFilelight::slotChanged( File * )
+{
+ if( !refreshNeeded )
+ refreshNeeded = true;
+}
+
+#include "dufilelight.moc"
diff --git a/krusader/DiskUsage/dufilelight.h b/krusader/DiskUsage/dufilelight.h
new file mode 100644
index 0000000..556830e
--- /dev/null
+++ b/krusader/DiskUsage/dufilelight.h
@@ -0,0 +1,80 @@
+/***************************************************************************
+ dufilelight.h - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __DU_FILELIGHT_H__
+#define __DU_FILELIGHT_H__
+
+#include "diskusage.h"
+#include "radialMap/widget.h"
+#include "filelightParts/Config.h"
+
+class DUFilelight : public RadialMap::Widget
+{
+ Q_OBJECT
+
+public:
+ DUFilelight( DiskUsage *usage, const char *name );
+
+ File * getCurrentFile();
+
+public slots:
+ void slotDirChanged( Directory * );
+ void clear();
+ void slotChanged( File * );
+ void slotRefresh();
+
+protected slots:
+ void slotAboutToShow( QWidget *widget );
+
+ void schemeRainbow() { setScheme( Filelight::Rainbow ); }
+ void schemeHighContrast() { setScheme( Filelight::HighContrast ); }
+ void schemeKDE() { setScheme( Filelight::KDE ); }
+
+ void increaseContrast();
+ void decreaseContrast();
+ void changeAntiAlias();
+ void showSmallFiles();
+ void varyLabelFontSizes();
+ void minFontSize();
+
+protected:
+ virtual void mousePressEvent( QMouseEvent* );
+
+ void setScheme( Filelight::MapScheme );
+
+ DiskUsage *diskUsage;
+ Directory *currentDir;
+
+private:
+ bool refreshNeeded;
+};
+
+#endif /* __DU_FILELIGHT_H__ */
+
diff --git a/krusader/DiskUsage/dulines.cpp b/krusader/DiskUsage/dulines.cpp
new file mode 100644
index 0000000..089a8a7
--- /dev/null
+++ b/krusader/DiskUsage/dulines.cpp
@@ -0,0 +1,522 @@
+/***************************************************************************
+ dulines.cpp - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "dulines.h"
+#include "../kicons.h"
+#include "../krusader.h"
+#include "../VFS/krpermhandler.h"
+#include <qheader.h>
+#include <klocale.h>
+#include <qpen.h>
+#include <qpainter.h>
+#include <qfontmetrics.h>
+#include <qtimer.h>
+#include <qtooltip.h>
+#include <kpopupmenu.h>
+
+class DULinesItem : public QListViewItem
+{
+public:
+ DULinesItem( DiskUsage *diskUsageIn, File *fileItem, QListView * parent, QString label1,
+ QString label2, QString label3, unsigned int italicPos ) : QListViewItem( parent, label1, label2, label3 ),
+ diskUsage( diskUsageIn ), file( fileItem ), isTruncated( false ), italicTextPos( italicPos ) {}
+ DULinesItem( DiskUsage *diskUsageIn, File *fileItem, QListView * parent, QListViewItem * after,
+ QString label1, QString label2, QString label3, unsigned int italicPos ) : QListViewItem( parent, after, label1,
+ label2, label3 ), diskUsage( diskUsageIn ), file( fileItem ), isTruncated( false ), italicTextPos( italicPos ) {}
+
+ virtual int compare ( QListViewItem * i, int col, bool ascending ) const
+ {
+ if( text(0) == ".." ) return ascending ? -1 : 1;
+ if( i->text(0) == "..") return ascending ? 1 : -1;
+
+ DULinesItem *compWith = dynamic_cast< DULinesItem * >( i );
+
+ QString buf1,buf2;
+
+ switch( col )
+ {
+ case 0:
+ case 1:
+ buf1.sprintf("%025llu",file->size());
+ buf2.sprintf("%025llu",compWith->file->size());
+ return -QString::compare( buf1, buf2 );
+ default:
+ return QListViewItem::compare( i, col, ascending );
+ }
+ }
+
+ virtual void paintCell( QPainter * p, const QColorGroup & cg, int column, int width, int align )
+ {
+ if( column == 2 )
+ {
+ if ( isSelected() )
+ p->fillRect( 0, 0, width, height(), cg.brush( QColorGroup::Highlight ) );
+ else
+ p->fillRect( 0, 0, width, height(), cg.brush( QColorGroup::Base ) );
+
+ QListView *lv = listView();
+
+ int pos = lv->itemMargin();
+
+ const QPixmap *icon = pixmap( column );
+ if( icon )
+ {
+ int iconWidth = icon->width() + lv->itemMargin();
+ int xo = pos;
+ int yo = ( height() - icon->height() ) / 2;
+
+ p->drawPixmap( xo, yo, *icon );
+
+ pos += iconWidth;
+ }
+
+ QFontMetrics fm( p->fontMetrics() );
+
+ if( isSelected() )
+ p->setPen( cg.highlightedText() );
+ else
+ p->setPen( cg.text() );
+
+ QString t = text( column );
+ QString b;
+
+ if( t.length() > italicTextPos )
+ {
+ b = t.mid( italicTextPos );
+ t.truncate( italicTextPos );
+ }
+
+ isTruncated = false;
+ if( !t.isEmpty() )
+ {
+ int remWidth = width-pos;
+
+ if( fm.width( t ) > remWidth )
+ {
+ while( !t.isEmpty() )
+ {
+ t.truncate( t.length() - 1 );
+ if( fm.width( t + "..." ) <= remWidth )
+ break;
+ }
+ t += "...";
+ isTruncated = true;
+ }
+
+ p->drawText( pos, 0, width, height(), align, t );
+ pos += fm.width( t );
+ }
+
+ if( !b.isEmpty() && !isTruncated )
+ {
+ QFont font( p->font() );
+ font.setItalic( true );
+ p->setFont( font );
+
+ QFontMetrics fm2( p->fontMetrics() );
+
+ int remWidth = width-pos;
+
+ if( fm2.width( b ) > remWidth )
+ {
+ while( !b.isEmpty() )
+ {
+ b.truncate( b.length() - 1 );
+ if( fm2.width( b + "..." ) <= remWidth )
+ break;
+ }
+ b += "...";
+ isTruncated = true;
+ }
+
+ p->drawText( pos, 0, width, height(), align, b );
+ }
+ }
+ else
+ QListViewItem::paintCell( p, cg, column, width, align );
+ }
+
+ inline File * getFile() { return file; }
+
+private:
+ DiskUsage *diskUsage;
+ File *file;
+
+ bool isTruncated;
+ unsigned int italicTextPos;
+};
+
+class DULinesToolTip : public QToolTip
+{
+public:
+ DULinesToolTip( DiskUsage *usage, QWidget *parent, QListView *lv );
+ void maybeTip( const QPoint &pos );
+
+ virtual ~DULinesToolTip() {}
+private:
+ QListView *view;
+ DiskUsage *diskUsage;
+};
+
+DULinesToolTip::DULinesToolTip( DiskUsage *usage, QWidget *parent, QListView *lv )
+ : QToolTip( parent ), view( lv ), diskUsage( usage )
+{
+}
+
+void DULinesToolTip::maybeTip( const QPoint &pos )
+{
+ QListViewItem *item = view->itemAt( pos );
+ QPoint contentsPos = view->viewportToContents( pos );
+ if ( !item )
+ return;
+
+ int col = view->header()->sectionAt( contentsPos.x() );
+
+ int width = item->width( QFontMetrics( view->font() ), view, col );
+
+ QRect r = view->itemRect( item );
+ int headerPos = view->header()->sectionPos( col );
+ r.setLeft( headerPos );
+ r.setRight( headerPos + view->header()->sectionSize( col ) );
+
+ if( col != 0 && width > view->columnWidth( col ) )
+ tip( r, item->text( col ) );
+ else if( col == 1 && item->text( 0 ) != ".." )
+ {
+ File *fileItem = ((DULinesItem *)item)->getFile();
+ tip( r, diskUsage->getToolTip( fileItem ) );
+ }
+}
+
+DULines::DULines( DiskUsage *usage, const char *name )
+ : QListView( usage, name ), diskUsage( usage ), refreshNeeded( false )
+{
+ setAllColumnsShowFocus(true);
+ setVScrollBarMode(QScrollView::Auto);
+ setHScrollBarMode(QScrollView::Auto);
+ setShowSortIndicator(true);
+ setTreeStepSize( 10 );
+
+ int defaultSize = QFontMetrics(font()).width("W");
+
+ krConfig->setGroup( diskUsage->getConfigGroup() );
+
+ showFileSize = krConfig->readBoolEntry( "L Show File Size", true );
+
+ int lineWidth = krConfig->readNumEntry("L Line Width", defaultSize * 20 );
+ addColumn( i18n("Line View"), lineWidth );
+ setColumnWidthMode(0,QListView::Manual);
+ int precentWidth = krConfig->readNumEntry("L Percent Width", defaultSize * 6 );
+ addColumn( i18n("Percent"), precentWidth );
+ setColumnWidthMode(1,QListView::Manual);
+ int nameWidth = krConfig->readNumEntry("L Name Width", defaultSize * 20 );
+ addColumn( i18n("Name"), nameWidth );
+ setColumnWidthMode(2,QListView::Manual);
+
+ setColumnAlignment( 1, Qt::AlignRight );
+
+ header()->setStretchEnabled( true, 0 );
+
+ setSorting( 1 );
+
+ toolTip = new DULinesToolTip( diskUsage, viewport(), this );
+
+ connect( diskUsage, SIGNAL( enteringDirectory( Directory * ) ), this, SLOT( slotDirChanged( Directory * ) ) );
+ connect( diskUsage, SIGNAL( clearing() ), this, SLOT( clear() ) );
+
+ connect( header(), SIGNAL( sizeChange( int, int, int ) ), this, SLOT( sectionResized( int ) ) );
+
+ connect( this, SIGNAL(rightButtonPressed(QListViewItem *, const QPoint &, int)),
+ this, SLOT( slotRightClicked(QListViewItem *) ) );
+ connect( diskUsage, SIGNAL( changed( File * ) ), this, SLOT( slotChanged( File * ) ) );
+ connect( diskUsage, SIGNAL( deleted( File * ) ), this, SLOT( slotDeleted( File * ) ) );
+}
+
+DULines::~DULines()
+{
+ krConfig->setGroup( diskUsage->getConfigGroup() );
+ krConfig->writeEntry("L Line Width", columnWidth( 0 ) );
+ krConfig->writeEntry("L Percent Width", columnWidth( 1 ) );
+ krConfig->writeEntry("L Name Width", columnWidth( 2 ) );
+ krConfig->writeEntry("L Show File Size", showFileSize );
+
+ delete toolTip;
+}
+
+void DULines::slotDirChanged( Directory *dirEntry )
+{
+ clear();
+
+ QListViewItem * lastItem = 0;
+
+ if( ! ( dirEntry->parent() == 0 ) )
+ {
+ lastItem = new QListViewItem( this, ".." );
+ lastItem->setPixmap( 0, FL_LOADICON( "up" ) );
+ lastItem->setSelectable( false );
+ }
+
+ int maxPercent = -1;
+ for( Iterator<File> it = dirEntry->iterator(); it != dirEntry->end(); ++it )
+ {
+ File *item = *it;
+ if( !item->isExcluded() && item->intPercent() > maxPercent )
+ maxPercent = item->intPercent();
+ }
+
+ for( Iterator<File> it = dirEntry->iterator(); it != dirEntry->end(); ++it )
+ {
+ File *item = *it;
+
+ QString fileName = item->name();
+
+ unsigned int italicStart = fileName.length();
+
+ if( showFileSize )
+ fileName += " [" + KIO::convertSize( item->size() ) + "]";
+
+ if( lastItem == 0 )
+ lastItem = new DULinesItem( diskUsage, item, this, "", item->percent() + " ", fileName, italicStart );
+ else
+ lastItem = new DULinesItem( diskUsage, item, this, lastItem, "", item->percent() + " ", fileName, italicStart );
+
+ if( item->isExcluded() )
+ lastItem->setVisible( false );
+
+ lastItem->setPixmap( 2, diskUsage->getIcon( item->mime() ) );
+ lastItem->setPixmap( 0, createPixmap( item->intPercent(), maxPercent, columnWidth( 0 ) - itemMargin() ) );
+ }
+
+ setCurrentItem( firstChild() );
+}
+
+QPixmap DULines::createPixmap( int percent, int maxPercent, int maxWidth )
+{
+ if( percent < 0 || percent > maxPercent || maxWidth < 2 || maxPercent == 0 )
+ return QPixmap();
+ maxWidth -= 2;
+
+ int actualWidth = maxWidth*percent/maxPercent;
+ if( actualWidth == 0 )
+ return QPixmap();
+
+ QPen pen;
+ pen.setColor( Qt::black );
+ QPainter painter;
+
+ int size = QFontMetrics(font()).height()-2;
+ QRect rect( 0, 0, actualWidth, size );
+ QPixmap pixmap( rect.width(), rect.height() );
+
+ painter.begin( &pixmap );
+ painter.setPen( pen );
+
+ for( int i = 1; i < actualWidth - 1; i++ )
+ {
+ int color = (511*i/maxWidth);
+ if( color < 256 )
+ pen.setColor( QColor( 255-color, 255, 0 ) );
+ else
+ pen.setColor( QColor( color-256, 511-color, 0 ) );
+
+ painter.setPen( pen );
+ painter.drawLine( i, 1, i, size-1 );
+ }
+
+ pen.setColor( Qt::black );
+ painter.setPen( pen );
+ painter.drawRect( rect );
+ painter.end();
+ pixmap.detach();
+ return pixmap;
+}
+
+void DULines::sectionResized( int column )
+{
+ if( childCount() == 0 || column != 0 )
+ return;
+
+ Directory * currentDir = diskUsage->getCurrentDir();
+ if( currentDir == 0 )
+ return;
+
+ int maxPercent = -1;
+ for( Iterator<File> it = currentDir->iterator(); it != currentDir->end(); ++it )
+ {
+ File *item = *it;
+
+ if( !item->isExcluded() && item->intPercent() > maxPercent )
+ maxPercent = item->intPercent();
+ }
+
+ DULinesItem *duItem = (DULinesItem *)firstChild();
+ while( duItem )
+ {
+ if( duItem->text( 0 ) != ".." )
+ duItem->setPixmap( 0, createPixmap( duItem->getFile()->intPercent(), maxPercent, columnWidth( 0 ) ) );
+ duItem = (DULinesItem *)duItem->nextSibling();
+ }
+}
+
+bool DULines::doubleClicked( QListViewItem * item )
+{
+ if( item )
+ {
+ if( item->text( 0 ) != ".." )
+ {
+ File *fileItem = ((DULinesItem *)item)->getFile();
+ if( fileItem->isDir() )
+ diskUsage->changeDirectory( dynamic_cast<Directory *> ( fileItem ) );
+ return true;
+ }
+ else
+ {
+ Directory *upDir = (Directory *)diskUsage->getCurrentDir()->parent();
+
+ if( upDir )
+ diskUsage->changeDirectory( upDir );
+ return true;
+ }
+ }
+ return false;
+}
+
+void DULines::contentsMouseDoubleClickEvent ( QMouseEvent * e )
+{
+ if ( e || e->button() == LeftButton )
+ {
+ QPoint vp = contentsToViewport(e->pos());
+ QListViewItem * item = itemAt( vp );
+
+ if( doubleClicked( item ) )
+ return;
+
+ }
+ QListView::contentsMouseDoubleClickEvent( e );
+}
+
+
+void DULines::keyPressEvent( QKeyEvent *e )
+{
+ switch ( e->key() )
+ {
+ case Key_Return :
+ case Key_Enter :
+ if( doubleClicked( currentItem() ) )
+ return;
+ break;
+ case Key_Left :
+ case Key_Right :
+ case Key_Up :
+ case Key_Down :
+ if( e->state() == ShiftButton )
+ {
+ e->ignore();
+ return;
+ }
+ break;
+ case Key_Delete :
+ e->ignore();
+ return;
+ }
+ QListView::keyPressEvent( e );
+}
+
+void DULines::slotRightClicked( QListViewItem *item )
+{
+ File * file = 0;
+
+ if ( item && item->text( 0 ) != ".." )
+ file = ((DULinesItem *)item)->getFile();
+
+ KPopupMenu linesPopup;
+ int lid = linesPopup.insertItem( i18n("Show file sizes"), this, SLOT( slotShowFileSizes() ) );
+ linesPopup.setItemChecked( lid, showFileSize );
+
+ diskUsage->rightClickMenu( file, &linesPopup, i18n( "Lines" ) );
+}
+
+void DULines::slotShowFileSizes()
+{
+ showFileSize = !showFileSize;
+ slotDirChanged( diskUsage->getCurrentDir() );
+}
+
+File * DULines::getCurrentFile()
+{
+ QListViewItem *item = currentItem();
+
+ if( item == 0 || item->text( 0 ) == ".." )
+ return 0;
+
+ return ((DULinesItem *)item)->getFile();
+}
+
+void DULines::slotChanged( File * item )
+{
+ QListViewItem *lvitem = firstChild();
+ while( lvitem )
+ {
+ if( lvitem->text( 0 ) != ".." ) {
+ DULinesItem *duItem = (DULinesItem *)( lvitem );
+ if( duItem->getFile() == item )
+ {
+ duItem->setVisible( !item->isExcluded() );
+ duItem->setText( 1, item->percent() );
+ if( !refreshNeeded )
+ {
+ refreshNeeded = true;
+ QTimer::singleShot( 0, this, SLOT( slotRefresh() ) );
+ }
+ break;
+ }
+ }
+ lvitem = lvitem->nextSibling();
+ }
+}
+
+void DULines::slotDeleted( File * item )
+{
+ QListViewItem *lvitem = firstChild();
+ while( lvitem )
+ {
+ if( lvitem->text( 0 ) != ".." ) {
+ DULinesItem *duItem = (DULinesItem *)( lvitem );
+ if( duItem->getFile() == item )
+ {
+ delete duItem;
+ break;
+ }
+ }
+ lvitem = lvitem->nextSibling();
+ }
+}
+
+#include "dulines.moc"
diff --git a/krusader/DiskUsage/dulines.h b/krusader/DiskUsage/dulines.h
new file mode 100644
index 0000000..aa83ad1
--- /dev/null
+++ b/krusader/DiskUsage/dulines.h
@@ -0,0 +1,78 @@
+/***************************************************************************
+ dulines.h - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __DU_LINES_H__
+#define __DU_LINES_H__
+
+#include <qlistview.h>
+#include <qpixmap.h>
+#include "diskusage.h"
+
+class DULinesToolTip;
+
+class DULines : public QListView
+{
+ Q_OBJECT
+
+public:
+ DULines( DiskUsage *usage, const char *name );
+ ~DULines();
+
+ File * getCurrentFile();
+
+public slots:
+ void slotDirChanged( Directory *dirEntry );
+ void sectionResized( int );
+ void slotRightClicked(QListViewItem *);
+ void slotChanged( File * );
+ void slotDeleted( File * );
+ void slotShowFileSizes();
+ void slotRefresh() { refreshNeeded = false; sectionResized( 0 ); }
+
+protected:
+ DiskUsage *diskUsage;
+
+ virtual void contentsMouseDoubleClickEvent ( QMouseEvent * e );
+ virtual void keyPressEvent( QKeyEvent *e );
+
+private:
+ QPixmap createPixmap( int percent, int maxPercent, int maxWidth );
+
+ bool doubleClicked( QListViewItem * item );
+
+ bool refreshNeeded;
+
+ bool showFileSize;
+
+ DULinesToolTip *toolTip;
+};
+
+#endif /* __DU_LINES_H__ */
+
diff --git a/krusader/DiskUsage/dulistview.cpp b/krusader/DiskUsage/dulistview.cpp
new file mode 100644
index 0000000..62c1fcf
--- /dev/null
+++ b/krusader/DiskUsage/dulistview.cpp
@@ -0,0 +1,293 @@
+/***************************************************************************
+ dulistview.cpp - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "dulistview.h"
+#include "../krusader.h"
+#include "../kicons.h"
+#include "../VFS/krpermhandler.h"
+#include <qfontmetrics.h>
+#include <klocale.h>
+#include <kmimetype.h>
+#include <kglobal.h>
+#include <qheader.h>
+#include <time.h>
+
+DUListView::DUListView( DiskUsage *usage, const char *name )
+ : QListView( usage, name ), diskUsage( usage )
+{
+ setAllColumnsShowFocus(true);
+ setVScrollBarMode(QScrollView::Auto);
+ setHScrollBarMode(QScrollView::Auto);
+ setShowSortIndicator(true);
+ setRootIsDecorated( true );
+ setTreeStepSize( 10 );
+
+ int defaultSize = QFontMetrics(font()).width("W");
+
+ krConfig->setGroup( diskUsage->getConfigGroup() );
+ int nameWidth = krConfig->readNumEntry("D Name Width", defaultSize * 20 );
+ addColumn( i18n("Name"), nameWidth );
+ setColumnWidthMode(0,QListView::Manual);
+ int percentWidth = krConfig->readNumEntry("D Percent Width", defaultSize * 5 );
+ addColumn( i18n("Percent"), percentWidth );
+ setColumnWidthMode(1,QListView::Manual);
+ int totalSizeWidth = krConfig->readNumEntry("D Total Size Width", defaultSize * 10 );
+ addColumn( i18n("Total size"), totalSizeWidth );
+ setColumnWidthMode(1,QListView::Manual);
+ int ownSizeWidth = krConfig->readNumEntry("D Own Size Width", defaultSize * 10 );
+ addColumn( i18n("Own size"), ownSizeWidth );
+ setColumnWidthMode(2,QListView::Manual);
+ int typeWidth = krConfig->readNumEntry("D Type Width", defaultSize * 10 );
+ addColumn( i18n("Type"), typeWidth );
+ setColumnWidthMode(3,QListView::Manual);
+ int dateWidth = krConfig->readNumEntry("D Date Width", defaultSize * 10 );
+ addColumn( i18n("Date"), dateWidth );
+ setColumnWidthMode(4,QListView::Manual);
+ int permissionsWidth = krConfig->readNumEntry("D Permissions Width", defaultSize * 6 );
+ addColumn( i18n("Permissions"), permissionsWidth );
+ setColumnWidthMode(5,QListView::Manual);
+ int ownerWidth = krConfig->readNumEntry("D Owner Width", defaultSize * 5 );
+ addColumn( i18n("Owner"), ownerWidth );
+ setColumnWidthMode(6,QListView::Manual);
+ int groupWidth = krConfig->readNumEntry("D Group Width", defaultSize * 5 );
+ addColumn( i18n("Group"), groupWidth );
+ setColumnWidthMode(7,QListView::Manual);
+
+ setColumnAlignment( 1, Qt::AlignRight );
+ setColumnAlignment( 2, Qt::AlignRight );
+ setColumnAlignment( 3, Qt::AlignRight );
+
+ setSorting( 2 );
+
+ connect( diskUsage, SIGNAL( enteringDirectory( Directory * ) ), this, SLOT( slotDirChanged( Directory * ) ) );
+ connect( diskUsage, SIGNAL( clearing() ), this, SLOT( clear() ) );
+ connect( diskUsage, SIGNAL( changed( File * ) ), this, SLOT( slotChanged( File * ) ) );
+ connect( diskUsage, SIGNAL( deleted( File * ) ), this, SLOT( slotDeleted( File * ) ) );
+
+ connect( this, SIGNAL(rightButtonPressed(QListViewItem *, const QPoint &, int)),
+ this, SLOT( slotRightClicked(QListViewItem *) ) );
+ connect( this, SIGNAL( expanded ( QListViewItem * ) ),
+ this, SLOT( slotExpanded( QListViewItem * ) ) );
+}
+
+DUListView::~ DUListView()
+{
+ krConfig->setGroup( diskUsage->getConfigGroup() );
+ krConfig->writeEntry("D Name Width", columnWidth( 0 ) );
+ krConfig->writeEntry("D Percent Width", columnWidth( 1 ) );
+ krConfig->writeEntry("D Total Size Width", columnWidth( 2 ) );
+ krConfig->writeEntry("D Own Size Width", columnWidth( 3 ) );
+ krConfig->writeEntry("D Type Width", columnWidth( 4 ) );
+ krConfig->writeEntry("D Date Width", columnWidth( 5 ) );
+ krConfig->writeEntry("D Permissions Width", columnWidth( 6 ) );
+ krConfig->writeEntry("D Owner Width", columnWidth( 7 ) );
+ krConfig->writeEntry("D Group Width", columnWidth( 8 ) );
+}
+
+void DUListView::addDirectory( Directory *dirEntry, QListViewItem *parent )
+{
+ QListViewItem * lastItem = 0;
+
+ if( parent == 0 && ! ( dirEntry->parent() == 0 ) )
+ {
+ lastItem = new QListViewItem( this, ".." );
+ lastItem->setPixmap( 0, FL_LOADICON( "up" ) );
+ lastItem->setSelectable( false );
+ }
+
+ for( Iterator<File> it = dirEntry->iterator(); it != dirEntry->end(); ++it )
+ {
+ File *item = *it;
+
+ KMimeType::Ptr mimePtr = KMimeType::mimeType( item->mime() );
+ QString mime = mimePtr->comment();
+
+ time_t tma = item->time();
+ struct tm* t=localtime((time_t *)&tma);
+ QDateTime tmp(QDate(t->tm_year+1900, t->tm_mon+1, t->tm_mday), QTime(t->tm_hour, t->tm_min));
+ QString date = KGlobal::locale()->formatDateTime(tmp);
+
+ QString totalSize = KRpermHandler::parseSize( item->size() ) + " ";
+ QString ownSize = KRpermHandler::parseSize( item->ownSize() ) + " ";
+ QString percent = item->percent();
+
+ if( lastItem == 0 && parent == 0 )
+ lastItem = new DUListViewItem( diskUsage, item, this, item->name(), percent, totalSize, ownSize,
+ mime, date, item->perm(), item->owner(), item->group() );
+ else if ( lastItem == 0 )
+ lastItem = new DUListViewItem( diskUsage, item, parent, item->name(), percent, totalSize, ownSize,
+ mime, date, item->perm(), item->owner(), item->group() );
+ else if ( parent == 0 )
+ lastItem = new DUListViewItem( diskUsage, item, this, lastItem, item->name(), percent, totalSize,
+ ownSize, mime, date, item->perm(), item->owner(), item->group() );
+ else
+ lastItem = new DUListViewItem( diskUsage, item, parent, lastItem, item->name(), percent, totalSize,
+ ownSize, mime, date, item->perm(), item->owner(), item->group() );
+
+ if( item->isExcluded() )
+ lastItem->setVisible( false );
+
+ lastItem->setPixmap( 0, diskUsage->getIcon( item->mime() ) );
+
+ if( item->isDir() && !item->isSymLink() )
+ lastItem->setExpandable( true );
+ }
+
+ QListViewItem *first = firstChild();
+ if( first )
+ setCurrentItem( first );
+}
+
+void DUListView::slotDirChanged( Directory *dirEntry )
+{
+ clear();
+ addDirectory( dirEntry, 0 );
+}
+
+File * DUListView::getCurrentFile()
+{
+ QListViewItem *item = currentItem();
+
+ if( item == 0 || item->text( 0 ) == ".." )
+ return 0;
+
+ return ((DUListViewItem *)item)->getFile();
+}
+
+void DUListView::slotChanged( File * item )
+{
+ void * itemPtr = diskUsage->getProperty( item, "ListView-Ref" );
+ if( itemPtr == 0 )
+ return;
+
+ DUListViewItem *duItem = (DUListViewItem *)itemPtr;
+ duItem->setVisible( !item->isExcluded() );
+ duItem->setText( 1, item->percent() );
+ duItem->setText( 2, KRpermHandler::parseSize( item->size() ) + " " );
+ duItem->setText( 3, KRpermHandler::parseSize( item->ownSize() ) + " " );
+}
+
+void DUListView::slotDeleted( File * item )
+{
+ void * itemPtr = diskUsage->getProperty( item, "ListView-Ref" );
+ if( itemPtr == 0 )
+ return;
+
+ DUListViewItem *duItem = (DUListViewItem *)itemPtr;
+ delete duItem;
+}
+
+void DUListView::slotRightClicked( QListViewItem *item )
+{
+ File * file = 0;
+
+ if ( item && item->text( 0 ) != ".." )
+ file = ((DUListViewItem *)item)->getFile();
+
+ diskUsage->rightClickMenu( file );
+}
+
+bool DUListView::doubleClicked( QListViewItem * item )
+{
+ if( item )
+ {
+ if( item->text( 0 ) != ".." )
+ {
+ File *fileItem = ((DUListViewItem *)item)->getFile();
+ if( fileItem->isDir() )
+ diskUsage->changeDirectory( dynamic_cast<Directory *> ( fileItem ) );
+ return true;
+ }
+ else
+ {
+ Directory *upDir = (Directory *)diskUsage->getCurrentDir()->parent();
+
+ if( upDir )
+ diskUsage->changeDirectory( upDir );
+ return true;
+ }
+ }
+ return false;
+}
+
+void DUListView::contentsMouseDoubleClickEvent ( QMouseEvent * e )
+{
+ if ( e || e->button() == LeftButton )
+ {
+ QPoint vp = contentsToViewport(e->pos());
+ QListViewItem * item = itemAt( vp );
+
+ if( doubleClicked( item ) )
+ return;
+
+ }
+ QListView::contentsMouseDoubleClickEvent( e );
+}
+
+void DUListView::keyPressEvent( QKeyEvent *e )
+{
+ switch ( e->key() )
+ {
+ case Key_Return :
+ case Key_Enter :
+ if( doubleClicked( currentItem() ) )
+ return;
+ break;
+ case Key_Left :
+ case Key_Right :
+ case Key_Up :
+ case Key_Down :
+ if( e->state() == ShiftButton )
+ {
+ e->ignore();
+ return;
+ }
+ break;
+ case Key_Delete :
+ e->ignore();
+ return;
+ }
+ QListView::keyPressEvent( e );
+}
+
+void DUListView::slotExpanded( QListViewItem *item )
+{
+ if( item == 0 || item->text( 0 ) == ".." )
+ return;
+
+ if( item->childCount() == 0 )
+ {
+ File *fileItem = ((DUListViewItem *)item)->getFile();
+ if( fileItem->isDir() )
+ addDirectory( dynamic_cast<Directory *>( fileItem ), item );
+ }
+}
+
+#include "dulistview.moc"
diff --git a/krusader/DiskUsage/dulistview.h b/krusader/DiskUsage/dulistview.h
new file mode 100644
index 0000000..01ab59f
--- /dev/null
+++ b/krusader/DiskUsage/dulistview.h
@@ -0,0 +1,144 @@
+/***************************************************************************
+ dulistview.h - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __DU_LISTVIEW_H__
+#define __DU_LISTVIEW_H__
+
+#include <qlistview.h>
+#include "diskusage.h"
+
+class DUListViewItem : public QListViewItem
+{
+public:
+ DUListViewItem( DiskUsage *diskUsageIn, File *fileIn, QListView * parent, QString label1,
+ QString label2, QString label3, QString label4, QString label5, QString label6,
+ QString label7, QString label8, QString label9 )
+ : QListViewItem( parent, label1, label2, label3, label4, label5, label6, label7, label8),
+ diskUsage( diskUsageIn ), file( fileIn )
+ {
+ setText( 8, label9 );
+ diskUsage->addProperty( file, "ListView-Ref", this );
+ }
+ DUListViewItem( DiskUsage *diskUsageIn, File *fileIn, QListViewItem * parent, QString label1,
+ QString label2, QString label3, QString label4, QString label5, QString label6,
+ QString label7, QString label8, QString label9 )
+ : QListViewItem( parent, label1, label2, label3, label4, label5, label6, label7, label8),
+ diskUsage( diskUsageIn ), file( fileIn )
+ {
+ setText( 8, label9 );
+ diskUsage->addProperty( file, "ListView-Ref", this );
+ }
+ DUListViewItem( DiskUsage *diskUsageIn, File *fileIn, QListView * parent, QListViewItem * after,
+ QString label1, QString label2, QString label3, QString label4, QString label5,
+ QString label6, QString label7, QString label8, QString label9 )
+ : QListViewItem( parent, after, label1, label2, label3, label4, label5, label6, label7, label8),
+ diskUsage( diskUsageIn ), file( fileIn )
+ {
+ setText( 8, label9 );
+ diskUsage->addProperty( file, "ListView-Ref", this );
+ }
+ DUListViewItem( DiskUsage *diskUsageIn, File *fileIn, QListViewItem * parent, QListViewItem * after,
+ QString label1, QString label2, QString label3, QString label4, QString label5,
+ QString label6, QString label7, QString label8, QString label9 )
+ : QListViewItem( parent, after, label1, label2, label3, label4, label5, label6, label7, label8),
+ diskUsage( diskUsageIn ), file( fileIn )
+ {
+ setText( 8, label9 );
+ diskUsage->addProperty( file, "ListView-Ref", this );
+ }
+ ~DUListViewItem()
+ {
+ diskUsage->removeProperty( file, "ListView-Ref" );
+ }
+
+ virtual int compare ( QListViewItem * i, int col, bool ascending ) const
+ {
+ if( text(0) == ".." ) return ascending ? -1 : 1;
+ if( i->text(0) == "..") return ascending ? 1 : -1;
+
+ DUListViewItem *compWith = dynamic_cast< DUListViewItem * >( i );
+
+ QString buf1,buf2;
+
+ switch( col )
+ {
+ case 1:
+ case 2:
+ buf1.sprintf("%025llu",file->size());
+ buf2.sprintf("%025llu",compWith->file->size());
+ return -QString::compare( buf1, buf2 );
+ case 3:
+ buf1.sprintf("%025llu",file->ownSize());
+ buf2.sprintf("%025llu",compWith->file->ownSize());
+ return -QString::compare( buf1, buf2 );
+ case 5:
+ return QListViewItem::compare( i, col, !ascending );
+ default:
+ return QListViewItem::compare( i, col, ascending );
+ }
+ }
+
+ inline File * getFile() { return file; }
+
+private:
+ DiskUsage *diskUsage;
+ File *file;
+};
+
+class DUListView : public QListView
+{
+ Q_OBJECT
+
+public:
+ DUListView( DiskUsage *usage, const char *name );
+ ~DUListView();
+
+ File * getCurrentFile();
+
+public slots:
+ void slotDirChanged( Directory * );
+ void slotChanged( File * );
+ void slotDeleted( File * );
+ void slotRightClicked(QListViewItem *);
+ void slotExpanded( QListViewItem * );
+
+protected:
+ DiskUsage *diskUsage;
+
+ virtual void contentsMouseDoubleClickEvent ( QMouseEvent * e );
+ virtual void keyPressEvent( QKeyEvent *e );
+
+private:
+ void addDirectory( Directory *dirEntry, QListViewItem *parent );
+ bool doubleClicked( QListViewItem * item );
+};
+
+#endif /* __DU_LISTVIEW_H__ */
+
diff --git a/krusader/DiskUsage/filelightParts/Config.cpp b/krusader/DiskUsage/filelightParts/Config.cpp
new file mode 100644
index 0000000..777ec68
--- /dev/null
+++ b/krusader/DiskUsage/filelightParts/Config.cpp
@@ -0,0 +1,50 @@
+
+#include "Config.h"
+#include <kconfig.h>
+#include <kglobal.h>
+
+
+bool Config::varyLabelFontSizes = true;
+bool Config::showSmallFiles = false;
+uint Config::contrast = 50;
+uint Config::antiAliasFactor = 2;
+uint Config::minFontPitch = 10;
+uint Config::defaultRingDepth = 4;
+Filelight::MapScheme Config::scheme;
+
+
+inline KConfig&
+Filelight::Config::kconfig()
+{
+ KConfig *config = KGlobal::config();
+ config->setGroup( "DiskUsage" );
+ return *config;
+}
+
+void
+Filelight::Config::read()
+{
+ const KConfig &config = kconfig();
+
+ varyLabelFontSizes = config.readBoolEntry( "varyLabelFontSizes", true );
+ showSmallFiles = config.readBoolEntry( "showSmallFiles", false );
+ contrast = config.readNumEntry( "contrast", 50 );
+ antiAliasFactor = config.readNumEntry( "antiAliasFactor", 2 );
+ minFontPitch = config.readNumEntry( "minFontPitch", QFont().pointSize() - 3);
+ scheme = (MapScheme) config.readNumEntry( "scheme", 0 );
+
+ defaultRingDepth = 4;
+}
+
+void
+Filelight::Config::write()
+{
+ KConfig &config = kconfig();
+
+ config.writeEntry( "varyLabelFontSizes", varyLabelFontSizes );
+ config.writeEntry( "showSmallFiles", showSmallFiles);
+ config.writeEntry( "contrast", contrast );
+ config.writeEntry( "antiAliasFactor", antiAliasFactor );
+ config.writeEntry( "minFontPitch", minFontPitch );
+ config.writeEntry( "scheme", scheme );
+}
diff --git a/krusader/DiskUsage/filelightParts/Config.h b/krusader/DiskUsage/filelightParts/Config.h
new file mode 100644
index 0000000..a0491b6
--- /dev/null
+++ b/krusader/DiskUsage/filelightParts/Config.h
@@ -0,0 +1,37 @@
+
+#ifndef Config_H
+#define Config_H
+
+#include <qstringlist.h>
+
+class KConfig;
+
+
+namespace Filelight
+{
+ enum MapScheme { Rainbow, HighContrast, KDE, FileDensity, ModTime };
+
+ class Config
+ {
+ static KConfig& kconfig();
+
+ public:
+ static void read();
+ static void write();
+
+ //keep everything positive, avoid using DON'T, NOT or NO
+
+ static bool varyLabelFontSizes;
+ static bool showSmallFiles;
+ static uint contrast;
+ static uint antiAliasFactor;
+ static uint minFontPitch;
+ static uint defaultRingDepth;
+
+ static MapScheme scheme;
+ };
+}
+
+using Filelight::Config;
+
+#endif
diff --git a/krusader/DiskUsage/filelightParts/Makefile.am b/krusader/DiskUsage/filelightParts/Makefile.am
new file mode 100644
index 0000000..002f461
--- /dev/null
+++ b/krusader/DiskUsage/filelightParts/Makefile.am
@@ -0,0 +1,9 @@
+noinst_LIBRARIES = libfilelightparts.a
+
+INCLUDES = $(all_includes)
+
+METASOURCES = AUTO
+
+libfilelightparts_a_SOURCES = \
+ Config.cpp \
+ fileTree.cpp
diff --git a/krusader/DiskUsage/filelightParts/debug.h b/krusader/DiskUsage/filelightParts/debug.h
new file mode 100644
index 0000000..252a001
--- /dev/null
+++ b/krusader/DiskUsage/filelightParts/debug.h
@@ -0,0 +1,14 @@
+//Author: Max Howell <max.howell@methylblue.com>, (C) 2003-4
+//Copyright: See COPYING file that comes with this distribution
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+#include <kdebug.h>
+
+#define debug kdDebug
+#define error kdError
+#define fatal kdFatal
+#define warning kdWarning
+
+#endif
diff --git a/krusader/DiskUsage/filelightParts/fileTree.cpp b/krusader/DiskUsage/filelightParts/fileTree.cpp
new file mode 100644
index 0000000..b9409c3
--- /dev/null
+++ b/krusader/DiskUsage/filelightParts/fileTree.cpp
@@ -0,0 +1,78 @@
+//Author: Max Howell <max.howell@methylblue.com>, (C) 2004
+//Copyright: See COPYING file that comes with this distribution
+
+#include "fileTree.h"
+#include <kglobal.h>
+#include <klocale.h>
+#include <qstring.h>
+
+//static definitions
+const FileSize File::DENOMINATOR[4] = { 1ull, 1ull<<10, 1ull<<20, 1ull<<30 };
+const char File::PREFIX[5][2] = { "", "K", "M", "G", "T" };
+
+QString
+File::fullPath( const Directory *root /*= 0*/ ) const
+{
+ QString path;
+
+ if( root == this ) root = 0; //prevent returning empty string when there is something we could return
+
+ const File *d;
+
+ for( d = this; d != root && d && d->parent() != 0; d = d->parent() )
+ {
+ if( !path.isEmpty() )
+ path = "/" + path;
+
+ path = d->name() + path;
+ }
+
+ if( d )
+ {
+ while( d->parent() )
+ d = d->parent();
+
+ if( d->directory().endsWith( "/" ) )
+ return d->directory() + path;
+ else
+ return d->directory() + "/" + path;
+ }
+ else
+ return path;
+}
+
+QString
+File::humanReadableSize( UnitPrefix key /*= mega*/ ) const //FIXME inline
+{
+ return humanReadableSize( m_size, key );
+}
+
+QString
+File::humanReadableSize( FileSize size, UnitPrefix key /*= mega*/ ) //static
+{
+ QString s;
+ double prettySize = (double)size / (double)DENOMINATOR[key];
+ const KLocale &locale = *KGlobal::locale();
+
+ if( prettySize >= 0.01 )
+ {
+ if( prettySize < 1 ) s = locale.formatNumber( prettySize, 2 );
+ else if( prettySize < 100 ) s = locale.formatNumber( prettySize, 1 );
+ else s = locale.formatNumber( prettySize, 0 );
+
+ s += ' ';
+ s += PREFIX[key];
+ s += 'B';
+ }
+
+ if( prettySize < 0.1 )
+ {
+ s += " (";
+ s += locale.formatNumber( size / DENOMINATOR[ key ? key - 1 : 0 ], 0 );
+ s += ' ';
+ s += PREFIX[key];
+ s += "B)";
+ }
+
+ return s;
+}
diff --git a/krusader/DiskUsage/filelightParts/fileTree.h b/krusader/DiskUsage/filelightParts/fileTree.h
new file mode 100644
index 0000000..f4d98b6
--- /dev/null
+++ b/krusader/DiskUsage/filelightParts/fileTree.h
@@ -0,0 +1,299 @@
+//Author: Max Howell <max.howell@methylblue.com>, (C) 2004
+//Copyright: See COPYING file that comes with this distribution
+
+#ifndef FILETREE_H
+#define FILETREE_H
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <kio/global.h>
+
+//TODO these are pointlessly general purpose now, make them incredibly specific
+
+
+
+typedef KIO::filesize_t FileSize;
+
+template <class T> class Iterator;
+template <class T> class ConstIterator;
+template <class T> class Chain;
+
+template <class T>
+class Link
+{
+public:
+ 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<T>;
+ friend class ConstIterator<T>;
+ friend class Chain<T>;
+
+private:
+ void unlink() { prev->next = next; next->prev = prev; prev = next = this; }
+
+ Link<T>* prev;
+ Link<T>* next;
+
+ T* data; //ensure only iterators have access to this
+};
+
+
+template <class T>
+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<T> *p ) : link( p ) { }
+
+ bool operator==( const Iterator<T>& it ) const { return link == it.link; }
+ bool operator!=( const Iterator<T>& it ) const { return link != it.link; }
+ bool operator!=( const Link<T> *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<T>& 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<T> &chain )
+ {
+ chain.append( remove() );
+ }
+
+ T* const remove() //remove from list, delete Link, data is returned NOT deleted
+ {
+ T* const d = link->data;
+ Link<T>* 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<T> *link;
+};
+
+
+template <class T>
+class ConstIterator
+{
+public:
+ ConstIterator( Link<T> *p ) : link( p ) { }
+
+ bool operator==( const Iterator<T>& it ) const { return link == it.link; }
+ bool operator!=( const Iterator<T>& it ) const { return link != it.link; }
+ bool operator!=( const Link<T> *p ) const { return p != link; }
+
+ const T* operator*() const { return link->data; }
+
+ ConstIterator<T>& operator++() { link = link->next; return *this; }
+
+private:
+ const Link<T> *link;
+};
+
+//**** try to make a generic list class and then a brief full list template that inlines
+// thus reducing code bloat
+template <class T>
+class Chain
+{
+public:
+ Chain() { }
+ virtual ~Chain() { empty(); }
+
+ void append( T* const data )
+ {
+ Link<T>* const link = new Link<T>( data );
+
+ link->prev = head.prev;
+ link->next = &head;
+
+ head.prev->next = link;
+ head.prev = link;
+ }
+
+ void transferTo( Chain &c )
+ {
+ if( isEmpty() ) return;
+
+ Link<T>* const first = head.next;
+ Link<T>* 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<T> iterator() const { return Iterator<T>( head.next ); }
+ ConstIterator<T> constIterator() const { return ConstIterator<T>( head.next ); }
+ const Link<T> *end() const { return &head; }
+ bool isEmpty() const { return ( head.next == &head ); }
+
+private:
+ Link<T> head;
+ void operator=( const Chain& ) {}
+};
+
+
+class Directory;
+class QString;
+class KURL;
+
+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::null ), m_size( sizeIn ), m_ownSize( sizeIn ), m_mode( 0 ),
+ m_owner( QString::null ), m_group( QString::null ), m_perm( QString::null ), m_time( -1 ),
+ m_symLink( false ), m_mimeType( QString::null ), 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 const FileSize size() const {return m_excluded ? 0 : m_size;}
+ inline const FileSize ownSize() const {return m_excluded ? 0 : m_ownSize;}
+ inline const 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 const time_t time() const {return m_time;}
+ inline const QString & mime() const {return m_mimeType;}
+ inline const bool isSymLink() const {return m_symLink;}
+ virtual const bool isDir() const {return false;}
+ inline const bool isExcluded() const {return m_excluded;}
+ inline void exclude( bool flag ) {m_excluded = flag;}
+ inline const 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<File>, 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 const 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<File>::append( p );
+ p->m_parent = this;
+ }
+
+ void remove( File *p )
+ {
+ for( Iterator<File> it = Chain<File>::iterator(); it != Chain<File>::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/Makefile.am b/krusader/DiskUsage/radialMap/Makefile.am
new file mode 100644
index 0000000..a3a3e74
--- /dev/null
+++ b/krusader/DiskUsage/radialMap/Makefile.am
@@ -0,0 +1,14 @@
+noinst_LIBRARIES = libradialmap.a
+
+INCLUDES = -I$(top_srcdir)/krusader/DiskUsage/filelightParts \
+ $(all_includes)
+
+METASOURCES = AUTO
+
+libradialmap_a_SOURCES = \
+ widget.cpp \
+ builder.cpp \
+ map.cpp \
+ widgetEvents.cpp \
+ labels.cpp \
+ segmentTip.cpp
diff --git a/krusader/DiskUsage/radialMap/builder.cpp b/krusader/DiskUsage/radialMap/builder.cpp
new file mode 100644
index 0000000..5a827af
--- /dev/null
+++ b/krusader/DiskUsage/radialMap/builder.cpp
@@ -0,0 +1,139 @@
+//Author: Max Howell <max.howell@methylblue.com>, (C) 2003-4
+//Copyright: See COPYING file that comes with this distribution
+
+#include "builder.h"
+#include "Config.h"
+#include "fileTree.h"
+#include <kglobal.h> //locale object
+#include <klocale.h>
+#include "widget.h"
+
+
+//**** REMOVE NEED FOR the +1 with MAX_RING_DEPTH uses
+//**** add some angle bounds checking (possibly in Segment ctor? can I delete in a ctor?)
+//**** this class is a mess
+
+RadialMap::Builder::Builder( RadialMap::Map *m, const Directory* const d, bool fast )
+ : m_map( m )
+ , m_root( d )
+ , m_minSize( static_cast<FileSize>((d->size() * 3) / (PI * m->height() - m->MAP_2MARGIN )) )
+ , m_depth( &m->m_visibleDepth )
+{
+ m_signature = new Chain<Segment> [*m_depth + 1];
+
+ if( !fast )//|| *m_depth == 0 ) //depth 0 is special case usability-wise //**** WHY?!
+ {
+ //determine depth rather than use old one
+ findVisibleDepth( d ); //sets m_depth
+ }
+
+ m_map->setRingBreadth();
+ setLimits( m_map->m_ringBreadth );
+ build( d );
+
+ m_map->m_signature = m_signature;
+
+ delete []m_limits;
+}
+
+
+void
+RadialMap::Builder::findVisibleDepth( const Directory* const dir, const unsigned int depth )
+{
+ //**** because I don't use the same minimumSize criteria as in the visual function
+ // this can lead to incorrect visual representation
+ //**** BUT, you can't set those limits until you know m_depth!
+
+ //**** also this function doesn't check to see if anything is actually visible
+ // it just assumes that when it reaches a new level everything in it is visible
+ // automatically. This isn't right especially as there might be no files in the
+ // dir provided to this function!
+
+ static uint stopDepth = 0;
+
+ if( dir == m_root )
+ {
+ stopDepth = *m_depth;
+ *m_depth = 0;
+ }
+
+ if( *m_depth < depth ) *m_depth = depth;
+ if( *m_depth >= stopDepth ) return;
+
+ for( ConstIterator<File> it = dir->constIterator(); it != dir->end(); ++it )
+ if( (*it)->isDir() && (*it)->size() > m_minSize )
+ findVisibleDepth( (Directory *)*it, depth + 1 ); //if no files greater than min size the depth is still recorded
+}
+
+void
+RadialMap::Builder::setLimits( const uint &b ) //b = breadth?
+{
+ double size3 = m_root->size() * 3;
+ double pi2B = PI * 2 * b;
+
+ m_limits = new FileSize [*m_depth + 1]; //FIXME delete!
+
+ for( unsigned int d = 0; d <= *m_depth; ++d )
+ m_limits[d] = (FileSize)(size3 / (double)(pi2B * (d + 1))); //min is angle that gives 3px outer diameter for that depth
+}
+
+
+//**** segments currently overlap at edges (i.e. end of first is start of next)
+bool
+RadialMap::Builder::build( const Directory* const dir, const unsigned int depth, unsigned int a_start, const unsigned int a_end )
+{
+ //first iteration: dir == m_root
+
+ if( dir->fileCount() == 0 ) //we do fileCount rather than size to avoid chance of divide by zero later
+ return false;
+
+ FileSize hiddenSize = 0;
+ uint hiddenFileCount = 0;
+
+ for( ConstIterator<File> it = dir->constIterator(); it != dir->end(); ++it )
+ {
+ if( (*it)->size() > m_limits[depth] )
+ {
+ unsigned int a_len = (unsigned int)(5760 * ((double)(*it)->size() / (double)m_root->size()));
+
+ Segment *s = new Segment( *it, a_start, a_len );
+
+ (m_signature + depth)->append( s );
+
+ if( (*it)->isDir() )
+ {
+ if( depth != *m_depth )
+ {
+ //recurse
+ s->m_hasHiddenChildren = build( (Directory*)*it, depth + 1, a_start, a_start + a_len );
+ }
+ else s->m_hasHiddenChildren = true;
+ }
+
+ a_start += a_len; //**** should we add 1?
+
+ } else {
+
+ hiddenSize += (*it)->size();
+
+ if( (*it)->isDir() ) //**** considered virtual, but dir wouldn't count itself!
+ hiddenFileCount += static_cast<const Directory*>(*it)->fileCount(); //need to add one to count the dir as well
+
+ ++hiddenFileCount;
+ }
+ }
+
+ if( hiddenFileCount == dir->fileCount() && !Config::showSmallFiles )
+
+ return true;
+
+ else if( (Config::showSmallFiles && hiddenSize > m_limits[depth]) || (depth == 0 && (hiddenSize > dir->size()/8)) /*|| > size() * 0.75*/ )
+ {
+ //append a segment for unrepresented space - a "fake" segment
+
+ const QString s = i18n( "%1 files: ~ %2" ).arg( KGlobal::locale()->formatNumber( hiddenFileCount, 0 ) ).arg( File::humanReadableSize( hiddenSize/hiddenFileCount ) );
+ (m_signature + depth)->append( new Segment( new File( s, hiddenSize ), a_start, a_end - a_start, true ) );
+ }
+
+ return false;
+}
diff --git a/krusader/DiskUsage/radialMap/builder.h b/krusader/DiskUsage/radialMap/builder.h
new file mode 100644
index 0000000..2fddbe0
--- /dev/null
+++ b/krusader/DiskUsage/radialMap/builder.h
@@ -0,0 +1,37 @@
+//Author: Max Howell <max.howell@methylblue.com>, (C) 2003-4
+//Copyright: See COPYING file that comes with this distribution
+
+#ifndef BUILDER_H
+#define BUILDER_H
+
+#include "radialMap.h" //Segment, defines
+#include "fileTree.h"
+
+template <class T> class Chain;
+
+namespace RadialMap
+{
+ class Map;
+
+ //temporary class that builds the Map signature
+
+ class Builder
+ {
+ public:
+ Builder( Map*, const Directory* const, bool fast=false );
+
+ private:
+ void findVisibleDepth( const Directory* const dir, const uint=0 );
+ void setLimits( const uint& );
+ bool build( const Directory* const, const uint=0, uint=0, const uint=5760 );
+
+ Map *m_map;
+ const Directory* const m_root;
+ const FileSize m_minSize;
+ uint *m_depth;
+ Chain<Segment> *m_signature;
+ FileSize *m_limits;
+ };
+}
+
+#endif
diff --git a/krusader/DiskUsage/radialMap/labels.cpp b/krusader/DiskUsage/radialMap/labels.cpp
new file mode 100644
index 0000000..5ba77ac
--- /dev/null
+++ b/krusader/DiskUsage/radialMap/labels.cpp
@@ -0,0 +1,342 @@
+//Author: Max Howell <max.howell@methylblue.com>, (C) 2003-4
+//Copyright: See COPYING file that comes with this distribution
+
+#include <kstringhandler.h>
+#include <qfont.h>
+#include <qfontmetrics.h>
+#include <qpainter.h>
+#include <qptrlist.h>
+
+#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 QPtrList<Label>
+ {
+ protected:
+ int compareItems( QPtrCollection::Item item1, QPtrCollection::Item item2 )
+ {
+ //you add 1440 to work round the fact that later you want the circle split vertically
+ //and as it is you start at 3 o' clock. It's to do with rightPrevY, stops annoying bug
+
+ int a1 = ((Label*)item1)->a + 1440;
+ int a2 = ((Label*)item2)->a + 1440;
+
+ if( a1 == a2 )
+ return 0;
+
+ if( a1 > 5760 ) a1 -= 5760;
+ if( a2 > 5760 ) a2 -= 5760;
+
+ if( a1 > a2 )
+ return 1;
+
+ return -1;
+ }
+ };
+}
+
+
+void
+RadialMap::Widget::paintExplodedLabels( QPainter &paint ) const
+{
+ //we are a friend of RadialMap::Map
+
+ LabelList list; list.setAutoDelete( true );
+ QPtrListIterator<Label> it( list );
+ unsigned int startLevel = 0;
+
+
+ //1. Create list of labels sorted in the order they will be rendered
+
+ if( m_focus != NULL && m_focus->file() != m_tree ) //separate behavior for selected vs unselected segments
+ {
+ //don't bother with files
+ if( m_focus->file() == 0 || !m_focus->file()->isDir() ) return;
+
+ //find the range of levels we will be potentially drawing labels for
+ for( const Directory *p = (const Directory *)m_focus->file();
+ p != m_tree;
+ ++startLevel ) //startLevel is the level above whatever m_focus is in
+ {
+ p = p->parent();
+ }
+
+ //range=2 means 2 levels to draw labels for
+
+ unsigned int a1, a2, minAngle;
+
+ a1 = m_focus->start();
+ a2 = m_focus->end(); //boundry angles
+ minAngle = int(m_focus->length() * LABEL_MIN_ANGLE_FACTOR);
+
+
+ #define segment (*it)
+ #define ring (m_map.m_signature + i)
+
+ //**** Levels should be on a scale starting with 0
+ //**** range is a useless parameter
+ //**** keep a topblock var which is the lowestLevel OR startLevel for identation purposes
+ for( unsigned int i = startLevel; i <= m_map.m_visibleDepth; ++i )
+ {
+ for( Iterator<Segment> it = ring->iterator(); it != ring->end(); ++it )
+ if( segment->start() >= a1 && segment->end() <= a2 )
+ if( segment->length() > minAngle )
+ list.inSort( new Label( segment, i ) );
+ }
+
+ #undef ring
+ #undef segment
+
+ } else {
+
+ #define ring m_map.m_signature
+
+ for( Iterator<Segment> it = ring->iterator(); it != ring->end(); ++it )
+ if( (*it)->length() > 288 )
+ list.inSort( new Label( (*it), 0 ) );
+
+ #undef ring
+
+ }
+
+ //2. Check to see if any adjacent labels are too close together
+ // if so, remove the least significant labels
+
+ it.toFirst();
+ QPtrListIterator<Label> jt( it );
+ ++jt;
+
+ while( jt ) //**** no need to check _it_ as jt will be NULL if _it_ was too
+ {
+ //this method is fairly efficient
+
+ if( (*it)->tooClose( (*jt)->a ) )
+ {
+ if( (*it)->lvl > (*jt)->lvl )
+ {
+ list.remove( *it );
+ it = jt;
+ }
+ else
+ list.remove( *jt );
+ }
+ else
+ ++it;
+
+ jt = it;
+ ++jt;
+ }
+
+ //used in next two steps
+ bool varySizes;
+ //**** should perhaps use doubles
+ int *sizes = new int [ m_map.m_visibleDepth + 1 ]; //**** make sizes an array of floats I think instead (or doubles)
+
+ do
+ {
+ //3. Calculate font sizes
+
+ {
+ //determine current range of levels to draw for
+ unsigned int range = 0;
+
+ for( it.toFirst(); it != 0; ++it )
+ {
+ unsigned int lvl = (*it)->lvl;
+ if( lvl > range )
+ range = lvl;
+
+ //**** better way would just be to assign if nothing is range
+ }
+
+ range -= startLevel; //range 0 means 1 level of labels
+
+ varySizes = Config::varyLabelFontSizes && (range != 0);
+
+ if( varySizes )
+ {
+ //create an array of font sizes for various levels
+ //will exceed normal font pitch automatically if necessary, but not minPitch
+ //**** this needs to be checked lots
+
+ //**** what if this is negative (min size gtr than default size)
+ unsigned int step = (paint.font().pointSize() - Config::minFontPitch) / range;
+ if( step == 0 ) step = 1;
+
+ for( unsigned int x = range + startLevel, y = Config::minFontPitch;
+ x >= startLevel;
+ y += step, --x )
+ {
+ sizes[x] = y;
+ }
+ }
+ }
+
+ //4. determine label co-ordinates
+
+ int x1, y1, x2, y2, x3, tx, ty; //coords
+ double sinra, cosra, ra; //angles
+
+ int cx = m_map.width() / 2 + m_offset.x(); //centre relative to canvas
+ int cy = m_map.height() / 2 + m_offset.y();
+
+ int spacer, preSpacer = int(m_map.m_ringBreadth * 0.5) + m_map.m_innerRadius;
+ int fullStrutLength = ( m_map.width() - m_map.MAP_2MARGIN ) / 2 + LABEL_MAP_SPACER; //full length of a strut from map center
+
+ int prevLeftY = 0;
+ int prevRightY = height();
+
+ bool rightSide;
+
+ QFont font;
+
+ for( it.toFirst(); it != 0; ++it )
+ {
+ //** bear in mind that text is drawn with QPoint param as BOTTOM left corner of text box
+ if( varySizes ) font.setPointSize( sizes[(*it)->lvl] );
+ QFontMetrics fm( font );
+ int fmh = fm.height(); //used to ensure label texts don't overlap
+ int fmhD4 = fmh / 4;
+
+ fmh += LABEL_TEXT_VMARGIN;
+
+ rightSide = ( (*it)->a < 1440 || (*it)->a > 4320 );
+
+ ra = M_PI/2880 * (*it)->a; //convert to radians
+#if 0
+ sincos( ra, &sinra, &cosra );
+#endif
+ sinra = sin(ra); cosra = cos(ra);
+
+ spacer = preSpacer + m_map.m_ringBreadth * (*it)->lvl;
+
+ x1 = cx + (int)(cosra * spacer);
+ y1 = cy - (int)(sinra * spacer);
+ y2 = y1 - (int)(sinra * (fullStrutLength - spacer));
+
+ if( rightSide ) { //righthand side, going upwards
+
+ if( y2 > prevRightY /*- fmh*/ ) //then it is too low, needs to be drawn higher
+ y2 = prevRightY /*- fmh*/;
+
+ } else { //lefthand side, going downwards
+
+ if( y2 < prevLeftY/* + fmh*/ ) //then we're too high, need to be drawn lower
+ y2 = prevLeftY /*+ fmh*/;
+ }
+
+ x2 = x1 - int(double(y2 - y1) / tan( ra ));
+ ty = y2 + fmhD4;
+
+ QString qs;
+ if( rightSide ) {
+
+ if( x2 > width() || ty < fmh || x2 < x1 )
+ {
+ //skip this strut
+ //**** don't duplicate this code
+ list.remove( *it ); //will delete the label and set it to list.current() which _should_ be the next ptr
+ break;
+ }
+
+ prevRightY = ty - fmh - fmhD4; //must be after above's "continue"
+
+ qs = KStringHandler::cPixelSqueeze( (*it)->segment->file()->name(), fm, width() - x2 );
+
+ x3 = width() - fm.width( qs )
+ - LABEL_HMARGIN //outer margin
+ - LABEL_TEXT_HMARGIN //margin between strut and text
+ //- ((*it)->lvl - startLevel) * LABEL_HMARGIN //indentation
+ ;
+ if( x3 < x2 ) x3 = x2;
+ tx = x3 + LABEL_TEXT_HMARGIN;
+
+ } else {
+
+ if( x2 < 0 || ty > height() || x2 > x1 )
+ {
+ //skip this strut
+ list.remove( *it ); //will delete the label and set it to list.current() which _should_ be the next ptr
+ break;
+ }
+
+ prevLeftY = ty + fmh - fmhD4;
+
+ qs = KStringHandler::cPixelSqueeze( (*it)->segment->file()->name(), fm, x2 );
+
+ //**** needs a little tweaking:
+
+ tx = fm.width( qs ) + LABEL_HMARGIN/* + ((*it)->lvl - startLevel) * LABEL_HMARGIN*/;
+ if( tx > x2 ) { //text is too long
+ tx = LABEL_HMARGIN + x2 - tx; //some text will be lost from sight
+ x3 = x2; //no text margin (right side of text here)
+ } else {
+ x3 = tx + LABEL_TEXT_HMARGIN;
+ tx = LABEL_HMARGIN /* + ((*it)->lvl - startLevel) * LABEL_HMARGIN*/;
+ }
+ }
+
+ (*it)->x1 = x1;
+ (*it)->y1 = y1;
+ (*it)->x2 = x2;
+ (*it)->y2 = y2;
+ (*it)->x3 = x3;
+ (*it)->tx = tx;
+ (*it)->ty = ty;
+ (*it)->qs = qs;
+ }
+
+ //if an element is deleted at this stage, we need to do this whole
+ //iteration again, thus the following loop
+ //**** in rare case that deleted label was last label in top level
+ // and last in labelList too, this will not work as expected (not critical)
+
+ } while( it != 0 );
+
+
+ //5. Render labels
+
+ paint.setPen( QPen( Qt::black, 1 ) );
+
+ for( it.toFirst(); it != 0; ++it )
+ {
+ if( varySizes )
+ {
+ //**** how much overhead in making new QFont each time?
+ // (implicate sharing remember)
+ QFont font = paint.font();
+ font.setPointSize( sizes[(*it)->lvl] );
+ paint.setFont( font );
+ }
+
+ paint.drawEllipse( (*it)->x1 - 3, (*it)->y1 - 3, 7, 7 ); //**** CPU intensive! better to use a pixmap
+ paint.drawLine( (*it)->x1, (*it)->y1, (*it)->x2, (*it)->y2 );
+ paint.drawLine( (*it)->x2, (*it)->y2, (*it)->x3, (*it)->y2);
+ paint.drawText( (*it)->tx, (*it)->ty, (*it)->qs );
+ }
+
+ delete [] sizes;
+}
diff --git a/krusader/DiskUsage/radialMap/map.cpp b/krusader/DiskUsage/radialMap/map.cpp
new file mode 100644
index 0000000..1a2899f
--- /dev/null
+++ b/krusader/DiskUsage/radialMap/map.cpp
@@ -0,0 +1,432 @@
+//Author: Max Howell <max.howell@methylblue.com>, (C) 2003-4
+//Copyright: See COPYING file that comes with this distribution
+
+#include <kcursor.h> //make()
+#include <kglobalsettings.h> //kdeColours
+#include <kimageeffect.h> //desaturate()
+#include <qapplication.h> //make()
+#include <qimage.h> //make() & paint()
+#include <qfont.h> //ctor
+#include <qfontmetrics.h> //ctor
+#include <qpainter.h>
+
+#include "builder.h"
+#include "Config.h"
+#include "fileTree.h"
+#include "sincos.h"
+#include "widget.h"
+
+#define COLOR_GREY QColor( 0, 0, 140, QColor::Hsv )
+
+
+RadialMap::Map::Map()
+ : m_signature( 0 )
+ , m_ringBreadth( MIN_RING_BREADTH )
+ , m_innerRadius( 0 )
+ , m_visibleDepth( DEFAULT_RING_DEPTH )
+{
+ //FIXME this is all broken. No longer is a maximum depth!
+ const int fmh = QFontMetrics( QFont() ).height();
+ const int fmhD4 = fmh / 4;
+ MAP_2MARGIN = 2 * ( fmh - (fmhD4 - LABEL_MAP_SPACER) ); //margin is dependent on fitting in labels at top and bottom
+}
+
+RadialMap::Map::~Map()
+{
+ delete [] m_signature;
+}
+
+void
+RadialMap::Map::invalidate( const bool desaturateTheImage )
+{
+ delete [] m_signature;
+ m_signature = 0;
+
+ if( desaturateTheImage )
+ {
+ QImage img = this->convertToImage();
+
+ KImageEffect::desaturate( img, 0.7 );
+ KImageEffect::toGray( img, true );
+
+ this->convertFromImage( img );
+ }
+
+ m_visibleDepth = Config::defaultRingDepth;
+}
+
+void
+RadialMap::Map::make( const Directory *tree, bool refresh )
+{
+ //**** determineText seems pointless optimisation
+ // but is it good to keep the text consistent?
+ // even if it makes it a lie?
+
+ //slow operation so set the wait cursor
+ QApplication::setOverrideCursor( KCursor::waitCursor() );
+
+ {
+ //build a signature of visible components
+ delete [] m_signature;
+ Builder builder( this, tree, refresh );
+ }
+
+ //colour the segments
+ colorise();
+
+ //determine centerText
+ if( !refresh )
+ {
+ int i;
+
+ for( i = 3; i > 0; --i )
+ if( tree->size() > File::DENOMINATOR[i] )
+ break;
+
+ m_centerText = tree->humanReadableSize( (File::UnitPrefix)i );
+ }
+
+ //paint the pixmap
+ aaPaint();
+
+ QApplication::restoreOverrideCursor();
+}
+
+void
+RadialMap::Map::setRingBreadth()
+{
+ m_ringBreadth = (height() - MAP_2MARGIN) / (2 * m_visibleDepth + 4);
+
+ if( m_ringBreadth < MIN_RING_BREADTH ) m_ringBreadth = MIN_RING_BREADTH;
+ else if( m_ringBreadth > MAX_RING_BREADTH ) m_ringBreadth = MAX_RING_BREADTH;
+}
+
+bool
+RadialMap::Map::resize( const QRect &rect )
+{
+ //there's a MAP_2MARGIN border
+
+ #define mw width()
+ #define mh height()
+ #define cw rect.width()
+ #define ch rect.height()
+
+ if( cw < mw || ch < mh || (cw > mw && ch > mh) )
+ {
+ uint size = (( cw < ch ) ? cw : ch) - MAP_2MARGIN;
+
+ //this also causes uneven sizes to always resize when resizing but map is small in that dimension
+ //size -= size % 2; //even sizes mean less staggered non-antialiased resizing
+
+ {
+ const uint minSize = MIN_RING_BREADTH * 2 * (m_visibleDepth + 2);
+ const uint mD2 = MAP_2MARGIN / 2;
+
+ if( size < minSize ) size = minSize;
+
+ //this QRect is used by paint()
+ m_rect.setRect( mD2, mD2, size, size );
+ }
+
+ //resize the pixmap
+ size += MAP_2MARGIN;
+ KPixmap::resize( size, size );
+
+ if( m_signature != NULL )
+ {
+ setRingBreadth();
+ paint();
+ }
+ else fill(); //FIXME I don't like having to do this..
+
+ return true;
+ }
+
+ #undef mw
+ #undef mh
+ #undef cw
+ #undef ch
+
+ return false;
+}
+
+void
+RadialMap::Map::colorise()
+{
+ QColor cp, cb;
+ double darkness = 1;
+ double contrast = (double)Config::contrast / (double)100;
+ int h, s1, s2, v1, v2;
+
+ QColor kdeColour[2] = { KGlobalSettings::inactiveTitleColor(), KGlobalSettings::activeTitleColor() };
+
+ double deltaRed = (double)(kdeColour[0].red() - kdeColour[1].red()) / 2880; //2880 for semicircle
+ double deltaGreen = (double)(kdeColour[0].green() - kdeColour[1].green()) / 2880;
+ double deltaBlue = (double)(kdeColour[0].blue() - kdeColour[1].blue()) / 2880;
+
+ for( uint i = 0; i <= m_visibleDepth; ++i, darkness += 0.04 )
+ {
+ for( Iterator<Segment> it = m_signature[i].iterator(); it != m_signature[i].end(); ++it )
+ {
+ switch( Config::scheme )
+ {
+ case 2000: //HACK for summary view
+
+ if( (*it)->file()->name() == "Used" ) {
+ cb = QApplication::palette().active().color( QColorGroup::Highlight );
+ cb.hsv( &h, &s1, &v1 );
+
+ if( s1 > 80 )
+ s1 = 80;
+
+ v2 = v1 - int(contrast * v1);
+ s2 = s1 + int(contrast * (255 - s1));
+
+ cb.setHsv( h, s1, v1 );
+ cp.setHsv( h, s2, v2 );
+ }
+ else {
+ cp = Qt::gray;
+ cb = Qt::white;
+ }
+
+ (*it)->setPalette( cp, cb );
+
+ continue;
+ case Filelight::KDE:
+ {
+ //gradient will work by figuring out rgb delta values for 360 degrees
+ //then each component is angle*delta
+
+ int a = (*it)->start();
+
+ if( a > 2880 ) a = 2880 - (a - 2880);
+
+ h = (int)(deltaRed * a) + kdeColour[1].red();
+ s1 = (int)(deltaGreen * a) + kdeColour[1].green();
+ v1 = (int)(deltaBlue * a) + kdeColour[1].blue();
+
+ cb.setRgb( h, s1, v1 );
+ cb.hsv( &h, &s1, &v1 );
+
+ break;
+ }
+
+ case Filelight::HighContrast:
+
+ cp.setHsv( 0, 0, 0 ); //values of h, s and v are irrelevant
+ cb.setHsv( 180, 0, int(255.0 * contrast) );
+ (*it)->setPalette( cp, cb );
+ continue;
+
+ default:
+ h = int((*it)->start() / 16);
+ s1 = 160;
+ v1 = (int)(255.0 / darkness); //****doing this more often than once seems daft!
+ }
+
+ v2 = v1 - int(contrast * v1);
+ s2 = s1 + int(contrast * (255 - s1));
+
+ if( s1 < 80 ) s1 = 80; //can fall too low and makes contrast between the files hard to discern
+
+ if( (*it)->isFake() ) //multi-file
+ {
+ cb.setHsv( h, s2, (v2 < 90) ? 90 : v2 ); //too dark if < 100
+ cp.setHsv( h, 17, v1 );
+ }
+ else if( !(*it)->file()->isDir() ) //file
+ {
+ cb.setHsv( h, 17, v1 );
+ cp.setHsv( h, 17, v2 );
+ }
+ else //directory
+ {
+ cb.setHsv( h, s1, v1 ); //v was 225
+ cp.setHsv( h, s2, v2 ); //v was 225 - delta
+ }
+
+ (*it)->setPalette( cp, cb );
+
+ //**** may be better to store KDE colours as H and S and vary V as others
+ //**** perhaps make saturation difference for s2 dependent on contrast too
+ //**** fake segments don't work with highContrast
+ //**** may work better with cp = cb rather than Qt::white
+ //**** you have to ensure the grey of files is sufficient, currently it works only with rainbow (perhaps use contrast there too)
+ //**** change v1,v2 to vp, vb etc.
+ //**** using percentages is not strictly correct as the eye doesn't work like that
+ //**** darkness factor is not done for kde_colour scheme, and also value for files is incorrect really for files in this scheme as it is not set like rainbow one is
+ }
+ }
+}
+
+void
+RadialMap::Map::aaPaint()
+{
+ //paint() is called during continuous processes
+ //aaPaint() is not and is slower so set overidecursor (make sets it too)
+ QApplication::setOverrideCursor( KCursor::waitCursor() );
+ paint( Config::antiAliasFactor );
+ QApplication::restoreOverrideCursor();
+}
+
+void
+RadialMap::Map::paint( unsigned int scaleFactor )
+{
+ if( scaleFactor == 0 ) //just in case
+ scaleFactor = 1;
+
+ QPainter paint;
+ QRect rect = m_rect;
+ int step = m_ringBreadth;
+ int excess = -1;
+
+ //scale the pixmap, or do intelligent distribution of excess to prevent nasty resizing
+ if( scaleFactor > 1 )
+ {
+ int x1, y1, x2, y2;
+ rect.coords( &x1, &y1, &x2, &y2 );
+ x1 *= scaleFactor;
+ y1 *= scaleFactor;
+ x2 *= scaleFactor;
+ y2 *= scaleFactor;
+ rect.setCoords( x1, y1, x2, y2 );
+
+ step *= scaleFactor;
+ KPixmap::resize( this->size() * (int)scaleFactor );
+ }
+ else if( m_ringBreadth != MAX_RING_BREADTH && m_ringBreadth != MIN_RING_BREADTH ) {
+ excess = rect.width() % m_ringBreadth;
+ ++step;
+ }
+
+ //**** best option you can think of is to make the circles slightly less perfect,
+ // ** i.e. slightly eliptic when resizing inbetween
+
+
+ paint.begin( this );
+
+ fill(); //erase background
+
+ for( int x = m_visibleDepth; x >= 0; --x )
+ {
+ int width = rect.width() / 2;
+ //clever geometric trick to find largest angle that will give biggest arrow head
+ int a_max = int(acos( (double)width / double((width + 5) * scaleFactor) ) * (180*16 / M_PI));
+
+ for( ConstIterator<Segment> it = m_signature[x].constIterator(); it != m_signature[x].end(); ++it )
+ {
+ //draw the pie segments, most of this code is concerned with drawing the little
+ //arrows on the ends of segments when they have hidden files
+
+ paint.setPen( (*it)->pen() );
+
+ if( (*it)->hasHiddenChildren() )
+ {
+ //draw arrow head to indicate undisplayed files/directories
+ QPointArray pts( 3 );
+ QPoint pos, cpos = rect.center();
+ int a[3] = { (*it)->start(), (*it)->length(), 0 };
+
+ a[2] = a[0] + (a[1] / 2); //assign to halfway between
+ if( a[1] > a_max )
+ {
+ a[1] = a_max;
+ a[0] = a[2] - a_max / 2;
+ }
+
+ a[1] += a[0];
+
+ for( int i = 0, radius = width; i < 3; ++i )
+ {
+ double ra = M_PI/(180*16) * a[i], sinra, cosra;
+
+ if( i == 2 )
+ radius += 5 * scaleFactor;
+#if 0
+ sincos( ra, &sinra, &cosra );
+#endif
+ sinra = sin(ra); cosra = cos(ra);
+ pos.rx() = cpos.x() + static_cast<int>(cosra * radius);
+ pos.ry() = cpos.y() - static_cast<int>(sinra * radius);
+ pts.setPoint( i, pos );
+ }
+
+ paint.setBrush( (*it)->pen() );
+ paint.drawPolygon( pts );
+ }
+
+ paint.setBrush( (*it)->brush() );
+ paint.drawPie( rect, (*it)->start(), (*it)->length() );
+
+ if( (*it)->hasHiddenChildren() )
+ {
+ //**** code is bloated!
+ paint.save();
+ QPen pen = paint.pen();
+ int width = 2 * scaleFactor;
+ pen.setWidth( width );
+ paint.setPen( pen );
+ QRect rect2 = rect;
+ width /= 2;
+ rect2.addCoords( width, width, -width, -width );
+ paint.drawArc( rect2, (*it)->start(), (*it)->length() );
+ paint.restore();
+ }
+ }
+
+ if( excess >= 0 ) { //excess allows us to resize more smoothly (still crud tho)
+ if( excess < 2 ) //only decrease rect by more if even number of excesses left
+ --step;
+ excess -= 2;
+ }
+
+ rect.addCoords( step, step, -step, -step );
+ }
+
+ // if( excess > 0 ) rect.addCoords( excess, excess, 0, 0 ); //ugly
+
+ paint.setPen( COLOR_GREY );
+ paint.setBrush( Qt::white );
+ paint.drawEllipse( rect );
+
+ if( scaleFactor > 1 )
+ {
+ //have to end in order to smoothscale()
+ paint.end();
+
+ int x1, y1, x2, y2;
+ rect.coords( &x1, &y1, &x2, &y2 );
+ x1 /= scaleFactor;
+ y1 /= scaleFactor;
+ x2 /= scaleFactor;
+ y2 /= scaleFactor;
+ rect.setCoords( x1, y1, x2, y2 );
+
+ QImage img = this->convertToImage();
+ img = img.smoothScale( this->size() / (int)scaleFactor );
+ this->convertFromImage( img );
+
+ paint.begin( this );
+ paint.setPen( COLOR_GREY );
+ paint.setBrush( Qt::white );
+ }
+
+ paint.drawText( rect, Qt::AlignCenter, m_centerText );
+
+ m_innerRadius = rect.width() / 2; //rect.width should be multiple of 2
+
+ paint.end();
+}
+#if 0
+#if __GLIBC__ < 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
+
+ void
+ sincos( double angleRadians, double *Sin, double *Cos )
+ {
+ *Sin = sin( angleRadians );
+ *Cos = cos( angleRadians );
+ }
+
+#endif
+#endif
diff --git a/krusader/DiskUsage/radialMap/radialMap.h b/krusader/DiskUsage/radialMap/radialMap.h
new file mode 100644
index 0000000..81959b8
--- /dev/null
+++ b/krusader/DiskUsage/radialMap/radialMap.h
@@ -0,0 +1,71 @@
+//Author: Max Howell <max.howell@methylblue.com>, (C) 2003-4
+//Copyright: See COPYING file that comes with this distribution
+
+#ifndef RADIALMAP_H
+#define RADIALMAP_H
+
+#include <qcolor.h>
+
+class File;
+
+
+namespace RadialMap
+{
+ class Segment //all angles are in 16ths of degrees
+ {
+ public:
+ Segment( const File *f, uint s, uint l, bool isFake = false )
+ : m_angleStart( s )
+ , m_angleSegment( l )
+ , m_file( f )
+ , m_hasHiddenChildren( false )
+ , m_fake( isFake ) {}
+ ~Segment();
+
+ uint start() const { return m_angleStart; }
+ uint length() const { return m_angleSegment; }
+ uint end() const { return m_angleStart + m_angleSegment; }
+ const File *file() const { return m_file; }
+ const QColor& pen() const { return m_pen; }
+ const QColor& brush() const { return m_brush; }
+
+ bool isFake() const { return m_fake; }
+ bool hasHiddenChildren() const { return m_hasHiddenChildren; }
+
+ bool intersects( uint a ) const { return ( ( a >= start() ) && ( a < end() ) ); }
+
+ friend class Map;
+ friend class Builder;
+
+ private:
+ void setPalette( const QColor &p, const QColor &b ) { m_pen = p; m_brush = b; }
+
+ const uint m_angleStart, m_angleSegment;
+ const File* const m_file;
+ QColor m_pen, m_brush;
+ bool m_hasHiddenChildren;
+ const bool m_fake;
+ };
+}
+
+
+#ifndef PI
+#define PI 3.141592653589793
+#endif
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338327
+#endif
+
+#define MIN_RING_BREADTH 20
+#define MAX_RING_BREADTH 60
+#define DEFAULT_RING_DEPTH 4 //first level = 0
+#define MIN_RING_DEPTH 0
+
+#define LABEL_MAP_SPACER 7
+#define LABEL_HMARGIN 10
+#define LABEL_TEXT_HMARGIN 5
+#define LABEL_TEXT_VMARGIN 0
+#define LABEL_ANGLE_MARGIN 32
+#define LABEL_MIN_ANGLE_FACTOR 0.05
+
+#endif
diff --git a/krusader/DiskUsage/radialMap/segmentTip.cpp b/krusader/DiskUsage/radialMap/segmentTip.cpp
new file mode 100644
index 0000000..a3ce1b0
--- /dev/null
+++ b/krusader/DiskUsage/radialMap/segmentTip.cpp
@@ -0,0 +1,163 @@
+//Author: Max Howell <max.howell@methylblue.com>, (C) 2003-4
+//Copyright: See COPYING file that comes with this distribution
+
+#include "fileTree.h"
+#include "segmentTip.h"
+
+#include <kapplication.h> //installing eventFilters
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <klocale.h>
+#include <kpixmapeffect.h>
+#include <qpainter.h>
+#include <qtooltip.h> //for its palette
+
+
+
+namespace RadialMap {
+
+SegmentTip::SegmentTip( uint h )
+ : QWidget( 0, 0, WNoAutoErase | WStyle_Customize | WStyle_NoBorder | WStyle_Tool | WStyle_StaysOnTop | WX11BypassWM )
+ , m_cursorHeight( -h )
+{
+ setBackgroundMode( Qt::NoBackground );
+}
+
+void
+SegmentTip::moveto( QPoint p, const QWidget &canvas, bool placeAbove )
+{
+ //**** this function is very slow and seems to be visibly influenced by operations like mapFromGlobal() (who knows why!)
+ // ** so any improvements are much desired
+
+ //TODO uints could improve the class
+ p.rx() -= rect().center().x();
+ p.ry() -= (placeAbove ? 8 + height() : m_cursorHeight - 8);
+
+ const QRect screen = KGlobalSettings::desktopGeometry( parentWidget() );
+
+ const int x = p.x();
+ const int y = p.y();
+ const int x2 = x + width();
+ const int y2 = y + height(); //how's it ever gunna get below screen height?! (well you never know I spose)
+ const int sw = screen.width();
+ const int sh = screen.height();
+
+ if( x < 0 ) p.setX( 0 );
+ if( y < 0 ) p.setY( 0 );
+ if( x2 > sw ) p.rx() -= x2 - sw;
+ if( y2 > sh ) p.ry() -= y2 - sh;
+
+
+ //I'm using this QPoint to determine where to offset the bitBlt in m_pixmap
+ QPoint offset = canvas.mapToGlobal( QPoint() ) - p;
+ if( offset.x() < 0 ) offset.setX( 0 );
+ if( offset.y() < 0 ) offset.setY( 0 );
+
+
+ const QRect alphaMaskRect( canvas.mapFromGlobal( p ), size() );
+ const QRect intersection( alphaMaskRect.intersect( canvas.rect() ) );
+
+ m_pixmap.resize( size() ); //move to updateTip once you are sure it can never be null
+ bitBlt( &m_pixmap, offset, &canvas, intersection, Qt::CopyROP );
+
+ QPainter paint( &m_pixmap );
+ paint.setPen( Qt::black );
+ paint.setBrush( Qt::NoBrush );
+ paint.drawRect( rect() );
+ paint.end();
+
+ m_pixmap = KPixmapEffect::fade( m_pixmap, 0.6, QToolTip::palette().color( QPalette::Active, QColorGroup::Background ) );
+
+ paint.begin( &m_pixmap );
+ paint.drawText( rect(), AlignCenter, m_text );
+ paint.end();
+
+ p += screen.topLeft(); //for Xinerama users
+
+ move( x, y );
+ show();
+ update();
+}
+
+void
+SegmentTip::updateTip( const File* const file, const Directory* const root )
+{
+ const QString s1 = file->fullPath( root );
+ QString s2 = file->humanReadableSize();
+ KLocale *loc = KGlobal::locale();
+ const uint MARGIN = 3;
+ const uint pc = 100 * file->size() / root->size();
+ uint maxw = 0;
+ uint h = fontMetrics().height()*2 + 2*MARGIN;
+
+ if( pc > 0 ) s2 += QString( " (%1%)" ).arg( loc->formatNumber( pc, 0 ) );
+
+ m_text = s1;
+ m_text += '\n';
+ m_text += s2;
+
+ if( file->isDir() )
+ {
+ double files = static_cast<const Directory*>(file)->fileCount();
+ const uint pc = uint((100 * files) / (double)root->fileCount());
+ QString s3 = i18n( "Files: %1" ).arg( loc->formatNumber( files, 0 ) );
+
+ if( pc > 0 ) s3 += QString( " (%1%)" ).arg( loc->formatNumber( pc, 0 ) );
+
+ maxw = fontMetrics().width( s3 );
+ h += fontMetrics().height();
+ m_text += '\n';
+ m_text += s3;
+ }
+
+ uint
+ w = fontMetrics().width( s1 ); if( w > maxw ) maxw = w;
+ w = fontMetrics().width( s2 ); if( w > maxw ) maxw = w;
+
+ resize( maxw + 2 * MARGIN, h );
+}
+
+bool
+SegmentTip::event( QEvent *e )
+{
+ switch( e->type() )
+ {
+ case QEvent::Show:
+ kapp->installEventFilter( this );
+ break;
+ case QEvent::Hide:
+ kapp->removeEventFilter( this );
+ break;
+ case QEvent::Paint:
+ {
+ //QPainter( this ).drawPixmap( 0, 0, m_pixmap );
+ bitBlt( this, 0, 0, &m_pixmap );
+ return true;
+ }
+ default:
+ ;
+ }
+
+ return false/*QWidget::event( e )*/;
+}
+
+bool
+SegmentTip::eventFilter( QObject*, QEvent *e )
+{
+ switch ( e->type() )
+ {
+ case QEvent::Leave:
+// case QEvent::MouseButtonPress:
+// case QEvent::MouseButtonRelease:
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ case QEvent::FocusIn:
+ case QEvent::FocusOut:
+ case QEvent::Wheel:
+ hide(); //FALL THROUGH
+ default:
+ return false; //allow this event to passed to target
+ }
+}
+
+} //namespace RadialMap
diff --git a/krusader/DiskUsage/radialMap/segmentTip.h b/krusader/DiskUsage/radialMap/segmentTip.h
new file mode 100644
index 0000000..648e083
--- /dev/null
+++ b/krusader/DiskUsage/radialMap/segmentTip.h
@@ -0,0 +1,33 @@
+// Author: Max Howell <max.howell@methylblue.com>, (C) 2004
+// Copyright: See COPYING file that comes with this distribution
+
+#ifndef SEGMENTTIP_H
+#define SEGMENTTIP_H
+
+#include <kpixmap.h>
+#include <qwidget.h>
+
+class File;
+class Directory;
+
+namespace RadialMap
+{
+ class SegmentTip : public QWidget
+ {
+ public:
+ SegmentTip( uint );
+
+ void updateTip( const File*, const Directory* );
+ void moveto( QPoint, const QWidget&, bool );
+
+ private:
+ virtual bool eventFilter( QObject*, QEvent* );
+ virtual bool event( QEvent* );
+
+ uint m_cursorHeight;
+ KPixmap m_pixmap;
+ QString m_text;
+ };
+}
+
+#endif
diff --git a/krusader/DiskUsage/radialMap/sincos.h b/krusader/DiskUsage/radialMap/sincos.h
new file mode 100644
index 0000000..5e66e54
--- /dev/null
+++ b/krusader/DiskUsage/radialMap/sincos.h
@@ -0,0 +1,17 @@
+//Author: Max Howell <max.howell@methylblue.com>, (C) 2003-4
+//Copyright: See COPYING file that comes with this distribution
+
+#ifndef SINCOS_H
+#define SINCOS_H
+
+#include <math.h>
+#if 0
+#if __GLIBC__ < 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
+
+ void
+ sincos( double angleRadians, double *Sin, double *Cos );
+
+#endif
+
+#endif
+#endif
diff --git a/krusader/DiskUsage/radialMap/widget.cpp b/krusader/DiskUsage/radialMap/widget.cpp
new file mode 100644
index 0000000..3d54c2d
--- /dev/null
+++ b/krusader/DiskUsage/radialMap/widget.cpp
@@ -0,0 +1,199 @@
+//Author: Max Howell <max.howell@methylblue.com>, (C) 2003-4
+//Copyright: See COPYING file that comes with this distribution
+
+#include <kcursor.h> //ctor
+#include <klocale.h>
+#include <kurl.h>
+#include <qapplication.h> //sendEvent
+#include <qbitmap.h> //ctor - finding cursor size
+#include <qcursor.h> //slotPostMouseEvent()
+#include <qtimer.h> //member
+
+#include "Config.h"
+#include "debug.h"
+#include "fileTree.h"
+#include "radialMap.h" //constants
+#include "widget.h"
+
+
+
+RadialMap::Widget::Widget( QWidget *parent, const char *name )
+ : QWidget( parent, name, Qt::WNoAutoErase )
+ , m_tree( 0 )
+ , m_focus( 0 )
+ , m_tip( KCursor::handCursor().bitmap()->height() ) //needs to know cursor height
+ , m_rootSegment( 0 ) //TODO we don't delete it, *shrug*
+{
+ setBackgroundColor( Qt::white );
+
+ connect( this, SIGNAL(created( const Directory* )), SLOT(sendFakeMouseEvent()) );
+ connect( this, SIGNAL(created( const Directory* )), SLOT(update()) );
+ connect( &m_timer, SIGNAL(timeout()), SLOT(resizeTimeout()) );
+}
+
+QString
+RadialMap::Widget::path() const
+{
+ if( m_tree == 0 )
+ return QString::null;
+ return m_tree->fullPath();
+}
+
+KURL
+RadialMap::Widget::url( File const * const file ) const
+{
+ if( file == 0 && m_tree == 0 )
+ return KURL();
+
+ return KURL::fromPathOrURL( file ? file->fullPath() : m_tree->fullPath() );
+}
+
+void
+RadialMap::Widget::invalidate( const bool b )
+{
+ if( isValid() )
+ {
+ //**** have to check that only way to invalidate is this function frankly
+ //**** otherwise you may get bugs..
+
+ //disable mouse tracking
+ setMouseTracking( false );
+
+ KURL urlInv = url();
+
+ //ensure this class won't think we have a map still
+ m_tree = 0;
+ m_focus = 0;
+
+ delete m_rootSegment;
+ m_rootSegment = 0;
+
+ //FIXME move this disablement thing no?
+ // it is confusing in other areas, like the whole createFromCache() thing
+ m_map.invalidate( b ); //b signifies whether the pixmap is made to look disabled or not
+ if( b )
+ update();
+
+ //tell rest of Filelight
+ emit invalidated( urlInv );
+ }
+}
+
+void
+RadialMap::Widget::create( const Directory *tree )
+{
+ //it is not the responsibility of create() to invalidate first
+ //skip invalidation at your own risk
+
+ //FIXME make it the responsibility of create to invalidate first
+
+ if( tree )
+ {
+ m_focus = 0;
+ //generate the filemap image
+ m_map.make( tree );
+
+ //this is the inner circle in the center
+ m_rootSegment = new Segment( tree, 0, 16*360 );
+
+ setMouseTracking( true );
+ }
+
+ m_tree = tree;
+
+ //tell rest of Filelight
+ emit created( tree );
+}
+
+void
+RadialMap::Widget::createFromCache( const Directory *tree )
+{
+ //no scan was necessary, use cached tree, however we MUST still emit invalidate
+ invalidate( false );
+ create( tree );
+}
+
+void
+RadialMap::Widget::sendFakeMouseEvent() //slot
+{
+ QMouseEvent me( QEvent::MouseMove, mapFromGlobal( QCursor::pos() ), Qt::NoButton, Qt::NoButton );
+ QApplication::sendEvent( this, &me );
+}
+
+void
+RadialMap::Widget::resizeTimeout() //slot
+{
+ // the segments are about to erased!
+ // this was a horrid bug, and proves the OO programming should be obeyed always!
+ m_focus = 0;
+ if( m_tree )
+ m_map.make( m_tree, true );
+ update();
+}
+
+void
+RadialMap::Widget::refresh( int filth )
+{
+ //TODO consider a more direct connection
+
+ if( !m_map.isNull() )
+ {
+ switch( filth )
+ {
+ case 1:
+ m_focus = 0;
+ if( m_tree )
+ m_map.make( m_tree, true ); //true means refresh only
+ break;
+
+ case 2:
+ m_map.aaPaint();
+ break;
+
+ case 3:
+ m_map.colorise(); //FALL THROUGH!
+ case 4:
+ m_map.paint();
+
+ default:
+ break;
+ }
+
+ update();
+ }
+}
+
+void
+RadialMap::Widget::zoomIn() //slot
+{
+ if( m_map.m_visibleDepth > MIN_RING_DEPTH )
+ {
+ m_focus = 0;
+ --m_map.m_visibleDepth;
+ if( m_tree )
+ m_map.make( m_tree );
+ Config::defaultRingDepth = m_map.m_visibleDepth;
+ update();
+ }
+}
+
+void
+RadialMap::Widget::zoomOut() //slot
+{
+ m_focus = 0;
+ ++m_map.m_visibleDepth;
+ if( m_tree )
+ m_map.make( m_tree );
+ if( m_map.m_visibleDepth > Config::defaultRingDepth )
+ Config::defaultRingDepth = m_map.m_visibleDepth;
+ update();
+}
+
+
+RadialMap::Segment::~Segment()
+{
+ if( isFake() )
+ delete m_file; //created by us in Builder::build()
+}
+
+#include "widget.moc"
diff --git a/krusader/DiskUsage/radialMap/widget.h b/krusader/DiskUsage/radialMap/widget.h
new file mode 100644
index 0000000..fcbe08c
--- /dev/null
+++ b/krusader/DiskUsage/radialMap/widget.h
@@ -0,0 +1,110 @@
+//Author: Max Howell <max.howell@methylblue.com>, (C) 2004
+//Copyright: See COPYING file that comes with this distribution
+
+#ifndef WIDGET_H
+#define WIDGET_H
+
+#include <kurl.h>
+#include <qtimer.h>
+#include "segmentTip.h"
+
+template <class T> class Chain;
+class Directory;
+class File;
+namespace KIO { class Job; }
+class KURL;
+
+namespace RadialMap
+{
+ class Segment;
+
+ class Map : public KPixmap
+ {
+ public:
+ Map();
+ ~Map();
+
+ void make( const Directory *, bool = false );
+ bool resize( const QRect& );
+
+ bool isNull() const { return ( m_signature == 0 ); }
+ void invalidate( const bool );
+
+ friend class Builder;
+ friend class Widget;
+
+ private:
+ void paint( uint = 1 );
+ void aaPaint();
+ void colorise();
+ void setRingBreadth();
+
+ Chain<Segment> *m_signature;
+
+ QRect m_rect;
+ uint m_ringBreadth; ///ring breadth
+ uint m_innerRadius; ///radius of inner circle
+ uint m_visibleDepth; ///visible level depth of system
+ QString m_centerText;
+
+ uint MAP_2MARGIN;
+ };
+
+ class Widget : public QWidget
+ {
+ Q_OBJECT
+
+ public:
+ Widget( QWidget* = 0, const char* = 0 );
+
+ QString path() const;
+ KURL url( File const * const = 0 ) const;
+
+ bool isValid() const { return m_tree != 0; }
+
+ friend class Label; //FIXME badness
+
+ public slots:
+ void zoomIn();
+ void zoomOut();
+ void create( const Directory* );
+ void invalidate( const bool = true );
+ void refresh( int );
+
+ private slots:
+ void resizeTimeout();
+ void sendFakeMouseEvent();
+ void deleteJobFinished( KIO::Job* );
+ void createFromCache( const Directory* );
+
+ signals:
+ void activated( const KURL& );
+ void invalidated( const KURL& );
+ void created( const Directory* );
+ void mouseHover( const QString& );
+
+ protected:
+ virtual void paintEvent( QPaintEvent* );
+ virtual void resizeEvent( QResizeEvent* );
+ virtual void mouseMoveEvent( QMouseEvent* );
+ virtual void mousePressEvent( QMouseEvent* );
+
+ protected:
+ const Segment *segmentAt( QPoint& ) const; //FIXME const reference for a library others can use
+ const Segment *rootSegment() const { return m_rootSegment; } ///never == 0
+ const Segment *focusSegment() const { return m_focus; } ///0 == nothing in focus
+
+ private:
+ void paintExplodedLabels( QPainter& ) const;
+
+ const Directory *m_tree;
+ const Segment *m_focus;
+ QPoint m_offset;
+ QTimer m_timer;
+ Map m_map;
+ SegmentTip m_tip;
+ Segment *m_rootSegment;
+ };
+}
+
+#endif
diff --git a/krusader/DiskUsage/radialMap/widgetEvents.cpp b/krusader/DiskUsage/radialMap/widgetEvents.cpp
new file mode 100644
index 0000000..a2486bb
--- /dev/null
+++ b/krusader/DiskUsage/radialMap/widgetEvents.cpp
@@ -0,0 +1,241 @@
+//Author: Max Howell <max.howell@methylblue.com>, (C) 2003-4
+//Copyright: See COPYING file that comes with this distribution
+
+#include "fileTree.h"
+#include "radialMap.h" //class Segment
+#include "widget.h"
+
+#include <kcursor.h> //::mouseMoveEvent()
+#include <kiconeffect.h> //::mousePressEvent()
+#include <kiconloader.h> //::mousePressEvent()
+#include <kio/job.h> //::mousePressEvent()
+#include <klocale.h>
+#include <kmessagebox.h> //::mousePressEvent()
+#include <kpopupmenu.h> //::mousePressEvent()
+#include <krun.h> //::mousePressEvent()
+#include <math.h> //::segmentAt()
+#include <qapplication.h>//QApplication::setOverrideCursor()
+#include <qpainter.h>
+#include <qtimer.h> //::resizeEvent()
+
+
+
+void
+RadialMap::Widget::resizeEvent( QResizeEvent* )
+{
+ if( m_map.resize( rect() ) )
+ m_timer.start( 500, true ); //will cause signature to rebuild for new size
+
+ //always do these as they need to be initialised on creation
+ m_offset.rx() = (width() - m_map.width()) / 2;
+ m_offset.ry() = (height() - m_map.height()) / 2;
+}
+
+void
+RadialMap::Widget::paintEvent( QPaintEvent* )
+{
+ //bltBit for some Qt setups will bitBlt _after_ the labels are painted. Which buggers things up!
+ //shame as bitBlt is faster, possibly Qt bug? Should report the bug? - seems to be race condition
+ //bitBlt( this, m_offset, &m_map );
+
+ QPainter paint( this );
+
+ paint.drawPixmap( m_offset, m_map );
+
+ //vertical strips
+ if( m_map.width() < width() )
+ {
+ paint.eraseRect( 0, 0, m_offset.x(), height() );
+ paint.eraseRect( m_map.width() + m_offset.x(), 0, m_offset.x() + 1, height() );
+ }
+ //horizontal strips
+ if( m_map.height() < height() )
+ {
+ paint.eraseRect( 0, 0, width(), m_offset.y() );
+ paint.eraseRect( 0, m_map.height() + m_offset.y(), width(), m_offset.y() + 1 );
+ }
+
+ //exploded labels
+ if( !m_map.isNull() && !m_timer.isActive() )
+ paintExplodedLabels( paint );
+}
+
+const RadialMap::Segment*
+RadialMap::Widget::segmentAt( QPoint &e ) const
+{
+ //determine which segment QPoint e is above
+
+ e -= m_offset;
+
+ if( e.x() <= m_map.width() && e.y() <= m_map.height() )
+ {
+ //transform to cartesian coords
+ e.rx() -= m_map.width() / 2; //should be an int
+ e.ry() = m_map.height() / 2 - e.y();
+
+ double length = hypot( e.x(), e.y() );
+
+ if( length >= m_map.m_innerRadius ) //not hovering over inner circle
+ {
+ uint depth = ((int)length - m_map.m_innerRadius) / m_map.m_ringBreadth;
+
+ if( depth <= m_map.m_visibleDepth ) //**** do earlier since you can //** check not outside of range
+ {
+ //vector calculation, reduces to simple trigonometry
+ //cos angle = (aibi + ajbj) / albl
+ //ai = x, bi=1, aj=y, bj=0
+ //cos angle = x / (length)
+
+ uint a = (uint)(acos( (double)e.x() / length ) * 916.736); //916.7324722 = #radians in circle * 16
+
+ //acos only understands 0-180 degrees
+ if( e.y() < 0 ) a = 5760 - a;
+
+ #define ring (m_map.m_signature + depth)
+ for( ConstIterator<Segment> it = ring->constIterator(); it != ring->end(); ++it )
+ if( (*it)->intersects( a ) )
+ return *it;
+ #undef ring
+ }
+ }
+ else return m_rootSegment; //hovering over inner circle
+ }
+
+ return 0;
+}
+
+void
+RadialMap::Widget::mouseMoveEvent( QMouseEvent *e )
+{
+ //set m_focus to what we hover over, update UI if it's a new segment
+
+ Segment const * const oldFocus = m_focus;
+ QPoint p = e->pos();
+
+ m_focus = segmentAt( p ); //NOTE p is passed by non-const reference
+
+ if( m_focus && m_focus->file() != m_tree )
+ {
+ if( m_focus != oldFocus ) //if not same as last time
+ {
+ setCursor( KCursor::handCursor() );
+ m_tip.updateTip( m_focus->file(), m_tree );
+ emit mouseHover( m_focus->file()->fullPath() );
+
+ //repaint required to update labels now before transparency is generated
+ repaint( false );
+ }
+
+ m_tip.moveto( e->globalPos(), *this, ( p.y() < 0 ) ); //updates tooltip psuedo-tranparent background
+ }
+ else if( oldFocus && oldFocus->file() != m_tree )
+ {
+ unsetCursor();
+ m_tip.hide();
+ update();
+
+ emit mouseHover( QString::null );
+ }
+}
+
+void
+RadialMap::Widget::mousePressEvent( QMouseEvent *e )
+{
+ //m_tip is hidden already by event filter
+ //m_focus is set correctly (I've been strict, I assure you it is correct!)
+
+ if( m_focus && !m_focus->isFake() )
+ {
+ const KURL url = Widget::url( m_focus->file() );
+ const bool isDir = m_focus->file()->isDir();
+
+ if( e->button() == Qt::RightButton )
+ {
+ KPopupMenu popup;
+ popup.insertTitle( m_focus->file()->fullPath( m_tree ) );
+
+ if( isDir )
+ {
+ popup.insertItem( SmallIconSet( "konqueror" ), i18n( "Open &Konqueror Here" ), 0 );
+ if( url.protocol() == "file" )
+ popup.insertItem( SmallIconSet( "konsole" ), i18n( "Open &Konsole Here" ), 1 );
+
+ if( m_focus->file() != m_tree )
+ {
+ popup.insertSeparator();
+ popup.insertItem( SmallIconSet( "viewmag" ), i18n( "&Center Map Here" ), 2 );
+ }
+ }
+ else popup.insertItem( SmallIconSet( "fileopen" ), i18n( "&Open" ), 3 );
+
+ popup.insertSeparator();
+ popup.insertItem( SmallIconSet( "editdelete" ), i18n( "&Delete" ), 4 );
+
+ switch( popup.exec( e->globalPos(), 1 ) ) {
+ case 0:
+ //KRun::runCommand will show an error message if there was trouble
+ KRun::runCommand( QString( "kfmclient openURL '%1'" ).arg( url.url() ) );
+ break;
+
+ case 1:
+ KRun::runCommand( QString( "konsole --workdir '%1'" ).arg( url.url() ) );
+ break;
+
+ case 2:
+ case 3:
+ goto sectionTwo;
+
+ case 4:
+ {
+ const KURL url = Widget::url( m_focus->file() );
+ const QString message = ( m_focus->file()->isDir()
+ ? i18n( "<qt>The directory at <i>'%1'</i> will be <b>recursively</b> and <b>permanently</b> deleted!</qt>" )
+ : i18n( "<qt><i>'%1'</i> will be <b>permanently</b> deleted!</qt>" )).arg( url.prettyURL() );
+ const int userIntention = KMessageBox::warningContinueCancel( this, message, QString::null, KGuiItem( i18n("&Delete"), "editdelete" ) );
+
+ if( userIntention == KMessageBox::Continue ) {
+ KIO::Job *job = KIO::del( url );
+ job->setWindow( this );
+ connect( job, SIGNAL(result( KIO::Job* )), SLOT(deleteJobFinished( KIO::Job* )) );
+ QApplication::setOverrideCursor( KCursor::workingCursor() );
+ }
+ }
+
+ default:
+ //ensure m_focus is set for new mouse position
+ sendFakeMouseEvent();
+ }
+
+ } else {
+
+ sectionTwo:
+
+ const QRect rect( e->x() - 20, e->y() - 20, 40, 40 );
+
+ m_tip.hide(); //user expects this
+
+ if( !isDir || e->button() == Qt::MidButton )
+ {
+ KIconEffect::visualActivate( this, rect );
+ new KRun( url, this, true ); //FIXME see above
+ }
+ else if( m_focus->file() != m_tree ) //is left mouse button
+ {
+ KIconEffect::visualActivate( this, rect );
+ emit activated( url ); //activate first, this will cause UI to prepare itself
+ if( m_focus )
+ createFromCache( (Directory *)m_focus->file() );
+ }
+ }
+ }
+}
+
+void
+RadialMap::Widget::deleteJobFinished( KIO::Job *job )
+{
+ QApplication::restoreOverrideCursor();
+ if( !job->error() )
+ invalidate();
+ else
+ job->showErrorDialog( this );
+}
diff --git a/krusader/Filter/Makefile.am b/krusader/Filter/Makefile.am
new file mode 100644
index 0000000..98b044b
--- /dev/null
+++ b/krusader/Filter/Makefile.am
@@ -0,0 +1,11 @@
+noinst_LIBRARIES = libFilter.a
+
+INCLUDES = $(all_includes)
+
+libFilter_a_METASOURCES = AUTO
+
+libFilter_a_SOURCES = \
+ advancedfilter.cpp \
+ generalfilter.cpp \
+ filtertabs.cpp \
+ filterdialog.cpp
diff --git a/krusader/Filter/advancedfilter.cpp b/krusader/Filter/advancedfilter.cpp
new file mode 100644
index 0000000..e599036
--- /dev/null
+++ b/krusader/Filter/advancedfilter.cpp
@@ -0,0 +1,711 @@
+/***************************************************************************
+ advancedfilter.cpp - description
+ -------------------
+ copyright : (C) 2003 + by Shie Erlich & Rafi Yanai & Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "../krusader.h"
+#include "advancedfilter.h"
+#include "../Dialogs/krdialogs.h"
+
+#include <qgroupbox.h>
+#include <klocale.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qbuttongroup.h>
+#include <qfile.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <time.h>
+#include <kiconloader.h>
+
+#define USERSFILE QString("/etc/passwd")
+#define GROUPSFILE QString("/etc/group")
+
+AdvancedFilter::AdvancedFilter( FilterTabs *tabs, QWidget *parent, const char *name ) : QWidget( parent, name ), fltTabs( tabs )
+{
+ QGridLayout *filterLayout = new QGridLayout( this );
+ filterLayout->setSpacing( 6 );
+ filterLayout->setMargin( 11 );
+
+ // Options for size
+
+ QGroupBox *sizeGroup = new QGroupBox( this, "sizeGroup" );
+ sizeGroup->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)1, sizeGroup->sizePolicy().hasHeightForWidth() ) );
+ sizeGroup->setTitle( i18n( "Size" ) );
+ sizeGroup->setColumnLayout(0, Qt::Vertical );
+ sizeGroup->layout()->setSpacing( 0 );
+ sizeGroup->layout()->setMargin( 0 );
+ QGridLayout *sizeLayout = new QGridLayout( sizeGroup->layout() );
+ sizeLayout->setAlignment( Qt::AlignTop );
+ sizeLayout->setSpacing( 6 );
+ sizeLayout->setMargin( 11 );
+
+ biggerThanEnabled = new QCheckBox( sizeGroup, "biggerThanEnabled" );
+ biggerThanEnabled->setText( i18n( "&Bigger than" ) );
+ sizeLayout->addWidget( biggerThanEnabled, 0, 0 );
+
+ biggerThanAmount = new QLineEdit( sizeGroup, "biggerThanAmount" );
+ biggerThanAmount->setEnabled( false );
+ biggerThanAmount->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed, biggerThanAmount->sizePolicy().hasHeightForWidth() ) );
+ sizeLayout->addWidget( biggerThanAmount, 0, 1 );
+
+ biggerThanType = new KComboBox( false, sizeGroup, "biggerThanType" );
+ biggerThanType->insertItem( i18n( "Bytes" ) );
+ biggerThanType->insertItem( i18n( "KB" ) );
+ biggerThanType->insertItem( i18n( "MB" ) );
+ biggerThanType->setEnabled( false );
+ sizeLayout->addWidget( biggerThanType, 0, 2 );
+
+ smallerThanEnabled = new QCheckBox( sizeGroup, "smallerThanEnabled" );
+ smallerThanEnabled->setText( i18n( "&Smaller than" ) );
+ sizeLayout->addWidget( smallerThanEnabled, 0, 3 );
+
+ smallerThanAmount = new QLineEdit( sizeGroup, "smallerThanAmount" );
+ smallerThanAmount->setEnabled( false );
+ smallerThanAmount->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed, smallerThanAmount->sizePolicy().hasHeightForWidth() ) );
+ sizeLayout->addWidget( smallerThanAmount, 0, 4 );
+
+ smallerThanType = new KComboBox( false, sizeGroup, "smallerThanType" );
+ smallerThanType->insertItem( i18n( "Bytes" ) );
+ smallerThanType->insertItem( i18n( "KB" ) );
+ smallerThanType->insertItem( i18n( "MB" ) );
+ smallerThanType->setEnabled( false );
+ sizeLayout->addWidget( smallerThanType, 0, 5 );
+
+ // set a tighter box around the type box
+
+ int height = QFontMetrics(biggerThanType->font()).height()+2;
+ biggerThanType->setMaximumHeight(height);
+ smallerThanType->setMaximumHeight(height);
+
+ filterLayout->addWidget( sizeGroup, 0, 0 );
+
+ // Options for date
+
+ QPixmap iconDate = krLoader->loadIcon( "date", KIcon::Toolbar, 16 );
+
+ QButtonGroup *dateGroup = new QButtonGroup( this, "dateGroup" );
+ dateGroup->setTitle( i18n( "Date" ) );
+ dateGroup->setExclusive( true );
+ dateGroup->setColumnLayout(0, Qt::Vertical );
+ dateGroup->layout()->setSpacing( 0 );
+ dateGroup->layout()->setMargin( 0 );
+ QGridLayout *dateLayout = new QGridLayout( dateGroup->layout() );
+ dateLayout->setAlignment( Qt::AlignTop );
+ dateLayout->setSpacing( 6 );
+ dateLayout->setMargin( 11 );
+
+ modifiedBetweenEnabled = new QRadioButton( dateGroup, "modifiedBetweenEnabled" );
+ modifiedBetweenEnabled->setText( i18n( "&Modified between" ) );
+ dateGroup->insert( modifiedBetweenEnabled, 0 );
+
+ dateLayout->addMultiCellWidget( modifiedBetweenEnabled, 0, 0, 0, 1 );
+
+ modifiedBetweenData1 = new QLineEdit( dateGroup, "modifiedBetweenData1" );
+ modifiedBetweenData1->setEnabled( false );
+ modifiedBetweenData1->setText( "" );
+ dateLayout->addMultiCellWidget( modifiedBetweenData1, 0, 0, 2, 3 );
+
+ modifiedBetweenBtn1 = new QToolButton( dateGroup, "modifiedBetweenBtn1" );
+ modifiedBetweenBtn1->setEnabled( false );
+ modifiedBetweenBtn1->setText( "" );
+ modifiedBetweenBtn1->setPixmap( iconDate );
+ dateLayout->addWidget( modifiedBetweenBtn1, 0, 4 );
+
+ QLabel *andLabel = new QLabel( dateGroup, "andLabel" );
+ andLabel->setText( i18n( "an&d" ) );
+ dateLayout->addWidget( andLabel, 0, 5 );
+
+ modifiedBetweenData2 = new QLineEdit( dateGroup, "modifiedBetweenData2" );
+ modifiedBetweenData2->setEnabled( false );
+ modifiedBetweenData2->setText( "" );
+ andLabel->setBuddy(modifiedBetweenData2);
+ dateLayout->addWidget( modifiedBetweenData2, 0, 6 );
+
+ modifiedBetweenBtn2 = new QToolButton( dateGroup, "modifiedBetweenBtn2" );
+ modifiedBetweenBtn2->setEnabled( false );
+ modifiedBetweenBtn2->setText( "" );
+ modifiedBetweenBtn2->setPixmap( iconDate );
+ dateLayout->addWidget( modifiedBetweenBtn2, 0, 7 );
+
+ notModifiedAfterEnabled = new QRadioButton( dateGroup, "notModifiedAfterEnabled" );
+ notModifiedAfterEnabled->setText( i18n( "&Not modified after" ) );
+ dateGroup->insert( notModifiedAfterEnabled, 0 );
+ dateLayout->addMultiCellWidget( notModifiedAfterEnabled, 1, 1, 0, 1 );
+
+ notModifiedAfterData = new QLineEdit( dateGroup, "notModifiedAfterData" );
+ notModifiedAfterData->setEnabled( false );
+ notModifiedAfterData->setText( "" );
+ dateLayout->addMultiCellWidget( notModifiedAfterData, 1, 1, 2, 3 );
+
+ notModifiedAfterBtn = new QToolButton( dateGroup, "notModifiedAfterBtn" );
+ notModifiedAfterBtn->setEnabled( false );
+ notModifiedAfterBtn->setText( "" );
+ notModifiedAfterBtn->setPixmap( iconDate );
+ dateLayout->addWidget( notModifiedAfterBtn, 1, 4 );
+
+ modifiedInTheLastEnabled = new QRadioButton( dateGroup, "modifiedInTheLastEnabled" );
+ modifiedInTheLastEnabled->setText( i18n("Mod&ified in the last") );
+ dateGroup->insert( modifiedInTheLastEnabled, 0 );
+ dateLayout->addWidget( modifiedInTheLastEnabled, 2, 0 );
+
+ modifiedInTheLastData = new QLineEdit( dateGroup, "modifiedInTheLastData" );
+ modifiedInTheLastData->setEnabled( false );
+ modifiedInTheLastData->setText( "" );
+ dateLayout->addWidget( modifiedInTheLastData, 2, 2 );
+
+ modifiedInTheLastType = new QComboBox( false, dateGroup, "modifiedInTheLastType" );
+ modifiedInTheLastType->insertItem( i18n( "days" ) );
+ modifiedInTheLastType->insertItem( i18n( "weeks" ) );
+ modifiedInTheLastType->insertItem( i18n( "months" ) );
+ modifiedInTheLastType->insertItem( i18n( "years" ) );
+ modifiedInTheLastType->setEnabled( false );
+ dateLayout->addMultiCellWidget( modifiedInTheLastType, 2, 2, 3, 4 );
+
+ notModifiedInTheLastData = new QLineEdit( dateGroup, "notModifiedInTheLastData" );
+ notModifiedInTheLastData->setEnabled( false );
+ notModifiedInTheLastData->setText( "" );
+ dateLayout->addWidget( notModifiedInTheLastData, 3, 2 );
+
+ QLabel *notModifiedInTheLastLbl = new QLabel( dateGroup, "notModifiedInTheLastLbl" );
+ notModifiedInTheLastLbl->setText( i18n( "No&t modified in the last" ) );
+ notModifiedInTheLastLbl->setBuddy(notModifiedInTheLastData);
+ dateLayout->addWidget( notModifiedInTheLastLbl, 3, 0 );
+
+ notModifiedInTheLastType = new QComboBox( false, dateGroup, "notModifiedInTheLastType" );
+ notModifiedInTheLastType->insertItem( i18n( "days" ) );
+ notModifiedInTheLastType->insertItem( i18n( "weeks" ) );
+ notModifiedInTheLastType->insertItem( i18n( "months" ) );
+ notModifiedInTheLastType->insertItem( i18n( "years" ) );
+ notModifiedInTheLastType->setEnabled( false );
+ dateLayout->addMultiCellWidget( notModifiedInTheLastType, 3, 3, 3, 4 );
+
+ filterLayout->addWidget( dateGroup, 1, 0 );
+
+ // Options for ownership
+
+ QGroupBox *ownershipGroup = new QGroupBox( this, "ownershipGroup" );
+ ownershipGroup->setTitle( i18n( "Ownership" ) );
+ ownershipGroup->setColumnLayout(0, Qt::Vertical );
+ ownershipGroup->layout()->setSpacing( 0 );
+ ownershipGroup->layout()->setMargin( 0 );
+ QGridLayout *ownershipLayout = new QGridLayout( ownershipGroup->layout() );
+ ownershipLayout->setAlignment( Qt::AlignTop );
+ ownershipLayout->setSpacing( 6 );
+ ownershipLayout->setMargin( 11 );
+
+ QHBoxLayout *hboxLayout = new QHBoxLayout();
+ hboxLayout->setSpacing( 6 );
+ hboxLayout->setMargin( 0 );
+
+ belongsToUserEnabled = new QCheckBox( ownershipGroup, "belongsToUserEnabled" );
+ belongsToUserEnabled->setText( i18n( "Belongs to &user" ) );
+ hboxLayout->addWidget( belongsToUserEnabled );
+
+ belongsToUserData = new QComboBox( false, ownershipGroup, "belongsToUserData" );
+ belongsToUserData->setEnabled( false );
+ belongsToUserData->setEditable( false );
+ hboxLayout->addWidget( belongsToUserData );
+
+ belongsToGroupEnabled = new QCheckBox( ownershipGroup, "belongsToGroupEnabled" );
+ belongsToGroupEnabled->setText( i18n( "Belongs to gr&oup" ) );
+ hboxLayout->addWidget( belongsToGroupEnabled );
+
+ belongsToGroupData = new QComboBox( false, ownershipGroup, "belongsToGroupData" );
+ belongsToGroupData->setEnabled( false );
+ belongsToGroupData->setEditable( false );
+ hboxLayout->addWidget( belongsToGroupData );
+
+ ownershipLayout->addMultiCellLayout( hboxLayout, 0, 0, 0, 3 );
+
+ permissionsEnabled = new QCheckBox( ownershipGroup, "permissionsEnabled" );
+ permissionsEnabled->setText( i18n( "P&ermissions" ) );
+ ownershipLayout->addWidget( permissionsEnabled, 1, 0 );
+
+ QGroupBox *ownerGroup = new QGroupBox( ownershipGroup, "ownerGroup" );
+ ownerGroup->setTitle( i18n( "O&wner" ) );
+ int width = 2*height + height / 2;
+
+ ownerR = new QComboBox( false, ownerGroup, "ownerR" );
+ ownerR->insertItem( i18n( "?" ) );
+ ownerR->insertItem( i18n( "r" ) );
+ ownerR->insertItem( i18n( "-" ) );
+ ownerR->setEnabled( false );
+ ownerR->setGeometry( QRect( 10, 20, width, height+6 ) );
+
+ ownerW = new QComboBox( false, ownerGroup, "ownerW" );
+ ownerW->insertItem( i18n( "?" ) );
+ ownerW->insertItem( i18n( "w" ) );
+ ownerW->insertItem( i18n( "-" ) );
+ ownerW->setEnabled( false );
+ ownerW->setGeometry( QRect( 10 + width, 20, width, height+6 ) );
+
+ ownerX = new QComboBox( false, ownerGroup, "ownerX" );
+ ownerX->insertItem( i18n( "?" ) );
+ ownerX->insertItem( i18n( "x" ) );
+ ownerX->insertItem( i18n( "-" ) );
+ ownerX->setEnabled( false );
+ ownerX->setGeometry( QRect( 10 + 2*width, 20, width, height+6 ) );
+
+ ownershipLayout->addWidget( ownerGroup, 1, 1 );
+
+ QGroupBox *groupGroup = new QGroupBox( ownershipGroup, "groupGroup" );
+ groupGroup->setTitle( i18n( "Grou&p" ) );
+
+ groupR = new QComboBox( false, groupGroup, "groupR" );
+ groupR->insertItem( i18n( "?" ) );
+ groupR->insertItem( i18n( "r" ) );
+ groupR->insertItem( i18n( "-" ) );
+ groupR->setEnabled( false );
+ groupR->setGeometry( QRect( 10, 20, width, height+6 ) );
+
+ groupW = new QComboBox( false, groupGroup, "groupW" );
+ groupW->insertItem( i18n( "?" ) );
+ groupW->insertItem( i18n( "w" ) );
+ groupW->insertItem( i18n( "-" ) );
+ groupW->setEnabled( false );
+ groupW->setGeometry( QRect( 10 + width, 20, width, height+6 ) );
+
+ groupX = new QComboBox( false, groupGroup, "groupX" );
+ groupX->insertItem( i18n( "?" ) );
+ groupX->insertItem( i18n( "x" ) );
+ groupX->insertItem( i18n( "-" ) );
+ groupX->setEnabled( false );
+ groupX->setGeometry( QRect( 10 + 2*width, 20, width, height+6 ) );
+
+ ownershipLayout->addWidget( groupGroup, 1, 2 );
+
+ QGroupBox *allGroup = new QGroupBox( ownershipGroup, "allGroup" );
+ allGroup->setTitle( i18n( "A&ll" ) );
+
+ allR = new QComboBox( false, allGroup, "allR" );
+ allR->insertItem( i18n( "?" ) );
+ allR->insertItem( i18n( "r" ) );
+ allR->insertItem( i18n( "-" ) );
+ allR->setEnabled( false );
+ allR->setGeometry( QRect( 10, 20, width, height+6 ) );
+
+ allW = new QComboBox( false, allGroup, "allW" );
+ allW->insertItem( i18n( "?" ) );
+ allW->insertItem( i18n( "w" ) );
+ allW->insertItem( i18n( "-" ) );
+ allW->setEnabled( false );
+ allW->setGeometry( QRect( 10 + width, 20, width, height+6 ) );
+
+ allX = new QComboBox( false, allGroup, "allX" );
+ allX->insertItem( i18n( "?" ) );
+ allX->insertItem( i18n( "x" ) );
+ allX->insertItem( i18n( "-" ) );
+ allX->setEnabled( false );
+ allX->setGeometry( QRect( 10 + 2*width, 20, width, height+6 ) );
+
+ ownershipLayout->addWidget( allGroup, 1, 3 );
+
+ QLabel *infoLabel = new QLabel( ownershipGroup, "TextLabel4" );
+ QFont infoLabel_font( infoLabel->font() );
+ infoLabel_font.setFamily( "adobe-helvetica" );
+ infoLabel_font.setItalic( true );
+ infoLabel->setFont( infoLabel_font );
+ infoLabel->setText( i18n( "Note: a '?' is a wildcard" ) );
+
+ ownershipLayout->addMultiCellWidget( infoLabel, 2, 2, 0, 3, Qt::AlignRight );
+
+ filterLayout->addWidget( ownershipGroup, 2, 0 );
+
+ // Connection table
+
+ connect( biggerThanEnabled, SIGNAL( toggled(bool) ), biggerThanAmount, SLOT( setEnabled(bool) ) );
+ connect( biggerThanEnabled, SIGNAL( toggled(bool) ), biggerThanType, SLOT( setEnabled(bool) ) );
+ connect( smallerThanEnabled, SIGNAL( toggled(bool) ), smallerThanAmount, SLOT( setEnabled(bool) ) );
+ connect( smallerThanEnabled, SIGNAL( toggled(bool) ), smallerThanType, SLOT( setEnabled(bool) ) );
+ connect( modifiedBetweenEnabled, SIGNAL( toggled(bool) ), modifiedBetweenData1, SLOT( setEnabled(bool) ) );
+ connect( modifiedBetweenEnabled, SIGNAL( toggled(bool) ), modifiedBetweenBtn1, SLOT( setEnabled(bool) ) );
+ connect( modifiedBetweenEnabled, SIGNAL( toggled(bool) ), modifiedBetweenData2, SLOT( setEnabled(bool) ) );
+ connect( modifiedBetweenEnabled, SIGNAL( toggled(bool) ), modifiedBetweenBtn2, SLOT( setEnabled(bool) ) );
+ connect( notModifiedAfterEnabled, SIGNAL( toggled(bool) ), notModifiedAfterData, SLOT( setEnabled(bool) ) );
+ connect( notModifiedAfterEnabled, SIGNAL( toggled(bool) ), notModifiedAfterBtn, SLOT( setEnabled(bool) ) );
+ connect( modifiedInTheLastEnabled, SIGNAL( toggled(bool) ), modifiedInTheLastData, SLOT( setEnabled(bool) ) );
+ connect( modifiedInTheLastEnabled, SIGNAL( toggled(bool) ), modifiedInTheLastType, SLOT( setEnabled(bool) ) );
+ connect( modifiedInTheLastEnabled, SIGNAL( toggled(bool) ), notModifiedInTheLastData, SLOT( setEnabled(bool) ) );
+ connect( modifiedInTheLastEnabled, SIGNAL( toggled(bool) ), notModifiedInTheLastType, SLOT( setEnabled(bool) ) );
+ connect( belongsToUserEnabled, SIGNAL( toggled(bool) ), belongsToUserData, SLOT( setEnabled(bool) ) );
+ connect( belongsToGroupEnabled, SIGNAL( toggled(bool) ), belongsToGroupData, SLOT( setEnabled(bool) ) );
+ connect( permissionsEnabled, SIGNAL( toggled(bool) ), ownerR, SLOT( setEnabled(bool) ) );
+ connect( permissionsEnabled, SIGNAL( toggled(bool) ), ownerW, SLOT( setEnabled(bool) ) );
+ connect( permissionsEnabled, SIGNAL( toggled(bool) ), ownerX, SLOT( setEnabled(bool) ) );
+ connect( permissionsEnabled, SIGNAL( toggled(bool) ), groupR, SLOT( setEnabled(bool) ) );
+ connect( permissionsEnabled, SIGNAL( toggled(bool) ), groupW, SLOT( setEnabled(bool) ) );
+ connect( permissionsEnabled, SIGNAL( toggled(bool) ), groupX, SLOT( setEnabled(bool) ) );
+ connect( permissionsEnabled, SIGNAL( toggled(bool) ), allR, SLOT( setEnabled(bool) ) );
+ connect( permissionsEnabled, SIGNAL( toggled(bool) ), allW, SLOT( setEnabled(bool) ) );
+ connect( permissionsEnabled, SIGNAL( toggled(bool) ), allX, SLOT( setEnabled(bool) ) );
+ connect( modifiedBetweenBtn1, SIGNAL( clicked() ), this, SLOT( modifiedBetweenSetDate1() ) );
+ connect( modifiedBetweenBtn2, SIGNAL( clicked() ), this, SLOT( modifiedBetweenSetDate2() ) );
+ connect( notModifiedAfterBtn, SIGNAL( clicked() ), this, SLOT( notModifiedAfterSetDate() ) );
+
+ // fill the users and groups list
+
+ fillList(belongsToUserData, USERSFILE);
+ fillList(belongsToGroupData, GROUPSFILE);
+
+ // tab order
+ setTabOrder( biggerThanEnabled, biggerThanAmount );
+ setTabOrder( biggerThanAmount, smallerThanEnabled );
+ setTabOrder( smallerThanEnabled, smallerThanAmount );
+ setTabOrder( smallerThanAmount, modifiedBetweenEnabled );
+ setTabOrder( modifiedBetweenEnabled, modifiedBetweenData1 );
+ setTabOrder( modifiedBetweenData1, modifiedBetweenData2 );
+ setTabOrder( modifiedBetweenData2, notModifiedAfterEnabled );
+ setTabOrder( notModifiedAfterEnabled, notModifiedAfterData );
+ setTabOrder( notModifiedAfterData, modifiedInTheLastEnabled );
+ setTabOrder( modifiedInTheLastEnabled, modifiedInTheLastData );
+ setTabOrder( modifiedInTheLastData, notModifiedInTheLastData );
+ setTabOrder( notModifiedInTheLastData, belongsToUserEnabled );
+ setTabOrder( belongsToUserEnabled, belongsToUserData );
+ setTabOrder( belongsToUserData, belongsToGroupEnabled );
+ setTabOrder( belongsToGroupEnabled, belongsToGroupData );
+ setTabOrder( belongsToGroupData, permissionsEnabled );
+ setTabOrder( permissionsEnabled, ownerR );
+ setTabOrder( ownerR, ownerW );
+ setTabOrder( ownerW, ownerX );
+ setTabOrder( ownerX, groupR );
+ setTabOrder( groupR, groupW );
+ setTabOrder( groupW, groupX );
+ setTabOrder( groupX, allR );
+ setTabOrder( allR, allW );
+ setTabOrder( allW, allX );
+ setTabOrder( allX, biggerThanType );
+ setTabOrder( biggerThanType, smallerThanType );
+ setTabOrder( smallerThanType, modifiedInTheLastType );
+ setTabOrder( modifiedInTheLastType, notModifiedInTheLastType );
+}
+
+void AdvancedFilter::modifiedBetweenSetDate1()
+{
+ changeDate(modifiedBetweenData1);
+}
+
+void AdvancedFilter::modifiedBetweenSetDate2()
+{
+ changeDate(modifiedBetweenData2);
+}
+
+void AdvancedFilter::notModifiedAfterSetDate()
+{
+ changeDate(notModifiedAfterData);
+}
+
+void AdvancedFilter::changeDate(QLineEdit *p) {
+ // check if the current date is valid
+ QDate d = KGlobal::locale()->readDate(p->text());
+ if (!d.isValid()) d = QDate::currentDate();
+
+ KRGetDate *gd = new KRGetDate(d, this);
+ d = gd->getDate();
+ // if a user pressed ESC or closed the dialog, we'll return an invalid date
+ if (d.isValid())
+ p->setText(KGlobal::locale()->formatDate(d, true));
+ delete gd;
+}
+
+// bool start: set it to true if this date is the beginning of the search,
+// if it's the end, set it to false
+void AdvancedFilter::qdate2time_t(time_t *dest, QDate d, bool start) {
+ struct tm t;
+ t.tm_sec = (start ? 0 : 59);
+ t.tm_min = (start ? 0 : 59);
+ t.tm_hour = (start ? 0 : 23);
+ t.tm_mday = d.day();
+ t.tm_mon = d.month() - 1;
+ t.tm_year = d.year() - 1900;
+ t.tm_wday = d.dayOfWeek() - 1; // actually ignored by mktime
+ t.tm_yday = d.dayOfYear() - 1; // actually ignored by mktime
+ t.tm_isdst = -1; // daylight saving time information isn't availble
+
+ (*dest) = mktime( &t );
+}
+
+
+void AdvancedFilter::fillList(QComboBox *list, QString filename) {
+ QFile data(filename);
+ if (!data.open(IO_ReadOnly))
+ {
+ krOut << "Search: Unable to read " << filename << " !!!" << endl;
+ return;
+ }
+ // and read it into the temporary array
+ QTextStream t(&data);
+ while (!data.atEnd())
+ {
+ QString s = t.readLine();
+ QString name = s.left(s.find(':'));
+ list->insertItem(name);
+ }
+}
+
+void AdvancedFilter::invalidDateMessage(QLineEdit *p)
+{
+ // FIXME p->text() is empty sometimes (to reproduce, set date to "13.09.005")
+ KMessageBox::detailedError(this, i18n("Invalid date entered."),
+ i18n("The date %1 is not valid according to your locale. Please re-enter a valid date (use the date button for easy access).").arg(p->text()) );
+ p->setFocus();
+}
+
+bool AdvancedFilter::fillQuery( KRQuery *query )
+{
+ KIO::filesize_t minSize = 0, maxSize = 0;
+
+ // size calculations ////////////////////////////////////////////////
+ if ( biggerThanEnabled->isChecked() &&
+ !(biggerThanAmount->text().simplifyWhiteSpace()).isEmpty() ) {
+ minSize = biggerThanAmount->text().toULong();
+ switch ( biggerThanType->currentItem() ) {
+ case 1 : minSize *= 1024;
+ break;
+ case 2 : minSize *= (1024*1024);
+ break;
+ }
+ query->setMinimumFileSize( minSize );
+ }
+ if ( smallerThanEnabled->isChecked() &&
+ !(smallerThanAmount->text().simplifyWhiteSpace()).isEmpty()) {
+ maxSize = smallerThanAmount->text().toULong();
+ switch (smallerThanType->currentItem()) {
+ case 1 : maxSize *= 1024;
+ break;
+ case 2 : maxSize *= (1024*1024);
+ break;
+ }
+ query->setMaximumFileSize( maxSize );
+ }
+ // check that minSize is smaller than maxSize
+ if ( ( minSize > 0) && ( maxSize > 0) && ( maxSize < minSize)) {
+ KMessageBox::detailedError(this, i18n("Specified sizes are inconsistent!"),
+ i18n("Please re-enter the values, so that the left side size will be smaller than (or equal to) the right side size."));
+ biggerThanAmount->setFocus();
+ return false;
+ }
+
+ // date calculations ////////////////////////////////////////////////////
+ if (modifiedBetweenEnabled->isChecked()) {
+ // first, if both dates are empty, than don't use them
+ if ( !(modifiedBetweenData1->text().simplifyWhiteSpace().isEmpty() &&
+ modifiedBetweenData2->text().simplifyWhiteSpace().isEmpty()) ) {
+ // check if date is valid
+ QDate d1 = KGlobal::locale()->readDate(modifiedBetweenData1->text());
+ if (!d1.isValid()) { invalidDateMessage(modifiedBetweenData1); return false; }
+ QDate d2 = KGlobal::locale()->readDate(modifiedBetweenData2->text());
+ if (!d2.isValid()) { invalidDateMessage(modifiedBetweenData2); return false; }
+
+ if (d1 > d2) {
+ KMessageBox::detailedError(this, i18n("Dates are inconsistent!"),
+ i18n("The date on the left is later than the date on the right. Please re-enter the dates, so that the left side date will be earlier than the right side date."));
+ modifiedBetweenData1->setFocus();
+ return false;
+ }
+ // all seems to be ok, create time_t
+
+ time_t newerTime, olderTime;
+ qdate2time_t(&newerTime, d1, true);
+ qdate2time_t(&olderTime, d2, false);
+ query->setNewerThan( newerTime );
+ query->setOlderThan( olderTime );
+ }
+ } else if (notModifiedAfterEnabled->isChecked()) {
+ if ( !notModifiedAfterData->text().simplifyWhiteSpace().isEmpty() ) {
+ QDate d = KGlobal::locale()->readDate(notModifiedAfterData->text());
+ if (!d.isValid()) { invalidDateMessage(notModifiedAfterData); return false; }
+ time_t olderTime;
+ qdate2time_t(&olderTime, d, false);
+ query->setOlderThan( olderTime );
+ }
+ } else if (modifiedInTheLastEnabled->isChecked()) {
+ if ( !(modifiedInTheLastData->text().simplifyWhiteSpace().isEmpty() &&
+ notModifiedInTheLastData->text().simplifyWhiteSpace().isEmpty()) ) {
+ QDate d1 = QDate::currentDate(); QDate d2 = QDate::currentDate();
+ if (!modifiedInTheLastData->text().simplifyWhiteSpace().isEmpty()) {
+ int tmp1 = modifiedInTheLastData->text().simplifyWhiteSpace().toInt();
+ switch (modifiedInTheLastType->currentItem()) {
+ case 1 : tmp1 *= 7;
+ break;
+ case 2 : tmp1 *= 30;
+ break;
+ case 3 : tmp1 *= 365;
+ break;
+ }
+ d1 = d1.addDays((-1) * tmp1);
+ time_t newerTime;
+ qdate2time_t(&newerTime, d1, true);
+ query->setNewerThan( newerTime );
+ }
+ if (!notModifiedInTheLastData->text().simplifyWhiteSpace().isEmpty()) {
+ int tmp2 = notModifiedInTheLastData->text().simplifyWhiteSpace().toInt();
+ switch (notModifiedInTheLastType->currentItem()) {
+ case 1 : tmp2 *= 7;
+ break;
+ case 2 : tmp2 *= 30;
+ break;
+ case 3 : tmp2 *= 365;
+ break;
+ }
+ d2 = d2.addDays((-1) * tmp2);
+ time_t olderTime;
+ qdate2time_t(&olderTime, d2, true);
+ query->setOlderThan( olderTime );
+ }
+ if ( !modifiedInTheLastData->text().simplifyWhiteSpace().isEmpty() &&
+ !notModifiedInTheLastData->text().simplifyWhiteSpace().isEmpty() ) {
+ if (d1 > d2) {
+ KMessageBox::detailedError(this, i18n("Dates are inconsistent!"),
+ i18n("The date on top is later than the date on the bottom. Please re-enter the dates, so that the top date will be earlier than the bottom date."));
+ modifiedInTheLastData->setFocus();
+ return false;
+ }
+ }
+ }
+ }
+ // permissions and ownership /////////////////////////////////////
+ if (permissionsEnabled->isChecked()) {
+ QString perm = ownerR->currentText() + ownerW->currentText() + ownerX->currentText() +
+ groupR->currentText() + groupW->currentText() + groupX->currentText() +
+ allR->currentText() + allW->currentText() + allX->currentText();
+ query->setPermissions( perm );
+ }
+ if (belongsToUserEnabled->isChecked())
+ query->setOwner( belongsToUserData->currentText() );
+ if (belongsToGroupEnabled->isChecked())
+ query->setGroup( belongsToGroupData->currentText() );
+
+ return true;
+}
+
+void AdvancedFilter::loadFromProfile( QString name )
+{
+ krConfig->setGroup( name );
+
+ smallerThanEnabled->setChecked( krConfig->readBoolEntry( "Smaller Than Enabled", false ) );
+ smallerThanAmount->setText( krConfig->readEntry( "Smaller Than Amount", "" ) );
+ smallerThanType->setCurrentItem( krConfig->readNumEntry( "Smaller Than Type", 0 ) );
+
+ biggerThanEnabled->setChecked( krConfig->readBoolEntry( "Bigger Than Enabled", false ) );
+ biggerThanAmount->setText( krConfig->readEntry( "Bigger Than Amount", "" ) );
+ biggerThanType->setCurrentItem( krConfig->readNumEntry( "Bigger Than Type", 0 ) );
+
+ modifiedBetweenEnabled->setChecked( krConfig->readBoolEntry( "Modified Between Enabled", false ) );
+ notModifiedAfterEnabled->setChecked( krConfig->readBoolEntry( "Not Modified After Enabled", false ) );
+ modifiedInTheLastEnabled->setChecked( krConfig->readBoolEntry( "Modified In The Last Enabled", false ) );
+
+ modifiedBetweenData1->setText( krConfig->readEntry( "Modified Between 1", "" ) );
+ modifiedBetweenData2->setText( krConfig->readEntry( "Modified Between 2", "" ) );
+
+ notModifiedAfterData->setText( krConfig->readEntry( "Not Modified After", "" ) );
+ modifiedInTheLastData->setText( krConfig->readEntry( "Modified In The Last", "" ) );
+ notModifiedInTheLastData->setText( krConfig->readEntry( "Not Modified In The Last", "" ) );
+
+ modifiedInTheLastType->setCurrentItem( krConfig->readNumEntry( "Modified In The Last Type", 0 ) );
+ notModifiedInTheLastType->setCurrentItem( krConfig->readNumEntry( "Not Modified In The Last Type", 0 ) );
+
+ belongsToUserEnabled->setChecked( krConfig->readBoolEntry( "Belongs To User Enabled", false ) );
+ belongsToGroupEnabled->setChecked( krConfig->readBoolEntry( "Belongs To Group Enabled", false ) );
+
+ QString user = krConfig->readEntry( "Belongs To User", "" );
+ for( int i = belongsToUserData->count(); i >= 0; i-- )
+ {
+ belongsToUserData->setCurrentItem( i );
+ if( belongsToUserData->currentText() == user )
+ break;
+ }
+
+ QString group = krConfig->readEntry( "Belongs To Group", "" );
+ for( int i = belongsToGroupData->count(); i >= 0; i-- )
+ {
+ belongsToGroupData->setCurrentItem( i );
+ if( belongsToGroupData->currentText() == group )
+ break;
+ }
+
+ permissionsEnabled->setChecked( krConfig->readBoolEntry( "Permissions Enabled", false ) );
+
+ ownerW->setCurrentItem( krConfig->readNumEntry( "Owner Write", 0 ) );
+ ownerR->setCurrentItem( krConfig->readNumEntry( "Owner Read", 0 ) );
+ ownerX->setCurrentItem( krConfig->readNumEntry( "Owner Execute", 0 ) );
+ groupW->setCurrentItem( krConfig->readNumEntry( "Group Write", 0 ) );
+ groupR->setCurrentItem( krConfig->readNumEntry( "Group Read", 0 ) );
+ groupX->setCurrentItem( krConfig->readNumEntry( "Group Execute", 0 ) );
+ allW->setCurrentItem( krConfig->readNumEntry( "All Write", 0 ) );
+ allR->setCurrentItem( krConfig->readNumEntry( "All Read", 0 ) );
+ allX->setCurrentItem( krConfig->readNumEntry( "All Execute", 0 ) );
+}
+
+void AdvancedFilter::saveToProfile( QString name )
+{
+ krConfig->setGroup( name );
+
+ krConfig->writeEntry( "Smaller Than Enabled", smallerThanEnabled->isChecked() );
+ krConfig->writeEntry( "Smaller Than Amount", smallerThanAmount->text() );
+ krConfig->writeEntry( "Smaller Than Type", smallerThanType->currentItem() );
+
+ krConfig->writeEntry( "Bigger Than Enabled", biggerThanEnabled->isChecked() );
+ krConfig->writeEntry( "Bigger Than Amount", biggerThanAmount->text() );
+ krConfig->writeEntry( "Bigger Than Type", biggerThanType->currentItem() );
+
+ krConfig->writeEntry( "Modified Between Enabled", modifiedBetweenEnabled->isChecked() );
+ krConfig->writeEntry( "Not Modified After Enabled", notModifiedAfterEnabled->isChecked() );
+ krConfig->writeEntry( "Modified In The Last Enabled", modifiedInTheLastEnabled->isChecked() );
+
+ krConfig->writeEntry( "Modified Between 1", modifiedBetweenData1->text() );
+ krConfig->writeEntry( "Modified Between 2", modifiedBetweenData2->text() );
+
+ krConfig->writeEntry( "Not Modified After", notModifiedAfterData->text() );
+ krConfig->writeEntry( "Modified In The Last", modifiedInTheLastData->text() );
+ krConfig->writeEntry( "Not Modified In The Last", notModifiedInTheLastData->text() );
+
+ krConfig->writeEntry( "Modified In The Last Type", modifiedInTheLastType->currentItem() );
+ krConfig->writeEntry( "Not Modified In The Last Type", notModifiedInTheLastType->currentItem() );
+
+ krConfig->writeEntry( "Belongs To User Enabled", belongsToUserEnabled->isChecked() );
+ krConfig->writeEntry( "Belongs To Group Enabled", belongsToGroupEnabled->isChecked() );
+
+ krConfig->writeEntry( "Belongs To User", belongsToUserData->currentText() );
+ krConfig->writeEntry( "Belongs To Group", belongsToGroupData->currentText() );
+
+ krConfig->writeEntry( "Permissions Enabled", permissionsEnabled->isChecked() );
+
+ krConfig->writeEntry( "Owner Write", ownerW->currentItem() );
+ krConfig->writeEntry( "Owner Read", ownerR->currentItem() );
+ krConfig->writeEntry( "Owner Execute", ownerX->currentItem() );
+ krConfig->writeEntry( "Group Write", groupW->currentItem() );
+ krConfig->writeEntry( "Group Read", groupR->currentItem() );
+ krConfig->writeEntry( "Group Execute", groupX->currentItem() );
+ krConfig->writeEntry( "All Write", allW->currentItem() );
+ krConfig->writeEntry( "All Read", allR->currentItem() );
+ krConfig->writeEntry( "All Execute", allX->currentItem() );
+}
+
+
+#include "advancedfilter.moc"
diff --git a/krusader/Filter/advancedfilter.h b/krusader/Filter/advancedfilter.h
new file mode 100644
index 0000000..77912e0
--- /dev/null
+++ b/krusader/Filter/advancedfilter.h
@@ -0,0 +1,115 @@
+/***************************************************************************
+ advancedfilter.h - description
+ -------------------
+ copyright : (C) 2003 + by Shie Erlich & Rafi Yanai & Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef ADVANCEDFILTER_H
+#define ADVANCEDFILTER_H
+
+#include "filterbase.h"
+#include "../VFS/krquery.h"
+
+#include <qwidget.h>
+#include <qcheckbox.h>
+#include <kcombobox.h>
+#include <klineedit.h>
+#include <qradiobutton.h>
+#include <qtoolbutton.h>
+
+class AdvancedFilter : public QWidget, public FilterBase
+{
+ Q_OBJECT
+
+public:
+ AdvancedFilter( FilterTabs *tabs, QWidget *parent = 0, const char *name = 0 );
+
+ virtual void queryAccepted() {}
+ virtual bool fillQuery( KRQuery *query );
+ virtual void loadFromProfile( QString name );
+ virtual void saveToProfile( QString name );
+ virtual QString name() { return "AdvancedFilter";}
+ virtual FilterTabs * filterTabs() { return fltTabs; }
+
+public slots:
+ void modifiedBetweenSetDate1();
+ void modifiedBetweenSetDate2();
+ void notModifiedAfterSetDate();
+
+public:
+ QCheckBox* smallerThanEnabled;
+ QLineEdit* smallerThanAmount;
+ KComboBox* smallerThanType;
+
+ QCheckBox* biggerThanEnabled;
+ KComboBox* biggerThanType;
+ QLineEdit* biggerThanAmount;
+
+ QRadioButton* modifiedBetweenEnabled;
+ QRadioButton* notModifiedAfterEnabled;
+ QRadioButton* modifiedInTheLastEnabled;
+
+ QLineEdit* modifiedBetweenData1;
+ QLineEdit* modifiedBetweenData2;
+
+ QToolButton* modifiedBetweenBtn1;
+ QToolButton* modifiedBetweenBtn2;
+ QToolButton* notModifiedAfterBtn;
+
+ QLineEdit* notModifiedAfterData;
+ QLineEdit* modifiedInTheLastData;
+ QLineEdit* notModifiedInTheLastData;
+ QComboBox* modifiedInTheLastType;
+ QComboBox* notModifiedInTheLastType;
+
+ QCheckBox* belongsToUserEnabled;
+ QComboBox* belongsToUserData;
+ QCheckBox* belongsToGroupEnabled;
+ QComboBox* belongsToGroupData;
+
+ QCheckBox* permissionsEnabled;
+
+ QComboBox* ownerW;
+ QComboBox* ownerR;
+ QComboBox* ownerX;
+ QComboBox* groupW;
+ QComboBox* groupR;
+ QComboBox* groupX;
+ QComboBox* allW;
+ QComboBox* allX;
+ QComboBox* allR;
+
+ FilterTabs *fltTabs;
+
+private:
+ void changeDate(QLineEdit *p);
+ void fillList(QComboBox *list, QString filename);
+ void qdate2time_t(time_t *dest, QDate d, bool start);
+ void invalidDateMessage(QLineEdit *p);
+};
+
+#endif /* ADVANCEDFILTER_H */
diff --git a/krusader/Filter/filterbase.h b/krusader/Filter/filterbase.h
new file mode 100644
index 0000000..ef9ed4d
--- /dev/null
+++ b/krusader/Filter/filterbase.h
@@ -0,0 +1,51 @@
+/***************************************************************************
+ filterbase.h - description
+ -------------------
+ copyright : (C) 2005 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef FILTERBASE_H
+#define FILTERBASE_H
+
+#include "../VFS/krquery.h"
+#include <qstring.h>
+
+class FilterTabs;
+
+class FilterBase
+{
+public:
+ virtual bool fillQuery( KRQuery *query ) = 0;
+ virtual void queryAccepted() = 0;
+ virtual void loadFromProfile( QString name ) = 0;
+ virtual void saveToProfile( QString name ) = 0;
+ virtual QString name() = 0;
+ virtual FilterTabs * filterTabs() = 0;
+ virtual ~FilterBase() {}
+};
+
+#endif /* FILTERBASE_H */
diff --git a/krusader/Filter/filterdialog.cpp b/krusader/Filter/filterdialog.cpp
new file mode 100644
index 0000000..1c76029
--- /dev/null
+++ b/krusader/Filter/filterdialog.cpp
@@ -0,0 +1,87 @@
+/***************************************************************************
+ filterdialog.cpp - description
+ -------------------
+ copyright : (C) 2005 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "filterdialog.h"
+#include "filtertabs.h"
+#include "generalfilter.h"
+
+#include <klocale.h>
+
+FilterDialog::FilterDialog( QWidget *parent, const char *name )
+ : KDialogBase( parent, name, true, i18n("Krusader::Choose Files"), Ok|Cancel )
+{
+ QGridLayout *filterGrid = new QGridLayout( this->layout() );
+ filterGrid->setSpacing( 6 );
+ filterGrid->setMargin( 11 );
+
+ QTabWidget *filterWidget = new QTabWidget( this, "filterTabs" );
+
+ filterTabs = FilterTabs::addTo( filterWidget, FilterTabs::HasProfileHandler );
+ generalFilter = (GeneralFilter *)filterTabs->get( "GeneralFilter" );
+ generalFilter->searchFor->setEditText( "*" );
+
+ filterGrid->addWidget( filterWidget, 0, 0 );
+ setMainWidget(filterWidget);
+
+ generalFilter->searchFor->setFocus();
+
+ connect( filterTabs, SIGNAL( closeRequest(bool) ), this, SLOT( slotCloseRequest(bool) ) );
+
+ exec();
+}
+
+KRQuery FilterDialog::getQuery()
+{
+ return query;
+}
+
+void FilterDialog::slotCloseRequest( bool doAccept )
+{
+ if( doAccept )
+ {
+ slotOk();
+ accept();
+ }
+ else
+ reject();
+}
+
+void FilterDialog::slotOk()
+{
+ if( filterTabs->fillQuery( &query ) )
+ {
+ KDialogBase::slotOk();
+ return;
+ }
+
+ query = KRQuery();
+}
+
+#include "filterdialog.moc"
diff --git a/krusader/Filter/filterdialog.h b/krusader/Filter/filterdialog.h
new file mode 100644
index 0000000..18d80c3
--- /dev/null
+++ b/krusader/Filter/filterdialog.h
@@ -0,0 +1,60 @@
+/***************************************************************************
+ filterdialog.h - description
+ -------------------
+ copyright : (C) 2005 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef FILTERDIALOG_H
+#define FILTERDIALOG_H
+
+#include <kdialogbase.h>
+#include "../VFS/krquery.h"
+
+class FilterTabs;
+class GeneralFilter;
+
+class FilterDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ FilterDialog( QWidget *parent = 0, const char *name = 0 );
+ KRQuery getQuery();
+
+public slots:
+ void slotCloseRequest( bool doAccept );
+
+protected:
+ void slotOk();
+
+private:
+ FilterTabs * filterTabs;
+ GeneralFilter * generalFilter;
+ KRQuery query;
+};
+
+#endif /* FILTERDIALOG_H */
diff --git a/krusader/Filter/filtertabs.cpp b/krusader/Filter/filtertabs.cpp
new file mode 100644
index 0000000..e66e7bd
--- /dev/null
+++ b/krusader/Filter/filtertabs.cpp
@@ -0,0 +1,133 @@
+/***************************************************************************
+ filtertab.cpp - description
+ -------------------
+ copyright : (C) 2005 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "filtertabs.h"
+#include "filterdialog.h"
+#include "generalfilter.h"
+#include "advancedfilter.h"
+
+#include <klocale.h>
+
+FilterTabs::FilterTabs( int properties, QTabWidget *tabWidget, QObject *parent ) :
+ QObject( parent, 0 )
+{
+ this->tabWidget = tabWidget;
+
+ GeneralFilter *generalFilter = new GeneralFilter( this, properties, tabWidget, "generalFilter" );
+ tabWidget->insertTab( generalFilter, i18n( "&General" ) );
+ filterList.append( generalFilter );
+ pageNumbers.append( tabWidget->indexOf( generalFilter ) );
+
+ AdvancedFilter *advancedFilter = new AdvancedFilter( this, tabWidget, "advancedFilter" );
+ tabWidget->insertTab( advancedFilter, i18n( "&Advanced" ) );
+ filterList.append( advancedFilter );
+ pageNumbers.append( tabWidget->indexOf( advancedFilter ) );
+}
+
+FilterTabs * FilterTabs::addTo( QTabWidget *tabWidget, int props )
+{
+ return new FilterTabs( props, tabWidget, tabWidget );
+}
+
+void FilterTabs::saveToProfile( QString name )
+{
+ FilterBase *filter = filterList.first();
+
+ while( filter )
+ {
+ filter->saveToProfile( name );
+ filter = filterList.next();
+ }
+}
+
+void FilterTabs::loadFromProfile( QString name )
+{
+ FilterBase *filter = filterList.first();
+
+ while( filter )
+ {
+ filter->loadFromProfile( name );
+ filter = filterList.next();
+ }
+}
+
+void FilterTabs::acceptQuery()
+{
+ FilterBase *filter = filterList.first();
+
+ while( filter )
+ {
+ filter->queryAccepted();
+ filter = filterList.next();
+ }
+}
+
+bool FilterTabs::fillQuery( KRQuery *query )
+{
+ for( unsigned int i=0; i != filterList.count(); i++ )
+ {
+
+ FilterBase *filter = filterList.at( i );
+
+ bool result = filter->fillQuery( query );
+ if( result == false )
+ {
+ tabWidget->setCurrentPage( pageNumbers[ i ] );
+ return false;
+ }
+ }
+
+ acceptQuery();
+ return true;
+}
+
+FilterBase * FilterTabs::get( QString name )
+{
+ FilterBase *filter = filterList.first();
+
+ while( filter )
+ {
+ if( filter->name() == name )
+ return filter;
+
+ filter = filterList.next();
+ }
+
+ return 0;
+}
+
+KRQuery FilterTabs::getQuery( QWidget *parent, const char *name )
+{
+ FilterDialog dialog( parent, name );
+ return dialog.getQuery();
+}
+
+#include "filtertabs.moc"
+
diff --git a/krusader/Filter/filtertabs.h b/krusader/Filter/filtertabs.h
new file mode 100644
index 0000000..94c5c48
--- /dev/null
+++ b/krusader/Filter/filtertabs.h
@@ -0,0 +1,80 @@
+/***************************************************************************
+ filtertab.h - description
+ -------------------
+ copyright : (C) 2005 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef FILTERTABS_H
+#define FILTERTABS_H
+
+#include <qtabwidget.h>
+#include <qptrlist.h>
+
+#include "filterbase.h"
+
+class FilterTabs : public QObject
+{
+ Q_OBJECT
+
+ public:
+
+ enum
+ {
+ HasRemoteContentSearch = 0x0800,
+ HasProfileHandler = 0x1000,
+ HasRecurseOptions = 0x2000,
+ HasSearchIn = 0x4000,
+ HasDontSearchIn = 0x8000,
+
+ Default = 0xe000
+ };
+
+ static FilterTabs * addTo( QTabWidget *tabWidget, int props = FilterTabs::Default );
+ static KRQuery getQuery( QWidget *parent = 0, const char *name = 0 );
+
+ FilterBase *get( QString name );
+
+ public slots:
+ void loadFromProfile( QString );
+ void saveToProfile( QString );
+ bool fillQuery( KRQuery *query );
+ void close( bool accept = true ) { emit closeRequest( accept ); }
+
+ signals:
+ void closeRequest( bool accept = true );
+
+ private:
+ FilterTabs( int properties, QTabWidget *tabWidget, QObject *parent );
+ void acceptQuery();
+
+ QPtrList<FilterBase> filterList;
+ QValueList<int> pageNumbers;
+
+ QTabWidget * tabWidget;
+};
+
+#endif /* FILTERTABS_H */
diff --git a/krusader/Filter/generalfilter.cpp b/krusader/Filter/generalfilter.cpp
new file mode 100644
index 0000000..2c037a4
--- /dev/null
+++ b/krusader/Filter/generalfilter.cpp
@@ -0,0 +1,536 @@
+/***************************************************************************
+ generalfilter.cpp - description
+ -------------------
+ copyright : (C) 2003 + by Shie Erlich & Rafi Yanai & Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "generalfilter.h"
+#include "filtertabs.h"
+#include "../krusader.h"
+#include "../VFS/vfs.h"
+
+#include <klocale.h>
+#include <kfiledialog.h>
+#include <kmessagebox.h>
+#include <kiconloader.h>
+#include <qwhatsthis.h>
+#include <qpushbutton.h>
+
+GeneralFilter::GeneralFilter( FilterTabs *tabs, int properties, QWidget *parent, const char *name ) : QWidget( parent, name ),
+ profileManager( 0 ), fltTabs( tabs )
+{
+ QGridLayout *filterLayout = new QGridLayout( this );
+ filterLayout->setSpacing( 6 );
+ filterLayout->setMargin( 11 );
+
+ this->properties = properties;
+
+ // Options for name filtering
+
+ QGroupBox *nameGroup = new QGroupBox( this, "nameGroup" );
+ nameGroup->setTitle( i18n( "File name" ) );
+ nameGroup->setColumnLayout(0, Qt::Vertical );
+ nameGroup->layout()->setSpacing( 0 );
+ nameGroup->layout()->setMargin( 0 );
+ QGridLayout *nameGroupLayout = new QGridLayout( nameGroup->layout() );
+ nameGroupLayout->setAlignment( Qt::AlignTop );
+ nameGroupLayout->setSpacing( 6 );
+ nameGroupLayout->setMargin( 11 );
+
+ searchForCase = new QCheckBox( nameGroup, "searchForCase" );
+ searchForCase->setText( i18n( "&Case sensitive" ) );
+ searchForCase->setChecked( false );
+ nameGroupLayout->addWidget( searchForCase, 1, 2 );
+
+ QLabel *searchForLabel = new QLabel( nameGroup, "searchForLabel" );
+ searchForLabel->setText( i18n( "Search &for:" ) );
+ nameGroupLayout->addWidget( searchForLabel, 0, 0 );
+
+ searchFor = new KHistoryCombo( false, nameGroup, "searchFor" );
+ searchFor->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7, (QSizePolicy::SizeType)0, searchFor->sizePolicy().hasHeightForWidth() ) );
+ searchFor->setEditable( true );
+ searchFor->setDuplicatesEnabled( false );
+ searchFor->setMaxCount( 25 );
+ searchForLabel->setBuddy( searchFor );
+ nameGroupLayout->addMultiCellWidget( searchFor, 0, 0, 1, 2 );
+
+ QString s = "<p><img src='toolbar|find'></p>" + i18n("<p>The filename filtering criteria is defined here.</p><p>You can make use of wildcards. Multiple patterns are separated by space (means logical OR) and patterns are excluded from the search using the pipe symbol.</p><p>If the pattern is ended with a slash (<code>*pattern*/</code>), that means that pattern relates to recursive search of directories.<ul><li><code>pattern</code> - means to search those files/directories that name is <code>pattern</code>, recursive search goes through all subdirectories independently of the value of <code>pattern</code></li><li><code>pattern/</code> - means to search all files/directories, but recursive search goes through/excludes the directories that name is <code>pattern</code></li></ul><p></p><p>It's allowed to use quotation marks for names that contain space. Filter <code>\"Program&nbsp;Files\"</code> searches out those files/directories that name is <code>Program&nbsp;Files</code>.</p><p>Examples:<ul><code><li>*.o</li><li>*.h *.c\?\?</li><li>*.cpp *.h | *.moc.cpp</li><li>* | CVS/ .svn/</li></code></ul><b>Note</b>: the search term '<code>text</code>' is equivalent to '<code>*text*</code>'.</p>");
+ QWhatsThis::add(searchFor, s);
+ QWhatsThis::add(searchForLabel, s);
+
+ QLabel *searchType = new QLabel( nameGroup, "searchType" );
+ searchType->setText( i18n( "&Of type:" ) );
+ nameGroupLayout->addWidget( searchType, 1, 0 );
+
+ ofType = new KComboBox( false, nameGroup, "ofType" );
+ ofType->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7, (QSizePolicy::SizeType)0, ofType->sizePolicy().hasHeightForWidth() ) );
+ ofType->setEditable( false );
+ searchType->setBuddy(ofType);
+ ofType->insertItem(i18n("All Files"));
+ ofType->insertItem(i18n("Archives"));
+ ofType->insertItem(i18n("Directories"));
+ ofType->insertItem(i18n("Image Files"));
+ ofType->insertItem(i18n("Text Files"));
+ ofType->insertItem(i18n("Video Files"));
+ ofType->insertItem(i18n("Audio Files"));
+
+ nameGroupLayout->addWidget( ofType, 1, 1 );
+ filterLayout->addWidget( nameGroup, 0, 0 );
+
+ middleLayout = new QHBoxLayout();
+ middleLayout->setSpacing( 6 );
+ middleLayout->setMargin( 0 );
+ QSpacerItem* middleSpacer = new QSpacerItem( 1, 1, QSizePolicy::Fixed, QSizePolicy::Fixed );
+ middleLayout->addItem( middleSpacer );
+
+ if( properties & FilterTabs::HasProfileHandler )
+ {
+ // The profile handler
+
+ QGroupBox *profileHandler = new QGroupBox( this, "profileHandler" );
+ profileHandler->setTitle( i18n( "&Profile handler" ) );
+ profileHandler->setColumnLayout(0, Qt::Vertical );
+ profileHandler->layout()->setSpacing( 0 );
+ profileHandler->layout()->setMargin( 0 );
+ QGridLayout *profileLayout = new QGridLayout( profileHandler->layout() );
+ profileLayout->setAlignment( Qt::AlignTop );
+ profileLayout->setSpacing( 6 );
+ profileLayout->setMargin( 11 );
+
+ profileListBox = new QListBox( profileHandler, "profileListBox" );
+ profileLayout->addMultiCellWidget( profileListBox, 0, 3, 0, 0 );
+
+ profileAddBtn = new QPushButton( i18n( "&Add" ), profileHandler, "profileAddBtn" );
+ profileLayout->addWidget( profileAddBtn, 0, 1 );
+
+ profileLoadBtn = new QPushButton( i18n( "&Load" ), profileHandler, "profileLoadBtn" );
+ profileLoadBtn->setEnabled( false );
+ profileLayout->addWidget( profileLoadBtn, 1, 1 );
+
+ profileOverwriteBtn = new QPushButton( i18n( "&Overwrite" ), profileHandler, "profileOverwriteBtn" );
+ profileOverwriteBtn->setEnabled( false );
+ profileLayout->addWidget( profileOverwriteBtn, 2, 1 );
+
+ profileRemoveBtn = new QPushButton( i18n( "&Remove" ), profileHandler, "profileRemoveBtn" );
+ profileRemoveBtn->setEnabled( false );
+ profileLayout->addWidget( profileRemoveBtn, 3, 1 );
+
+ profileManager = new ProfileManager( "SelectionProfile", this, "selectionProfileManager" );
+ profileManager->hide();
+
+ middleLayout->addWidget( profileHandler );
+
+ refreshProfileListBox();
+ }
+
+ if( properties & FilterTabs::HasSearchIn )
+ {
+ // Options for search in
+
+ QGroupBox *searchInGroup = new QGroupBox( this, "searchInGroup" );
+ searchInGroup->setTitle( i18n( "&Search in" ) );
+ searchInGroup->setColumnLayout(0, Qt::Vertical );
+ searchInGroup->layout()->setSpacing( 0 );
+ searchInGroup->layout()->setMargin( 0 );
+ QGridLayout *searchInLayout = new QGridLayout( searchInGroup->layout() );
+ searchInLayout->setAlignment( Qt::AlignTop );
+ searchInLayout->setSpacing( 6 );
+ searchInLayout->setMargin( 11 );
+
+ searchIn = new KURLListRequester( searchInGroup, "searchIn" );
+ searchInLayout->addWidget( searchIn, 0, 0 );
+
+ middleLayout->addWidget( searchInGroup );
+ }
+
+ if( properties & FilterTabs::HasDontSearchIn )
+ {
+ // Options for don't search in
+
+ QGroupBox *dontSearchInGroup = new QGroupBox( this, "dontSearchInGroup" );
+ dontSearchInGroup->setTitle( i18n( "&Don't search in" ) );
+ dontSearchInGroup->setColumnLayout(0, Qt::Vertical );
+ dontSearchInGroup->layout()->setSpacing( 0 );
+ dontSearchInGroup->layout()->setMargin( 0 );
+ QGridLayout *dontSearchInLayout = new QGridLayout( dontSearchInGroup->layout() );
+ dontSearchInLayout->setAlignment( Qt::AlignTop );
+ dontSearchInLayout->setSpacing( 6 );
+ dontSearchInLayout->setMargin( 11 );
+
+ dontSearchIn = new KURLListRequester( dontSearchInGroup, "dontSearchIn" );
+ dontSearchInLayout->addWidget( dontSearchIn, 0, 0 );
+
+ middleLayout->addWidget( dontSearchInGroup );
+ }
+
+ filterLayout->addLayout( middleLayout, 1, 0 );
+
+ // Options for containing text
+
+ QGroupBox *containsGroup = new QGroupBox( this, "containsGroup" );
+ containsGroup->setTitle( i18n( "Containing text" ) );
+ containsGroup->setColumnLayout(0, Qt::Vertical );
+ containsGroup->layout()->setSpacing( 0 );
+ containsGroup->layout()->setMargin( 0 );
+ QGridLayout *containsLayout = new QGridLayout( containsGroup->layout() );
+ containsLayout->setAlignment( Qt::AlignTop );
+ containsLayout->setSpacing( 6 );
+ containsLayout->setMargin( 11 );
+
+ QHBoxLayout *containsTextLayout = new QHBoxLayout();
+ containsTextLayout->setSpacing( 6 );
+ containsTextLayout->setMargin( 0 );
+
+ QLabel *containsLabel = new QLabel( containsGroup, "containsLabel" );
+ containsLabel->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)0, (QSizePolicy::SizeType)1, containsLabel->sizePolicy().hasHeightForWidth() ) );
+ containsLabel->setText( i18n( "&Text:" ) );
+ containsTextLayout->addWidget( containsLabel );
+
+ containsText = new KHistoryCombo( false, containsGroup, "containsText" );
+ containsText->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7, (QSizePolicy::SizeType)0, containsText->sizePolicy().hasHeightForWidth() ) );
+ containsText->setDuplicatesEnabled( false );
+ containsText->setMaxCount( 25 );
+ containsTextLayout->addWidget( containsText );
+ containsLabel->setBuddy(containsText);
+
+ containsLayout->addLayout( containsTextLayout, 0, 0 );
+
+ QHBoxLayout *containsCbsLayout = new QHBoxLayout();
+ containsCbsLayout->setSpacing( 6 );
+ containsCbsLayout->setMargin( 0 );
+ QSpacerItem* cbSpacer = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ containsCbsLayout->addItem( cbSpacer );
+
+ remoteContentSearch = new QCheckBox( containsGroup, "remoteContentSearch" );
+ remoteContentSearch->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)0, remoteContentSearch->sizePolicy().hasHeightForWidth() ) );
+ remoteContentSearch->setText( i18n( "&Remote content search" ) );
+ remoteContentSearch->setChecked( false );
+ containsCbsLayout->addWidget( remoteContentSearch );
+ if( !( properties & FilterTabs::HasRemoteContentSearch ) )
+ remoteContentSearch->hide();
+
+ containsWholeWord = new QCheckBox( containsGroup, "containsWholeWord" );
+ containsWholeWord->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)0, containsWholeWord->sizePolicy().hasHeightForWidth() ) );
+ containsWholeWord->setText( i18n( "&Match whole word only" ) );
+ containsWholeWord->setChecked( false );
+ containsCbsLayout->addWidget( containsWholeWord );
+
+ containsTextCase = new QCheckBox( containsGroup, "containsTextCase" );
+ containsTextCase->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)0, containsTextCase->sizePolicy().hasHeightForWidth() ) );
+ containsTextCase->setText( i18n( "Cas&e sensitive" ) );
+ containsTextCase->setChecked( true );
+ containsCbsLayout->addWidget( containsTextCase );
+
+ containsLayout->addLayout( containsCbsLayout, 1, 0 );
+
+ filterLayout->addWidget( containsGroup, 2, 0 );
+
+ if( properties & FilterTabs::HasRecurseOptions )
+ {
+ // Options for recursive searching
+
+ QHBoxLayout *recurseLayout = new QHBoxLayout();
+ recurseLayout->setSpacing( 6 );
+ recurseLayout->setMargin( 0 );
+ QSpacerItem* recurseSpacer = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ recurseLayout->addItem( recurseSpacer );
+
+ searchInDirs = new QCheckBox( this, "searchInDirs" );
+ searchInDirs->setText( i18n( "Search in s&ubdirectories" ) );
+ searchInDirs->setChecked( true );
+ recurseLayout->addWidget( searchInDirs );
+
+ searchInArchives = new QCheckBox( this, "searchInArchives" );
+ searchInArchives->setText( i18n( "Search in arch&ives" ) );
+ recurseLayout->addWidget( searchInArchives );
+
+ followLinks = new QCheckBox( this, "followLinks" );
+ followLinks->setText( i18n( "Follow &links" ) );
+ recurseLayout->addWidget( followLinks );
+
+ filterLayout->addLayout( recurseLayout, 3, 0 );
+ }
+
+ // Connection table
+
+ if( properties & FilterTabs::HasProfileHandler )
+ {
+ connect( profileAddBtn, SIGNAL(clicked()) , this, SLOT( slotAddBtnClicked() ) );
+ connect( profileLoadBtn, SIGNAL(clicked()) , this, SLOT( slotLoadBtnClicked() ) );
+ connect( profileOverwriteBtn, SIGNAL(clicked()) , this, SLOT( slotOverwriteBtnClicked() ) );
+ connect( profileRemoveBtn, SIGNAL(clicked()) , this, SLOT( slotRemoveBtnClicked() ) );
+ connect( profileListBox, SIGNAL(doubleClicked(QListBoxItem *)) , this, SLOT( slotProfileDoubleClicked(QListBoxItem *) ) );
+ connect( profileManager, SIGNAL(loadFromProfile(QString )), fltTabs, SLOT( loadFromProfile(QString ) ) );
+ connect( profileManager, SIGNAL(saveToProfile(QString )), fltTabs, SLOT( saveToProfile(QString ) ) );
+ }
+
+ connect( searchFor, SIGNAL(activated(const QString&)), searchFor, SLOT(addToHistory(const QString&)));
+ connect( containsText, SIGNAL(activated(const QString&)), containsText, SLOT(addToHistory(const QString&)));
+
+ // load the completion and history lists
+ // ==> search for
+ krConfig->setGroup("Search");
+ QStringList list = krConfig->readListEntry("SearchFor Completion");
+ searchFor->completionObject()->setItems(list);
+ list = krConfig->readListEntry("SearchFor History");
+ searchFor->setHistoryItems(list);
+ // ==> grep
+ krConfig->setGroup("Search");
+ list = krConfig->readListEntry("ContainsText Completion");
+ containsText->completionObject()->setItems(list);
+ list = krConfig->readListEntry("ContainsText History");
+ containsText->setHistoryItems(list);
+
+ setTabOrder( searchFor, containsText ); // search for -> content
+ setTabOrder( containsText, searchType ); // content -> search type
+}
+
+GeneralFilter::~GeneralFilter()
+{
+ // save the history combos
+ // ==> search for
+ QStringList list = searchFor->completionObject()->items();
+ krConfig->setGroup("Search");
+ krConfig->writeEntry("SearchFor Completion", list);
+ list = searchFor->historyItems();
+ krConfig->writeEntry("SearchFor History", list);
+ // ==> grep text
+ list = containsText->completionObject()->items();
+ krConfig->setGroup("Search");
+ krConfig->writeEntry("ContainsText Completion", list);
+ list = containsText->historyItems();
+ krConfig->writeEntry("ContainsText History", list);
+
+ krConfig->sync();
+}
+
+bool GeneralFilter::fillQuery( KRQuery *query )
+{
+ // check that we have (at least) what to search, and where to search in
+ if (searchFor->currentText().simplifyWhiteSpace().isEmpty()) {
+ KMessageBox::error(this ,i18n("No search criteria entered!"));
+ searchFor->setFocus();
+ return false;
+ }
+
+ // now fill the query
+
+ query->setNameFilter( searchFor->currentText().stripWhiteSpace(), searchForCase->isChecked() );
+
+ bool remoteContent = (properties & FilterTabs::HasRemoteContentSearch ) ?
+ remoteContentSearch->isChecked() : false;
+
+ query->setContent( containsText->currentText(),
+ containsTextCase->isChecked(),
+ containsWholeWord->isChecked(),
+ remoteContent );
+
+ if (ofType->currentText()!=i18n("All Files"))
+ query->setMimeType( ofType->currentText() );
+ else query->setMimeType( QString::null );
+
+ if ( properties & FilterTabs::HasRecurseOptions )
+ {
+ query->setSearchInArchives( searchInArchives->isChecked() );
+ query->setRecursive( searchInDirs->isChecked() );
+ query->setFollowLinks( followLinks->isChecked() );
+
+ // create the lists
+ }
+ if( properties & FilterTabs::HasSearchIn )
+ {
+ query->setSearchInDirs( searchIn->urlList() );
+
+ // checking the lists
+
+ if (query->searchInDirs().isEmpty() ) { // we need a place to search in
+ KMessageBox::error(this ,i18n("Please specify a location to search in."));
+ searchIn->lineEdit()->setFocus();
+ return false;
+ }
+ }
+
+ if( properties & FilterTabs::HasDontSearchIn )
+ query->setDontSearchInDirs( dontSearchIn->urlList() );
+
+ return true;
+}
+
+void GeneralFilter::queryAccepted()
+{
+ searchFor->addToHistory(searchFor->currentText());
+ containsText->addToHistory(containsText->currentText());
+}
+
+void GeneralFilter::loadFromProfile( QString name )
+{
+ krConfig->setGroup( name );
+
+ searchForCase->setChecked( krConfig->readBoolEntry( "Case Sensitive Search", false ) );
+ containsTextCase->setChecked( krConfig->readBoolEntry( "Case Sensitive Content", false ) );
+ remoteContentSearch->setChecked( krConfig->readBoolEntry( "Remote Content Search", false ) );
+ containsWholeWord->setChecked( krConfig->readBoolEntry( "Match Whole Word Only", false ) );
+ containsText->setEditText( krConfig->readEntry( "Contains Text", "" ) );
+ searchFor->setEditText( krConfig->readEntry( "Search For", "" ) );
+
+ QString mime = krConfig->readEntry( "Mime Type", "" );
+ for( int i = ofType->count(); i >= 0; i-- )
+ {
+ ofType->setCurrentItem( i );
+ if( ofType->currentText() == mime )
+ break;
+ }
+
+ if( properties & FilterTabs::HasRecurseOptions )
+ {
+ searchInDirs->setChecked( krConfig->readBoolEntry( "Search In Subdirectories", true ) );
+ searchInArchives->setChecked( krConfig->readBoolEntry( "Search In Archives", false ) );
+ followLinks->setChecked( krConfig->readBoolEntry( "Follow Symlinks", false ) );
+ }
+
+ if( properties & FilterTabs::HasSearchIn )
+ {
+ searchIn->lineEdit()->setText( krConfig->readEntry( "Search In Edit", "" ) );
+
+ searchIn->listBox()->clear();
+ QStringList searchInList = krConfig->readListEntry( "Search In List" );
+ if( !searchInList.isEmpty() )
+ searchIn->listBox()->insertStringList( searchInList );
+ }
+
+ if( properties & FilterTabs::HasDontSearchIn )
+ {
+ dontSearchIn->lineEdit()->setText( krConfig->readEntry( "Dont Search In Edit", "" ) );
+
+ dontSearchIn->listBox()->clear();
+ QStringList dontSearchInList = krConfig->readListEntry( "Dont Search In List" );
+ if( !dontSearchInList.isEmpty() )
+ dontSearchIn->listBox()->insertStringList( dontSearchInList );
+ }
+}
+
+void GeneralFilter::saveToProfile( QString name )
+{
+ krConfig->setGroup( name );
+
+ krConfig->writeEntry( "Case Sensitive Search", searchForCase->isChecked() );
+ krConfig->writeEntry( "Case Sensitive Content", containsTextCase->isChecked() );
+ krConfig->writeEntry( "Remote Content Search", remoteContentSearch->isChecked() );
+ krConfig->writeEntry( "Match Whole Word Only", containsWholeWord->isChecked() );
+ krConfig->writeEntry( "Contains Text", containsText->currentText() );
+ krConfig->writeEntry( "Search For", searchFor->currentText() );
+
+ krConfig->writeEntry( "Mime Type", ofType->currentText() );
+
+ if( properties & FilterTabs::HasRecurseOptions )
+ {
+ krConfig->writeEntry( "Search In Subdirectories", searchInDirs->isChecked() );
+ krConfig->writeEntry( "Search In Archives", searchInArchives->isChecked() );
+ krConfig->writeEntry( "Follow Symlinks", followLinks->isChecked() );
+ }
+
+ if( properties & FilterTabs::HasSearchIn )
+ {
+ krConfig->writeEntry( "Search In Edit", searchIn->lineEdit()->text() );
+
+ QStringList searchInList;
+ for ( QListBoxItem *item = searchIn->listBox()->firstItem(); item != 0; item = item->next() )
+ searchInList.append( item->text().simplifyWhiteSpace() );
+ krConfig->writeEntry( "Search In List", searchInList );
+ }
+
+ if( properties & FilterTabs::HasDontSearchIn )
+ {
+ krConfig->writeEntry( "Dont Search In Edit", dontSearchIn->lineEdit()->text() );
+
+ QStringList dontSearchInList;
+ for ( QListBoxItem *item = dontSearchIn->listBox()->firstItem(); item != 0; item = item->next() )
+ dontSearchInList.append( item->text().simplifyWhiteSpace() );
+ krConfig->writeEntry( "Dont Search In List", dontSearchInList );
+ }
+}
+
+void GeneralFilter::refreshProfileListBox()
+{
+ profileListBox->clear();
+ profileListBox->insertStringList( ProfileManager::availableProfiles( "SelectionProfile" ) );
+
+ if( profileListBox->count() != 0 )
+ {
+ profileLoadBtn->setEnabled( true );
+ profileOverwriteBtn->setEnabled( true );
+ profileRemoveBtn->setEnabled( true );
+ }
+ else
+ {
+ profileLoadBtn->setEnabled( false );
+ profileOverwriteBtn->setEnabled( false );
+ profileRemoveBtn->setEnabled( false );
+ }
+}
+
+void GeneralFilter::slotAddBtnClicked()
+{
+ profileManager->newProfile( searchFor->currentText().simplifyWhiteSpace() );
+ refreshProfileListBox();
+}
+
+void GeneralFilter::slotOverwriteBtnClicked()
+{
+ QListBoxItem *item = profileListBox->item( profileListBox->currentItem() );
+ if( item != 0 )
+ profileManager->overwriteProfile( item->text() );
+}
+
+void GeneralFilter::slotRemoveBtnClicked()
+{
+ QListBoxItem *item = profileListBox->item( profileListBox->currentItem() );
+ if( item != 0 )
+ {
+ profileManager->deleteProfile( item->text() );
+ refreshProfileListBox();
+ }
+}
+
+void GeneralFilter::slotProfileDoubleClicked( QListBoxItem *item )
+{
+ if( item != 0 )
+ {
+ QString profileName = item->text();
+ profileManager->loadProfile( profileName );
+ fltTabs->close( true );
+ }
+}
+
+void GeneralFilter::slotLoadBtnClicked()
+{
+ QListBoxItem *item = profileListBox->item( profileListBox->currentItem() );
+ if( item != 0 )
+ profileManager->loadProfile( item->text() );
+}
+
+#include "generalfilter.moc"
diff --git a/krusader/Filter/generalfilter.h b/krusader/Filter/generalfilter.h
new file mode 100644
index 0000000..24e3b87
--- /dev/null
+++ b/krusader/Filter/generalfilter.h
@@ -0,0 +1,106 @@
+/***************************************************************************
+ generalfilter.h - description
+ -------------------
+ copyright : (C) 2003 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef GENERALFILTER_H
+#define GENERALFILTER_H
+
+#include "filterbase.h"
+#include "../VFS/krquery.h"
+#include "../Dialogs/kurllistrequester.h"
+#include "../GUI/profilemanager.h"
+
+#include <qwidget.h>
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qlistbox.h>
+#include <kcombobox.h>
+#include <kshellcompletion.h>
+
+class GeneralFilter : public QWidget, public FilterBase
+{
+ Q_OBJECT
+
+public:
+ GeneralFilter( FilterTabs *tabs, int properties, QWidget *parent = 0, const char *name = 0 );
+ ~GeneralFilter();
+
+ virtual bool fillQuery( KRQuery *query );
+ virtual void queryAccepted();
+ virtual void loadFromProfile( QString name );
+ virtual void saveToProfile( QString name );
+ virtual QString name() { return "GeneralFilter";}
+ virtual FilterTabs * filterTabs() { return fltTabs; }
+
+public slots:
+ void slotAddBtnClicked();
+ void slotLoadBtnClicked();
+ void slotOverwriteBtnClicked();
+ void slotRemoveBtnClicked();
+ void slotProfileDoubleClicked( QListBoxItem * );
+ void refreshProfileListBox();
+
+public:
+ QCheckBox* searchForCase;
+ QCheckBox* remoteContentSearch;
+ QCheckBox* containsTextCase;
+ QCheckBox* containsWholeWord;
+ QCheckBox* searchInDirs;
+ QCheckBox* searchInArchives;
+ QCheckBox* followLinks;
+
+ KURLListRequester *searchIn;
+ KURLListRequester *dontSearchIn;
+ QHBoxLayout *middleLayout;
+
+ KHistoryCombo* searchFor;
+ KHistoryCombo* containsText;
+
+ KComboBox* ofType;
+
+ KShellCompletion completion;
+
+ QListBox* profileListBox;
+
+ QPushButton *profileAddBtn;
+ QPushButton *profileLoadBtn;
+ QPushButton *profileOverwriteBtn;
+ QPushButton *profileRemoveBtn;
+
+ ProfileManager *profileManager;
+
+ int properties;
+
+ FilterTabs *fltTabs;
+
+};
+
+#endif /* GENERALFILTER_H */
diff --git a/krusader/GUI/Makefile.am b/krusader/GUI/Makefile.am
new file mode 100644
index 0000000..f7d9c9e
--- /dev/null
+++ b/krusader/GUI/Makefile.am
@@ -0,0 +1,18 @@
+noinst_LIBRARIES = libGUI.a
+
+INCLUDES = $(all_includes)
+
+libGUI_a_METASOURCES = AUTO
+
+libGUI_a_SOURCES = \
+ dirhistoryqueue.cpp \
+ dirhistorybutton.cpp \
+ krusaderstatus.cpp \
+ kfnkeys.cpp \
+ kcmdline.cpp \
+ syncbrowsebutton.cpp \
+ profilemanager.cpp \
+ krremoteencodingmenu.cpp \
+ mediabutton.cpp \
+ kcmdmodebutton.cpp
+
diff --git a/krusader/GUI/dirhistorybutton.cpp b/krusader/GUI/dirhistorybutton.cpp
new file mode 100644
index 0000000..1863782
--- /dev/null
+++ b/krusader/GUI/dirhistorybutton.cpp
@@ -0,0 +1,82 @@
+/***************************************************************************
+ dirhistorybutton.cpp - description
+ -------------------
+ begin : Sun Jan 4 2004
+ copyright : (C) 2004 by Shie Erlich & Rafi Yanai
+ email :
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "dirhistorybutton.h"
+#include "dirhistoryqueue.h"
+
+#include "../VFS/vfs.h"
+#include <qpopupmenu.h>
+#include <qdir.h>
+#include <klocale.h>
+#include <kiconloader.h>
+
+#include <kdebug.h>
+
+DirHistoryButton::DirHistoryButton( DirHistoryQueue* hQ, QWidget *parent, const char *name ) : QToolButton( parent, name ) {
+ KIconLoader * iconLoader = new KIconLoader();
+ QPixmap icon = iconLoader->loadIcon( "history", KIcon::Toolbar, 16 );
+
+ setFixedSize( icon.width() + 4, icon.height() + 4 );
+ setPixmap( icon );
+ setTextLabel( i18n( "Open the directory history list" ), true );
+ setPopupDelay( 10 ); // 0.01 seconds press
+ setAcceptDrops( false );
+
+ popupMenu = new QPopupMenu( this );
+ Q_CHECK_PTR( popupMenu );
+
+ setPopup( popupMenu );
+ popupMenu->setCheckable( true );
+
+ historyQueue = hQ;
+
+ connect( popupMenu, SIGNAL( aboutToShow() ), this, SLOT( slotAboutToShow() ) );
+ connect( popupMenu, SIGNAL( activated( int ) ), this, SLOT( slotPopupActivated( int ) ) );
+}
+
+DirHistoryButton::~DirHistoryButton() {}
+
+void DirHistoryButton::openPopup() {
+ QPopupMenu * pP = popup();
+ if ( pP ) {
+ popup() ->exec( mapToGlobal( QPoint( 0, height() ) ) );
+ }
+}
+/** No descriptions */
+void DirHistoryButton::slotPopup() {
+ // kdDebug() << "History slot" << endl;
+}
+/** No descriptions */
+void DirHistoryButton::slotAboutToShow() {
+ // kdDebug() << "about to show" << endl;
+ popupMenu->clear();
+ KURL::List::iterator it;
+
+ int id = 0;
+ for ( it = historyQueue->urlQueue.begin(); it != historyQueue->urlQueue.end(); ++it ) {
+ popupMenu->insertItem( (*it).prettyURL(), id++ );
+ }
+ if ( id > 0 ) {
+ popupMenu->setItemChecked( 0, true );
+ }
+}
+/** No descriptions */
+void DirHistoryButton::slotPopupActivated( int id ) {
+ emit openUrl( historyQueue->urlQueue[ id ] );
+}
+
+#include "dirhistorybutton.moc"
diff --git a/krusader/GUI/dirhistorybutton.h b/krusader/GUI/dirhistorybutton.h
new file mode 100644
index 0000000..643795a
--- /dev/null
+++ b/krusader/GUI/dirhistorybutton.h
@@ -0,0 +1,56 @@
+/***************************************************************************
+ dirhistorybutton.h - description
+ -------------------
+ begin : Sun Jan 4 2004
+ copyright : (C) 2004 by Shie Erlich & Rafi Yanai
+ email :
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef DIRHISTORYBUTTON_H
+#define DIRHISTORYBUTTON_H
+
+#include <qwidget.h>
+#include <qtoolbutton.h>
+#include <kurl.h>
+
+class QPopupMenu;
+class DirHistoryQueue;
+
+/**
+ *@author Shie Erlich & Rafi Yanai
+ */
+
+class DirHistoryButton : public QToolButton {
+ Q_OBJECT
+public:
+ DirHistoryButton(DirHistoryQueue* hQ, QWidget *parent=0, const char *name=0);
+ ~DirHistoryButton();
+
+ void openPopup();
+
+private:
+ QPopupMenu* popupMenu;
+ DirHistoryQueue* historyQueue;
+
+public slots: // Public slots
+ /** No descriptions */
+ void slotPopup();
+ /** No descriptions */
+ void slotAboutToShow();
+ /** No descriptions */
+ void slotPopupActivated(int id);
+signals: // Signals
+ /** No descriptions */
+ void openUrl(const KURL&);
+};
+
+#endif
diff --git a/krusader/GUI/dirhistoryqueue.cpp b/krusader/GUI/dirhistoryqueue.cpp
new file mode 100644
index 0000000..a66d47f
--- /dev/null
+++ b/krusader/GUI/dirhistoryqueue.cpp
@@ -0,0 +1,87 @@
+/***************************************************************************
+ dirhistoryqueue.cpp - description
+ -------------------
+ begin : Thu Jan 1 2004
+ copyright : (C) 2004 by Shie Erlich & Rafi Yanai
+ email :
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "dirhistoryqueue.h"
+#include "../Panel/listpanel.h"
+
+#include <kdebug.h>
+
+DirHistoryQueue::DirHistoryQueue( ListPanel* p ) {
+ panel = p;
+
+ connect( panel, SIGNAL( pathChanged( ListPanel* ) ), this, SLOT( slotPathChanged( ListPanel* ) ) );
+}
+DirHistoryQueue::~DirHistoryQueue() {}
+
+/** No descriptions */
+void DirHistoryQueue::slotPathChanged( ListPanel* p ) {
+ KURL url = p->virtualPath();
+ // already in the queue ?
+ if( urlQueue.findIndex( url ) >= 0 ){
+ // remove it !
+ urlQueue.remove( url );
+ }
+ // do we have room for another ?
+ if ( urlQueue.size() > 12 ) {
+ // no room - remove the oldest entry
+ urlQueue.pop_back();
+ }
+
+ urlQueue.push_front( url );
+}
+
+#if 0
+void DirHistoryQueue::addUrl(const KURL& url){
+ if ( pathQueue.findIndex( path ) == -1 ) {
+ if ( pathQueue.size() > 12 ) {
+ // remove the oldest entry
+ pathQueue.pop_back();
+ }
+ } else {
+ pathQueue.remove( path );
+ }
+
+ pathQueue.push_front( path );
+}
+
+void DirHistoryQueue::RemovePath( const QString& path ) {
+ QStringList::iterator it;
+ it = pathQueue.find( path );
+ if ( it != pathQueue.end() ) {
+ pathQueue.remove( it );
+ }
+}
+
+bool DirHistoryQueue::checkPath( const QString& path ) {
+ KURL url( path );
+
+ QString p = url.path();
+ // kdDebug() << "url:" << p << ", file: " << url.fileName() << ", dir: " << url.directory() << endl;
+ if ( url.protocol() == "file" ) {
+ QDir dir( path );
+ if ( !dir.exists() ) {
+ RemovePath( path );
+ return false;
+ }
+ }
+
+ return true;
+
+}
+#endif
+
+#include "dirhistoryqueue.moc"
diff --git a/krusader/GUI/dirhistoryqueue.h b/krusader/GUI/dirhistoryqueue.h
new file mode 100644
index 0000000..21665f8
--- /dev/null
+++ b/krusader/GUI/dirhistoryqueue.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ dirhistoryqueue.h - description
+ -------------------
+ begin : Thu Jan 1 2004
+ copyright : (C) 2004 by Shie Erlich & Rafi Yanai
+ email :
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef DIRHISTORYQUEUE_H
+#define DIRHISTORYQUEUE_H
+
+#include <qobject.h>
+#include <kurl.h>
+
+class ListPanel;
+
+/**
+ *@author Shie Erlich & Rafi Yanai
+ */
+
+class DirHistoryQueue : public QObject {
+ Q_OBJECT
+public:
+ DirHistoryQueue(ListPanel* p);
+ ~DirHistoryQueue();
+ KURL::List urlQueue;
+// bool checkPath(const QString& path);
+// void RemovePath(const QString& path);
+
+public slots: // Public slots
+ /** No descriptions */
+ void slotPathChanged(ListPanel* p);
+private:
+// void addUrl(const KURL& url);
+ ListPanel* panel;
+};
+
+#endif
diff --git a/krusader/GUI/kcmdline.cpp b/krusader/GUI/kcmdline.cpp
new file mode 100644
index 0000000..46e360f
--- /dev/null
+++ b/krusader/GUI/kcmdline.cpp
@@ -0,0 +1,253 @@
+/***************************************************************************
+ kcmdline.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+ Description
+***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+
+#include "kcmdline.h"
+#include "stdlib.h"
+#include <unistd.h>
+#include <qmessagebox.h>
+#include <kprocess.h>
+#include <qiconset.h>
+#include <qwhatsthis.h>
+#include <unistd.h>
+#include "../krusader.h"
+#include "../kicons.h"
+#include "../krslots.h"
+#include "../resources.h"
+#include "../defaults.h"
+#include "../krusaderview.h"
+#include "../Panel/listpanel.h"
+#include "../krservices.h"
+#include "../ActionMan/addplaceholderpopup.h"
+#include "kcmdmodebutton.h"
+#include <qdir.h>
+#include <kstandarddirs.h>
+#include <klocale.h>
+#include <kglobalsettings.h>
+#include <qfontmetrics.h>
+#include <qimage.h>
+#include <qstringlist.h>
+#include <qsizepolicy.h>
+#include <ktempfile.h>
+
+KCMDLine::KCMDLine( QWidget *parent, const char *name ) : QWidget( parent, name ) {
+ QGridLayout * layout = new QGridLayout( this, 1, 4 );
+ path = new QLabel( this );
+ QWhatsThis::add
+ ( path, i18n( "Name of directory where command will be processed." ) );
+ path->setAlignment( Qt::AlignRight );
+ path->setFrameStyle( QFrame::Box | QFrame::Sunken );
+ path->setLineWidth( 1 );
+ path->setFont( KGlobalSettings::generalFont() );
+ int height = QFontMetrics( KGlobalSettings::generalFont() ).height();
+ height = height + 5*(height > 14) + 6;
+ path->setMaximumHeight( height );
+ path->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred));
+ layout->addWidget( path, 0, 0 );
+
+ // and editable command line
+ completion.setMode( KURLCompletion::FileCompletion );
+ cmdLine = new KrHistoryCombo( this );
+ cmdLine->setMaxCount(100); // remember 100 commands
+ cmdLine->setDuplicatesEnabled( false );
+ cmdLine->setFont( KGlobalSettings::generalFont() );
+ cmdLine->setMaximumHeight( height );
+ cmdLine->setCompletionObject( &completion );
+ cmdLine->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
+ // load the history
+ KConfigGroupSaver grpSvr( krConfig, "Private" );
+ QStringList list = krConfig->readListEntry( "cmdline history" );
+ cmdLine->setHistoryItems( list );
+
+ connect( cmdLine, SIGNAL( returnPressed(const QString &) ), this, SLOT( slotRun() ) );
+ connect( cmdLine, SIGNAL( returnPressed(const QString &) ), cmdLine, SLOT( clearEdit() ) );
+ connect( cmdLine, SIGNAL( returnToPanel() ), this, SLOT( slotReturnFocus() ));
+
+ QWhatsThis::add
+ ( cmdLine, i18n( "<qt><p>Well, it's actually quite simple: You type your command here and Krusader obeys.</p><p><b>Tip</b>: Move within command line history with &lt;Up&gt; and &lt;Down&gt; arrows.</p></qt>" ) );
+ layout->addWidget( cmdLine, 0, 1 );
+
+ buttonAddPlaceholder = new QToolButton( this, "ButtonAddPlaceholder" );
+ buttonAddPlaceholder->setFixedSize(22,20);
+ buttonAddPlaceholder->adjustSize();
+ buttonAddPlaceholder->setPixmap( SmallIcon( "add" ) );
+ connect( buttonAddPlaceholder, SIGNAL( clicked() ), this, SLOT( addPlaceholder() ) );
+ QWhatsThis::add( buttonAddPlaceholder, i18n( "Add <b>Placeholders</b> for the selected files in the panel." ) );
+
+ layout->addWidget( buttonAddPlaceholder, 0, 2 );
+
+ // a run in terminal button
+ terminal = new KCMDModeButton( this );
+ layout->addWidget( terminal, 0, 3 );
+
+ layout->activate();
+}
+
+void KCMDLine::addPlaceholder() {
+ AddPlaceholderPopup popup( this );
+ QString exp = popup.getPlaceholder(
+ buttonAddPlaceholder->mapToGlobal( QPoint( 0, 0) )
+ );
+ this->addText( exp );
+}
+
+void KCMDLine::setCurrent( const QString &p ) {
+
+ QString pathName = p;
+ QFontMetrics fm(path->fontMetrics());
+ int textWidth = fm.width(pathName);
+ int maxWidth = ( cmdLine->width() + path->width() ) * 2 / 5;
+ int letters = p.length() / 2;
+
+ while ( letters && textWidth > maxWidth )
+ {
+ pathName = p.left( letters ) + "..." + p.right( letters );
+ letters--;
+ textWidth = fm.width(pathName);
+ }
+
+ path->setText( pathName + ">" );
+
+ completion.setDir( p );
+ // make sure our command is executed in the right directory
+ // This line is important for Krusader overall functions -> do not remove !
+ chdir( p.local8Bit() );
+}
+
+KCMDLine::~KCMDLine() {
+ KConfigGroupSaver grpSvr( krConfig, "Private" );
+ QStringList list = cmdLine->historyItems();
+ //krOut << list[0] << endl;
+ krConfig->writeEntry( "cmdline history", list );
+ krConfig->sync();
+}
+
+void KCMDLine::slotRun() {
+ const QString command1(cmdLine->currentText());
+ if ( command1.isEmpty() )
+ return ;
+ QString panelPath = path->text().left( path->text().length() - 1 );
+
+ cmdLine->addToHistory(command1);
+
+ if ( command1.simplifyWhiteSpace().left( 3 ) == "cd " ) { // cd command effect the active panel
+ QString dir = command1.right( command1.length() - command1.find( " " ) ).stripWhiteSpace();
+ if ( dir == "~" )
+ dir = QDir::homeDirPath();
+ else
+ if ( dir.left( 1 ) != "/" && !dir.contains( ":/" ) )
+ dir = panelPath + ( panelPath == "/" ? "" : "/" ) + dir;
+ SLOTS->refresh( dir );
+ } else {
+ exec();
+ cmdLine->clearEdit();
+ }
+}
+
+
+void KCMDLine::slotReturnFocus() {
+ Krusader::App->mainView->cmdLineUnFocus();
+}
+
+static const KrActionBase::ExecType execModesMenu[] = {
+ KrActionBase::Normal,
+ KrActionBase::CollectOutputSeparateStderr,
+ KrActionBase::CollectOutput,
+ KrActionBase::Terminal,
+ KrActionBase::RunInTE,
+};
+
+QString KCMDLine::command() const {
+ return cmdLine->currentText();
+}
+
+KrActionBase::ExecType KCMDLine::execType() const {
+ KConfigGroup grp( krConfig, "Private" );
+ int i = grp.readNumEntry("Command Execution Mode",0);
+ return execModesMenu[i];
+}
+
+QString KCMDLine::startpath() const {
+ return path->text().left( path->text().length() - 1 );
+}
+
+QString KCMDLine::user() const {
+ return QString();
+}
+
+QString KCMDLine::text() const {
+ return cmdLine->currentText();
+}
+
+bool KCMDLine::acceptURLs() const {
+ return false;
+}
+
+bool KCMDLine::confirmExecution() const {
+ return false;
+}
+
+bool KCMDLine::doSubstitution() const {
+ return true;
+}
+
+void KCMDLine::setText(QString text) {
+ cmdLine->setCurrentText( text );
+}
+
+void KrHistoryCombo::keyPressEvent( QKeyEvent *e ) {
+ switch (e->key()) {
+ case Key_Enter:
+ case Key_Return:
+ if (e->state() & ControlButton) {
+ SLOTS->insertFileName( ( e->state() & ShiftButton ) != 0 );
+ break;
+ }
+ KHistoryCombo::keyPressEvent(e);
+ break;
+ case Key_Down:
+ if (e->state() == ( ControlButton | ShiftButton ) ) {
+ MAIN_VIEW->focusTerminalEmulator();
+ return;
+ } else
+ KHistoryCombo::keyPressEvent(e);
+ break;
+ case Key_Up:
+ if (e->state() == ControlButton || e->state() == ( ControlButton | ShiftButton ) ) {
+ emit returnToPanel();
+ return;
+ }
+ default:
+ KHistoryCombo::keyPressEvent(e);
+ }
+}
+
+#include "kcmdline.moc"
+
diff --git a/krusader/GUI/kcmdline.h b/krusader/GUI/kcmdline.h
new file mode 100644
index 0000000..3c13efb
--- /dev/null
+++ b/krusader/GUI/kcmdline.h
@@ -0,0 +1,99 @@
+/***************************************************************************
+ kcmdline.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+ Description
+***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+
+#ifndef KCMDLINE_H
+#define KCMDLINE_H
+
+// QT includes
+#include <qwidget.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qtoolbutton.h>
+
+// KDE includes
+#include <klineedit.h>
+#include <kshellcompletion.h>
+#include <kcombobox.h>
+
+#include "../UserAction/kractionbase.h"
+
+class KCMDModeButton;
+
+class KrHistoryCombo: public KHistoryCombo {
+ Q_OBJECT
+
+ public:
+ KrHistoryCombo(QWidget *parent): KHistoryCombo(parent) {}
+
+ protected:
+ void keyPressEvent( QKeyEvent *e );
+
+ signals:
+ void returnToPanel();
+};
+
+class KCMDLine : public QWidget, KrActionBase {
+ Q_OBJECT
+ public:
+ KCMDLine( QWidget *parent = 0, const char *name = 0 );
+ ~KCMDLine();
+ void setCurrent( const QString & );
+ //virtual methods from KrActionBase
+ void setText(QString text);
+ QString command() const;
+ ExecType execType() const;
+ QString startpath() const;
+ QString user() const;
+ QString text() const;
+ bool acceptURLs() const;
+ bool confirmExecution() const;
+ bool doSubstitution() const;
+ signals:
+ void signalRun();
+ public slots:
+ inline void setFocus() { cmdLine->setFocus(); } // overloaded for KCmdLine
+ void slotReturnFocus(); // returns keyboard focus to panel
+ void slotRun();
+ void addPlaceholder();
+ void addText( QString text ) { cmdLine->setCurrentText( cmdLine->currentText() + text ); }
+ void popup() { cmdLine->popup(); }
+
+
+ private:
+ QLabel *path;
+ KrHistoryCombo *cmdLine;
+ KCMDModeButton *terminal;
+ QToolButton *buttonAddPlaceholder;
+ KShellCompletion completion;
+};
+
+#endif
diff --git a/krusader/GUI/kcmdmodebutton.cpp b/krusader/GUI/kcmdmodebutton.cpp
new file mode 100644
index 0000000..46960bc
--- /dev/null
+++ b/krusader/GUI/kcmdmodebutton.cpp
@@ -0,0 +1,74 @@
+/***************************************************************************
+ kcmmodebutton.cpp - description
+ -------------------
+
+ this file contains a class KCMDModeButton, which represents a button with
+ popup menu to switch the mode of the krusader built-in command-line
+
+ begin : Oct 2006
+ inspired by : other Krusader source files
+ author of this file : Vaclav Juza
+ email : vaclavjuza at gmail dot com
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "kcmdmodebutton.h"
+
+#include "../krusader.h"
+#include "../krusaderview.h"
+
+#include <kactionclasses.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+
+#include <kdebug.h>
+
+KCMDModeButton::KCMDModeButton( QWidget *parent, const char *name ) : QToolButton( parent, name ) {
+ setFixedSize( 22, 20 );
+/* // from the old terminal-button:
+ setTextLabel( i18n( "If pressed, Krusader executes command line in a terminal." ) );
+ QWhatsThis::add( terminal, i18n(
+ "The 'run in terminal' button allows Krusader "
+ "to run console (or otherwise non-graphical) "
+ "programs in a terminal of your choice. If it's "
+ "pressed, terminal mode is active." ) );
+*/
+ setIconSet( SmallIcon( "konsole" ) );
+ adjustSize();
+ action = new KActionMenu( i18n("Execution mode") );
+ Q_CHECK_PTR( action );
+ for( int i=0; Krusader::execTypeArray[i] != 0; i++ )
+ {
+ action->insert( *Krusader::execTypeArray[i] );
+ }
+ QPopupMenu *pP = action->popupMenu();
+ Q_CHECK_PTR( pP );
+ setPopup( pP );
+ setPopupDelay( 10 );
+ setAcceptDrops( false );
+}
+
+KCMDModeButton::~KCMDModeButton() {
+ delete action;
+}
+
+/** called when clicked to the button */
+void KCMDModeButton::openPopup() {
+ QPopupMenu * pP = popup();
+ if ( pP ) {
+ popup() ->exec( mapToGlobal( QPoint( 0, 0 ) ) );
+ }
+}
+
+
+
+#include "kcmdmodebutton.moc"
diff --git a/krusader/GUI/kcmdmodebutton.h b/krusader/GUI/kcmdmodebutton.h
new file mode 100644
index 0000000..1da4a79
--- /dev/null
+++ b/krusader/GUI/kcmdmodebutton.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ kcmmodebutton.h - description
+ -------------------
+
+ this file contains a class KCMDModeButton, which represents a button with
+ popup menu to switch the mode of the krusader built-in command-line
+
+ begin : Oct 2006
+ inspired by : other Krusader source files
+ author of this file : Vaclav Juza
+ email : vaclavjuza at gmail dot com
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KCMDMODEBUTTON_H
+#define KCMDMODEBUTTON_H
+
+#include <qtoolbutton.h>
+
+class KActionMenu;
+
+/**
+ * @author Vaclav Juza
+ *
+ * represents a button for switching the command-line execution mode
+ * It extends QToolButton, set the icon etc., and creates a popup menu
+ * containing the actions to actually switch the mode.
+ */
+class KCMDModeButton : public QToolButton {
+ Q_OBJECT
+public:
+ /** Constructor. Sets up the menu, and the icon */
+ KCMDModeButton(QWidget *parent=0, const char *name=0);
+ ~KCMDModeButton();
+
+ /** Shows the popup menu. Called when clicked to the button */
+ void openPopup();
+
+private:
+ /** The menu containing the actions for switching the mode */
+ KActionMenu *action;
+};
+
+#endif
diff --git a/krusader/GUI/kfnkeys.cpp b/krusader/GUI/kfnkeys.cpp
new file mode 100644
index 0000000..be48163
--- /dev/null
+++ b/krusader/GUI/kfnkeys.cpp
@@ -0,0 +1,133 @@
+/***************************************************************************
+ kfnkeys.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <qtooltip.h>
+#include <klocale.h>
+#include <kglobalsettings.h>
+#include <qfontmetrics.h>
+#include <qwhatsthis.h>
+#include "kfnkeys.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include "../krslots.h"
+
+KFnKeys::KFnKeys(QWidget *parent, char *name): QWidget(parent,name) {
+ krConfig->setGroup("Look&Feel");
+ ////////////////////////////////
+#define SETUP(TARGET) {\
+ TARGET->setMinimumWidth(45);\
+}
+
+ setFont( KGlobalSettings::generalFont() );
+ layout=new QGridLayout(this,1,9); // 9 keys
+ F2=new QPushButton( i18n("F2 Term ") ,this);
+ QToolTip::add( F2, "<qt>" + i18n( "<p>Open terminal in current directory.</p>"
+ "<p>The terminal can be defined in Konfigurator, "
+ "default is <b>konsole</b>.</p>" ) + "</qt>" );
+ connect(F2,SIGNAL(clicked()), SLOTS, SLOT(terminal()));
+ SETUP(F2);
+
+ F3=new QPushButton( i18n("F3 View ") ,this);
+ QToolTip::add( F3, i18n( "Open file in viewer." ) );
+ connect(F3,SIGNAL(clicked()), SLOTS, SLOT(view()));
+ SETUP(F3);
+
+ F4=new QPushButton( i18n("F4 Edit ") ,this);
+ QToolTip::add( F4, "<qt>" + i18n( "<p>Edit file.</p>"
+ "<p>The editor can be defined in Konfigurator, "
+ "default is <b>internal editor</b>.</p>" ) + "</qt>" );
+ connect(F4,SIGNAL(clicked()), SLOTS, SLOT(edit()));
+ SETUP(F4);
+
+ F5=new QPushButton( i18n("F5 Copy ") ,this);
+ QToolTip::add( F5, i18n( "Copy file from one panel to the other." ) );
+ connect(F5,SIGNAL(clicked()), SLOTS, SLOT(copyFiles()));
+ SETUP(F5);
+
+ F6=new QPushButton( i18n("F6 Move") ,this);
+ QToolTip::add( F6, i18n( "Move file from one panel to the other." ) );
+ connect(F6,SIGNAL(clicked()), SLOTS, SLOT(moveFiles()));
+ SETUP(F6);
+
+ F7=new QPushButton( i18n("F7 Mkdir ") ,this);
+ QToolTip::add( F7, i18n( "Create directory in current panel." ) );
+ connect(F7,SIGNAL(clicked()), SLOTS, SLOT(mkdir()));
+ SETUP(F7);
+
+ F8=new QPushButton( i18n("F8 Delete") ,this);
+ QToolTip::add( F8, i18n( "Delete file, directory, etc." ) );
+ connect(F8,SIGNAL(clicked()), SLOTS, SLOT(deleteFiles()));
+ SETUP(F8);
+
+ F9=new QPushButton( i18n("F9 Rename") ,this);
+ QToolTip::add( F9, i18n( "Rename file, directory, etc." ) );
+ connect(F9,SIGNAL(clicked()), SLOTS, SLOT(rename()));
+ SETUP(F9);
+
+ F10=new QPushButton( i18n("F10 Quit ") ,this);
+ QToolTip::add( F10, i18n( "Quit Krusader." ) );
+ connect(F10,SIGNAL(clicked()),krApp, SLOT(slotClose()));
+ SETUP(F10);
+
+ // set a tighter box around the keys
+ int h = QFontMetrics(F2->font()).height()+2;
+ F2->setMaximumHeight(h); F3->setMaximumHeight(h);
+ F4->setMaximumHeight(h); F5->setMaximumHeight(h);
+ F6->setMaximumHeight(h); F7->setMaximumHeight(h);
+ F8->setMaximumHeight(h); F9->setMaximumHeight(h);
+ F10->setMaximumHeight(h);
+
+ layout->addWidget(F2,0,0);
+ layout->addWidget(F3,0,1);
+ layout->addWidget(F4,0,2);
+ layout->addWidget(F5,0,3);
+ layout->addWidget(F6,0,4);
+ layout->addWidget(F7,0,5);
+ layout->addWidget(F8,0,6);
+ layout->addWidget(F9,0,7);
+ layout->addWidget(F10,0,8);
+
+ layout->activate();
+}
+
+void KFnKeys::updateShortcuts() {
+ F2->setText(krF2->shortcut().toString() + i18n(" Term"));
+ F3->setText(krF3->shortcut().toString() + i18n(" View"));
+ F4->setText(krF4->shortcut().toString() + i18n(" Edit"));
+ F5->setText(krF5->shortcut().toString() + i18n(" Copy"));
+ F6->setText(krF6->shortcut().toString() + i18n(" Move"));
+ F7->setText(krF7->shortcut().toString() + i18n(" Mkdir"));
+ F8->setText(krF8->shortcut().toString() + i18n(" Delete"));
+ F9->setText(krF9->shortcut().toString() + i18n(" Rename"));
+ F10->setText(krF10->shortcut().toString() + i18n(" Quit"));
+}
+
+#include "kfnkeys.moc"
+
diff --git a/krusader/GUI/kfnkeys.h b/krusader/GUI/kfnkeys.h
new file mode 100644
index 0000000..d25b9d1
--- /dev/null
+++ b/krusader/GUI/kfnkeys.h
@@ -0,0 +1,54 @@
+/***************************************************************************
+ kfnkeys.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KFNKEYS_H
+#define KFNKEYS_H
+
+#include <qwidget.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+
+// Function Keys widget
+///////////////////////
+class KFnKeys : public QWidget {
+ Q_OBJECT
+
+public:
+ // constructor
+ KFnKeys(QWidget *parent, char *name=0);
+ void updateShortcuts();
+
+private:
+ QPushButton *F2 ,*F3,*F4,*F5,*F6,*F7,*F8,*F9,*F10;
+ QGridLayout *layout;
+};
+
+#endif
diff --git a/krusader/GUI/krremoteencodingmenu.cpp b/krusader/GUI/krremoteencodingmenu.cpp
new file mode 100644
index 0000000..4563356
--- /dev/null
+++ b/krusader/GUI/krremoteencodingmenu.cpp
@@ -0,0 +1,207 @@
+/***************************************************************************
+ krremoteencodingmenu.cpp - description
+ -------------------
+ copyright : (C) 2005 + by Csaba Karai
+ based on : KRemoteEncodingPlugin from Dawit Alemayehu
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <kpopupmenu.h>
+#include <kcharsets.h>
+#include <kio/slaveconfig.h>
+#include <dcopclient.h>
+
+#include "../krusader.h"
+#include "../krusaderview.h"
+#include "../Panel/listpanel.h"
+#include "../Panel/panelfunc.h"
+
+#include "krremoteencodingmenu.h"
+
+#define DATA_KEY QString::fromLatin1("Charset")
+
+KrRemoteEncodingMenu::KrRemoteEncodingMenu(const QString &text, const QString &icon, QObject *parent, const char *name) :
+ KActionMenu( text, icon, parent, name ), settingsLoaded( false )
+{
+ connect(popupMenu(), SIGNAL(aboutToShow()), this, SLOT(slotAboutToShow()));
+}
+
+void KrRemoteEncodingMenu::slotAboutToShow()
+{
+ if (!settingsLoaded)
+ loadSettings();
+
+ // uncheck everything
+ for (unsigned i = 0; i < popupMenu()->count(); i++)
+ popupMenu()->setItemChecked(popupMenu()->idAt(i), false);
+
+ KURL currentURL = ACTIVE_PANEL->virtualPath();
+
+ QString charset = KIO::SlaveConfig::self()->configData(currentURL.protocol(), currentURL.host(), DATA_KEY);
+ if (!charset.isEmpty())
+ {
+ int id = 1;
+ QStringList::Iterator it;
+ for (it = encodingNames.begin(); it != encodingNames.end(); ++it, ++id)
+ if ((*it).find(charset) != -1)
+ break;
+
+// kdDebug() << k_funcinfo << "URL=" << currentURL << " charset=" << charset << endl;
+
+ if (it == encodingNames.end())
+ kdWarning() << k_funcinfo << "could not find entry for charset=" << charset << endl;
+ else
+ popupMenu()->setItemChecked(id, true);
+ }
+ else
+ popupMenu()->setItemChecked(defaultID, true);
+}
+
+void KrRemoteEncodingMenu::loadSettings()
+{
+ settingsLoaded = true;
+ encodingNames = KGlobal::charsets()->descriptiveEncodingNames();
+
+ KPopupMenu *menu = popupMenu();
+ menu->clear();
+
+ QStringList::ConstIterator it;
+ int count = 0;
+ for (it = encodingNames.begin(); it != encodingNames.end(); ++it)
+ menu->insertItem(*it, this, SLOT(slotItemSelected(int)), 0, ++count);
+ menu->insertSeparator();
+
+ menu->insertItem(i18n("Reload"), this, SLOT(slotReload()), 0, ++count);
+ menu->insertItem(i18n("Default"), this, SLOT(slotDefault()), 0, ++count);
+ defaultID = count;
+}
+
+int KrRemoteEncodingMenu::plug( QWidget *widget, int index )
+{
+ if( widget->inherits( "QPopupMenu" ) )
+ {
+ connect( widget, SIGNAL(aboutToShow()), this, SLOT(slotCheckEnabled()));
+ slotCheckEnabled();
+ }
+
+ return KActionMenu::plug( widget, index );
+}
+
+void KrRemoteEncodingMenu::slotCheckEnabled()
+{
+ KURL currentURL = ACTIVE_PANEL->virtualPath();
+ setEnabled( currentURL.protocol() == "ftp" || currentURL.protocol() == "sftp" || currentURL.protocol() == "fish" );
+}
+
+void KrRemoteEncodingMenu::slotItemSelected(int id)
+{
+ KURL currentURL = ACTIVE_PANEL->virtualPath();
+
+ KConfig config(("kio_" + currentURL.protocol() + "rc").latin1());
+ QString host = currentURL.host();
+
+ if (!popupMenu()->isItemChecked(id))
+ {
+ QString charset = KGlobal::charsets()->encodingForName( encodingNames[id - 1] );
+
+ config.setGroup(host);
+ config.writeEntry(DATA_KEY, charset);
+ config.sync();
+
+ // Update the io-slaves...
+ updateKIOSlaves();
+ }
+}
+
+void KrRemoteEncodingMenu::slotReload()
+{
+ loadSettings();
+}
+
+void KrRemoteEncodingMenu::slotDefault()
+{
+ KURL currentURL = ACTIVE_PANEL->virtualPath();
+
+ // We have no choice but delete all higher domain level
+ // settings here since it affects what will be matched.
+ KConfig config(("kio_" + currentURL.protocol() + "rc").latin1());
+
+ QStringList partList = QStringList::split('.', currentURL.host(), false);
+ if (!partList.isEmpty())
+ {
+ partList.remove(partList.begin());
+
+ QStringList domains;
+ // Remove the exact name match...
+ domains << currentURL.host();
+
+ while (partList.count())
+ {
+ if (partList.count() == 2)
+ if (partList[0].length() <= 2 && partList[1].length() == 2)
+ break;
+
+ if (partList.count() == 1)
+ break;
+
+ domains << partList.join(".");
+ partList.remove(partList.begin());
+ }
+
+ for (QStringList::Iterator it = domains.begin(); it != domains.end(); it++)
+ {
+// kdDebug() << k_funcinfo << "Domain to remove: " << *it << endl;
+ if (config.hasGroup(*it))
+ config.deleteGroup(*it);
+ else if (config.hasKey(*it))
+ config.deleteEntry(*it);
+ }
+ }
+ config.sync();
+
+ updateKIOSlaves();
+}
+
+
+void KrRemoteEncodingMenu::updateKIOSlaves()
+{
+ // Inform running io-slaves about the change...
+ DCOPClient *client = new DCOPClient();
+
+ if (!client->attach())
+ kdDebug() << "Can't connect with DCOP server." << endl;
+
+ QByteArray data;
+ QDataStream stream(data, IO_WriteOnly);
+ stream << QString::null;
+ client->send("*", "KIO::Scheduler", "reparseSlaveConfiguration(QString)", data);
+ delete client;
+
+ // Reload the page with the new charset
+ QTimer::singleShot( 500, ACTIVE_FUNC, SLOT( refresh() ) );
+}
+
+#include "krremoteencodingmenu.moc"
diff --git a/krusader/GUI/krremoteencodingmenu.h b/krusader/GUI/krremoteencodingmenu.h
new file mode 100644
index 0000000..9ee4680
--- /dev/null
+++ b/krusader/GUI/krremoteencodingmenu.h
@@ -0,0 +1,67 @@
+/***************************************************************************
+ krremoteencodingmenu.h - description
+ -------------------
+ copyright : (C) 2005 + by Csaba Karai
+ based on : KRemoteEncodingPlugin from Dawit Alemayehu
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef REMOTEENCODING_MENU_H
+#define REMOTEENCODING_MENU_H
+
+#include <qstringlist.h>
+#include <kurl.h>
+#include <klibloader.h>
+#include <kaction.h>
+
+class KrRemoteEncodingMenu: public KActionMenu
+{
+ Q_OBJECT
+public:
+ KrRemoteEncodingMenu (const QString &text, const QString &icon, QObject *parent=0, const char *name=0);
+
+ virtual int plug( QWidget *widget, int index = -1);
+
+protected slots:
+
+ void slotAboutToShow();
+ void slotCheckEnabled();
+
+ void slotItemSelected(int);
+ void slotReload();
+ void slotDefault();
+
+private:
+
+ void loadSettings();
+ void updateKIOSlaves();
+
+ QStringList encodingNames;
+ bool settingsLoaded;
+ int defaultID;
+};
+
+#endif /* REMOTEENCODING_MENU_H */
diff --git a/krusader/GUI/krusaderstatus.cpp b/krusader/GUI/krusaderstatus.cpp
new file mode 100644
index 0000000..ad11308
--- /dev/null
+++ b/krusader/GUI/krusaderstatus.cpp
@@ -0,0 +1,46 @@
+/***************************************************************************
+ krusaderstatus.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+// Krusader includes
+#include <qfontmetrics.h>
+#include "krusaderstatus.h"
+#include "../resources.h"
+
+
+KrusaderStatus::KrusaderStatus(QWidget *parent, const char *name ):
+ KStatusBar(parent,name){
+ insertItem(i18n("Ready."), S_READY_ID);
+ setMaximumHeight(QFontMetrics(font()).height()+2);
+}
+
+KrusaderStatus::~KrusaderStatus(){
+}
+
+#include "krusaderstatus.moc"
diff --git a/krusader/GUI/krusaderstatus.h b/krusader/GUI/krusaderstatus.h
new file mode 100644
index 0000000..45a4cf5
--- /dev/null
+++ b/krusader/GUI/krusaderstatus.h
@@ -0,0 +1,56 @@
+/***************************************************************************
+ krusaderstatus.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KRUSADERSTATUS_H
+#define KRUSADERSTATUS_H
+
+// QT includes
+#include <qlabel.h>
+#include <qwidget.h>
+#include <qframe.h>
+
+// KDE includes
+#include <kstatusbar.h>
+#include <klocale.h>
+
+class KrusaderStatus : public KStatusBar {
+ Q_OBJECT
+public:
+ KrusaderStatus(QWidget *parent=0, const char *name=0);
+ ~KrusaderStatus();
+
+private:
+ QLabel *mess;
+
+};
+
+#endif
diff --git a/krusader/GUI/mediabutton.cpp b/krusader/GUI/mediabutton.cpp
new file mode 100644
index 0000000..65e8fc9
--- /dev/null
+++ b/krusader/GUI/mediabutton.cpp
@@ -0,0 +1,692 @@
+/***************************************************************************
+ mediabutton.cpp - description
+ -------------------
+ copyright : (C) 2006 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "mediabutton.h"
+#include "../krusader.h"
+#include "../krservices.h"
+#include "../kicons.h"
+#include "../krslots.h"
+#include "../MountMan/kdiskfreesp.h"
+#include "../MountMan/kmountman.h"
+
+#include <qpopupmenu.h>
+#include <qfile.h>
+#include <qfontmetrics.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+
+#include <kdeversion.h>
+#include <kio/job.h>
+#include <kmessagebox.h>
+#include <kmimetype.h>
+#include <kprotocolinfo.h>
+#include <kfileitem.h>
+#include <kprocess.h>
+#include <qcursor.h>
+
+#ifdef Q_OS_LINUX
+// For CD/DVD drive detection
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <stdint.h>
+#define CDROM_GET_CAPABILITY 0x5331
+#define CDSL_CURRENT ((int) (~0U>>1))
+#define CDC_DVD_R 0x10000 /* drive can write DVD-R */
+#define CDC_DVD_RAM 0x20000 /* drive can write DVD-RAM */
+#define CDC_CD_R 0x2000 /* drive is a CD-R */
+#define CDC_CD_RW 0x4000 /* drive is a CD-RW */
+#define CDC_DVD 0x8000 /* drive is a DVD */
+#include <qfile.h>
+#endif
+
+
+
+MediaButton::MediaButton( QWidget *parent, const char *name ) : QToolButton( parent, name ),
+ popupMenu( 0 ), rightMenu( 0 ), hasMedia( false ), waitingForMount( -1 ), mountCheckerTimer()
+ {
+ KIconLoader * iconLoader = new KIconLoader();
+ QPixmap icon = iconLoader->loadIcon( "blockdevice", KIcon::Toolbar, 16 );
+
+ setFixedSize( icon.width() + 4, icon.height() + 4 );
+ setPixmap( icon );
+ setTextLabel( i18n( "Open the available media list" ), true );
+ setPopupDelay( 1 ); // immediate press
+ setAcceptDrops( false );
+
+ popupMenu = new QPopupMenu( this );
+ popupMenu->installEventFilter( this );
+ Q_CHECK_PTR( popupMenu );
+
+ setPopup( popupMenu );
+
+ connect( popupMenu, SIGNAL( aboutToShow() ), this, SLOT( slotAboutToShow() ) );
+ connect( popupMenu, SIGNAL( aboutToHide() ), this, SLOT( slotAboutToHide() ) );
+ connect( popupMenu, SIGNAL( activated( int ) ), this, SLOT( slotPopupActivated( int ) ) );
+
+ connect( &mountCheckerTimer, SIGNAL( timeout() ), this, SLOT( slotTimeout() ) );
+}
+
+MediaButton::~MediaButton() {
+ busy = false;
+}
+
+void MediaButton::slotAboutToShow() {
+ hasMedia = KProtocolInfo::isKnownProtocol( QString( "media" ) );
+ krConfig->setGroup( "Advanced" );
+ if( krConfig->readBoolEntry( "DontUseMediaProt", !hasMedia ) )
+ hasMedia = false;
+
+ popupMenu->clear();
+ urls.clear();
+ mediaUrls.clear();
+ mimes.clear();
+ quasiMounted.clear();
+ waitingForMount = -1;
+
+ if( hasMedia )
+ createListWithMedia();
+ else
+ createListWithoutMedia();
+
+ mountCheckerTimer.start( 1000, true );
+}
+
+void MediaButton::slotAboutToHide() {
+ if( rightMenu )
+ rightMenu->close();
+
+ if( waitingForMount < 0 )
+ mountCheckerTimer.stop();
+}
+
+void MediaButton::createListWithMedia() {
+ KIO::ListJob *job = KIO::listDir( KURL( "media:/" ), false );
+ connect( job, SIGNAL( entries( KIO::Job*, const KIO::UDSEntryList& ) ),
+ this, SLOT( slotEntries( KIO::Job*, const KIO::UDSEntryList& ) ) );
+ connect( job, SIGNAL( result( KIO::Job* ) ),
+ this, SLOT( slotListResult( KIO::Job* ) ) );
+ busy = true;
+
+ if( !busy )
+ qApp->processEvents();
+}
+
+void MediaButton::slotEntries( KIO::Job *, const KIO::UDSEntryList& entries )
+{
+ KMountPoint::List mountList = KMountPoint::currentMountPoints();
+
+ KIO::UDSEntryListConstIterator it = entries.begin();
+ KIO::UDSEntryListConstIterator end = entries.end();
+
+ while( it != end )
+ {
+ KURL url;
+ QString text;
+ QString mime;
+ QString localPath;
+ bool mounted = false;
+
+ KIO::UDSEntry::ConstIterator it2 = (*it).begin();
+
+ for( ; it2 != (*it).end(); it2++ ) {
+ switch ((*it2).m_uds) {
+ case KIO::UDS_NAME:
+ text = KURL::decode_string((*it2).m_str);
+ break;
+ case KIO::UDS_URL:
+ url = KURL::fromPathOrURL( (*it2).m_str );
+ break;
+ case KIO::UDS_MIME_TYPE:
+ mime = (*it2).m_str;
+ if( !mime.endsWith( "unmounted" ) )
+ mounted = true;
+ break;
+#if KDE_IS_VERSION(3,4,0)
+ case KIO::UDS_LOCAL_PATH:
+ localPath = (*it2).m_str;
+ break;
+#endif
+ }
+ }
+
+ if( text != "." && text != ".." ) {
+ int index = popupMenu->count();
+ QPixmap pixmap = FL_LOADICON( KMimeType::mimeType( mime ) ->icon( QString::null, true ) );
+
+ mediaUrls.append( url );
+
+ if( mounted && !localPath.isEmpty() )
+ {
+ url = KURL::fromPathOrURL( localPath );
+ if( !text.contains( url.path() ) )
+ text += " [" + url.path() + "]";
+ }
+ else if( mounted )
+ {
+ url = getLocalPath( url, &mountList );
+ if( url.isLocalFile() && !text.contains( url.path() ) )
+ text += " [" + url.path() + "]";
+ }
+
+ popupMenu->insertItem( pixmap, text, index, index );
+
+ urls.append( url );
+ mimes.append( mime );
+ quasiMounted.append( false );
+ }
+ ++it;
+ }
+}
+
+void MediaButton::slotListResult( KIO::Job * ) {
+ busy = false;
+}
+
+KURL MediaButton::getLocalPath( const KURL &url, KMountPoint::List *mountList ) {
+ KMountPoint::List mountListRef;
+ if( mountList == 0 ) {
+ mountListRef = KMountPoint::currentMountPoints();
+ mountList = &mountListRef;
+ }
+
+ for (KMountPoint::List::iterator it = mountList->begin(); it != mountList->end(); ++it) {
+ QString name = (*it)->mountedFrom();
+ name = name.mid( name.findRev( "/" ) + 1 );
+ if( name == url.fileName() ) {
+ QString point = (*it)->mountPoint();
+ if( !point.isEmpty() )
+ return KURL::fromPathOrURL( point );
+ }
+ }
+ return url;
+}
+
+
+void MediaButton::createListWithoutMedia() {
+ /* WORKAROUND CODE START */
+
+ /* 1. the menu is drawn when we know all the mount points
+ 2. the menu is corrected, when the HDD volume sizes arrive from df
+
+ when the volume sizes are added to the items, some cases widget resize
+ is necessary. If transparency is set for the widget, QT produces weird
+ looking widgets, and that's why this workaround is used.
+ Here we add additional spaces to the mounted HDD elements for avoiding
+ the buggy widget resize. These are extra spaces. */
+
+ extraSpaces = "";
+ QFontMetrics fm( popupMenu->font() );
+ int requiredWidth = fm.width( "999.9 GB " );
+ while( fm.width( extraSpaces ) < requiredWidth )
+ extraSpaces+=" ";
+ /* WORKAROUND CODE END */
+
+ KMountPoint::List possibleMountList = KMountPoint::possibleMountPoints();
+ for (KMountPoint::List::iterator it = possibleMountList.begin(); it != possibleMountList.end(); ++it) {
+ addMountPoint( *it, false );
+ }
+
+ KMountPoint::List mountList = KMountPoint::currentMountPoints();
+ for (KMountPoint::List::iterator it = mountList.begin(); it != mountList.end(); ++it) {
+ addMountPoint( *it, true );
+ }
+}
+
+QString MediaButton::detectType( KMountPoint *mp )
+{
+ QString typeName = QString::null;
+#ifdef Q_OS_LINUX
+ // Guessing device types by mount point is not exactly accurate...
+ // Do something accurate first, and fall back if necessary.
+
+ bool isCd=false;
+ QString devname=mp->mountedFrom().section('/', -1);
+ if(devname.startsWith("scd") || devname.startsWith("sr"))
+ {
+ // SCSI CD/DVD drive
+ isCd=true;
+ }
+ else if(devname.startsWith("hd"))
+ {
+ // IDE device -- we can't tell if this is a
+ // CD/DVD drive or harddisk by just looking at the
+ // filename
+ QFile m(QString("/proc/ide/") + devname + "/media");
+ if(m.open(IO_ReadOnly))
+ {
+ QTextStream in(&m);
+ QString buf=in.readLine();
+ if(buf.contains("cdrom"))
+ isCd=true;
+ m.close();
+ }
+ }
+ if(isCd)
+ {
+ int device=::open((const char *)QFile::encodeName(mp->mountedFrom()), O_RDONLY | O_NONBLOCK );
+ if(device>=0)
+ {
+ int drv=::ioctl(device, CDROM_GET_CAPABILITY, CDSL_CURRENT);
+ if(drv>=0)
+ {
+ if((drv & CDC_DVD_R) || (drv & CDC_DVD_RAM))
+ typeName = "dvdwriter";
+ else if((drv & CDC_CD_R) || (drv & CDC_CD_RW))
+ typeName = "cdwriter";
+ else if(drv & CDC_DVD)
+ typeName = "dvd";
+ else
+ typeName = "cdrom";
+ }
+
+ ::close(device);
+ }
+ }
+ if( !typeName.isNull() )
+ return typeName;
+
+#elif defined(__FreeBSD__)
+ if (-1!=mp->mountedFrom().find("/acd",0,FALSE)) typeName="cdrom";
+ else if (-1!=mp->mountedFrom().find("/scd",0,FALSE)) typeName="cdrom";
+ else if (-1!=mp->mountedFrom().find("/ad",0,FALSE)) typeName="hdd";
+ else if (-1!=mp->mountedFrom().find("/da",0,FALSE)) typeName="hdd";
+ else if (-1!=mp->mountedFrom().find("/afd",0,FALSE)) typeName="zip";
+ else
+#endif
+
+ /* Guessing of cdrom and cd recorder devices */
+ if (-1!=mp->mountPoint().find("cdrom",0,FALSE)) typeName="cdrom";
+ else if (-1!=mp->mountedFrom().find("cdrom",0,FALSE)) typeName="cdrom";
+ else if (-1!=mp->mountPoint().find("cdwriter",0,FALSE)) typeName="cdwriter";
+ else if (-1!=mp->mountedFrom().find("cdwriter",0,FALSE)) typeName="cdwriter";
+ else if (-1!=mp->mountedFrom().find("cdrw",0,FALSE)) typeName="cdwriter";
+ else if (-1!=mp->mountPoint().find("cdrw",0,FALSE)) typeName="cdwriter";
+ else if (-1!=mp->mountedFrom().find("cdrecorder",0,FALSE)) typeName="cdwriter";
+ else if (-1!=mp->mountPoint().find("cdrecorder",0,FALSE)) typeName="cdwriter";
+ else if (-1!=mp->mountedFrom().find("dvdrecorder",0,FALSE)) typeName="dvdwriter";
+ else if (-1!=mp->mountPoint().find("dvdrecorder",0,FALSE)) typeName="dvdwriter";
+ else if (-1!=mp->mountPoint().find("dvdwriter",0,FALSE)) typeName="dvdwriter";
+ else if (-1!=mp->mountedFrom().find("dvdwriter",0,FALSE)) typeName="dvdwriter";
+ else if (-1!=mp->mountPoint().find("dvd",0,FALSE)) typeName="dvd";
+ else if (-1!=mp->mountedFrom().find("dvd",0,FALSE)) typeName="dvd";
+ else if (-1!=mp->mountedFrom().find("/dev/scd",0,FALSE)) typeName="cdrom";
+ else if (-1!=mp->mountedFrom().find("/dev/sr",0,FALSE)) typeName="cdrom";
+
+ /* Guessing of floppy types */
+ else if (-1!=mp->mountedFrom().find("fd",0,FALSE)) {
+ if (-1!=mp->mountedFrom().find("360",0,FALSE)) typeName="floppy5";
+ if (-1!=mp->mountedFrom().find("1200",0,FALSE)) typeName="floppy5";
+ else typeName="floppy";
+ }
+ else if (-1!=mp->mountPoint().find("floppy",0,FALSE)) typeName="floppy";
+
+ else if (-1!=mp->mountPoint().find("zip",0,FALSE)) typeName="zip";
+ else if (-1!=mp->mountType().find("nfs",0,FALSE)) typeName="nfs";
+ else if (-1!=mp->mountType().find("smb",0,FALSE)) typeName="smb";
+ else if (-1!=mp->mountedFrom().find("//",0,FALSE)) typeName="smb";
+ else typeName="hdd";
+
+ return typeName;
+}
+
+void MediaButton::slotPopupActivated( int elem ) {
+ if( !quasiMounted[ elem ] && mimes[ elem ].endsWith( "_unmounted" ) ) {
+ mount( elem );
+ waitingForMount = elem;
+ maxMountWait = 20;
+ newTabAfterMount = false;
+ mountCheckerTimer.start( 1000, true );
+ return;
+ }
+ emit openUrl( urls[ elem ] );
+}
+
+void MediaButton::gettingSpaceData(const QString &mountPoint, unsigned long kBSize, unsigned long, unsigned long ) {
+ KURL mediaURL = KURL::fromPathOrURL( mountPoint );
+
+ KIO::filesize_t size = kBSize;
+ size *= 1024;
+ QString sizeText = KIO::convertSize( size );
+
+ for( unsigned i=0; i != urls.size(); i++ ) {
+ if( mediaURL.equals( urls[ i ], true ) ) {
+ if( kBSize == 0 ) { // if df gives 0, it means the device is quasy umounted
+ QString mime = mimes[ i ];
+ if( mimes[ i ].endsWith( "_mounted" ) ) {
+ quasiMounted[ i ] = true;
+ mimes[ i ] = mimes[ i ].replace( "_mounted", "_unmounted" );
+ }
+
+ QPixmap pixmap = FL_LOADICON( KMimeType::mimeType( mimes[ i ] ) ->icon( QString::null, true ) );
+ popupMenu->changeItem( i, pixmap, popupMenu->text( i ) );
+ }
+ else if( mimes[ i ].contains( "hdd_" ) )
+ popupMenu->changeItem( i, sizeText + " " + popupMenu->text( i ).stripWhiteSpace() );
+ return;
+ }
+ }
+}
+
+void MediaButton::openPopup() {
+ QPopupMenu * pP = popup();
+ if ( pP ) {
+ popup() ->exec( mapToGlobal( QPoint( 0, height() ) ) );
+ }
+}
+
+void MediaButton::addMountPoint( KMountPoint * mp, bool isMounted ) {
+ QString mountString = isMounted ? "_mounted" : "_unmounted";
+ if( mp->mountPoint() == "/dev/swap" ||
+ mp->mountPoint() == "/dev/pts" ||
+ mp->mountPoint().startsWith( "/sys/kernel" ) ||
+ mp->mountPoint().find( "/proc" ) == 0 )
+ return;
+ if( mp->mountType() == "swap" ||
+ mp->mountType() == "sysfs" ||
+ mp->mountType() == "tmpfs" ||
+ mp->mountType() == "kernfs" ||
+ mp->mountType() == "usbfs" ||
+ mp->mountType() == "unknown" ||
+ mp->mountType() == "none" ||
+ mp->mountType() == "sunrpc" )
+ return;
+ if( mp->mountedFrom() == "none" ||
+ mp->mountedFrom() == "tmpfs" ||
+ mp->mountedFrom().find( "shm" ) != -1 )
+ return;
+
+ int overwrite = -1;
+ KURL mountURL = KURL::fromPathOrURL( mp->mountPoint() );
+
+ for( unsigned i=0; i != urls.size(); i++ )
+ if( urls[ i ].equals( mountURL, true ) ) {
+ overwrite = i;
+ break;
+ }
+
+ QString name;
+ QString type = detectType( mp );
+
+ /* WORKAROUND CODE START */
+ /* add spaces to avoid widget resize in gettingSpaceData,
+ which is buggy in QT when transparency is set */
+ QString extSpc = ( isMounted && type == "hdd" ) ? extraSpaces : "";
+ /* WORKAROUND CODE END */
+
+#if KDE_IS_VERSION(3,4,0)
+ QString mimeBase = "media/";
+#else
+ QString mimeBase = "kdedevice/";
+#endif
+
+ QString mime = mimeBase + type + mountString;
+
+ if( type == "hdd" )
+ name = i18n( "Hard Disk" ) ;
+ else if( type == "cdrom" )
+ name = i18n( "CD-ROM" );
+ else if( type == "cdwriter" )
+ name = i18n( "CD Recorder" );
+ else if( type == "dvdwriter" ) {
+ mime = mimeBase + "cdwriter" + mountString;
+ name = i18n( "DVD Recorder" );
+ }
+ else if( type == "dvd" )
+ name = i18n( "DVD" );
+ else if( type == "smb" )
+ name = i18n( "Remote Share" );
+ else if( type == "nfs" )
+ name = i18n( "Remote Share" );
+ else if( type == "floppy" )
+ name = i18n( "Floppy" );
+ else if( type == "floppy5" )
+ name = i18n( "Floppy" );
+ else if( type == "zip" )
+ name = i18n( "Zip Disk" );
+ else {
+ mime = mimeBase + "hdd" + mountString;
+ name = i18n( "Unknown" );
+ }
+
+ if( isMounted ) {
+ KDiskFreeSp *sp = KDiskFreeSp::findUsageInfo( mp->mountPoint() );
+ connect( sp, SIGNAL( foundMountPoint( const QString &, unsigned long, unsigned long, unsigned long ) ),
+ this, SLOT( gettingSpaceData( const QString&, unsigned long, unsigned long, unsigned long ) ) );
+ }
+
+ QPixmap pixmap = FL_LOADICON( KMimeType::mimeType( mime ) ->icon( QString::null, true ) );
+
+ if( overwrite == -1 ) {
+ int index = popupMenu->count();
+ urls.append( KURL::fromPathOrURL( mp->mountPoint() ) );
+ mimes.append( mime );
+ mediaUrls.append( KURL() );
+ quasiMounted.append( false );
+ popupMenu->insertItem( pixmap, name + " [" + mp->mountPoint() + "]" + extSpc, index, index );
+ }
+ else {
+ mimes[ overwrite ] = mime;
+ popupMenu->changeItem( overwrite, pixmap, name + " [" + mp->mountPoint() + "]" + extSpc );
+ }
+}
+
+bool MediaButton::eventFilter( QObject *o, QEvent *e ) {
+ if( o == popupMenu ) {
+ if( e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonRelease ) {
+ QMouseEvent *m = (QMouseEvent *)e;
+ if( m->button() == RightButton ) {
+ if( e->type() == QEvent::MouseButtonPress ) {
+ int id = popupMenu->idAt( m->pos() );
+ if( id != -1 )
+ rightClickMenu( id );
+ }
+ m->accept();
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void MediaButton::rightClickMenu( int index ) {
+ if( rightMenu )
+ rightMenu->close();
+
+ QString mime = mimes[ index ];
+ bool ejectable = mime.contains( "dvd_" ) || mime.contains( "dvdwriter_" ) || mime.contains( "cdrom_" ) || mime.contains( "cdwriter_" );
+ bool mounted = mime.contains( "_mounted" );
+
+ QPopupMenu * myMenu = rightMenu = new QPopupMenu( popupMenu );
+ myMenu->insertItem( i18n( "Open" ), 1 );
+ myMenu->insertItem( i18n( "Open in a new tab" ), 2 );
+ myMenu->insertSeparator();
+ if( !mounted )
+ myMenu->insertItem( i18n( "Mount" ), 3 );
+ else
+ myMenu->insertItem( i18n( "Unmount" ), 4 );
+ if( ejectable )
+ myMenu->insertItem( i18n( "Eject" ), 5 );
+ int result = myMenu->exec( QCursor::pos() );
+ delete myMenu;
+ if( rightMenu == myMenu )
+ rightMenu = 0;
+ else
+ return;
+
+ switch ( result ) {
+ case 1:
+ case 2:
+ popupMenu->close();
+ if( mounted || quasiMounted[ index ] ) {
+ if( result == 1 )
+ emit openUrl( urls[ index ] );
+ else
+ SLOTS->newTab( urls[ index ] );
+ } else {
+ mount( index ); // mount first, when mounted open the tab
+ waitingForMount = index;
+ maxMountWait = 20;
+ newTabAfterMount = ( result == 2 );
+ mountCheckerTimer.start( 1000, true );
+ }
+ break;
+ case 3:
+ mount( index );
+ break;
+ case 4:
+ umount( index );
+ break;
+ case 5:
+ eject( index );
+ break;
+ default:
+ break;
+ }
+}
+
+bool MediaButton::mount( int index ) {
+ if ( (unsigned)index < mimes.count() ) {
+ if( !mediaUrls[ index ].isEmpty() ) {
+ KProcess proc;
+ proc << KrServices::fullPathName( "kio_media_mounthelper" ) << "-m" << mediaUrls[ index ].url();
+ proc.start( KProcess::DontCare );
+ } else {
+ krMtMan.mount( urls[ index ].path(), false );
+ }
+ }
+ return false;
+}
+
+bool MediaButton::umount( int index ) {
+ if ( (unsigned)index < mimes.count() ) {
+ if( !mediaUrls[ index ].isEmpty() ) {
+ KProcess proc;
+ proc << KrServices::fullPathName( "kio_media_mounthelper" ) << "-u" << mediaUrls[ index ].url();
+ proc.start( KProcess::DontCare );
+ } else {
+ krMtMan.unmount( urls[ index ].path(), false );
+ }
+ }
+ return false;
+}
+
+bool MediaButton::eject( int index ) {
+ if ( (unsigned)index < mimes.count() ) {
+ if( !mediaUrls[ index ].isEmpty() ) {
+ KProcess proc;
+ proc << KrServices::fullPathName( "kio_media_mounthelper" ) << "-e" << mediaUrls[ index ].url();
+ proc.start( KProcess::DontCare );
+ } else {
+ krMtMan.eject( urls[ index ].path() );
+ }
+ }
+ return false;
+}
+
+void MediaButton::slotTimeout() {
+ if( isHidden() && ( waitingForMount < 0 ) )
+ return;
+
+ KMountPoint::List mountList = KMountPoint::currentMountPoints();
+
+ for( unsigned index = 0; index < urls.count(); index++ ) {
+ bool mounted = false;
+
+ QString text = popupMenu->text( index );
+
+ if( mediaUrls[ index ].isEmpty() ) {
+ for (KMountPoint::List::iterator it = mountList.begin(); it != mountList.end(); ++it)
+ if( (*it)->mountPoint() == urls[ index ].path() ) {
+ mounted = true;;
+ break;
+ }
+ } else {
+ KURL uri = getLocalPath( mediaUrls[ index ], &mountList );
+ if( uri.isLocalFile() ) {
+ urls[ index ] = uri;
+ mounted = true;
+
+ if( !text.contains( uri.path() ) )
+ {
+ if( text.endsWith( "]" ) )
+ {
+ int ndx = text.findRev( " [" );
+ if( ndx >0 )
+ text.truncate( ndx );
+ }
+
+ text += " [" + uri.path() + "]";
+ }
+ }
+ else
+ {
+ if( text.endsWith( "]" ) )
+ {
+ int ndx = text.findRev( " [" );
+ if( ndx >0 )
+ text.truncate( ndx );
+ }
+ }
+ }
+
+ if( quasiMounted[ index ] ) // mounted but not listed with DF
+ mounted = false;
+
+ if( mimes[ index ].contains( "_mounted" ) && !mounted )
+ mimes[ index ] = mimes[ index ].replace( "_mounted", "_unmounted" );
+ if( mimes[ index ].contains( "_unmounted" ) && mounted )
+ mimes[ index ] = mimes[ index ].replace( "_unmounted", "_mounted" );
+
+ QPixmap pixmap = FL_LOADICON( KMimeType::mimeType( mimes[ index ] ) ->icon( QString::null, true ) );
+ popupMenu->changeItem( index, pixmap, text );
+
+ if( ((int)index == waitingForMount) && mounted ) {
+ waitingForMount = -1;
+ if( newTabAfterMount )
+ SLOTS->newTab( urls[ index ] );
+ else
+ emit openUrl( urls[ index ] );
+ }
+ }
+
+ if( waitingForMount >= 0 ) { // maximum wait for mounting expired ?
+ if( --maxMountWait < 0 ) {
+ waitingForMount = -1;
+ return;
+ }
+ }
+
+ mountCheckerTimer.start( 1000, true );
+}
+
+
+#include "mediabutton.moc"
diff --git a/krusader/GUI/mediabutton.h b/krusader/GUI/mediabutton.h
new file mode 100644
index 0000000..1158a2b
--- /dev/null
+++ b/krusader/GUI/mediabutton.h
@@ -0,0 +1,106 @@
+/***************************************************************************
+ mediabutton.h - description
+ -------------------
+ copyright : (C) 2006 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef MEDIABUTTON_H
+#define MEDIABUTTON_H
+
+#include <qwidget.h>
+#include <qtoolbutton.h>
+#include <kurl.h>
+#include <kio/jobclasses.h>
+#include <qvaluelist.h>
+#include <kmountpoint.h>
+#include <qtimer.h>
+
+/**
+ *@author Csaba Karai
+ */
+
+class QPopupMenu;
+class KMountPoint;
+
+class MediaButton : public QToolButton {
+ Q_OBJECT
+public:
+ MediaButton(QWidget *parent=0, const char *name=0);
+ ~MediaButton();
+
+ QString detectType( KMountPoint *mp );
+
+public slots:
+ void slotAboutToShow();
+ void slotAboutToHide();
+ void slotTimeout();
+ void slotPopupActivated( int );
+ void gettingSpaceData(const QString &mountPoint, unsigned long kBSize, unsigned long kBUsed, unsigned long kBAvail);
+ void openPopup();
+ void slotEntries( KIO::Job*, const KIO::UDSEntryList& );
+ void slotListResult( KIO::Job* );
+
+signals:
+ void openUrl(const KURL&);
+
+protected:
+ bool eventFilter( QObject *o, QEvent *e );
+
+private:
+ void createListWithMedia();
+ void createListWithoutMedia();
+
+ KURL getLocalPath( const KURL &, KMountPoint::List * list = 0 );
+ bool mount( int );
+ bool umount( int );
+ bool eject( int );
+
+ void rightClickMenu( int );
+
+ void addMountPoint( KMountPoint *mp, bool isMounted );
+
+ QPopupMenu *popupMenu;
+ QPopupMenu *rightMenu;
+
+ bool hasMedia;
+ bool busy;
+
+ int waitingForMount;
+ bool newTabAfterMount;
+ int maxMountWait;
+
+ QValueList<KURL> urls;
+ QValueList<KURL> mediaUrls;
+ QValueList<QString> mimes;
+ QValueList<bool> quasiMounted;
+
+ QString extraSpaces; //prevents from increasing the size of the widget
+
+ QTimer mountCheckerTimer;
+};
+
+#endif /* MEDIABUTTON_H */
diff --git a/krusader/GUI/profilemanager.cpp b/krusader/GUI/profilemanager.cpp
new file mode 100644
index 0000000..b886751
--- /dev/null
+++ b/krusader/GUI/profilemanager.cpp
@@ -0,0 +1,198 @@
+/***************************************************************************
+ profilemanager.cpp - description
+ -------------------
+ copyright : (C) 2004 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "../krusader.h"
+#include "profilemanager.h"
+
+#include <klocale.h>
+#include <qtooltip.h>
+#include <kpopupmenu.h>
+#include <qcursor.h>
+#include <kinputdialog.h>
+#include <kiconloader.h>
+
+ProfileManager::ProfileManager( QString profileType, QWidget * parent, const char * name )
+ : QPushButton( parent, name )
+{
+ setText( "" );
+ KIconLoader *iconLoader = new KIconLoader();
+ setPixmap( iconLoader->loadIcon( "kr_profile", KIcon::Toolbar, 16 ) );
+ QToolTip::add( this, i18n( "Profiles" ) );
+
+ this->profileType = profileType;
+
+ connect( this, SIGNAL( clicked() ), this, SLOT( profilePopup() ) );
+
+ krConfig->setGroup("Private");
+ profileList = krConfig->readListEntry( profileType );
+}
+
+void ProfileManager::profilePopup()
+{
+ // profile menu identifiers
+ #define ADD_NEW_ENTRY_ID 1000
+ #define LOAD_ENTRY_ID 2000
+ #define REMOVE_ENTRY_ID 3000
+ #define OVERWRITE_ENTRY_ID 4000
+
+ // create the menu
+ KPopupMenu popup, removePopup, overwritePopup;
+ popup.insertTitle(i18n("Profiles"));
+
+ for( unsigned i=0; i != profileList.count() ; i++ )
+ {
+ krConfig->setGroup( profileType + " - " + profileList[i] );
+ QString name = krConfig->readEntry( "Name" );
+ popup.insertItem( name, LOAD_ENTRY_ID + i );
+ removePopup.insertItem( name, REMOVE_ENTRY_ID + i );
+ overwritePopup.insertItem( name, OVERWRITE_ENTRY_ID + i );
+ }
+
+ popup.insertSeparator();
+
+ if( profileList.count() )
+ {
+ popup.insertItem( i18n("Remove entry"), &removePopup );
+ popup.insertItem( i18n("Overwrite entry"), &overwritePopup );
+ }
+
+ popup.insertItem(i18n("Add new entry"),ADD_NEW_ENTRY_ID);
+
+ unsigned result=popup.exec(QCursor::pos());
+
+ // check out the user's selection
+ if( result == ADD_NEW_ENTRY_ID )
+ newProfile();
+ else if( result >= LOAD_ENTRY_ID && result < LOAD_ENTRY_ID + profileList.count() )
+ {
+ emit loadFromProfile( profileType + " - " + profileList[ result - LOAD_ENTRY_ID ] );
+ }else if( result >= REMOVE_ENTRY_ID && result < REMOVE_ENTRY_ID + profileList.count() )
+ {
+ krConfig->deleteGroup( profileType + " - " + profileList[ result - REMOVE_ENTRY_ID ] );
+ profileList.remove( profileList[ result - REMOVE_ENTRY_ID ] );
+
+ krConfig->setGroup("Private");
+ krConfig->writeEntry( profileType, profileList );
+ krConfig->sync();
+ }else if( result >= OVERWRITE_ENTRY_ID && result < OVERWRITE_ENTRY_ID + profileList.count() )
+ {
+ emit saveToProfile( profileType + " - " + profileList[ result - OVERWRITE_ENTRY_ID ] );
+ }
+}
+
+void ProfileManager::newProfile( QString defaultName )
+{
+ QString profile = KInputDialog::getText( i18n( "Krusader::ProfileManager" ), i18n( "Enter the profile name:" ),
+ defaultName, 0, this );
+ if( !profile.isEmpty() )
+ {
+ int profileNum = 1;
+ while( profileList.contains( QString( "%1" ).arg( profileNum ) ) )
+ profileNum++;
+
+ QString profileString = QString( "%1" ).arg( profileNum );
+ QString profileName = profileType + " - " + profileString;
+ profileList.append( QString( "%1" ).arg( profileString ) );
+
+ krConfig->setGroup("Private");
+ krConfig->writeEntry( profileType, profileList );
+
+ krConfig->setGroup( profileName );
+ krConfig->writeEntry( "Name", profile );
+ emit saveToProfile( profileName );
+ krConfig->sync();
+ }
+}
+
+void ProfileManager::deleteProfile( QString name )
+{
+ for( unsigned i=0; i != profileList.count() ; i++ )
+ {
+ krConfig->setGroup( profileType + " - " + profileList[ i ] );
+ QString currentName = krConfig->readEntry( "Name" );
+
+ if( name == currentName )
+ {
+ krConfig->deleteGroup( profileType + " - " + profileList[ i ] );
+ profileList.remove( profileList[ i ] );
+
+ krConfig->setGroup("Private");
+ krConfig->writeEntry( profileType, profileList );
+ krConfig->sync();
+ return;
+ }
+ }
+}
+
+void ProfileManager::overwriteProfile( QString name )
+{
+ for( unsigned i=0; i != profileList.count() ; i++ )
+ {
+ krConfig->setGroup( profileType + " - " + profileList[ i ] );
+ QString currentName = krConfig->readEntry( "Name" );
+
+ if( name == currentName )
+ {
+ emit saveToProfile( profileType + " - " + profileList[ i ] );
+ return;
+ }
+ }
+}
+
+bool ProfileManager::loadProfile( QString name )
+{
+ for( unsigned i=0; i != profileList.count() ; i++ )
+ {
+ krConfig->setGroup( profileType + " - " + profileList[i] );
+ QString currentName = krConfig->readEntry( "Name" );
+
+ if( name == currentName )
+ {
+ emit loadFromProfile( profileType + " - " + profileList[ i ] );
+ return true;
+ }
+ }
+ return false;
+}
+
+QStringList ProfileManager::availableProfiles( QString profileType ) {
+ krConfig->setGroup("Private");
+ QStringList profiles = krConfig->readListEntry( profileType );
+ QStringList profileNames;
+
+ for( unsigned i=0; i != profiles.count() ; i++ ) {
+ krConfig->setGroup( profileType + " - " + profiles[ i ] );
+ profileNames.append( krConfig->readEntry("Name") );
+ }
+
+ return profileNames;
+}
+
+#include "profilemanager.moc"
diff --git a/krusader/GUI/profilemanager.h b/krusader/GUI/profilemanager.h
new file mode 100644
index 0000000..7566872
--- /dev/null
+++ b/krusader/GUI/profilemanager.h
@@ -0,0 +1,69 @@
+/***************************************************************************
+ profilemanager.h - description
+ -------------------
+ copyright : (C) 2004 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef PROFILEMANAGER_H
+#define PROFILEMANAGER_H
+
+#include <qpushbutton.h>
+#include <qstring.h>
+
+class ProfileManager : public QPushButton
+{
+ Q_OBJECT
+
+public:
+ ProfileManager( QString profileType, QWidget * parent = 0, const char * name = 0 );
+
+ /**
+ * @param profileType Type of the profile (sync, search, ...)
+ * @return A list of all available profile-names
+ */
+ static QStringList availableProfiles( QString profileType );
+
+ QStringList getNames();
+
+public slots:
+ void profilePopup();
+
+ void newProfile( QString defaultName = QString::null );
+ void deleteProfile( QString name );
+ void overwriteProfile( QString name );
+ bool loadProfile( QString name );
+
+signals:
+ void saveToProfile( QString profileName );
+ void loadFromProfile( QString profileName );
+
+private:
+ QString profileType;
+ QStringList profileList;
+};
+
+#endif /* PROFILEMANAGER_H */
diff --git a/krusader/GUI/syncbrowsebutton.cpp b/krusader/GUI/syncbrowsebutton.cpp
new file mode 100644
index 0000000..7f42594
--- /dev/null
+++ b/krusader/GUI/syncbrowsebutton.cpp
@@ -0,0 +1,72 @@
+/***************************************************************************
+ syncbrowsebutton.h - description
+ -------------------
+ copyright : (C) 2004 by Jonas Bhr
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+This is the button which toggles the synchron-browse-mode (a directory-change
+is done in both panels)
+I could imagine an optional extension which also performs mkdir etc. in the other panel
+or in ALL tabs on the other side (this could also include copy-actions to this panels)
+This is very handy if you have several identical clients which you want to update
+simoultanious.
+
+The current version only manages sync-browse and got no mode-switch options.
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "syncbrowsebutton.h"
+
+#include <klocale.h>
+#include <kiconloader.h>
+
+//#include <kdebug.h>
+
+SyncBrowseButton::SyncBrowseButton(QWidget *parent, const char *name) : QToolButton(parent,name)
+{
+ KIconLoader *iconLoader = new KIconLoader();
+ _icon_on = iconLoader->loadIcon( "kr_syncbrowse_on", KIcon::Toolbar, 16 );
+ _icon_off = iconLoader->loadIcon( "kr_syncbrowse_off", KIcon::Toolbar, 16 );
+
+ setFixedSize( _icon_off.width() + 4, _icon_off.height() + 4 );
+ setPixmap( _icon_off );
+ setToggleButton( true );
+
+ setTextLabel( i18n( "This button toggles the sync-browse mode.\n"
+ "When active, each directory change is performed in the\n"
+ "active and inactive panel - if possible." ), true ); //set this as toop-tip (somehow whatsthis::add(this, ...) don't work)
+
+ connect( this, SIGNAL(toggled(bool)), this, SLOT(slotToggled(bool)) );
+}
+
+SyncBrowseButton::~SyncBrowseButton() {
+}
+
+void SyncBrowseButton::slotToggled( bool on ) {
+ if ( on )
+ setPixmap( _icon_on );
+ else
+ setPixmap( _icon_off );
+}
+
+int SyncBrowseButton::state() {
+ if ( isOn() )
+ _state = SYNCBROWSE_CD;
+ else
+ _state = SYNCBROWSE_OFF;
+
+ return _state;
+}
+
+
+#include "syncbrowsebutton.moc"
diff --git a/krusader/GUI/syncbrowsebutton.h b/krusader/GUI/syncbrowsebutton.h
new file mode 100644
index 0000000..7345151
--- /dev/null
+++ b/krusader/GUI/syncbrowsebutton.h
@@ -0,0 +1,66 @@
+/***************************************************************************
+ syncbrowsebutton.h - description
+ -------------------
+ copyright : (C) 2004 by Jonas Bhr
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+This is the button which toggles the synchron-browse-mode (a directory-change
+is done in both panels)
+I could imagine an optional extension which also performs mkdir etc. in the other panel
+or in ALL tabs on the other side (this could also include copy-actions to this panels)
+This is very handy if you have several identical clients which you want to update
+simoultanious.
+
+The current version only manages sync-browse and got no mode-switch options.
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef SYNCBROWSEBUTTON_H
+#define SYNCBROWSEBUTTON_H
+
+#include <qtoolbutton.h>
+
+// No synchrone browsing
+#define SYNCBROWSE_OFF 0
+// Change only the directory
+#define SYNCBROWSE_CD 1
+/*
+// Make new dirs in both panels
+#define SYNCBROWSE_MKDIR 2
+// Delete in both panels
+#define SYNCBROWSE_DELETE 4
+
+// Do everything in all tabs on the other side (not only the oposite panel)
+#define SYNCBROWSE_ALLTABS 1024
+// Copy files not only to the other panel but to all tabs on the other side
+#define SYNCBROWSE_COPY 2048
+*/
+
+class SyncBrowseButton : public QToolButton {
+ Q_OBJECT
+public:
+ SyncBrowseButton(QWidget *parent=0, const char *name=0);
+ ~SyncBrowseButton();
+
+ int state();
+
+protected:
+ int _state;
+ QPixmap _icon_on;
+ QPixmap _icon_off;
+
+private slots:
+ void slotToggled(bool on);
+};
+
+#endif
diff --git a/krusader/KViewer/Makefile.am b/krusader/KViewer/Makefile.am
new file mode 100644
index 0000000..f4bf90f
--- /dev/null
+++ b/krusader/KViewer/Makefile.am
@@ -0,0 +1,11 @@
+noinst_LIBRARIES = libKViewer.a
+
+INCLUDES = $(all_includes)
+
+libKViewer_a_METASOURCES = AUTO
+
+libKViewer_a_SOURCES = \
+ krviewer.cpp \
+ kimagefilepreview.cpp \
+ panelviewer.cpp \
+ diskusageviewer.cpp
diff --git a/krusader/KViewer/diskusageviewer.cpp b/krusader/KViewer/diskusageviewer.cpp
new file mode 100644
index 0000000..76ad373
--- /dev/null
+++ b/krusader/KViewer/diskusageviewer.cpp
@@ -0,0 +1,129 @@
+/***************************************************************************
+ diskusageviewer.cpp - description
+ -------------------
+ copyright : (C) 2005 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "../krusader.h"
+#include "../krusaderview.h"
+#include "../Panel/listpanel.h"
+#include "../Panel/panelfunc.h"
+#include "diskusageviewer.h"
+
+DiskUsageViewer::DiskUsageViewer( QWidget *parent, char *name )
+ : QWidget( parent, name ), diskUsage( 0 ), statusLabel( 0 )
+{
+ layout = new QGridLayout( this, 1, 1 );
+}
+
+DiskUsageViewer::~ DiskUsageViewer()
+{
+ if( diskUsage )
+ {
+ krConfig->setGroup( "DiskUsageViewer" );
+ krConfig->writeEntry( "View", diskUsage->getActiveView() );
+ delete diskUsage;
+ }
+}
+
+void DiskUsageViewer::openURL( KURL url )
+{
+ if( diskUsage == 0 )
+ {
+ diskUsage = new DiskUsage( "DiskUsageViewer", this );
+
+ connect( diskUsage, SIGNAL( enteringDirectory( Directory * ) ), this, SLOT( slotUpdateStatus() ) );
+ connect( diskUsage, SIGNAL( status( QString ) ), this, SLOT( slotUpdateStatus( QString ) ) );
+ connect( diskUsage, SIGNAL( newSearch() ), this, SLOT( slotNewSearch() ) );
+ layout->addWidget( diskUsage, 0, 0 );
+ this->show();
+ diskUsage->show();
+
+ krConfig->setGroup( "DiskUsageViewer" );
+ int view = krConfig->readNumEntry( "View", VIEW_FILELIGHT );
+ if( view < VIEW_LINES || view > VIEW_FILELIGHT )
+ view = VIEW_FILELIGHT;
+ diskUsage->setView( view );
+ }
+
+ url.setPath( url.path( -1 ) );
+
+ KURL baseURL = diskUsage->getBaseURL();
+ if( !diskUsage->isLoading() && !baseURL.isEmpty() )
+ {
+ if( url.protocol() == baseURL.protocol() && ( !url.hasHost() || url.host() == baseURL.host() ) )
+ {
+ QString baseStr = baseURL.path( 1 ), urlStr = url.path( 1 );
+
+ if( urlStr.startsWith( baseStr ) )
+ {
+ QString relURL = urlStr.mid( baseStr.length() );
+ if( relURL.endsWith( "/" ) )
+ relURL.truncate( relURL.length() -1 );
+
+ Directory *dir = diskUsage->getDirectory( relURL );
+ if( dir )
+ {
+ diskUsage->changeDirectory( dir );
+ return;
+ }
+ }
+ }
+ }
+ diskUsage->load( url );
+}
+
+void DiskUsageViewer::closeURL()
+{
+ if( diskUsage )
+ diskUsage->close();
+}
+
+void DiskUsageViewer::setStatusLabel( QLabel *statLabel, QString pref )
+{
+ statusLabel = statLabel;
+ prefix = pref;
+}
+
+void DiskUsageViewer::slotUpdateStatus( QString status )
+{
+ if( statusLabel ) {
+ if( status.isEmpty() ) {
+ Directory * dir = diskUsage->getCurrentDir();
+ if( dir )
+ status = prefix + dir->name() + " [" + KIO::convertSize( dir->size() ) + "]";
+ }
+ statusLabel->setText( status );
+ }
+}
+
+void DiskUsageViewer::slotNewSearch()
+{
+ diskUsage->load( ACTIVE_PANEL->func->files()->vfs_getOrigin() );
+}
+
+#include "diskusageviewer.moc"
diff --git a/krusader/KViewer/diskusageviewer.h b/krusader/KViewer/diskusageviewer.h
new file mode 100644
index 0000000..9049cfd
--- /dev/null
+++ b/krusader/KViewer/diskusageviewer.h
@@ -0,0 +1,68 @@
+/***************************************************************************
+ diskusageviewer.h - description
+ -------------------
+ copyright : (C) 2005 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef DISKUSAGEVIEWER_H
+#define DISKUSAGEVIEWER_H
+
+#include "../DiskUsage/diskusage.h"
+#include <kurl.h>
+#include <qlayout.h>
+#include <qlabel.h>
+
+class DiskUsageViewer : public QWidget
+{
+ Q_OBJECT
+
+public:
+ DiskUsageViewer( QWidget *parent = 0, char *name = 0 );
+ ~DiskUsageViewer();
+
+ void openURL( KURL url );
+ void closeURL();
+ void setStatusLabel( QLabel *statLabel, QString pref );
+
+ inline DiskUsage * getWidget() { return diskUsage; }
+
+signals:
+ void openURLRequest(const KURL &);
+
+protected slots:
+ void slotUpdateStatus( QString status = QString() );
+ void slotNewSearch();
+
+protected:
+ DiskUsage *diskUsage;
+ QGridLayout *layout;
+
+ QLabel *statusLabel;
+ QString prefix;
+};
+
+#endif /* DISKUSAGEVIEWER_H */
diff --git a/krusader/KViewer/kimagefilepreview.cpp b/krusader/KViewer/kimagefilepreview.cpp
new file mode 100644
index 0000000..84039e0
--- /dev/null
+++ b/krusader/KViewer/kimagefilepreview.cpp
@@ -0,0 +1,136 @@
+/*
+* This file is part of the KDE project
+* Copyright (C) 2001 Martin R. Jones <mjones@kde.org>
+* 2001 Carsten Pfeiffer <pfeiffer@kde.org>
+*
+* You can Freely distribute this program under the GNU Library General Public
+* License. See the file "COPYING" for the exact licensing terms.
+*/
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <qwhatsthis.h>
+#include <qtimer.h>
+
+#include <kapplication.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+#include <kpushbutton.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kfiledialog.h>
+#include <kfileitem.h>
+#include <kio/previewjob.h>
+
+#include "kimagefilepreview.h"
+
+/**** KrusaderImageFilePreview ****/
+
+KrusaderImageFilePreview::KrusaderImageFilePreview( QWidget *parent )
+ : KPreviewWidgetBase( parent ),
+m_job( 0L ) {
+ QVBoxLayout *vb = new QVBoxLayout( this, KDialog::marginHint() );
+
+ imageLabel = new QLabel( this );
+ imageLabel->setFrameStyle( QFrame::Panel | QFrame::Sunken );
+ imageLabel->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
+ imageLabel->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Ignored ) );
+ vb->addWidget( imageLabel, 1 );
+
+ timer = new QTimer( this );
+ connect( timer, SIGNAL( timeout() ), SLOT( showPreview() ) );
+
+ setSupportedMimeTypes( KIO::PreviewJob::supportedMimeTypes() );
+}
+
+KrusaderImageFilePreview::~KrusaderImageFilePreview() {
+ if ( m_job )
+ m_job->kill();
+}
+
+void KrusaderImageFilePreview::showPreview() {
+ // Pass a copy since clearPreview() will clear currentURL
+ KURL url = currentURL;
+ showPreview( url, true );
+}
+
+// called via KPreviewWidgetBase interface
+void KrusaderImageFilePreview::showPreview( const KURL& url ) {
+ showPreview( url, false );
+}
+
+void KrusaderImageFilePreview::showPreview( const KURL &url, bool force ) {
+ if ( !url.isValid() ) {
+ clearPreview();
+ return ;
+ }
+
+ if ( url != currentURL || force ) {
+ clearPreview();
+ currentURL = url;
+
+ int w = imageLabel->contentsRect().width() - 4;
+ int h = imageLabel->contentsRect().height() - 4;
+
+ m_job = createJob( url, w, h );
+ connect( m_job, SIGNAL( result( KIO::Job * ) ),
+ this, SLOT( slotResult( KIO::Job * ) ) );
+ connect( m_job, SIGNAL( gotPreview( const KFileItem*,
+ const QPixmap& ) ),
+ SLOT( gotPreview( const KFileItem*, const QPixmap& ) ) );
+
+ connect( m_job, SIGNAL( failed( const KFileItem* ) ),
+ this, SLOT( slotFailed( const KFileItem* ) ) );
+ }
+}
+
+void KrusaderImageFilePreview::resizeEvent( QResizeEvent * ) {
+ timer->start( 100, true ); // forces a new preview
+}
+
+QSize KrusaderImageFilePreview::sizeHint() const {
+ return QSize( 20, 200 ); // otherwise it ends up huge???
+}
+
+KIO::PreviewJob * KrusaderImageFilePreview::createJob( const KURL& url, int w, int h ) {
+ KURL::List urls;
+ urls.append( url );
+ return KIO::filePreview( urls, w, h, 0, 0, true, false );
+}
+
+void KrusaderImageFilePreview::gotPreview( const KFileItem* item, const QPixmap& pm ) {
+ if ( item->url() == currentURL ) // should always be the case
+ imageLabel->setPixmap( pm );
+}
+
+void KrusaderImageFilePreview::slotFailed( const KFileItem* item ) {
+ if ( item->isDir() )
+ imageLabel->clear();
+ else if ( item->url() == currentURL ) // should always be the case
+ imageLabel->setPixmap( SmallIcon( "file_broken", KIcon::SizeLarge,
+ KIcon::DisabledState ) );
+}
+
+void KrusaderImageFilePreview::slotResult( KIO::Job *job ) {
+ if ( job == m_job )
+ m_job = 0L;
+}
+
+void KrusaderImageFilePreview::clearPreview() {
+ if ( m_job ) {
+ m_job->kill();
+ m_job = 0L;
+ }
+
+ imageLabel->clear();
+ currentURL = KURL();
+}
+
+void KrusaderImageFilePreview::virtual_hook( int id, void* data ) {
+ KPreviewWidgetBase::virtual_hook( id, data );
+}
+
+#include "kimagefilepreview.moc"
diff --git a/krusader/KViewer/kimagefilepreview.h b/krusader/KViewer/kimagefilepreview.h
new file mode 100644
index 0000000..7e0caec
--- /dev/null
+++ b/krusader/KViewer/kimagefilepreview.h
@@ -0,0 +1,70 @@
+/*
+*
+* This file is part of the KDE project.
+* Copyright (C) 2001 Martin R. Jones <mjones@kde.org>
+* 2001 Carsten Pfeiffer <pfeiffer@kde.org>
+*
+* Modified for Krusader by Shie Erlich, October 2004
+*
+* You can Freely distribute this program under the GNU Library General Public
+* License. See the file "COPYING" for the exact licensing terms.
+*/
+
+#ifndef KrusaderImageFilePreview_H
+#define KrusaderImageFilePreview_H
+
+#include <qpixmap.h>
+
+#include <kurl.h>
+#include <kpreviewwidgetbase.h>
+
+class QCheckBox;
+class QPushButton;
+class QLabel;
+class QTimer;
+
+class KFileDialog;
+class KFileItem;
+
+class KrusaderImageFilePreview : public KPreviewWidgetBase {
+ Q_OBJECT
+
+ public:
+ KrusaderImageFilePreview( QWidget *parent );
+ ~KrusaderImageFilePreview();
+
+ virtual QSize sizeHint() const;
+
+ public slots:
+ virtual void showPreview( const KURL &url );
+ virtual void clearPreview();
+
+ protected slots:
+ void showPreview();
+ void showPreview( const KURL& url, bool force );
+
+ virtual void gotPreview( const KFileItem*, const QPixmap& );
+
+ protected:
+ virtual void resizeEvent( QResizeEvent *e );
+ virtual KIO::PreviewJob * createJob( const KURL& url,
+ int w, int h );
+
+ private slots:
+ void slotResult( KIO::Job * );
+ virtual void slotFailed( const KFileItem* );
+
+ private:
+ KURL currentURL;
+ QTimer *timer;
+ QLabel *imageLabel;
+ QLabel *infoLabel;
+ KIO::PreviewJob *m_job;
+ protected:
+ virtual void virtual_hook( int id, void* data );
+ private:
+ class KrusaderImageFilePreviewPrivate;
+ KrusaderImageFilePreviewPrivate *d;
+};
+
+#endif // KrusaderImageFilePreview_H
diff --git a/krusader/KViewer/krviewer.cpp b/krusader/KViewer/krviewer.cpp
new file mode 100644
index 0000000..4e73bda
--- /dev/null
+++ b/krusader/KViewer/krviewer.cpp
@@ -0,0 +1,702 @@
+/***************************************************************************
+ krviewer.cpp - description
+ -------------------
+ begin : Thu Apr 18 2002
+ copyright : (C) 2002 by Shie Erlich & Rafi Yanai
+ email :
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+// Qt includes
+#include <qdatastream.h>
+#include <qfile.h>
+#include <qpopupmenu.h>
+#include <qtimer.h>
+// KDE includes
+#include <kmenubar.h>
+#include <kmimetype.h>
+#include <klocale.h>
+#include <kparts/part.h>
+#include <kparts/componentfactory.h>
+#include <kmessagebox.h>
+#include <klibloader.h>
+#include <ktrader.h>
+#include <kio/netaccess.h>
+#include <kio/jobclasses.h>
+#include <kio/job.h>
+#include <kstatusbar.h>
+#include <kdebug.h>
+#include <klargefile.h>
+#include <khtml_part.h>
+#include <kprocess.h>
+#include <kfileitem.h>
+// Krusader includes
+#include "krviewer.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include "../kicons.h"
+
+#include "panelviewer.h"
+
+#define VIEW_ICON "viewmag"
+#define EDIT_ICON "edit"
+#define MODIFIED_ICON "filesaveas"
+
+
+QPtrList<KrViewer> KrViewer::viewers;
+
+KrViewer::KrViewer( QWidget *parent, const char *name ) :
+KParts::MainWindow( parent, name ), manager( this, this ), tabBar( this ), returnFocusTo( 0 ), returnFocusTab( 0 ),
+ reservedKeys(), reservedKeyIDs() {
+
+ //setWFlags(WType_TopLevel | WDestructiveClose);
+ setXMLFile( "krviewer.rc" ); // kpart-related xml file
+ setHelpMenuEnabled( false );
+
+ setAutoSaveSettings( "KrViewerWindow", true );
+ tmpFile.setAutoDelete( true );
+
+ connect( &manager, SIGNAL( activePartChanged( KParts::Part* ) ),
+ this, SLOT( createGUI( KParts::Part* ) ) );
+ connect( &tabBar, SIGNAL( currentChanged( QWidget *) ),
+ this, SLOT( tabChanged(QWidget*) ) );
+ connect( &tabBar, SIGNAL( closeRequest( QWidget *) ),
+ this, SLOT( tabCloseRequest(QWidget*) ) );
+
+ tabBar.setTabReorderingEnabled(false);
+#if KDE_IS_VERSION(3,4,0)
+ tabBar.setAutomaticResizeTabs(true);
+#endif
+// "edit"
+// "filesaveas"
+ setCentralWidget( &tabBar );
+
+ printAction = KStdAction::print( this, SLOT( print() ), 0, 0 );
+ copyAction = KStdAction::copy( this, SLOT( copy() ), 0, 0 );
+
+ viewerMenu = new QPopupMenu( this );
+ viewerMenu->insertItem( i18n( "&Generic viewer" ), this, SLOT( viewGeneric() ), CTRL + SHIFT + Key_G, 1 );
+ viewerMenu->insertItem( i18n( "&Text viewer" ), this, SLOT( viewText() ), CTRL + SHIFT + Key_T, 2 );
+ viewerMenu->insertItem( i18n( "&Hex viewer" ), this, SLOT( viewHex() ), CTRL + SHIFT + Key_H, 3 );
+ viewerMenu->insertSeparator();
+ viewerMenu->insertItem( i18n( "Text &editor" ), this, SLOT( editText() ), CTRL + SHIFT + Key_E, 4 );
+ viewerMenu->insertSeparator();
+ viewerMenu->insertItem( i18n( "&Next tab" ), this, SLOT( nextTab() ), ALT+Key_Right );
+ viewerMenu->insertItem( i18n( "&Previous tab" ), this, SLOT( prevTab() ), ALT+Key_Left );
+
+ detachActionIndex = viewerMenu->insertItem( i18n( "&Detach tab" ), this, SLOT( detachTab() ), CTRL + SHIFT + Key_D );
+ //no point in detaching only one tab..
+ viewerMenu->setItemEnabled(detachActionIndex,false);
+ viewerMenu->insertSeparator();
+ viewerMenu->insertItem( printAction->text(), this, SLOT( print() ), printAction->shortcut() );
+ viewerMenu->insertItem( copyAction->text(), this, SLOT( copy() ), copyAction->shortcut() );
+ viewerMenu->insertSeparator();
+ tabCloseID = viewerMenu->insertItem( i18n( "&Close current tab" ), this, SLOT( tabCloseRequest() ), Key_Escape );
+ closeID = viewerMenu->insertItem( i18n( "&Quit" ), this, SLOT( close() ), CTRL + Key_Q );
+
+ //toolBar() ->insertLined("Edit:",1,"",this,"",true ,i18n("Enter an URL to edit and press enter"));
+
+ tabBar.setHoverCloseButton(true);
+
+ checkModified();
+}
+
+KrViewer::~KrViewer() {
+
+ disconnect( &manager, SIGNAL( activePartChanged( KParts::Part* ) ),
+ this, SLOT( createGUI( KParts::Part* ) ) );
+
+ viewers.remove( this );
+ delete printAction;
+ delete copyAction;
+}
+
+void KrViewer::createGUI( KParts::Part* part ) {
+ if ( part == 0 ) /* KHTMLPart calls this function with 0 at destruction. */
+ return ; /* Can cause crash after JavaScript self.close() if removed */
+
+
+ // and show the new part widget
+ connect( part, SIGNAL( setStatusBarText( const QString& ) ),
+ this, SLOT( slotSetStatusBarText( const QString& ) ) );
+
+ KParts::MainWindow::createGUI( part );
+ toolBar() ->insertLineSeparator(0);
+
+ PanelViewerBase *pvb = getPanelViewerBase( part );
+ if( pvb )
+ updateActions( pvb );
+
+ toolBar() ->show();
+ statusBar() ->show();
+
+ // the KParts part may override the viewer shortcuts. We prevent it
+ // by installing an event filter on the menuBar() and the part
+ reservedKeys.clear();
+ reservedKeyIDs.clear();
+
+ // getting the key sequences of the viewer menu
+ for( unsigned w=0; w != viewerMenu->count(); w++ )
+ {
+ int id = viewerMenu->idAt( w );
+ QKeySequence sequence = viewerMenu->accel( id );
+ if( sequence.count() > 0 )
+ {
+ reservedKeys.push_back( sequence[ 0 ] );
+ reservedKeyIDs.push_back( id );
+ }
+ }
+
+ // and "fix" the menubar
+ menuBar() ->removeItem( 70 );
+ menuBar() ->insertItem( i18n( "&KrViewer" ), viewerMenu, 70 );
+ menuBar() ->show();
+
+ // filtering out the key events
+ menuBar() ->installEventFilter( this );
+ part->installEventFilter( this );
+}
+
+bool KrViewer::eventFilter ( QObject * /* watched */, QEvent * e )
+{
+ if( e->type() == QEvent::AccelOverride )
+ {
+ QKeyEvent* ke = (QKeyEvent*) e;
+ if( reservedKeys.contains( ke->key() ) )
+ {
+ ke->accept();
+
+ int id = reservedKeyIDs[ reservedKeys.findIndex( ke->key() ) ];
+ if( id != -1 )
+ {
+ // don't activate the close functions immediately!
+ // it can cause crash
+ if( id == tabCloseID )
+ QTimer::singleShot( 0, this, SLOT( tabCloseRequest() ) );
+ else if( id == closeID )
+ QTimer::singleShot( 0, this, SLOT( close() ) );
+ else {
+ int index = viewerMenu->indexOf( id );
+ viewerMenu->activateItemAt( index );
+ }
+ }
+ return true;
+ }
+ }
+ else if( e->type() == QEvent::KeyPress )
+ {
+ QKeyEvent* ke = (QKeyEvent*) e;
+ if( reservedKeys.contains( ke->key() ) )
+ {
+ ke->accept();
+ return true;
+ }
+ }
+ return false;
+}
+void KrViewer::keyPressEvent( QKeyEvent *e ) {
+ switch ( e->key() ) {
+ case Key_F10:
+ close();
+ break;
+ case Key_Escape:
+ tabCloseRequest();
+ break;
+ default:
+ e->ignore();
+ break;
+ }
+}
+
+KrViewer* KrViewer::getViewer(bool new_window){
+ if( !new_window ){
+ if( !viewers.first() ){
+ viewers.prepend( new KrViewer() ); // add to first (active)
+ }
+ else {
+ if( viewers.first()->isMinimized() ) // minimized? -> show it again
+ viewers.first()->showNormal();
+ viewers.first()->raise();
+ viewers.first()->setActiveWindow();
+ }
+ return viewers.first();
+ }
+ else {
+ KrViewer *newViewer = new KrViewer();
+ viewers.prepend( newViewer );
+ return newViewer;
+ }
+}
+
+void KrViewer::view( KURL url, QWidget * parent ) {
+ Mode defaultMode = Generic;
+ bool defaultWindow = false;
+
+ krConfig->setGroup( "General" );
+ defaultWindow = krConfig->readBoolEntry( "View In Separate Window",_ViewInSeparateWindow );
+
+ QString modeString = krConfig->readEntry( "Default Viewer Mode","generic" );
+
+ if( modeString == "generic" ) defaultMode = Generic;
+ else if( modeString == "text" ) defaultMode = Text;
+ else if( modeString == "hex" ) defaultMode = Hex;
+
+ view(url,defaultMode,defaultWindow, parent );
+}
+
+void KrViewer::view( KURL url, Mode mode, bool new_window, QWidget * parent ) {
+ KrViewer* viewer = getViewer(new_window);
+
+ PanelViewerBase* viewWidget = new PanelViewer(&viewer->tabBar);
+ KParts::Part* part = viewWidget->openURL(url,mode);
+ viewer->addTab(viewWidget,i18n( "Viewing" ),VIEW_ICON,part);
+
+ viewer->returnFocusTo = parent;
+ viewer->returnFocusTab = viewWidget;
+}
+
+void KrViewer::edit( KURL url, QWidget * parent ) {
+ edit( url, Text, -1, parent );
+}
+
+void KrViewer::edit( KURL url, Mode mode, int new_window, QWidget * parent ) {
+ krConfig->setGroup( "General" );
+ QString edit = krConfig->readEntry( "Editor", _Editor );
+
+ if( new_window == -1 )
+ new_window = krConfig->readBoolEntry( "View In Separate Window",_ViewInSeparateWindow );
+
+ if ( edit != "internal editor" ) {
+ KProcess proc;
+ // if the file is local, pass a normal path and not a url. this solves
+ // the problem for editors that aren't url-aware
+ if ( url.isLocalFile() )
+ proc << QStringList::split( ' ', edit ) << url.path();
+ else proc << QStringList::split( ' ', edit ) << url.prettyURL();
+ if ( !proc.start( KProcess::DontCare ) )
+ KMessageBox::sorry( krApp, i18n( "Can't open " ) + "\"" + edit + "\"" );
+ return ;
+ }
+
+ KrViewer* viewer = getViewer(new_window);
+
+ PanelViewerBase* editWidget = new PanelEditor(&viewer->tabBar);
+ KParts::Part* part = editWidget->openURL(url,mode);
+ viewer->addTab(editWidget,i18n("Editing"),EDIT_ICON,part);
+
+ viewer->returnFocusTo = parent;
+ viewer->returnFocusTab = editWidget;
+}
+
+void KrViewer::addTab(PanelViewerBase* pvb, QString msg, QString iconName ,KParts::Part* part){
+ if( !part ) return;
+
+ KURL url = pvb->url();
+ setCaption( msg+": " + url.prettyURL() );
+
+ QIconSet icon = QIconSet(krLoader->loadIcon(iconName,KIcon::Small));
+
+ manager.addPart( part, this );
+ manager.setActivePart( part );
+ tabBar.insertTab(pvb,icon,url.fileName()+"("+msg+")");
+ tabBar.setCurrentPage(tabBar.indexOf(pvb));
+ tabBar.setTabToolTip(pvb,msg+": " + url.prettyURL());
+
+ updateActions( pvb );
+
+ // now we can offer the option to detach tabs (we have more than one)
+ if( tabBar.count() > 1 ){
+ viewerMenu->setItemEnabled(detachActionIndex,true);
+ }
+
+ show();
+ tabBar.show();
+
+ connect( pvb, SIGNAL( urlChanged( PanelViewerBase *, const KURL & ) ),
+ this, SLOT( tabURLChanged(PanelViewerBase *, const KURL & ) ) );
+}
+
+void KrViewer::tabURLChanged( PanelViewerBase *pvb, const KURL & url ) {
+ QString msg = pvb->isEditor() ? i18n( "Editing" ) : i18n( "Viewing" );
+ tabBar.setTabLabel( pvb, url.fileName()+"("+msg+")" );
+ tabBar.setTabToolTip(pvb,msg+": " + url.prettyURL());
+}
+
+void KrViewer::tabChanged(QWidget* w){
+ manager.setActivePart( static_cast<PanelViewerBase*>(w)->part() );
+
+ if( static_cast<PanelViewerBase*>(w) != returnFocusTab ) {
+ returnFocusTo = 0;
+ returnFocusTab = 0;
+ }
+
+ // set this viewer to be the main viewer
+ if( viewers.remove( this ) ) viewers.prepend( this ); // move to first
+}
+
+void KrViewer::tabCloseRequest(QWidget *w){
+ if( !w ) return;
+
+ // important to save as returnFocusTo will be cleared at removePart
+ QWidget * returnFocusToThisWidget = returnFocusTo;
+
+ PanelViewerBase* pvb = static_cast<PanelViewerBase*>(w);
+
+ if( !pvb->queryClose() )
+ return;
+
+ manager.removePart(pvb->part());
+
+ pvb->closeURL();
+
+ tabBar.removePage(w);
+
+ if( tabBar.count() <= 0 ){
+ if( returnFocusToThisWidget ){
+ returnFocusToThisWidget->raise();
+ returnFocusToThisWidget->setActiveWindow();
+ }
+ else {
+ krApp->raise();
+ krApp->setActiveWindow();
+ }
+ delete this;
+ return;
+ } else if( tabBar.count() == 1 ){
+ //no point in detaching only one tab..
+ viewerMenu->setItemEnabled(detachActionIndex,false);
+ }
+
+ if( returnFocusToThisWidget ){
+ returnFocusToThisWidget->raise();
+ returnFocusToThisWidget->setActiveWindow();
+ }
+}
+
+void KrViewer::tabCloseRequest(){
+ tabCloseRequest( tabBar.currentPage() );
+}
+
+bool KrViewer::queryClose() {
+ for( int i=0; i != tabBar.count(); i++ ) {
+ PanelViewerBase* pvb = static_cast<PanelViewerBase*>( tabBar.page( i ) );
+ if( !pvb )
+ continue;
+
+ tabBar.setCurrentPage( i );
+
+ if( !pvb->queryClose() )
+ return false;
+ }
+ return true;
+}
+
+bool KrViewer::queryExit() {
+ return true; // don't let the reference counter reach zero
+}
+
+void KrViewer::viewGeneric(){
+ PanelViewerBase* pvb = static_cast<PanelViewerBase*>( tabBar.currentPage() );
+ if( !pvb ) return;
+
+ PanelViewerBase* viewerWidget = new PanelViewer(&tabBar);
+ KParts::Part* part = viewerWidget->openURL(pvb->url(),Generic);
+ addTab(viewerWidget,i18n("Viewing"),VIEW_ICON,part);
+}
+
+void KrViewer::viewText(){
+ PanelViewerBase* pvb = static_cast<PanelViewerBase*>( tabBar.currentPage() );
+ if( !pvb ) return;
+
+ PanelViewerBase* viewerWidget = new PanelViewer(&tabBar);
+ KParts::Part* part = viewerWidget->openURL(pvb->url(),Text);
+ addTab(viewerWidget,i18n("Viewing"),VIEW_ICON,part);
+}
+
+void KrViewer::viewHex(){
+ PanelViewerBase* pvb = static_cast<PanelViewerBase*>( tabBar.currentPage() );
+ if( !pvb ) return;
+
+ PanelViewerBase* viewerWidget = new PanelViewer(&tabBar);
+ KParts::Part* part = viewerWidget->openURL(pvb->url(),Hex);
+ addTab(viewerWidget,i18n("Viewing"),VIEW_ICON,part);
+}
+
+void KrViewer::editText(){
+ PanelViewerBase* pvb = static_cast<PanelViewerBase*>( tabBar.currentPage() );
+ if( !pvb ) return;
+
+ PanelViewerBase* editWidget = new PanelEditor(&tabBar);
+ KParts::Part* part = editWidget->openURL(pvb->url(),Text);
+ addTab(editWidget,i18n("Editing"),EDIT_ICON,part);
+}
+
+void KrViewer::checkModified(){
+ QTimer::singleShot( 1000, this, SLOT(checkModified()) );
+
+ PanelViewerBase* pvb = static_cast<PanelViewerBase*>( tabBar.currentPage() );
+ if( !pvb ) return;
+
+ if( !pvb->part()->url().equals( pvb->url(), true ) ) {
+ pvb->setUrl( pvb->part()->url() );
+ }
+
+ // add a * to modified files.
+ if( pvb->isModified() ){
+ QString label = tabBar.tabLabel(pvb);
+ if( !label.startsWith("*" + pvb->part()->url().fileName() ) ){
+ label.prepend("*");
+ QIconSet icon = QIconSet(krLoader->loadIcon(MODIFIED_ICON,KIcon::Small));
+
+ tabBar.changeTab(pvb,icon,label);
+ }
+ }
+ // remove the * from previously modified files.
+ else {
+ QString label = tabBar.tabLabel(pvb);
+ if( label.startsWith("*" + pvb->part()->url().fileName() ) ){
+ label = label.mid( 1 );
+ QIconSet icon = QIconSet(krLoader->loadIcon(EDIT_ICON,KIcon::Small));
+
+ tabBar.changeTab(pvb,icon,label);
+ }
+ }
+}
+
+void KrViewer::nextTab(){
+ int index = (tabBar.currentPageIndex()+1)%tabBar.count();
+ tabBar.setCurrentPage( index );
+}
+
+void KrViewer::prevTab(){
+ int index = (tabBar.currentPageIndex()-1)%tabBar.count();
+ while( index < 0 ) index+=tabBar.count();
+ tabBar.setCurrentPage( index );
+}
+
+void KrViewer::detachTab(){
+ PanelViewerBase* pvb = static_cast<PanelViewerBase*>( tabBar.currentPage() );
+ if( !pvb ) return;
+
+ KrViewer* viewer = getViewer(true);
+
+ manager.removePart(pvb->part());
+ tabBar.removePage(pvb);
+
+ if( tabBar.count() == 1 ) {
+ //no point in detaching only one tab..
+ viewerMenu->setItemEnabled(detachActionIndex,false);
+ }
+
+ pvb->reparent(&viewer->tabBar,QPoint(0,0));
+
+ if( pvb->isEditor() )
+ viewer->addTab(pvb,i18n( "Editing" ),EDIT_ICON,pvb->part());
+ else
+ viewer->addTab(pvb,i18n( "Viewing" ),VIEW_ICON,pvb->part());
+}
+
+void KrViewer::windowActivationChange ( bool /* oldActive */ ) {
+ if( isActiveWindow() )
+ if( viewers.remove( this ) ) viewers.prepend( this ); // move to first
+}
+
+void KrViewer::print() {
+ PanelViewerBase* pvb = static_cast<PanelViewerBase*>( tabBar.currentPage() );
+ if( !pvb ) return;
+
+ KParts::BrowserExtension * ext = KParts::BrowserExtension::childObject( pvb->part() );
+ if( ext && ext->isActionEnabled( "print" ) )
+ Invoker( ext, SLOT( print() ) ).invoke();
+}
+
+void KrViewer::copy() {
+ PanelViewerBase* pvb = static_cast<PanelViewerBase*>( tabBar.currentPage() );
+ if( !pvb ) return;
+
+ KParts::BrowserExtension * ext = KParts::BrowserExtension::childObject( pvb->part() );
+ if( ext && ext->isActionEnabled( "copy" ) )
+ Invoker( ext, SLOT( copy() ) ).invoke();
+}
+
+PanelViewerBase * KrViewer::getPanelViewerBase( KParts::Part * part ) {
+ for( int i=0; i != tabBar.count(); i++ ) {
+ PanelViewerBase *pvb = static_cast<PanelViewerBase*>( tabBar.page( i ) );
+ if( pvb && pvb->part() == part )
+ return pvb;
+ }
+ return 0;
+}
+
+void KrViewer::updateActions( PanelViewerBase * pvb ) {
+ if( pvb->isEditor() ) {
+ printAction->unplugAll();
+ copyAction->unplugAll();
+ }
+ else {
+ if( !printAction->isPlugged( toolBar() ) )
+ printAction->plug( toolBar(), 0 );
+ if( !copyAction->isPlugged( toolBar() ) )
+ copyAction->plug( toolBar(), 1 );
+ }
+}
+
+#if 0
+bool KrViewer::editGeneric( QString mimetype, KURL _url ) {
+ KParts::ReadWritePart * kedit_part = 0L;
+ KLibFactory *factory = 0;
+ KTrader::OfferList offers = KTrader::self() ->query( mimetype );
+
+ // in theory, we only care about the first one.. but let's try all
+ // offers just in case the first can't be loaded for some reason
+ KTrader::OfferList::Iterator it( offers.begin() );
+ for ( ; it != offers.end(); ++it ) {
+ KService::Ptr ptr = ( *it );
+ // we now know that our offer can handle mimetype and is a part.
+ // since it is a part, it must also have a library... let's try to
+ // load that now
+ factory = KLibLoader::self() ->factory( ptr->library().latin1() );
+ if ( factory ) {
+ kedit_part = static_cast<KParts::ReadWritePart *>( factory->create( this,
+ ptr->name().latin1(), "KParts::ReadWritePart" ) );
+ if ( kedit_part )
+ if ( kedit_part->openURL( _url ) ) break;
+ else {
+ delete kedit_part;
+ kedit_part = 0L;
+ }
+ }
+ }
+
+ if ( !kedit_part ) {
+ KMessageBox::error( this, i18n( "Sorry, can't find internal editor" ) );
+ return false;
+ }
+
+ setCentralWidget( kedit_part->widget() );
+ createGUI( kedit_part );
+ kedit_part->widget() ->show();
+ return true;
+}
+
+bool KrViewer::editText( bool create ) {
+ if ( !editor_part ) {
+ editor_part = static_cast<KParts::ReadWritePart*>( getPart( url, "text/plain", false, create ) );
+ if ( !editor_part ) return false;
+ manager.addPart( editor_part, this );
+ }
+ manager.setActivePart( editor_part );
+ tabBar.addTab(editor_part->widget(),url.fileName());
+ return true;
+}
+
+bool KrViewer::viewGeneric() {
+ QString mimetype = KMimeType::findByURL( url ) ->name();
+ // ugly hack: don't try to get a part for an XML file, it usually don't work
+ if ( mimetype == "text/xml" ) return false;
+ if ( url.prettyURL().startsWith( "man:" ) ) mimetype = "text/html";
+ if ( mimetype == "text/plain" )
+ viewerMenu->setItemEnabled( 1, false );
+
+ if ( !generic_part ) {
+ if ( mimetype.contains( "html" ) ) {
+ KHTMLPart * p = new KHTMLPart( this, 0, 0, 0, KHTMLPart::BrowserViewGUI );
+ connect( p->browserExtension(), SIGNAL( openURLRequest( const KURL &, const KParts::URLArgs & ) ),
+ this, SLOT( handleOpenURLRequest( const KURL &, const KParts::URLArgs & ) ) );
+ /* At JavaScript self.close() the KHTMLPart destroys itself. */
+ /* After destruction, just close the window */
+ connect( p, SIGNAL( destroyed() ), this, SLOT( close() ) );
+
+ p-> openURL( url );
+ generic_part = p;
+ } else {
+ generic_part = static_cast<KParts::ReadOnlyPart*>( getPart( url, mimetype, true ) );
+ }
+ if ( generic_part ) manager.addPart( generic_part, this );
+
+ else return false;
+ }
+
+ manager.setActivePart( generic_part );
+ tabBar.addTab(generic_part->widget(),url.fileName());
+ return true;
+}
+
+bool KrViewer::viewText() {
+ if ( !text_part ) {
+ text_part = static_cast<KParts::ReadOnlyPart*>( getPart( url, "text/plain", true ) );
+ if ( !text_part ) return false;
+ manager.addPart( text_part, this );
+ }
+ manager.setActivePart( text_part );
+ tabBar.addTab(text_part->widget(),url.fileName());
+ return true;
+}
+
+void KrViewer::viewHex() {
+ if ( !hex_part ) {
+ QString file;
+ // files that are not local must first be downloaded
+ if ( !url.isLocalFile() ) {
+ if ( !KIO::NetAccess::download( url, file ) ) {
+ KMessageBox::sorry( this, i18n( "KrViewer is unable to download: " ) + url.url() );
+ return ;
+ }
+ } else file = url.path();
+
+
+ // create a hex file
+ QFile f_in( file );
+ f_in.open( IO_ReadOnly );
+ QDataStream in( &f_in );
+
+ FILE *out = KDE_fopen( tmpFile.name().local8Bit(), "w" );
+
+ KIO::filesize_t fileSize = f_in.size();
+ KIO::filesize_t address = 0;
+ char buf[ 16 ];
+ unsigned int* pBuff = ( unsigned int* ) buf;
+
+ while ( address < fileSize ) {
+ memset( buf, 0, 16 );
+ int bufSize = ( ( fileSize - address ) > 16 ) ? 16 : ( fileSize - address );
+ in.readRawBytes( buf, bufSize );
+ fprintf( out, "0x%8.8llx: ", address );
+ for ( int i = 0; i < 4; ++i ) {
+ if ( i < ( bufSize / 4 ) ) fprintf( out, "%8.8x ", pBuff[ i ] );
+ else fprintf( out, " " );
+ }
+ fprintf( out, "| " );
+
+ for ( int i = 0; i < bufSize; ++i ) {
+ if ( buf[ i ] > ' ' && buf[ i ] < '~' ) fputc( buf[ i ], out );
+ else fputc( '.', out );
+ }
+ fputc( '\n', out );
+
+ address += 16;
+ }
+ // clean up
+ f_in.close();
+ fclose( out );
+ if ( !url.isLocalFile() )
+ KIO::NetAccess::removeTempFile( file );
+
+ hex_part = static_cast<KParts::ReadOnlyPart*>( getPart( tmpFile.name(), "text/plain", true ) );
+ if ( !hex_part ) return ;
+ manager.addPart( hex_part, this );
+ }
+ manager.setActivePart( hex_part );
+ tabBar.addTab(hex_part->widget(),url.fileName());
+}
+#endif
+
+
+#include "krviewer.moc"
diff --git a/krusader/KViewer/krviewer.h b/krusader/KViewer/krviewer.h
new file mode 100644
index 0000000..618e9a2
--- /dev/null
+++ b/krusader/KViewer/krviewer.h
@@ -0,0 +1,128 @@
+/***************************************************************************
+ krviewer.h - description
+ -------------------
+ begin : Thu Apr 18 2002
+ copyright : (C) 2002 by Shie Erlich & Rafi Yanai
+ email :
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KRVIEWER_H
+#define KRVIEWER_H
+
+#include <qwidget.h>
+#include <qptrlist.h>
+#include <kparts/mainwindow.h>
+#include <ktempfile.h>
+#include <kparts/partmanager.h>
+#include <kparts/browserextension.h>
+#include <qguardedptr.h>
+#include <ktabwidget.h>
+
+#include "../krusader.h"
+
+
+/**
+ *@author Shie Erlich & Rafi Yanai
+ */
+
+class QPopupMenu;
+class PanelViewerBase;
+
+class KrViewer : public KParts::MainWindow {
+ Q_OBJECT
+public:
+ virtual ~KrViewer();
+
+ enum Mode{Generic,Text,Hex};
+
+ static void view( KURL url, QWidget * parent = krApp );
+ static void view( KURL url, Mode mode, bool new_window, QWidget * parent = krApp );
+ static void edit( KURL url, QWidget * parent );
+ static void edit( KURL url, Mode mode=Text, int new_window=-1, QWidget * parent = krApp );
+
+ virtual bool eventFilter ( QObject * watched, QEvent * e );
+
+public slots:
+ void keyPressEvent( QKeyEvent *e );
+ void createGUI( KParts::Part* );
+
+ void viewGeneric();
+ void viewText();
+ void viewHex();
+ void editText();
+
+ void print();
+ void copy();
+
+ void tabChanged(QWidget* w);
+ void tabURLChanged( PanelViewerBase * pvb, const KURL &url );
+ void tabCloseRequest(QWidget *w);
+ void tabCloseRequest();
+
+ void nextTab();
+ void prevTab();
+ void detachTab();
+
+ void checkModified();
+
+protected:
+ virtual bool queryClose();
+ virtual bool queryExit();
+ virtual void windowActivationChange ( bool oldActive );
+
+ virtual void focusInEvent( QFocusEvent * ){ if( viewers.remove( this ) ) viewers.prepend( this ); } // move to first
+
+private:
+ KrViewer( QWidget *parent = 0, const char *name = 0 );
+ void addTab(PanelViewerBase* pvb, QString msg,QString iconName, KParts::Part* part);
+ PanelViewerBase * getPanelViewerBase( KParts::Part* part);
+ void updateActions( PanelViewerBase * base );
+
+ static KrViewer* getViewer(bool new_window);
+
+ KParts::PartManager manager;
+ QPopupMenu* viewerMenu;
+ KTempFile tmpFile;
+ KTabWidget tabBar;
+ QGuardedPtr<QWidget> returnFocusTo;
+ PanelViewerBase * returnFocusTab;
+
+ int detachActionIndex;
+
+ KAction *printAction;
+ KAction *copyAction;
+
+ int tabCloseID;
+ int closeID;
+
+ static QPtrList<KrViewer> viewers; // the first viewer is the active one
+ QValueList<int> reservedKeys; // the reserved key sequences
+ QValueList<int> reservedKeyIDs; // the IDs of the reserved keys
+};
+
+class Invoker : public QObject {
+ Q_OBJECT
+
+public:
+ Invoker( QObject *recv, const char * slot ) {
+ connect( this, SIGNAL( invokeSignal() ), recv, slot );
+ }
+
+ void invoke() {
+ emit invokeSignal();
+ }
+
+signals:
+ void invokeSignal();
+};
+
+#endif
diff --git a/krusader/KViewer/panelviewer.cpp b/krusader/KViewer/panelviewer.cpp
new file mode 100644
index 0000000..f39d075
--- /dev/null
+++ b/krusader/KViewer/panelviewer.cpp
@@ -0,0 +1,307 @@
+#include <kurl.h>
+#include <qstring.h>
+#include <qwidgetstack.h>
+#include <qapplication.h>
+#include <kparts/part.h>
+#include <kparts/browserextension.h>
+#include <kmessagebox.h>
+#include <qdict.h>
+#include <qlabel.h>
+#include <kmimetype.h>
+#include <ktempfile.h>
+#include <klocale.h>
+#include <klibloader.h>
+#include <kuserprofile.h>
+#include <kdebug.h>
+#include <kfileitem.h>
+#include <kio/netaccess.h>
+#include <qfile.h>
+#include <klargefile.h>
+#include "panelviewer.h"
+
+#define DICTSIZE 211
+
+/* ----==={ PanelViewerBase }===---- */
+
+PanelViewerBase::PanelViewerBase( QWidget *parent ) :
+QWidgetStack( parent ), mimes( 0 ), cpart( 0 ) {
+ setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Ignored ) );
+
+ mimes = new QDict<KParts::ReadOnlyPart>( DICTSIZE, false );
+ mimes->setAutoDelete( true );
+ cpart = 0;
+ fallback = new QLabel( i18n( "No file selected or selected file can't be displayed." ), this );
+ fallback->setAlignment( AlignCenter | ExpandTabs | WordBreak );
+ addWidget( fallback );
+ raiseWidget( fallback );
+}
+
+PanelViewerBase::~PanelViewerBase() {
+// cpart->queryClose();
+ closeURL();
+ mimes->clear();
+ delete mimes;
+ delete fallback;
+}
+
+/* ----==={ PanelViewer }===---- */
+
+PanelViewer::PanelViewer( QWidget *parent ) :
+PanelViewerBase( parent ) {
+}
+
+PanelViewer::~PanelViewer() {
+}
+
+KParts::ReadOnlyPart* PanelViewer::openURL( const KURL &url, KrViewer::Mode mode ) {
+ emit urlChanged( this, url );
+ closeURL();
+ curl = url;
+
+ if( mode == KrViewer::Generic ){
+ cmimetype = KMimeType::findByURL( curl ) ->name();
+ cpart = ( *mimes ) [ cmimetype ];
+ if ( !cpart ){
+ cpart = getPart( cmimetype );
+ mimes->insert( cmimetype, cpart );
+ }
+ }
+
+ KTempFile tmpFile;
+
+ if( mode == KrViewer::Hex ){
+ if ( !cpart ) cpart = getHexPart();
+ if ( !cpart ) oldHexViewer(tmpFile);
+ }
+
+ if ( !cpart ) cpart = getPart( "text/plain" );
+ if ( !cpart ) cpart = getPart( "all/allfiles" );
+
+ if ( cpart ) {
+ addWidget( cpart->widget() );
+ raiseWidget( cpart->widget() );
+ }
+ if ( cpart && cpart->openURL( curl ) ){
+ curl = url; /* needed because of the oldHexViewer */
+ return cpart;
+ }
+ else {
+ raiseWidget( fallback );
+ return 0;
+ }
+}
+
+bool PanelViewer::closeURL() {
+ raiseWidget( fallback );
+ if ( cpart && cpart->closeURL() ) {
+ cpart = 0;
+ return true;
+ }
+ return false;
+}
+
+KParts::ReadOnlyPart* PanelViewer::getPart( QString mimetype ) {
+ KParts::ReadOnlyPart * part = 0L;
+ KLibFactory *factory = 0;
+ KService::Ptr ptr = KServiceTypeProfile::preferredService( mimetype, "KParts/ReadOnlyPart" );
+ if ( ptr ) {
+ QStringList args;
+ QVariant argsProp = ptr->property( "X-KDE-BrowserView-Args" );
+ if ( argsProp.isValid() ) {
+ QString argStr = argsProp.toString();
+ args = QStringList::split( " ", argStr );
+ }
+ QVariant prop = ptr->property( "X-KDE-BrowserView-AllowAsDefault" );
+ if ( !prop.isValid() || prop.toBool() ) // defaults to true
+ {
+ factory = KLibLoader::self() ->factory( ptr->library().latin1() );
+ if ( factory ) {
+ part = static_cast<KParts::ReadOnlyPart *>( factory->create( this,
+ ptr->name().latin1(), QString( "KParts::ReadOnlyPart" ).latin1(), args ) );
+ }
+ }
+ }
+ if ( part ) {
+ KParts::BrowserExtension * ext = KParts::BrowserExtension::childObject( part );
+ if ( ext ) {
+ connect( ext, SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ), this, SLOT( openURL( const KURL & ) ) );
+ connect( ext, SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ), this, SIGNAL( openURLRequest( const KURL & ) ) );
+ }
+ }
+ return part;
+}
+
+KParts::ReadOnlyPart* PanelViewer::getHexPart(){
+ KParts::ReadOnlyPart * part = 0L;
+
+ KLibFactory * factory = KLibLoader::self() ->factory( "libkhexedit2part" );
+ if ( factory ) {
+ // Create the part
+ part = ( KParts::ReadOnlyPart * ) factory->create( this, "hexedit2part","KParts::ReadOnlyPart" );
+ }
+
+ return part;
+}
+
+void PanelViewer::oldHexViewer(KTempFile& tmpFile) {
+ QString file;
+ // files that are not local must first be downloaded
+ if ( !curl.isLocalFile() ) {
+ if ( !KIO::NetAccess::download( curl, file,this ) ) {
+ KMessageBox::sorry( this, i18n( "KrViewer is unable to download: " ) + curl.url() );
+ return ;
+ }
+ } else file = curl.path();
+
+
+ // create a hex file
+ QFile f_in( file );
+ f_in.open( IO_ReadOnly );
+ QDataStream in( &f_in );
+
+ FILE *out = KDE_fopen( tmpFile.name().local8Bit(), "w" );
+
+ KIO::filesize_t fileSize = f_in.size();
+ KIO::filesize_t address = 0;
+ char buf[ 16 ];
+ unsigned int* pBuff = ( unsigned int* ) buf;
+
+ while ( address < fileSize ) {
+ memset( buf, 0, 16 );
+ int bufSize = ( ( fileSize - address ) > 16 ) ? 16 : ( fileSize - address );
+ in.readRawBytes( buf, bufSize );
+ fprintf( out, "0x%8.8llx: ", address );
+ for ( int i = 0; i < 4; ++i ) {
+ if ( i < ( bufSize / 4 ) ) fprintf( out, "%8.8x ", pBuff[ i ] );
+ else fprintf( out, " " );
+ }
+ fprintf( out, "| " );
+
+ for ( int i = 0; i < bufSize; ++i ) {
+ if ( buf[ i ] > ' ' && buf[ i ] < '~' ) fputc( buf[ i ], out );
+ else fputc( '.', out );
+ }
+ fputc( '\n', out );
+
+ address += 16;
+ }
+ // clean up
+ f_in.close();
+ fclose( out );
+ if ( !curl.isLocalFile() )
+ KIO::NetAccess::removeTempFile( file );
+
+ curl = tmpFile.name();
+}
+
+/* ----==={ PanelEditor }===---- */
+
+PanelEditor::PanelEditor( QWidget *parent ) :
+PanelViewerBase( parent ) {
+}
+
+PanelEditor::~PanelEditor() {
+}
+
+KParts::ReadOnlyPart* PanelEditor::openURL( const KURL &url, KrViewer::Mode mode ) {
+ emit urlChanged( this, url );
+ closeURL();
+ curl = url;
+
+ if( mode == KrViewer::Generic ){
+ cmimetype = KMimeType::findByURL( curl ) ->name();
+ cpart = ( *mimes ) [ cmimetype ];
+ if ( !cpart ){
+ cpart = getPart( cmimetype );
+ mimes->insert( cmimetype, cpart );
+ }
+ }
+
+ if ( !cpart ) cpart = getPart( "text/plain" );
+ if ( !cpart ) cpart = getPart( "all/allfiles" );
+
+ if ( cpart ) {
+ addWidget( cpart->widget() );
+ raiseWidget( cpart->widget() );
+ }
+ else {
+ raiseWidget( fallback );
+ return 0;
+ }
+
+ bool create = true;
+ KIO::StatJob* statJob = KIO::stat( url, false );
+ connect( statJob, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotStatResult( KIO::Job* ) ) );
+ busy = true;
+ while ( busy ) qApp->processEvents();
+ if( !entry.isEmpty() ) {
+ KFileItem file( entry, url );
+ if( file.isReadable() ) create = false;
+ }
+
+ if( create ){
+ if( static_cast<KParts::ReadWritePart *>(cpart)->saveAs( curl ) ) return cpart;
+ }
+ else {
+ if ( cpart->openURL( curl ) ) return cpart;
+ }
+ return 0;
+}
+
+bool PanelEditor::queryClose() {
+ if ( !cpart ) return true;
+ return static_cast<KParts::ReadWritePart *>(cpart)->queryClose();
+}
+
+bool PanelEditor::closeURL() {
+ if ( !cpart ) return false;
+
+ static_cast<KParts::ReadWritePart *>(cpart)->closeURL( false );
+
+ raiseWidget( fallback );
+ cpart = 0;
+ return true;
+}
+
+KParts::ReadWritePart* PanelEditor::getPart( QString mimetype ) {
+ KParts::ReadWritePart * part = 0L;
+ KLibFactory *factory = 0;
+ KService::Ptr ptr = KServiceTypeProfile::preferredService( mimetype, "KParts/ReadWritePart" );
+ if ( ptr ) {
+ QStringList args;
+ QVariant argsProp = ptr->property( "X-KDE-BrowserView-Args" );
+ if ( argsProp.isValid() ) {
+ QString argStr = argsProp.toString();
+ args = QStringList::split( " ", argStr );
+ }
+ QVariant prop = ptr->property( "X-KDE-BrowserView-AllowAsDefault" );
+ if ( !prop.isValid() || prop.toBool() ) // defaults to true
+ {
+ factory = KLibLoader::self() ->factory( ptr->library().latin1() );
+ if ( factory ) {
+ part = static_cast<KParts::ReadWritePart *>( factory->create( this,
+ ptr->name().latin1(), QString( "KParts::ReadWritePart" ).latin1(), args ) );
+ }
+ }
+ }
+ if ( part ) {
+ KParts::BrowserExtension * ext = KParts::BrowserExtension::childObject( part );
+ if ( ext ) {
+ connect( ext, SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ), this, SLOT( openURL( const KURL & ) ) );
+ connect( ext, SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ), this, SIGNAL( openURLRequest( const KURL & ) ) );
+ }
+ }
+ return part;
+}
+
+void PanelEditor::slotStatResult( KIO::Job* job ) {
+ if( !job || job->error() ) entry = KIO::UDSEntry();
+ else entry = static_cast<KIO::StatJob*>(job)->statResult();
+ busy = false;
+}
+
+bool PanelEditor::isModified(){
+ return static_cast<KParts::ReadWritePart *>(cpart)->isModified();
+}
+
+#include "panelviewer.moc"
diff --git a/krusader/KViewer/panelviewer.h b/krusader/KViewer/panelviewer.h
new file mode 100644
index 0000000..dfc72bd
--- /dev/null
+++ b/krusader/KViewer/panelviewer.h
@@ -0,0 +1,88 @@
+#ifndef _SUPERVIEW_H
+#define _SUPERVIEW_H
+
+#include <kurl.h>
+#include <qstring.h>
+#include <qwidgetstack.h>
+#include <kparts/part.h>
+#include <kio/job.h>
+#include <ktempfile.h>
+#include <qdict.h>
+#include <qlabel.h>
+
+#include "krviewer.h"
+
+
+class PanelViewerBase: public QWidgetStack {
+ Q_OBJECT
+
+public:
+ PanelViewerBase( QWidget *parent = 0 );
+ virtual ~PanelViewerBase();
+ inline KURL url() const { return curl; }
+ inline void setUrl( KURL url ) { emit urlChanged( this, url ); curl = url; }
+ inline KParts::ReadOnlyPart* part() const { return cpart; }
+ virtual bool isModified() { return false; }
+ virtual bool isEditor() = 0;
+
+public slots:
+ virtual KParts::ReadOnlyPart* openURL( const KURL&, KrViewer::Mode=KrViewer::Generic ){ return 0;}
+ virtual bool closeURL(){ return false; }
+ virtual bool queryClose() { return true; }
+
+signals:
+ void openURLRequest( const KURL &url );
+ void urlChanged( PanelViewerBase *, const KURL & );
+
+protected:
+ QDict<KParts::ReadOnlyPart> *mimes;
+ KParts::ReadOnlyPart *cpart;
+
+ QString cmimetype;
+ KURL curl;
+ QLabel *fallback;
+
+};
+
+class PanelViewer: public PanelViewerBase {
+ Q_OBJECT
+public slots:
+ KParts::ReadOnlyPart* openURL( const KURL &url, KrViewer::Mode mode=KrViewer::Generic );
+ bool closeURL();
+
+public:
+ PanelViewer( QWidget *parent = 0 );
+ ~PanelViewer();
+
+ virtual bool isEditor() { return false; }
+
+protected:
+ KParts::ReadOnlyPart *getPart( QString mimetype );
+ KParts::ReadOnlyPart* getHexPart();
+ void oldHexViewer(KTempFile& tmpFile);
+};
+
+class PanelEditor: public PanelViewerBase {
+ Q_OBJECT
+public:
+ virtual bool isModified();
+ virtual bool isEditor() { return true; }
+
+public slots:
+ KParts::ReadOnlyPart* openURL( const KURL &url, KrViewer::Mode mode=KrViewer::Generic );
+ bool closeURL();
+ bool queryClose();
+ void slotStatResult( KIO::Job* job );
+
+public:
+ PanelEditor( QWidget *parent = 0 );
+ ~PanelEditor();
+
+protected:
+ KParts::ReadWritePart* getPart( QString mimetype );
+
+ bool busy;
+ KIO::UDSEntry entry;
+};
+
+#endif
diff --git a/krusader/Konfigurator/Makefile.am b/krusader/Konfigurator/Makefile.am
new file mode 100644
index 0000000..8bb4372
--- /dev/null
+++ b/krusader/Konfigurator/Makefile.am
@@ -0,0 +1,23 @@
+noinst_LIBRARIES = libKonfigurator.a
+
+INCLUDES = -I$(top_builddir)/krusader/GUI $(all_includes)
+
+libKonfigurator_a_METASOURCES = AUTO
+
+libKonfigurator_a_SOURCES = \
+ kgcolors.cpp \
+ kgdependencies.cpp \
+ konfiguratorpage.cpp \
+ konfiguratoritems.cpp \
+ konfigurator.cpp \
+ kgwelcome.cpp \
+ kgstartup.cpp \
+ kglookfeel.cpp \
+ kggeneral.cpp \
+ kgarchives.cpp \
+ kgadvanced.cpp \
+ kguseractions.cpp \
+ kgprotocols.cpp \
+ krresulttable.cpp \
+ krresulttabledialog.cpp \
+ searchobject.cpp
diff --git a/krusader/Konfigurator/kgadvanced.cpp b/krusader/Konfigurator/kgadvanced.cpp
new file mode 100644
index 0000000..7806ab8
--- /dev/null
+++ b/krusader/Konfigurator/kgadvanced.cpp
@@ -0,0 +1,133 @@
+/***************************************************************************
+ kgadvanced.cpp - description
+ -------------------
+ copyright : (C) 2004 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "kgadvanced.h"
+#include "../defaults.h"
+#include <klocale.h>
+#include <qhbox.h>
+#include <qwhatsthis.h>
+#include <sys/param.h>
+#include <kdeversion.h>
+#include <kprotocolinfo.h>
+
+KgAdvanced::KgAdvanced( bool first, QWidget* parent, const char* name ) :
+ KonfiguratorPage( first, parent, name )
+{
+ QGridLayout *kgAdvancedLayout = new QGridLayout( parent );
+ kgAdvancedLayout->setSpacing( 6 );
+
+ // -------------------------- GENERAL GROUPBOX ----------------------------------
+
+ QGroupBox *generalGrp = createFrame( i18n( "General" ), parent, "kgAdvGeneralGrp" );
+ QGridLayout *generalGrid = createGridLayout( generalGrp->layout() );
+
+#if KDE_IS_VERSION( 3,5,1 )
+ bool dontUseMedia = false;
+#else
+ bool dontUseMedia = true;
+#endif
+
+ bool isMediaProtocolPresent = KProtocolInfo::isKnownProtocol( QString( "media" ) );
+ if( !isMediaProtocolPresent )
+ dontUseMedia = true;
+
+ KONFIGURATOR_CHECKBOX_PARAM generalSettings[] =
+ // cfg_class cfg_name default text restart tooltip
+ {{"Advanced","PreserveAttributes", _PreserveAttributes, i18n( "Preserve attributes for local copy/move (slower)" ), false, i18n( "Krusader will try to preserve all attributes (time, owner, group) of the local files according to the source depending on your permissions:<ul><li>User preserving if you are root</li><li>Group preserving if you are root or member of the group</li><li>Preserving the timestamp</li></ul><b>Note</b>: This can slow down the copy process." ) },
+ {"Advanced","AutoMount", _AutoMount, i18n( "Automount filesystems" ), false, i18n( "When stepping into a directory which is defined as a mount point in the <b>fstab</b>, try mounting it with the defined parameters." )},
+ {"Advanced","DontUseMediaProt", dontUseMedia, i18n( "Don't use KDE's media protocol for media button (if it's buggy or missing)" ), false, i18n( "Select if your media protocol is buggy (in some older KDE versions), or not present (no kdebase package installed)." )}};
+
+ KonfiguratorCheckBoxGroup *generals = createCheckBoxGroup( 1, 0, generalSettings, 3, generalGrp );
+
+ if( !isMediaProtocolPresent )
+ generals->find( "DontUseMediaProt" )->setEnabled( false );
+
+ generalGrid->addWidget( generals, 1, 0 );
+
+ addLabel( generalGrid, 2, 0, i18n( "MountMan won't (un)mount the following mount-points:" ),
+ generalGrp, "KgAdvLabel2" );
+ KonfiguratorEditBox *nonMountPoints = createEditBox( "Advanced", "Nonmount Points", _NonMountPoints, generalGrp, false );
+ generalGrid->addWidget( nonMountPoints, 2, 1 );
+
+
+#ifdef BSD
+ generals->find( "AutoMount" )->setEnabled( false ); /* disable AutoMount on BSD */
+#endif
+
+ kgAdvancedLayout->addWidget( generalGrp, 0 ,0 );
+
+ // ----------------------- CONFIRMATIONS GROUPBOX -------------------------------
+
+ QGroupBox *confirmGrp = createFrame( i18n( "Confirmations" ), parent, "confirmGrp" );
+ QGridLayout *confirmGrid = createGridLayout( confirmGrp->layout() );
+
+ addLabel( confirmGrid, 0, 0, "\n"+i18n( "Request user confirmation for the following operations:" )+"\n",
+ confirmGrp, "KgAdvLabel1" );
+
+ KONFIGURATOR_CHECKBOX_PARAM confirmations[] =
+ // cfg_class cfg_name default text restart ToolTip
+ {{"Advanced","Confirm Unempty Dir", _ConfirmUnemptyDir, i18n( "Deleting non-empty directories" ), false, ""},
+ {"Advanced","Confirm Delete", _ConfirmDelete, i18n( "Deleting files" ), false, ""},
+ {"Advanced","Confirm Copy", _ConfirmCopy, i18n( "Copying files" ), false, ""},
+ {"Advanced","Confirm Move", _ConfirmMove, i18n( "Moving files" ), false, ""},
+ {"Advanced","Confirm Feed to Listbox", _ConfirmFeedToListbox, i18n( "Confirm feed to listbox" ), false, i18n("Ask for a result name when feeding items to the listbox. By default the standard value is used.")},
+ {"Notification Messages","Confirm Remove UserAction", true, i18n( "Removing Useractions" ), false, ""}};
+
+ KonfiguratorCheckBoxGroup *confWnd = createCheckBoxGroup( 2, 0, confirmations, 6, confirmGrp );
+
+ confirmGrid->addWidget( confWnd, 1, 0 );
+
+ kgAdvancedLayout->addWidget( confirmGrp, 1 ,0 );
+
+
+ // ------------------------ FINE-TUNING GROUPBOX --------------------------------
+
+ QGroupBox *fineTuneGrp = createFrame( i18n( "Fine-Tuning" ), parent, "kgFineTuneGrp" );
+ QGridLayout *fineTuneGrid = createGridLayout( fineTuneGrp->layout() );
+ fineTuneGrid->setAlignment( Qt::AlignLeft | Qt::AlignTop );
+
+ QLabel *label = new QLabel( i18n( "Icon cache size (KB):" ), fineTuneGrp, "iconCacheLabel" );
+ QWhatsThis::add( label, i18n( "The icon cache size influences how fast the contents of a panel can be displayed. However, too large a cache might consume your memory." ) );
+ fineTuneGrid->addWidget( label, 0, 0 );
+ KonfiguratorSpinBox *spinBox = createSpinBox( "Advanced", "Icon Cache Size", _IconCacheSize,
+ 1, 8192, fineTuneGrp, false );
+ QWhatsThis::add( spinBox, i18n( "The icon cache size influences how fast the contents of a panel can be displayed. However, too large a cache might consume your memory." ) );
+ spinBox->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed);
+ fineTuneGrid->addWidget( spinBox, 0, 1 );
+
+ addLabel( fineTuneGrid, 1, 0, i18n( "Arguments of updatedb:" ),
+ fineTuneGrp, "KgAdvLabel1" );
+ KonfiguratorEditBox *updatedbArgs = createEditBox( "Locate", "UpdateDB Arguments", "", fineTuneGrp, false );
+ fineTuneGrid->addWidget( updatedbArgs, 1, 1 );
+
+ kgAdvancedLayout->addWidget( fineTuneGrp, 2 ,0 );
+}
+
+#include "kgadvanced.moc"
diff --git a/krusader/Konfigurator/kgadvanced.h b/krusader/Konfigurator/kgadvanced.h
new file mode 100644
index 0000000..a539a01
--- /dev/null
+++ b/krusader/Konfigurator/kgadvanced.h
@@ -0,0 +1,44 @@
+/***************************************************************************
+ kgadvanced.h - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __KGADVANCED_H__
+#define __KGADVANCED_H__
+
+#include "konfiguratorpage.h"
+
+class KgAdvanced : public KonfiguratorPage
+{
+ Q_OBJECT
+
+public:
+ KgAdvanced( bool first, QWidget* parent=0, const char* name=0 );
+};
+
+#endif /* __KGADVANCED_H__ */
diff --git a/krusader/Konfigurator/kgarchives.cpp b/krusader/Konfigurator/kgarchives.cpp
new file mode 100644
index 0000000..cd2f315
--- /dev/null
+++ b/krusader/Konfigurator/kgarchives.cpp
@@ -0,0 +1,155 @@
+/***************************************************************************
+ kgarchives.cpp - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <qhbox.h>
+#include <qpushbutton.h>
+
+#include "kgarchives.h"
+#include "krresulttable.h"
+#include "krresulttabledialog.h"
+
+#include "searchobject.h"
+#include "../defaults.h"
+#include "../krusader.h"
+#include "../VFS/krarchandler.h"
+
+KgArchives::KgArchives( bool first, QWidget* parent, const char* name ) :
+ KonfiguratorPage( first, parent, name )
+{
+ QGridLayout *kgArchivesLayout = new QGridLayout( parent );
+ kgArchivesLayout->setSpacing( 6 );
+
+ // -------------------------- GENERAL GROUPBOX ----------------------------------
+
+ QGroupBox *generalGrp = createFrame( i18n( "General" ), parent, "generalGrp" );
+ QGridLayout *generalGrid = createGridLayout( generalGrp->layout() );
+
+ addLabel( generalGrid, 0, 0, i18n( "Krusader transparently handles the following types of archives:" ),
+ generalGrp, "KgLabel1" );
+
+ KONFIGURATOR_CHECKBOX_PARAM packers[] =
+ // cfg_class cfg_name default text restart tooltip
+ {{"Archives","Do Tar", _DoTar, i18n( "Tar" ), false, ""},
+ {"Archives","Do GZip", _DoGZip, i18n( "GZip" ), false, ""},
+ {"Archives","Do BZip2", _DoBZip2, i18n( "BZip2" ), false, ""},
+ {"Archives","Do UnZip", _DoUnZip, i18n( "Zip" ), false, ""},
+ {"Archives","Do UnRar", _DoUnRar, i18n( "Rar" ), false, ""},
+ {"Archives","Do Unarj", _DoArj, i18n( "Arj" ), false, ""},
+ {"Archives","Do RPM", _DoRPM, i18n( "Rpm" ), false, ""},
+ {"Archives","Do UnAce", _DoUnAce, i18n( "Ace" ), false, ""},
+ {"Archives","Do Lha", _DoLha, i18n( "Lha" ), false, ""},
+ {"Archives","Do DEB", _DoDEB, i18n( "Deb" ), false, ""},
+ {"Archives","Do 7z", _Do7z, i18n( "7zip" ), false, ""}
+ };
+
+ cbs = createCheckBoxGroup( 3, 0, packers, 11, generalGrp );
+ generalGrid->addWidget( cbs, 1, 0 );
+
+ addLabel( generalGrid, 2, 0, i18n( "The archives that are \"greyed-out\" were unavailable on your\nsystem last time Krusader checked. If you wish Krusader to\nsearch again, click the 'Auto Configure' button." ),
+ generalGrp, "KgLabel2" );
+
+ QHBox *hbox = new QHBox( generalGrp );
+ createSpacer( hbox, "spacer1" );
+ QPushButton *btnAutoConfigure = new QPushButton( i18n( "Auto Configure" ), hbox, "kgAutoConfigure" );
+ createSpacer( hbox, "spacer2" );
+ generalGrid->addWidget( hbox, 3, 0 );
+ connect( btnAutoConfigure, SIGNAL( clicked() ), this, SLOT( slotAutoConfigure() ) );
+
+ kgArchivesLayout->addWidget( generalGrp, 0 ,0 );
+
+ // ------------------------ FINE-TUNING GROUPBOX --------------------------------
+
+ QGroupBox *fineTuneGrp = createFrame( i18n( "Fine-Tuning" ), parent, "fineTuneGrp" );
+ QGridLayout *fineTuneGrid = createGridLayout( fineTuneGrp->layout() );
+
+ KONFIGURATOR_CHECKBOX_PARAM finetuners[] =
+ // cfg_class cfg_name default text restart ToolTip
+ {//{"Archives","Allow Move Into Archive", _MoveIntoArchive, i18n( "Allow moving into archives" ), false, i18n( "This action can be tricky, since system failure during the process\nmight result in misplaced files. If this happens,\nthe files are stored in a temp directory inside /tmp." )},
+ {"Archives","Test Archives", _TestArchives, i18n( "Test archive after packing" ), false, i18n( "Check the archive's integrity after packing it." )},
+ {"Archives","Test Before Unpack", _TestBeforeUnpack,i18n( "Test archive before unpacking" ), false, i18n( "Some corrupted archives might cause a crash; therefore, testing is suggested." )}};
+
+ KonfiguratorCheckBoxGroup *finetunes = createCheckBoxGroup( 1, 0, finetuners, 2, fineTuneGrp );
+
+ disableNonExistingPackers();
+ fineTuneGrid->addWidget( finetunes, 1, 0 );
+
+ kgArchivesLayout->addWidget( fineTuneGrp, 1 ,0 );
+
+ if( first )
+ slotAutoConfigure();
+
+}
+
+
+void KgArchives::slotAutoConfigure()
+{
+ KrResultTableDialog* dia = new KrResultTableDialog(this, KrResultTableDialog::Archiver, i18n("Search results"), i18n("Searching for packers..."),
+ "package", i18n("Make sure to install new packers in your <code>$PATH</code> (e.g. /usr/bin)"));
+ dia->exec();
+
+ disableNonExistingPackers();
+}
+
+void KgArchives::disableNonExistingPackers()
+{
+ #define PS(x) lst.contains(x)>0
+
+ QStringList lst=KRarcHandler::supportedPackers(); // get list of availble packers
+ cbs->find( "Do Tar" )->setEnabled(PS("tar"));
+ cbs->find( "Do GZip" )->setEnabled(PS("gzip"));
+ cbs->find( "Do BZip2" )->setEnabled(PS("bzip2"));
+ cbs->find( "Do UnZip" )->setEnabled(PS("unzip"));
+ cbs->find( "Do Lha" )->setEnabled(PS("lha"));
+ cbs->find( "Do RPM" )->setEnabled(PS("rpm") || PS("cpio"));
+ cbs->find( "Do UnRar" )->setEnabled(PS("unrar") || PS("rar") );
+ cbs->find( "Do UnAce" )->setEnabled(PS("unace"));
+ cbs->find( "Do Unarj" )->setEnabled(PS("unarj") || PS("arj") );
+ cbs->find( "Do DEB" )->setEnabled(PS("dpkg") && PS("tar") );
+ cbs->find( "Do 7z" )->setEnabled( PS("7z") );
+
+ krConfig->setGroup( "Archives" );
+ krConfig->writeEntry( "Supported Packers", lst );
+}
+
+bool KgArchives::apply()
+{
+ krConfig->setGroup( "Archives" );
+ krConfig->writeEntry("Supported Packers",KRarcHandler::supportedPackers());
+ return KonfiguratorPage::apply();
+}
+
+void KgArchives::setDefaults()
+{
+ krConfig->setGroup( "Archives" );
+ krConfig->writeEntry("Supported Packers",KRarcHandler::supportedPackers());
+ return KonfiguratorPage::setDefaults();
+}
+
+#include "kgarchives.moc"
diff --git a/krusader/Konfigurator/kgarchives.h b/krusader/Konfigurator/kgarchives.h
new file mode 100644
index 0000000..a3656d4
--- /dev/null
+++ b/krusader/Konfigurator/kgarchives.h
@@ -0,0 +1,54 @@
+/***************************************************************************
+ kgarchives.h - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __KGARCHIVES_H__
+#define __KGARCHIVES_H__
+
+#include "konfiguratorpage.h"
+
+class KgArchives : public KonfiguratorPage
+{
+ Q_OBJECT
+
+public:
+ KgArchives( bool first, QWidget* parent=0, const char* name=0 );
+ virtual bool apply();
+ virtual void setDefaults();
+
+public slots:
+ void slotAutoConfigure();
+
+protected:
+ KonfiguratorCheckBoxGroup *cbs;
+
+ void disableNonExistingPackers();
+};
+
+#endif /* __KGARCHIVES_H__ */
diff --git a/krusader/Konfigurator/kgcolors.cpp b/krusader/Konfigurator/kgcolors.cpp
new file mode 100644
index 0000000..461792e
--- /dev/null
+++ b/krusader/Konfigurator/kgcolors.cpp
@@ -0,0 +1,633 @@
+/***************************************************************************
+ kgcolors.cpp - description
+ -------------------
+ copyright : (C) 2004 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "kgcolors.h"
+#include "../defaults.h"
+#include "../Panel/krcolorcache.h"
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kfiledialog.h>
+#include <kglobalsettings.h>
+#include <kstandarddirs.h>
+#include <qhbox.h>
+#include <qheader.h>
+#include <qtabwidget.h>
+
+KgColors::KgColors( bool first, QWidget* parent, const char* name ) :
+ KonfiguratorPage( first, parent, name ), offset( 0 )
+{
+ QGridLayout *kgColorsLayout = new QGridLayout( parent );
+ kgColorsLayout->setSpacing( 6 );
+
+ // -------------------------- GENERAL GROUPBOX ----------------------------------
+
+ QGroupBox *generalGrp = createFrame( i18n( "General" ), parent, "kgColorsGeneralGrp" );
+ QGridLayout *generalGrid = createGridLayout( generalGrp->layout() );
+
+ generalGrid->setSpacing( 0 );
+ generalGrid->setMargin( 5 );
+
+ KONFIGURATOR_CHECKBOX_PARAM generalSettings[] =
+ // cfg_class cfg_name default text restart tooltip
+ {{"Colors","KDE Default", _KDEDefaultColors, i18n( "Use the default KDE colors" ), false, "<p><img src='toolbar|kcontrol'></p>" + i18n( "<p>Use KDE's global color configuration.</p><p><i>KDE Control Center -> Appearance & Themes -> Colors</i></p>") },
+ {"Colors","Enable Alternate Background", _AlternateBackground, i18n( "Use alternate background color" ), false, i18n( "<p>The <b>background color</b> and the <b>alternate background</b> color alternates line by line.</p><p>When you don't use the <i>KDE default colors</i>, you can configure the alternate colors in the <i>colors</i> box.</p>") },
+ {"Colors","Show Current Item Always", _ShowCurrentItemAlways, i18n( "Show current item even if not focused" ), false, i18n( "<p>Shows the last cursor position in the non active list panel.</p><p>This option is only available when you don't use the <i>KDE default colors</i>.</p>" ) },
+ {"Colors","Dim Inactive Colors", _DimInactiveColors, i18n( "Dim the colors of the inactive panel" ), false, i18n( "<p>The colors of the inactive panel are calculated by a dim color and a dim factor.</p>" ) }};
+
+ generals = createCheckBoxGroup( 0, 2, generalSettings, sizeof(generalSettings)/sizeof(generalSettings[0]), generalGrp );
+ generalGrid->addWidget( generals, 1, 0 );
+
+ generals->layout()->setSpacing( 5 );
+
+ connect( generals->find( "KDE Default" ), SIGNAL( stateChanged( int ) ), this, SLOT( slotDisable() ) );
+ connect( generals->find( "Enable Alternate Background" ), SIGNAL( stateChanged( int ) ), this, SLOT( generatePreview() ) );
+ connect( generals->find( "Show Current Item Always" ), SIGNAL( stateChanged( int ) ), this, SLOT( slotDisable() ) );
+ connect( generals->find( "Dim Inactive Colors" ), SIGNAL( stateChanged( int ) ), this, SLOT( slotDisable() ) );
+
+ kgColorsLayout->addMultiCellWidget( generalGrp, 0 ,0, 0, 2 );
+ QHBox *hbox = new QHBox( parent );
+
+ // -------------------------- COLORS GROUPBOX ----------------------------------
+
+ QGroupBox *colorsFrameGrp = createFrame( i18n( "Colors" ), hbox, "kgColorsColorsGrp" );
+ QGridLayout *colorsFrameGrid = createGridLayout( colorsFrameGrp->layout() );
+ colorsFrameGrid->setSpacing( 0 );
+ colorsFrameGrid->setMargin( 3 );
+
+ colorTabWidget = new QTabWidget( colorsFrameGrp, "colorTabWidget" );
+
+ connect( colorTabWidget, SIGNAL( currentChanged ( QWidget * ) ), this, SLOT( generatePreview() ) );
+
+ colorsGrp = new QWidget( colorTabWidget, "colorTab" );
+ colorTabWidget->insertTab( colorsGrp, i18n( "Active" ) );
+
+ colorsGrid = new QGridLayout( colorsGrp );
+ colorsGrid->setSpacing( 0 );
+ colorsGrid->setMargin( 2 );
+
+ ADDITIONAL_COLOR transparent = { i18n("Transparent"), Qt::white, "transparent" };
+
+ addColorSelector( "Foreground", i18n( "Foreground:" ), KGlobalSettings::textColor() );
+ addColorSelector( "Directory Foreground", i18n( "Directory foreground:" ), getColorSelector( "Foreground" )->getColor(), i18n( "Same as foreground" ) );
+ addColorSelector( "Executable Foreground", i18n( "Executable foreground:" ), getColorSelector( "Foreground" )->getColor(), i18n( "Same as foreground" ) );
+ addColorSelector( "Symlink Foreground", i18n( "Symbolic link foreground:" ), getColorSelector( "Foreground" )->getColor(), i18n( "Same as foreground" ) );
+ addColorSelector( "Invalid Symlink Foreground", i18n( "Invalid symlink foreground:" ), getColorSelector( "Foreground" )->getColor(), i18n( "Same as foreground" ) );
+ addColorSelector( "Background", i18n( "Background:" ), KGlobalSettings::baseColor() );
+ ADDITIONAL_COLOR sameAsBckgnd = { i18n("Same as background"), getColorSelector( "Background" )->getColor(), "Background" };
+ addColorSelector( "Alternate Background", i18n( "Alternate background:" ), KGlobalSettings::alternateBackgroundColor(),"", &sameAsBckgnd, 1 );
+ addColorSelector( "Marked Foreground", i18n( "Selected foreground:" ), KGlobalSettings::highlightedTextColor(), "", &transparent, 1 );
+ addColorSelector( "Marked Background", i18n( "Selected background:" ), KGlobalSettings::highlightColor(), "", &sameAsBckgnd, 1 );
+ ADDITIONAL_COLOR sameAsAltern = { i18n("Same as alt. background"), getColorSelector( "Alternate Background" )->getColor(), "Alternate Background" };
+ addColorSelector( "Alternate Marked Background",i18n( "Alternate selected background:" ), getColorSelector( "Marked Background" )->getColor(), i18n( "Same as selected background" ), &sameAsAltern, 1 );
+ addColorSelector( "Current Foreground", i18n( "Current foreground:" ), Qt::white, i18n( "Not used" ) );
+ ADDITIONAL_COLOR sameAsMarkedForegnd = { i18n("Same as selected foreground"), getColorSelector( "Marked Foreground" )->getColor(), "Marked Foreground" };
+ addColorSelector( "Marked Current Foreground", i18n( "Selected current foreground:" ), Qt::white, i18n( "Not used" ), &sameAsMarkedForegnd, 1);
+ addColorSelector( "Current Background", i18n( "Current background:" ), Qt::white, i18n( "Not used" ), &sameAsBckgnd, 1 );
+
+ colorsGrid->addWidget(createSpacer(colorsGrp, ""), itemList.count() - offset, 1);
+
+ connect( getColorSelector( "Foreground" ), SIGNAL( colorChanged() ), this, SLOT( slotForegroundChanged() ) );
+ connect( getColorSelector( "Background" ), SIGNAL( colorChanged() ), this, SLOT( slotBackgroundChanged() ) );
+ connect( getColorSelector( "Alternate Background" ), SIGNAL( colorChanged() ), this, SLOT( slotAltBackgroundChanged() ) );
+ connect( getColorSelector( "Marked Background" ), SIGNAL( colorChanged() ), this, SLOT( slotMarkedBackgroundChanged() ) );
+
+ inactiveColorStack = new QWidgetStack( colorTabWidget, "colorTab2" );
+ colorTabWidget->insertTab( inactiveColorStack, i18n( "Inactive" ) );
+
+ colorsGrp = normalInactiveWidget = new QWidget( inactiveColorStack, "colorTab2" );
+
+ colorsGrid = new QGridLayout( normalInactiveWidget );
+ colorsGrid->setSpacing( 0 );
+ colorsGrid->setMargin( 2 );
+
+ offset = endOfActiveColors = itemList.count();
+
+ addColorSelector( "Inactive Foreground", i18n( "Foreground:" ), getColorSelector( "Foreground" )->getColor(), i18n( "Same as active" ) );
+ ADDITIONAL_COLOR sameAsInactForegnd = { i18n("Same as foreground"), getColorSelector( "Inactive Foreground" )->getColor(), "Inactive Foreground" };
+ addColorSelector( "Inactive Directory Foreground", i18n( "Directory foreground:" ), getColorSelector( "Directory Foreground" )->getColor(), i18n( "Same as active" ), &sameAsInactForegnd, 1 );
+ addColorSelector( "Inactive Executable Foreground", i18n( "Executable foreground:" ), getColorSelector( "Executable Foreground" )->getColor(), i18n( "Same as active" ), &sameAsInactForegnd, 1 );
+ addColorSelector( "Inactive Symlink Foreground", i18n( "Symbolic link foreground:" ), getColorSelector( "Symlink Foreground" )->getColor(), i18n( "Same as active" ), &sameAsInactForegnd, 1 );
+ addColorSelector( "Inactive Invalid Symlink Foreground", i18n( "Invalid symlink foreground:" ), getColorSelector( "Invalid Symlink Foreground" )->getColor(), i18n( "Same as active" ), &sameAsInactForegnd, 1 );
+ addColorSelector( "Inactive Background", i18n( "Background:" ), getColorSelector( "Background" )->getColor(), i18n( "Same as active" ) );
+ ADDITIONAL_COLOR sameAsInactBckgnd = { i18n("Same as background"), getColorSelector( "Inactive Background" )->getColor(), "Inactive Background" };
+ addColorSelector( "Inactive Alternate Background", i18n( "Alternate background:" ), getColorSelector( "Alternate Background" )->getColor(), i18n( "Same as active" ), &sameAsInactBckgnd, 1 );
+ addColorSelector( "Inactive Marked Foreground", i18n( "Selected foreground:" ), getColorSelector( "Marked Foreground" )->getColor(), i18n( "Same as active" ), &transparent, 1 );
+ addColorSelector( "Inactive Marked Background", i18n( "Selected background:" ), getColorSelector( "Marked Background" )->getColor(), i18n( "Same as active" ), &sameAsInactBckgnd, 1 );
+ ADDITIONAL_COLOR sameAsInactAltern[] = {{ i18n("Same as alt. background"), getColorSelector( "Inactive Alternate Background" )->getColor(), "Inactive Alternate Background" },
+ { i18n("Same as selected background"), getColorSelector( "Inactive Marked Background" )->getColor(), "Inactive Marked Background" } };
+ addColorSelector( "Inactive Alternate Marked Background", i18n( "Alternate selected background:" ), getColorSelector( "Alternate Marked Background" )->getColor(), i18n( "Same as active" ), sameAsInactAltern, 2 );
+ addColorSelector( "Inactive Current Foreground", i18n( "Current foreground:" ), getColorSelector( "Current Foreground" )->getColor(), i18n( "Same as active" ) );
+ ADDITIONAL_COLOR sameAsInactMarkedForegnd = { i18n("Same as selected foreground"), getColorSelector( "Inactive Marked Foreground" )->getColor(), "Inactive Marked Foreground" };
+ addColorSelector( "Inactive Marked Current Foreground", i18n( "Selected current foreground:" ), getColorSelector( "Marked Current Foreground" )->getColor(), i18n( "Same as active" ), &sameAsInactMarkedForegnd, 1 );
+ addColorSelector( "Inactive Current Background", i18n( "Current background:" ), getColorSelector( "Current Background" )->getColor(), i18n( "Same as active" ), &sameAsInactBckgnd, 1 );
+
+ colorsGrid->addWidget(createSpacer(normalInactiveWidget, ""), itemList.count() - offset, 1);
+
+ connect( getColorSelector( "Inactive Foreground" ), SIGNAL( colorChanged() ), this, SLOT( slotInactiveForegroundChanged() ) );
+ connect( getColorSelector( "Inactive Background" ), SIGNAL( colorChanged() ), this, SLOT( slotInactiveBackgroundChanged() ) );
+ connect( getColorSelector( "Inactive Alternate Background" ), SIGNAL( colorChanged() ), this, SLOT( slotInactiveAltBackgroundChanged() ) );
+ connect( getColorSelector( "Inactive Marked Background" ), SIGNAL( colorChanged() ), this, SLOT( slotInactiveMarkedBackgroundChanged() ) );
+
+ offset = endOfPanelColors = itemList.count();
+
+ inactiveColorStack->addWidget( normalInactiveWidget );
+
+ colorsGrp = dimmedInactiveWidget = new QWidget( inactiveColorStack, "colorTab2dimmed" );
+
+ colorsGrid = new QGridLayout( dimmedInactiveWidget );
+ colorsGrid->setSpacing( 0 );
+ colorsGrid->setMargin( 2 );
+
+ addColorSelector( "Dim Target Color", i18n( "Dim target color:" ), Qt::white);
+
+ int index = itemList.count() - offset;
+ labelList.append( addLabel( colorsGrid, index, 0, i18n("Dim factor:"), colorsGrp, QString( "ColorsLabel%1" ).arg( index ).ascii() ) );
+ dimFactor = createSpinBox("Colors", "Dim Factor", 100, 0, 100, colorsGrp);
+ dimFactor->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
+ connect( dimFactor, SIGNAL( valueChanged( int ) ), this, SLOT( generatePreview() ) );
+ colorsGrid->addWidget( dimFactor, index++, 1 );
+
+ colorsGrid->addWidget(createSpacer(dimmedInactiveWidget, ""), itemList.count() + 1 - offset, 1);
+
+ inactiveColorStack->addWidget( dimmedInactiveWidget );
+
+ inactiveColorStack->raiseWidget( normalInactiveWidget );
+
+ colorsGrp = new QWidget( colorTabWidget, "colorTab3" );
+ colorTabWidget->insertTab( colorsGrp, i18n( "Synchronizer" ) );
+
+ colorsGrid = new QGridLayout( colorsGrp );
+ colorsGrid->setSpacing( 0 );
+ colorsGrid->setMargin( 2 );
+
+ ADDITIONAL_COLOR KDEDefaultBase = { i18n("KDE default"), KGlobalSettings::baseColor(), "KDE default" };
+ ADDITIONAL_COLOR KDEDefaultFore = { i18n("KDE default"), KGlobalSettings::textColor(), "KDE default" };
+
+ offset = endOfPanelColors = itemList.count();
+
+ addColorSelector( "Synchronizer Equals Foreground", i18n( "Equals foreground:" ), Qt::black, QString::null, &KDEDefaultFore, 1 );
+ addColorSelector( "Synchronizer Equals Background", i18n( "Equals background:" ), KGlobalSettings::baseColor(), QString::null, &KDEDefaultBase, 1 );
+ addColorSelector( "Synchronizer Differs Foreground", i18n( "Differing foreground:" ), Qt::red, QString::null, &KDEDefaultFore, 1 );
+ addColorSelector( "Synchronizer Differs Background", i18n( "Differing background:" ), KGlobalSettings::baseColor(), QString::null, &KDEDefaultBase, 1 );
+ addColorSelector( "Synchronizer LeftCopy Foreground", i18n( "Copy to left foreground:" ), Qt::blue, QString::null, &KDEDefaultFore, 1 );
+ addColorSelector( "Synchronizer LeftCopy Background", i18n( "Copy to left background:" ), KGlobalSettings::baseColor(), QString::null, &KDEDefaultBase, 1 );
+ addColorSelector( "Synchronizer RightCopy Foreground", i18n( "Copy to right foreground:" ), Qt::darkGreen, QString::null, &KDEDefaultFore, 1 );
+ addColorSelector( "Synchronizer RightCopy Background", i18n( "Copy to right background:" ), KGlobalSettings::baseColor(), QString::null, &KDEDefaultBase, 1 );
+ addColorSelector( "Synchronizer Delete Foreground", i18n( "Delete foreground:" ), Qt::white, QString::null, &KDEDefaultFore, 1 );
+ addColorSelector( "Synchronizer Delete Background", i18n( "Delete background:" ), Qt::red, QString::null, &KDEDefaultBase, 1 );
+
+ colorsGrid->addWidget(createSpacer(colorsGrp, ""), itemList.count() - offset, 1);
+
+ colorsFrameGrid->addWidget( colorTabWidget, 0, 0 );
+
+ // -------------------------- PREVIEW GROUPBOX ----------------------------------
+
+ previewGrp = createFrame( i18n( "Preview" ), hbox, "kgColorsPreviewGrp" );
+ previewGrid = createGridLayout( previewGrp->layout() );
+
+ preview = new QListView( previewGrp, "colorPreView" );
+
+ preview->setShowSortIndicator(false);
+ preview->setSorting(-1);
+ preview->setEnabled( false );
+
+ preview->addColumn( i18n("Colors") );
+ preview->header()->setStretchEnabled( true, 0 );
+
+ previewGrid->addWidget( preview, 0 ,0 );
+
+ kgColorsLayout->addMultiCellWidget( hbox, 1 ,1, 0, 2 );
+
+ importBtn = new KPushButton(i18n("Import color-scheme"),parent);
+ kgColorsLayout->addWidget(importBtn,2,0);
+ exportBtn = new KPushButton(i18n("Export color-scheme"),parent);
+ kgColorsLayout->addWidget(exportBtn,2,1);
+ kgColorsLayout->addWidget(createSpacer(parent, ""), 2,2);
+ connect(importBtn, SIGNAL(clicked()), this, SLOT(slotImportColors()));
+ connect(exportBtn, SIGNAL(clicked()), this, SLOT(slotExportColors()));
+
+ slotDisable();
+}
+
+int KgColors::addColorSelector( QString cfgName, QString name, QColor dflt, QString dfltName,
+ ADDITIONAL_COLOR *addColor, int addColNum )
+{
+ int index = itemList.count() - offset;
+
+ labelList.append( addLabel( colorsGrid, index, 0, name, colorsGrp, QString( "ColorsLabel%1" ).arg( index ).ascii() ) );
+ KonfiguratorColorChooser *chooser = createColorChooser( "Colors", cfgName, dflt, colorsGrp, false, addColor, addColNum );
+ chooser->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
+
+ if( !dfltName.isEmpty() )
+ chooser->setDefaultText( dfltName );
+
+ colorsGrid->addWidget( chooser, index, 1 );
+
+ connect( chooser, SIGNAL( colorChanged() ), this, SLOT( generatePreview() ) );
+ if( !offset )
+ connect( chooser, SIGNAL( colorChanged() ), this, SLOT( slotActiveChanged() ) );
+
+ itemList.append( chooser );
+ itemNames.append( cfgName );
+
+ return index;
+}
+
+KonfiguratorColorChooser *KgColors::getColorSelector( QString name )
+{
+ QValueList<QString>::iterator it;
+ int position = 0;
+
+ for( it = itemNames.begin(); it != itemNames.end(); it++, position++ )
+ if( *it == name )
+ return itemList.at( position );
+
+ return 0;
+}
+
+QLabel *KgColors::getSelectorLabel( QString name )
+{
+ QValueList<QString>::iterator it;
+ int position = 0;
+
+ for( it = itemNames.begin(); it != itemNames.end(); it++, position++ )
+ if( *it == name )
+ return labelList.at( position );
+
+ return 0;
+}
+
+void KgColors::slotDisable()
+{
+ bool enabled = generals->find( "KDE Default" )->isChecked();
+
+ importBtn->setEnabled(!enabled);
+ exportBtn->setEnabled(!enabled);
+
+ for( int i = 0; labelList.at( i ) && i < endOfPanelColors ; i++ )
+ labelList.at( i )->setEnabled( !enabled );
+
+ for( int j = 0; itemList.at( j ) && j < endOfPanelColors ; j++ )
+ itemList.at( j )->setEnabled( !enabled );
+
+ generals->find("Enable Alternate Background")->setEnabled( enabled );
+ generals->find("Show Current Item Always")->setEnabled( !enabled );
+ generals->find("Dim Inactive Colors")->setEnabled( !enabled );
+
+ bool dimmed = !enabled && generals->find("Dim Inactive Colors")->isChecked();
+ if( dimmed )
+ inactiveColorStack->raiseWidget( dimmedInactiveWidget );
+ else
+ inactiveColorStack->raiseWidget( normalInactiveWidget );
+
+ enabled = enabled || !generals->find( "Show Current Item Always" )->isChecked();
+
+ getColorSelector( "Inactive Current Foreground" )->setEnabled( !enabled );
+ getColorSelector( "Inactive Current Background" )->setEnabled( !enabled );
+
+ generatePreview();
+}
+
+void KgColors::slotActiveChanged()
+{
+ for( int i = 0; i != endOfActiveColors; i++ )
+ itemList.at( endOfActiveColors + i )->setDefaultColor( itemList.at( i )->getColor() );
+}
+
+void KgColors::slotForegroundChanged()
+{
+ QColor color = getColorSelector( "Foreground" )->getColor();
+
+ getColorSelector( "Directory Foreground" )->setDefaultColor( color );
+ getColorSelector( "Executable Foreground" )->setDefaultColor( color );
+ getColorSelector( "Symlink Foreground" )->setDefaultColor( color );
+ getColorSelector( "Invalid Symlink Foreground" )->setDefaultColor( color );
+}
+
+void KgColors::slotBackgroundChanged()
+{
+ QColor color = getColorSelector( "Background" )->getColor();
+
+ getColorSelector( "Alternate Background" )->changeAdditionalColor( 0, color );
+ getColorSelector( "Marked Background" )->changeAdditionalColor( 0, color );
+ getColorSelector( "Current Background" )->changeAdditionalColor( 0, color );
+}
+
+void KgColors::slotAltBackgroundChanged()
+{
+ QColor color = getColorSelector( "Alternate Background" )->getColor();
+ getColorSelector( "Alternate Marked Background" )->changeAdditionalColor( 0, color );
+}
+
+void KgColors::slotMarkedBackgroundChanged()
+{
+ QColor color = getColorSelector( "Marked Background" )->getColor();
+ getColorSelector( "Alternate Marked Background" )->setDefaultColor( color );
+}
+
+void KgColors::slotInactiveForegroundChanged()
+{
+ QColor color = getColorSelector( "Inactive Foreground" )->getColor();
+
+ getColorSelector( "Inactive Directory Foreground" )->changeAdditionalColor( 0, color );
+ getColorSelector( "Inactive Executable Foreground" )->changeAdditionalColor( 0, color );
+ getColorSelector( "Inactive Symlink Foreground" )->changeAdditionalColor( 0, color );
+ getColorSelector( "Inactive Invalid Symlink Foreground" )->changeAdditionalColor( 0, color );
+}
+
+void KgColors::slotInactiveBackgroundChanged()
+{
+ QColor color = getColorSelector( "Inactive Background" )->getColor();
+
+ getColorSelector( "Inactive Alternate Background" )->changeAdditionalColor( 0, color );
+ getColorSelector( "Inactive Marked Background" )->changeAdditionalColor( 0, color );
+ getColorSelector( "Inactive Current Background" )->changeAdditionalColor( 0, color );
+}
+
+void KgColors::slotInactiveAltBackgroundChanged()
+{
+ QColor color = getColorSelector( "Inactive Alternate Background" )->getColor();
+ getColorSelector( "Inactive Alternate Marked Background" )->changeAdditionalColor( 0, color );
+}
+
+void KgColors::slotInactiveMarkedBackgroundChanged()
+{
+ QColor color = getColorSelector( "Inactive Marked Background" )->getColor();
+ getColorSelector( "Inactive Alternate Marked Background" )->changeAdditionalColor( 1, color );
+}
+
+void KgColors::setColorWithDimming(PreviewItem * item, QColor foreground, QColor background, bool dimmed )
+{
+ if ( dimmed && dimFactor->value() < 100)
+ {
+ int dim = dimFactor->value();
+ QColor dimColor = getColorSelector("Dim Target Color")->getColor();
+
+ foreground = QColor((dimColor.red() * (100 - dim) + foreground.red() * dim) / 100,
+ (dimColor.green() * (100 - dim) + foreground.green() * dim) / 100,
+ (dimColor.blue() * (100 - dim) + foreground.blue() * dim) / 100);
+ background = QColor((dimColor.red() * (100 - dim) + background.red() * dim) / 100,
+ (dimColor.green() * (100 - dim) + background.green() * dim) / 100,
+ (dimColor.blue() * (100 - dim) + background.blue() * dim) / 100);
+ }
+ item->setColor(foreground, background);
+}
+
+void KgColors::generatePreview()
+{
+ int currentPage = colorTabWidget->currentPageIndex();
+
+ preview->clear();
+
+ if( currentPage == 0 || currentPage == 1 )
+ {
+ PreviewItem *pwMarkCur = new PreviewItem( preview, i18n( "Selected + Current" ) );
+ PreviewItem *pwMark2 = new PreviewItem( preview, i18n( "Selected 2" ) );
+ PreviewItem *pwMark1 = new PreviewItem( preview, i18n( "Selected 1" ) );
+ PreviewItem *pwCurrent = new PreviewItem( preview, i18n( "Current" ) );
+ PreviewItem *pwInvLink = new PreviewItem( preview, i18n( "Invalid symlink" ) );
+ PreviewItem *pwSymLink = new PreviewItem( preview, i18n( "Symbolic link" ) );
+ PreviewItem *pwApp = new PreviewItem( preview, i18n( "Application" ) );
+ PreviewItem *pwFile = new PreviewItem( preview, i18n( "File" ) );
+ PreviewItem *pwDir = new PreviewItem( preview, i18n( "Directory" ) );
+
+ bool isActive = currentPage == 0;
+
+ // create local color cache instance, which does NOT affect the color cache instance using to paint the panels
+ KrColorCache colCache;
+
+ // create local color settings instance, which initially contains the setings from krConfig
+ KrColorSettings colorSettings;
+
+ // copy over local settings to color settings instance, which does not affect the persisted krConfig settings
+ QValueList<QString> names = KrColorSettings::getColorNames();
+ for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it )
+ {
+ KonfiguratorColorChooser * chooser = getColorSelector( *it );
+ if (!chooser)
+ continue;
+ colorSettings.setColorTextValue( *it, chooser->getValue());
+ if (chooser->isValueRGB())
+ colorSettings.setColorValue( *it, chooser->getColor());
+ else
+ colorSettings.setColorValue( *it, QColor());
+ }
+
+ colorSettings.setBoolValue("KDE Default", generals->find( "KDE Default" )->isChecked());
+ colorSettings.setBoolValue("Enable Alternate Background", generals->find( "Enable Alternate Background" )->isChecked());
+ colorSettings.setBoolValue("Show Current Item Always", generals->find( "Show Current Item Always" )->isChecked());
+ colorSettings.setBoolValue("Dim Inactive Colors", generals->find( "Dim Inactive Colors" )->isChecked());
+ colorSettings.setNumValue("Dim Factor", dimFactor->value());
+
+ // let the color cache use the local color settings
+ colCache.setColors( colorSettings );
+
+ // ask the local color cache for certain color groups and use them to color the preview
+ QColorGroup cg;
+ colCache.getColors(cg, KrColorItemType(KrColorItemType::Directory, false, isActive, false, false));
+ pwDir->setColor( cg.text(), cg.background() );
+ colCache.getColors(cg, KrColorItemType(KrColorItemType::File, true, isActive, false, false));
+ pwFile->setColor( cg.text(), cg.background() );
+ colCache.getColors(cg, KrColorItemType(KrColorItemType::Executable, false, isActive, false, false));
+ pwApp->setColor( cg.text(), cg.background() );
+ colCache.getColors(cg, KrColorItemType(KrColorItemType::Symlink, true, isActive, false, false));
+ pwSymLink->setColor( cg.text(), cg.background() );
+ colCache.getColors(cg, KrColorItemType(KrColorItemType::InvalidSymlink, false, isActive, false, false));
+ pwInvLink->setColor( cg.text(), cg.background() );
+ colCache.getColors(cg, KrColorItemType(KrColorItemType::File, true, isActive, true, false));
+ pwCurrent->setColor( cg.highlightedText(), cg.highlight() );
+ colCache.getColors(cg, KrColorItemType(KrColorItemType::File, false, isActive, false, true));
+ pwMark1->setColor( cg.highlightedText(), cg.highlight() );
+ colCache.getColors(cg, KrColorItemType(KrColorItemType::File, true, isActive, false, true));
+ pwMark2->setColor( cg.highlightedText(), cg.highlight() );
+ colCache.getColors(cg, KrColorItemType(KrColorItemType::File, false, isActive, true, true));
+ pwMarkCur->setColor( cg.highlightedText(), cg.highlight() );
+ }else if( currentPage == 2 )
+ {
+ PreviewItem *pwDelete = new PreviewItem( preview, i18n( "Delete" ) );
+ PreviewItem *pwRightCopy = new PreviewItem( preview, i18n( "Copy to right" ) );
+ PreviewItem *pwLeftCopy = new PreviewItem( preview, i18n( "Copy to left" ) );
+ PreviewItem *pwDiffers = new PreviewItem( preview, i18n( "Differing" ) );
+ PreviewItem *pwEquals = new PreviewItem( preview, i18n( "Equals" ) );
+
+ pwEquals->setColor( getColorSelector( "Synchronizer Equals Foreground" )->getColor(),
+ getColorSelector( "Synchronizer Equals Background" )->getColor() );
+ pwDiffers->setColor( getColorSelector( "Synchronizer Differs Foreground" )->getColor(),
+ getColorSelector( "Synchronizer Differs Background" )->getColor() );
+ pwLeftCopy->setColor ( getColorSelector( "Synchronizer LeftCopy Foreground" )->getColor(),
+ getColorSelector( "Synchronizer LeftCopy Background" )->getColor() );
+ pwRightCopy->setColor( getColorSelector( "Synchronizer RightCopy Foreground" )->getColor(),
+ getColorSelector( "Synchronizer RightCopy Background" )->getColor() );
+ pwDelete->setColor( getColorSelector( "Synchronizer Delete Foreground" )->getColor(),
+ getColorSelector( "Synchronizer Delete Background" )->getColor() );
+ }
+}
+
+bool KgColors::apply()
+{
+ bool result = KonfiguratorPage::apply();
+ KrColorCache::getColorCache().refreshColors();
+ return result;
+}
+
+void KgColors::slotImportColors() {
+ // find $KDEDIR/share/apps/krusader
+ QString basedir = KGlobal::dirs()->findResourceDir("appdata", "total_commander.keymap");
+ // let the user select a file to load
+ QString file = KFileDialog::getOpenFileName(basedir, "*.color", 0, i18n("Select a color-scheme file"));
+ if (file == QString::null) return;
+ QFile f(file);
+ if (!f.open(IO_ReadOnly)) {
+ KMessageBox::error(this, i18n("Error: unable to read from file"), i18n("Error"));
+ return;
+ }
+ QDataStream stream(&f);
+ // ok, import away
+ deserialize(stream);
+ generatePreview();
+}
+
+void KgColors::slotExportColors() {
+ QString file = KFileDialog::getSaveFileName(QString::null, "*", 0, i18n("Select a color scheme file"));
+ if (file == QString::null) return;
+ QFile f(file);
+ if (f.exists() && KMessageBox::warningContinueCancel(this,
+ i18n("File ")+file+i18n(" already exists. Are you sure you want to overwrite it?"),
+ i18n("Warning"), i18n("Overwrite")) != KMessageBox::Continue) return;
+ if (!f.open(IO_WriteOnly)) {
+ KMessageBox::error(this, i18n("Error: unable to write to file"), i18n("Error"));
+ return;
+ }
+ QDataStream stream(&f);
+ serialize(stream);
+}
+
+void KgColors::serialize(QDataStream & stream)
+{
+ serializeItem(stream, "Alternate Background");
+ serializeItem(stream, "Alternate Marked Background");
+ serializeItem(stream, "Background");
+ serializeItem(stream, "Current Background");
+ serializeItem(stream, "Current Foreground");
+ serializeItem(stream, "Enable Alternate Background");
+ serializeItem(stream, "Foreground");
+ serializeItem(stream, "Directory Foreground");
+ serializeItem(stream, "Executable Foreground");
+ serializeItem(stream, "Symlink Foreground");
+ serializeItem(stream, "Invalid Symlink Foreground");
+ serializeItem(stream, "Inactive Alternate Background");
+ serializeItem(stream, "Inactive Alternate Marked Background");
+ serializeItem(stream, "Inactive Background");
+ serializeItem(stream, "Inactive Current Foreground");
+ serializeItem(stream, "Inactive Current Background");
+ serializeItem(stream, "Inactive Marked Background");
+ serializeItem(stream, "Inactive Marked Current Foreground");
+ serializeItem(stream, "Inactive Marked Foreground");
+ serializeItem(stream, "Inactive Foreground");
+ serializeItem(stream, "Inactive Directory Foreground");
+ serializeItem(stream, "Inactive Executable Foreground");
+ serializeItem(stream, "Inactive Symlink Foreground");
+ serializeItem(stream, "Inactive Invalid Symlink Foreground");
+ serializeItem(stream, "Dim Inactive Colors");
+ serializeItem(stream, "Dim Target Color");
+ serializeItem(stream, "Dim Factor");
+ serializeItem(stream, "KDE Default");
+ serializeItem(stream, "Marked Background");
+ serializeItem(stream, "Marked Current Foreground");
+ serializeItem(stream, "Marked Foreground");
+ serializeItem(stream, "Show Current Item Always");
+ serializeItem(stream, "Synchronizer Equals Foreground");
+ serializeItem(stream, "Synchronizer Equals Background");
+ serializeItem(stream, "Synchronizer Differs Foreground");
+ serializeItem(stream, "Synchronizer Differs Background");
+ serializeItem(stream, "Synchronizer LeftCopy Foreground");
+ serializeItem(stream, "Synchronizer LeftCopy Background");
+ serializeItem(stream, "Synchronizer RightCopy Foreground");
+ serializeItem(stream, "Synchronizer RightCopy Background");
+ serializeItem(stream, "Synchronizer Delete Foreground");
+ serializeItem(stream, "Synchronizer Delete Background");
+ stream << QString("") << QString("");
+}
+
+void KgColors::deserialize(QDataStream & stream)
+{
+ for (;;)
+ {
+ QString name, value;
+ stream >> name >> value;
+ if (name == "")
+ break;
+
+ if (name == "KDE Default" || name == "Enable Alternate Background" ||
+ name == "Show Current Item Always" || name == "Dim Inactive Colors" )
+ {
+ bool bValue = false;
+ value = value.lower();
+ if( value == "true" || value == "yes" || value == "on" || value == "1" )
+ bValue = true;
+
+ generals->find( name )->setChecked( bValue );
+ continue;
+ }
+
+ if( name == "Dim Factor" )
+ {
+ dimFactor->setValue( value.toInt() );
+ continue;
+ }
+
+ KonfiguratorColorChooser *selector = getColorSelector( name );
+ if( selector == 0 )
+ break;
+ selector->setValue( value );
+ }
+}
+
+void KgColors::serializeItem(class QDataStream & stream, const char * name)
+{
+ stream << QString(name);
+ if( (strcmp( name, "KDE Default") == 0)
+ || (strcmp( name, "Enable Alternate Background") == 0)
+ || (strcmp( name, "Show Current Item Always") == 0)
+ || (strcmp( name, "Dim Inactive Colors") == 0) )
+ {
+ bool bValue = generals->find( name )->isChecked();
+ stream << QString( bValue ? "true" : "false" );
+ }
+ else if( strcmp( name, "Dim Factor") == 0 )
+ stream << QString::number(dimFactor->value());
+ else
+ {
+ KonfiguratorColorChooser *selector = getColorSelector( name );
+ stream << selector->getValue();
+ }
+}
+
+#include "kgcolors.moc"
diff --git a/krusader/Konfigurator/kgcolors.h b/krusader/Konfigurator/kgcolors.h
new file mode 100644
index 0000000..55398f4
--- /dev/null
+++ b/krusader/Konfigurator/kgcolors.h
@@ -0,0 +1,139 @@
+/***************************************************************************
+ kgcolors.h - description
+ -------------------
+ copyright : (C) 2004 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __KGCOLORS_H__
+#define __KGCOLORS_H__
+
+#include "konfiguratorpage.h"
+#include <qptrlist.h>
+#include <qvaluelist.h>
+#include <qlistview.h>
+#include <qwidgetstack.h>
+
+class KgColors : public KonfiguratorPage
+{
+ Q_OBJECT
+
+public:
+ KgColors( bool first, QWidget* parent=0, const char* name=0 );
+
+ bool apply();
+
+public slots:
+ void slotDisable();
+ void slotForegroundChanged();
+ void slotBackgroundChanged();
+ void slotAltBackgroundChanged();
+ void slotActiveChanged();
+ void slotMarkedBackgroundChanged();
+ void slotInactiveForegroundChanged();
+ void slotInactiveBackgroundChanged();
+ void slotInactiveAltBackgroundChanged();
+ void slotInactiveMarkedBackgroundChanged();
+ void generatePreview();
+
+protected slots:
+ void slotImportColors();
+ void slotExportColors();
+
+private:
+ class PreviewItem;
+
+ int addColorSelector( QString cfgName, QString name, QColor dflt, QString dfltName = QString::null,
+ ADDITIONAL_COLOR *addColor = 0, int addColNum = 0);
+ KonfiguratorColorChooser *getColorSelector( QString name );
+ QLabel *getSelectorLabel( QString name );
+ void serialize(class QDataStream &);
+ void deserialize(class QDataStream &);
+ void serializeItem(class QDataStream &, const char * name);
+ void setColorWithDimming(PreviewItem * item, QColor foreground, QColor background, bool dimmed );
+
+private:
+ QWidget *colorsGrp;
+ QGridLayout *colorsGrid;
+ int offset;
+ int endOfActiveColors;
+ int endOfPanelColors;
+
+ QGroupBox *previewGrp;
+ QGridLayout *previewGrid;
+ QTabWidget *colorTabWidget;
+
+ QWidgetStack *inactiveColorStack;
+ QWidget *normalInactiveWidget;
+ QWidget *dimmedInactiveWidget;
+ KonfiguratorSpinBox *dimFactor;
+
+ KonfiguratorCheckBoxGroup *generals;
+
+ QPtrList<QLabel> labelList;
+ QPtrList<KonfiguratorColorChooser> itemList;
+ QValueList<QString> itemNames;
+
+ QListView *preview;
+ KPushButton *importBtn, *exportBtn;
+
+ class PreviewItem : public QListViewItem
+ {
+ private:
+ QColor defaultBackground;
+ QColor defaultForeground;
+ QString label;
+
+ public:
+ PreviewItem( QListView * parent, QString name ) : QListViewItem( parent, name )
+ {
+ defaultBackground = QColor( 255, 255, 255 );
+ defaultForeground = QColor( 0, 0, 0 );
+ label = name;
+ }
+
+ void setColor( QColor foregnd, QColor backgnd )
+ {
+ defaultForeground = foregnd;
+ defaultBackground = backgnd;
+ listView()->repaintItem( this );
+ }
+
+ QString text()
+ {
+ return label;
+ }
+
+ void paintCell ( QPainter * p, const QColorGroup & cg, int column, int width, int align )
+ {
+ QColorGroup _cg( cg );
+ _cg.setColor( QColorGroup::Base, defaultBackground );
+ _cg.setColor( QColorGroup::Text, defaultForeground );
+ QListViewItem::paintCell(p, _cg, column, width, align);
+ }
+ };
+};
+#endif /* __KGCOLORS_H__ */
diff --git a/krusader/Konfigurator/kgdependencies.cpp b/krusader/Konfigurator/kgdependencies.cpp
new file mode 100644
index 0000000..7e9f948
--- /dev/null
+++ b/krusader/Konfigurator/kgdependencies.cpp
@@ -0,0 +1,169 @@
+/***************************************************************************
+ kgdependencies.cpp - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "kgdependencies.h"
+#include "../krservices.h"
+#include "../krusader.h"
+#include <qtabwidget.h>
+#include <klocale.h>
+#include <qhbox.h>
+#include <kmessagebox.h>
+
+#define PAGE_GENERAL 0
+#define PAGE_PACKERS 1
+#define PAGE_CHECKSUM 2
+
+KgDependencies::KgDependencies( bool first, QWidget* parent, const char* name ) :
+ KonfiguratorPage( first, parent, name )
+{
+ QGridLayout *kgDependenciesLayout = new QGridLayout( parent );
+ kgDependenciesLayout->setSpacing( 6 );
+
+ // ---------------------------- GENERAL TAB -------------------------------------
+ tabWidget = new QTabWidget( parent, "tabWidget" );
+
+ QWidget *general_tab = new QWidget( tabWidget, "tab" );
+ tabWidget->insertTab( general_tab, i18n( "General" ) );
+
+ QGridLayout *pathsGrid = new QGridLayout( general_tab );
+ pathsGrid->setSpacing( 6 );
+ pathsGrid->setMargin( 11 );
+ pathsGrid->setAlignment( Qt::AlignTop );
+
+ addApplication( "df", pathsGrid, 0, general_tab, PAGE_GENERAL );
+ addApplication( "eject", pathsGrid, 1, general_tab, PAGE_GENERAL );
+ addApplication( "kdesu", pathsGrid, 2, general_tab, PAGE_GENERAL );
+ addApplication( "kget", pathsGrid, 3, general_tab, PAGE_GENERAL );
+ addApplication( "kmail", pathsGrid, 4, general_tab, PAGE_GENERAL );
+ addApplication( "diff utility", pathsGrid, 5, general_tab, PAGE_GENERAL );
+ addApplication( "krename", pathsGrid, 6, general_tab, PAGE_GENERAL );
+ addApplication( "krusader", pathsGrid, 7, general_tab, PAGE_GENERAL );
+ addApplication( "locate", pathsGrid, 8, general_tab, PAGE_GENERAL );
+ addApplication( "mount", pathsGrid, 9, general_tab, PAGE_GENERAL );
+ addApplication( "umount", pathsGrid,10, general_tab, PAGE_GENERAL );
+ addApplication( "updatedb", pathsGrid,11, general_tab, PAGE_GENERAL );
+
+ // ---------------------------- PACKERS TAB -------------------------------------
+ QWidget *packers_tab = new QWidget( tabWidget, "tab_3" );
+ tabWidget->insertTab( packers_tab, i18n( "Packers" ) );
+
+ QGridLayout *archGrid1 = new QGridLayout( packers_tab );
+ archGrid1->setSpacing( 6 );
+ archGrid1->setMargin( 11 );
+ archGrid1->setAlignment( Qt::AlignTop );
+
+ addApplication( "7z", archGrid1, 0, packers_tab, PAGE_PACKERS, "7za" );
+ addApplication( "arj", archGrid1, 1, packers_tab, PAGE_PACKERS );
+ addApplication( "bzip2", archGrid1, 2, packers_tab, PAGE_PACKERS );
+ addApplication( "cpio", archGrid1, 3, packers_tab, PAGE_PACKERS );
+ addApplication( "dpkg", archGrid1, 4, packers_tab, PAGE_PACKERS );
+ addApplication( "gzip", archGrid1, 5, packers_tab, PAGE_PACKERS );
+ addApplication( "lha", archGrid1, 6, packers_tab, PAGE_PACKERS );
+ addApplication( "rar", archGrid1, 7, packers_tab, PAGE_PACKERS );
+ addApplication( "tar", archGrid1, 8, packers_tab, PAGE_PACKERS );
+ addApplication( "unace", archGrid1, 9, packers_tab, PAGE_PACKERS );
+ addApplication( "unarj", archGrid1,10, packers_tab, PAGE_PACKERS );
+ addApplication( "unrar", archGrid1,11, packers_tab, PAGE_PACKERS );
+ addApplication( "unzip", archGrid1,12, packers_tab, PAGE_PACKERS );
+ addApplication( "zip", archGrid1,13, packers_tab, PAGE_PACKERS );
+
+ // ---------------------------- CHECKSUM TAB -------------------------------------
+ QWidget *checksum_tab = new QWidget( tabWidget, "tab_4" );
+ tabWidget->insertTab( checksum_tab, i18n( "Checksum Utilities" ) );
+
+ QGridLayout *archGrid2 = new QGridLayout( checksum_tab );
+ archGrid2->setSpacing( 6 );
+ archGrid2->setMargin( 11 );
+ archGrid2->setAlignment( Qt::AlignTop );
+
+ addApplication( "md5sum", archGrid2, 0, checksum_tab, PAGE_CHECKSUM );
+ addApplication( "sha1sum", archGrid2, 1, checksum_tab, PAGE_CHECKSUM );
+ addApplication( "sha224sum", archGrid2, 2, checksum_tab, PAGE_CHECKSUM );
+ addApplication( "sha256sum", archGrid2, 3, checksum_tab, PAGE_CHECKSUM );
+ addApplication( "sha384sum", archGrid2, 4, checksum_tab, PAGE_CHECKSUM );
+ addApplication( "sha512sum", archGrid2, 5, checksum_tab, PAGE_CHECKSUM );
+ addApplication( "md5deep", archGrid2, 6, checksum_tab, PAGE_CHECKSUM );
+ addApplication( "sha1deep", archGrid2, 7, checksum_tab, PAGE_CHECKSUM );
+ addApplication( "sha256deep", archGrid2, 8, checksum_tab, PAGE_CHECKSUM );
+ addApplication( "tigerdeep", archGrid2, 9, checksum_tab, PAGE_CHECKSUM );
+ addApplication( "whirlpooldeep", archGrid2, 10, checksum_tab, PAGE_CHECKSUM );
+ addApplication( "cfv", archGrid2, 11, checksum_tab, PAGE_CHECKSUM );
+
+ kgDependenciesLayout->addWidget( tabWidget, 0, 0 );
+}
+
+void KgDependencies::addApplication( QString name, QGridLayout *grid, int row, QWidget *parent, int page, QString additionalList )
+{
+ QString dflt = KrServices::fullPathName( name ); /* try to autodetect the full path name */
+
+ if( dflt.isEmpty() ) {
+ QStringList list = QStringList::split( ',', additionalList );
+ for( unsigned i=0; i != list.count(); i++ )
+ if( !KrServices::fullPathName( list[ i ] ).isEmpty() ) {
+ dflt = KrServices::fullPathName( list[ i ] );
+ break;
+ }
+ }
+
+ addLabel( grid, row, 0, name, parent, (QString( "label:" )+name).ascii() );
+
+ KonfiguratorURLRequester *fullPath = createURLRequester( "Dependencies", name, dflt, parent, false, page );
+ connect( fullPath->extension(), SIGNAL( applyManually( QObject *, QString, QString ) ),
+ this, SLOT( slotApply( QObject *, QString, QString ) ) );
+ grid->addWidget( fullPath, row, 1 );
+}
+
+void KgDependencies::slotApply( QObject *obj, QString cls, QString name )
+{
+ KonfiguratorURLRequester *urlRequester = (KonfiguratorURLRequester *) obj;
+
+ krConfig->setGroup( cls );
+ krConfig->writeEntry( name, urlRequester->url() );
+
+ QString usedPath = KrServices::fullPathName( name );
+
+ if( urlRequester->url() != usedPath )
+ {
+ krConfig->writeEntry( name, usedPath );
+ if( usedPath.isEmpty() )
+ KMessageBox::error( this, i18n( "The %1 path is incorrect, no valid path found." )
+ .arg( urlRequester->url() ) );
+ else
+ KMessageBox::error( this, i18n( "The %1 path is incorrect, %2 used instead." )
+ .arg( urlRequester->url() ).arg( usedPath ) );
+ urlRequester->setURL( usedPath );
+ }
+}
+
+int KgDependencies::activeSubPage() {
+ return tabWidget->currentPageIndex();
+}
+
+#include "kgdependencies.moc"
diff --git a/krusader/Konfigurator/kgdependencies.h b/krusader/Konfigurator/kgdependencies.h
new file mode 100644
index 0000000..766c8ce
--- /dev/null
+++ b/krusader/Konfigurator/kgdependencies.h
@@ -0,0 +1,58 @@
+/***************************************************************************
+ kgdependencies.h - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __KGDEPENDENCIES_H__
+#define __KGDEPENDENCIES_H__
+
+#include "konfiguratorpage.h"
+
+class QTabWidget;
+
+
+class KgDependencies : public KonfiguratorPage
+{
+ Q_OBJECT
+
+public:
+ KgDependencies( bool first, QWidget* parent=0, const char* name=0 );
+
+ virtual int activeSubPage();
+
+private:
+ void addApplication( QString name, QGridLayout *grid, int row, QWidget *parent, int page, QString additionalList=QString::null );
+
+public slots:
+ void slotApply( QObject *obj, QString cls, QString name );
+
+private:
+ QTabWidget *tabWidget;
+};
+
+#endif /* __KGDEPENDENCIES_H__ */
diff --git a/krusader/Konfigurator/kggeneral.cpp b/krusader/Konfigurator/kggeneral.cpp
new file mode 100644
index 0000000..d97189b
--- /dev/null
+++ b/krusader/Konfigurator/kggeneral.cpp
@@ -0,0 +1,213 @@
+/***************************************************************************
+ kggeneral.cpp - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <qlabel.h>
+#include <qhbox.h>
+#include <qvbox.h>
+#include <qfontmetrics.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kinputdialog.h>
+#include "krresulttabledialog.h"
+#include "kggeneral.h"
+#include "../defaults.h"
+#include "../krusader.h"
+#include "../kicons.h"
+
+KgGeneral::KgGeneral( bool first, QWidget* parent, const char* name ) :
+ KonfiguratorPage( first, parent, name )
+{
+if( first )
+ slotFindTools();
+
+ QGridLayout *kgGeneralLayout = new QGridLayout( parent );
+ kgGeneralLayout->setSpacing( 6 );
+
+ // -------------------------- GENERAL GROUPBOX ----------------------------------
+
+ QGroupBox *generalGrp = createFrame( i18n( "General" ), parent, "kgGenGeneralGrp" );
+ QGridLayout *generalGrid = createGridLayout( generalGrp->layout() );
+
+ KONFIGURATOR_NAME_VALUE_TIP deleteMode[] =
+ // name value tooltip
+ {{ i18n( "Delete files" ), "false", i18n( "Files will be permanently deleted." ) },
+ { i18n( "Move to trash" ), "true", i18n( "Files will be moved to trash when deleted." ) }};
+
+ KonfiguratorRadioButtons *trashRadio = createRadioButtonGroup( "General", "Move To Trash",
+ _MoveToTrash ? "true" : "false", 2, 0, deleteMode, 2, generalGrp, "myRadio", false );
+ generalGrid->addMultiCellWidget( trashRadio, 0, 0, 0, 1 );
+
+ KonfiguratorCheckBox *checkBox = createCheckBox( "General", "Mimetype Magic", _MimetypeMagic,
+ i18n( "Use mimetype magic" ), generalGrp, false,
+ i18n( "Mimetype magic allows better distinction of file types, but is slower." ) );
+ generalGrid->addMultiCellWidget( checkBox, 1, 1, 0, 1 );
+
+ QFrame *line1 = createLine( generalGrp, "line1" );
+ generalGrid->addMultiCellWidget( line1, 2, 2, 0, 1 );
+
+ // editor
+ QLabel *label1 = new QLabel( i18n( "Editor:" ), generalGrp, "EditorLabel" );
+ generalGrid->addWidget( label1, 3, 0 );
+ KonfiguratorURLRequester *urlReq = createURLRequester( "General", "Editor", "internal editor",
+ generalGrp, false );
+ generalGrid->addWidget( urlReq, 3, 1 );
+
+ QLabel *label2 = new QLabel( i18n( "Hint: use 'internal editor' if you want to use Krusader's fast built-in editor" ), generalGrp, "EditorLabel" );
+ generalGrid->addMultiCellWidget( label2, 4, 4, 0, 1 );
+
+QFrame *line2 = createLine( generalGrp, "line2" );
+ generalGrid->addMultiCellWidget( line2, 5, 5, 0, 1 );
+
+ // viewer
+
+ QHBox * hbox2 = new QHBox( generalGrp );
+ QVBox * vbox = new QVBox( hbox2 );
+
+ new QLabel( i18n("Default viewer mode:"), vbox);
+
+ KONFIGURATOR_NAME_VALUE_TIP viewMode[] =
+ // name value tooltip
+ {{ i18n( "Generic mode" ), "generic", i18n( "Use the system's default viewer" ) },
+ { i18n( "Text mode" ), "text", i18n( "View the file in text-only mode" ) },
+ { i18n( "Hex mode" ), "hex", i18n( "View the file in hex-mode (better for binary files)" ) } };
+ createRadioButtonGroup( "General", "Default Viewer Mode",
+ "generic", 0, 3, viewMode, 3, vbox, "myRadio2", false );
+
+ createCheckBox( "General", "View In Separate Window", _ViewInSeparateWindow,
+ i18n( "Internal editor and viewer opens each file in a separate window" ), vbox, false,
+ i18n( "If checked, each file will open in a separate window, otherwise, the viewer will work in a single, tabbed mode" ) );
+
+ generalGrid->addMultiCellWidget(hbox2, 6, 8, 0, 1);
+
+ // atomic extensions
+ QFrame * frame21 = createLine( hbox2, "line2.1", true );
+ frame21->setMinimumWidth( 15 );
+ QVBox * vbox2 = new QVBox( hbox2 );
+
+ QHBox * hbox3 = new QHBox( vbox2 );
+ QLabel * atomLabel = new QLabel( i18n("Atomic extensions:"), hbox3);
+
+ int size = QFontMetrics( atomLabel->font() ).height();
+
+ QToolButton *addButton = new QToolButton( hbox3, "addBtnList" );
+ QPixmap icon = krLoader->loadIcon("add",KIcon::Desktop, size );
+ addButton->setFixedSize( icon.width() + 4, icon.height() + 4 );
+ addButton->setPixmap( icon );
+ connect( addButton, SIGNAL( clicked() ), this, SLOT( slotAddExtension() ) );
+
+ QToolButton *removeButton = new QToolButton( hbox3, "removeBtnList" );
+ icon = krLoader->loadIcon("remove",KIcon::Desktop, size );
+ removeButton->setFixedSize( icon.width() + 4, icon.height() + 4 );
+ removeButton->setPixmap( icon );
+ connect( removeButton, SIGNAL( clicked() ), this, SLOT( slotRemoveExtension() ) );
+
+ QStringList defaultAtomicExtensions;
+ defaultAtomicExtensions += ".tar.gz";
+ defaultAtomicExtensions += ".tar.bz2";
+ defaultAtomicExtensions += ".moc.cpp";
+
+ listBox = createListBox( "Look&Feel", "Atomic Extensions",
+ defaultAtomicExtensions, vbox2, true, false );
+
+ QFrame *line3 = createLine( generalGrp, "line3" );
+ generalGrid->addMultiCellWidget( line3, 9, 9, 0, 1 );
+
+ // terminal
+ QLabel *label3 = new QLabel( i18n( "Terminal:" ), generalGrp, "TerminalLabel" );
+ generalGrid->addWidget( label3, 10, 0 );
+ KonfiguratorURLRequester *urlReq2 = createURLRequester( "General", "Terminal", "konsole",
+ generalGrp, false );
+ generalGrid->addWidget( urlReq2, 10, 1 );
+
+ KonfiguratorCheckBox *checkBox1 = createCheckBox( "General", "Send CDs", _SendCDs,
+ i18n( "Terminal Emulator sends Chdir on panel change" ), generalGrp, false,
+ i18n( "When checked, whenever the panel is changed (for example, by pressing TAB), krusader changes the current directory in the terminal emulator." ) );
+ generalGrid->addMultiCellWidget( checkBox1, 11, 11, 0, 1 );
+
+ QFrame *line31 = createLine( generalGrp, "line4" );
+ generalGrid->addMultiCellWidget( line31, 12, 12, 0, 1 );
+
+ // temp dir
+ QHBox *hbox = new QHBox( generalGrp, "hbox" );
+ new QLabel( i18n( "Temp Directory:" ), hbox, "TempDirectory" );
+ KonfiguratorURLRequester *urlReq3 = createURLRequester( "General", "Temp Directory", "/tmp/krusader.tmp",
+ hbox, false );
+ urlReq3->setMode( KFile::Directory );
+ connect( urlReq3->extension(), SIGNAL( applyManually(QObject *,QString, QString) ),
+ this, SLOT( applyTempDir(QObject *,QString, QString) ) );
+ generalGrid->addMultiCellWidget( hbox, 13, 13, 0, 1 );
+
+ QLabel *label4 = new QLabel( i18n( "Note: you must have full permissions for the temporary directory!" ),
+ generalGrp, "NoteLabel" );
+ generalGrid->addMultiCellWidget( label4, 14, 14, 0, 1 );
+
+
+ kgGeneralLayout->addWidget( generalGrp, 0 ,0 );
+}
+
+void KgGeneral::applyTempDir(QObject *obj,QString cls, QString name)
+{
+ KonfiguratorURLRequester *urlReq = (KonfiguratorURLRequester *)obj;
+ QString value = QDir(urlReq->url()).path();
+
+ krConfig->setGroup( cls );
+ krConfig->writeEntry( name, value );
+}
+
+void KgGeneral::slotFindTools()
+{
+ KrResultTableDialog* dia = new KrResultTableDialog(this, KrResultTableDialog::Tool, i18n("Search results"), i18n("Searching for tools..."),
+ "package_settings", i18n("Make sure to install new tools in your <code>$PATH</code> (e.g. /usr/bin)"));
+ dia->exec();
+}
+
+void KgGeneral::slotAddExtension()
+{
+ bool ok;
+ QString atomExt =
+ KInputDialog::getText( i18n( "Add new atomic extension" ), i18n( "Extension: " ), QString::null, &ok );
+
+ if( ok )
+ {
+ if( !atomExt.startsWith( "." ) || atomExt.find( '.', 1 ) == -1 )
+ KMessageBox::error(krApp, i18n("Atomic extensions must start with '.'\n and must contain at least one more '.' character"), i18n("Error"));
+ else
+ listBox->addItem( atomExt );
+ }
+}
+
+void KgGeneral::slotRemoveExtension()
+{
+ QListBoxItem * item = listBox->selectedItem();
+ if( item )
+ listBox->removeItem( item->text() );
+}
+
+#include "kggeneral.moc"
diff --git a/krusader/Konfigurator/kggeneral.h b/krusader/Konfigurator/kggeneral.h
new file mode 100644
index 0000000..6e6b69f
--- /dev/null
+++ b/krusader/Konfigurator/kggeneral.h
@@ -0,0 +1,54 @@
+/***************************************************************************
+ kgadvanced.h - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __KGGENERAL_H__
+#define __KGGENERAL_H__
+
+#include "konfiguratorpage.h"
+
+class KgGeneral : public KonfiguratorPage
+{
+ Q_OBJECT
+
+public:
+ KgGeneral( bool first, QWidget* parent=0, const char* name=0 );
+
+public slots:
+ void applyTempDir(QObject *,QString, QString);
+ void slotFindTools();
+
+ void slotAddExtension();
+ void slotRemoveExtension();
+
+private:
+ KonfiguratorListBox *listBox;
+};
+
+#endif /* __KGGENERAL_H__ */
diff --git a/krusader/Konfigurator/kglookfeel.cpp b/krusader/Konfigurator/kglookfeel.cpp
new file mode 100644
index 0000000..c9a167e
--- /dev/null
+++ b/krusader/Konfigurator/kglookfeel.cpp
@@ -0,0 +1,373 @@
+/***************************************************************************
+ kglookfeel.cpp - description
+ -------------------
+ copyright : (C) 2003 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "kglookfeel.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include "../Dialogs/krdialogs.h"
+#include <qtabwidget.h>
+#include <klocale.h>
+#include <qwhatsthis.h>
+#include <qvalidator.h>
+#include <qlistview.h>
+#include <kmessagebox.h>
+#include <kfiledialog.h>
+#include <kglobal.h>
+#include <kstandarddirs.h>
+#include "../Panel/krselectionmode.h"
+#include "../Panel/listpanel.h"
+
+#define PAGE_OPERATION 0
+#define PAGE_PANEL 1
+#define PAGE_PANELTOOLBAR 2
+#define PAGE_MOUSE 3
+
+KgLookFeel::KgLookFeel( bool first, QWidget* parent, const char* name ) :
+ KonfiguratorPage( first, parent, name )
+{
+ QGridLayout *kgLookAndFeelLayout = new QGridLayout( parent );
+ kgLookAndFeelLayout->setSpacing( 6 );
+
+ tabWidget = new QTabWidget( parent, "tabWidget" );
+
+ setupOperationTab();
+ setupPanelTab();
+ setupPanelToolbarTab();
+ setupMouseModeTab();
+
+ kgLookAndFeelLayout->addWidget( tabWidget, 0, 0 );
+}
+
+// ---------------------------------------------------------------------------------------
+// ---------------------------- OPERATION TAB -------------------------------------
+// ---------------------------------------------------------------------------------------
+void KgLookFeel::setupOperationTab() {
+ QWidget *tab = new QWidget( tabWidget, "tab_operation" );
+ tabWidget->insertTab( tab, i18n( "Operation" ) );
+
+ QGridLayout *lookAndFeelLayout = new QGridLayout( tab );
+ lookAndFeelLayout->setSpacing( 6 );
+ lookAndFeelLayout->setMargin( 11 );
+
+ // -------------- General -----------------
+ QGroupBox *lookFeelGrp = createFrame( i18n( "Look && Feel" ), tab, "kgLookAndFeelGrp" );
+ QGridLayout *lookFeelGrid = createGridLayout( lookFeelGrp->layout() );
+
+ KONFIGURATOR_CHECKBOX_PARAM settings[] =
+ { // cfg_class cfg_name default text restart tooltip
+ {"Look&Feel","Warn On Exit", _WarnOnExit, i18n( "Warn on exit" ), false, i18n( "Display a warning when trying to close the main window." ) }, // KDE4: move warn on exit to the other confirmations
+ {"Look&Feel","Minimize To Tray", _MinimizeToTray, i18n( "Minimize to tray" ), false, i18n( "The icon will appear in the system tray instead of the taskbar, when Krusader is minimized." ) },
+ {"Look&Feel","Mark Dirs", _MarkDirs, i18n( "Autoselect directories" ), false, i18n( "When matching the select criteria, not only files will be selected, but also directories." ) },
+ {"Look&Feel","Rename Selects Extension",true, i18n( "Rename selects extension" ), false, i18n( "When renaming a file, the whole text is selected. If you want Total-Commander like renaming of just the name, without extension, uncheck this option." ) },
+ {"Look&Feel","Fullpath Tab Names", _FullPathTabNames, i18n( "Use full path tab names" ), true , i18n( "Display the full path in the folder tabs. By default only the last part of the path is displayed." ) },
+ {"Look&Feel","Fullscreen Terminal Emulator", false, i18n( "Fullscreen terminal (mc-style)" ), false, i18n( "Terminal is shown instead of the Krusader window (full screen).") },
+ };
+
+ cbs = createCheckBoxGroup( 2, 0, settings, 6 /*count*/, lookFeelGrp, 0, PAGE_OPERATION );
+ lookFeelGrid->addWidget( cbs, 0, 0 );
+
+ lookAndFeelLayout->addWidget( lookFeelGrp, 0, 0 );
+
+ // -------------- Quicksearch -----------------
+ QGroupBox *quicksearchGroup = createFrame( i18n( "Quicksearch" ), tab, "kgQuicksearchGrp" );
+ QGridLayout *quicksearchGrid = createGridLayout( quicksearchGroup->layout() );
+
+ KONFIGURATOR_CHECKBOX_PARAM quicksearch[] =
+ { // cfg_class cfg_name default text restart tooltip
+ {"Look&Feel","New Style Quicksearch", _NewStyleQuicksearch, i18n( "New style quicksearch" ), false, i18n( "Opens a quick search dialog box." ) },
+ {"Look&Feel","Case Sensitive Quicksearch", _CaseSensitiveQuicksearch, i18n( "Case sensitive quicksearch" ), false, i18n( "All files beginning with capital letters appear before files beginning with non-capital letters (UNIX default)." ) },
+ };
+
+ quicksearchCheckboxes = createCheckBoxGroup( 2, 0, quicksearch, 2 /*count*/, quicksearchGroup, 0, PAGE_OPERATION );
+ quicksearchGrid->addWidget( quicksearchCheckboxes, 0, 0 );
+ connect( quicksearchCheckboxes->find( "New Style Quicksearch" ), SIGNAL( stateChanged( int ) ), this, SLOT( slotDisable() ) );
+ slotDisable();
+
+ lookAndFeelLayout->addWidget( quicksearchGroup, 1, 0 );
+}
+
+// ----------------------------------------------------------------------------------
+// ---------------------------- PANEL TAB -------------------------------------
+// ----------------------------------------------------------------------------------
+void KgLookFeel::setupPanelTab() {
+ QWidget* tab_panel = new QWidget( tabWidget, "tab_panel" );
+ tabWidget->insertTab( tab_panel, i18n( "Panel" ) );
+
+ QGridLayout *panelLayout = new QGridLayout( tab_panel );
+ panelLayout->setSpacing( 6 );
+ panelLayout->setMargin( 11 );
+ QGroupBox *panelGrp = createFrame( i18n( "Panel settings" ), tab_panel, "kgPanelGrp" );
+ QGridLayout *panelGrid = createGridLayout( panelGrp->layout() );
+
+ QHBox *hbox = new QHBox( panelGrp, "lookAndFeelHBox1" );
+ new QLabel( i18n( "Panel font:" ), hbox, "lookAndFeelLabel" );
+ createFontChooser( "Look&Feel", "Filelist Font", _FilelistFont, hbox, true, PAGE_PANEL );
+ createSpacer ( hbox );
+ panelGrid->addWidget( hbox, 0, 0 );
+
+ QHBox *hbox2 = new QHBox( panelGrp, "lookAndFeelHBox2" );
+ QLabel *lbl1 = new QLabel( i18n( "Filelist icon size:" ), hbox2, "lookAndFeelLabel2" );
+ lbl1->setMinimumWidth( 230 );
+ KONFIGURATOR_NAME_VALUE_PAIR iconSizes[] =
+ {{ i18n( "16" ), "16" },
+ { i18n( "22" ), "22" },
+ { i18n( "32" ), "32" },
+ { i18n( "48" ), "48" }};
+ KonfiguratorComboBox *iconCombo = createComboBox( "Look&Feel", "Filelist Icon Size", _FilelistIconSize, iconSizes, 4, hbox2, true, true, PAGE_PANEL );
+ iconCombo->lineEdit()->setValidator( new QRegExpValidator( QRegExp( "[1-9]\\d{0,1}" ), iconCombo ) );
+ createSpacer ( hbox2 );
+ panelGrid->addWidget( hbox2, 1, 0 );
+
+ panelGrid->addWidget( createLine( panelGrp, "lookSep3" ), 2, 0 );
+
+ KONFIGURATOR_CHECKBOX_PARAM panelSettings[] =
+ // cfg_class cfg_name default text restart tooltip
+ {
+ {"Look&Feel","With Icons", _WithIcons, i18n( "Use icons in the filenames" ), true , i18n( "Show the icons for filenames and folders." ) },
+ {"Look&Feel","Human Readable Size", _HumanReadableSize, i18n( "Use human-readable file size" ), true , i18n( "File sizes are displayed in B, KB, MB and GB, not just in bytes." ) },
+ {"Look&Feel","Show Hidden", _ShowHidden, i18n( "Show hidden files" ), false, i18n( "Display files beginning with a dot." ) },
+ {"Look&Feel","Case Sensative Sort", _CaseSensativeSort, i18n( "Case sensitive sorting" ), true , i18n( "All files beginning with capital letters appear before files beginning with non-capital letters (UNIX default)." ) },
+ {"Look&Feel","Always sort dirs by name", false, i18n( "Always sort dirs by name" ), true, i18n( "Directories are sorted by name, regardless of the sort column.") },
+ {"Look&Feel","Numeric permissions", _NumericPermissions, i18n( "Numeric Permissions" ), true, i18n( "Show octal numbers (0755) instead of the standard permissions (rwxr-xr-x) in the permission column.") },
+ };
+
+ KonfiguratorCheckBoxGroup *panelSett = createCheckBoxGroup( 2, 0, panelSettings, 6 /*count*/, panelGrp, 0, PAGE_PANEL );
+
+ panelGrid->addWidget( panelSett, 3, 0 );
+
+// ----------------------------------------------------------------------------------
+// ---------------------------- DEFAULT PANEL TYPE -------------------------------------
+// ----------------------------------------------------------------------------------
+
+ panelGrid->addWidget( createLine( panelGrp, "lookSep4" ), 4, 0 );
+
+ QHBox *hbox3 = new QHBox( panelGrp, "lookAndFeelHBox3" );
+ QLabel *lbl2 = new QLabel( i18n( "Default panel type:" ), hbox3, "lookAndFeelLabel3" );
+ KONFIGURATOR_NAME_VALUE_PAIR panelTypes[] =
+ {{ i18n( "Detailed" ), "Detailed" },
+ { i18n( "Brief" ), "Brief" }};
+ KonfiguratorComboBox *panelCombo = createComboBox( "Look&Feel", "Default Panel Type", _DefaultPanelType, panelTypes, 2, hbox3, false, false, PAGE_PANEL );
+ createSpacer ( hbox3 );
+ panelGrid->addWidget( hbox3, 5, 0 );
+
+ panelLayout->addWidget( panelGrp, 0, 0 );
+}
+
+// -----------------------------------------------------------------------------------
+// -------------------------- Panel Toolbar TAB ----------------------------------
+// -----------------------------------------------------------------------------------
+void KgLookFeel::setupPanelToolbarTab() {
+ QWidget *tab_4 = new QWidget( tabWidget, "tab_4" );
+ tabWidget->insertTab( tab_4, i18n( "Panel Toolbar" ) );
+
+ QBoxLayout * panelToolbarVLayout = new QVBoxLayout( tab_4 );
+ panelToolbarVLayout->setSpacing( 6 );
+ panelToolbarVLayout->setMargin( 11 );
+
+ KONFIGURATOR_CHECKBOX_PARAM panelToolbarActiveCheckbox[] =
+ // cfg_class cfg_name default text restart tooltip
+ {{"Look&Feel", "Panel Toolbar visible", _PanelToolBar, i18n( "Show Panel Toolbar" ), true, i18n( "The panel toolbar will be visible." ) }
+ };
+
+ panelToolbarActive = createCheckBoxGroup( 1, 0, panelToolbarActiveCheckbox, 1, tab_4, "panelToolbarActive", PAGE_PANELTOOLBAR);
+ connect( panelToolbarActive->find( "Panel Toolbar visible" ), SIGNAL( stateChanged( int ) ), this, SLOT( slotEnablePanelToolbar() ) );
+
+ QGroupBox * panelToolbarGrp = createFrame( i18n( "Visible Panel Toolbar buttons" ), tab_4, "panelToolbarGrp");
+ QGridLayout * panelToolbarGrid = createGridLayout( panelToolbarGrp->layout() );
+
+ KONFIGURATOR_CHECKBOX_PARAM panelToolbarCheckboxes[] =
+ {
+ // cfg_class cfg_name default text restart tooltip
+ {"Look&Feel", "Clear Location Bar Visible", _ClearLocation, i18n( "Clear location bar button" ), true , i18n( "Clears the location bar" ) },
+ {"Look&Feel", "Open Button Visible", _Open, i18n( "Open button" ), true , i18n( "Opens the directory browser." ) },
+ {"Look&Feel", "Equal Button Visible", _cdOther, i18n( "Equal button (=)" ),true , i18n( "Changes the panel directory to the other panel directory." ) },
+ {"Look&Feel", "Up Button Visible", _cdUp, i18n( "Up button (..)" ), true , i18n( "Changes the panel directory to the parent directory." ) },
+ {"Look&Feel", "Home Button Visible", _cdHome, i18n( "Home button (~)" ), true , i18n( "Changes the panel directory to the home directory." ) },
+ {"Look&Feel", "Root Button Visible", _cdRoot, i18n( "Root button (/)" ), true , i18n( "Changes the panel directory to the root directory." ) },
+ {"Look&Feel", "SyncBrowse Button Visible", _syncBrowseButton, i18n( "Toggle-button for sync-browsing" ), true , i18n( "Each directory change in the panel is also performed in the other panel." ) },
+ };
+
+
+ pnlcbs = createCheckBoxGroup(1, 0, panelToolbarCheckboxes, 7,
+ panelToolbarGrp, "panelToolbarChecks", PAGE_PANELTOOLBAR);
+
+ panelToolbarVLayout->addWidget( panelToolbarActive, 0, 0 );
+ panelToolbarGrid->addWidget( pnlcbs, 0, 0 );
+ panelToolbarVLayout->addWidget( panelToolbarGrp, 1, 0 );
+
+ // Enable panel toolbar checkboxes
+ slotEnablePanelToolbar();
+}
+
+// ---------------------------------------------------------------------------
+// -------------------------- Mouse TAB ----------------------------------
+// ---------------------------------------------------------------------------
+void KgLookFeel::setupMouseModeTab() {
+ QWidget *tab_mouse = new QWidget( tabWidget, "tab_mouse" );
+ tabWidget->insertTab( tab_mouse, i18n( "Selection Mode" ) );
+ QGridLayout *mouseLayout = new QGridLayout( tab_mouse );
+ mouseLayout->setSpacing( 6 );
+ mouseLayout->setMargin( 11 );
+
+ // -------------- General -----------------
+ QGroupBox *mouseGeneralGroup = createFrame( i18n( "General" ), tab_mouse, "mouseGeneralGroup" );
+ QGridLayout *mouseGeneralGrid = createGridLayout( mouseGeneralGroup->layout() );
+ mouseGeneralGrid->setSpacing( 0 );
+ mouseGeneralGrid->setMargin( 5 );
+
+ KONFIGURATOR_NAME_VALUE_TIP mouseSelection[] =
+ {
+ // name value tooltip
+ { i18n( "Krusader Mode" ), "0", i18n( "Both keys allow selecting files. To select more than one file, hold the Ctrl key and click the left mouse button. Right-click menu is invoked using a short click on the right mouse button." ) },
+ { i18n( "Konqueror Mode" ), "1", i18n( "Pressing the left mouse button selects files - you can click and select multiple files. Right-click menu is invoked using a short click on the right mouse button." ) },
+ { i18n( "Total-Commander Mode" ), "2", i18n( "The left mouse button does not select, but sets the current file without affecting the current selection. The right mouse button selects multiple files and the right-click menu is invoked by pressing and holding the right mouse button." ) },
+ { i18n( "Custom Selection Mode" ), "3", i18n( "Design your own selection mode!" ) }
+ };
+ mouseRadio = createRadioButtonGroup( "Look&Feel", "Mouse Selection", "0", 2, 2, mouseSelection, 4, mouseGeneralGroup, "myLook&FeelRadio", true, PAGE_MOUSE );
+ mouseRadio->layout()->setMargin( 0 );
+ mouseGeneralGrid->addWidget( mouseRadio, 0, 0 );
+ connect( mouseRadio, SIGNAL( clicked(int) ), SLOT( slotSelectionModeChanged() ) );
+
+ mouseLayout->addMultiCellWidget( mouseGeneralGroup, 0,0, 0,1 );
+
+ // -------------- Details -----------------
+ QGroupBox *mouseDetailGroup = createFrame( i18n( "Details" ), tab_mouse, "mouseDetailGroup" );
+ QGridLayout *mouseDetailGrid = createGridLayout( mouseDetailGroup->layout() );
+ mouseDetailGrid->setSpacing( 0 );
+ mouseDetailGrid->setMargin( 5 );
+
+ KONFIGURATOR_NAME_VALUE_TIP singleOrDoubleClick[] =
+ {
+ // name value tooltip
+ { i18n( "Double-click selects (classic)" ), "0", i18n( "A single click on a file will select and focus, a double click opens the file or steps into the directory." ) },
+ { i18n( "Obey KDE's global selection policy" ), "1", i18n( "<p>Use KDE's global setting:</p><p><i>KDE Control Center -> Peripherals -> Mouse</i></p>" ) }
+ };
+ KonfiguratorRadioButtons *clickRadio = createRadioButtonGroup( "Look&Feel", "Single Click Selects", "0", 1, 0, singleOrDoubleClick, 2, mouseDetailGroup, "myLook&FeelRadio0", true, PAGE_MOUSE );
+ clickRadio->layout()->setMargin( 0 );
+ mouseDetailGrid->addWidget( clickRadio, 0, 0 );
+
+ KONFIGURATOR_CHECKBOX_PARAM mouseCheckboxesParam[] =
+ {
+ // {cfg_class, cfg_name, default
+ // text, restart,
+ // tooltip }
+ {"Custom Selection Mode", "QT Selection", _QtSelection,
+ i18n( "Based on KDE's selection mode" ), true,
+ i18n( "If checked, use a mode based on KDE's style." ) },
+ {"Custom Selection Mode", "Left Selects", _LeftSelects,
+ i18n( "Left mouse button selects" ), true,
+ i18n( "If checked, left clicking an item will select it." ) },
+ {"Custom Selection Mode", "Left Preserves", _LeftPreserves,
+ i18n( "Left mouse button preserves selection" ), true,
+ i18n( "If checked, left clicking an item will select it, but will not unselect other, already selected items." ) },
+ {"Custom Selection Mode", "ShiftCtrl Left Selects", _ShiftCtrlLeft,
+ i18n( "Shift/Ctrl-Left mouse button selects" ), true,
+ i18n( "If checked, shift/ctrl left clicking will select items. \nNote: This is meaningless if 'Left Button Selects' is checked." ) },
+ {"Custom Selection Mode", "Right Selects", _RightSelects,
+ i18n( "Right mouse button selects" ), true,
+ i18n( "If checked, right clicking an item will select it." ) },
+ {"Custom Selection Mode", "Right Preserves", _RightPreserves,
+ i18n( "Right mouse button preserves selection" ), true,
+ i18n( "If checked, right clicking an item will select it, but will not unselect other, already selected items." ) },
+ {"Custom Selection Mode", "ShiftCtrl Right Selects", _ShiftCtrlRight,
+ i18n( "Shift/Ctrl-Right mouse button selects" ), true,
+ i18n( "If checked, shift/ctrl right clicking will select items. \nNote: This is meaningless if 'Right Button Selects' is checked." ) },
+ {"Custom Selection Mode", "Space Moves Down", _SpaceMovesDown,
+ i18n( "Spacebar moves down" ), true,
+ i18n( "If checked, pressing the spacebar will select the current item and move down. \nOtherwise, current item is selected, but remains the current item." ) },
+ {"Custom Selection Mode", "Space Calc Space", _SpaceCalcSpace,
+ i18n( "Spacebar calculates disk space" ), true,
+ i18n( "If checked, pressing the spacebar while the current item is a folder, will (except from selecting the folder) \ncalculate space occupied by the folder (recursively)." ) },
+ {"Custom Selection Mode", "Insert Moves Down", _InsertMovesDown,
+ i18n( "Insert moves down" ), true,
+ i18n( "If checked, pressing INSERT will select the current item, and move down to the next item. \nOtherwise, current item is not changed." ) },
+ {"Custom Selection Mode", "Immediate Context Menu", _ImmediateContextMenu,
+ i18n( "Right clicking pops context menu immediately" ), true,
+ i18n( "If checked, right clicking will result in an immediate showing of the context menu. \nOtherwise, user needs to click and hold the right mouse button for 500ms." ) },
+ };
+
+
+ mouseCheckboxes = createCheckBoxGroup(1, 0, mouseCheckboxesParam, 11 /*count*/, mouseDetailGroup, "customMouseModeChecks", PAGE_MOUSE);
+ mouseDetailGrid->addWidget( mouseCheckboxes, 1, 0 );
+
+ mouseLayout->addWidget( mouseDetailGroup, 1,0 );
+
+ // Disable the details-button if not in custom-mode
+ slotSelectionModeChanged();
+
+ // -------------- Preview -----------------
+ QGroupBox *mousePreviewGroup = createFrame( i18n( "Preview" ), tab_mouse, "mousePreviewGroup" );
+ QGridLayout *mousePreviewGrid = createGridLayout( mousePreviewGroup->layout() );
+ // TODO preview
+ mousePreview = new QListView( mousePreviewGroup, "mousePreview" );
+ mousePreviewGrid->addWidget( mousePreview, 0 ,0 );
+ mousePreviewGroup->setEnabled(false); // TODO re-enable once the preview is implemented
+ // ------------------------------------------
+ mouseLayout->addWidget( mousePreviewGroup, 1,1 );
+}
+
+void KgLookFeel::slotDisable()
+{
+ bool isNewStyleQuickSearch = quicksearchCheckboxes->find( "New Style Quicksearch" )->isChecked();
+ quicksearchCheckboxes->find( "Case Sensitive Quicksearch" )->setEnabled( isNewStyleQuickSearch );
+}
+
+void KgLookFeel::slotEnablePanelToolbar()
+{
+ bool enableTB = panelToolbarActive->find("Panel Toolbar visible")->isChecked();
+ pnlcbs->find( "Root Button Visible" )->setEnabled(enableTB);
+ pnlcbs->find( "Home Button Visible" )->setEnabled(enableTB);
+ pnlcbs->find( "Up Button Visible" )->setEnabled(enableTB);
+ pnlcbs->find( "Equal Button Visible" )->setEnabled(enableTB);
+ pnlcbs->find( "Open Button Visible" )->setEnabled(enableTB);
+ pnlcbs->find("SyncBrowse Button Visible")->setEnabled(enableTB);
+}
+
+void KgLookFeel::slotSelectionModeChanged() {
+ bool enable = mouseRadio->find( i18n("Custom Selection Mode") )->isChecked();
+ mouseCheckboxes->find( "QT Selection" )->setEnabled( enable );
+ mouseCheckboxes->find( "Left Selects" )->setEnabled( enable );
+ mouseCheckboxes->find( "Left Preserves" )->setEnabled( enable );
+ mouseCheckboxes->find( "ShiftCtrl Left Selects" )->setEnabled( enable );
+ mouseCheckboxes->find( "Right Selects" )->setEnabled( enable );
+ mouseCheckboxes->find( "Right Preserves" )->setEnabled( enable );
+ mouseCheckboxes->find( "ShiftCtrl Right Selects" )->setEnabled( enable );
+ mouseCheckboxes->find( "Space Moves Down" )->setEnabled( enable );
+ mouseCheckboxes->find( "Space Calc Space" )->setEnabled( enable );
+ mouseCheckboxes->find( "Insert Moves Down" )->setEnabled( enable );
+ mouseCheckboxes->find( "Immediate Context Menu" )->setEnabled( enable );
+}
+
+int KgLookFeel::activeSubPage() {
+ return tabWidget->currentPageIndex();
+}
+
+#include "kglookfeel.moc"
+
diff --git a/krusader/Konfigurator/kglookfeel.h b/krusader/Konfigurator/kglookfeel.h
new file mode 100644
index 0000000..c78e6d5
--- /dev/null
+++ b/krusader/Konfigurator/kglookfeel.h
@@ -0,0 +1,69 @@
+/***************************************************************************
+ kglookfeel.h - description
+ -------------------
+ copyright : (C) 2003 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __KGLOOKFEEL_H__
+#define __KGLOOKFEEL_H__
+
+#include "konfiguratorpage.h"
+
+class QListView;
+
+class KgLookFeel : public KonfiguratorPage
+{
+ Q_OBJECT
+
+public:
+ KgLookFeel( bool first, QWidget* parent=0, const char* name=0 );
+
+ virtual int activeSubPage();
+
+protected:
+ KonfiguratorCheckBoxGroup *cbs;
+ KonfiguratorCheckBoxGroup* quicksearchCheckboxes;
+ KonfiguratorCheckBoxGroup *pnlcbs;
+ KonfiguratorCheckBoxGroup *panelToolbarActive;
+ KonfiguratorRadioButtons *mouseRadio;
+ KonfiguratorCheckBoxGroup *mouseCheckboxes;
+ QListView* mousePreview;
+
+protected slots:
+ void slotDisable();
+ void slotEnablePanelToolbar();
+ void slotSelectionModeChanged();
+
+private:
+ void setupOperationTab();
+ void setupPanelTab();
+ void setupPanelToolbarTab();
+ void setupMouseModeTab();
+ QTabWidget *tabWidget;
+};
+
+#endif /* __KGLOOKFEEL_H__ */
diff --git a/krusader/Konfigurator/kgprotocols.cpp b/krusader/Konfigurator/kgprotocols.cpp
new file mode 100644
index 0000000..11f6357
--- /dev/null
+++ b/krusader/Konfigurator/kgprotocols.cpp
@@ -0,0 +1,418 @@
+/***************************************************************************
+ KgProtocols.cpp - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "kgprotocols.h"
+#include "../krusader.h"
+#include "../krservices.h"
+#include <klocale.h>
+#include <kprotocolinfo.h>
+#include <kmimetype.h>
+#include <qvbox.h>
+#include <qheader.h>
+#include <kiconloader.h>
+#include <qwhatsthis.h>
+
+QString KgProtocols::defaultProtocols = "krarc,iso,tar";
+QString KgProtocols::defaultIsoMimes = "application/x-iso";
+QString KgProtocols::defaultKrarcMimes = "application/x-7z,application/x-7z-compressed,"
+ "application/x-ace,application/x-ace-compressed,"
+ "application/x-arj,application/x-arj-compressed,"
+ "application/x-bzip2,"
+ "application/x-cpio,application/x-deb,"
+ "application/x-debian-package,"
+ "application/x-gzip,application/x-jar,"
+ "application/x-lha,application/x-lha-compressed,"
+ "application/x-rar,application/x-rar-compressed,"
+ "application/x-rpm,"
+ "application/x-zip,application/x-zip-compressed";
+QString KgProtocols::defaultTarMimes = "application/x-tar,application/x-tarz,"
+ "application/x-compressed-tar,"
+ "application/x-tbz,application/x-tgz";
+
+KgProtocols::KgProtocols( bool first, QWidget* parent, const char* name ) :
+ KonfiguratorPage( first, parent, name )
+{
+ QGridLayout *KgProtocolsLayout = new QGridLayout( parent );
+ KgProtocolsLayout->setSpacing( 6 );
+
+ // -------------------------- LINK VIEW ----------------------------------
+
+ QGroupBox *linkGrp = createFrame( i18n( "Links" ), parent, "linkGrp" );
+ QGridLayout *linkGrid = createGridLayout( linkGrp->layout() );
+
+ linkList = new QListView( linkGrp, "linkList" );
+ linkList->addColumn( i18n( "Defined Links" ) );
+ linkList->header()->setStretchEnabled( true, 0 );
+ linkList->setRootIsDecorated( true );
+
+ linkGrid->addWidget( linkList, 0, 0 );
+ KgProtocolsLayout->addMultiCellWidget( linkGrp, 0 ,1, 0, 0 );
+
+ // -------------------------- BUTTONS ----------------------------------
+
+ QVBox *vbox1 = new QVBox( parent, "vbox1" ) ;
+
+ addSpacer( vbox1 );
+ btnAddProtocol = new QPushButton( vbox1, "btnAddProtocolButton" );
+ btnAddProtocol->setPixmap( krLoader->loadIcon( "1leftarrow", KIcon::Small ) );
+ QWhatsThis::add( btnAddProtocol, i18n( "Add protocol to the link list." ) );
+ btnRemoveProtocol = new QPushButton( vbox1, "btnRemoveProtocolButton" );
+ btnRemoveProtocol->setPixmap( krLoader->loadIcon( "1rightarrow", KIcon::Small ) );
+ QWhatsThis::add( btnRemoveProtocol, i18n( "Remove protocol from the link list." ) );
+ addSpacer( vbox1 );
+
+ KgProtocolsLayout->addWidget( vbox1, 0 ,1 );
+
+ QVBox *vbox2 = new QVBox( parent, "vbox2" ) ;
+
+ addSpacer( vbox2 );
+ btnAddMime = new QPushButton( vbox2, "btnAddMimeButton" );
+ btnAddMime->setPixmap( krLoader->loadIcon( "1leftarrow", KIcon::Small ) );
+ QWhatsThis::add( btnAddMime, i18n( "Add mime to the selected protocol on the link list." ) );
+ btnRemoveMime = new QPushButton( vbox2, "btnRemoveMimeButton" );
+ btnRemoveMime->setPixmap( krLoader->loadIcon( "1rightarrow", KIcon::Small ) );
+ QWhatsThis::add( btnRemoveMime, i18n( "Remove mime from the link list." ) );
+ addSpacer( vbox2 );
+
+ KgProtocolsLayout->addWidget( vbox2, 1 ,1 );
+
+ // -------------------------- PROTOCOLS LISTBOX ----------------------------------
+
+ QGroupBox *protocolGrp = createFrame( i18n( "Protocols" ), parent, "protocolGrp" );
+ QGridLayout *protocolGrid = createGridLayout( protocolGrp->layout() );
+
+ protocolList = new QListBox( protocolGrp, "protocolList" );
+ loadListCapableProtocols();
+ protocolGrid->addWidget( protocolList, 0, 0 );
+
+ KgProtocolsLayout->addWidget( protocolGrp, 0 ,2 );
+
+ // -------------------------- MIMES LISTBOX ----------------------------------
+
+ QGroupBox *mimeGrp = createFrame( i18n( "Mimes" ), parent, "mimeGrp" );
+ QGridLayout *mimeGrid = createGridLayout( mimeGrp->layout() );
+
+ mimeList = new QListBox( mimeGrp, "protocolList" );
+ loadMimes();
+ mimeGrid->addWidget( mimeList, 0, 0 );
+
+ KgProtocolsLayout->addWidget( mimeGrp, 1 ,2 );
+
+ // -------------------------- CONNECT TABLE ----------------------------------
+
+ connect( protocolList, SIGNAL( selectionChanged() ), this, SLOT( slotDisableButtons() ) );
+ connect( linkList, SIGNAL( selectionChanged() ), this, SLOT( slotDisableButtons() ) );
+ connect( mimeList, SIGNAL( selectionChanged() ), this, SLOT( slotDisableButtons() ) );
+ connect( linkList, SIGNAL( currentChanged( QListViewItem *) ), this, SLOT( slotDisableButtons() ) );
+ connect( btnAddProtocol, SIGNAL( clicked() ) , this, SLOT( slotAddProtocol() ) );
+ connect( btnRemoveProtocol, SIGNAL( clicked() ) , this, SLOT( slotRemoveProtocol() ) );
+ connect( btnAddMime, SIGNAL( clicked() ) , this, SLOT( slotAddMime() ) );
+ connect( btnRemoveMime, SIGNAL( clicked() ) , this, SLOT( slotRemoveMime() ) );
+
+ loadInitialValues();
+ slotDisableButtons();
+}
+
+QWidget* KgProtocols::addSpacer( QWidget *parent, const char *widgetName )
+{
+ QWidget *widget = new QWidget( parent, widgetName );
+ QVBoxLayout *vboxlayout = new QVBoxLayout( widget );
+ QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ vboxlayout->addItem( spacer );
+ return widget;
+}
+
+void KgProtocols::loadListCapableProtocols()
+{
+ QStringList protocols = KProtocolInfo::protocols();
+ protocols.sort();
+
+ for ( QStringList::Iterator it = protocols.begin(); it != protocols.end();)
+ {
+ if( !KProtocolInfo::supportsListing( *it ) )
+ {
+ it = protocols.remove( it );
+ continue;
+ }
+ ++it;
+ }
+ protocolList->insertStringList( protocols );
+}
+
+void KgProtocols::loadMimes()
+{
+ KMimeType::List mimes = KMimeType::allMimeTypes();
+
+ for( QValueListIterator<KMimeType::Ptr> it = mimes.begin(); it != mimes.end(); it++ )
+ mimeList->insertItem( (*it)->name() );
+
+ mimeList->sort();
+}
+
+void KgProtocols::slotDisableButtons()
+{
+ btnAddProtocol->setEnabled( protocolList->selectedItem() != 0 );
+ QListViewItem *listViewItem = linkList->currentItem();
+ bool isProtocolSelected = ( listViewItem == 0 ? false : listViewItem->parent() == 0 );
+ btnRemoveProtocol->setEnabled( isProtocolSelected );
+ btnAddMime->setEnabled( listViewItem != 0 && mimeList->selectedItem() != 0 );
+ btnRemoveMime->setEnabled( listViewItem == 0 ? false : listViewItem->parent() != 0 );
+
+ if( linkList->currentItem() == 0 && linkList->firstChild() != 0 )
+ linkList->setCurrentItem( linkList->firstChild() );
+ if( linkList->selectedItem() == 0 && linkList->currentItem() != 0 )
+ linkList->setSelected( linkList->currentItem(), true );
+}
+
+void KgProtocols::slotAddProtocol()
+{
+ QListBoxItem *item = protocolList->selectedItem();
+ if( item )
+ {
+ addProtocol( item->text(), true );
+ slotDisableButtons();
+ emit sigChanged();
+ }
+}
+
+void KgProtocols::addProtocol( QString name, bool changeCurrent )
+{
+ QListBoxItem *item = protocolList->findItem( name, ExactMatch );
+ if( item )
+ {
+ protocolList->removeItem( protocolList->index( item ) );
+ QListViewItem *listViewItem = new QListViewItem( linkList, name );
+ listViewItem->setPixmap( 0, krLoader->loadIcon( "exec", KIcon::Small ) );
+
+ if( changeCurrent )
+ linkList->setCurrentItem( listViewItem );
+ }
+}
+
+void KgProtocols::slotRemoveProtocol()
+{
+ QListViewItem *item = linkList->currentItem();
+ if( item )
+ {
+ removeProtocol( item->text( 0 ) );
+ slotDisableButtons();
+ emit sigChanged();
+ }
+}
+
+void KgProtocols::removeProtocol( QString name )
+{
+ QListViewItem *item = linkList->findItem( name, 0 );
+ if( item )
+ {
+ while( item->childCount() != 0 )
+ removeMime( item->firstChild()->text( 0 ) );
+
+ linkList->takeItem( item );
+ protocolList->insertItem( name );
+ protocolList->sort();
+ }
+}
+
+void KgProtocols::slotAddMime()
+{
+ QListBoxItem *item = mimeList->selectedItem();
+ if( item && linkList->currentItem() != 0 )
+ {
+ QListViewItem *itemToAdd = linkList->currentItem();
+ if( itemToAdd->parent() )
+ itemToAdd = itemToAdd->parent();
+
+ addMime( item->text(), itemToAdd->text( 0 ) );
+ slotDisableButtons();
+ emit sigChanged();
+ }
+}
+
+void KgProtocols::addMime( QString name, QString protocol )
+{
+ QListBoxItem *item = mimeList->findItem( name, ExactMatch );
+ QListViewItem *currentListItem = linkList->findItem( protocol, 0 );
+
+ if( item && currentListItem && currentListItem->parent() == 0 )
+ {
+ mimeList->removeItem( mimeList->index( item ) );
+ QListViewItem *listViewItem = new QListViewItem( currentListItem, name );
+ listViewItem->setPixmap( 0, krLoader->loadIcon( "mime", KIcon::Small ) );
+ currentListItem->setOpen( true );
+ }
+}
+
+void KgProtocols::slotRemoveMime()
+{
+ QListViewItem *item = linkList->currentItem();
+ if( item )
+ {
+ removeMime( item->text( 0 ) );
+ slotDisableButtons();
+ emit sigChanged();
+ }
+}
+
+void KgProtocols::removeMime( QString name )
+{
+ QListViewItem *currentMimeItem = linkList->findItem( name, 0 );
+
+ if( currentMimeItem && currentMimeItem->parent() != 0 )
+ {
+ mimeList->insertItem( currentMimeItem->text( 0 ) );
+ mimeList->sort();
+ currentMimeItem->parent()->takeItem( currentMimeItem );
+ }
+}
+
+void KgProtocols::loadInitialValues()
+{
+ while( linkList->childCount() != 0 )
+ removeProtocol( linkList->firstChild()->text( 0 ) );
+
+ krConfig->setGroup( "Protocols" );
+ QStringList protList = krConfig->readListEntry( "Handled Protocols" );
+
+ for( QStringList::Iterator it = protList.begin(); it != protList.end(); it++ )
+ {
+ addProtocol( *it );
+
+ QStringList mimes = krConfig->readListEntry( QString( "Mimes For %1" ).arg( *it ) );
+
+ for( QStringList::Iterator it2 = mimes.begin(); it2 != mimes.end(); it2++ )
+ addMime( *it2, *it );
+ }
+
+ if( linkList->firstChild() != 0 )
+ linkList->setCurrentItem( linkList->firstChild() );
+ slotDisableButtons();
+}
+
+void KgProtocols::setDefaults()
+{
+ while( linkList->childCount() != 0 )
+ removeProtocol( linkList->firstChild()->text( 0 ) );
+
+ addProtocol( "iso" );
+ addMime( "application/x-iso", "iso" );
+
+ addProtocol( "krarc" );
+ QStringList krarcMimes = QStringList::split( ',', defaultKrarcMimes );
+ for( QStringList::Iterator it = krarcMimes.begin(); it != krarcMimes.end(); it++ )
+ addMime( *it, "krarc" );
+
+ addProtocol( "tar" );
+ QStringList tarMimes = QStringList::split( ',', defaultTarMimes );
+ for( QStringList::Iterator it = tarMimes.begin(); it != tarMimes.end(); it++ )
+ addMime( *it, "tar" );
+
+ slotDisableButtons();
+
+ if( isChanged() )
+ emit sigChanged();
+}
+
+bool KgProtocols::isChanged()
+{
+ krConfig->setGroup( "Protocols" );
+ QStringList protList = krConfig->readListEntry( "Handled Protocols" );
+
+ if( (int)protList.count() != linkList->childCount() )
+ return true;
+
+ QListViewItem *item = linkList->firstChild();
+ while( item )
+ {
+ if( !protList.contains( item->text( 0 ) ) )
+ return true;
+
+ QStringList mimes = krConfig->readListEntry( QString( "Mimes For %1" ).arg( item->text( 0 ) ) );
+
+ if( (int)mimes.count() != item->childCount() )
+ return true;
+ QListViewItem *childs = item->firstChild();
+ while( childs )
+ {
+ if( !mimes.contains( childs->text( 0 ) ) )
+ return true;
+ childs = childs->nextSibling();
+ }
+
+ item = item->nextSibling();
+ }
+
+ return false;
+}
+
+bool KgProtocols::apply()
+{
+ krConfig->setGroup( "Protocols" );
+
+ QStringList protocolList;
+
+ QListViewItem *item = linkList->firstChild();
+ while( item )
+ {
+ protocolList.append( item->text( 0 ) );
+
+ QStringList mimes;
+ QListViewItem *childs = item->firstChild();
+ while( childs )
+ {
+ mimes.append( childs->text( 0 ) );
+ childs = childs->nextSibling();
+ }
+ krConfig->writeEntry( QString( "Mimes For %1" ).arg( item->text( 0 ) ), mimes );
+
+ item = item->nextSibling();
+ }
+ krConfig->writeEntry( "Handled Protocols", protocolList );
+ krConfig->sync();
+
+ KrServices::clearProtocolCache();
+
+ emit sigChanged();
+ return false;
+}
+
+void KgProtocols::init()
+{
+ if( !krConfig->groupList().contains( "Protocols" ) )
+ {
+ krConfig->setGroup( "Protocols" );
+ krConfig->writeEntry( "Handled Protocols", defaultProtocols );
+ krConfig->writeEntry( "Mimes For iso", defaultIsoMimes );
+ krConfig->writeEntry( "Mimes For krarc", defaultKrarcMimes );
+ krConfig->writeEntry( "Mimes For tar", defaultTarMimes );
+ }
+}
+
+#include "kgprotocols.moc"
diff --git a/krusader/Konfigurator/kgprotocols.h b/krusader/Konfigurator/kgprotocols.h
new file mode 100644
index 0000000..64a177d
--- /dev/null
+++ b/krusader/Konfigurator/kgprotocols.h
@@ -0,0 +1,86 @@
+/***************************************************************************
+ KgProtocols.h - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __KgProtocols_H__
+#define __KgProtocols_H__
+
+#include "konfiguratorpage.h"
+#include <qlistbox.h>
+#include <qpushbutton.h>
+#include <qlistview.h>
+
+class KgProtocols : public KonfiguratorPage
+{
+ Q_OBJECT
+
+public:
+ KgProtocols( bool first, QWidget* parent=0, const char* name=0 );
+
+ virtual void loadInitialValues();
+ virtual void setDefaults();
+ virtual bool apply();
+ virtual bool isChanged();
+
+ static void init();
+
+public slots:
+ void slotDisableButtons();
+ void slotAddProtocol();
+ void slotRemoveProtocol();
+ void slotAddMime();
+ void slotRemoveMime();
+
+protected:
+ void loadListCapableProtocols();
+ void loadMimes();
+ QWidget* addSpacer( QWidget *parent, const char *widgetName = 0);
+
+ void addProtocol( QString name, bool changeCurrent = false );
+ void removeProtocol( QString name );
+ void addMime( QString name, QString protocol );
+ void removeMime( QString name );
+
+ QListView *linkList;
+
+ QListBox *protocolList;
+ QListBox *mimeList;
+
+ QPushButton *btnAddProtocol;
+ QPushButton *btnRemoveProtocol;
+ QPushButton *btnAddMime;
+ QPushButton *btnRemoveMime;
+
+ static QString defaultProtocols;
+ static QString defaultIsoMimes;
+ static QString defaultKrarcMimes;
+ static QString defaultTarMimes;
+};
+
+#endif /* __KgProtocols_H__ */
diff --git a/krusader/Konfigurator/kgstartup.cpp b/krusader/Konfigurator/kgstartup.cpp
new file mode 100644
index 0000000..b02e321
--- /dev/null
+++ b/krusader/Konfigurator/kgstartup.cpp
@@ -0,0 +1,117 @@
+/***************************************************************************
+ kgstartup.cpp - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "kgstartup.h"
+#include "../defaults.h"
+#include "../GUI/profilemanager.h"
+#include "../krusader.h"
+#include <klocale.h>
+#include <klineedit.h>
+#include <qwhatsthis.h>
+
+KgStartup::KgStartup( bool first, QWidget* parent, const char* name ) :
+ KonfiguratorPage( first, parent, name ), profileCombo( 0 )
+{
+ QGridLayout *kgStartupLayout = new QGridLayout( parent );
+ kgStartupLayout->setSpacing( 6 );
+
+ // --------------------------- PANELS GROUPBOX ----------------------------------
+
+ QGroupBox *panelsGrp = createFrame( i18n( "General" ), parent, "panelsGrp" );
+ QGridLayout *panelsGrid = createGridLayout( panelsGrp->layout() );
+
+ QString s = "<p><img src='toolbar|kr_profile'></p>" + i18n( "Defines the panel profile used at startup. A panel profile contains:<ul><li>all the tabs paths</li><li>the current tab</li><li>the active panel</li></ul><b>&lt;Last session&gt;</b> is a special panel profile which is saved automatically when Krusader is closed.");
+ QLabel *label = addLabel( panelsGrid, 0, 0, i18n( "Startup profile:" ), panelsGrp, "Startup session" );
+ QWhatsThis::add( label, s );
+ QWhatsThis::add( panelsGrp, s );
+
+ QStringList profileList = ProfileManager::availableProfiles( "Panel" );
+ profileList.push_front( "<" + i18n( "Last session" ) + ">" );
+
+ KONFIGURATOR_NAME_VALUE_PAIR comboItems[ profileList.count() ];
+ for(unsigned int i=0; i != profileList.count(); i++ )
+ comboItems[ i ].text = comboItems[ i ].value = profileList [ i ];
+ comboItems[ 0 ].value = "";
+
+ profileCombo = createComboBox( "Startup", "Starter Profile Name", comboItems[ 0 ].value, comboItems, profileList.count(), panelsGrp, false, false );
+ profileCombo->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed);
+ panelsGrid->addWidget( profileCombo, 0, 1 );
+
+ //------------------------------------------------
+ panelsGrid->addMultiCellWidget( createLine( panelsGrp, "lookSep3" ), 1, 1, 0, 1 );
+
+ KONFIGURATOR_CHECKBOX_PARAM settings[] =
+ { // cfg_class cfg_name default text restart tooltip
+ {"Look&Feel","Show splashscreen", _ShowSplashScreen, i18n( "Show splashscreen" ), false, i18n( "Display a splashscreen when starting krusader.") },
+ {"Look&Feel","Single Instance Mode", _SingleInstanceMode, i18n( "Single instance mode" ), false, i18n( "Only one Krusader instance is allowed to run.") }
+ };
+
+ KonfiguratorCheckBoxGroup* cbs = createCheckBoxGroup( 2, 0, settings, 2 /* settings count */, panelsGrp );
+ panelsGrid->addMultiCellWidget( cbs, 2, 2, 0, 1 );
+
+ kgStartupLayout->addWidget( panelsGrp, 0, 0 );
+
+ // ------------------------ USERINTERFACE GROUPBOX ------------------------------
+
+ QGroupBox *uiGrp = createFrame( i18n( "User Interface" ), parent, "uiGrp" );
+ QGridLayout *uiGrid = createGridLayout( uiGrp->layout() );
+
+ KONFIGURATOR_CHECKBOX_PARAM uiCheckBoxes[] =
+ { // cfg_class cfg_name default text restart ToolTip
+ {"Startup","UI Save Settings", _UiSave, i18n( "Save settings on exit" ), false, i18n( "Check the state of the user interface components and restore them to their condition when last shutdown." ) },
+ {"Startup","Show tool bar", _ShowToolBar, i18n( "Show toolbar" ), false, i18n( "Toolbar will be visible after startup." ) },
+ {"Startup","Show status bar", _ShowStatusBar, i18n( "Show statusbar" ), false, i18n( "Statusbar will be visible after startup." ) },
+ {"Startup","Show FN Keys", _ShowFNkeys, i18n( "Show function keys" ), false, i18n( "Function keys will be visible after startup." ) },
+ {"Startup","Show Cmd Line", _ShowCmdline, i18n( "Show command line" ), false, i18n( "Command line will be visible after startup." ) },
+ {"Startup","Show Terminal Emulator",_ShowTerminalEmulator, i18n( "Show terminal emulator" ), false, i18n( "Terminal emulator will be visible after startup." ) },
+ {"Startup","Remember Position", _RememberPos, i18n( "Save last position, size and panel settings" ), false, i18n( "<p>At startup, the main window will resize itself to the size it was when last shutdown. It will also appear in the same location of the screen, having panels sorted and aligned as they were before.</p><p>If this option is disabled, you can use the menu <i>Window -> Save Position</i> option to manually set the main window's size and position at startup.</p>" ) },
+ {"Startup","Start To Tray", _StartToTray, i18n( "Start to tray" ), false, i18n( "Krusader starts to tray (if minimize to tray is set), without showing the main window" ) },
+ };
+
+ uiCbGroup = createCheckBoxGroup( 2, 0, uiCheckBoxes, 8, uiGrp );
+ connect( uiCbGroup->find( "UI Save Settings" ), SIGNAL( stateChanged( int ) ), this, SLOT( slotDisable() ) );
+
+ uiGrid->addWidget( uiCbGroup, 1, 0 );
+
+ slotDisable();
+
+ kgStartupLayout->addWidget( uiGrp, 1, 0 );
+}
+
+void KgStartup::slotDisable()
+{
+ bool isUiSave = !uiCbGroup->find( "UI Save Settings" )->isChecked();
+
+ int i=1;
+ while( uiCbGroup->find( i ) )
+ uiCbGroup->find( i++ )->setEnabled( isUiSave );
+}
+
+#include "kgstartup.moc"
diff --git a/krusader/Konfigurator/kgstartup.h b/krusader/Konfigurator/kgstartup.h
new file mode 100644
index 0000000..38f05a0
--- /dev/null
+++ b/krusader/Konfigurator/kgstartup.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ kgstartup.h - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __KGSTARTUP_H__
+#define __KGSTARTUP_H__
+
+#include "konfiguratorpage.h"
+
+class KgStartup : public KonfiguratorPage
+{
+ Q_OBJECT
+
+public:
+ KgStartup( bool first, QWidget* parent=0, const char* name=0 );
+
+public slots:
+ void slotDisable();
+
+protected:
+ KonfiguratorRadioButtons *saveRadio;
+ KonfiguratorCheckBoxGroup *uiCbGroup;
+ KonfiguratorComboBox *profileCombo;
+};
+
+#endif /* __KGSTARTUP_H__ */
diff --git a/krusader/Konfigurator/kguseractions.cpp b/krusader/Konfigurator/kguseractions.cpp
new file mode 100644
index 0000000..5488c2e
--- /dev/null
+++ b/krusader/Konfigurator/kguseractions.cpp
@@ -0,0 +1,106 @@
+/***************************************************************************
+ kguseractions.cpp - description
+ -------------------
+ copyright : (C) 2004 by Jonas B�r
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "kguseractions.h"
+#include "../defaults.h"
+#include "../krusader.h"
+#include "../ActionMan/actionman.h"
+
+#include <klocale.h>
+#include <kpushbutton.h>
+#include <kdebug.h>
+
+
+KgUserActions::KgUserActions( bool first, QWidget* parent, const char* name ) :
+ KonfiguratorPage( first, parent, name )
+{
+ QGridLayout *kgUserActionLayout = new QGridLayout( parent, 2, 1,
+ 0 /* margin */, 6 /* spacing */, "kgUserActionLayout" );
+
+ // ============= Info Group =============
+ QGroupBox *InfoGroup = createFrame( i18n( "Information" ), parent, "kgUserActionInfoGroup" );
+ QGridLayout *InfoGrid = createGridLayout( InfoGroup->layout() );
+
+ // terminal for the UserActions
+ QLabel *labelInfo = new QLabel( i18n(
+ "Here you can configure settings about useractions.\n"
+ "To set up, configure and manage your useractions please use ActionMan."
+ ), InfoGroup, "InformationLabel" );
+ InfoGrid->addWidget( labelInfo, 0, 0 );
+ KPushButton *actionmanButton = new KPushButton( i18n("Start ActionMan"), InfoGroup, "actionmanButton");
+ connect( actionmanButton, SIGNAL( clicked() ), SLOT( startActionMan() ) );
+ InfoGrid->addWidget( actionmanButton, 1, 0 );
+
+ kgUserActionLayout->addWidget( InfoGroup, 0 ,0 );
+
+ // ============= Terminal Group =============
+ QGroupBox *terminalGroup = createFrame( i18n( "Terminal execution" ), parent, "kgUserActionTerminalGroup" );
+ QGridLayout *terminalGrid = createGridLayout( terminalGroup->layout() );
+
+ // terminal for the UserActions
+ QLabel *labelTerminal = new QLabel( i18n( "Terminal for UserActions:" ),
+ terminalGroup, "TerminalLabel" );
+ terminalGrid->addWidget( labelTerminal, 0, 0 );
+ KonfiguratorURLRequester *urlReqUserActions = createURLRequester( "UserActions",
+ "Terminal", _UserActions_Terminal, terminalGroup, false );
+ terminalGrid->addWidget( urlReqUserActions, 0, 1 );
+
+ kgUserActionLayout->addWidget( terminalGroup, 1 ,0 );
+
+ // ============= Outputcollection Group =============
+ QGroupBox *outputGroup = createFrame( i18n( "Output collection" ), parent, "kgUserActionOutputGroup" );
+ QGridLayout *outputGrid = createGridLayout( outputGroup->layout() );
+
+ QHBox *hbox;
+ hbox = new QHBox( outputGroup, "HBoxNormalFont" );
+ new QLabel( i18n( "Normal font:" ), hbox, "NormalFontLabel" );
+ createFontChooser( "UserActions", "Normal Font", _UserActions_NormalFont, hbox );
+ createSpacer ( hbox );
+ outputGrid->addWidget( hbox, 2, 0 );
+
+ hbox = new QHBox( outputGroup, "HBoxFixedFont" );
+ new QLabel( i18n( "Font with fixed width:" ), hbox, "FixedFontLabel" );
+ createFontChooser( "UserActions", "Fixed Font", _UserActions_FixedFont, hbox );
+ createSpacer ( hbox );
+ outputGrid->addWidget( hbox, 3, 0 );
+
+ KonfiguratorCheckBox *useFixed = createCheckBox( "UserActions", "Use Fixed Font", _UserActions_UseFixedFont,
+ i18n("Use fixed width font as default"), outputGroup );
+ outputGrid->addWidget( useFixed, 4, 0 );
+
+ kgUserActionLayout->addWidget( outputGroup, 2 ,0 );
+}
+
+void KgUserActions::startActionMan() {
+ ActionMan actionMan( static_cast<QWidget*>(parent()) );
+}
+
+
+#include "kguseractions.moc"
diff --git a/krusader/Konfigurator/kguseractions.h b/krusader/Konfigurator/kguseractions.h
new file mode 100644
index 0000000..2515c84
--- /dev/null
+++ b/krusader/Konfigurator/kguseractions.h
@@ -0,0 +1,51 @@
+/***************************************************************************
+ kguseractions.h - description
+ -------------------
+ copyright : (C) 2004 by Jonas B�r
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __KGUSERACTIONS_H__
+#define __KGUSERACTIONS_H__
+
+#include "konfiguratorpage.h"
+
+class KPushButton;
+class ActionProperty;
+class UserActionListView;
+
+class KgUserActions : public KonfiguratorPage
+{
+ Q_OBJECT
+
+public:
+ KgUserActions( bool first, QWidget* parent=0, const char* name=0 );
+
+public slots:
+ void startActionMan();
+};
+
+#endif /* __KGUSERACTIONS_H__ */
diff --git a/krusader/Konfigurator/kgwelcome.cpp b/krusader/Konfigurator/kgwelcome.cpp
new file mode 100644
index 0000000..ee9a82e
--- /dev/null
+++ b/krusader/Konfigurator/kgwelcome.cpp
@@ -0,0 +1,50 @@
+/***************************************************************************
+ kgwelcome.cpp - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "kgwelcome.h"
+#include <kstandarddirs.h>
+
+KgWelcome::KgWelcome( bool first, QWidget* parent, const char* name ) :
+ KonfiguratorPage( first, parent, name )
+{
+ QGridLayout *kgWelcomeLayout = new QGridLayout( parent );
+ kgWelcomeLayout->setSpacing( 6 );
+
+ QString pix=KGlobal::dirs()->findResource("appdata","konfig_small.jpg");
+ QPixmap image0( pix );
+
+ QLabel *pixmapLabel = new QLabel( parent, "pixmapLabel" );
+ pixmapLabel->setPixmap( image0 );
+ pixmapLabel->setScaledContents( TRUE );
+
+ kgWelcomeLayout->addWidget( pixmapLabel, 0, 0 );
+}
+
+#include "kgwelcome.moc"
diff --git a/krusader/Konfigurator/kgwelcome.h b/krusader/Konfigurator/kgwelcome.h
new file mode 100644
index 0000000..92e1811
--- /dev/null
+++ b/krusader/Konfigurator/kgwelcome.h
@@ -0,0 +1,44 @@
+/***************************************************************************
+ kgwelcome.h - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __KGWELCOME_H__
+#define __KGWELCOME_H__
+
+#include "konfiguratorpage.h"
+
+class KgWelcome : public KonfiguratorPage
+{
+ Q_OBJECT
+
+public:
+ KgWelcome( bool first, QWidget* parent=0, const char* name=0 );
+};
+
+#endif /* __KGWELCOME_H__ */
diff --git a/krusader/Konfigurator/konfigurator.cpp b/krusader/Konfigurator/konfigurator.cpp
new file mode 100644
index 0000000..3467425
--- /dev/null
+++ b/krusader/Konfigurator/konfigurator.cpp
@@ -0,0 +1,220 @@
+/***************************************************************************
+ konfigurator.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+
+#include "konfigurator.h"
+#include "../krusader.h"
+#include "../Dialogs/krdialogs.h"
+#include "../kicons.h"
+
+#include <kfiledialog.h>
+#include <qwidget.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kstandarddirs.h>
+#include <kmessagebox.h>
+#include "../defaults.h"
+#include "../krusaderview.h"
+#include "../GUI/kfnkeys.h"
+
+// the frames
+#include "kgwelcome.h"
+#include "kgstartup.h"
+#include "kglookfeel.h"
+#include "kggeneral.h"
+#include "kgadvanced.h"
+#include "kgarchives.h"
+#include "kgdependencies.h"
+#include "kgcolors.h"
+#include "kguseractions.h"
+#include "kgprotocols.h"
+
+Konfigurator::Konfigurator( bool f, int startPage ) : KDialogBase(0,0,true,"Konfigurator",
+ KDialogBase::Help | KDialogBase::User1 | KDialogBase::Apply | KDialogBase::Cancel,
+ KDialogBase::User1, false, i18n("Defaults") ), firstTime(f), internalCall( false ),
+ restartGUI( false )
+{
+ setPlainCaption(i18n("Konfigurator - Creating Your Own Krusader"));
+ kgFrames.setAutoDelete(true);
+ widget=new KJanusWidget(this,0,KJanusWidget::IconList);
+
+ setButtonCancel(i18n("Close"));
+
+ setHelp("konfigurator");
+
+ connect( widget, SIGNAL( aboutToShowPage(QWidget *) ), this, SLOT( slotPageSwitch() ) );
+ connect( &restoreTimer, SIGNAL(timeout()), this, SLOT(slotRestorePage()));
+
+ createLayout( startPage );
+ setMainWidget(widget);
+ exec();
+}
+
+void Konfigurator::newContent(KonfiguratorPage *page)
+{
+ kgFrames.append(page);
+ connect( page, SIGNAL( sigChanged() ), this, SLOT( slotApplyEnable() ) );
+}
+
+void Konfigurator::createLayout( int startPage )
+{
+ // startup
+ newContent(new KgStartup(firstTime, widget->addPage(i18n("Startup"),
+ i18n("Krusader's settings upon startup"),QPixmap(krLoader->loadIcon("kfm_home",
+ KIcon::Desktop,32)))));
+ // look n' feel
+ newContent(new KgLookFeel(firstTime, widget->addPage(i18n("Look & Feel"),
+ i18n("Look & Feel"),QPixmap(krLoader->loadIcon("looknfeel",KIcon::Desktop,32)))));
+ // colors
+ newContent(new KgColors(firstTime, widget->addPage(i18n("Colors"),
+ i18n("Colors"),QPixmap(krLoader->loadIcon("colors",KIcon::Desktop,32)))));
+ // general
+ newContent(new KgGeneral(firstTime, widget->addPage(i18n("General"),
+ i18n("Basic Operations"),QPixmap(krLoader->loadIcon("configure",KIcon::Desktop,32)))));
+ // advanced
+ newContent(new KgAdvanced(firstTime, widget->addPage(i18n("Advanced"),
+ i18n("Be sure you know what you're doing!"),
+ QPixmap(krLoader->loadIcon("messagebox_warning",KIcon::Desktop,32)))));
+ // archives
+ newContent(new KgArchives(firstTime, widget->addPage(i18n("Archives"),i18n("Customize the way Krusader deals with archives"),
+ QPixmap(krLoader->loadIcon("tgz",KIcon::Desktop,32)))));
+ // dependencies
+ newContent(new KgDependencies(firstTime, widget->addPage(i18n("Dependencies"),i18n("Set the full path of the external applications"),
+ QPixmap(krLoader->loadIcon("kr_dependencies",KIcon::Desktop,32)))));
+ // useractions
+ newContent(new KgUserActions(firstTime, widget->addPage(i18n("User Actions"),i18n("Configure your personal actions"),
+ QPixmap(krLoader->loadIcon("kr_useractions",KIcon::Desktop,32)))));
+ // protocols
+ newContent(new KgProtocols(firstTime, widget->addPage(i18n("Protocols"),
+ i18n("Link mimes to protocols"), QPixmap(krLoader->loadIcon("about_kde",KIcon::Desktop,32)))));
+
+ widget->showPage( widget->pageIndex( kgFrames.at( startPage )->parentWidget() ) );
+ slotApplyEnable();
+}
+
+void Konfigurator::slotUser1()
+{
+ int ndx = searchPage( lastPage = widget->activePageIndex() );
+ kgFrames.at( ndx )->setDefaults();
+}
+#include <kdebug.h>
+void Konfigurator::slotApply()
+{
+ int ndx = searchPage( lastPage = widget->activePageIndex() );
+ if( kgFrames.at( ndx )->apply() )
+ {
+ restartGUI = true;
+// KMessageBox::information(this,i18n("Changes to the GUI will be updated next time you run Krusader."),
+// QString::null,"konfigGUInotify");
+ }
+
+ // really ugly, but reload the Fn keys just in case - csaba: any better idea?
+ krApp->mainView->fnKeys->updateShortcuts();
+}
+
+void Konfigurator::slotCancel()
+{
+ lastPage = widget->activePageIndex();
+ if( slotPageSwitch() )
+ reject();
+}
+
+int Konfigurator::searchPage( int pageNum )
+{
+ KonfiguratorPage *page;
+ int i=0;
+
+ while( ( page = kgFrames.at( i ) ) )
+ {
+ if( pageNum == widget->pageIndex( page->parentWidget() ) )
+ return i;
+
+ i++;
+ }
+
+ return 0;
+}
+
+void Konfigurator::slotApplyEnable()
+{
+ int ndx = searchPage( lastPage = widget->activePageIndex() );
+ enableButtonApply( kgFrames.at( ndx )->isChanged() );
+}
+
+bool Konfigurator::slotPageSwitch()
+{
+ int ndx = searchPage( lastPage );
+ KonfiguratorPage *currentPage = kgFrames.at( ndx );
+
+ if( internalCall )
+ {
+ internalCall = false;
+ return true;
+ }
+
+ if( currentPage->isChanged() )
+ {
+ int result = KMessageBox::questionYesNoCancel( 0, i18n("The current page has been changed. Do you want to apply changes?" ));
+
+ switch( result )
+ {
+ case KMessageBox::No:
+ currentPage->loadInitialValues();
+ break;
+ case KMessageBox::Yes:
+ if( currentPage->apply() )
+ {
+ restartGUI = true;
+// KMessageBox::information(this,i18n("Changes to the GUI will be updated next time you run Krusader."),
+// QString::null,"konfigGUInotify");
+ }
+ break;
+ default:
+ restoreTimer.start( 0, true );
+ return false;
+ }
+ }
+
+ enableButtonApply( currentPage->isChanged() );
+ lastPage = widget->activePageIndex();
+ return true;
+}
+
+void Konfigurator::slotRestorePage()
+{
+ if( lastPage != widget->activePageIndex() )
+ {
+ internalCall = true;
+ widget->showPage( lastPage );
+ }
+}
+
+#include "konfigurator.moc"
diff --git a/krusader/Konfigurator/konfigurator.h b/krusader/Konfigurator/konfigurator.h
new file mode 100644
index 0000000..3058244
--- /dev/null
+++ b/krusader/Konfigurator/konfigurator.h
@@ -0,0 +1,81 @@
+/***************************************************************************
+ konfigurator.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KONFIGURATOR_H
+#define KONFIGURATOR_H
+
+#include "konfiguratorpage.h"
+#include <qwidget.h>
+#include <kdialogbase.h>
+#include <kjanuswidget.h>
+#include <qtimer.h>
+
+class QLineEdit;
+class QString;
+
+class Konfigurator : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ Konfigurator( bool f=false, int startPage = 0 ); // true if Konfigurator is run for the first time
+ ~Konfigurator() {};
+
+ bool isGUIRestartNeeded() { return restartGUI; }
+
+protected:
+ void newContent(KonfiguratorPage *widget);// adds widget into newPage and connects to slot
+ void createLayout( int startPage );
+
+protected slots:
+ void slotUser1();
+ void slotApply(); // actually used for defaults
+ void slotCancel();
+ void slotApplyEnable();
+ bool slotPageSwitch();
+ void slotRestorePage();
+
+private:
+ int searchPage( int pageNum );
+
+private:
+ QPtrList<KonfiguratorPage> kgFrames;
+ KJanusWidget *widget;
+ bool firstTime;
+ int lastPage;
+ bool internalCall;
+ QTimer restoreTimer;
+ bool restartGUI;
+};
+
+#endif
+
diff --git a/krusader/Konfigurator/konfiguratoritems.cpp b/krusader/Konfigurator/konfiguratoritems.cpp
new file mode 100644
index 0000000..17b9fcc
--- /dev/null
+++ b/krusader/Konfigurator/konfiguratoritems.cpp
@@ -0,0 +1,815 @@
+/***************************************************************************
+ konfiguratoritems.cpp - description
+ -------------------
+ copyright : (C) 2003 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "konfiguratoritems.h"
+#include "../krusader.h"
+#include <klocale.h>
+#include <qpainter.h>
+#include <qpen.h>
+#include <qcolordialog.h>
+#include <kiconloader.h>
+
+KonfiguratorExtension::KonfiguratorExtension( QObject *obj, QString cfgClass, QString cfgName, bool rst, int pg) :
+ QObject(), objectPtr( obj ), applyConnected( false ), setDefaultsConnected( false ),
+ changed( false ), restartNeeded( rst ), subpage(pg), configClass( cfgClass ), configName( cfgName )
+{
+}
+
+void KonfiguratorExtension::connectNotify( const char *signal )
+{
+ QString signalString = QString( signal ).replace( " ", "" );
+ QString applyString = QString( SIGNAL( applyManually(QObject *,QString, QString) ) ).replace( " ", "" );
+ QString defaultsString = QString( SIGNAL( setDefaultsManually(QObject *) ) ).replace( " ", "" );
+
+ if( signalString == applyString )
+ applyConnected = true;
+ else if ( signalString == defaultsString )
+ setDefaultsConnected = true;
+
+ QObject::connectNotify( signal );
+}
+
+bool KonfiguratorExtension::apply()
+{
+ if( !changed )
+ return false;
+
+ if( applyConnected )
+ emit applyManually( objectPtr, configClass, configName );
+ else
+ emit applyAuto( objectPtr, configClass, configName );
+
+ setChanged( false );
+ return restartNeeded;
+}
+
+void KonfiguratorExtension::setDefaults()
+{
+ if( setDefaultsConnected )
+ emit setDefaultsManually( objectPtr );
+ else
+ emit setDefaultsAuto( objectPtr );
+}
+
+void KonfiguratorExtension::loadInitialValue()
+{
+ emit setInitialValue( objectPtr );
+}
+
+bool KonfiguratorExtension::isChanged()
+{
+ return changed;
+}
+
+// KonfiguratorCheckBox class
+///////////////////////////////
+
+KonfiguratorCheckBox::KonfiguratorCheckBox( QString cls, QString name, bool dflt, QString text,
+ QWidget *parent, const char *widgetName, bool rst, int pg ) : QCheckBox( text, parent, widgetName ),
+ defaultValue( dflt )
+{
+ ext = new KonfiguratorExtension( this, cls, name, rst, pg );
+ connect( ext, SIGNAL( applyAuto(QObject *,QString, QString) ), this, SLOT( slotApply(QObject *,QString, QString) ) );
+ connect( ext, SIGNAL( setDefaultsAuto(QObject *) ), this, SLOT( slotSetDefaults(QObject *) ) );
+ connect( ext, SIGNAL( setInitialValue(QObject *) ), this, SLOT( loadInitialValue() ) );
+
+ connect( this, SIGNAL( stateChanged( int ) ), ext, SLOT( setChanged() ) );
+ loadInitialValue();
+}
+
+KonfiguratorCheckBox::~KonfiguratorCheckBox()
+{
+ delete ext;
+}
+
+void KonfiguratorCheckBox::loadInitialValue()
+{
+ krConfig->setGroup( ext->getCfgClass() );
+ setChecked( krConfig->readBoolEntry( ext->getCfgName(), defaultValue ) );
+ ext->setChanged( false );
+}
+
+void KonfiguratorCheckBox::slotApply(QObject *,QString cls, QString name)
+{
+ krConfig->setGroup( cls );
+ krConfig->writeEntry( name, isChecked() );
+}
+
+void KonfiguratorCheckBox::slotSetDefaults(QObject *)
+{
+ if( isChecked() != defaultValue )
+ setChecked( defaultValue );
+}
+
+// KonfiguratorSpinBox class
+///////////////////////////////
+
+KonfiguratorSpinBox::KonfiguratorSpinBox( QString cls, QString name, int dflt, int min, int max,
+ QWidget *parent, const char *widgetName, bool rst, int pg ) : QSpinBox( parent, widgetName ),
+ defaultValue( dflt )
+{
+ ext = new KonfiguratorExtension( this, cls, name, rst, pg );
+ connect( ext, SIGNAL( applyAuto(QObject *,QString, QString) ), this, SLOT( slotApply(QObject *,QString, QString) ) );
+ connect( ext, SIGNAL( setDefaultsAuto(QObject *) ), this, SLOT( slotSetDefaults(QObject *) ) );
+ connect( ext, SIGNAL( setInitialValue(QObject *) ), this, SLOT( loadInitialValue() ) );
+
+ connect( this, SIGNAL( valueChanged(int) ), ext, SLOT( setChanged() ) );
+
+ setMinValue( min );
+ setMaxValue( max );
+
+ loadInitialValue();
+}
+
+KonfiguratorSpinBox::~KonfiguratorSpinBox()
+{
+ delete ext;
+}
+
+void KonfiguratorSpinBox::loadInitialValue()
+{
+ krConfig->setGroup( ext->getCfgClass() );
+ setValue( krConfig->readNumEntry( ext->getCfgName(), defaultValue ) );
+ ext->setChanged( false );
+}
+
+void KonfiguratorSpinBox::slotApply(QObject *,QString cls, QString name)
+{
+ krConfig->setGroup( cls );
+ krConfig->writeEntry( name, value() );
+}
+
+void KonfiguratorSpinBox::slotSetDefaults(QObject *)
+{
+ if( value() != defaultValue )
+ setValue( defaultValue );
+}
+
+// KonfiguratorCheckBoxGroup class
+///////////////////////////////
+
+void KonfiguratorCheckBoxGroup::add( KonfiguratorCheckBox *checkBox )
+{
+ checkBoxList.append( checkBox );
+}
+
+KonfiguratorCheckBox * KonfiguratorCheckBoxGroup::find( int index )
+{
+ return checkBoxList.at( index );
+}
+
+KonfiguratorCheckBox * KonfiguratorCheckBoxGroup::find( QString name )
+{
+ KonfiguratorCheckBox *checkBox = checkBoxList.first();
+
+ while( checkBox )
+ {
+ if( checkBox->extension()->getCfgName() == name )
+ return checkBox;
+ checkBox = checkBoxList.next();
+ }
+
+ return 0;
+}
+
+
+// KonfiguratorRadioButtons class
+///////////////////////////////
+
+KonfiguratorRadioButtons::KonfiguratorRadioButtons( QString cls, QString name,
+ QString dflt, QWidget *parent, const char *widgetName, bool rst, int pg ) :
+ QButtonGroup( parent, widgetName ), defaultValue( dflt )
+{
+ ext = new KonfiguratorExtension( this, cls, name, rst, pg );
+ connect( ext, SIGNAL( applyAuto(QObject *,QString, QString) ), this, SLOT( slotApply(QObject *,QString, QString) ) );
+ connect( ext, SIGNAL( setDefaultsAuto(QObject *) ), this, SLOT( slotSetDefaults(QObject *) ) );
+ connect( ext, SIGNAL( setInitialValue(QObject *) ), this, SLOT( loadInitialValue() ) );
+}
+
+KonfiguratorRadioButtons::~KonfiguratorRadioButtons()
+{
+ delete ext;
+}
+
+void KonfiguratorRadioButtons::addRadioButton( QRadioButton *radioWidget, QString name, QString value )
+{
+ radioButtons.append( radioWidget );
+ radioNames.push_back( name );
+ radioValues.push_back( value );
+
+ connect( radioWidget, SIGNAL( stateChanged(int) ), ext, SLOT( setChanged() ) );
+}
+
+QRadioButton * KonfiguratorRadioButtons::find( int index )
+{
+ return radioButtons.at( index );
+}
+
+QRadioButton * KonfiguratorRadioButtons::find( QString name )
+{
+ int index = radioNames.findIndex( name );
+ if( index == -1 )
+ return 0;
+
+ return radioButtons.at( index );
+}
+
+void KonfiguratorRadioButtons::selectButton( QString value )
+{
+ int cnt = 0;
+ QRadioButton *btn = radioButtons.first();
+
+ while( btn )
+ {
+ if( value == radioValues[ cnt ] )
+ {
+ btn->setChecked( true );
+ return;
+ }
+
+ btn = radioButtons.next();
+ cnt++;
+ }
+
+ if( radioButtons.first() )
+ radioButtons.first()->setChecked( true );
+}
+
+void KonfiguratorRadioButtons::loadInitialValue()
+{
+ krConfig->setGroup( ext->getCfgClass() );
+ QString initValue = krConfig->readEntry( ext->getCfgName(), defaultValue );
+
+ selectButton( initValue );
+ ext->setChanged( false );
+}
+
+void KonfiguratorRadioButtons::slotApply(QObject *,QString cls, QString name)
+{
+ QRadioButton *btn = radioButtons.first();
+ int cnt = 0;
+
+ while( btn )
+ {
+ if( btn->isChecked() )
+ {
+ krConfig->setGroup( cls );
+ krConfig->writeEntry( name, radioValues[ cnt ] );
+ break;
+ }
+
+ btn = radioButtons.next();
+ cnt++;
+ }
+}
+
+void KonfiguratorRadioButtons::slotSetDefaults(QObject *)
+{
+ selectButton( defaultValue );
+}
+
+// KonfiguratorEditBox class
+///////////////////////////////
+
+KonfiguratorEditBox::KonfiguratorEditBox( QString cls, QString name, QString dflt,
+ QWidget *parent, const char *widgetName, bool rst, int pg ) : QLineEdit( parent, widgetName ),
+ defaultValue( dflt )
+{
+ ext = new KonfiguratorExtension( this, cls, name, rst, pg );
+ connect( ext, SIGNAL( applyAuto(QObject *,QString, QString) ), this, SLOT( slotApply(QObject *,QString, QString) ) );
+ connect( ext, SIGNAL( setDefaultsAuto(QObject *) ), this, SLOT( slotSetDefaults(QObject *) ) );
+ connect( ext, SIGNAL( setInitialValue(QObject *) ), this, SLOT( loadInitialValue() ) );
+
+ connect( this, SIGNAL( textChanged(const QString &) ), ext, SLOT( setChanged() ) );
+
+ loadInitialValue();
+}
+
+KonfiguratorEditBox::~KonfiguratorEditBox()
+{
+ delete ext;
+}
+
+void KonfiguratorEditBox::loadInitialValue()
+{
+ krConfig->setGroup( ext->getCfgClass() );
+ setText( krConfig->readEntry( ext->getCfgName(), defaultValue ) );
+ ext->setChanged( false );
+}
+
+void KonfiguratorEditBox::slotApply(QObject *,QString cls, QString name)
+{
+ krConfig->setGroup( cls );
+ krConfig->writeEntry( name, text() );
+}
+
+void KonfiguratorEditBox::slotSetDefaults(QObject *)
+{
+ if( text() != defaultValue )
+ setText( defaultValue );
+}
+
+
+// KonfiguratorURLRequester class
+///////////////////////////////
+
+KonfiguratorURLRequester::KonfiguratorURLRequester( QString cls, QString name, QString dflt,
+ QWidget *parent, const char *widgetName, bool rst, int pg ) : KURLRequester( parent, widgetName ),
+ defaultValue( dflt )
+{
+ ext = new KonfiguratorExtension( this, cls, name, rst, pg );
+ connect( ext, SIGNAL( applyAuto(QObject *,QString, QString) ), this, SLOT( slotApply(QObject *,QString, QString) ) );
+ connect( ext, SIGNAL( setDefaultsAuto(QObject *) ), this, SLOT( slotSetDefaults(QObject *) ) );
+ connect( ext, SIGNAL( setInitialValue(QObject *) ), this, SLOT( loadInitialValue() ) );
+
+ connect( this, SIGNAL( textChanged(const QString &) ), ext, SLOT( setChanged() ) );
+
+ button()->setIconSet( SmallIcon( "fileopen" ) );
+ loadInitialValue();
+}
+
+KonfiguratorURLRequester::~KonfiguratorURLRequester()
+{
+ delete ext;
+}
+
+void KonfiguratorURLRequester::loadInitialValue()
+{
+ krConfig->setGroup( ext->getCfgClass() );
+ setURL( krConfig->readEntry( ext->getCfgName(), defaultValue ) );
+ ext->setChanged( false );
+}
+
+void KonfiguratorURLRequester::slotApply(QObject *,QString cls, QString name)
+{
+ krConfig->setGroup( cls );
+ krConfig->writeEntry( name, url() );
+}
+
+void KonfiguratorURLRequester::slotSetDefaults(QObject *)
+{
+ if( url() != defaultValue )
+ setURL( defaultValue );
+}
+
+// KonfiguratorFontChooser class
+///////////////////////////////
+
+KonfiguratorFontChooser::KonfiguratorFontChooser( QString cls, QString name, QFont *dflt,
+ QWidget *parent, const char *widgetName, bool rst, int pg ) : QHBox ( parent, widgetName ),
+ defaultValue( dflt )
+{
+ ext = new KonfiguratorExtension( this, cls, name, rst, pg );
+ connect( ext, SIGNAL( applyAuto(QObject *,QString, QString) ), this, SLOT( slotApply(QObject *,QString, QString) ) );
+ connect( ext, SIGNAL( setDefaultsAuto(QObject *) ), this, SLOT( slotSetDefaults(QObject *) ) );
+ connect( ext, SIGNAL( setInitialValue(QObject *) ), this, SLOT( loadInitialValue() ) );
+
+ pLabel = new QLabel( this );
+ pLabel->setMinimumWidth( 150 );
+ pToolButton = new QToolButton( this );
+
+ connect( pToolButton, SIGNAL( clicked() ), this, SLOT( slotBrowseFont() ) );
+
+ pToolButton->setIconSet( SmallIcon( "fileopen" ) );
+
+ loadInitialValue();
+}
+
+KonfiguratorFontChooser::~KonfiguratorFontChooser()
+{
+ delete ext;
+}
+
+void KonfiguratorFontChooser::loadInitialValue()
+{
+ krConfig->setGroup( ext->getCfgClass() );
+ font = krConfig->readFontEntry( ext->getCfgName(), defaultValue );
+ ext->setChanged( false );
+ setFont();
+}
+
+void KonfiguratorFontChooser::setFont()
+{
+ pLabel->setFont( font );
+ pLabel->setText( font.family()+QString(", %1").arg(font.pointSize()) );
+}
+
+void KonfiguratorFontChooser::slotApply(QObject *,QString cls, QString name)
+{
+ krConfig->setGroup( cls );
+ krConfig->writeEntry( name, font );
+}
+
+void KonfiguratorFontChooser::slotSetDefaults(QObject *)
+{
+ font = *defaultValue;
+ ext->setChanged();
+ setFont();
+}
+
+void KonfiguratorFontChooser::slotBrowseFont()
+{
+ int ok=KFontDialog::getFont( font );
+ if (ok!=1) return; // cancelled by the user
+ ext->setChanged();
+ setFont();
+}
+
+// KonfiguratorComboBox class
+///////////////////////////////
+
+KonfiguratorComboBox::KonfiguratorComboBox( QString cls, QString name, QString dflt,
+ KONFIGURATOR_NAME_VALUE_PAIR *listIn, int listInLen, QWidget *parent,
+ const char *widgetName, bool rst, bool editable, int pg ) : QComboBox ( parent, widgetName ),
+ defaultValue( dflt ), listLen( listInLen )
+{
+ list = new KONFIGURATOR_NAME_VALUE_PAIR[ listInLen ];
+
+ for( int i=0; i != listLen; i++ )
+ {
+ list[i] = listIn[i];
+ insertItem( list[i].text );
+ }
+
+ ext = new KonfiguratorExtension( this, cls, name, rst, pg );
+ connect( ext, SIGNAL( applyAuto(QObject *,QString, QString) ), this, SLOT( slotApply(QObject *,QString, QString) ) );
+ connect( ext, SIGNAL( setDefaultsAuto(QObject *) ), this, SLOT( slotSetDefaults(QObject *) ) );
+ connect( ext, SIGNAL( setInitialValue(QObject *) ), this, SLOT( loadInitialValue() ) );
+
+// connect( this, SIGNAL( highlighted(int) ), ext, SLOT( setChanged() ) ); /* Removed because of startup combo failure */
+ connect( this, SIGNAL( activated(int) ), ext, SLOT( setChanged() ) );
+ connect( this, SIGNAL( textChanged ( const QString & ) ), ext, SLOT( setChanged() ) );
+
+ setEditable( editable );
+ loadInitialValue();
+}
+
+KonfiguratorComboBox::~KonfiguratorComboBox()
+{
+ delete []list;
+ delete ext;
+}
+
+void KonfiguratorComboBox::loadInitialValue()
+{
+ krConfig->setGroup( ext->getCfgClass() );
+ QString select = krConfig->readEntry( ext->getCfgName(), defaultValue );
+ selectEntry( select );
+ ext->setChanged( false );
+}
+
+void KonfiguratorComboBox::slotApply(QObject *,QString cls, QString name)
+{
+ QString text = editable() ? lineEdit()->text() : currentText();
+ QString value = text;
+
+ for( int i=0; i != listLen; i++ )
+ if( list[i].text == text ) {
+ value = list[i].value;
+ break;
+ }
+
+ krConfig->setGroup( cls );
+ krConfig->writeEntry( name, value );
+}
+
+void KonfiguratorComboBox::selectEntry( QString entry )
+{
+ for( int i=0; i != listLen; i++ )
+ if( list[i].value == entry )
+ {
+ setCurrentItem( i );
+ return;
+ }
+
+ if( editable() )
+ lineEdit()->setText( entry );
+ else
+ setCurrentItem( 0 );
+}
+
+void KonfiguratorComboBox::slotSetDefaults(QObject *)
+{
+ selectEntry( defaultValue );
+}
+
+
+// KonfiguratorColorChooser class
+///////////////////////////////
+
+KonfiguratorColorChooser::KonfiguratorColorChooser( QString cls, QString name, QColor dflt,
+ QWidget *parent, const char *widgetName, bool rst, ADDITIONAL_COLOR *addColPtr,
+ int addColNum, int pg ) : QComboBox ( parent, widgetName ),
+ defaultValue( dflt ), disableColorChooser( true )
+{
+ ext = new KonfiguratorExtension( this, cls, name, rst, pg );
+
+ connect( ext, SIGNAL( applyAuto(QObject *,QString, QString) ), this, SLOT( slotApply(QObject *,QString, QString) ) );
+ connect( ext, SIGNAL( setDefaultsAuto(QObject *) ), this, SLOT( slotSetDefaults(QObject *) ) );
+ connect( ext, SIGNAL( setInitialValue(QObject *) ), this, SLOT( loadInitialValue() ) );
+
+ addColor( i18n("Custom color" ), QColor( 255, 255, 255 ) );
+ addColor( i18n("Default" ), defaultValue );
+
+ for( int i=0; i != addColNum; i++ )
+ {
+ additionalColors.push_back( addColPtr[i] );
+ addColor( addColPtr[i].name, addColPtr[i].color );
+ }
+
+ addColor( i18n("Red" ), Qt::red );
+ addColor( i18n("Green" ), Qt::green );
+ addColor( i18n("Blue" ), Qt::blue );
+ addColor( i18n("Cyan" ), Qt::cyan );
+ addColor( i18n("Magenta" ), Qt::magenta );
+ addColor( i18n("Yellow" ), Qt::yellow );
+ addColor( i18n("Dark Red" ), Qt::darkRed );
+ addColor( i18n("Dark Green" ), Qt::darkGreen );
+ addColor( i18n("Dark Blue" ), Qt::darkBlue );
+ addColor( i18n("Dark Cyan" ), Qt::darkCyan );
+ addColor( i18n("Dark Magenta" ), Qt::darkMagenta );
+ addColor( i18n("Dark Yellow" ), Qt::darkYellow );
+ addColor( i18n("White" ), Qt::white );
+ addColor( i18n("Light Gray" ), Qt::lightGray );
+ addColor( i18n("Gray" ), Qt::gray );
+ addColor( i18n("Dark Gray" ), Qt::darkGray );
+ addColor( i18n("Black" ), Qt::black );
+
+ connect( this, SIGNAL( activated(int) ), this, SLOT( slotCurrentChanged( int ) ) );
+
+ loadInitialValue();
+}
+
+KonfiguratorColorChooser::~KonfiguratorColorChooser()
+{
+ delete ext;
+}
+
+QPixmap KonfiguratorColorChooser::createPixmap( QColor color )
+{
+ QPainter painter;
+ QPen pen;
+ int size = QFontMetrics(font()).height()*3/4;
+ QRect rect( 0, 0, size, size );
+ QPixmap pixmap( rect.width(), rect.height() );
+
+ pen.setColor( Qt::black );
+
+ painter.begin( &pixmap );
+ QBrush brush( color );
+ painter.fillRect( rect, brush );
+ painter.setPen( pen );
+ painter.drawRect( rect );
+ painter.end();
+
+ pixmap.detach();
+ return pixmap;
+}
+
+void KonfiguratorColorChooser::addColor( QString text, QColor color )
+{
+ insertItem( createPixmap(color), text );
+ palette.push_back( color );
+}
+
+void KonfiguratorColorChooser::loadInitialValue()
+{
+ krConfig->setGroup( ext->getCfgClass() );
+ QString selected = krConfig->readEntry( ext->getCfgName(), "" );
+ setValue( selected );
+ ext->setChanged( false );
+}
+
+void KonfiguratorColorChooser::setDefaultColor( QColor dflt )
+{
+ defaultValue = dflt;
+ palette[1] = defaultValue;
+ changeItem( createPixmap( defaultValue ), text( 1 ), 1 );
+
+ if( currentItem() == 1 )
+ emit colorChanged();
+}
+
+void KonfiguratorColorChooser::changeAdditionalColor( unsigned int num, QColor color )
+{
+ if( num < additionalColors.size() )
+ {
+ palette[2+num] = color;
+ additionalColors[num].color = color;
+ changeItem( createPixmap( color ), text( 2+num ), 2+num );
+
+ if( (unsigned int)currentItem() == 2+num )
+ emit colorChanged();
+ }
+}
+
+void KonfiguratorColorChooser::setDefaultText( QString text )
+{
+ changeItem( createPixmap( defaultValue ), text, 1 );
+}
+
+void KonfiguratorColorChooser::slotApply(QObject *,QString cls, QString name)
+{
+ krConfig->setGroup( cls );
+ krConfig->writeEntry( name, getValue() );
+}
+
+void KonfiguratorColorChooser::setValue( QString value )
+{
+ disableColorChooser = true;
+
+ if( value.isEmpty() )
+ {
+ setCurrentItem( 1 );
+ customValue = defaultValue;
+ }
+ else
+ {
+ bool found = false;
+
+ for( unsigned j=0; j != additionalColors.size(); j++ )
+ if( additionalColors[j].value == value )
+ {
+ setCurrentItem( 2 + j );
+ found = true;
+ break;
+ }
+
+ if( ! found )
+ {
+ krConfig->setGroup( ext->getCfgClass() );
+ krConfig->writeEntry( "TmpColor", value );
+ QColor color = krConfig->readColorEntry( "TmpColor", &defaultValue );
+ customValue = color;
+ krConfig->deleteEntry( "TmpColor" );
+
+ setCurrentItem( 0 );
+ for( unsigned i= 2+additionalColors.size(); i != palette.size(); i++ )
+ if( palette[i] == color )
+ {
+ setCurrentItem( i );
+ break;
+ }
+ }
+ }
+
+ palette[0] = customValue;
+ changeItem( createPixmap( customValue ), text( 0 ), 0 );
+
+ ext->setChanged();
+ emit colorChanged();
+ disableColorChooser = false;
+}
+
+QString KonfiguratorColorChooser::getValue()
+{
+ QColor color = palette[ currentItem() ];
+ if( currentItem() == 1 ) /* it's the default value? */
+ return "";
+ else if( currentItem() >= 2 && (unsigned)currentItem() < 2 + additionalColors.size() )
+ return additionalColors[ currentItem() - 2 ].value;
+ else
+ return QString( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
+}
+
+bool KonfiguratorColorChooser::isValueRGB()
+{
+ return !( currentItem() >= 1 && (unsigned)currentItem() < 2 + additionalColors.size() );
+}
+
+void KonfiguratorColorChooser::slotSetDefaults(QObject *)
+{
+ ext->setChanged();
+ setCurrentItem( 1 );
+ emit colorChanged();
+}
+
+void KonfiguratorColorChooser::slotCurrentChanged( int number )
+{
+ ext->setChanged();
+ if( number == 0 && !disableColorChooser )
+ {
+ QColor color = QColorDialog::getColor ( customValue, this, "ColorDialog" );
+ if( color.isValid() )
+ {
+ disableColorChooser = true;
+ customValue = color;
+ palette[0] = customValue;
+ changeItem( createPixmap( customValue ), text( 0 ), 0 );
+ disableColorChooser = false;
+ }
+ }
+
+ emit colorChanged();
+}
+
+QColor KonfiguratorColorChooser::getColor()
+{
+ return palette[ currentItem() ];
+}
+
+// KonfiguratorListBox class
+///////////////////////////////
+
+KonfiguratorListBox::KonfiguratorListBox( QString cls, QString name, QStringList dflt,
+ QWidget *parent, const char *widgetName, bool rst, int pg ) : QListBox( parent, widgetName ),
+ defaultValue( dflt )
+{
+ ext = new KonfiguratorExtension( this, cls, name, rst, pg );
+ connect( ext, SIGNAL( applyAuto(QObject *,QString, QString) ), this, SLOT( slotApply(QObject *,QString, QString) ) );
+ connect( ext, SIGNAL( setDefaultsAuto(QObject *) ), this, SLOT( slotSetDefaults(QObject *) ) );
+ connect( ext, SIGNAL( setInitialValue(QObject *) ), this, SLOT( loadInitialValue() ) );
+
+ loadInitialValue();
+}
+
+KonfiguratorListBox::~KonfiguratorListBox()
+{
+ delete ext;
+}
+
+void KonfiguratorListBox::loadInitialValue()
+{
+ krConfig->setGroup( ext->getCfgClass() );
+ setList( krConfig->readListEntry( ext->getCfgName().ascii(), defaultValue ) );
+ ext->setChanged( false );
+}
+
+void KonfiguratorListBox::slotApply(QObject *,QString cls, QString name)
+{
+ krConfig->setGroup( cls );
+ krConfig->writeEntry( name, list() );
+}
+
+void KonfiguratorListBox::slotSetDefaults(QObject *)
+{
+ if( list() != defaultValue )
+ {
+ ext->setChanged();
+ setList( defaultValue );
+ }
+}
+
+void KonfiguratorListBox::setList( QStringList list )
+{
+ clear();
+ insertStringList( list );
+}
+
+QStringList KonfiguratorListBox::list()
+{
+ QStringList lst;
+
+ for( unsigned i=0; i != count(); i++ )
+ lst += text( i );
+
+ return lst;
+}
+
+void KonfiguratorListBox::addItem( const QString & item )
+{
+ if( !list().contains( item ) )
+ {
+ insertItem( item );
+ ext->setChanged();
+ }
+}
+
+void KonfiguratorListBox::removeItem( const QString & item )
+{
+ QListBoxItem * listItem = findItem( item );
+ if( listItem != 0 )
+ {
+ takeItem( listItem );
+ ext->setChanged();
+ }
+}
+
+#include "konfiguratoritems.moc"
diff --git a/krusader/Konfigurator/konfiguratoritems.h b/krusader/Konfigurator/konfiguratoritems.h
new file mode 100644
index 0000000..1763401
--- /dev/null
+++ b/krusader/Konfigurator/konfiguratoritems.h
@@ -0,0 +1,418 @@
+/***************************************************************************
+ konfiguratoritems.h - description
+ -------------------
+ copyright : (C) 2003 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __KONFIGURATOR_ITEMS_H__
+#define __KONFIGURATOR_ITEMS_H__
+
+#include <qobject.h>
+#include <qstring.h>
+#include <qcheckbox.h>
+#include <qspinbox.h>
+#include <qpushbutton.h>
+#include <qradiobutton.h>
+#include <qptrlist.h>
+#include <qvaluelist.h>
+#include <qvaluevector.h>
+#include <qbuttongroup.h>
+#include <qlineedit.h>
+#include <kurlrequester.h>
+#include <qhbox.h>
+#include <kfontdialog.h>
+#include <qlabel.h>
+#include <qfont.h>
+#include <qtoolbutton.h>
+#include <qcombobox.h>
+
+#define FIRST_PAGE 0
+
+class KonfiguratorExtension : public QObject
+{
+ Q_OBJECT
+
+public:
+ KonfiguratorExtension(QObject *obj, QString cfgClass, QString cfgName, bool rst = false, int pg=FIRST_PAGE );
+
+ virtual void loadInitialValue();
+ virtual bool apply();
+ virtual void setDefaults();
+ virtual bool isChanged();
+ virtual void setSubPage(int pg) {subpage = pg;}
+ virtual int subPage() {return subpage;}
+
+ inline QObject *object() {return objectPtr;}
+
+ inline QString getCfgClass() {return configClass;}
+ inline QString getCfgName() {return configName;}
+
+public slots:
+ void setChanged() {emit sigChanged( changed = true);}
+ void setChanged( bool chg ) {emit sigChanged( changed = chg);}
+
+signals:
+ void applyManually(QObject *,QString, QString);
+ void applyAuto(QObject *,QString, QString);
+ void setDefaultsManually(QObject *);
+ void setDefaultsAuto(QObject *);
+ void setInitialValue(QObject *);
+ void sigChanged( bool );
+
+protected:
+ QObject *objectPtr;
+
+ bool applyConnected;
+ bool setDefaultsConnected;
+ bool changed;
+ bool restartNeeded;
+ int subpage;
+
+ QString configClass;
+ QString configName;
+
+ virtual void connectNotify( const char *signal );
+};
+
+
+// KonfiguratorCheckBox class
+///////////////////////////////
+
+class KonfiguratorCheckBox : public QCheckBox
+{
+ Q_OBJECT
+
+public:
+ KonfiguratorCheckBox( QString cls, QString name, bool dflt, QString text,
+ QWidget *parent=0, const char *widgetName=0, bool rst=false, int pg=FIRST_PAGE );
+ ~KonfiguratorCheckBox();
+
+ inline KonfiguratorExtension *extension() {return ext;}
+
+public slots:
+ virtual void loadInitialValue();
+ void slotApply(QObject *,QString, QString);
+ void slotSetDefaults(QObject *);
+
+protected:
+ bool defaultValue;
+ KonfiguratorExtension *ext;
+};
+
+// KonfiguratorSpinBox class
+///////////////////////////////
+
+class KonfiguratorSpinBox : public QSpinBox
+{
+ Q_OBJECT
+
+public:
+ KonfiguratorSpinBox( QString cls, QString name, int dflt, int min, int max,
+ QWidget *parent=0, const char *widgetName=0, bool rst=false, int pg=FIRST_PAGE );
+ ~KonfiguratorSpinBox();
+
+ inline KonfiguratorExtension *extension() {return ext;}
+
+public slots:
+ virtual void loadInitialValue();
+ void slotApply(QObject *,QString, QString);
+ void slotSetDefaults(QObject *);
+
+protected:
+ int defaultValue;
+ KonfiguratorExtension *ext;
+};
+
+// KonfiguratorCheckBoxGroup class
+///////////////////////////////
+
+class KonfiguratorCheckBoxGroup : public QWidget
+{
+public:
+ KonfiguratorCheckBoxGroup( QWidget * parent = 0, const char * name = 0 ) :
+ QWidget( parent, name ) {};
+
+ void add( KonfiguratorCheckBox * );
+ KonfiguratorCheckBox * find( int index );
+ KonfiguratorCheckBox * find( QString name );
+
+private:
+ QPtrList<KonfiguratorCheckBox> checkBoxList;
+};
+
+// KonfiguratorRadioButtons class
+///////////////////////////////
+
+class KonfiguratorRadioButtons : public QButtonGroup
+{
+ Q_OBJECT
+
+public:
+ KonfiguratorRadioButtons( QString cls, QString name, QString dflt, QWidget *parent=0,
+ const char *widgetName=0, bool rst=false, int pg=FIRST_PAGE );
+ ~KonfiguratorRadioButtons();
+
+ inline KonfiguratorExtension *extension() {return ext;}
+
+ void addRadioButton( QRadioButton *radioWidget, QString name, QString value );
+
+ void selectButton( QString value );
+
+ QRadioButton* find( int index );
+ QRadioButton* find( QString name );
+
+public slots:
+ virtual void loadInitialValue();
+ void slotApply(QObject *,QString, QString);
+ void slotSetDefaults(QObject *);
+
+protected:
+ QPtrList<QRadioButton> radioButtons;
+ QValueList<QString> radioValues;
+ QValueList<QString> radioNames;
+
+ QString defaultValue;
+ QButtonGroup *buttonGroup;
+
+ KonfiguratorExtension *ext;
+};
+
+// KonfiguratorEditBox class
+///////////////////////////////
+
+class KonfiguratorEditBox : public QLineEdit
+{
+ Q_OBJECT
+
+public:
+ KonfiguratorEditBox( QString cls, QString name, QString dflt, QWidget *parent=0,
+ const char *widgetName=0, bool rst=false, int pg=FIRST_PAGE );
+ ~KonfiguratorEditBox();
+
+ inline KonfiguratorExtension *extension() {return ext;}
+
+public slots:
+ virtual void loadInitialValue();
+ void slotApply(QObject *,QString, QString);
+ void slotSetDefaults(QObject *);
+
+protected:
+ QString defaultValue;
+ KonfiguratorExtension *ext;
+};
+
+
+// KonfiguratorURLRequester class
+///////////////////////////////
+
+class KonfiguratorURLRequester : public KURLRequester
+{
+ Q_OBJECT
+
+public:
+ KonfiguratorURLRequester( QString cls, QString name, QString dflt, QWidget *parent=0,
+ const char *widgetName=0, bool rst=false, int pg=FIRST_PAGE );
+ ~KonfiguratorURLRequester();
+
+ inline KonfiguratorExtension *extension() {return ext;}
+
+public slots:
+ virtual void loadInitialValue();
+ void slotApply(QObject *,QString, QString);
+ void slotSetDefaults(QObject *);
+
+protected:
+ QString defaultValue;
+ KonfiguratorExtension *ext;
+};
+
+// KonfiguratorFontChooser class
+///////////////////////////////
+
+class KonfiguratorFontChooser : public QHBox
+{
+ Q_OBJECT
+
+public:
+ KonfiguratorFontChooser( QString cls, QString name, QFont *dflt, QWidget *parent=0,
+ const char *widgetName=0, bool rst=false, int pg=FIRST_PAGE );
+ ~KonfiguratorFontChooser();
+
+ inline KonfiguratorExtension *extension() {return ext;}
+
+public slots:
+ virtual void loadInitialValue();
+ void slotApply(QObject *,QString, QString);
+ void slotSetDefaults(QObject *);
+ void slotBrowseFont();
+
+protected:
+ QFont * defaultValue;
+ QFont font;
+ KonfiguratorExtension *ext;
+
+ QLabel * pLabel;
+ QToolButton * pToolButton;
+
+ void setFont();
+};
+
+// KONFIGURATOR_NAME_VALUE_PAIR structure
+///////////////////////////////
+
+struct KONFIGURATOR_NAME_VALUE_PAIR
+{
+ QString text;
+ QString value;
+};
+
+// KONFIGURATOR_NAME_VALUE_TIP structure
+///////////////////////////////
+
+struct KONFIGURATOR_NAME_VALUE_TIP
+{
+ QString text;
+ QString value;
+ QString tooltip;
+};
+
+// KonfiguratorComboBox class
+///////////////////////////////
+
+class KonfiguratorComboBox : public QComboBox
+{
+ Q_OBJECT
+
+public:
+ KonfiguratorComboBox( QString cls, QString name, QString dflt,
+ KONFIGURATOR_NAME_VALUE_PAIR *listIn, int listInLen,
+ QWidget *parent=0, const char *widgetName=0,
+ bool rst=false, bool editable=false, int pg=FIRST_PAGE );
+ ~KonfiguratorComboBox();
+
+ inline KonfiguratorExtension *extension() {return ext;}
+
+public slots:
+ virtual void loadInitialValue();
+ void slotApply(QObject *,QString, QString);
+ void slotSetDefaults(QObject *);
+
+protected:
+ QString defaultValue;
+ KONFIGURATOR_NAME_VALUE_PAIR *list;
+ int listLen;
+ KonfiguratorExtension *ext;
+
+ void selectEntry( QString entry );
+};
+
+
+// KonfiguratorColorChooser class
+///////////////////////////////
+
+typedef struct
+{
+ QString name;
+ QColor color;
+ QString value;
+} ADDITIONAL_COLOR;
+
+class KonfiguratorColorChooser : public QComboBox
+{
+ Q_OBJECT
+
+public:
+ KonfiguratorColorChooser( QString cls, QString name, QColor dflt,
+ QWidget *parent=0, const char *widgetName=0, bool rst=false,
+ ADDITIONAL_COLOR *addColPtr = 0, int addColNum = 0, int pg=FIRST_PAGE );
+ ~KonfiguratorColorChooser();
+
+ inline KonfiguratorExtension *extension() {return ext;}
+
+ void setDefaultColor( QColor dflt );
+ void setDefaultText( QString text );
+ QColor getColor();
+ void changeAdditionalColor( unsigned int num, QColor color );
+ QString getValue();
+ bool isValueRGB();
+ void setValue( QString value );
+
+public slots:
+ virtual void loadInitialValue();
+ void slotApply(QObject *,QString, QString);
+ void slotSetDefaults(QObject *);
+ void slotCurrentChanged( int number );
+
+signals:
+ void colorChanged();
+
+private:
+ void addColor( QString text, QColor color );
+ QPixmap createPixmap( QColor color );
+
+protected:
+ QColor defaultValue;
+ QColor customValue;
+ QValueVector<QColor> palette;
+ QValueVector<ADDITIONAL_COLOR> additionalColors;
+ KonfiguratorExtension *ext;
+ bool disableColorChooser;
+};
+
+// KonfiguratorListBox class
+///////////////////////////////
+
+class KonfiguratorListBox : public QListBox
+{
+ Q_OBJECT
+
+public:
+ KonfiguratorListBox( QString cls, QString name, QStringList dflt,
+ QWidget *parent=0, const char *widgetName=0,
+ bool rst=false, int pg=FIRST_PAGE );
+ ~KonfiguratorListBox();
+
+ inline KonfiguratorExtension *extension() {return ext;}
+
+ void addItem( const QString & );
+ void removeItem( const QString & );
+
+public slots:
+ virtual void loadInitialValue();
+ void slotApply(QObject *,QString, QString);
+ void slotSetDefaults(QObject *);
+
+protected:
+ QStringList list();
+ void setList( QStringList );
+
+ QStringList defaultValue;
+ KonfiguratorExtension *ext;
+};
+
+#endif /* __KONFIGURATOR_ITEMS_H__ */
+
diff --git a/krusader/Konfigurator/konfiguratorpage.cpp b/krusader/Konfigurator/konfiguratorpage.cpp
new file mode 100644
index 0000000..731a522
--- /dev/null
+++ b/krusader/Konfigurator/konfiguratorpage.cpp
@@ -0,0 +1,334 @@
+/* **************************************************************************
+ konfiguratorpage.cpp - description
+ -------------------
+ copyright : (C) 2003 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "konfiguratorpage.h"
+#include <qlayout.h>
+#include "../krusader.h"
+#include <qwhatsthis.h>
+
+KonfiguratorPage::KonfiguratorPage( bool firstTime, QWidget* parent, const char* name ) :
+ QFrame( parent, name ), firstCall( firstTime )
+{
+}
+
+bool KonfiguratorPage::apply()
+{
+ bool restartNeeded = false;
+
+ KonfiguratorExtension *item = itemList.first();
+
+ while( item )
+ {
+ restartNeeded = item->apply() || restartNeeded;
+ item = itemList.next();
+ }
+
+ krConfig->sync();
+ return restartNeeded;
+}
+
+void KonfiguratorPage::setDefaults()
+{
+ KonfiguratorExtension *item = itemList.first();
+ int activePage = activeSubPage();
+
+ while( item )
+ {
+ if( item->subPage() == activePage )
+ item->setDefaults();
+ item = itemList.next();
+ }
+}
+
+void KonfiguratorPage::loadInitialValues()
+{
+ KonfiguratorExtension *item = itemList.first();
+
+ while( item )
+ {
+ item->loadInitialValue();
+ item = itemList.next();
+ }
+}
+
+bool KonfiguratorPage::isChanged()
+{
+ KonfiguratorExtension *currentItem = itemList.current(); /* save the current pointer */
+ bool isChanged = false;
+
+ KonfiguratorExtension *item = itemList.first();
+
+ while( item )
+ {
+ isChanged = isChanged || item->isChanged();
+ item = itemList.next();
+ }
+
+ itemList.find( currentItem ); /* restore the current pointer */
+ return isChanged;
+}
+
+KonfiguratorCheckBox* KonfiguratorPage::createCheckBox( QString cls, QString name,
+ bool dflt, QString text, QWidget *parent, bool rst, QString toolTip, int pg )
+{
+ KonfiguratorCheckBox *checkBox = new KonfiguratorCheckBox( cls, name, dflt, text,
+ parent, QString(cls + "/" + name).ascii(), rst, pg );
+ if( !toolTip.isEmpty() )
+ QWhatsThis::add( checkBox, toolTip );
+
+ registerObject( checkBox->extension() );
+ return checkBox;
+}
+
+KonfiguratorSpinBox* KonfiguratorPage::createSpinBox( QString cls, QString name,
+ int dflt, int min, int max, QWidget *parent, bool rst, int pg )
+{
+ KonfiguratorSpinBox *spinBox = new KonfiguratorSpinBox( cls, name, dflt, min, max,
+ parent, QString(cls + "/" + name).ascii(), rst, pg );
+
+ registerObject( spinBox->extension() );
+ return spinBox;
+}
+
+KonfiguratorEditBox* KonfiguratorPage::createEditBox( QString cls, QString name,
+ QString dflt, QWidget *parent, bool rst, int pg )
+{
+ KonfiguratorEditBox *editBox = new KonfiguratorEditBox( cls, name, dflt, parent,
+ QString(cls + "/" + name).ascii(), rst, pg );
+
+ registerObject( editBox->extension() );
+ return editBox;
+}
+
+KonfiguratorListBox* KonfiguratorPage::createListBox( QString cls, QString name,
+ QStringList dflt, QWidget *parent, bool rst, int pg )
+{
+ KonfiguratorListBox *listBox = new KonfiguratorListBox( cls, name, dflt, parent,
+ QString(cls + "/" + name).ascii(), rst, pg );
+
+ registerObject( listBox->extension() );
+ return listBox;
+}
+
+KonfiguratorURLRequester* KonfiguratorPage::createURLRequester( QString cls, QString name,
+ QString dflt, QWidget *parent, bool rst, int pg )
+{
+ KonfiguratorURLRequester *urlRequester = new KonfiguratorURLRequester( cls, name, dflt,
+ parent, QString(cls + "/" + name).ascii(), rst, pg );
+
+ registerObject( urlRequester->extension() );
+ return urlRequester;
+}
+
+QGroupBox* KonfiguratorPage::createFrame( QString text, QWidget *parent,
+ const char *widgetName )
+{
+ QGroupBox *groupBox = new QGroupBox( parent, widgetName );
+ groupBox->setFrameShape( QGroupBox::Box );
+ groupBox->setFrameShadow( QGroupBox::Sunken );
+ if( !text.isNull() )
+ groupBox->setTitle( text );
+ groupBox->setColumnLayout(0, Qt::Vertical );
+ groupBox->layout()->setSpacing( 0 );
+ groupBox->layout()->setMargin( 0 );
+ return groupBox;
+}
+
+QGridLayout* KonfiguratorPage::createGridLayout( QLayout *parent )
+{
+ QGridLayout *gridLayout = new QGridLayout( parent );
+ gridLayout->setAlignment( Qt::AlignTop );
+ gridLayout->setSpacing( 6 );
+ gridLayout->setMargin( 11 );
+ return gridLayout;
+}
+
+QLabel* KonfiguratorPage::addLabel( QGridLayout *layout, int x, int y, QString label,
+ QWidget *parent, const char *widgetName )
+{
+ QLabel *lbl = new QLabel( label, parent, widgetName );
+ layout->addWidget( lbl, x, y );
+ return lbl;
+}
+
+QWidget* KonfiguratorPage::createSpacer( QWidget *parent, const char *widgetName )
+{
+ QWidget *widget = new QWidget( parent, widgetName );
+ QHBoxLayout *hboxlayout = new QHBoxLayout( widget );
+ QSpacerItem* spacer = new QSpacerItem( 40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ hboxlayout->addItem( spacer );
+ return widget;
+}
+
+KonfiguratorCheckBoxGroup* KonfiguratorPage::createCheckBoxGroup( int sizex, int sizey,
+ KONFIGURATOR_CHECKBOX_PARAM *params, int paramNum, QWidget *parent,
+ const char *widgetName, int pg )
+{
+ KonfiguratorCheckBoxGroup *groupWidget = new KonfiguratorCheckBoxGroup( parent, widgetName );
+ QGridLayout *layout = new QGridLayout( groupWidget );
+ layout->setSpacing( 6 );
+ layout->setMargin( 0 );
+
+ int x = 0, y = 0;
+
+ for( int i=0; i != paramNum; i++ )
+ {
+ KonfiguratorCheckBox *checkBox = createCheckBox( params[i].configClass,
+ params[i].configName, params[i].defaultValue, params[i].text, groupWidget,
+ params[i].restart, params[i].toolTip, pg );
+
+ groupWidget->add( checkBox );
+ layout->addWidget( checkBox, y, x );
+
+ if( sizex )
+ {
+ if( ++x == sizex )
+ x = 0, y++;
+ }
+ else
+ {
+ if( ++y == sizey )
+ y = 0, x++;
+ }
+ }
+
+ return groupWidget;
+}
+
+KonfiguratorRadioButtons* KonfiguratorPage::createRadioButtonGroup( QString cls,
+ QString name, QString dflt, int sizex, int sizey, KONFIGURATOR_NAME_VALUE_TIP *params,
+ int paramNum, QWidget *parent, const char *widgetName, bool rst, int pg )
+{
+ KonfiguratorRadioButtons *radioWidget = new KonfiguratorRadioButtons( cls, name, dflt, parent, widgetName, rst, pg );
+ radioWidget->setFrameShape( QButtonGroup::NoFrame );
+ radioWidget->setFrameShadow( QButtonGroup::Sunken );
+ radioWidget->setTitle( "" );
+ radioWidget->setExclusive( true );
+ radioWidget->setRadioButtonExclusive( true );
+ radioWidget->setColumnLayout(0, Qt::Vertical );
+
+ QGridLayout *layout = new QGridLayout( radioWidget->layout() );
+ layout->setAlignment( Qt::AlignTop );
+ layout->setSpacing( 6 );
+ layout->setMargin( 0 );
+
+ int x = 0, y = 0;
+
+ for( int i=0; i != paramNum; i++ )
+ {
+ QRadioButton *radBtn = new QRadioButton( params[i].text, radioWidget,
+ QString( cls + "/" + name + "/" + params[i].value ).ascii() );
+
+ if( !params[i].tooltip.isEmpty() )
+ QWhatsThis::add( radBtn, params[i].tooltip );
+
+ layout->addWidget( radBtn, y, x );
+
+ radioWidget->addRadioButton( radBtn, params[i].text, params[i].value );
+
+ if( sizex )
+ {
+ if( ++x == sizex )
+ x = 0, y++;
+ }
+ else
+ {
+ if( ++y == sizey )
+ y = 0, x++;
+ }
+ }
+
+ radioWidget->loadInitialValue();
+ registerObject( radioWidget->extension() );
+ return radioWidget;
+}
+
+KonfiguratorFontChooser *KonfiguratorPage::createFontChooser( QString cls, QString name,
+ QFont *dflt, QWidget *parent, bool rst, int pg )
+{
+ KonfiguratorFontChooser *fontChooser = new KonfiguratorFontChooser( cls, name, dflt, parent,
+ QString(cls + "/" + name).ascii(), rst, pg );
+
+ registerObject( fontChooser->extension() );
+ return fontChooser;
+}
+
+KonfiguratorComboBox *KonfiguratorPage::createComboBox( QString cls, QString name, QString dflt,
+ KONFIGURATOR_NAME_VALUE_PAIR *params, int paramNum, QWidget *parent, bool rst, bool editable, int pg )
+{
+ KonfiguratorComboBox *comboBox = new KonfiguratorComboBox( cls, name, dflt, params,
+ paramNum, parent, QString(cls + "/" + name).ascii(),
+ rst, editable, pg );
+
+ registerObject( comboBox->extension() );
+ return comboBox;
+}
+
+QFrame* KonfiguratorPage::createLine( QWidget *parent, const char *widgetName, bool vertical )
+{
+ QFrame *line = new QFrame( parent, widgetName );
+ line->setFrameStyle( ( vertical ? QFrame::VLine : QFrame::HLine ) | QFrame::Sunken );
+ return line;
+}
+
+void KonfiguratorPage::registerObject( KonfiguratorExtension *item )
+{
+ KonfiguratorExtension *currentItem = itemList.current();
+
+ itemList.append( item );
+ connect( item, SIGNAL( sigChanged( bool ) ), this, SIGNAL ( sigChanged( ) ) );
+
+ itemList.find( currentItem );
+}
+
+void KonfiguratorPage::removeObject( KonfiguratorExtension *item )
+{
+ if( item == itemList.current() )
+ {
+ itemList.remove();
+ if( itemList.current() != itemList.getFirst() )
+ itemList.prev();
+ }
+ else
+ itemList.removeRef( item );
+}
+
+KonfiguratorColorChooser *KonfiguratorPage::createColorChooser( QString cls, QString name, QColor dflt,
+ QWidget *parent, bool rst,
+ ADDITIONAL_COLOR *addColPtr, int addColNum, int pg )
+{
+ KonfiguratorColorChooser *colorChooser = new KonfiguratorColorChooser( cls, name, dflt, parent,
+ QString(cls + "/" + name).ascii(), rst, addColPtr, addColNum, pg );
+
+ registerObject( colorChooser->extension() );
+ return colorChooser;
+}
+
+#include "konfiguratorpage.moc"
diff --git a/krusader/Konfigurator/konfiguratorpage.h b/krusader/Konfigurator/konfiguratorpage.h
new file mode 100644
index 0000000..64a1b6b
--- /dev/null
+++ b/krusader/Konfigurator/konfiguratorpage.h
@@ -0,0 +1,522 @@
+/* **************************************************************************
+ konfiguratorpage.h - description
+ -------------------
+ copyright : (C) 2003 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __KONFIGURATOR_PAGE_H__
+#define __KONFIGURATOR_PAGE_H__
+
+#include "konfiguratoritems.h"
+#include <qframe.h>
+#include <qptrlist.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+
+struct KONFIGURATOR_CHECKBOX_PARAM;
+struct KONFIGURATOR_NAME_VALUE_TIP;
+struct KONFIGURATOR_NAME_VALUE_PAIR;
+
+/**
+ * KonfiguratorPage is responsible for handling pages in Konfigurator.
+ * It provides simple methods for create and manage Konfigurator pages.
+ *
+ * @short The base class of a page in Konfigurator
+ */
+class KonfiguratorPage : public QFrame
+{
+ Q_OBJECT
+
+public:
+/**
+ * The constructor of the KonfiguratorPage class.
+ *
+ * @param firstTime this parameter is true if it is the first call of Konfigurator
+ * @param parent reference to the parent widget
+ * @param name name of the newly generated Konfigurator page widget
+ */
+ KonfiguratorPage( bool firstTime, QWidget* parent, const char* name );
+
+ /**
+ * Applies the changes in the Konfigurator page.
+ *
+ * Writes out all relevent information to the konfiguration object and synchronizes
+ * it with the file storage (hard disk, krusaderrc file). This function calls the apply()
+ * method of each konfigurator item and finally performs the synchronization.
+ *
+ * @return a boolean value indicates that Krusader restart is needed for the correct change
+ */
+ virtual bool apply();
+
+ /**
+ * Sets every konfigurator item to its default value on the page.
+ *
+ * This method calls the setDefaults() method of each konfigurator item. This function
+ * doesn't modify the current configuration, only the values of the GUI items. The
+ * apply() method must be called for finalizing the changes.
+ */
+ virtual void setDefaults();
+
+ /**
+ * Reloads the original value of each konfigurator item from the configuration object.
+ *
+ * This function calls the loadInitialValue() method of each konfigurator item.
+ * Used to rollback the changes on the konfigurator page. Called if the user
+ * responds 'No' to the "Apply changes" question.
+ */
+ virtual void loadInitialValues();
+
+ /**
+ * Checks whether the page was changed.
+ *
+ * This function calls the isChanged() method of each konfigurator item and
+ * performs logical OR operation on them. Actually, this function returns true
+ * if any of the konfigurator items was changed.
+ *
+ * @return true if at least one of the konfigurator items was changed
+ */
+ virtual bool isChanged();
+
+ /**
+ * Flag, indicates the first call of Konfigurator
+ * @return true if konfigurator was started at the first time
+ */
+ inline bool isFirst() {return firstCall;}
+
+ /**
+ * This method is used to query the active subpage from the Konfigurator
+ * @return the active page (by default the first page)
+ */
+ virtual int activeSubPage() {return FIRST_PAGE;}
+
+ /**
+ * Adds a new checkbox item to the page.
+ * <br>The checkbox widget's name is QString(cls + "/" + name).ascii()<br>
+ *
+ * Sample:<br><br>
+ * KonfiguratorCheckBox *myCheckBox = createCheckBox( "class", "name", false, parentWidget );<br>
+ * myLayout->addWidget( myCheckBox, 0, 0 );
+ *
+ * @param cls The class name used in KConfig (ex. "Archives")
+ * @param name The item name used in KConfig (ex. "Do Tar")
+ * @param dflt The default value of the checkbox
+ * @param text The text field of the checkbox
+ * @param parent Reference to the parent widget
+ * @param rst The change of this parameter requires Krusader restart
+ * @param toolTip Tooltip used for this checkbox
+ * @param pg The subpage of a Konfigurator page (because of setDefaults)
+ *
+ * @return reference to the newly created checkbox
+ */
+ KonfiguratorCheckBox *createCheckBox( QString cls, QString name, bool dflt,
+ QString text, QWidget *parent=0, bool rst=false,
+ QString toolTip = QString::null, int pg=FIRST_PAGE );
+
+ /**
+ * Adds a new spinbox item to the page.
+ * <br>The spinbox widget's name is QString(cls + "/" + name).ascii()<br>
+ *
+ * Sample:<br><br>
+ * KonfiguratorSpinBox *mySpinBox = createSpinBox( "class", "name", 10, 1, 100, parentWidget );<br>
+ * myLayout->addWidget( mySpinBox, 0, 0 );
+ *
+ * @param cls The class name used in KConfig (ex. "Archives")
+ * @param name The item name used in KConfig (ex. "Do Tar")
+ * @param dflt The default value of the spinbox
+ * @param min The minimum value of the spinbox
+ * @param max The maximum value of the spinbox
+ * @param parent Reference to the parent widget
+ * @param rst The change of this parameter requires Krusader restart
+ * @param pg The subpage of a Konfigurator page (because of setDefaults)
+ *
+ * @return reference to the newly created spinbox
+ */
+ KonfiguratorSpinBox *createSpinBox( QString cls, QString name, int dflt, int min,
+ int max, QWidget *parent = 0, bool rst = false, int pg=FIRST_PAGE );
+
+ /**
+ * Adds a new editbox item to the page.
+ * <br>The editbox widget's name is QString(cls + "/" + name).ascii()<br>
+ *
+ * Sample:<br><br>
+ * KonfiguratorEditBox *myEditBox = createEditBox( "class", "name", "default", parentWidget );<br>
+ * myLayout->addWidget( myEditBox, 0, 0 );
+ *
+ * @param cls The class name used in KConfig (ex. "Archives")
+ * @param name The itemname used in KConfig (ex. "Do Tar")
+ * @param dflt The default value of the editbox
+ * @param parent Reference to the parent widget
+ * @param rst The change of this parameter requires Krusader restart
+ * @param pg The subpage of a Konfigurator page (because of setDefaults)
+ *
+ * @return reference to the newly created editbox
+ */
+ KonfiguratorEditBox *createEditBox( QString cls, QString name, QString dflt,
+ QWidget *parent=0, bool rst=false, int pg=FIRST_PAGE );
+
+ /**
+ * Adds a new listbox item to the page.
+ * <br>The listbox widget's name is QString(cls + "/" + name).ascii()<br>
+ *
+ * Sample:<br><br>
+ * QStringList valueList;<br>
+ * valueList += "item";<br>
+ * KonfiguratorListBox *myListBox = createListBox( "class", "name", valueList, parentWidget );<br>
+ * myLayout->addWidget( myListBox, 0, 0 );
+ *
+ * @param cls The class name used in KConfig (ex. "Archives")
+ * @param name The itemname used in KConfig (ex. "Do Tar")
+ * @param dflt The default value of the listbox
+ * @param parent Reference to the parent widget
+ * @param rst The change of this parameter requires Krusader restart
+ * @param pg The subpage of a Konfigurator page (because of setDefaults)
+ *
+ * @return reference to the newly created editbox
+ */
+ KonfiguratorListBox *createListBox( QString cls, QString name, QStringList dflt,
+ QWidget *parent=0, bool rst=false, int pg=FIRST_PAGE );
+
+ /**
+ * Adds a new URL requester item to the page.
+ * <br>The URL requester widget's name is QString(cls + "/" + name).ascii()<br>
+ *
+ * Sample:<br><br>
+ * KonfiguratorURLRequester *myURLRequester = createURLRequester( "class", "name", "default", parentWidget );<br>
+ * myLayout->addWidget( myURLRequester, 0, 0 );
+ *
+ * @param cls The class name used in KConfig (ex. "Archives")
+ * @param name The itemname used in KConfig (ex. "Do Tar")
+ * @param dflt The default value of the URL requester
+ * @param text The text field of the URL requester
+ * @param parent Reference to the parent widget
+ * @param rst The change of this parameter requires Krusader restart
+ * @param pg The subpage of a Konfigurator page (because of setDefaults)
+ *
+ * @return reference to the newly created URL requester
+ */
+ KonfiguratorURLRequester *createURLRequester( QString cls, QString name,
+ QString dflt, QWidget *parent, bool rst, int pg=FIRST_PAGE );
+
+ /**
+ * Adds a new font chooser item to the page.
+ * <br>The font chooser widget's name is QString(cls + "/" + name).ascii()<br>
+ *
+ * Sample:<br><br>
+ * KonfiguratorFontChooser *myFontChooser = createFontChooser( "class", "name", new QFont(), parentWidget );<br>
+ * myLayout->addWidget( myFontChooser, 0, 0 );
+ *
+ * @param cls The class name used in KConfig (ex. "Archives")
+ * @param name The item name used in KConfig (ex. "Do Tar")
+ * @param dflt The default value of the font chooser
+ * @param parent Reference to the parent widget
+ * @param rst The change of this parameter requires Krusader restart
+ * @param pg The subpage of a Konfigurator page (because of setDefaults)
+ *
+ * @return reference to the newly created font chooser
+ */
+ KonfiguratorFontChooser *createFontChooser( QString cls, QString name, QFont *dflt,
+ QWidget *parent=0, bool rst=false, int pg=FIRST_PAGE );
+
+ /**
+ * Adds a new combobox item to the page.
+ * <br>The combobox widget's name is QString(cls + "/" + name).ascii()<br>
+ *
+ * Sample:<br><br>
+ * KONFIGURATOR_NAME_VALUE_PAIR comboInfo[] =<br>
+ * &nbsp;{{ i18n( "combo text1" ), "value1" },<br>
+ * &nbsp;&nbsp;{ i18n( "combo text2" ), "value2" },<br>
+ * &nbsp;&nbsp;{ i18n( "combo text3" ), "value3" }};<br><br>
+ * KonfiguratorComboBox *myComboBox = createComboBox( "class", "name", "value2", comboInfo, 3, parentWidget );<br>
+ * myLayout->addWidget( myComboBox, 0, 0 );
+ *
+ * @param cls The class name used in KConfig (ex. "Archives")
+ * @param name The item name used in KConfig (ex. "Do Tar")
+ * @param dflt The default value of the combobox
+ * @param params Pointer to the name-value pair array (combo elements)
+ * @param paramNum Number of the combobox elements
+ * @param text The text field of the combobox
+ * @param parent Reference to the parent widget
+ * @param rst The change of this parameter requires Krusader restart
+ * @param editable Flag indicates that the combo can be edited
+ * @param pg The subpage of a Konfigurator page (because of setDefaults)
+ *
+ * @return reference to the newly created combobox
+ */
+ KonfiguratorComboBox *createComboBox( QString cls, QString name, QString dflt,
+ KONFIGURATOR_NAME_VALUE_PAIR *params, int paramNum,
+ QWidget *parent=0, bool rst=false, bool editable=false, int pg=FIRST_PAGE );
+
+ /**
+ * Creates a frame on the page.
+ *
+ * Sample:<br><br>
+ * QGroupBox *myGroup = createFrame( i18n( "MyFrameName" ), parentWidget, "frameName" );<br>
+ * myLayout->addWidget( myGroup, 0, 0 );
+ *
+ * @param text The text written out onto the frame
+ * @param parent Reference to the parent widget
+ * @param widgetName The name of the widget
+ *
+ * @return reference to the newly created frame
+ */
+ QGroupBox *createFrame( QString text = QString::null, QWidget *parent=0,
+ const char *widgetName=0 );
+
+ /**
+ * Creates a new QGridLayout element and sets its margins.
+ *
+ * Sample:<br><br>
+ * QGroupBox *myGroup = createFrame( i18n( "MyFrameName" ), parentWidget, "frameName" );<br>
+ * QGridLayout *myLayout = createGridLayout( myGroup->layout() );<br>
+ * myLayout->addWidget( myGroup, 0, 0 );
+ *
+ * @param parent Reference to the parent layout
+ *
+ * @return reference to the newly created QGridLayout
+ */
+ QGridLayout *createGridLayout( QLayout *parent );
+
+ /**
+ * Adds a new label to a grid layout.
+ *
+ * Sample:<br><br>
+ * QGroupBox *myGroup = createFrame( i18n( "MyFrameName" ), parentWidget, "frameName" );<br>
+ * QGridLayout *myLayout = createGridLayout( myGroup->layout() );<br>
+ * addLabel( myLayout, 0, 0, i18n( "Hello world!" ), myGroup, "myLabel" );<br>
+ * mainLayout->addWidget( myGroup, 0, 0 );
+ *
+ * @param layout The grid layout on which the item will be placed
+ * @param x the column to which the label will be placed
+ * @param y the row to which the label will be placed
+ * @param label the text of the label
+ * @param parent Reference to the parent widget
+ * @param widgetName The name of the newly generated label widget
+ *
+ * @return reference to the newly created label
+ */
+ QLabel *addLabel( QGridLayout *layout, int x, int y, QString label,
+ QWidget *parent=0, const char *widgetName=0 );
+
+ /**
+ * Creates a spacer object (for justifying in QHBox).
+ *
+ * Sample:<br><br>
+ * QHBox *hbox = new QHBox( myParent, "hbox" );<br>
+ * createSpinBox( "class", "spin", 5, 1, 10, hbox );<br>
+ * createSpacer( hbox, "mySpacer" );<br>
+ * myLayout->addWidget( hbox, 0, 0 );
+ *
+ * @param parent Reference to the parent widget
+ * @param widgetName The name of the newly generated label widget
+ *
+ * @return reference to the newly created spacer widget
+ */
+ QWidget *createSpacer( QWidget *parent=0, const char *widgetName=0 );
+
+ /**
+ * Creates a separator line.
+ *
+ * Sample:<br><br>
+ * QFrame *myLine = createLine( myParent, "myLine" );<br>
+ * myLayout->addWidget( myLine, 1, 0 );<br>
+ *
+ * @param parent Reference to the parent widget
+ * @param widgetName The name of the newly generated label widget
+ * @param vertical Means vertical line
+ *
+ * @return reference to the newly created spacer widget
+ */
+ QFrame *createLine( QWidget *parent=0, const char *widgetName=0, bool vertical = false );
+
+ /**
+ * Creates a checkbox group. A checkbox group contains a lot of checkboxes.
+ * The grouped checkboxes are embedded into one widget, which can be placed anywhere
+ * on the GUI. The placing of the elements can be horizontal or vertical in the group.
+ * At horizontal placing the sizex integer defines the maximum element number in
+ * one row, sizey is 0. At vertical placing sizex is 0, and sizey defines the
+ * maximum row number in one column. <br>
+ *
+ * One specific element can be reached by its name or index with the find methods.
+ * The first element is checkBoxGroup->find( 0 ), "myCb" element is checkBoxGroup->find( "myCb" ) ...
+ *
+ * Sample:<br><br>
+ * KONFIGURATOR_CHECKBOX_PARAM myCBArray[] =<br>
+ * &nbsp;{{"CbClass","CbName1", false, i18n( "name1" ), false, "tooltip1"},<br>
+ * &nbsp;&nbsp;{"CbClass","CbName2", true, i18n( "name2" ), false, "tooltip2"},<br>
+ * &nbsp;&nbsp;{"CbClass","CbName3", true, i18n( "name3" ), false, "tooltip3"}};<br><br>
+ * KonfiguratorCheckBoxGroup *myCheckBoxGroup = createCheckBoxGroup( 1, 0, myCBArray, 3, myParent, "myCheckboxGroup" );<br>
+ * myCheckBoxGroup->find( 0 )->setEnabled( false );<br><br>
+ * myLayout->addWidget( myCheckBoxGroup, 0, 0 );<br>
+ *
+ * @param sizex the maximum column number at horizontal placing
+ * @param sizey the maximum row number at vertical placing
+ * @param params pointer to the checkbox array
+ * @param paramNum number of the checkbox elements
+ * @param parent Reference to the parent widget
+ * @param widgetName The name of the newly created checkbox group widget
+ * @param pg The subpage of a Konfigurator page (because of setDefaults)
+ *
+ * @return reference to the newly created checkbox group widget
+ */
+ KonfiguratorCheckBoxGroup *createCheckBoxGroup( int sizex, int sizey,
+ KONFIGURATOR_CHECKBOX_PARAM *params, int paramNum,
+ QWidget *parent=0, const char *widgetName=0, int pg=FIRST_PAGE );
+ /**
+ * Creates a radio button group. A radio button group contains a lot of radio buttons.
+ * The grouped buttons are embedded into one widget, which can be placed anywhere
+ * on the GUI. The placing of the elements can be horizontal or vertical in the group.
+ * At horizontal placing the sizex integer defines the maximum element number in
+ * one row, sizey is 0. At vertical placing sizex is 0, and sizey defines the
+ * maximum row number in one column.<br>
+ *
+ * The references of the buttons can be accessed by the find methods of KonfiguratorRadioButtons.
+ * The first element is myRadioGrp->find( 0 ), "myRadio" element is myRadioGrp->find( "myRadio" ) ...
+ *
+ * Sample:<br><br>
+ * KONFIGURATOR_NAME_VALUE_TIP radioInfo[] =<br>
+ * &nbsp;{{ i18n( "radio text1" ), "value1", i18n( "tooltip1" ) },<br>
+ * &nbsp;&nbsp;{ i18n( "radio text2" ), "value2", i18n( "tooltip2" ) },<br>
+ * &nbsp;&nbsp;{ i18n( "radio text3" ), "value3", i18n( "tooltip3" ) }};<br><br>
+ * KonfiguratorRadioButtons *myRadioGroup = createRadioButtonGroup( "class", "name", "value1", 1, 0, radioInfo, 3, myParent, "myRadioGroup" );<br>
+ * myRadioGroup->find( i18n( "radio text1" ) )->setEnabled( false );<br>
+ * myLayout->addWidget( myRadioGroup, 0, 0 );<br>
+ *
+ * @param cls The class name used in KConfig (ex. "Archives")
+ * @param name The item name used in KConfig (ex. "Do Tar")
+ * @param dflt The default value of the radio buttons
+ * @param sizex the maximum column number at horizontal placing
+ * @param sizey the maximum row number at vertical placing
+ * @param params pointer to the checkbox array
+ * @param paramNum number of the checkbox elements
+ * @param parent Reference to the parent widget
+ * @param widgetName The name of the newly created button group widget
+ * @param rst The change of this parameter requires Krusader restart
+ * @param pg The subpage of a Konfigurator page (because of setDefaults)
+ *
+ * @return reference to the newly created radio button group widget
+ */
+ KonfiguratorRadioButtons *createRadioButtonGroup( QString cls, QString name,
+ QString dflt, int sizex, int sizey,
+ KONFIGURATOR_NAME_VALUE_TIP *params, int paramNum,
+ QWidget *parent=0, const char *widgetName=0, bool rst=false, int pg=FIRST_PAGE );
+
+ /**
+ * This function is used to insert new, unknown items into KonfiguratorPage. The
+ * item must be derived from KonfiguratorExtension class, which have
+ * isChanged(), apply(), setDefaults, loadInitialValue() methods. After that, the
+ * object is properly handled by Konfigurator page.
+ *
+ *
+ * @param item The item to be added to KonfiguratorPage
+ */
+ void registerObject( KonfiguratorExtension *item );
+
+ /**
+ * This function is used to remove elements from KonfiguratorPage.
+ *
+ * Sample:<br><br>
+ * KonfiguratorEditBox *myEditBox = createEditBox( "class", "name", "default", parentWidget );<br>
+ * myLayout->addWidget( myEditBox, 0, 0 );<br>
+ * removeObject( myEditBox->extension() );
+ *
+ * After the removeObject myEditBox will be untouched at apply(), setDefaults(), isChanged(),
+ * loadInitialValues() methods of the KonfiguratorPage.
+ *
+ * @param item The item to be removed from KonfiguratorPage
+ */
+ void removeObject( KonfiguratorExtension *item );
+
+ /**
+ * Adds a new color chooser combobox item to the page.
+ * <br>The chooser's widget's name is QString(cls + "/" + name).ascii()<br>
+ *
+ * Sample:<br><br>
+ * KonfiguratorColorChooser *myColorChooser = createColorChooser( "class", "name", QColor( 255, 0, 255 ), parentWidget );<br>
+ * myLayout->addWidget( myColorChooser, 0, 0 );
+ *
+ * @param cls The class name used in KConfig (ex. "Archives")
+ * @param name The item name used in KConfig (ex. "Do Tar")
+ * @param dflt The default value of the color chooser
+ * @param parent Reference to the parent widget
+ * @param rst The change of this parameter requires Krusader restart
+ * @param addColPtr The additional color values
+ * @param rst Number of additional colors
+ * @param pg The subpage of a Konfigurator page (because of setDefaults)
+ *
+ * @return reference to the newly created combobox
+ */
+ KonfiguratorColorChooser *createColorChooser( QString cls, QString name, QColor dflt,
+ QWidget *parent=0, bool rst=false,
+ ADDITIONAL_COLOR *addColPtr = 0, int addColNum = 0, int pg=FIRST_PAGE );
+signals:
+ /**
+ * The signal is emitted if the changed flag was modified in any konfigurator item.
+ * Used for enabling/disabling the apply button.
+ */
+ void sigChanged();
+
+protected:
+ QPtrList<KonfiguratorExtension> itemList;
+
+private:
+ bool firstCall;
+};
+
+/**
+ * KONFIGURATOR_CHECKBOX_PARAM is the basic item of checkbox arrays. It contains
+ * every information related to a checkbox.
+ */
+struct KONFIGURATOR_CHECKBOX_PARAM
+{
+ /**
+ * The class used in KConfig (ex. "Archives")
+ */
+ QString configClass;
+ /**
+ * The item name used in KConfig (ex. "Do Tar")
+ */
+ QString configName;
+ /**
+ * The default value of the checkbox
+ */
+ bool defaultValue;
+ /**
+ * The text field of the checkbox
+ */
+ QString text;
+ /**
+ * The change of this parameter requires Krusader restart
+ */
+ bool restart;
+ /**
+ * The checkbox's tooltip
+ */
+ QString toolTip;
+};
+
+#endif /* __KONFIGURATOR_PAGE_H__ */
diff --git a/krusader/Konfigurator/krresulttable.cpp b/krusader/Konfigurator/krresulttable.cpp
new file mode 100644
index 0000000..3e18e2c
--- /dev/null
+++ b/krusader/Konfigurator/krresulttable.cpp
@@ -0,0 +1,377 @@
+/***************************************************************************
+ krresulttable.cpp
+ -------------------
+ copyright : (C) 2005 by Dirk Eschler & Krusader Krew
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "krresulttable.h"
+#include <iostream>
+using namespace std;
+
+#define PS(x) _supported.contains(x)>0
+
+KrResultTable::KrResultTable(QWidget* parent)
+ : QWidget(parent),
+ _numRows(1)
+{
+}
+
+KrResultTable::~KrResultTable()
+{
+}
+
+
+QGridLayout* KrResultTable::initTable()
+{
+ _grid = new QGridLayout(this, _numRows, _numColumns);
+ _grid->setColStretch(_numColumns-1, 1); // stretch last column
+
+ // +++ Build and add table header +++
+ int column = 0;
+ for( QStringList::Iterator it=_tableHeaders.begin(); it!=_tableHeaders.end(); ++it )
+ {
+ _label = new QLabel(*it, this);
+ _label->setMargin(5);
+ _grid->addWidget(_label, 0, column);
+
+ // Set font
+ QFont defFont = KGlobalSettings::generalFont();
+ defFont.setPointSize(defFont.pointSize()-1);
+ defFont.setBold(true);
+ _label->setFont(defFont);
+
+ ++column;
+ }
+
+ return _grid;
+}
+
+
+void KrResultTable::adjustRow(QGridLayout* grid)
+{
+ QLayoutIterator it = grid->iterator();
+ QLayoutItem *child;
+ int col = 0;
+
+ while( (child = it.current()) != 0 )
+ {
+ // Add some space between columns
+ child->widget()->setMinimumWidth( child->widget()->sizeHint().width() + 15 );
+
+ // Paint uneven rows in alternate color
+ if( ((col/_numColumns)%2) )
+ child->widget()->setPaletteBackgroundColor( KGlobalSettings::baseColor() );
+
+ ++it;
+ ++col;
+ }
+}
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+
+KrArchiverResultTable::KrArchiverResultTable(QWidget* parent)
+ : KrResultTable(parent)
+{
+ _supported = KRarcHandler::supportedPackers(); // get list of available packers
+
+ Archiver* tar = new Archiver("tar", "http://www.gnu.org", PS("tar"), true, true);
+ Archiver* gzip = new Archiver("gzip", "http://www.gnu.org", PS("gzip"), true, true);
+ Archiver* bzip2 = new Archiver("bzip2", "http://www.gnu.org", PS("bzip2"), true, true);
+ Archiver* lha = new Archiver("lha", "http://www.gnu.org", PS("lha"), true, true);
+ Archiver* zip = new Archiver("zip", "http://www.info-zip.org", PS("zip"), true, false);
+ Archiver* unzip = new Archiver("unzip", "http://www.info-zip.org", PS("unzip"), false, true);
+ Archiver* arj = new Archiver("arj", "http://www.arjsoftware.com", PS("arj"), true, true);
+ Archiver* unarj = new Archiver("unarj", "http://www.arjsoftware.com", PS("unarj"), false, true);
+ Archiver* unace = new Archiver("unace", "http://www.winace.com", PS("unace"), false, true);
+ Archiver* rar = new Archiver("rar", "http://www.rarsoft.com", PS("rar"), true, true);
+ Archiver* unrar = new Archiver("unrar", "http://www.rarsoft.com", PS("unrar"), false, true);
+ Archiver* rpm = new Archiver("rpm", "http://www.gnu.org", PS("rpm"), false, true);
+ Archiver* dpkg = new Archiver("dpkg", "http://www.dpkg.org", PS("dpkg"), false, true);
+ Archiver* _7z = new Archiver("7z", "http://www.7-zip.org", PS("7z"), true, true);
+
+ // Special case: arj can unpack, but unarj is prefered
+ if(PS("arj") && PS("unarj"))
+ arj->setIsUnpacker(false);
+ if(PS("arj") && !PS("unarj"))
+ unarj->setNote( i18n("unarj not found, but arj found, which will be used for unpacking") );
+ // Special case: rar can unpack, but unrar is prefered
+ if(PS("rar") && PS("unrar"))
+ rar->setIsUnpacker(false);
+ // Special case: rpm needs cpio for unpacking
+ if(PS("rpm") && !PS("cpio"))
+ rpm->setNote( i18n("rpm found, but cpio not found which is required for unpacking") );
+
+ _tableHeaders.append( i18n("Name") );
+ _tableHeaders.append( i18n("Found") );
+ _tableHeaders.append( i18n("Packing") );
+ _tableHeaders.append( i18n("Unpacking") );
+ _tableHeaders.append( i18n("Note") );
+ _numColumns = _tableHeaders.size();
+
+ _grid = initTable();
+
+ addRow(tar, _grid);
+ addRow(gzip, _grid);
+ addRow(bzip2, _grid);
+ addRow(lha, _grid);
+ addRow(zip, _grid);
+ addRow(unzip, _grid);
+ addRow(arj, _grid);
+ addRow(unarj, _grid);
+ addRow(unace, _grid);
+ addRow(rar, _grid);
+ addRow(unrar, _grid);
+ addRow(rpm, _grid);
+ addRow(dpkg, _grid);
+ addRow(_7z, _grid);
+
+ delete tar;
+ delete gzip;
+ delete bzip2;
+ delete lha;
+ delete zip;
+ delete unzip;
+ delete arj;
+ delete unarj;
+ delete unace;
+ delete rar;
+ delete unrar;
+ delete rpm;
+ delete dpkg;
+ delete _7z;
+}
+
+KrArchiverResultTable::~KrArchiverResultTable()
+{
+}
+
+
+bool KrArchiverResultTable::addRow(SearchObject* search, QGridLayout* grid)
+{
+ Archiver* arch = dynamic_cast<Archiver*>(search);
+
+ // Name column
+ _label = new KURLLabel(arch->getWebsite(), arch->getSearchName(), this);
+ _label->setMargin(5);
+ _label->setAlignment(Qt::AlignTop);
+ grid->addWidget(_label, _numRows, 0);
+ connect(_label, SIGNAL(leftClickedURL(const QString&)),
+ SLOT(website(const QString&)));
+
+ // Found column
+ _label = new QLabel( arch->getPath(), this );
+ _label->setMargin(5);
+ grid->addWidget(_label, _numRows, 1);
+
+ // Packing column
+ _label = new QLabel(this);
+ _label->setMargin(5);
+ _label->setAlignment( Qt::AlignTop );
+ if( arch->getIsPacker() && arch->getFound() ) {
+ _label->setText( i18n("enabled") );
+ _label->setPaletteForegroundColor("darkgreen");
+ } else if( arch->getIsPacker() && !arch->getFound() ) {
+ _label->setText( i18n("disabled") );
+ _label->setPaletteForegroundColor("red");
+ } else
+ _label->setText( "" );
+ grid->addWidget(_label, _numRows, 2);
+
+ // Unpacking column
+ _label = new QLabel(this);
+ _label->setMargin(5);
+ _label->setAlignment( Qt::AlignTop );
+ if( arch->getIsUnpacker() && arch->getFound() ) {
+ _label->setText( i18n("enabled") );
+ _label->setPaletteForegroundColor("darkgreen");
+ } else if( arch->getIsUnpacker() && !arch->getFound() ) {
+ _label->setText( i18n("disabled") );
+ _label->setPaletteForegroundColor("red");
+ } else
+ _label->setText( "" );
+ grid->addWidget(_label, _numRows, 3);
+
+ // Note column
+ _label = new QLabel(arch->getNote(), this);
+ _label->setMargin(5);
+ _label->setAlignment( Qt::AlignTop | Qt::WordBreak ); // wrap words
+ grid->addWidget(_label, _numRows, 4);
+
+ // Apply shared design elements
+ adjustRow(_grid);
+
+ // Ensure the last column takes more space
+ _label->setMinimumWidth(300);
+
+ ++_numRows;
+ return true;
+}
+
+
+void KrArchiverResultTable::website(const QString& url)
+{
+ (void) new KRun(url);
+}
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+
+KrToolResultTable::KrToolResultTable(QWidget* parent)
+ : KrResultTable(parent)
+{
+ _supported = Krusader::supportedTools(); // get list of available tools
+
+ QValueVector<Application*> vecDiff, vecMail, vecRename, vecChecksum;
+ Application* kdiff3 = new Application("kdiff3", "http://kdiff3.sourceforge.net/", KrServices::cmdExist("kdiff3"));
+ Application* kompare = new Application("kompare", "http://www.caffeinated.me.uk/kompare/", KrServices::cmdExist("kompare"));
+ Application* xxdiff = new Application("xxdiff", "http://xxdiff.sourceforge.net/", KrServices::cmdExist("xxdiff"));
+ Application* kmail = new Application("kmail", "http://kmail.kde.org/", KrServices::cmdExist("kmail"));
+ Application* krename = new Application("krename", "http://www.krename.net/", KrServices::cmdExist("krename"));
+ Application* md5sum = new Application("md5sum", "http://www.gnu.org/software/textutils/textutils.html", KrServices::cmdExist("md5sum"));
+ Application* md5deep = new Application("md5deep", "http://md5deep.sourceforge.net/", KrServices::cmdExist("md5deep"));
+ Application* sha1deep = new Application("sha1deep", "http://md5deep.sourceforge.net/", KrServices::cmdExist("sha1deep"));
+ Application* sha256deep = new Application("sha256deep", "http://md5deep.sourceforge.net/", KrServices::cmdExist("sha256deep"));
+ Application* tigerdeep = new Application("tigerdeep", "http://md5deep.sourceforge.net/", KrServices::cmdExist("tigerdeep"));
+ Application* whirlpooldeep = new Application("whirlpooldeep", "http://md5deep.sourceforge.net/", KrServices::cmdExist("whirlpooldeep"));
+ Application* cfv = new Application("cfv", "http://cfv.sourceforge.net/", KrServices::cmdExist("cfv"));
+
+ vecDiff.push_back(kdiff3);
+ vecDiff.push_back(kompare);
+ vecDiff.push_back(xxdiff);
+ vecMail.push_back(kmail);
+ vecRename.push_back(krename);
+ vecChecksum.push_back(md5sum);
+ vecChecksum.push_back(md5deep);
+ vecChecksum.push_back(sha1deep);
+ vecChecksum.push_back(sha256deep);
+ vecChecksum.push_back(tigerdeep);
+ vecChecksum.push_back(whirlpooldeep);
+ vecChecksum.push_back(cfv);
+
+ ApplicationGroup* diff = new ApplicationGroup( i18n("diff utility"), PS("DIFF"), vecDiff);
+ ApplicationGroup* mail = new ApplicationGroup( i18n("email client"), PS("MAIL"), vecMail);
+ ApplicationGroup* rename = new ApplicationGroup( i18n("batch renamer"), PS("RENAME"), vecRename);
+ ApplicationGroup* checksum = new ApplicationGroup( i18n("checksum utility"), PS("MD5"), vecChecksum);
+
+ _tableHeaders.append( i18n("Group") );
+ _tableHeaders.append( i18n("Tool") );
+ _tableHeaders.append( i18n("Found") );
+ _tableHeaders.append( i18n("Status") );
+ _numColumns = _tableHeaders.size();
+
+ _grid = initTable();
+
+ addRow(diff, _grid);
+ addRow(mail, _grid);
+ addRow(rename, _grid);
+ addRow(checksum, _grid);
+
+ delete kmail;
+ delete kompare;
+ delete kdiff3;
+ delete xxdiff;
+ delete krename;
+ delete md5sum;
+ delete md5deep;
+ delete sha1deep;
+ delete sha256deep;
+ delete tigerdeep;
+ delete whirlpooldeep;
+ delete cfv;
+
+ delete diff;
+ delete mail;
+ delete rename;
+ delete checksum;
+}
+
+KrToolResultTable::~KrToolResultTable()
+{
+}
+
+
+bool KrToolResultTable::addRow(SearchObject* search, QGridLayout* grid)
+{
+ ApplicationGroup* appGroup = dynamic_cast<ApplicationGroup*>(search);
+ QValueVector<Application*> _apps = appGroup->getAppVec();
+
+ // Name column
+ _label = new QLabel(appGroup->getSearchName(), this);
+ _label->setMargin(5);
+ _label->setAlignment( Qt::AlignTop );
+ grid->addWidget(_label, _numRows, 0);
+
+ // Tool column
+ QVBox* toolBox = new QVBox(this);
+ for( QValueVector<Application*>::Iterator it=_apps.begin(); it!=_apps.end(); it++ )
+ {
+ KURLLabel* l = new KURLLabel( (*it)->getWebsite(), (*it)->getAppName(), toolBox);
+ l->setAlignment(Qt::AlignLeft | Qt::AlignTop);
+ l->setMargin(5);
+ connect(l, SIGNAL(leftClickedURL(const QString&)),
+ SLOT(website(const QString&)));
+ }
+ grid->addWidget(toolBox, _numRows, 1);
+
+ // Found column
+ QVBox* vbox = new QVBox(this);
+ for( QValueVector<Application*>::Iterator it=_apps.begin(); it!=_apps.end(); it++ )
+ {
+ _label = new QLabel( (*it)->getPath(), vbox);
+ _label->setMargin(5);
+ _label->setAlignment( Qt::AlignTop );
+ }
+ grid->addWidget(vbox, _numRows, 2);
+
+ // Status column
+ _label = new QLabel(this);
+ _label->setMargin(5);
+ _label->setAlignment( Qt::AlignTop );
+ if( appGroup->getFoundGroup() ) {
+ _label->setText( i18n("enabled") );
+ _label->setPaletteForegroundColor("darkgreen");
+ } else {
+ _label->setText( i18n("disabled") );
+ _label->setPaletteForegroundColor("red");
+ }
+ grid->addWidget(_label, _numRows, 3);
+
+ // Apply shared design elements
+ adjustRow(_grid);
+
+ // Ensure the last column takes more space
+ _label->setMinimumWidth(300);
+
+ ++_numRows;
+ return true;
+}
+
+void KrToolResultTable::website(const QString& url)
+{
+ (void) new KRun(url);
+}
diff --git a/krusader/Konfigurator/krresulttable.h b/krusader/Konfigurator/krresulttable.h
new file mode 100644
index 0000000..8cdfbfd
--- /dev/null
+++ b/krusader/Konfigurator/krresulttable.h
@@ -0,0 +1,140 @@
+/***************************************************************************
+ krresulttable.h
+ -------------------
+ copyright : (C) 2005 by Dirk Eschler & Krusader Krew
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KRRESULTTABLE_H
+#define KRRESULTTABLE_H
+
+#include <qstring.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qhbox.h>
+#include <qvbox.h>
+#include <qgrid.h>
+#include <qstringlist.h>
+#include <qvaluevector.h>
+
+#include <kiconloader.h>
+#include <kglobalsettings.h>
+#include <klocale.h>
+#include <klocale.h>
+#include <krun.h>
+#include <kseparator.h>
+#include <kurllabel.h>
+
+#include "searchobject.h"
+#include "../krusader.h"
+#include "../krservices.h"
+#include "../VFS/krarchandler.h"
+
+/**
+@author Dirk Eschler <deschler@users.sourceforge.net>
+*/
+class KrResultTable : public QWidget
+{
+public:
+ KrResultTable(QWidget* parent);
+ virtual ~KrResultTable();
+
+ /**
+ * Adds a row of search results to the end of a QGridLayout
+ * Each KrResultTable has to implement it
+ *
+ * @param const SearchObject* search Name of the SearchObject
+ * @param const QGridLayout* grid The GridLayout where the row is inserted
+ *
+ * @return bool True if row was added successfully to rows, else false
+ */
+ virtual bool addRow(SearchObject* search, QGridLayout* grid) = 0;
+
+protected:
+ QStringList _supported;
+ QStringList _tableHeaders;
+ int _numColumns;
+ int _numRows;
+
+ QGridLayout* _grid;
+ QHBox* _iconBox;
+ QLabel* _label; // generic label
+
+ /**
+ * Creates the main grid layout and attaches the table header
+ *
+ * @return bool Pointer to the main grid layout
+ */
+ QGridLayout* initTable();
+
+ /**
+ * Applies settings to each cell of the grid layout
+ * Supposed to be run after a row was added
+ *
+ * @param const QGridLayout* grid The GridLayout
+ */
+ void adjustRow(QGridLayout* grid);
+};
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+
+class KrArchiverResultTable : public KrResultTable
+{
+ Q_OBJECT
+public:
+ KrArchiverResultTable(QWidget* parent);
+ virtual ~KrArchiverResultTable();
+
+ bool addRow(SearchObject* search, QGridLayout* grid);
+
+protected:
+ KURLLabel* _nameLabel;
+
+protected slots:
+ void website(const QString&);
+};
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+
+class KrToolResultTable : public KrResultTable
+{
+ Q_OBJECT
+public:
+ KrToolResultTable(QWidget* parent);
+ virtual ~KrToolResultTable();
+
+ bool addRow(SearchObject* search, QGridLayout* grid);
+
+protected:
+ QValueVector<Application*> _apps;
+
+protected slots:
+ void website(const QString&);
+};
+
+#endif
diff --git a/krusader/Konfigurator/krresulttabledialog.cpp b/krusader/Konfigurator/krresulttabledialog.cpp
new file mode 100644
index 0000000..622de83
--- /dev/null
+++ b/krusader/Konfigurator/krresulttabledialog.cpp
@@ -0,0 +1,97 @@
+/***************************************************************************
+ krresulttabledialog.cpp
+ -------------------
+ copyright : (C) 2005 by Dirk Eschler & Krusader Krew
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "krresulttabledialog.h"
+
+KrResultTableDialog::KrResultTableDialog( QWidget *parent, DialogType type,
+ const QString& caption, const QString& heading, const QString& headerIcon,
+ const QString& hint)
+ : KDialogBase( parent, "KrSearchResultDialog", true, caption, KDialogBase::Help|KDialogBase::Ok,
+ KDialogBase::Ok, false )
+
+{
+ _page = new QWidget(this);
+ setMainWidget(_page);
+ _topLayout = new QVBoxLayout(_page, 0, spacingHint());
+ _topLayout->setAlignment( Qt::AlignTop );
+
+ // +++ Heading +++
+ // prepare the icon
+ _iconBox = new QHBox(_page, "_iconBox");
+ _iconLabel = new QLabel(_iconBox, "iconLabel");
+ _iconLabel->setPixmap(krLoader->loadIcon(headerIcon, KIcon::Desktop, 32));
+ _iconLabel->setMinimumWidth(fontMetrics().maxWidth()*20);
+ _iconLabel->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
+ _iconLabel->setFixedSize( _iconLabel->sizeHint() );
+ _headingLabel = new QLabel(heading, _iconBox);
+ QFont defFont = KGlobalSettings::generalFont();
+ defFont.setBold(true);
+ _headingLabel->setFont(defFont);
+ _headingLabel->setIndent(10);
+ _topLayout->addWidget(_iconBox);
+
+ // +++ Add some space between heading and table +++
+ QSpacerItem* hSpacer1 = new QSpacerItem(0, 5);
+ _topLayout->addItem(hSpacer1);
+
+ // +++ Table +++
+ switch(type) {
+ case Archiver:
+ _resultTable = new KrArchiverResultTable(_page);
+ setHelp("konfig-archives"); // launch handbook at sect1-id via help button
+ break;
+ case Tool:
+ _resultTable = new KrToolResultTable(_page);
+ setHelp(""); // TODO find a good anchor
+ break;
+ default:
+ break;
+ }
+ _topLayout->addWidget(_resultTable);
+
+ // +++ Separator +++
+ KSeparator* hSep = new KSeparator(QFrame::HLine, _page);
+ hSep->setMargin(5);
+ _topLayout->addWidget(hSep);
+
+ // +++ Hint +++
+ if(hint != QString::null) {
+ _hintLabel = new QLabel(hint, _page);
+ _hintLabel->setIndent(5);
+ _hintLabel->setAlignment(Qt::AlignRight);
+ _topLayout->addWidget(_hintLabel);
+ }
+
+ this->setFixedSize( this->sizeHint() ); // make non-resizeable
+}
+
+KrResultTableDialog::~KrResultTableDialog()
+{
+}
diff --git a/krusader/Konfigurator/krresulttabledialog.h b/krusader/Konfigurator/krresulttabledialog.h
new file mode 100644
index 0000000..fe1b85a
--- /dev/null
+++ b/krusader/Konfigurator/krresulttabledialog.h
@@ -0,0 +1,84 @@
+/***************************************************************************
+ krresulttabledialog.h
+ -------------------
+ copyright : (C) 2005 by Dirk Eschler & Krusader Krew
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KRRESULTTABLEDIALOG_H
+#define KRRESULTTABLEDIALOG_H
+
+#include <qlabel.h>
+#include <qvbox.h>
+#include <qhbox.h>
+#include <qlayout.h>
+#include <qstringlist.h>
+#include <qvaluevector.h>
+
+#include <kdialogbase.h>
+#include <kiconloader.h>
+#include <kglobalsettings.h>
+#include <klocale.h>
+
+#include "../krusader.h"
+#include "../Konfigurator/krresulttable.h"
+#include "../Konfigurator/searchobject.h"
+
+/**
+@author Dirk Eschler <deschler@users.sourceforge.net>
+*/
+class KrResultTableDialog : public KDialogBase
+{
+public:
+
+ enum DialogType
+ {
+ Archiver = 1,
+ Tool = 2
+ };
+
+ KrResultTableDialog(QWidget *parent, DialogType type, const QString& caption, const QString& heading, const QString& headerIcon=QString::null, const QString& hint=QString::null);
+ virtual ~KrResultTableDialog();
+
+ const QString& getHeading() const { return _heading; }
+ const QString& getHint() const { return _hint; }
+ void setHeading(const QString& s) { _heading = s; }
+ void setHint(const QString& s) { _hint = s; }
+
+protected:
+ QString _heading;
+ QString _hint;
+
+ QLabel* _headingLabel;
+ QLabel* _iconLabel;
+ QLabel* _hintLabel;
+ QHBox* _iconBox;
+ QWidget* _page;
+ QVBoxLayout* _topLayout;
+ KrResultTable* _resultTable;
+};
+
+#endif
diff --git a/krusader/Konfigurator/searchobject.cpp b/krusader/Konfigurator/searchobject.cpp
new file mode 100644
index 0000000..5686870
--- /dev/null
+++ b/krusader/Konfigurator/searchobject.cpp
@@ -0,0 +1,106 @@
+/***************************************************************************
+ searchobject.cpp
+ -------------------
+ copyright : (C) 2005 by Dirk Eschler & Krusader Krew
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "searchobject.h"
+
+SearchObject::SearchObject()
+{
+}
+
+SearchObject::SearchObject(const QString& searchName, bool found, const QString& note)
+ : _searchName(searchName),
+ _found(found),
+ _note(note)
+{
+}
+
+SearchObject::~SearchObject()
+{
+}
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+
+Application::Application()
+{
+}
+
+Application::Application(const QString& searchName, bool found, const QString& appName, const QString& website, const QString& note)
+ : SearchObject(searchName, found, note),
+ _appName(appName),
+ _website(website),
+ _path(KrServices::fullPathName(appName))
+{
+}
+
+Application::Application(const QString& searchName, const QString& website, bool found, const QString& note)
+ : SearchObject(searchName, found, note),
+ _appName(searchName),
+ _website(website),
+ _path(KrServices::fullPathName(searchName))
+{
+}
+
+Application::~Application()
+{
+}
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+
+Archiver::Archiver()
+ : Application()
+{
+}
+
+Archiver::Archiver(const QString& searchName, const QString& website, bool found, bool isPacker, bool isUnpacker, const QString& note)
+ : Application(searchName, website, found, note),
+ _isPacker(isPacker),
+ _isUnpacker(isUnpacker)
+{
+}
+
+Archiver::~Archiver()
+{
+}
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+
+ApplicationGroup::ApplicationGroup(const QString& searchName, bool foundGroup, const QValueVector<Application*>& apps, const QString& note)
+ : SearchObject(searchName, foundGroup, note),
+ _apps(apps),
+ _foundGroup(foundGroup)
+{
+}
+
+ApplicationGroup::~ApplicationGroup()
+{
+}
diff --git a/krusader/Konfigurator/searchobject.h b/krusader/Konfigurator/searchobject.h
new file mode 100644
index 0000000..fe01a76
--- /dev/null
+++ b/krusader/Konfigurator/searchobject.h
@@ -0,0 +1,131 @@
+/***************************************************************************
+ searchobject.h
+ -------------------
+ copyright : (C) 2005 by Dirk Eschler & Krusader Krew
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef SEARCHOBJECT_H
+#define SEARCHOBJECT_H
+
+#include <qstring.h>
+#include <qvaluevector.h>
+#include "../krservices.h"
+
+/**
+@author Dirk Eschler <deschler@users.sourceforge.net>
+*/
+class SearchObject
+{
+public:
+ SearchObject();
+ SearchObject(const QString& name, bool found, const QString& note);
+ virtual ~SearchObject();
+
+ const QString& getSearchName() const { return _searchName; }
+ const QString& getNote() const { return _note; }
+ const bool getFound() const { return _found; }
+ void setSearchName(const QString& s) { _searchName = s; }
+ void setNote(const QString& s) { _note = s; }
+ void setFound(const bool& b) { _found = b; }
+
+protected:
+ QString _searchName;
+ bool _found;
+ QString _note;
+};
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+
+/**
+@author Dirk Eschler <deschler@users.sourceforge.net>
+*/
+class Application : public SearchObject
+{
+public:
+ Application();
+ Application(const QString& searchName, bool found, const QString& appName, const QString& website=QString::null, const QString& note=QString::null);
+ Application(const QString& searchName, const QString& website, bool found, const QString& note=QString::null);
+ virtual ~Application();
+
+ const QString& getWebsite() const { return _website; }
+ const QString& getAppName() const { return _appName; }
+ const QString& getPath() const { return _path; }
+ void setWebsite(const QString& s) { _website = s; }
+ void setAppName(const QString& s) { _appName = s; }
+ void setPath(const QString& s) { _path = s; }
+
+protected:
+ QString _appName;
+ QString _website;
+ QString _path;
+};
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+
+/**
+@author Dirk Eschler <deschler@users.sourceforge.net>
+*/
+class Archiver : public Application
+{
+public:
+ Archiver();
+ Archiver(const QString& searchName, const QString& website, bool found, bool isPacker, bool isUnpacker, const QString& note=QString::null);
+ ~Archiver();
+
+ const bool getIsPacker() const { return _isPacker; }
+ const bool getIsUnpacker() const { return _isUnpacker; }
+ void setIsPacker(const bool& b) { _isPacker = b; }
+ void setIsUnpacker(const bool& b) { _isUnpacker = b; }
+
+protected:
+ bool _isPacker;
+ bool _isUnpacker;
+};
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+
+/**
+@author Dirk Eschler <deschler@users.sourceforge.net>
+*/
+class ApplicationGroup : public SearchObject
+{
+public:
+ ApplicationGroup(const QString& searchName, bool foundGroup, const QValueVector<Application*>& apps, const QString& note=QString::null);
+ ~ApplicationGroup();
+
+ const QValueVector<Application*>& getAppVec() const { return _apps; }
+ const bool getFoundGroup() const { return _foundGroup; }
+
+protected:
+ QValueVector<Application*> _apps;
+ bool _foundGroup;
+};
+
+#endif
diff --git a/krusader/KrJS/Makefile.am b/krusader/KrJS/Makefile.am
new file mode 100644
index 0000000..af10182
--- /dev/null
+++ b/krusader/KrJS/Makefile.am
@@ -0,0 +1,13 @@
+# This should not be nessesary because this subdir is only visited if KJSEmbed should be used...
+#if include_libkjsembed
+#AM_CPPFLAGS = -D__KJSEMBED__
+#endif
+
+noinst_LIBRARIES = libKrJS.a
+
+INCLUDES = $(all_includes)
+
+libKrJS_a_METASOURCES = AUTO
+
+libKrJS_a_SOURCES = \
+ krjs.cpp
diff --git a/krusader/KrJS/krjs.cpp b/krusader/KrJS/krjs.cpp
new file mode 100644
index 0000000..435b43e
--- /dev/null
+++ b/krusader/KrJS/krjs.cpp
@@ -0,0 +1,89 @@
+// Implementation of our JavaScript-Interpreter
+//
+// Author: Jonas B�r (C) 2005
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+
+#include "krjs.h"
+
+#include "../krusader.h"
+#include "../krusaderview.h"
+#include "../panelmanager.h"
+
+#include <kmessagebox.h>
+
+KrJS::KrJS() : KJSEmbed::KJSEmbedPart() {
+
+ // make this object, the object Krusader, available for scripting as "Krusader":
+ addObject( krApp, "Krusader" );
+
+ // make this object available for scripting
+ addObject( ACTIVE_MNG, "PanelManager" );
+}
+
+bool KrJS::runFile(const QString & filename) {
+
+ KJS::ExecState *exec = globalExec();
+
+ // set up the variable scriptDir with the directory of the current script
+ putValue( "scriptDir", KJSEmbed::convertToValue(exec, KURL(filename).directory(false) ) );
+
+ bool ok = KJSEmbedPart::runFile(filename);
+
+ KJS::Completion jsres = completion();
+
+ // this is based on this example-code http://webcvs.kde.org/kdebindings/kjsembed/kjscmd.cpp?rev=1.28&view=auto
+ if ( jsres.complType() != KJS::Normal) {
+ switch ( jsres.complType() ) {
+ case KJS::Break:
+ case KJS::Continue:
+ // TODO: find out what this means
+ krOut << "JavaScript: " << jsres.value().toString(exec).qstring() << endl;
+ break;
+ case KJS::ReturnValue:
+ // that's only needed when a specific function is called
+ //someString = jsres.value().toString(exec).qstring();
+ break;
+ case KJS::Throw:
+ /*
+ This is the interesting part: If the JS throws an exception which is not handled inside the script,
+ we can catch it here and handle it with c++
+ */
+ {
+#if KDE_IS_VERSION(3,4,0)
+ KJS::Object exception = jsres.value().toObject(exec);
+ int line = int( exception.get( exec, KJS::Identifier("line") ).toNumber(exec) );
+ QString type = exception.get( exec, KJS::Identifier("name") ).toString(exec).qstring();
+ QString message = exception.get( exec, KJS::Identifier("message") ).toString(exec).qstring();
+
+ krOut << "JavaScript: Uncaught " << type << " exception at line " << line << " in " << filename << endl;
+ krOut << message << endl;
+
+ KMessageBox::error ( 0, //parent
+ ( line < 0 ?
+ QString( i18n("In %1:\nUncaught JavaScript exception '%2'\n%3") ).arg(filename).arg(type).arg(message) :
+ QString( i18n("In %1:\nUncaught JavaScript exception '%2' at line %3\n%4") ).arg(filename).arg(type).arg(line).arg(message)
+ ), //text
+ i18n("JavaScript error"), //caption
+ KMessageBox::Dangerous) ;
+#else
+ KMessageBox::error ( 0, //parent
+ QString(i18n("In %1:\nThere is an error in the JavaScript")).arg(filename), //text
+ i18n("JavaScript error"), //caption
+ KMessageBox::Dangerous) ;
+#endif
+ break;
+ }
+ default:
+ krOut << "JavaScript: Unknown error." << endl;
+ break;
+ } // switch
+ } // if
+
+
+ krOut << "JS: done" << endl;
+
+ return ok;
+}
+
diff --git a/krusader/KrJS/krjs.h b/krusader/KrJS/krjs.h
new file mode 100644
index 0000000..73f81ae
--- /dev/null
+++ b/krusader/KrJS/krjs.h
@@ -0,0 +1,32 @@
+// Interface for our JavaScript-Interpreter
+//
+// Author: Jonas Bhr (C) 2005
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+
+#ifndef KRJS_H
+#define KRJS_H
+
+#include <kjsembed/kjsembedpart.h>
+
+/**
+ * Our own version of KJSEmbedPart. Here are all the Krusader-specific extensions implemented.
+ *
+ * @author Jonas Bhr (http://jonas-baehr.de/)
+*/
+
+class KrJS: public KJSEmbed::KJSEmbedPart {
+public:
+ KrJS();
+
+ /**
+ * This loads and runs a file. In addition to the original runFile function it displays an popup
+ * on errors and sets some variables
+ *
+ * @par filename The file to run
+ */
+ bool runFile(const QString & filename);
+};
+
+#endif //KRJS_H
diff --git a/krusader/Locate/Makefile.am b/krusader/Locate/Makefile.am
new file mode 100644
index 0000000..5c4b95f
--- /dev/null
+++ b/krusader/Locate/Makefile.am
@@ -0,0 +1,7 @@
+noinst_LIBRARIES = libLocate.a
+
+INCLUDES = $(all_includes)
+
+libLocate_a_METASOURCES = AUTO
+
+libLocate_a_SOURCES = locate.cpp
diff --git a/krusader/Locate/locate.cpp b/krusader/Locate/locate.cpp
new file mode 100755
index 0000000..c875de3
--- /dev/null
+++ b/krusader/Locate/locate.cpp
@@ -0,0 +1,613 @@
+/***************************************************************************
+ locate.cpp - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "locate.h"
+#include "../krusader.h"
+#include "../krusaderview.h"
+#include "../Panel/listpanel.h"
+#include "../Panel/panelfunc.h"
+#include "../defaults.h"
+#include "../krservices.h"
+#include "../VFS/vfs.h"
+#include "../VFS/virt_vfs.h"
+#include "../KViewer/krviewer.h"
+#include "../panelmanager.h"
+#include <klocale.h>
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qfontmetrics.h>
+#include <kmessagebox.h>
+#include <kpopupmenu.h>
+#include <qcursor.h>
+#include <qeventloop.h>
+#include <kfinddialog.h>
+#include <kinputdialog.h>
+#include <qregexp.h>
+#include <qdir.h>
+#include <qclipboard.h>
+#include <kurldrag.h>
+#include <../kicons.h>
+
+// these are the values that will exist in the menu
+#define VIEW_ID 90
+#define EDIT_ID 91
+#define FIND_ID 92
+#define FIND_NEXT_ID 93
+#define FIND_PREV_ID 94
+#define COPY_SELECTED_TO_CLIPBOARD 95
+//////////////////////////////////////////////////////////
+
+class LocateListView : public KListView
+{
+public:
+ LocateListView( QWidget * parent, const char * name = 0 ) : KListView( parent, name )
+ {
+ }
+
+ void startDrag()
+ {
+ KURL::List urls;
+
+ QListViewItem * item = firstChild();
+ while( item )
+ {
+ if( item->isSelected() )
+ urls.push_back( vfs::fromPathOrURL( item->text( 0 ) ) );
+
+ item = item->nextSibling();
+ }
+
+ if( urls.count() == 0 )
+ return;
+
+ KURLDrag *d = new KURLDrag(urls, this);
+ d->setPixmap( FL_LOADICON( "file" ), QPoint( -7, 0 ) );
+ d->dragCopy();
+ }
+};
+
+KProcess * LocateDlg::updateProcess = 0;
+LocateDlg * LocateDlg::LocateDialog = 0;
+
+LocateDlg::LocateDlg() : KDialogBase(0,0,false,"Locate", KDialogBase::User1 | KDialogBase::User2 | KDialogBase::User3 | KDialogBase::Close,
+ KDialogBase::User3, false, i18n("Stop"), i18n("Update DB"), i18n("Locate") ), isFeedToListBox( false )
+{
+ QWidget *widget=new QWidget(this, "locateMainWidget");
+ QGridLayout *grid = new QGridLayout( widget );
+ grid->setSpacing( 6 );
+ grid->setMargin( 11 );
+
+ setPlainCaption( i18n( "Krusader::Locate" ) );
+
+ QHBox *hbox = new QHBox( widget, "locateHBox" );
+ QLabel *label = new QLabel( i18n( "Search for:" ), hbox, "locateLabel" );
+ locateSearchFor = new KHistoryCombo( false, hbox, "locateSearchFor" );
+ label->setBuddy( locateSearchFor );
+ krConfig->setGroup("Locate");
+ QStringList list = krConfig->readListEntry("Search For");
+ locateSearchFor->setMaxCount(25); // remember 25 items
+ locateSearchFor->setHistoryItems(list);
+ locateSearchFor->setEditable( true );
+ locateSearchFor->setDuplicatesEnabled( false );
+ locateSearchFor->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed);
+ locateSearchFor->lineEdit()->setFocus();
+
+ grid->addWidget( hbox, 0, 0 );
+
+ QHBox *hbox2 = new QHBox( widget, "locateHBox" );
+ QSpacerItem* spacer = new QSpacerItem( 40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ hbox2->layout()->addItem( spacer );
+ dontSearchInPath = new QCheckBox( i18n( "Don't search in path" ), hbox2, "dontSearchInPath" );
+ dontSearchInPath->setChecked( krConfig->readBoolEntry("Dont Search In Path") );
+ existingFiles = new QCheckBox( i18n( "Show only the existing files" ), hbox2, "existingFiles" );
+ existingFiles->setChecked( krConfig->readBoolEntry("Existing Files") );
+ caseSensitive = new QCheckBox( i18n( "Case Sensitive" ), hbox2, "caseSensitive" );
+ caseSensitive->setChecked( krConfig->readBoolEntry("Case Sensitive") );
+ grid->addWidget( hbox2, 1, 0 );
+
+ QFrame *line1 = new QFrame( widget, "locateLine1" );
+ line1->setFrameStyle( QFrame::HLine | QFrame::Sunken );
+ grid->addWidget( line1, 2, 0 );
+
+ resultList=new LocateListView( widget ); // create the main container
+
+ krConfig->setGroup("Look&Feel");
+ resultList->setFont(krConfig->readFontEntry("Filelist Font",_FilelistFont));
+
+ resultList->setAllColumnsShowFocus(true);
+ resultList->setVScrollBarMode(QScrollView::Auto);
+ resultList->setHScrollBarMode(QScrollView::Auto);
+ resultList->setShowSortIndicator(false);
+ resultList->setSorting(-1);
+ resultList->setSelectionMode( QListView::Extended );
+
+ resultList->addColumn( i18n("Results"), QFontMetrics(resultList->font()).width("W") * 60 );
+ resultList->setColumnWidthMode(0,QListView::Maximum);
+
+ connect( resultList,SIGNAL(rightButtonPressed(QListViewItem *, const QPoint &, int)),
+ this, SLOT(slotRightClick(QListViewItem *)));
+ connect( resultList,SIGNAL(doubleClicked(QListViewItem *)),
+ this, SLOT(slotDoubleClick(QListViewItem *)));
+ connect( resultList,SIGNAL(returnPressed(QListViewItem *)),
+ this, SLOT(slotDoubleClick(QListViewItem *)));
+
+ grid->addWidget( resultList, 3, 0 );
+
+ QFrame *line2 = new QFrame( widget, "locateLine2" );
+ line2->setFrameStyle( QFrame::HLine | QFrame::Sunken );
+ grid->addWidget( line2, 4, 0 );
+
+ enableButton( KDialogBase::User1, false ); /* disable the stop button */
+
+ if( updateProcess )
+ {
+ if( updateProcess->isRunning() )
+ {
+ connect( updateProcess, SIGNAL(processExited(KProcess *)), this, SLOT(updateFinished()));
+ enableButton( KDialogBase::User2, false );
+ }
+ else
+ updateFinished();
+ }
+
+ setMainWidget(widget);
+ show();
+
+ LocateDialog = this;
+}
+
+void LocateDlg::slotUser1() /* The stop / feed to listbox button */
+{
+ if( isFeedToListBox )
+ feedToListBox();
+ else
+ stopping = true;
+}
+
+void LocateDlg::slotUser2() /* The Update DB button */
+{
+ if( !updateProcess )
+ {
+ krConfig->setGroup("Locate");
+
+ updateProcess = new KProcess();
+ *updateProcess << KrServices::fullPathName( "updatedb" );
+ *updateProcess << KrServices::separateArgs( krConfig->readEntry( "UpdateDB Arguments", "" ) );
+
+ connect( updateProcess, SIGNAL(processExited(KProcess *)), this, SLOT(updateFinished()));
+ updateProcess->start(KProcess::NotifyOnExit);
+ enableButton( KDialogBase::User2, false );
+ }
+}
+
+void LocateDlg::updateFinished()
+{
+ delete updateProcess;
+ updateProcess = 0;
+ enableButton( KDialogBase::User2, true );
+}
+
+void LocateDlg::slotUser3() /* The locate button */
+{
+ locateSearchFor->addToHistory(locateSearchFor->currentText());
+ QStringList list = locateSearchFor->historyItems();
+ krConfig->setGroup("Locate");
+ krConfig->writeEntry("Search For", list);
+ krConfig->writeEntry("Dont Search In Path", dontSearchPath = dontSearchInPath->isChecked() );
+ krConfig->writeEntry("Existing Files", onlyExist = existingFiles->isChecked() );
+ krConfig->writeEntry("Case Sensitive", isCs = caseSensitive->isChecked() );
+
+ if( !KrServices::cmdExist( "locate" ) )
+ {
+ KMessageBox::error(0,
+ i18n("Can't start 'locate'! Check the 'Dependencies' page in konfigurator."));
+ return;
+ }
+
+ resultList->clear();
+ lastItem = 0;
+ remaining = "";
+
+ enableButton( KDialogBase::User3, false ); /* disable the locate button */
+ enableButton( KDialogBase::User1, true ); /* enable the stop button */
+ setButtonText( KDialogBase::User1, i18n( "Stop" ) ); /* the button behaves as stop */
+ isFeedToListBox = false;
+ resultList->setFocus();
+
+ qApp->processEvents();
+
+ stopping = false;
+
+ KProcess locateProc;
+ connect( &locateProc, SIGNAL( receivedStdout(KProcess *, char *, int) ),
+ this, SLOT( processStdout(KProcess *, char *, int) ) );
+ connect( &locateProc, SIGNAL( receivedStderr(KProcess *, char *, int) ),
+ this, SLOT( processStderr(KProcess *, char *, int) ) );
+
+ locateProc << KrServices::fullPathName( "locate" );
+ if( !isCs )
+ locateProc << "-i";
+ locateProc << (pattern = locateSearchFor->currentText());
+
+ if( !pattern.startsWith( "*" ) )
+ pattern = "*" + pattern;
+ if( !pattern.endsWith( "*" ) )
+ pattern = pattern + "*";
+
+ collectedErr = "";
+ bool result = !locateProc.start( KProcess::Block, KProcess::AllOutput );
+ if( !collectedErr.isEmpty() && ( !locateProc.normalExit() || locateProc.exitStatus() ) )
+ {
+ KMessageBox::error( krApp, i18n( "Locate produced the following error message:\n\n" ) + collectedErr );
+ }else if ( result )
+ {
+ KMessageBox::error( krApp, i18n( "Error during the start of 'locate' process!" ) );
+ }
+ enableButton( KDialogBase::User3, true ); /* enable the locate button */
+
+ if( resultList->childCount() == 0 )
+ {
+ locateSearchFor->setFocus();
+ enableButton( KDialogBase::User1, false ); /* disable the stop button */
+ isFeedToListBox = false;
+ }else{
+ setButtonText( KDialogBase::User1, i18n("Feed to listbox") ); /* feed to listbox */
+ isFeedToListBox = true;
+ }
+}
+
+void LocateDlg::processStdout(KProcess *proc, char *buffer, int length)
+{
+ char *buf = new char[ length+1 ];
+ memcpy( buf, buffer, length );
+ buf[ length ] = 0;
+
+ remaining += QString::fromLocal8Bit( buf );
+ delete []buf;
+
+ QStringList list = QStringList::split("\n", remaining );
+ int items = list.size();
+
+ for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it )
+ {
+ if( --items == 0 && buffer[length-1] != '\n' )
+ remaining = *it;
+ else
+ {
+ if( dontSearchPath )
+ {
+ QRegExp regExp( pattern, isCs, true );
+ QString fileName = (*it).stripWhiteSpace();
+ if( fileName.endsWith( "/" ) && fileName != "/" )
+ fileName.truncate( fileName.length() -1 );
+ fileName = fileName.mid( fileName.findRev( '/' ) + 1 );
+
+ if( !regExp.exactMatch( fileName ) )
+ continue;
+ }
+ if( onlyExist )
+ {
+ KFileItem file(KFileItem::Unknown, KFileItem::Unknown, (*it).stripWhiteSpace() );
+ if( !file.isReadable() )
+ continue;
+ }
+
+ if( lastItem )
+ lastItem = new KListViewItem( resultList, lastItem, *it );
+ else
+ lastItem = new KListViewItem( resultList, *it );
+
+ lastItem->setDragEnabled( true );
+ }
+ }
+
+ if( stopping )
+ proc->kill( SIGKILL );
+
+ qApp->processEvents();
+}
+
+void LocateDlg::processStderr(KProcess *, char *buffer, int length)
+{
+ char *buf = new char[ length+1 ];
+ memcpy( buf, buffer, length );
+ buf[ length ] = 0;
+
+ collectedErr += QString::fromLocal8Bit( buf );
+ delete []buf;
+}
+
+void LocateDlg::slotRightClick(QListViewItem *item)
+{
+ if ( !item )
+ return;
+
+ // create the menu
+ KPopupMenu popup;
+ popup.insertTitle(i18n("Locate"));
+
+ popup.insertItem(i18n("View (F3)"), VIEW_ID);
+ popup.insertItem(i18n("Edit (F4)"), EDIT_ID);
+
+ popup.insertSeparator();
+
+ popup.insertItem(i18n("Find (Ctrl+F)"), FIND_ID);
+ popup.insertItem(i18n("Find next (Ctrl+N)"), FIND_NEXT_ID);
+ popup.insertItem(i18n("Find previous (Ctrl+P)"), FIND_PREV_ID);
+
+ popup.insertSeparator();
+
+ popup.insertItem(i18n("Copy selected to clipboard"), COPY_SELECTED_TO_CLIPBOARD);
+
+
+ int result=popup.exec(QCursor::pos());
+
+ // check out the user's option
+ switch (result)
+ {
+ case VIEW_ID:
+ case EDIT_ID:
+ case FIND_ID:
+ case FIND_NEXT_ID:
+ case FIND_PREV_ID:
+ case COPY_SELECTED_TO_CLIPBOARD:
+ operate( item, result );
+ break;
+ }
+}
+
+void LocateDlg::slotDoubleClick(QListViewItem *item)
+{
+ if ( !item )
+ return;
+
+ QString dirName = item->text(0);
+ QString fileName;
+
+ if( !QDir( dirName ).exists() )
+ {
+ fileName = dirName.mid( dirName.findRev( '/' ) + 1 );
+ dirName.truncate( dirName.findRev( '/' ) );
+ }
+
+ ACTIVE_FUNC->openUrl(vfs::fromPathOrURL( dirName ), fileName );
+ KDialogBase::accept();
+}
+
+void LocateDlg::keyPressEvent( QKeyEvent *e )
+{
+ if( Krusader::actCopy->shortcut().contains( KKey( e ) ) )
+ {
+ operate( 0, COPY_SELECTED_TO_CLIPBOARD );
+ e->accept();
+ return;
+ }
+
+ switch ( e->key() )
+ {
+ case Key_M :
+ if( e->state() == ControlButton )
+ {
+ resultList->setFocus();
+ e->accept();
+ }
+ break;
+ case Key_F3 :
+ if( resultList->currentItem() )
+ operate( resultList->currentItem(), VIEW_ID );
+ break;
+ case Key_F4 :
+ if( resultList->currentItem() )
+ operate( resultList->currentItem(), EDIT_ID );
+ break;
+ case Key_N :
+ if ( e->state() == ControlButton )
+ operate( resultList->currentItem(), FIND_NEXT_ID );
+ break;
+ case Key_P :
+ if ( e->state() == ControlButton )
+ operate( resultList->currentItem(), FIND_PREV_ID );
+ break;
+ case Key_F :
+ if ( e->state() == ControlButton )
+ operate( resultList->currentItem(), FIND_ID );
+ break;
+ }
+
+ QDialog::keyPressEvent( e );
+}
+
+void LocateDlg::operate( QListViewItem *item, int task )
+{
+ KURL name;
+ if( item != 0 )
+ name = vfs::fromPathOrURL( item->text( 0 ) );
+
+ switch ( task )
+ {
+ case VIEW_ID:
+ KrViewer::view( name, this ); // view the file
+ break;
+ case EDIT_ID:
+ KrViewer::edit( name, this ); // view the file
+ break;
+ case FIND_ID:
+ {
+ krConfig->setGroup("Locate");
+ long options = krConfig->readNumEntry("Find Options", 0);
+ QStringList list = krConfig->readListEntry("Find Patterns");
+
+ KFindDialog dlg( this, "locateFindDialog", options, list );
+ if ( dlg.exec() != QDialog::Accepted )
+ return;
+
+ if( list.first() != ( findPattern = dlg.pattern() ) )
+ list.push_front( dlg.pattern() );
+
+ krConfig->writeEntry( "Find Options", findOptions = dlg.options() );
+ krConfig->writeEntry( "Find Patterns", list );
+
+ if( !( findOptions & KFindDialog::FromCursor ) )
+ resultList->setCurrentItem( ( findOptions & KFindDialog::FindBackwards ) ?
+ resultList->lastItem() : resultList->firstChild() );
+
+ findCurrentItem = (KListViewItem *)resultList->currentItem();
+
+ if( find() && findCurrentItem )
+ resultList->setCurrentItem( findCurrentItem );
+ else
+ KMessageBox::information( 0, i18n( "Search string not found!" ) );
+
+ resultList->ensureItemVisible( resultList->currentItem() );
+ }
+ break;
+ case FIND_NEXT_ID:
+ case FIND_PREV_ID:
+ {
+ if( task == FIND_PREV_ID )
+ findOptions ^= KFindDialog::FindBackwards;
+
+ findCurrentItem = (KListViewItem *)resultList->currentItem();
+ nextLine();
+
+ if( find() && findCurrentItem )
+ resultList->setCurrentItem( findCurrentItem );
+ else
+ KMessageBox::information( 0, i18n( "Search string not found!" ) );
+
+ resultList->ensureItemVisible( resultList->currentItem() );
+
+ if( task == FIND_PREV_ID )
+ findOptions ^= KFindDialog::FindBackwards;
+ }
+ break;
+ case COPY_SELECTED_TO_CLIPBOARD:
+ {
+ KURL::List urls;
+
+ QListViewItem * item = resultList->firstChild();
+ while( item )
+ {
+ if( item->isSelected() )
+ urls.push_back( vfs::fromPathOrURL( item->text( 0 ) ) );
+
+ item = item->nextSibling();
+ }
+
+ if( urls.count() == 0 )
+ return;
+
+ KURLDrag *d = new KURLDrag(urls, this);
+ d->setPixmap( FL_LOADICON( "file" ), QPoint( -7, 0 ) );
+ QApplication::clipboard()->setData( d );
+ }
+ break;
+ }
+}
+
+void LocateDlg::nextLine()
+{
+ if( findOptions & KFindDialog::FindBackwards )
+ findCurrentItem = (KListViewItem *)findCurrentItem->itemAbove();
+ else
+ findCurrentItem = (KListViewItem *)findCurrentItem->itemBelow();
+}
+
+bool LocateDlg::find()
+{
+ while( findCurrentItem )
+ {
+ QString item = findCurrentItem->text( 0 );
+
+ if( findOptions & KFindDialog::RegularExpression )
+ {
+ if( item.contains( QRegExp( findPattern, findOptions & KFindDialog::CaseSensitive ) ) )
+ return true;
+ }
+ else
+ {
+ if( item.contains( findPattern, findOptions & KFindDialog::CaseSensitive ) )
+ return true;
+ }
+
+ nextLine();
+ }
+
+ return false;
+}
+
+void LocateDlg::feedToListBox()
+{
+ virt_vfs v(0,true);
+ v.vfs_refresh( KURL( "/" ) );
+
+ krConfig->setGroup( "Locate" );
+ int listBoxNum = krConfig->readNumEntry( "Feed To Listbox Counter", 1 );
+ QString queryName;
+ do {
+ queryName = i18n("Locate results")+QString( " %1" ).arg( listBoxNum++ );
+ }while( v.vfs_search( queryName ) != 0 );
+ krConfig->writeEntry( "Feed To Listbox Counter", listBoxNum );
+
+ krConfig->setGroup( "Advanced" );
+ if ( krConfig->readBoolEntry( "Confirm Feed to Listbox", _ConfirmFeedToListbox ) ) {
+ bool ok;
+ queryName = KInputDialog::getText(
+ i18n("Query name"), // Caption
+ i18n("Here you can name the file collection"), // Questiontext
+ queryName, // Default
+ &ok );
+ if ( ! ok)
+ return;
+ }
+
+ KURL::List urlList;
+ QListViewItem * item = resultList->firstChild();
+ while( item )
+ {
+ urlList.push_back( vfs::fromPathOrURL( item->text( 0 ) ) );
+ item = item->nextSibling();
+ }
+ KURL url = KURL::fromPathOrURL(QString("virt:/")+ queryName);
+ v.vfs_refresh( url );
+ v.vfs_addFiles( &urlList, KIO::CopyJob::Copy, 0 );
+ //ACTIVE_FUNC->openUrl(url);
+ ACTIVE_MNG->slotNewTab(url.prettyURL());
+ accept();
+}
+
+void LocateDlg::reset()
+{
+ locateSearchFor->lineEdit()->setFocus();
+ locateSearchFor->lineEdit()->selectAll();
+}
+
+#include "locate.moc"
diff --git a/krusader/Locate/locate.h b/krusader/Locate/locate.h
new file mode 100755
index 0000000..e99b987
--- /dev/null
+++ b/krusader/Locate/locate.h
@@ -0,0 +1,100 @@
+/***************************************************************************
+ locate.h - description
+ -------------------
+ copyright : (C) 2004 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __LOCATE_H__
+#define __LOCATE_H__
+
+#include <kdialogbase.h>
+#include <kcombobox.h>
+#include <klistview.h>
+#include <kprocess.h>
+#include <qcheckbox.h>
+
+class LocateDlg : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ LocateDlg();
+
+ static LocateDlg *LocateDialog;
+
+ virtual void slotUser1();
+ virtual void slotUser2();
+ virtual void slotUser3();
+ virtual void feedToListBox();
+
+ void reset();
+
+public slots:
+ void processStdout(KProcess *, char *, int);
+ void processStderr(KProcess *proc, char *buffer, int length);
+ void slotRightClick(QListViewItem *);
+ void slotDoubleClick(QListViewItem *);
+ void updateFinished();
+
+protected:
+ virtual void keyPressEvent( QKeyEvent * );
+
+private:
+ void operate( QListViewItem *item, int task );
+
+ bool find();
+ void nextLine();
+
+ bool stopping;
+
+ bool dontSearchPath;
+ bool onlyExist;
+ bool isCs;
+
+ bool isFeedToListBox;
+
+ QString pattern;
+
+ KHistoryCombo *locateSearchFor;
+ KListView *resultList;
+ QString remaining;
+ KListViewItem *lastItem;
+
+ QString collectedErr;
+
+ long findOptions;
+ QString findPattern;
+ KListViewItem *findCurrentItem;
+
+ QCheckBox *dontSearchInPath;
+ QCheckBox *existingFiles;
+ QCheckBox *caseSensitive;
+
+ static KProcess *updateProcess;
+};
+
+#endif /* __LOCATE_H__ */
diff --git a/krusader/Makefile.am b/krusader/Makefile.am
new file mode 100644
index 0000000..bfc36b7
--- /dev/null
+++ b/krusader/Makefile.am
@@ -0,0 +1,192 @@
+# the condition for this is found in configure.in.in
+if include_libkonq
+LIB_KONQ = -lkonq
+endif
+
+# the condition for this is found in configure.in.in
+if include_libkjsembed
+AM_CPPFLAGS = -D__KJSEMBED__
+LIB_KJSEMBED = -lkjsembed
+KRJSDIR = KrJS
+LIB_KRJS = KrJS/libKrJS.a
+endif
+
+
+# these subdirs are also visited during the build-process
+SUBDIRS = \
+ ActionMan \
+ BookMan \
+ Dialogs \
+ DiskUsage \
+ Filter \
+ GUI \
+ Konfigurator \
+ KViewer \
+ Locate \
+ MountMan \
+ Queue \
+ Panel \
+ RemoteMan \
+ Search \
+ Splitter \
+ Synchronizer \
+ UserAction \
+ $(KRJSDIR) \
+ UserMenu \
+ VFS
+
+
+###########################################################
+######################## BUILDING #########################
+##########################################################
+
+
+# the programm which is build and installed:
+bin_PROGRAMS = krusader
+
+
+krusader_SOURCES = \
+ paneltabbar.cpp \
+ panelmanager.cpp \
+ krservices.cpp \
+ main.cpp \
+ krusaderview.cpp \
+ krusader.cpp \
+ krslots.cpp \
+ kicons.cpp
+
+
+# this makes that .ui and .moc files are generated automaticly.
+# to make this happen include filename.moc at the end of filename.cpp (assuming that filename.h is the header to use)
+# and add filename.ui to the *_SOURCES
+METASOURCES = AUTO
+
+
+# set the include path for X, qt and KDE
+INCLUDES= $(all_includes)
+
+# these are the libs which are liked together for krusader.
+# the correct order is very important, also the double entries are necessary!
+krusader_LDADD = \
+ BookMan/libBookMan.a \
+ Dialogs/libDialogs.a \
+ DiskUsage/libDiskUsage.a \
+ DiskUsage/radialMap/libradialmap.a \
+ DiskUsage/filelightParts/libfilelightparts.a \
+ GUI/libGUI.a \
+ Konfigurator/libKonfigurator.a \
+ KViewer/libKViewer.a \
+ MountMan/libMountMan.a \
+ Panel/libPanel.a \
+ Queue/libQueue.a \
+ RemoteMan/libRemoteMan.a \
+ VFS/libVFS.a \
+ Search/libSearch.a \
+ Splitter/libSplitter.a \
+ Synchronizer/libSynchronizer.a \
+ UserMenu/libUserMenu.a \
+ Locate/libLocate.a \
+ UserAction/libUserAction.a \
+ ActionMan/libActionMan.a \
+ $(LIB_KRJS) \
+ KViewer/libKViewer.a \
+ Filter/libFilter.a \
+ Dialogs/libDialogs.a \
+ GUI/libGUI.a \
+ $(LIB_KONQ) \
+ $(LIB_KJSEMBED) \
+ $(LIB_KPARTS) \
+ $(LIB_KFILE) \
+ $(LIB_KHTML) \
+ $(LIB_KDEUI) \
+ $(LIB_KDECORE) \
+ $(LIB_QT) \
+ $(LIBSOCKET)
+
+
+# the library search path.
+krusader_LDFLAGS = $(all_libraries) $(kde_RPATH)
+
+
+###########################################################
+###################### INSTALLING #########################
+##########################################################
+
+
+# this installes alle the icons in the current dir.
+# see the comment in krusader_kde3/icons/Makefile.am for more info
+KDE_ICON = AUTO
+
+# How it works (by jonas):
+# somenamedir = /path/what/ever # a directory
+# somename_DATA = file1 file2 file3 # the data whichshold be installed there
+
+# These paths are KDE specific. Use them (jonas: taken from the old Makefile.am):
+# kde_appsdir Where your application's menu entry (.desktop) should go to.
+# xdg_appsdir Where your application's .desktop-files should go acording to freedesktop.org's standard
+# kde_icondir Where your icon should go to - better use KDE_ICON.
+# kde_sounddir Where your sounds should go to.
+# kde_htmldir Where your docs should go to. (contains lang subdirs)
+# kde_datadir Where you install application data. (Use a subdir)
+# kde_locale Where translation files should go to. (contains lang subdirs)
+# kde_cgidir Where cgi-bin executables should go to.
+# kde_confdir Where config files should go to (system-wide ones with default values).
+# kde_mimedir Where mimetypes .desktop files should go to.
+# kde_servicesdir Where services .desktop files should go to.
+# kde_servicetypesdir Where servicetypes .desktop files should go to.
+# kde_wallpaperdir Where general wallpapers should go to.
+# kde_templatesdir Where templates for the "New" menu (Konqueror/KDesktop) should go to.
+# kde_bindir Where executables should go to. Use bin_PROGRAMS or bin_SCRIPTS.
+# kde_libdir Where shared libraries should go to. Use lib_LTLIBRARIES.
+# kde_moduledir Where modules (e.g. parts) should go to. Use kde_module_LTLIBRARIES.
+# kde_styledir Where Qt/KDE widget styles should go to (new in KDE 3).
+# kde_designerdir Where Qt Designer plugins should go to (new in KDE 3).
+
+
+# this installes the .desktop-files at hte right place
+# use 'xdg' instead of 'kde' here to follow freedesktop.org's standard (jonas)
+xdg_apps_DATA = \
+ krusader.desktop \
+ krusader_root-mode.desktop
+
+# this installes all additional data.
+krusaderlocaldir = $(kde_datadir)/krusader
+krusaderlocal_DATA = \
+ krusaderui.rc \
+ alpa-yellow.color \
+ bash.color \
+ dos_navigator.color \
+ midnight_commander.color \
+ midnight_cmd_AHamann.color \
+ total_commander.color \
+ total_cmd_pleasent.color \
+ midnight_commander.keymap \
+ midnight_commander.keymap.info \
+ total_commander.keymap \
+ total_commander.keymap.info \
+ useraction_examples.xml \
+ splash.png
+
+# this installs data for example javascript useractions.
+krusaderuajsdir = $(kde_datadir)/krusader/js
+krusaderuajs_DATA = \
+ recode.js \
+ recode.ui \
+ mount.js \
+ mount.ui \
+ calc.js \
+ calc.ui \
+ select_from_file.js
+
+# Jonas: I've no idea how this thing works so I leave it like it was.
+
+# WARNING: if you use a ui.rc file above, use:
+# messages: rc.cpp
+# instead of
+# messages:
+
+messages: rc.cpp
+ LIST=`find . -name \*.h -o -name \*.hh -o -name \*.H -o -name \*.hxx -o -name \*.hpp -o -name \*.cpp -o -name \*.cc -o -name \*.cxx -o -name \*.ecpp -o -name \*.C`; \
+ if test -n "$$LIST"; then \
+ $(XGETTEXT) $$LIST -o $(podir)/krusader.pot; \
+ fi
diff --git a/krusader/MountMan/Makefile.am b/krusader/MountMan/Makefile.am
new file mode 100644
index 0000000..3e3f35c
--- /dev/null
+++ b/krusader/MountMan/Makefile.am
@@ -0,0 +1,10 @@
+noinst_LIBRARIES = libMountMan.a
+
+INCLUDES = $(all_includes)
+
+libMountMan_a_METASOURCES = AUTO
+
+libMountMan_a_SOURCES = \
+ kmountmangui.cpp \
+ kmountman.cpp \
+ kdiskfreesp.cpp
diff --git a/krusader/MountMan/kdiskfreesp.cpp b/krusader/MountMan/kdiskfreesp.cpp
new file mode 100644
index 0000000..a8a58fc
--- /dev/null
+++ b/krusader/MountMan/kdiskfreesp.cpp
@@ -0,0 +1,168 @@
+/*
+ * kdiskfreesp.cpp
+ *
+ * Copyright (c) 1999 Michael Kropfberger <michael.kropfberger@gmx.net>
+ *
+ * Requires the Qt widget libraries, available at no cost at
+ * http://www.troll.no/
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "kdiskfreesp.h"
+#include <qfile.h>
+#include <qtextstream.h>
+
+#include <kdebug.h>
+#include <kprocess.h>
+#include <kio/global.h>
+
+#include "kdiskfreesp.moc"
+
+#define DF_COMMAND "df"
+#define DF_ARGS "-k"
+#define NO_FS_TYPE true
+
+#define BLANK ' '
+#define FULL_PERCENT 95.0
+
+/***************************************************************************
+ * constructor
+**/
+KDiskFreeSp::KDiskFreeSp(QObject *parent, const char *name)
+ : QObject(parent,name)
+{
+ dfProc = new KProcess(); Q_CHECK_PTR(dfProc);
+ dfProc->setEnvironment("LANGUAGE", "C");
+ connect( dfProc, SIGNAL(receivedStdout(KProcess *, char *, int) ),
+ this, SLOT (receivedDFStdErrOut(KProcess *, char *, int)) );
+ connect(dfProc,SIGNAL(processExited(KProcess *) ),
+ this, SLOT(dfDone() ) );
+
+ readingDFStdErrOut=false;
+}
+
+
+/***************************************************************************
+ * destructor
+**/
+KDiskFreeSp::~KDiskFreeSp()
+{
+ delete dfProc;
+}
+
+/***************************************************************************
+ * is called, when the df-command writes on StdOut
+**/
+void KDiskFreeSp::receivedDFStdErrOut(KProcess *, char *data, int len)
+{
+ QCString tmp(data,len+1); // adds a zero-byte
+ dfStringErrOut.append(tmp);
+}
+
+/***************************************************************************
+ * reads the df-commands results
+**/
+int KDiskFreeSp::readDF( const QString & mountPoint )
+{
+ if (readingDFStdErrOut || dfProc->isRunning())
+ return -1;
+ m_mountPoint = mountPoint;
+ dfStringErrOut=""; // yet no data received
+ dfProc->clearArguments();
+ (*dfProc) << QString::fromLocal8Bit(DF_COMMAND) << QString::fromLocal8Bit(DF_ARGS) << mountPoint;
+ if (!dfProc->start( KProcess::NotifyOnExit, KProcess::AllOutput ))
+ kdError() << "could not execute ["<< DF_COMMAND << "]" << endl;
+ return 1;
+}
+
+
+/***************************************************************************
+ * is called, when the df-command has finished
+**/
+void KDiskFreeSp::dfDone()
+{
+ readingDFStdErrOut=true;
+
+ QTextStream t (dfStringErrOut, IO_ReadOnly);
+ QString s=t.readLine();
+ if ( (s.isEmpty()) || ( s.left(10) != QString::fromLatin1("Filesystem") ) )
+ kdError() << "Error running df command... got [" << s << "]" << endl;
+ while ( !t.eof() ) {
+ QString u,v;
+ s=t.readLine();
+ s=s.simplifyWhiteSpace();
+ if ( !s.isEmpty() ) {
+ //kdDebug(kfile_area) << "GOT: [" << s << "]" << endl;
+
+ if (s.find(BLANK)<0) // devicename was too long, rest in next line
+ if ( !t.eof() ) { // just appends the next line
+ v=t.readLine();
+ s=s.append(v);
+ s=s.simplifyWhiteSpace();
+ //kdDebug(kfile_area) << "SPECIAL GOT: [" << s << "]" << endl;
+ }//if silly linefeed
+
+ //kdDebug(kfile_area) << "[" << s << "]" << endl;
+
+ //QString deviceName = s.left(s.find(BLANK));
+ s=s.remove(0,s.find(BLANK)+1 );
+ //kdDebug(kfile_area) << " DeviceName: [" << deviceName << "]" << endl;
+
+ if (!NO_FS_TYPE)
+ s=s.remove(0,s.find(BLANK)+1 ); // eat fs type
+
+ u=s.left(s.find(BLANK));
+ unsigned long kBSize = u.toULong();
+ s=s.remove(0,s.find(BLANK)+1 );
+ //kdDebug(kfile_area) << " Size: [" << kBSize << "]" << endl;
+
+ u=s.left(s.find(BLANK));
+ unsigned long kBUsed = u.toULong();
+ s=s.remove(0,s.find(BLANK)+1 );
+ //kdDebug(kfile_area) << " Used: [" << kBUsed << "]" << endl;
+
+ u=s.left(s.find(BLANK));
+ unsigned long kBAvail = u.toULong();
+ s=s.remove(0,s.find(BLANK)+1 );
+ //kdDebug(kfile_area) << " Avail: [" << kBAvail << "]" << endl;
+
+
+ s=s.remove(0,s.find(BLANK)+1 ); // delete the capacity 94%
+ QString mountPoint = s.stripWhiteSpace();
+ //kdDebug(kfile_area) << " MountPoint: [" << mountPoint << "]" << endl;
+
+ if ( mountPoint == m_mountPoint )
+ {
+ //kdDebug(kfile_area) << "Found mount point. Emitting" << endl;
+ emit foundMountPoint( mountPoint, kBSize, kBUsed, kBAvail );
+ emit foundMountPoint( kBSize, kBUsed, kBAvail, mountPoint ); // sic!
+ }
+ }//if not header
+ }//while further lines available
+
+ readingDFStdErrOut=false;
+ emit done();
+ delete this;
+}
+
+KDiskFreeSp * KDiskFreeSp::findUsageInfo( const QString & path )
+{
+ KDiskFreeSp * job = new KDiskFreeSp;
+ QString mountPoint = KIO::findPathMountPoint( path );
+ job->readDF( mountPoint );
+ return job;
+}
diff --git a/krusader/MountMan/kdiskfreesp.h b/krusader/MountMan/kdiskfreesp.h
new file mode 100644
index 0000000..ff0e039
--- /dev/null
+++ b/krusader/MountMan/kdiskfreesp.h
@@ -0,0 +1,88 @@
+/*
+ * kdiskfreesp.h
+ *
+ * Copyright (c) 1999 Michael Kropfberger <michael.kropfberger@gmx.net>
+ *
+ * Requires the Qt widget libraries, available at no cost at
+ * http://www.troll.no/
+ *
+ * Modifed for Krusader by shie erlich, October 2004
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef __KDISKFREESP_H__
+#define __KDISKFREESP_H__
+
+#include <qobject.h>
+#include <qstring.h>
+
+class KProcess;
+
+/**
+ * This class parses the output of "df" to find the disk usage
+ * information for a given partition (mount point).
+ */
+class KDiskFreeSp : public QObject
+{ Q_OBJECT
+public:
+ KDiskFreeSp( QObject *parent=0, const char *name=0 );
+ /**
+ * Destructor - this object autodeletes itself when it's done
+ */
+ ~KDiskFreeSp();
+ /**
+ * Call this to fire a search on the disk usage information
+ * for @p mountPoint. foundMountPoint will be emitted
+ * if this mount point is found, with the info requested.
+ * done is emitted in any case.
+ */
+ int readDF( const QString & mountPoint );
+
+ /**
+ * Call this to fire a search on the disk usage information
+ * for the mount point containing @p path.
+ * foundMountPoint will be emitted
+ * if this mount point is found, with the info requested.
+ * done is emitted in any case.
+ */
+ static KDiskFreeSp * findUsageInfo( const QString & path );
+
+signals:
+ void foundMountPoint( const QString & mountPoint, unsigned long kBSize, unsigned long kBUsed, unsigned long kBAvail );
+
+ // This one is a hack around a weird (compiler?) bug. In the former signal,
+ // the slot in KPropsDlg would get 0L, 0L as the last two parameters.
+ // When using const ulong& instead, all is ok.
+ void foundMountPoint( const unsigned long&, const unsigned long&, const unsigned long&, const QString& );
+ void done();
+
+private slots:
+ void receivedDFStdErrOut(KProcess *, char *data, int len);
+ void dfDone();
+
+private:
+ KProcess *dfProc;
+ QCString dfStringErrOut;
+ QString m_mountPoint;
+ bool readingDFStdErrOut;
+ class KDiskFreeSpPrivate;
+ KDiskFreeSpPrivate * d;
+};
+/***************************************************************************/
+
+
+#endif
diff --git a/krusader/MountMan/kmountman.cpp b/krusader/MountMan/kmountman.cpp
new file mode 100644
index 0000000..7728fc4
--- /dev/null
+++ b/krusader/MountMan/kmountman.cpp
@@ -0,0 +1,327 @@
+/***************************************************************************
+ kmountman.cpp
+ -------------------
+copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+e-mail : krusader@users.sourceforge.net
+web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+
+A
+
+db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+
+#include <sys/param.h>
+#include <time.h>
+#include "kmountman.h"
+// KDE includes
+#include <kmessagebox.h>
+#include <kprocess.h>
+#include <klocale.h>
+#include <kpopupmenu.h>
+#include <kdebug.h>
+
+// Krusader includes
+#include "../krusader.h"
+#include "../defaults.h"
+#include "../Dialogs/krdialogs.h"
+#include "../krservices.h"
+#include "kmountmangui.h"
+#include <unistd.h>
+#include "../Dialogs/krprogress.h"
+#include "../VFS/krpermhandler.h"
+
+#ifdef _OS_SOLARIS_
+#define FSTAB "/etc/vfstab"
+#else
+#define FSTAB "/etc/fstab"
+#endif
+
+static int __delayedIdx; // ugly: pass the processEvents deadlock
+
+KMountMan::KMountMan() : QObject(), Operational( false ), waiting(false), mountManGui( 0 ) {
+ _actions = 0L;
+
+ // added as a precaution, although we use kde services now
+ if( !KrServices::cmdExist( "df" ) || !KrServices::cmdExist( "mount" ) ) {
+ Operational = false;
+ } else {
+ Operational = true;
+ }
+
+ // list of FS that we don't manage at all
+ invalid_fs << "swap" << "/dev/pts" << "tmpfs" << "devpts" << "sysfs" << "rpc_pipefs" << "usbfs" << "binfmt_misc";
+#if defined(BSD)
+ invalid_fs << "procfs";
+#else
+ invalid_fs << "proc";
+#endif
+
+ // list of FS that we don't allow to mount/unmount
+ nonmount_fs << "supermount";
+ {
+ KConfigGroupSaver saver(krConfig, "Advanced");
+ QStringList nonmount = QStringList::split(",", krConfig->readEntry("Nonmount Points", _NonMountPoints));
+ nonmount_fs_mntpoint += nonmount;
+ // simplify the white space
+ for ( QStringList::Iterator it = nonmount_fs_mntpoint.begin(); it != nonmount_fs_mntpoint.end(); ++it ) {
+ *it = (*it).simplifyWhiteSpace();
+ }
+ }
+
+}
+
+KMountMan::~KMountMan() {}
+
+bool KMountMan::invalidFilesystem(QString type) {
+ return (invalid_fs.contains(type) > 0);
+}
+
+// this is an ugly hack, but type can actually be a mountpoint. oh well...
+bool KMountMan::nonmountFilesystem(QString type, QString mntPoint) {
+ return((nonmount_fs.contains(type) > 0) || (nonmount_fs_mntpoint.contains(mntPoint) > 0));
+}
+
+void KMountMan::mainWindow() {
+ mountManGui = new KMountManGUI();
+ delete mountManGui; /* as KMountManGUI is modal, we can now delete it */
+ mountManGui = 0; /* for sanity */
+}
+
+KMountPoint *KMountMan::findInListByMntPoint(KMountPoint::List &lst, QString value) {
+ KMountPoint *m;
+ for (KMountPoint::List::iterator it = lst.begin(); it != lst.end(); ++it) {
+ m = *it;
+ if (m->mountPoint() == value)
+ return m;
+ }
+
+ return 0;
+}
+
+void KMountMan::jobResult(KIO::Job *job) {
+ waiting = false;
+ if ( job->error() )
+ job->showErrorDialog( 0 );
+}
+
+void KMountMan::mount( QString mntPoint, bool blocking ) {
+ KMountPoint::List possible = KMountPoint::possibleMountPoints(KMountPoint::NeedMountOptions);
+ KMountPoint *m = findInListByMntPoint(possible, mntPoint);
+ if (!m) return;
+ if (blocking)
+ waiting = true; // prepare to block
+ KIO::SimpleJob *job = KIO::mount(false, m->mountType().local8Bit(), m->mountedFrom(), m->mountPoint(), false);
+ new KrProgress(job);
+ connect(job, SIGNAL(result(KIO::Job* )), this, SLOT(jobResult(KIO::Job* )));
+ while (blocking && waiting) {
+ qApp->processEvents();
+ usleep( 1000 );
+ }
+}
+
+void KMountMan::unmount( QString mntPoint, bool blocking ) {
+ if (blocking)
+ waiting = true; // prepare to block
+ KIO::SimpleJob *job = KIO::unmount(mntPoint, false);
+ new KrProgress(job);
+ connect(job, SIGNAL(result(KIO::Job* )), this, SLOT(jobResult(KIO::Job* )));
+ while (blocking && waiting) {
+ qApp->processEvents();
+ usleep( 1000 );
+ }
+}
+
+KMountMan::mntStatus KMountMan::getStatus( QString mntPoint ) {
+ KMountPoint::List::iterator it;
+ KMountPoint *m;
+
+ // 1: is it already mounted
+ KMountPoint::List current = KMountPoint::currentMountPoints();
+ m = findInListByMntPoint(current, mntPoint);
+ if (m)
+ return MOUNTED;
+
+ // 2: is it a mount point but not mounted?
+ KMountPoint::List possible = KMountPoint::possibleMountPoints();
+ m = findInListByMntPoint(possible, mntPoint);
+ if (m)
+ return NOT_MOUNTED;
+
+ // 3: unknown
+ return DOESNT_EXIST;
+}
+
+
+void KMountMan::toggleMount( QString mntPoint ) {
+ mntStatus status = getStatus(mntPoint);
+ switch (status) {
+ case MOUNTED:
+ unmount(mntPoint);
+ break;
+ case NOT_MOUNTED:
+ mount(mntPoint);
+ break;
+ case DOESNT_EXIST:
+ // do nothing: no-op to make the compiler quiet ;-)
+ break;
+ }
+}
+
+void KMountMan::autoMount( QString path ) {
+ if ( getStatus( path ) == NOT_MOUNTED )
+ mount( path );
+}
+
+void KMountMan::eject( QString mntPoint ) {
+ KShellProcess proc;
+ proc << KrServices::fullPathName( "eject" ) << "'" + mntPoint + "'";
+ proc.start( KProcess::Block );
+ if ( !proc.normalExit() || proc.exitStatus() != 0 ) // if we failed with eject
+ KMessageBox::information( 0, i18n( "Error ejecting device! You need to have 'eject' in your path." ), i18n( "Error" ), "CantExecuteEjectWarning" );
+}
+
+// returns true if the path is an ejectable mount point (at the moment CDROM and DVD)
+bool KMountMan::ejectable( QString path ) {
+#if !defined(BSD) && !defined(_OS_SOLARIS_)
+ KMountPoint::List possible = KMountPoint::possibleMountPoints();
+ KMountPoint *m = findInListByMntPoint(possible, path);
+ if (m && (m->mountType()=="iso9660" || m->mountedFrom().left(7)=="/dev/cd" || m->mountedFrom().left(8)=="/dev/dvd"))
+ return KrServices::cmdExist( "eject" );
+#endif
+
+ return false;
+}
+
+
+// a mountMan special version of KIO::convertSize, which deals
+// with large filesystems ==> >4GB, it actually recieve size in
+// a minimum block of 1024 ==> data is KB not bytes
+QString KMountMan::convertSize( KIO::filesize_t size ) {
+ float fsize;
+ QString s;
+ // Tera-byte
+ if ( size >= 1073741824 ) {
+ fsize = ( float ) size / ( float ) 1073741824;
+ if ( fsize > 1024 ) // no name for something bigger than tera byte
+ // let's call it Zega-Byte, who'll ever find out? :-)
+ s = i18n( "%1 ZB" ).arg( KGlobal::locale() ->formatNumber( fsize / ( float ) 1024, 1 ) );
+ else
+ s = i18n( "%1 TB" ).arg( KGlobal::locale() ->formatNumber( fsize, 1 ) );
+ }
+ // Giga-byte
+ else if ( size >= 1048576 ) {
+ fsize = ( float ) size / ( float ) 1048576;
+ s = i18n( "%1 GB" ).arg( KGlobal::locale() ->formatNumber( fsize, 1 ) );
+ }
+ // Mega-byte
+ else if ( size > 1024 ) {
+ fsize = ( float ) size / ( float ) 1024;
+ s = i18n( "%1 MB" ).arg( KGlobal::locale() ->formatNumber( fsize, 1 ) );
+ }
+ // Kilo-byte
+ else {
+ fsize = ( float ) size;
+ s = i18n( "%1 KB" ).arg( KGlobal::locale() ->formatNumber( fsize, 0 ) );
+ }
+ return s;
+}
+
+
+// populate the pop-up menu of the mountman tool-button with actions
+void KMountMan::quickList() {
+ if ( !Operational ) {
+ KMessageBox::error( 0, i18n( "MountMan is not operational. Sorry" ) );
+ return ;
+ }
+
+ // clear the popup menu
+ ( ( KToolBarPopupAction* ) krMountMan ) ->popupMenu() ->clear();
+
+ // create lists of current and possible mount points
+ KMountPoint::List current = KMountPoint::currentMountPoints();
+ KMountPoint::List possible = KMountPoint::possibleMountPoints();
+
+ // create a popupmenu, displaying mountpoints with possible actions
+ // also, populate a small array with the actions
+ if ( _actions )
+ delete[] _actions;
+ _actions = new QString[ possible.size() ];
+
+ KMountPoint::List::iterator it;
+ KMountPoint *m;
+ int idx;
+ for ( it = possible.begin(), idx = 0; it != possible.end(); ++it, ++idx ) {
+ m = *it;
+ // skip nonmountable file systems
+ if (nonmountFilesystem(m->mountType(), m->mountPoint()) || invalidFilesystem(m->mountType()))
+ continue;
+ // does the mountpoint exist in current list? if so, it can only
+ // be umounted, otherwise, it can be mounted
+ bool needUmount = false;
+ KMountPoint::List::iterator otherIt;
+ for ( otherIt = current.begin(); otherIt != current.end(); ++otherIt ) {
+ if ( ( *otherIt ) ->mountPoint() == m->mountPoint() ) { // found it, in needs umount
+ needUmount = true;
+ break;
+ }
+ }
+ // add the item to the menu
+ _actions[ idx ] = QString( needUmount ? "_U_" : "_M_" ) + m->mountPoint();
+ QString text = QString( ( needUmount ? i18n( "Unmount" ) : i18n( "Mount" ) ) ) + " " + m->mountPoint() +
+ " (" + m->mountedFrom() + ")";
+
+
+ ( ( KToolBarPopupAction* ) krMountMan ) ->popupMenu() ->insertItem( text, idx );
+ }
+ connect( ( ( KToolBarPopupAction* ) krMountMan ) ->popupMenu(), SIGNAL( activated( int ) ),
+ this, SLOT( delayedPerformAction( int ) ) );
+
+}
+
+void KMountMan::delayedPerformAction( int idx ) {
+ __delayedIdx = idx;
+ QTimer::singleShot(0, this, SLOT(performAction(int)));
+}
+
+void KMountMan::performAction( int idx ) {
+ while ( qApp->hasPendingEvents() )
+ qApp->processEvents();
+
+ // ugly !!! take idx from the value put there by delayedPerformAction so
+ // as to NOT DIE because of a processEvents deadlock!!! @#$@!@
+ idx = __delayedIdx;
+
+ if ( idx < 0 )
+ return ;
+ bool domount = _actions[ idx ].left( 3 ) == "_M_";
+ QString mountPoint = _actions[ idx ].mid( 3 );
+ if ( !domount ) { // umount
+ unmount( mountPoint);
+ } else { // mount
+ mount( mountPoint);
+ }
+
+ // free memory
+ delete[] _actions;
+ _actions = 0L;
+ disconnect( ( ( KToolBarPopupAction* ) krMountMan ) ->popupMenu(), SIGNAL( activated( int ) ), 0, 0 );
+}
+
+#include "kmountman.moc"
diff --git a/krusader/MountMan/kmountman.h b/krusader/MountMan/kmountman.h
new file mode 100644
index 0000000..67c6509
--- /dev/null
+++ b/krusader/MountMan/kmountman.h
@@ -0,0 +1,102 @@
+/***************************************************************************
+ kmountman.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+***************************************************************************
+
+A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+#ifndef KMOUNTMAN_H
+#define KMOUNTMAN_H
+
+// QT includes
+#include <qobject.h>
+#include <qstring.h>
+
+// KDE includes
+#include <kdeversion.h>
+#include <kio/jobclasses.h>
+#include <kio/job.h>
+#include <kio/global.h>
+#include <kmountpoint.h>
+
+// krusader includes
+#include <stdlib.h>
+#include <math.h>
+
+class KMountManGUI;
+
+class KMountMan : public QObject {
+ Q_OBJECT
+ friend class KMountManGUI;
+
+public:
+ enum mntStatus {DOESNT_EXIST, NOT_MOUNTED, MOUNTED};
+
+ inline bool operational() {
+ return Operational;
+ } // check this 1st
+
+ void mainWindow(); // opens up the GUI
+ void mount( QString mntPoint, bool blocking=true ); // this is probably what you need for mount
+ void unmount( QString mntPoint, bool blocking=true ); // this is probably what you need for unmount
+ mntStatus getStatus( QString mntPoint ); // return the status of a mntPoint (if any)
+ void autoMount( QString path ); // just call it before refreshing into a dir
+ static void eject( QString mntPoint );
+ bool ejectable( QString path );
+ QString convertSize( KIO::filesize_t size );
+ bool invalidFilesystem(QString type);
+ bool nonmountFilesystem(QString type, QString mntPoint);
+
+ KMountMan();
+ ~KMountMan();
+
+public slots:
+ void delayedPerformAction( int idx );
+ void performAction( int idx );
+ void quickList();
+
+protected slots:
+ void jobResult(KIO::Job *job);
+
+protected:
+ // used internally
+ static KMountPoint *findInListByMntPoint(KMountPoint::List &lst, QString value);
+ void toggleMount( QString mntPoint );
+
+private:
+ QString *_actions;
+
+private:
+ bool Operational; // if false, something went terribly wrong on startup
+ bool waiting; // used to block krusader while waiting for (un)mount operation
+ KMountManGUI *mountManGui;
+ // the following is the FS type
+ QStringList invalid_fs;
+ QStringList nonmount_fs;
+ // the following is the FS name
+ QStringList nonmount_fs_mntpoint;
+};
+
+#endif
diff --git a/krusader/MountMan/kmountmangui.cpp b/krusader/MountMan/kmountmangui.cpp
new file mode 100644
index 0000000..540f102
--- /dev/null
+++ b/krusader/MountMan/kmountmangui.cpp
@@ -0,0 +1,396 @@
+/***************************************************************************
+ kmountmangui.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+Description
+***************************************************************************
+
+A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+
+
+#include "kmountmangui.h"
+#include "kmountman.h"
+#include "../krusader.h"
+#include "../Dialogs/krspecialwidgets.h"
+#include "../kicons.h"
+#include "../defaults.h"
+#include "../VFS/vfs.h"
+#include <klocale.h>
+#include <qpixmap.h>
+#include <kpopupmenu.h>
+#include <qbitmap.h>
+#include <kmessagebox.h>
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <kprocess.h>
+#include <qcursor.h>
+#include <kdebug.h>
+#include <kguiitem.h>
+#include <qfileinfo.h>
+#include <sys/param.h>
+
+#if defined(BSD)
+#include <kmountpoint.h>
+#include <kmdcodec.h>
+#else
+#define MTAB "/etc/mtab"
+#endif
+
+// use our version of it until kde fixes theirs
+#include "kdiskfreesp.h"
+
+KMountManGUI::KMountManGUI() : KDialogBase( krApp, 0, true, "Mount.Man" ),
+info( 0 ), mountList( 0 ) {
+ watcher = new QTimer( this );
+ connect( watcher, SIGNAL( timeout() ), this, SLOT( checkMountChange() ) );
+
+ connect( this, SIGNAL( finishedGettingSpaceData() ), this, SLOT( updateList() ) );
+ setButtonOK( i18n( "&Close" ) );
+ showButtonApply( false ); showButtonCancel( false );
+ setPlainCaption( i18n( "MountMan - Your Mount-Manager" ) );
+ widget = new KJanusWidget( this, 0, KJanusWidget::Tabbed );
+ createLayout();
+ setMainWidget( widget );
+ widget->setMinimumSize( widget->sizeHint().width() + mountList->columnWidth( 5 ),
+ widget->sizeHint().height() );
+ setMinimumSize( widget->minimumSize().width(), widget->minimumSize().height() );
+ resize( minimumSize() );
+
+ // connections
+ connect( mountList, SIGNAL( doubleClicked( QListViewItem * ) ), this,
+ SLOT( doubleClicked( QListViewItem* ) ) );
+ connect( mountList, SIGNAL( contextMenuRequested( QListViewItem *, const QPoint &, int ) ),
+ this, SLOT( clicked( QListViewItem*, const QPoint&, int ) ) );
+ connect( mountList, SIGNAL( clicked( QListViewItem * ) ), this,
+ SLOT( changeActive( QListViewItem * ) ) );
+ connect( mountList, SIGNAL( selectionChanged( QListViewItem * ) ), this,
+ SLOT( changeActive( QListViewItem * ) ) );
+
+ getSpaceData();
+ exec();
+}
+
+KMountManGUI::~KMountManGUI() {
+ watcher->stop();
+ delete watcher;
+}
+
+void KMountManGUI::createLayout() {
+ mainPage = widget->addPage( i18n( "Filesystems" ), 0 );
+ createMainPage();
+ widget->showPage( Filesystems );
+}
+
+void KMountManGUI::createMainPage() {
+ // check if we need to clean up first!
+ if ( mountList != 0 ) {
+ mountList->hide();
+ delete mountList;
+ mountList = 0;
+ }
+ // clean up is finished...
+ QGridLayout *layout = new QGridLayout( mainPage, 1, 1 );
+ mountList = new QListView( mainPage ); // create the main container
+ krConfig->setGroup( "Look&Feel" );
+ mountList->setFont( krConfig->readFontEntry( "Filelist Font", _FilelistFont ) );
+ mountList->setAllColumnsShowFocus( true );
+ mountList->setMultiSelection( false );
+ mountList->setSelectionMode( QListView::Single );
+ mountList->setVScrollBarMode( QScrollView::AlwaysOn );
+ mountList->setHScrollBarMode( QScrollView::Auto );
+ mountList->setShowSortIndicator( true );
+ int i = QFontMetrics( mountList->font() ).width( "W" );
+ int j = QFontMetrics( mountList->font() ).width( "0" );
+ j = ( i > j ? i : j );
+ mountList->addColumn( i18n( "Name" ), j * 8 );
+ mountList->addColumn( i18n( "Type" ), j * 4 );
+ mountList->addColumn( i18n( "Mnt.Point" ), j * 6 );
+ mountList->addColumn( i18n( "Total Size" ), j * 6 );
+ mountList->addColumn( i18n( "Free Size" ), j * 6 );
+ mountList->addColumn( i18n( "Free %" ), j * 5 );
+ mountList->setColumnWidthMode( 0, QListView::Maximum );
+ mountList->setColumnWidthMode( 1, QListView::Maximum );
+ mountList->setColumnWidthMode( 2, QListView::Maximum );
+ mountList->setColumnWidthMode( 3, QListView::Maximum );
+ mountList->setColumnWidthMode( 4, QListView::Maximum );
+ mountList->setColumnWidthMode( 5, QListView::Maximum );
+ // now the list is created, time to fill it with data.
+ //=>krMtMan.forceUpdate();
+ QGroupBox *box = new QGroupBox( "MountMan.Info", mainPage );
+ box->setAlignment( Qt::AlignHCenter );
+ info = new KRFSDisplay( box );
+ info->resize( info->width(), height() );
+ layout->addWidget( box, 0, 0 );
+ layout->addWidget( mountList, 0, 1 );
+}
+
+void KMountManGUI::getSpaceData() {
+ fileSystemsTemp.clear();
+ KrMountDetector::getInstance()->hasMountsChanged();
+
+ mounted = KMountPoint::currentMountPoints();
+ possible = KMountPoint::possibleMountPoints();
+ if ( mounted.size() == 0 ) { // nothing is mounted
+ updateList(); // let's continue
+ return ;
+ }
+
+ numOfMountPoints = mounted.size();
+ for ( KMountPoint::List::iterator it = mounted.begin(); it != mounted.end(); ++it ) {
+ // don't bother with invalid file systems
+ if (krMtMan.invalidFilesystem((*it)->mountType())) {
+ --numOfMountPoints;
+ continue;
+ }
+ KDiskFreeSp *sp = KDiskFreeSp::findUsageInfo( ( *it ) ->mountPoint() );
+ connect( sp, SIGNAL( foundMountPoint( const QString &, unsigned long, unsigned long, unsigned long ) ),
+ this, SLOT( gettingSpaceData( const QString&, unsigned long, unsigned long, unsigned long ) ) );
+ connect( sp, SIGNAL( done() ), this, SLOT( gettingSpaceData() ) );
+ }
+}
+
+// this decrements the counter, while the following uses the data
+// used when certain filesystem (/dev, /sys) can't have the needed stats
+void KMountManGUI::gettingSpaceData() {
+ if ( --numOfMountPoints == 0 ) {
+ fileSystems = fileSystemsTemp;
+ emit finishedGettingSpaceData();
+ }
+}
+
+void KMountManGUI::gettingSpaceData( const QString &mountPoint, unsigned long kBSize,
+ unsigned long /*kBUsed*/, unsigned long kBAvail ) {
+ KMountPoint *m = KMountMan::findInListByMntPoint( mounted, mountPoint );
+ if ( !m ) { // this should never never never happen!
+ KMessageBox::error( 0, i18n( "Critical Error" ),
+ i18n( "Internal error in MountMan\nPlease email the developers" ) );
+ exit( 1 );
+ }
+ fsData data;
+ data.setMntPoint( mountPoint );
+ data.setMounted( true );
+ data.setTotalBlks( kBSize );
+ data.setFreeBlks( kBAvail );
+ data.setName( m->mountedFrom() );
+ data.setType( m->mountType() );
+ fileSystemsTemp.append( data );
+}
+
+void KMountManGUI::addItemToMountList( QListView *lst, fsData &fs ) {
+ bool mtd = fs.mounted();
+
+ QString tSize = QString( "%1" ).arg( KIO::convertSizeFromKB( fs.totalBlks() ) );
+ QString fSize = QString( "%1" ).arg( KIO::convertSizeFromKB( fs.freeBlks() ) );
+ QString sPrct = QString( "%1%" ).arg( 100 - ( fs.usedPerct() ) );
+ QListViewItem *item = new QListViewItem( lst, fs.name(),
+ fs.type(), fs.mntPoint(),
+ ( mtd ? tSize : QString( "N/A" ) ), ( mtd ? fSize : QString( "N/A" ) ),
+ ( mtd ? sPrct : QString( "N/A" ) ) );
+
+ QString id = fs.name().left(7); // only works assuming devices start with "/dev/XX"
+ QPixmap *icon = 0;
+ if ( id == "/dev/fd") {
+ icon = new QPixmap( LOADICON( mtd ? "3floppy_mount" : "3floppy_unmount" ) );
+ } else if ( id == "/dev/cd" || fs.type() == "iso9660" ) {
+ icon = new QPixmap( LOADICON( mtd ? "cdrom_mount" : "cdrom_unmount" ) );
+ } else if ( fs.type() == "nfs" || fs.type() == "smbfs" ) {
+ icon = new QPixmap( LOADICON( mtd ? "nfs_mount" : "nfs_unmount" ) );
+ } else icon = new QPixmap( LOADICON( mtd ? "hdd_mount" : "hdd_unmount" ) );
+
+ item->setPixmap( 0, *icon );
+ delete icon;
+}
+
+void KMountManGUI::updateList() {
+ mountList->clear();
+ // this handles the mounted ones
+ for ( QValueList<fsData>::iterator it = fileSystems.begin(); it != fileSystems.end() ; ++it ) {
+ if (krMtMan.invalidFilesystem((*it).type())) {
+ continue;
+ }
+ addItemToMountList( mountList, *it );
+ }
+
+ // now, handle the non-mounted ones
+ for (KMountPoint::List::iterator it = possible.begin(); it != possible.end(); ++it) {
+ // make sure we don't add things we've already added
+ if (KMountMan::findInListByMntPoint(mounted, (*it)->mountPoint())) {
+ continue;
+ } else {
+ fsData data;
+ data.setMntPoint((*it)->mountPoint());
+ data.setMounted(false);
+ data.setType((*it)->mountType());
+ data.setName((*it)->mountedFrom());
+ fileSystems.append(data);
+
+ if (krMtMan.invalidFilesystem(data.type())) continue;
+ addItemToMountList(mountList, data);
+ }
+ }
+
+ mountList->clearSelection();
+ if ( info ) {
+ info->setEmpty( true );
+ info->repaint();
+ }
+ watcher->start( WATCHER_DELAY, true ); // starting the watch timer ( single shot )
+}
+
+void KMountManGUI::checkMountChange() {
+ if (KrMountDetector::getInstance()->hasMountsChanged())
+ getSpaceData();
+ watcher->start( WATCHER_DELAY, true ); // starting the watch timer ( single shot )
+}
+
+void KMountManGUI::doubleClicked( QListViewItem *i ) {
+ if ( !i )
+ return; // we don't want to refresh to swap, do we ?
+
+ // change the active panel to this mountpoint
+ connect( ( QObject* ) this, SIGNAL( refreshPanel( const KURL & ) ), ( QObject* ) SLOTS,
+ SLOT( refresh( const KURL & ) ) );
+ emit refreshPanel( vfs::fromPathOrURL( i->text(2) ) ); // text(2) ? so ugly ...
+ disconnect( this, SIGNAL( refreshPanel( const KURL & ) ), 0, 0 );
+ slotClose();
+}
+
+// when user clicks on a filesystem, change information
+void KMountManGUI::changeActive( QListViewItem *i ) {
+ if ( !i ) return ;
+ fsData *system = 0;
+
+ for (QValueList<fsData>::Iterator it = fileSystems.begin(); it != fileSystems.end(); ++it) {
+ // the only thing which is unique is the mount point
+ if ((*it).mntPoint() == i->text(2)) { // text(2) ? ugly ugly ugly
+ system = &(*it);
+ break;
+ }
+ }
+
+ if (system == 0) {
+ KMessageBox::error(0, i18n("Critical Error"), i18n("Internal error in MountMan\nCall the developers"));
+ exit(1);
+ }
+ info->setAlias( system->mntPoint() );
+ info->setRealName( system->name() );
+ info->setMounted( system->mounted() );
+ info->setEmpty( false );
+ info->setTotalSpace( system->totalBlks() );
+ info->setFreeSpace( system->freeBlks() );
+ info->repaint();
+}
+
+// called when right-clicked on a filesystem
+void KMountManGUI::clicked( QListViewItem *item, const QPoint& pos, int /* col */ ) {
+ // these are the values that will exist in the menu
+#define MOUNT_ID 90
+#define UNMOUNT_ID 91
+#define FORMAT_ID 93
+#define EJECT_ID 94
+ //////////////////////////////////////////////////////////
+ if ( !item ) return ;
+
+ fsData *system = 0;
+ for (QValueList<fsData>::Iterator it = fileSystems.begin(); it != fileSystems.end(); ++it) {
+ // the only thing which is unique is the mount point
+ if ((*it).mntPoint() == item->text(2)) { // text(2) ? ugly ugly ugly
+ system = &(*it);
+ break;
+ }
+ }
+
+ if ( !system ) {
+ KMessageBox::error( 0, i18n( "MountMan has an internal error. Please notify the developers. Thank you." ) );
+ exit( 0 );
+ }
+ // create the menu
+ KPopupMenu popup;
+ popup.insertTitle( i18n( "MountMan" ) );
+ if ( !system->mounted() ) {
+ popup.insertItem( i18n( "Mount" ), MOUNT_ID );
+ bool enable = !(krMtMan.nonmountFilesystem(system->type(), system->mntPoint()));
+ popup.setItemEnabled( MOUNT_ID, enable);
+ } else {
+ popup.insertItem( i18n( "Unmount" ), UNMOUNT_ID );
+ bool enable = !(krMtMan.nonmountFilesystem(system->type(), system->mntPoint()));
+ popup.setItemEnabled( UNMOUNT_ID, enable);
+ }
+ if ( krMtMan.ejectable( system->mntPoint() ) )
+ // if (system->type()=="iso9660" || krMtMan.followLink(system->name()).left(2)=="cd")
+ popup.insertItem( i18n( "Eject" ), EJECT_ID );
+ else {
+ popup.insertItem( i18n( "Format" ), FORMAT_ID );
+ popup.setItemEnabled( FORMAT_ID, false );
+ }
+
+ QString mountPoint = system->mntPoint();
+
+ int result = popup.exec( pos );
+ // check out the user's option
+ switch ( result ) {
+ case - 1 : return ; // the user clicked outside of the menu
+ case MOUNT_ID :
+ case UNMOUNT_ID :
+ krMtMan.toggleMount( mountPoint );
+ break;
+ case FORMAT_ID :
+ break;
+ case EJECT_ID :
+ KMountMan::eject( mountPoint );
+ break;
+ }
+}
+
+KrMountDetector::KrMountDetector() {
+ hasMountsChanged();
+}
+
+bool KrMountDetector::hasMountsChanged() {
+#if defined(BSD)
+ KMountPoint::List mountPoints = KMountPoint::currentMountPoints(KMountPoint::NeedRealDeviceName);
+ KMD5 md5;
+ for(KMountPoint::List::iterator i = mountPoints.begin(); i != mountPoints.end(); ++i) {
+ md5.update((*i)->mountedFrom().utf8());
+ md5.update((*i)->realDeviceName().utf8());
+ md5.update((*i)->mountPoint().utf8());
+ md5.update((*i)->mountType().utf8());
+ }
+ QString s = md5.hexDigest();
+ bool result = s != checksum;
+ checksum = s;
+#else
+ bool result = QFileInfo(MTAB).lastModified() != lastMtab;
+ lastMtab = QFileInfo(MTAB).lastModified();
+#endif
+ return result;
+}
+
+KrMountDetector krMountDetector;
+KrMountDetector * KrMountDetector::getInstance() {
+ return & krMountDetector;
+}
+
+#include "kmountmangui.moc"
diff --git a/krusader/MountMan/kmountmangui.h b/krusader/MountMan/kmountmangui.h
new file mode 100644
index 0000000..f379b5d
--- /dev/null
+++ b/krusader/MountMan/kmountmangui.h
@@ -0,0 +1,198 @@
+/***************************************************************************
+ kmountmangui.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+ Description
+***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+
+#ifndef KMOUNTMANGUI_H
+#define KMOUNTMANGUI_H
+
+#include <sys/param.h>
+#include <kdialogbase.h>
+#include <qlistview.h>
+#include <kjanuswidget.h>
+#include <qtimer.h>
+#include <kurl.h>
+#include <qvaluelist.h>
+#include <kmountpoint.h>
+#include <qdatetime.h>
+#include "kmountman.h"
+
+#define WATCHER_DELAY 3000
+
+class KRFSDisplay;
+class KRdirWatch;
+
+
+// forward definitions
+class fsData;
+
+class KMountManGUI : public KDialogBase {
+ Q_OBJECT
+
+ enum Pages {
+ Filesystems = 0
+ };
+
+public:
+ KMountManGUI();
+ ~KMountManGUI();
+ void createLayout(); // calls the various tab layout-creators
+ void createMainPage(); // creator of the main page - filesystems
+
+protected slots:
+ void doubleClicked( QListViewItem * );
+ void clicked( QListViewItem *, const QPoint& pos, int col );
+ void changeActive( QListViewItem * );
+ void checkMountChange(); // check whether the mount table was changed
+
+ void updateList(); // fill-up the filesystems list
+ void getSpaceData();
+ void gettingSpaceData();
+ void gettingSpaceData(const QString &mountPoint, unsigned long kBSize,
+ unsigned long kBUsed, unsigned long kBAvail);
+
+protected:
+ void addItemToMountList( QListView *lst, fsData &fs );
+
+signals:
+ void refreshPanel( const KURL & );
+ void finishedGettingSpaceData();
+
+private:
+ KRFSDisplay *info;
+ QFrame *mainPage;
+ KJanusWidget *widget;
+ QListView *mountList;
+ QTimer *watcher;
+ QDateTime lastMtab;
+ // used for the getSpace - gotSpace functions
+ KMountPoint::List possible, mounted;
+ QValueList<fsData> fileSystems;
+ QValueList<fsData> fileSystemsTemp; // first collect to a temporary place
+ int numOfMountPoints;
+};
+
+
+// Data container for a single-filesystem data
+// maximum size supported is 2GB of 1kb blocks == 2048GB, enough.
+// not really needed, but kept for backward compatiblity
+/////////////////////////////////////////////////////////////////
+class fsData {
+public:
+ fsData() : Name( 0 ), Type( 0 ), MntPoint( 0 ), TotalBlks( 0 ),
+ FreeBlks( 0 ), Mounted( false ) {}
+
+ // get information
+ inline QString name() {
+ return Name;
+ }
+ inline QString shortName() {
+ return Name.right( Name.length() - Name.find( "/", 1 ) - 1 );
+ }
+ inline QString type() {
+ return Type;
+ }
+ inline QString mntPoint() {
+ return MntPoint;
+ }
+ inline long totalBlks() {
+ return TotalBlks;
+ }
+ inline long freeBlks() {
+ return FreeBlks;
+ }
+ inline KIO::filesize_t totalBytes() {
+ return TotalBlks * 1024;
+ }
+ inline KIO::filesize_t freeBytes() {
+ return FreeBlks * 1024;
+ }
+ //////////////////// insert a good round function here /////////////////
+ int usedPerct() {
+ if ( TotalBlks == 0 )
+ return 0;
+ float res = ( ( float ) ( TotalBlks - FreeBlks ) ) / ( ( float ) TotalBlks ) * 100;
+ if ( ( res - ( int ) res ) > 0.5 )
+ return ( int ) res + 1;
+ else
+ return ( int ) res;
+ }
+ inline bool mounted() {
+ return Mounted;
+ }
+
+ // set information
+ inline void setName( QString n_ ) {
+ Name = n_;
+ }
+ inline void setType( QString t_ ) {
+ Type = t_;
+ }
+ inline void setMntPoint( QString m_ ) {
+ MntPoint = m_;
+ }
+ inline void setTotalBlks( long t_ ) {
+ TotalBlks = t_;
+ }
+ inline void setFreeBlks( long f_ ) {
+ FreeBlks = f_;
+ }
+ inline void setMounted( bool m_ ) {
+ Mounted = m_;
+ }
+
+private:
+ QString Name; // i.e: /dev/cdrom
+ QString Type; // i.e: iso9600
+ QString MntPoint; // i.e: /mnt/cdrom
+ long TotalBlks; // measured in 1024bytes per block
+ long FreeBlks;
+ bool Mounted; // true if filesystem is mounted
+
+ // additional attributes of a filesystem, parsed from fstab
+public:
+ QString options; // additional fstab options
+};
+
+class KrMountDetector {
+#if defined(BSD)
+ QString checksum;
+#else
+ QDateTime lastMtab;
+#endif
+public:
+ KrMountDetector();
+ static KrMountDetector * getInstance();
+ bool hasMountsChanged();
+};
+
+
+
+#endif
diff --git a/krusader/Panel/Makefile.am b/krusader/Panel/Makefile.am
new file mode 100644
index 0000000..3317a9b
--- /dev/null
+++ b/krusader/Panel/Makefile.am
@@ -0,0 +1,29 @@
+if include_libkonq
+AM_CPPFLAGS = -D__LIBKONQ__
+endif
+
+
+noinst_LIBRARIES = libPanel.a
+
+INCLUDES = $(all_includes)
+
+libPanel_a_METASOURCES = AUTO
+
+libPanel_a_SOURCES = \
+ krcolorcache.cpp \
+ krcalcspacedialog.cpp \
+ krpopupmenu.cpp \
+ krpreviewpopup.cpp \
+ krview.cpp \
+ krviewitem.cpp \
+ krdetailedviewitem.cpp \
+ krdetailedview.cpp \
+ panelfunc.cpp \
+ listpanel.cpp \
+ panelpopup.cpp \
+ krdrag.cpp \
+ krselectionmode.cpp \
+ krbriefview.cpp \
+ krbriefviewitem.cpp
+
+
diff --git a/krusader/Panel/krbriefview.cpp b/krusader/Panel/krbriefview.cpp
new file mode 100644
index 0000000..1fe8a36
--- /dev/null
+++ b/krusader/Panel/krbriefview.cpp
@@ -0,0 +1,1461 @@
+/***************************************************************************
+ krbriefview.cpp
+ -------------------
+copyright : (C) 2000-2007 by Shie Erlich & Rafi Yanai & Csaba Karai
+e-mail : krusader@users.sourceforge.net
+web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+Description
+***************************************************************************
+
+A
+
+db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+#include "krbriefview.h"
+#include "krbriefviewitem.h"
+#include "krcolorcache.h"
+#include "krselectionmode.h"
+#include "../krusader.h"
+#include "../kicons.h"
+#include "../defaults.h"
+#include "../krslots.h"
+#include "../VFS/krarchandler.h"
+#include "../VFS/krquery.h"
+#include "../Dialogs/krspecialwidgets.h"
+#include <qheader.h>
+#include <qtooltip.h>
+
+#define CANCEL_TWO_CLICK_RENAME {singleClicked = false;renameTimer.stop();}
+#define PROPS static_cast<KrBriefViewProperties*>(_properties)
+#define MAX_COLS 5
+#define VF getVfile()
+
+
+class KrBriefViewToolTip : public QToolTip
+{
+public:
+ KrBriefViewToolTip( KrBriefView *view, QWidget *parent );
+ void maybeTip( const QPoint &pos );
+
+ virtual ~KrBriefViewToolTip() {}
+private:
+ KrBriefView *view;
+};
+
+KrBriefViewToolTip::KrBriefViewToolTip( KrBriefView *lv, QWidget *parent )
+ : QToolTip( parent ), view( lv )
+{
+}
+
+void KrBriefViewToolTip::maybeTip( const QPoint &pos )
+{
+ QIconViewItem *item = view->findItem( view->viewportToContents( pos ) );
+
+ if ( !item )
+ return;
+
+ int width = QFontMetrics( view->font() ).width( item->text() ) + 4;
+
+ QRect r = item->rect();
+ r.setTopLeft( view->contentsToViewport( r.topLeft() ) );
+ if( width > item->textRect().width() )
+ tip( r, item->text() );
+}
+
+
+KrBriefView::KrBriefView( QHeader * headerIn, QWidget *parent, bool &left, KConfig *cfg, const char *name ):
+ KIconView(parent, name), KrView( cfg ), header( headerIn ), _currDragItem( 0 ),
+ currentlyRenamedItem( 0 ), pressedItem( 0 ), mouseEvent( 0 ) {
+ setWidget( this );
+ _nameInKConfig = QString( "KrBriefView" ) + QString( ( left ? "Left" : "Right" ) );
+ krConfig->setGroup("Private");
+ if (krConfig->readBoolEntry("Enable Input Method", true))
+ setInputMethodEnabled(true);
+ toolTip = new KrBriefViewToolTip( this, viewport() );
+}
+
+void KrBriefView::setup() {
+ lastSwushPosition = 0;
+
+ // use the {} so that KConfigGroupSaver will work correctly!
+ KConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ setFont( _config->readFontEntry( "Filelist Font", _FilelistFont ) );
+ // decide on single click/double click selection
+ if ( _config->readBoolEntry( "Single Click Selects", _SingleClickSelects ) &&
+ KGlobalSettings::singleClick() ) {
+ connect( this, SIGNAL( executed( QIconViewItem* ) ), this, SLOT( slotExecuted( QIconViewItem* ) ) );
+ } else {
+ connect( this, SIGNAL( clicked( QIconViewItem* ) ), this, SLOT( slotClicked( QIconViewItem* ) ) );
+ connect( this, SIGNAL( doubleClicked( QIconViewItem* ) ), this, SLOT( slotDoubleClicked( QIconViewItem* ) ) );
+ }
+
+ // a change in the selection needs to update totals
+ connect( this, SIGNAL( onItem( QIconViewItem* ) ), this, SLOT( slotItemDescription( QIconViewItem* ) ) );
+ connect( this, SIGNAL( contextMenuRequested( QIconViewItem*, const QPoint& ) ),
+ this, SLOT( handleContextMenu( QIconViewItem*, const QPoint& ) ) );
+ connect( this, SIGNAL( rightButtonPressed(QIconViewItem*, const QPoint&)),
+ this, SLOT(slotRightButtonPressed(QIconViewItem*, const QPoint&)));
+ connect( this, SIGNAL( currentChanged( QIconViewItem* ) ), this, SLOT( setNameToMakeCurrent( QIconViewItem* ) ) );
+ connect( this, SIGNAL( currentChanged( QIconViewItem* ) ), this, SLOT( transformCurrentChanged( QIconViewItem* ) ) );
+ connect( this, SIGNAL( mouseButtonClicked ( int, QIconViewItem *, const QPoint & ) ),
+ this, SLOT( slotMouseClicked ( int, QIconViewItem *, const QPoint & ) ) );
+ connect( &KrColorCache::getColorCache(), SIGNAL( colorsRefreshed() ), this, SLOT( refreshColors() ) );
+
+ // add whatever columns are needed to the listview
+ krConfig->setGroup( nameInKConfig() );
+
+ // determine basic settings for the view
+ setAcceptDrops( true );
+ setItemsMovable( false );
+ setItemTextPos( QIconView::Right );
+ setArrangement( QIconView::TopToBottom );
+ setWordWrapIconText( false );
+ setSpacing( 0 );
+ horizontalScrollBar()->installEventFilter( this );
+
+ // allow in-place renaming
+
+ connect( this, SIGNAL( itemRenamed ( QIconViewItem * ) ),
+ this, SLOT( inplaceRenameFinished( QIconViewItem * ) ) );
+ connect( &renameTimer, SIGNAL( timeout() ), this, SLOT( renameCurrentItem() ) );
+ connect( &contextMenuTimer, SIGNAL (timeout()), this, SLOT (showContextMenu()));
+
+ setSelectionMode( QIconView::Extended );
+
+ setFocusPolicy( StrongFocus );
+ restoreSettings();
+ refreshColors();
+
+ CANCEL_TWO_CLICK_RENAME;
+
+ // setting the header
+ while( header->count() )
+ header->removeLabel( 0 );
+
+ header->addLabel( i18n( "Name" ) );
+ header->setStretchEnabled( true );
+
+ header->setSortIndicator( 0, sortDirection() ? Qt::Ascending : Qt::Descending );
+ connect( header, SIGNAL(clicked( int )), this, SLOT( changeSortOrder()));
+
+ header->installEventFilter( this );
+ header->show();
+}
+
+KrBriefView::~KrBriefView() {
+ delete _properties; _properties = 0;
+ delete _operator; _operator = 0;
+ if( mouseEvent )
+ delete mouseEvent;
+ mouseEvent = 0;
+ delete toolTip;
+}
+
+void KrBriefView::resizeEvent ( QResizeEvent * resEvent )
+{
+ QPoint pnt( contentsX(), contentsY() );
+ QRect viewportRect( pnt, resEvent->oldSize() );
+ bool visible = false;
+ if( currentItem() )
+ visible = viewportRect.contains( currentItem()->rect() );
+
+ KIconView::resizeEvent( resEvent );
+ redrawColumns();
+
+ if( visible && currentItem() )
+ ensureItemVisible( currentItem() );
+}
+
+void KrBriefView::redrawColumns()
+{
+ bool ascending = sortDirection();
+ setSorting( false, ascending );
+
+ setGridX( width() / PROPS->numberOfColumns );
+
+ // QT bug, it's important for recalculating the bounding rectangle
+ for( QIconViewItem * item = firstItem(); item; item = item->nextItem() )
+ {
+ QString txt = item->text();
+ item->setText( "" );
+ item->setText( txt );
+ }
+
+ setSorting( true, ascending );
+
+ arrangeItemsInGrid();
+}
+
+// if vfile passes the filter, create an item, otherwise, drop it
+KrViewItem *KrBriefView::preAddItem( vfile *vf ) {
+ bool isDir = vf->vfile_isDir();
+ if ( !isDir || ( isDir && ( _properties->filter & KrViewProperties::ApplyToDirs ) ) ) {
+ switch ( _properties->filter ) {
+ case KrViewProperties::All :
+ break;
+ case KrViewProperties::Custom :
+ if ( !_properties->filterMask.match( vf ) ) return 0;
+ break;
+ case KrViewProperties::Dirs:
+ if ( !vf->vfile_isDir() ) return 0;
+ break;
+ case KrViewProperties::Files:
+ if ( vf->vfile_isDir() ) return 0;
+ break;
+ case KrViewProperties::ApplyToDirs :
+ break; // no-op, stop compiler complaints
+ }
+ }
+ // passed the filter ...
+ return new KrBriefViewItem( this, lastItem(), vf );
+}
+
+bool KrBriefView::preDelItem(KrViewItem *item) {
+ if( item ) {
+ KrBriefViewItem * viewItem = dynamic_cast<KrBriefViewItem*>( item );
+ if( viewItem == currentlyRenamedItem ) {
+ currentlyRenamedItem->cancelRename();
+ currentlyRenamedItem = 0;
+ }
+ }
+
+ return true;
+}
+
+void KrBriefView::addItems( vfs *v, bool addUpDir ) {
+ QIconViewItem * item = firstItem();
+ QIconViewItem * currentItem = item;
+
+ // add the up-dir arrow if needed
+ if ( addUpDir ) {
+ new KrBriefViewItem( this, ( QIconViewItem* ) 0L, ( vfile* ) 0L );
+ }
+
+
+ // text for updating the status bar
+ QString statusText = QString("%1/ ").arg( v->vfs_getOrigin().fileName() ) + i18n("Directory");
+
+ bool as = sortDirection();
+ setSorting( false, as ); // disable sorting
+
+ for ( vfile * vf = v->vfs_getFirstFile(); vf != 0 ; vf = v->vfs_getNextFile() ) {
+ bool isDir = vf->vfile_isDir();
+ if ( !isDir || ( isDir && ( _properties->filter & KrViewProperties::ApplyToDirs ) ) ) {
+ switch ( _properties->filter ) {
+ case KrViewProperties::All :
+ break;
+ case KrViewProperties::Custom :
+ if ( !_properties->filterMask.match( vf ) )
+ continue;
+ break;
+ case KrViewProperties::Dirs:
+ if ( !vf->vfile_isDir() )
+ continue;
+ break;
+ case KrViewProperties::Files:
+ if ( vf->vfile_isDir() )
+ continue;
+ break;
+
+ case KrViewProperties::ApplyToDirs :
+ break; // no-op, stop compiler complaints
+ }
+ }
+
+ KrBriefViewItem *bvitem = new KrBriefViewItem( this, item, vf );
+ _dict.insert( vf->vfile_getName(), bvitem );
+ if ( isDir )
+ ++_numDirs;
+ else
+ _countSize += bvitem->VF->vfile_getSize();
+ ++_count;
+ // if the item should be current - make it so
+ if ( bvitem->name() == nameToMakeCurrent() )
+ {
+ currentItem = static_cast<QIconViewItem*>(bvitem);
+ statusText = bvitem->description();
+ }
+ }
+
+
+ // re-enable sorting
+ setSorting( true, as );
+ sort( as );
+
+ if ( !currentItem )
+ currentItem = firstItem();
+ KIconView::setCurrentItem( currentItem );
+ ensureItemVisible( currentItem );
+
+ op()->emitItemDescription( statusText );
+}
+
+void KrBriefView::delItem( const QString &name ) {
+ KrView::delItem( name );
+ arrangeItemsInGrid();
+}
+
+QString KrBriefView::getCurrentItem() const {
+ QIconViewItem * it = currentItem();
+ if ( !it )
+ return QString::null;
+ else
+ return dynamic_cast<KrViewItem*>( it ) ->name();
+}
+
+void KrBriefView::setCurrentItem( const QString& name ) {
+ KrBriefViewItem * it = dynamic_cast<KrBriefViewItem*>(_dict[ name ]);
+ if ( it )
+ KIconView::setCurrentItem( it );
+}
+
+void KrBriefView::clear() {
+ if( currentlyRenamedItem ) {
+ currentlyRenamedItem->cancelRename();
+ currentlyRenamedItem = 0;
+ }
+
+ op()->emitSelectionChanged(); /* to avoid rename crash at refresh */
+ KIconView::clear();
+ KrView::clear();
+}
+
+void KrBriefView::slotClicked( QIconViewItem *item ) {
+ if ( !item ) return ;
+
+ if ( !modifierPressed ) {
+ if ( singleClicked && !renameTimer.isActive() ) {
+ KConfig * config = KGlobal::config();
+ config->setGroup( "KDE" );
+ int doubleClickInterval = config->readNumEntry( "DoubleClickInterval", 400 );
+
+ int msecsFromLastClick = clickTime.msecsTo( QTime::currentTime() );
+
+ if ( msecsFromLastClick > doubleClickInterval && msecsFromLastClick < 5 * doubleClickInterval ) {
+ singleClicked = false;
+ renameTimer.start( doubleClickInterval, true );
+ return ;
+ }
+ }
+
+ CANCEL_TWO_CLICK_RENAME;
+ singleClicked = true;
+ clickTime = QTime::currentTime();
+ clickedItem = item;
+ }
+}
+
+void KrBriefView::slotDoubleClicked( QIconViewItem *item ) {
+ CANCEL_TWO_CLICK_RENAME;
+ if ( !item )
+ return ;
+ QString tmp = dynamic_cast<KrViewItem*>( item ) ->name();
+ op()->emitExecuted(tmp);
+}
+
+void KrBriefView::prepareForActive() {
+ KrView::prepareForActive();
+ setFocus();
+ slotItemDescription( currentItem() );
+}
+
+void KrBriefView::prepareForPassive() {
+ KrView::prepareForPassive();
+ CANCEL_TWO_CLICK_RENAME;
+ KConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ if ( _config->readBoolEntry( "New Style Quicksearch", _NewStyleQuicksearch ) ) {
+ if ( MAIN_VIEW ) {
+ if ( ACTIVE_PANEL ) {
+ if ( ACTIVE_PANEL->quickSearch ) {
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ stopQuickSearch( 0 );
+ }
+ }
+ }
+ }
+ }
+}
+
+void KrBriefView::slotItemDescription( QIconViewItem * item ) {
+ KrViewItem * it = static_cast<KrBriefViewItem*>( item );
+ if ( !it )
+ return ;
+ QString desc = it->description();
+ op()->emitItemDescription(desc);
+}
+
+void KrBriefView::handleQuickSearchEvent( QKeyEvent * e ) {
+ switch ( e->key() ) {
+ case Key_Insert:
+ {
+ QKeyEvent ev = QKeyEvent( QKeyEvent::KeyPress, Key_Space, 0, 0 );
+ KIconView::keyPressEvent( & ev );
+ ev = QKeyEvent( QKeyEvent::KeyPress, Key_Down, 0, 0 );
+ keyPressEvent( & ev );
+ break;
+ }
+ case Key_Home:
+ {
+ QIconView::setCurrentItem( firstItem() );
+ QKeyEvent ev = QKeyEvent( QKeyEvent::KeyPress, Key_Down, 0, 0 );
+ keyPressEvent( & ev );
+ break;
+ }
+ case Key_End:
+ {
+ QIconView::setCurrentItem( firstItem() );
+ QKeyEvent ev = QKeyEvent( QKeyEvent::KeyPress, Key_Up, 0, 0 );
+ keyPressEvent( & ev );
+ break;
+ }
+ }
+}
+
+
+void KrBriefView::slotCurrentChanged( QIconViewItem * item ) {
+ CANCEL_TWO_CLICK_RENAME;
+ if ( !item )
+ return ;
+ _nameToMakeCurrent = static_cast<KrBriefViewItem*>( item ) ->name();
+}
+
+void KrBriefView::contentsMousePressEvent( QMouseEvent * e ) {
+ bool callDefaultHandler = true, processEvent = true, selectionChanged = false;
+ pressedItem = 0;
+
+ e = transformMouseEvent( e );
+
+ QIconViewItem * oldCurrent = currentItem();
+ QIconViewItem *newCurrent = findItem( e->pos() );
+ if (e->button() == RightButton)
+ {
+ if (KrSelectionMode::getSelectionHandler()->rightButtonSelects() ||
+ (((e->state() & ShiftButton) || (e->state() & ControlButton))) && KrSelectionMode::getSelectionHandler()->shiftCtrlRightButtonSelects())
+ {
+ if (KrSelectionMode::getSelectionHandler()->rightButtonPreservesSelection() && !(e->state() & ShiftButton)
+ && !(e->state() & ControlButton) && !(e->state() & AltButton))
+ {
+ if (newCurrent)
+ {
+ if (KrSelectionMode::getSelectionHandler()->showContextMenu() >= 0)
+ {
+ swushSelects = !newCurrent->isSelected();
+ lastSwushPosition = newCurrent;
+ }
+ newCurrent->setSelected(!newCurrent->isSelected(), true);
+ newCurrent->repaint();
+ selectionChanged = true;
+ }
+ callDefaultHandler = false;
+ processEvent = false;
+ e->accept();
+ }
+
+ if( !KrSelectionMode::getSelectionHandler()->rightButtonPreservesSelection() && KrSelectionMode::getSelectionHandler()->showContextMenu() >= 0)
+ {
+ if( (e->state() & ControlButton) && !(e->state() & AltButton) )
+ {
+ if( newCurrent )
+ {
+ newCurrent->setSelected(!newCurrent->isSelected());
+ newCurrent->repaint();
+ selectionChanged = true;
+ callDefaultHandler = false;
+ e->accept();
+ }
+ }
+ else if( !(e->state() & ControlButton) && !(e->state() & AltButton) )
+ {
+ clearSelection();
+ if( newCurrent )
+ {
+ newCurrent->setSelected( true );
+ newCurrent->repaint();
+ }
+ selectionChanged = true;
+ callDefaultHandler = false;
+ e->accept();
+ }
+ }
+ }
+ else
+ {
+ callDefaultHandler = false;
+ processEvent = false;
+ e->accept();
+ }
+ }
+ if (e->button() == LeftButton)
+ {
+ dragStartPos = e->pos();
+ if (KrSelectionMode::getSelectionHandler()->leftButtonSelects() ||
+ (((e->state() & ShiftButton) || (e->state() & ControlButton))) &&
+ KrSelectionMode::getSelectionHandler()->shiftCtrlLeftButtonSelects())
+ {
+ if (KrSelectionMode::getSelectionHandler()->leftButtonPreservesSelection() && !(e->state() & ShiftButton)
+ && !(e->state() & ControlButton) && !(e->state() & AltButton))
+ {
+ if (newCurrent)
+ {
+ newCurrent->setSelected(!newCurrent->isSelected(), true);
+ newCurrent->repaint();
+ selectionChanged = true;
+ }
+ callDefaultHandler = false;
+ processEvent = false;
+ e->accept();
+ }
+ }
+ else
+ {
+ callDefaultHandler = false;
+ processEvent = false;
+ e->accept();
+ }
+ }
+
+ modifierPressed = false;
+ if ( (e->state() & ShiftButton) || (e->state() & ControlButton) || (e->state() & AltButton) ) {
+ CANCEL_TWO_CLICK_RENAME;
+ modifierPressed = true;
+ }
+
+ // stop quick search in case a mouse click occured
+ KConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ if ( _config->readBoolEntry( "New Style Quicksearch", _NewStyleQuicksearch ) ) {
+ if ( MAIN_VIEW ) {
+ if ( ACTIVE_PANEL ) {
+ if ( ACTIVE_PANEL->quickSearch ) {
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ stopQuickSearch( 0 );
+ }
+ }
+ }
+ }
+ }
+
+ if ( !_focused )
+ op()->emitNeedFocus();
+ setFocus();
+
+ if (processEvent && ( (e->state() & ShiftButton) || (e->state() & ControlButton) || (e->state() & AltButton) ) && !KrSelectionMode::getSelectionHandler()->useQTSelection()){
+ if ( oldCurrent && newCurrent && oldCurrent != newCurrent && e->state() & ShiftButton ) {
+ int oldPos = oldCurrent->index();
+ int newPos = newCurrent->index();
+ QIconViewItem *top = 0, *bottom = 0;
+ if ( oldPos > newPos ) {
+ top = newCurrent;
+ bottom = oldCurrent;
+ } else {
+ top = oldCurrent;
+ bottom = newCurrent;
+ }
+ while( top )
+ {
+ if ( !top->isSelected() ) {
+ top->setSelected( true, true );
+ selectionChanged = true;
+ }
+ if ( top == bottom )
+ break;
+ top = top->nextItem();
+ }
+ QIconView::setCurrentItem( newCurrent );
+ callDefaultHandler = false;
+ }
+ if( e->state() & ShiftButton )
+ callDefaultHandler = false;
+ }
+
+ if (selectionChanged)
+ updateView(); // don't call triggerUpdate directly!
+
+ if (callDefaultHandler)
+ {
+ dragStartPos = QPoint( -1, -1 );
+
+ QString name = QString::null; // will the file be deleted by the mouse event?
+ if( newCurrent ) // save the name of the file
+ name = static_cast<KrBriefViewItem*>( newCurrent ) ->name();
+
+ KIconView::contentsMousePressEvent( e );
+
+ if( name.isEmpty() || _dict.find( name ) == 0 ) // is the file still valid?
+ newCurrent = 0; // if not, don't do any crash...
+ } else {
+ // emitting the missing signals from QIconView::contentsMousePressEvent();
+ // the right click signal is not emitted as it is used for selection
+
+ QPoint vp = contentsToViewport( e->pos() );
+
+ if( !newCurrent ) {
+ emit pressed( pressedItem = newCurrent );
+ emit pressed( newCurrent, viewport()->mapToGlobal( vp ) );
+ }
+
+ emit mouseButtonPressed( e->button(), newCurrent, viewport()->mapToGlobal( vp ) );
+ }
+
+ // if (i != 0) // comment in, if click sould NOT select
+ // setSelected(i, FALSE);
+ if (newCurrent) QIconView::setCurrentItem(newCurrent);
+
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ ACTIVE_PANEL->quickSearch->hide();
+ ACTIVE_PANEL->quickSearch->clear();
+ krDirUp->setEnabled( true );
+ }
+ if ( OTHER_PANEL->quickSearch->isShown() ) {
+ OTHER_PANEL->quickSearch->hide();
+ OTHER_PANEL->quickSearch->clear();
+ krDirUp->setEnabled( true );
+ }
+}
+
+void KrBriefView::contentsMouseReleaseEvent( QMouseEvent * e ) {
+ if (e->button() == RightButton)
+ contextMenuTimer.stop();
+
+ e = transformMouseEvent( e );
+
+ KIconView::contentsMouseReleaseEvent( e );
+
+ if( pressedItem ) {
+ QPoint vp = contentsToViewport( e->pos() );
+ QIconViewItem *newCurrent = findItem( e->pos() );
+
+ if( pressedItem == newCurrent ) {
+ // emitting the missing signals from QIconView::contentsMouseReleaseEvent();
+ // the right click signal is not emitted as it is used for selection
+
+ if( !newCurrent ) {
+ emit clicked( newCurrent );
+ emit clicked( newCurrent, viewport()->mapToGlobal( vp ) );
+ }
+
+ emit mouseButtonClicked( e->button(), newCurrent, viewport()->mapToGlobal( vp ) );
+ }
+
+ pressedItem = 0;
+ }
+}
+
+void KrBriefView::contentsMouseMoveEvent ( QMouseEvent * e ) {
+ e = transformMouseEvent( e );
+
+ if ( ( singleClicked || renameTimer.isActive() ) && findItem( e->pos() ) != clickedItem )
+ CANCEL_TWO_CLICK_RENAME;
+
+ if ( dragStartPos != QPoint( -1, -1 ) &&
+ e->state() & LeftButton && ( dragStartPos - e->pos() ).manhattanLength() > QApplication::startDragDistance() )
+ startDrag();
+ if (KrSelectionMode::getSelectionHandler()->rightButtonPreservesSelection()
+ && KrSelectionMode::getSelectionHandler()->rightButtonSelects()
+ && KrSelectionMode::getSelectionHandler()->showContextMenu() >= 0 && e->state() == Qt::RightButton)
+ {
+ QIconViewItem *newItem = findItem( e->pos() );
+ e->accept();
+ if (newItem != lastSwushPosition && newItem)
+ {
+ // is the new item above or below the previous one?
+ QIconViewItem * above = newItem;
+ QIconViewItem * below = newItem;
+ for (;(above || below) && above != lastSwushPosition && below != lastSwushPosition;)
+ {
+ if (above)
+ above = above->nextItem();
+ if (below)
+ below = below->prevItem();
+ }
+ if (above && (above == lastSwushPosition))
+ {
+ for (; above != newItem; above = above->prevItem())
+ above->setSelected(swushSelects,true);
+ newItem->setSelected(swushSelects,true);
+ lastSwushPosition = newItem;
+ updateView();
+ }
+ else if (below && (below == lastSwushPosition))
+ {
+ for (; below != newItem; below = below->nextItem())
+ below->setSelected(swushSelects,true);
+ newItem->setSelected(swushSelects,true);
+ lastSwushPosition = newItem;
+ updateView();
+ }
+ contextMenuTimer.stop();
+ }
+ // emitting the missing signals from QIconView::contentsMouseMoveEvent();
+ if( newItem )
+ emit onItem( newItem );
+ else
+ emit onViewport();
+ }
+ else
+ KIconView::contentsMouseMoveEvent( e );
+}
+
+void KrBriefView::contentsMouseDoubleClickEvent ( QMouseEvent * e )
+{
+ e = transformMouseEvent ( e );
+ KIconView::contentsMouseDoubleClickEvent( e );
+}
+
+void KrBriefView::handleContextMenu( QIconViewItem * it, const QPoint & pos ) {
+ if ( !_focused )
+ op()->emitNeedFocus();
+ setFocus();
+
+ if ( !it )
+ return ;
+ if ( static_cast<KrBriefViewItem*>( it ) ->
+ name() == ".." )
+ return ;
+ int i = KrSelectionMode::getSelectionHandler()->showContextMenu();
+ contextMenuPoint = QPoint( pos.x(), pos.y() );
+ if (i < 0)
+ showContextMenu();
+ else if (i > 0)
+ contextMenuTimer.start(i, true);
+}
+
+void KrBriefView::showContextMenu()
+{
+ if (lastSwushPosition)
+ lastSwushPosition->setSelected(true);
+ op()->emitContextMenu( contextMenuPoint );
+}
+
+KrViewItem *KrBriefView::getKrViewItemAt( const QPoint & vp ) {
+ return dynamic_cast<KrViewItem*>( KIconView::findItem( vp ) );
+}
+
+bool KrBriefView::acceptDrag( QDropEvent* ) const {
+ return true;
+}
+
+void KrBriefView::contentsDropEvent( QDropEvent * e ) {
+ _currDragItem = 0;
+ op()->emitGotDrop(e);
+ e->ignore();
+ KIconView::contentsDropEvent( e );
+}
+
+void KrBriefView::contentsDragMoveEvent( QDragMoveEvent * e ) {
+ KrViewItem *oldDragItem = _currDragItem;
+
+ _currDragItem = getKrViewItemAt( e->pos() );
+ if( _currDragItem && !_currDragItem->VF->vfile_isDir() )
+ _currDragItem = 0;
+
+ KIconView::contentsDragMoveEvent( e );
+
+ if( _currDragItem != oldDragItem )
+ {
+ if( oldDragItem )
+ dynamic_cast<KrBriefViewItem *>( oldDragItem )->repaint();
+ if( _currDragItem )
+ dynamic_cast<KrBriefViewItem *>( _currDragItem )->repaint();
+ }
+}
+
+void KrBriefView::contentsDragLeaveEvent ( QDragLeaveEvent *e )
+{
+ KrViewItem *oldDragItem = _currDragItem;
+
+ _currDragItem = 0;
+ KIconView::contentsDragLeaveEvent( e );
+
+ if( oldDragItem )
+ dynamic_cast<KrBriefViewItem *>( oldDragItem )->repaint();
+}
+
+void KrBriefView::imStartEvent(QIMEvent* e)
+{
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ ACTIVE_PANEL->quickSearch->myIMStartEvent( e );
+ return ;
+ }else {
+ KConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ if ( !_config->readBoolEntry( "New Style Quicksearch", _NewStyleQuicksearch ) )
+ KIconView::imStartEvent( e );
+ else {
+ // first, show the quicksearch if its hidden
+ if ( ACTIVE_PANEL->quickSearch->isHidden() ) {
+ ACTIVE_PANEL->quickSearch->show();
+ // hack: if the pressed key requires a scroll down, the selected
+ // item is "below" the quick search window, as the icon view will
+ // realize its new size after the key processing. The following line
+ // will resize the icon view immediately.
+ ACTIVE_PANEL->layout->activate();
+ // second, we need to disable the dirup action - hack!
+ krDirUp->setEnabled( false );
+ }
+ // now, send the key to the quicksearch
+ ACTIVE_PANEL->quickSearch->myIMStartEvent( e );
+ }
+ }
+}
+
+void KrBriefView::imEndEvent(QIMEvent* e)
+{
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ ACTIVE_PANEL->quickSearch->myIMEndEvent( e );
+ return ;
+ }
+}
+
+void KrBriefView::imComposeEvent(QIMEvent* e)
+{
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ ACTIVE_PANEL->quickSearch->myIMComposeEvent( e );
+ return ;
+ }
+}
+
+void KrBriefView::keyPressEvent( QKeyEvent * e ) {
+ if ( !e || !firstItem() )
+ return ; // subclass bug
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ ACTIVE_PANEL->quickSearch->myKeyPressEvent( e );
+ return ;
+ }
+ switch ( e->key() ) {
+ case Key_Up :
+ if ( e->state() == ControlButton ) { // let the panel handle it - jump to the Location Bar
+ e->ignore();
+ break;
+ } else if (!KrSelectionMode::getSelectionHandler()->useQTSelection()) {
+ QIconViewItem * i = currentItem();
+ if ( !i ) break;
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+ i = i->prevItem();
+ if ( i ) {
+ QIconView::setCurrentItem( i );
+ QIconView::ensureItemVisible( i );
+ }
+ } else KIconView::keyPressEvent(e);
+ break;
+ case Key_Down :
+ if ( e->state() == ControlButton || e->state() == ( ControlButton | ShiftButton ) ) { // let the panel handle it - jump to command line
+ e->ignore();
+ break;
+ } else if (!KrSelectionMode::getSelectionHandler()->useQTSelection()){
+ QIconViewItem * i = currentItem();
+ if ( !i ) break;
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+ i = i->nextItem();
+ if ( i ) {QIconView::setCurrentItem( i ); QIconView::ensureItemVisible( i ); }
+ } else KIconView::keyPressEvent(e);
+ break;
+ case Key_Next: if (!KrSelectionMode::getSelectionHandler()->useQTSelection()){
+ QIconViewItem * i = currentItem(), *j;
+ if ( !i ) break;
+ QRect r( i->rect() );
+ if ( !r.height() ) break;
+ for ( int page = visibleHeight() / r.height() - 1; page > 0 && ( j = i->nextItem() ); --page )
+ i = j;
+ if ( i ) {QIconView::setCurrentItem( i ); QIconView::ensureItemVisible( i ); }
+ } else KIconView::keyPressEvent(e);
+ break;
+ case Key_Prior: if (!KrSelectionMode::getSelectionHandler()->useQTSelection()){
+ QIconViewItem * i = currentItem(), *j;
+ if ( !i ) break;
+ QRect r( i->rect() );
+ if ( !r.height() ) break;
+ for ( int page = visibleHeight() / r.height() - 1; page > 0 && ( j = i->prevItem() ); --page )
+ i = j;
+ if ( i ) {QIconView::setCurrentItem( i ); QIconView::ensureItemVisible( i ); }
+ } else KIconView::keyPressEvent(e);
+ break;
+ case Key_Home: if (!KrSelectionMode::getSelectionHandler()->useQTSelection()){
+ if ( e->state() & ShiftButton ) /* Shift+Home */
+ {
+ clearSelection();
+ KIconView::keyPressEvent( e );
+ op()->emitSelectionChanged();
+ arrangeItemsInGrid();
+ break;
+ } else {
+ QIconViewItem * i = firstItem();
+ if ( i ) {QIconView::setCurrentItem( i ); QIconView::ensureItemVisible( i ); }
+ }
+ } else KIconView::keyPressEvent(e);
+ break;
+ case Key_End: if (!KrSelectionMode::getSelectionHandler()->useQTSelection()){
+ if ( e->state() & ShiftButton ) /* Shift+End */
+ {
+ clearSelection();
+ KIconView::keyPressEvent( e );
+ op()->emitSelectionChanged();
+ arrangeItemsInGrid();
+ break;
+ } else {
+ QIconViewItem *i = firstItem(), *j;
+ while ( ( j = i->nextItem() ) )
+ i = j;
+ while ( ( j = i->nextItem() ) )
+ i = j;
+ if ( i ) {QIconView::setCurrentItem( i ); QIconView::ensureItemVisible( i ); }
+ break;
+ }
+ } else KIconView::keyPressEvent(e);
+ break;
+ case Key_Enter :
+ case Key_Return : {
+ if ( e->state() & ControlButton ) // let the panel handle it
+ e->ignore();
+ else {
+ KrViewItem * i = getCurrentKrViewItem();
+ QString tmp = i->name();
+ op()->emitExecuted(tmp);
+ }
+ break;
+ }
+ case Key_QuoteLeft : // Terminal Emulator bugfix
+ if ( e->state() == ControlButton ) { // let the panel handle it
+ e->ignore();
+ break;
+ } else { // a normal click - do a lynx-like moving thing
+ SLOTS->home(); // ask krusader to move up a directory
+ return ; // safety
+ }
+ break;
+ case Key_Right :
+ if ( e->state() == ControlButton ) { // let the panel handle it
+ e->ignore();
+ break;
+ } else if (!KrSelectionMode::getSelectionHandler()->useQTSelection()) {
+ QIconViewItem *i = currentItem();
+ QIconViewItem *newCurrent = 0;
+
+ if ( !i ) break;
+
+ int minY = i->y() - i->height() / 2;
+ int minX = i->width() / 2 + i->x();
+
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+
+ while( i && i->x() <= minX )
+ {
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+ newCurrent = i;
+ i = i->nextItem();
+ }
+
+ while( i && i->y() < minY )
+ {
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+ newCurrent = i;
+ i = i->nextItem();
+ }
+
+ if( i )
+ {
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+ newCurrent = i;
+ }
+
+ if( newCurrent )
+ {
+ QIconView::setCurrentItem( newCurrent );
+ QIconView::ensureItemVisible( newCurrent );
+ }
+ } else KIconView::keyPressEvent(e);
+ break;
+ case Key_Backspace : // Terminal Emulator bugfix
+ if ( e->state() == ControlButton || e->state() == ShiftButton ) { // let the panel handle it
+ e->ignore();
+ break;
+ } else { // a normal click - do a lynx-like moving thing
+ SLOTS->dirUp(); // ask krusader to move up a directory
+ return ; // safety
+ }
+ case Key_Left :
+ if ( e->state() == ControlButton ) { // let the panel handle it
+ e->ignore();
+ break;
+ } else if (!KrSelectionMode::getSelectionHandler()->useQTSelection()) {
+ QIconViewItem *i = currentItem();
+ QIconViewItem *newCurrent = 0;
+
+ if ( !i ) break;
+
+ int maxY = i->y() + i->height() / 2;
+ int maxX = i->x() - i->width() / 2;
+
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+
+ while( i && i->x() >= maxX )
+ {
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+ newCurrent = i;
+ i = i->prevItem();
+ }
+
+ while( i && i->y() > maxY )
+ {
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+ newCurrent = i;
+ i = i->prevItem();
+ }
+ if( i )
+ {
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+ newCurrent = i;
+ }
+
+ if( newCurrent )
+ {
+ QIconView::setCurrentItem( newCurrent );
+ QIconView::ensureItemVisible( newCurrent );
+ }
+ } else KIconView::keyPressEvent(e);
+ break;
+
+ case Key_Delete : // kill file
+ SLOTS->deleteFiles( e->state() == ShiftButton || e->state() == ControlButton );
+
+ break ;
+ case Key_Insert : {
+ {
+ QIconViewItem *i = currentItem();
+ if( !i )
+ break;
+
+ if (KrSelectionMode::getSelectionHandler()->insertMovesDown())
+ {
+ setSelected( i, !i->isSelected(), true );
+ if( i->nextItem() )
+ {
+ QIconView::setCurrentItem( i->nextItem() );
+ QIconView::ensureItemVisible( i->nextItem() );
+ }
+ }
+ else
+ {
+ setSelected( i, !i->isSelected(), true );
+ }
+ }
+ break ;
+ }
+ case Key_Space : {
+ {
+ QIconViewItem *i = currentItem();
+ if( !i )
+ break;
+
+ if (KrSelectionMode::getSelectionHandler()->spaceMovesDown())
+ {
+ setSelected( i, !i->isSelected(), true );
+ if( i->nextItem() )
+ {
+ QIconView::setCurrentItem( i->nextItem() );
+ QIconView::ensureItemVisible( i->nextItem() );
+ }
+ }
+ else
+ {
+ setSelected( i, !i->isSelected(), true );
+ }
+ }
+ break ;
+ }
+ case Key_A : // mark all
+ if ( e->state() == ControlButton ) {
+ KIconView::keyPressEvent( e );
+ updateView();
+ break;
+ }
+ default:
+ if ( e->key() == Key_Escape ) {
+ QIconView::keyPressEvent( e ); return ; // otherwise the selection gets lost??!??
+ }
+ // if the key is A..Z or 1..0 do quick search otherwise...
+ if ( e->text().length() > 0 && e->text() [ 0 ].isPrint() ) // better choice. Otherwise non-ascii characters like can not be the first character of a filename
+ /* if ( ( e->key() >= Key_A && e->key() <= Key_Z ) ||
+ ( e->key() >= Key_0 && e->key() <= Key_9 ) ||
+ ( e->key() == Key_Backspace ) ||
+ ( e->key() == Key_Down ) ||
+ ( e->key() == Key_Period ) ) */{
+ // are we doing quicksearch? if not, send keys to panel
+ //if ( _config->readBoolEntry( "Do Quicksearch", _DoQuicksearch ) ) {
+ // are we using krusader's classic quicksearch, or wincmd style?
+ {
+ KConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ if ( !_config->readBoolEntry( "New Style Quicksearch", _NewStyleQuicksearch ) )
+ KIconView::keyPressEvent( e );
+ else {
+ // first, show the quicksearch if its hidden
+ if ( ACTIVE_PANEL->quickSearch->isHidden() ) {
+ ACTIVE_PANEL->quickSearch->show();
+ // hack: if the pressed key requires a scroll down, the selected
+ // item is "below" the quick search window, as the icon view will
+ // realize its new size after the key processing. The following line
+ // will resize the icon view immediately.
+ ACTIVE_PANEL->layout->activate();
+ // second, we need to disable the dirup action - hack!
+ krDirUp->setEnabled( false );
+ }
+ // now, send the key to the quicksearch
+ ACTIVE_PANEL->quickSearch->myKeyPressEvent( e );
+ }
+ }
+ //} else
+ // e->ignore(); // send to panel
+ } else {
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ ACTIVE_PANEL->quickSearch->hide();
+ ACTIVE_PANEL->quickSearch->clear();
+ krDirUp->setEnabled( true );
+ }
+ KIconView::keyPressEvent( e );
+ }
+ }
+ // emit the new item description
+ slotItemDescription( currentItem() ); // actually send the QIconViewItem
+}
+// overridden to make sure EXTENTION won't be lost during rename
+void KrBriefView::rename( QIconViewItem * item ) {
+ currentlyRenamedItem = dynamic_cast< KrBriefViewItem * >( item );
+ currentlyRenamedItem->rename();
+ //TODO: renameLineEdit() ->selectAll();
+}
+
+void KrBriefView::renameCurrentItem() {
+ QString newName, fileName;
+
+ // handle inplace renaming, if possible
+
+ KrBriefViewItem *it = static_cast<KrBriefViewItem*>(getCurrentKrViewItem());
+ if ( it )
+ fileName = it->name();
+ else
+ return ; // quit if no current item available
+ // don't allow anyone to rename ..
+ if ( fileName == ".." )
+ return ;
+
+ rename( static_cast<QIconViewItem*>( it ) );
+ // if applicable, select only the name without extension
+/* TODO:
+ KConfigGroupSaver svr(krConfig,"Look&Feel");
+ if (!krConfig->readBoolEntry("Rename Selects Extension", true)) {
+ if (it->hasExtension() && !it->VF->vfile_isDir() )
+ renameLineEdit()->setSelection(0, it->name().findRev(it->extension())-1);
+ }*/
+}
+
+void KrBriefView::inplaceRenameFinished( QIconViewItem * it ) {
+ if ( !it ) { // major failure - call developers
+ krOut << "Major failure at inplaceRenameFinished(): item is null" << endl;
+ return;
+ }
+
+ KrBriefViewItem *item = dynamic_cast<KrBriefViewItem *>( it );
+ if( item->text() != item->name() )
+ op()->emitRenameItem( item->name(), item->text() );
+
+ currentlyRenamedItem = 0;
+ setFocus();
+}
+
+// TODO: move the whole quicksearch mess out of here and into krview
+void KrBriefView::quickSearch( const QString & str, int direction ) {
+ KrViewItem * item = getCurrentKrViewItem();
+ if (!item)
+ return;
+ KConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ bool caseSensitive = _config->readBoolEntry( "Case Sensitive Quicksearch", _CaseSensitiveQuicksearch );
+ if ( !direction ) {
+ if ( caseSensitive ? item->name().startsWith( str ) : item->name().lower().startsWith( str.lower() ) )
+ return ;
+ direction = 1;
+ }
+ KrViewItem * startItem = item;
+ while ( true ) {
+ item = ( direction > 0 ) ? getNext( item ) : getPrev( item );
+ if ( !item )
+ item = ( direction > 0 ) ? getFirst() : getLast();
+ if ( item == startItem )
+ return ;
+ if ( caseSensitive ? item->name().startsWith( str ) : item->name().lower().startsWith( str.lower() ) ) {
+ setCurrentItem( item->name() );
+ makeItemVisible( item );
+ return ;
+ }
+ }
+}
+
+void KrBriefView::stopQuickSearch( QKeyEvent * e ) {
+ if( ACTIVE_PANEL && ACTIVE_PANEL->quickSearch ) {
+ ACTIVE_PANEL->quickSearch->hide();
+ ACTIVE_PANEL->quickSearch->clear();
+ krDirUp->setEnabled( true );
+ if ( e )
+ keyPressEvent( e );
+ }
+}
+
+void KrBriefView::setNameToMakeCurrent( QIconViewItem * it ) {
+ if (!it) return;
+ KrView::setNameToMakeCurrent( static_cast<KrBriefViewItem*>( it ) ->name() );
+}
+
+void KrBriefView::slotMouseClicked( int button, QIconViewItem * item, const QPoint& ) {
+ pressedItem = 0; // if the signals are emitted, don't emit twice at contentsMouseReleaseEvent
+ if ( button == Qt::MidButton )
+ emit middleButtonClicked( dynamic_cast<KrViewItem *>( item ) );
+}
+
+void KrBriefView::refreshColors() {
+ krConfig->setGroup("Colors");
+ bool kdeDefault = krConfig->readBoolEntry("KDE Default");
+ if ( !kdeDefault ) {
+ // KDE default is not choosen: set the background color (as this paints the empty areas) and the alternate color
+ bool isActive = hasFocus();
+ if ( MAIN_VIEW && ACTIVE_PANEL && ACTIVE_PANEL->view )
+ isActive = ( static_cast<KrView *>( this ) == ACTIVE_PANEL->view );
+ QColorGroup cg;
+ KrColorCache::getColorCache().getColors(cg, KrColorItemType(KrColorItemType::File, false, isActive, false, false));
+ setPaletteBackgroundColor( cg.background() );
+ } else {
+ // KDE default is choosen: set back the background color
+ setPaletteBackgroundColor( KGlobalSettings::baseColor() );
+ }
+ slotUpdate();
+}
+
+bool KrBriefView::event( QEvent *e ) {
+ modifierPressed = false;
+
+ switch ( e->type() ) {
+ case QEvent::Timer:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ break;
+ default:
+ CANCEL_TWO_CLICK_RENAME;
+ }
+ if( e->type() == QEvent::Wheel )
+ {
+ if ( !_focused )
+ op()->emitNeedFocus();
+ setFocus();
+ }
+ return KIconView::event( e );
+}
+
+
+bool KrBriefView::eventFilter( QObject * watched, QEvent * e )
+{
+ if( watched == horizontalScrollBar() )
+ {
+ if( e->type() == QEvent::Hide || e->type() == QEvent::Show )
+ {
+ bool res = KIconView::eventFilter( watched, e );
+ arrangeItemsInGrid();
+ return res;
+ }
+ }
+ else if( watched == header )
+ {
+ if( e->type() == QEvent::MouseButtonPress && ((QMouseEvent *)e )->button() == Qt::RightButton )
+ {
+ setColumnNr();
+ return TRUE;
+ }
+ return FALSE;
+ }
+ return KIconView::eventFilter( watched, e );
+}
+
+void KrBriefView::makeItemVisible( const KrViewItem *item ) {
+// qApp->processEvents(); // Please don't remove the comment. Causes crash if it is inserted!
+ ensureItemVisible( (QIconViewItem *)( static_cast<const KrBriefViewItem*>( item ) ) );
+}
+
+void KrBriefView::initOperator() {
+ _operator = new KrViewOperator(this, this);
+ // QIconView emits selection changed, so chain them to operator
+ connect(this, SIGNAL(selectionChanged()), _operator, SIGNAL(selectionChanged()));
+}
+
+void KrBriefView::initProperties() {
+ // TODO: move this to a general location, maybe KrViewProperties constructor ?
+ _properties = new KrBriefViewProperties;
+ _properties->filter = KrViewProperties::All;
+ _properties->filterMask = KRQuery( "*" );
+ KConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ _properties->displayIcons = _config->readBoolEntry( "With Icons", _WithIcons );
+ bool dirsByNameAlways = _config->readBoolEntry("Always sort dirs by name", false);
+ _properties->sortMode = static_cast<KrViewProperties::SortSpec>( KrViewProperties::Name |
+ KrViewProperties::Descending | KrViewProperties::DirsFirst |
+ (dirsByNameAlways ? KrViewProperties::AlwaysSortDirsByName : 0) );
+ if ( !_config->readBoolEntry( "Case Sensative Sort", _CaseSensativeSort ) )
+ _properties->sortMode = static_cast<KrViewProperties::SortSpec>( _properties->sortMode |
+ KrViewProperties::IgnoreCase );
+ _properties->humanReadableSize = krConfig->readBoolEntry("Human Readable Size", _HumanReadableSize);
+ _properties->localeAwareCompareIsCaseSensitive = QString( "a" ).localeAwareCompare( "B" ) > 0; // see KDE bug #40131
+
+ QStringList defaultAtomicExtensions;
+ defaultAtomicExtensions += ".tar.gz";
+ defaultAtomicExtensions += ".tar.bz2";
+ defaultAtomicExtensions += ".moc.cpp";
+ QStringList atomicExtensions = krConfig->readListEntry("Atomic Extensions", defaultAtomicExtensions);
+ for (QStringList::iterator i = atomicExtensions.begin(); i != atomicExtensions.end(); )
+ {
+ QString & ext = *i;
+ ext = ext.stripWhiteSpace();
+ if (!ext.length())
+ {
+ i = atomicExtensions.remove(i);
+ continue;
+ }
+ if (!ext.startsWith("."))
+ ext.insert(0, '.');
+ ++i;
+ }
+ _properties->atomicExtensions = atomicExtensions;
+
+ _config->setGroup( nameInKConfig() );
+ PROPS->numberOfColumns = _config->readNumEntry( "Number Of Brief Columns", _NumberOfBriefColumns );
+ if( PROPS->numberOfColumns < 1 )
+ PROPS->numberOfColumns = 1;
+ else if( PROPS->numberOfColumns > MAX_COLS )
+ PROPS->numberOfColumns = MAX_COLS;
+}
+
+void KrBriefView::setColumnNr()
+{
+ KPopupMenu popup( this );
+ popup.insertTitle( i18n("Columns"));
+
+ int COL_ID = 14700;
+
+ for( int i=1; i <= MAX_COLS; i++ )
+ {
+ popup.insertItem( QString( "%1" ).arg( i ), COL_ID + i );
+ popup.setItemChecked( COL_ID + i, PROPS->numberOfColumns == i );
+ }
+
+ int result=popup.exec(QCursor::pos());
+
+ krConfig->setGroup( nameInKConfig() );
+
+ if( result > COL_ID && result <= COL_ID + MAX_COLS )
+ {
+ krConfig->writeEntry( "Number Of Brief Columns", result - COL_ID );
+ PROPS->numberOfColumns = result - COL_ID;
+ redrawColumns();
+ }
+}
+
+void KrBriefView::sortOrderChanged() {
+ ensureItemVisible(currentItem());
+
+ if( !_focused )
+ op()->emitNeedFocus();
+
+}
+
+void KrBriefView::updateView() {
+ arrangeItemsInGrid();
+ op()->emitSelectionChanged();
+}
+
+void KrBriefView::updateItem(KrViewItem* item) {
+ dynamic_cast<KrBriefViewItem*>(item)->repaintItem();
+}
+
+void KrBriefView::slotRightButtonPressed(QIconViewItem*, const QPoint& point) {
+ op()->emitEmptyContextMenu(point);
+}
+
+void KrBriefView::changeSortOrder()
+{
+ bool asc = !sortDirection();
+ header->setSortIndicator( 0, asc ? Qt::Ascending : Qt::Descending );
+ sort( asc );
+}
+
+QMouseEvent * KrBriefView::transformMouseEvent( QMouseEvent * e )
+{
+ if( findItem( e->pos() ) != 0 )
+ return e;
+
+ QIconViewItem *closestItem = 0;
+ int mouseX = e->pos().x(), mouseY = e->pos().y();
+ int closestDelta = 0x7FFFFFFF;
+
+ int minX = ( mouseX / gridX() ) * gridX();
+ int maxX = minX + gridX();
+
+ QIconViewItem *current = firstItem();
+ while( current )
+ {
+ if( current->x() >= minX && current->x() < maxX )
+ {
+ int delta = mouseY - current->y();
+ if( delta >= 0 && delta < closestDelta )
+ {
+ closestDelta = delta;
+ closestItem = current;
+ }
+ }
+ current = current->nextItem();
+ }
+
+ if( closestItem != 0 )
+ {
+ if( mouseX - closestItem->x() > gridX() )
+ closestItem = 0;
+ else if( mouseY - closestItem->y() > closestItem->height() )
+ closestItem = 0;
+ }
+
+ if( closestItem != 0 )
+ {
+ QRect rec = closestItem->textRect( false );
+ if( mouseX < rec.x() )
+ mouseX = rec.x();
+ if( mouseY < rec.y() )
+ mouseY = rec.y();
+ if( mouseX > rec.x() + rec.width() -1 )
+ mouseX = rec.x() + rec.width() -1;
+ if( mouseY > rec.y() + rec.height() -1 )
+ mouseY = rec.y() + rec.height() -1;
+ QPoint newPos( mouseX, mouseY );
+ QPoint glPos;
+ if( !e->globalPos().isNull() )
+ {
+ glPos = QPoint( mouseX - e->pos().x() + e->globalPos().x(),
+ mouseY - e->pos().y() + e->globalPos().y() );
+ }
+
+ if( mouseEvent )
+ delete mouseEvent;
+ return mouseEvent = new QMouseEvent( e->type(), newPos, glPos, e->button(), e->state() );
+ }
+
+ return e;
+}
+
+#include "krbriefview.moc"
diff --git a/krusader/Panel/krbriefview.h b/krusader/Panel/krbriefview.h
new file mode 100644
index 0000000..8ba27f4
--- /dev/null
+++ b/krusader/Panel/krbriefview.h
@@ -0,0 +1,172 @@
+/***************************************************************************
+ krbriefview.h
+ -------------------
+ copyright : (C) 2000-2007 by Shie Erlich & Rafi Yanai & Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+Description
+***************************************************************************
+
+A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+#ifndef KRBRIEFVIEW_H
+#define KRBRIEFVIEW_H
+
+#include "krview.h"
+#include "krviewitem.h"
+#include <kiconview.h>
+#include <qtimer.h>
+
+// extends KrViewProperties to add detailedview-only properties
+class KrBriefViewProperties: public KrViewProperties {
+public:
+ int numberOfColumns; // the number of columns in the view
+};
+
+class KrBriefViewItem;
+class QDragMoveEvent;
+class QToolTip;
+class QHeader;
+
+/**
+ * KrBriefView implements everthing and anything regarding a brief view in a filemananger.
+ * IT MUST USE KrViewItem as the children to it's *KIconView. KrBriefView and KrViewItem are
+ * tightly coupled and the view will not work with other kinds of items.
+ * Apart from this, the view is self-reliant and you can use the vast interface to get whatever
+ * information is necessery from it.
+ */
+class KrBriefView: public KIconView, public KrView {
+ friend class KrBriefViewItem;
+ Q_OBJECT
+public:
+ KrBriefView( QHeader *header, QWidget *parent, bool &left, KConfig *cfg = krConfig, const char *name = 0 );
+ virtual ~KrBriefView();
+ virtual inline KrViewItem *getFirst() { return dynamic_cast<KrViewItem*>( firstItem() ); }
+ virtual inline KrViewItem *getLast() { return dynamic_cast<KrViewItem*>( lastItem() ); }
+ virtual inline KrViewItem *getNext( KrViewItem *current ) { return dynamic_cast<KrViewItem*>( dynamic_cast<QIconViewItem*>( current ) ->nextItem() ); }
+ virtual inline KrViewItem *getPrev( KrViewItem *current ) { return dynamic_cast<KrViewItem*>( dynamic_cast<QIconViewItem*>( current ) ->prevItem() ); }
+ virtual inline KrViewItem *getCurrentKrViewItem() { return dynamic_cast<KrViewItem*>( currentItem() ); }
+ virtual KrViewItem *getKrViewItemAt(const QPoint &vp);
+ virtual inline KrViewItem *findItemByName(const QString &name) { return dynamic_cast<KrViewItem*>( findItem( name, Qt::ExactMatch ) ); }
+ virtual void addItems(vfs* v, bool addUpDir = true);
+ virtual void delItem(const QString &);
+ virtual QString getCurrentItem() const;
+ virtual void makeItemVisible(const KrViewItem * item );
+ virtual void setCurrentItem(const QString& name );
+ virtual void updateView();
+ virtual void updateItem(KrViewItem* item );
+ virtual void clear();
+ virtual void sort() { if( sortDirection() ) sortOrderChanged();KIconView::sort( true ); }
+ virtual void sort( bool ascending ) { if( sortDirection() != ascending ) sortOrderChanged();KIconView::sort( ascending ); }
+ virtual void prepareForActive();
+ virtual void prepareForPassive();
+ virtual void saveSettings() {}
+ virtual void restoreSettings() {}
+ virtual QString nameInKConfig() {return _nameInKConfig;}
+ virtual void resizeEvent ( QResizeEvent * );
+
+signals:
+ void middleButtonClicked( KrViewItem *item );
+ void currentChanged( KrViewItem *item );
+
+protected:
+ virtual void setup();
+ virtual void initProperties();
+ virtual void initOperator();
+ virtual KrViewItem *preAddItem(vfile * vf);
+ virtual bool preDelItem(KrViewItem * item );
+
+ void setColumnNr();
+ void redrawColumns();
+
+ virtual void keyPressEvent( QKeyEvent *e );
+ virtual void imStartEvent( QIMEvent* e );
+ virtual void imEndEvent( QIMEvent *e );
+ virtual void imComposeEvent( QIMEvent *e );
+ virtual void contentsMousePressEvent( QMouseEvent *e );
+ virtual void contentsMouseReleaseEvent (QMouseEvent *e);
+ virtual void contentsMouseMoveEvent ( QMouseEvent * e );
+ virtual void contentsMouseDoubleClickEvent ( QMouseEvent * e );
+ virtual bool acceptDrag( QDropEvent* e ) const;
+ virtual void contentsDropEvent( QDropEvent *e );
+ virtual void contentsDragMoveEvent( QDragMoveEvent *e );
+ virtual void contentsDragLeaveEvent ( QDragLeaveEvent * );
+ virtual void startDrag() { op()->startDrag(); }
+ virtual bool event( QEvent *e );
+ virtual bool eventFilter( QObject * watched, QEvent * e );
+ QMouseEvent * transformMouseEvent( QMouseEvent * );
+
+protected slots:
+ void rename( QIconViewItem *item );
+ void slotClicked( QIconViewItem *item );
+ void slotDoubleClicked( QIconViewItem *item );
+ void slotItemDescription( QIconViewItem * );
+ void slotCurrentChanged( QIconViewItem *item );
+ void handleContextMenu( QIconViewItem*, const QPoint& );
+ virtual void renameCurrentItem();
+ virtual void showContextMenu( );
+ void inplaceRenameFinished( QIconViewItem *it );
+ void setNameToMakeCurrent( QIconViewItem *it );
+ void sortOrderChanged();
+ void slotRightButtonPressed(QIconViewItem*, const QPoint& point);
+ void transformCurrentChanged( QIconViewItem * item ) { emit currentChanged( dynamic_cast<KrViewItem *>(item ) ); }
+
+ /**
+ * used internally to produce the signal middleButtonClicked()
+ */
+ void slotMouseClicked( int button, QIconViewItem * item, const QPoint & pos );
+ inline void slotExecuted( QIconViewItem* i ) {
+ QString tmp = dynamic_cast<KrViewItem*>( i ) ->name();
+ op()->emitExecuted( tmp );
+ }
+
+public slots:
+ void refreshColors();
+ void quickSearch( const QString &, int = 0 );
+ void stopQuickSearch( QKeyEvent* );
+ void handleQuickSearchEvent( QKeyEvent* );
+ void changeSortOrder();
+
+
+signals:
+ void letsDrag(QStringList items, QPixmap icon);
+ void gotDrop(QDropEvent *);
+
+private:
+ QHeader * header;
+ bool swushSelects;
+ QPoint dragStartPos;
+ QIconViewItem *lastSwushPosition;
+ KrViewItem *_currDragItem;
+ bool singleClicked;
+ bool modifierPressed;
+ QTime clickTime;
+ QIconViewItem *clickedItem;
+ QTimer renameTimer;
+ QTimer contextMenuTimer;
+ QPoint contextMenuPoint;
+ KrBriefViewItem *currentlyRenamedItem;
+ QIconViewItem *pressedItem;
+ QMouseEvent *mouseEvent;
+ QToolTip *toolTip;
+};
+
+#endif
diff --git a/krusader/Panel/krbriefviewitem.cpp b/krusader/Panel/krbriefviewitem.cpp
new file mode 100644
index 0000000..533090f
--- /dev/null
+++ b/krusader/Panel/krbriefviewitem.cpp
@@ -0,0 +1,225 @@
+#include "krbriefview.h"
+#include "krbriefviewitem.h"
+#include "../krusaderview.h"
+#include "../defaults.h"
+#include "../kicons.h"
+#include "listpanel.h"
+#include <kconfig.h>
+#include "krcolorcache.h"
+
+#include <qpainter.h>
+#include <qpointarray.h>
+
+#define PROPS _viewProperties
+#define VF getVfile()
+
+#ifdef FASTER
+int KrBriefViewItem::expHeight = 0;
+#endif // FASTER
+
+KrBriefViewItem::KrBriefViewItem(KrBriefView *parent, QIconViewItem *after, vfile *vf):
+ KIconViewItem(parent, after), KrViewItem(vf, parent->properties()) {
+#ifdef FASTER
+ initiated = false;
+ // get the expected height of an item - should be done only once
+ if (expHeight == 0) {
+ KConfigGroupSaver svr(krConfig, "Look&Feel");
+ expHeight = 2 + (krConfig->readEntry("Filelist Icon Size",_FilelistIconSize)).toInt();
+ }
+ if( PROPS->displayIcons )
+ itemIcon = QPixmap( expHeight, expHeight );
+#endif // FASTER
+
+ // there's a special case, where if _vf is null, then we've got the ".." (updir) item
+ // in that case, create a special vfile for that item, and delete it, if needed
+ if (!_vf) {
+ dummyVfile = true;
+ _vf = new vfile("..", 0, "drw-r--r--", 0, false, 0, 0, QString::null, QString::null, 0);
+
+ setText("..");
+ if ( PROPS->displayIcons )
+ setPixmap( FL_LOADICON( "up" ) );
+ setSelectable( false );
+ setDragEnabled( false );
+ setDropEnabled( false );
+#ifdef FASTER
+ initiated = true;
+#endif // FASTER
+ }
+
+ setRenameEnabled( false );
+ setDragEnabled( true );
+ setDropEnabled( true );
+ repaintItem();
+}
+
+
+int KrBriefViewItem::compare(QIconViewItem *i ) const {
+ bool ignoreCase = (PROPS->sortMode & KrViewProperties::IgnoreCase);
+
+ KrBriefViewItem *other = (KrBriefViewItem *)i;
+ int asc = iconView()->sortDirection() ? -1 : 1;
+
+ bool thisDir = VF->vfile_isDir();
+ bool otherDir = other->VF->vfile_isDir();
+
+ // handle directory sorting
+ if ( thisDir ){
+ if ( !otherDir ) return 1*asc;
+ } else if( otherDir ) return -1*asc;
+
+ if ( isDummy() ) return 1*asc;
+ if ( other->isDummy() ) return -1*asc;
+
+ QString text0 = name();
+ if (text0 == "..") return 1*asc;
+
+ QString itext0 = other->name();
+ if (itext0 == "..") return -1*asc;
+
+ if( ignoreCase )
+ {
+ text0 = text0.lower();
+ itext0 = itext0.lower();
+ }
+
+ if ( isHidden() ) {
+ if ( !other->isHidden() ) return 1*asc;
+ } else if ( other->isHidden() ) return -1*asc;
+
+ if (!ignoreCase && !PROPS->localeAwareCompareIsCaseSensitive) {
+ // sometimes, localeAwareCompare is not case sensative. in that case,
+ // we need to fallback to a simple string compare (KDE bug #40131)
+ return QString::compare(text0, itext0);
+ } else return QString::localeAwareCompare(text0,itext0);
+}
+
+void KrBriefViewItem::paintItem(QPainter *p, const QColorGroup &cg) {
+#ifdef FASTER
+ if (!initiated && !dummyVfile) {
+ // display an icon if needed
+ initiated = true;
+ if (PROPS->displayIcons)
+ itemIcon =KrView::getIcon(_vf);
+ }
+#endif
+
+ QColorGroup _cg(cg);
+
+ KrColorItemType colorItemType;
+ colorItemType.m_activePanel = (dynamic_cast<KrView *>(iconView()) == ACTIVE_PANEL->view);
+
+ int gridX = iconView()->gridX();
+ int xpos = x() / gridX;
+ int ypos = y() / height();
+
+ colorItemType.m_alternateBackgroundColor = (xpos & 1) ^ (ypos & 1) ;
+ colorItemType.m_currentItem = (iconView()->currentItem() == this);
+ colorItemType.m_selectedItem = isSelected();
+ if (VF->vfile_isSymLink())
+ {
+ if (_vf->vfile_getMime() == "Broken Link !" )
+ colorItemType.m_fileType = KrColorItemType::InvalidSymlink;
+ else
+ colorItemType.m_fileType = KrColorItemType::Symlink;
+ }
+ else if (VF->vfile_isDir())
+ colorItemType.m_fileType = KrColorItemType::Directory;
+ else if (VF->vfile_isExecutable())
+ colorItemType.m_fileType = KrColorItemType::Executable;
+ else
+ colorItemType.m_fileType = KrColorItemType::File;
+ KrColorCache::getColorCache().getColors(_cg, colorItemType);
+
+ if( _cg.background() != iconView()->paletteBackgroundColor() )
+ {
+ p->save();
+ p->setPen( Qt::NoPen );
+ p->setBrush( QBrush( _cg.background() ) );
+ p->drawRect( rect() );
+ p->restore();
+ }
+
+ QIconViewItem::paintItem(p, _cg);
+
+ paintFocus( p, cg );
+}
+
+void KrBriefViewItem::paintFocus(QPainter *p, const QColorGroup &cg) {
+ if ( ( iconView()->hasFocus() && this == iconView()->currentItem() ) ||
+ ((KrBriefView *)iconView())->_currDragItem == this )
+ {
+ p->save();
+ QPen pen( cg.shadow(), 0, Qt::DotLine );
+ p->setPen( pen );
+
+ // we manually draw the focus rect by points
+ QRect rec = rect();
+ QPointArray points( rec.right() - rec.left() + rec.bottom() - rec.top() + 4 );
+
+ int ndx = 0;
+ for( int x=rec.left(); x <= rec.right(); x+=2 )
+ {
+ points.setPoint( ndx++, x, rec.top() );
+ points.setPoint( ndx++, x, rec.bottom() );
+ }
+ for( int y=rec.top(); y <= rec.bottom(); y+=2 )
+ {
+ points.setPoint( ndx++, rec.left(), y );
+ points.setPoint( ndx++, rec.right(), y );
+ }
+
+ p->drawPoints( points );
+ p->restore();
+
+// --- That didn't work with all themes
+// iconView()->style().drawPrimitive(QStyle::PE_FocusRect, p,
+// QRect( rect().x(), rect().y(), rect().width(), rect().height() ), cg,
+// QStyle::Style_Default, cg.base() );
+ }
+}
+
+void KrBriefViewItem::itemHeightChanged() {
+#ifdef FASTER
+ expHeight = 0;
+#endif // FASTER
+}
+
+void KrBriefViewItem::repaintItem()
+{
+ if ( dummyVfile ) return;
+
+#ifndef FASTER
+ if (PROPS->displayIcons)
+ setPixmap(KrView::getIcon(_vf));
+#endif // FASTER
+ setText( _vf->vfile_getName() );
+}
+
+// for keeping the exact item heights...
+void KrBriefViewItem::calcRect ( const QString & text_ )
+{
+ KIconViewItem::calcRect( text_ );
+ QRect rec = rect();
+
+ int gridX = iconView()->gridX();
+ int minX = ( rec.x() / gridX ) * gridX;
+ rec.setX( minX );
+ rec.setWidth( gridX );
+ rec.setHeight( expHeight );
+ setItemRect( rec );
+
+ rec = pixmapRect();
+ if( rec.height() > expHeight )
+ {
+ rec.setHeight( expHeight );
+ setPixmapRect( rec );
+ }
+
+ rec = textRect();
+ if( rec.height() > expHeight )
+ {
+ rec.setHeight( expHeight );
+ setTextRect( rec );
+ }
+}
diff --git a/krusader/Panel/krbriefviewitem.h b/krusader/Panel/krbriefviewitem.h
new file mode 100644
index 0000000..e95c01b
--- /dev/null
+++ b/krusader/Panel/krbriefviewitem.h
@@ -0,0 +1,79 @@
+/***************************************************************************
+ krbriefviewitem.h
+ -------------------
+ copyright : (C) 2000-2007 by Shie Erlich & Rafi Yanai & Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KRBRIEFVIEWITEM_H
+#define KRBRIEFVIEWITEM_H
+
+#include "krviewitem.h"
+#include <sys/types.h>
+#include "../VFS/vfile.h"
+#include <kiconview.h>
+#include <qguardedptr.h>
+
+#define FASTER
+
+class QPixmap;
+class KrBriefView;
+
+class KrBriefViewItem : public KIconViewItem, public KrViewItem {
+friend class KrBriefView;
+friend class KrCalcSpaceDialog;
+public:
+ KrBriefViewItem(KrBriefView *parent, QIconViewItem *after, vfile *vf);
+ inline bool isSelected() const { return KIconViewItem::isSelected(); }
+ inline void setSelected(bool s) { KIconViewItem::setSelected(s); }
+ inline void cancelRename() { removeRenameBox(); }
+ int compare(QIconViewItem *i) const;
+ virtual void repaintItem();
+ static void itemHeightChanged(); // force the items to resize when icon/font size change
+ // TODO: virtual void setup(); // called when iconview needs to know the height of the item
+#ifdef FASTER
+ virtual QPixmap * pixmap() const {return const_cast<QPixmap *>(&itemIcon);}
+ virtual void setPixmap ( const QPixmap &icon ) { itemIcon = icon;}
+#endif
+
+protected:
+ virtual void paintItem(QPainter *p, const QColorGroup &cg);
+ virtual void paintFocus(QPainter *p, const QColorGroup &cg);
+ virtual void calcRect ( const QString & text_ = QString::null );
+
+private:
+#ifdef FASTER
+ bool initiated;
+ static int expHeight;
+ QPixmap itemIcon;
+#endif // FASTER
+ // TODO:
+ static const QColor & setColorIfContrastIsSufficient(const QColor & /* background */, const QColor & /* color1 */, const QColor & /* color2 */ ) {static QColor col; return col;}
+
+// static int expHeight;
+};
+
+#endif
diff --git a/krusader/Panel/krcalcspacedialog.cpp b/krusader/Panel/krcalcspacedialog.cpp
new file mode 100644
index 0000000..aced7ed
--- /dev/null
+++ b/krusader/Panel/krcalcspacedialog.cpp
@@ -0,0 +1,187 @@
+/***************************************************************************
+ krcalcspacedialog.cpp - description
+ -------------------
+ begin : Fri Jan 2 2004
+ copyright : (C) 2004 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+Description
+***************************************************************************
+
+A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+// Qt Includes
+#include <qtimer.h>
+#include <qlayout.h>
+#include <qlabel.h>
+// KDE Includes
+#include <klocale.h>
+#include <kcursor.h>
+// Krusader Includes
+#include "krcalcspacedialog.h"
+#include "listpanel.h"
+#include "panelfunc.h"
+#include "../krusader.h"
+#include "../VFS/krpermhandler.h"
+
+/* --=={ Patch by Heiner <h.eichmann@gmx.de> }==-- */
+KrCalcSpaceDialog::CalcThread::CalcThread(KrCalcSpaceDialog * parent, ListPanel * panel, const QStringList & items)
+ : m_totalSize(0), m_currentSize(0), m_totalFiles(0), m_totalDirs(0), m_items(items), m_files(panel->func->files()),
+ m_view(panel->view), m_parent(parent), m_threadInUse(true), m_stop(false) {}
+
+void KrCalcSpaceDialog::CalcThread::cleanUp(){
+ if (m_threadInUse || !finished())
+ m_synchronizeUsageAccess.unlock();
+ else{
+ m_synchronizeUsageAccess.unlock(); // prevents a resource leak
+ // otherwise: no one needs this instance any more: delete it
+ delete this;
+ }
+}
+
+void KrCalcSpaceDialog::CalcThread::deleteInstance(){
+ // synchronize to avoid race condition.
+ m_synchronizeUsageAccess.lock();
+ m_threadInUse = false;
+ cleanUp();
+}
+
+void KrCalcSpaceDialog::CalcThread::run(){
+ if ( !m_items.isEmpty() ) // if something to do: do the calculation
+ for ( QStringList::ConstIterator it = m_items.begin(); it != m_items.end(); ++it )
+ {
+ m_currentSize = 0;
+ m_files->vfs_calcSpace( *it, &m_currentSize, &m_totalFiles, &m_totalDirs , & m_stop);
+ if (m_stop)
+ break;
+ KrDetailedViewItem * viewItem = dynamic_cast<KrDetailedViewItem *>(m_view->findItemByName ( *it ) );
+ if (viewItem){
+ KrCalcSpaceDialog::setDirSize(viewItem, m_currentSize);
+ //viewItem->repaintItem(); // crash in KrDetailedViewItem::repaintItem(): setPixmap(_view->column(KrDetailedView::Name),KrView::getIcon(_vf))
+ }
+ m_totalSize += m_currentSize;
+ m_currentSize = 0;
+ }
+ // synchronize to avoid race condition.
+ m_synchronizeUsageAccess.lock();
+ cleanUp(); // this does not need the instance any more
+}
+
+void KrCalcSpaceDialog::CalcThread::stop(){
+ // cancel was pressed
+ m_stop = true;
+}
+
+KrCalcSpaceDialog::KrCalcSpaceDialog(QWidget *parent, ListPanel * files, const QStringList & items, bool autoclose) :
+ KDialogBase(parent, "KrCalcSpaceDialog", true, i18n("Calculate Occupied Space"), Ok|Cancel),
+ m_autoClose(autoclose), m_canceled(false), m_timerCounter(0){
+ // the dialog: The Ok button is hidden until it is needed
+ showButtonOK(false);
+ m_thread = new CalcThread(this, files, items);
+ m_pollTimer = new QTimer(this);
+ QWidget * mainWidget = new QWidget( this );
+ setMainWidget(mainWidget);
+ QVBoxLayout *topLayout = new QVBoxLayout( mainWidget, 0, spacingHint() );
+
+ m_label = new QLabel( "", mainWidget, "caption" );
+ showResult(); // fill m_label with something usefull
+ topLayout->addWidget( m_label );
+ topLayout->addStretch(10);
+}
+
+void KrCalcSpaceDialog::calculationFinished(){
+ // close dialog if auto close is true
+ if (m_autoClose){
+ done(0);
+ return;
+ }
+ // otherwise hide cancel and show ok button
+ showButtonCancel(false);
+ showButtonOK(true);
+ showResult(); // and show final result
+}
+
+/* This timer has two jobs: it polls the thread if it is finished. Polling is
+ better here as it might finish while the dialog builds up. Secondly it refreshes
+ the displayed result.
+ */
+void KrCalcSpaceDialog::timer(){
+ // thread finished?
+ if (m_thread->finished()){
+ // close dialog or switch buttons
+ calculationFinished();
+ m_pollTimer->stop(); // stop the polling. No longer needed
+ return;
+ }
+
+ // Every 10 pollings (1 second) refresh the displayed result
+ if (++m_timerCounter > 10){
+ m_timerCounter = 0;
+ showResult();
+ }
+}
+
+void KrCalcSpaceDialog::showResult(){
+ if (!m_thread) return;
+ QString msg;
+ QString fileName = ( ( m_thread->getItems().count() == 1 ) ? ( i18n( "Name: " ) + m_thread->getItems().first() + "\n" ) : QString( "" ) );
+ msg = fileName + i18n( "Total occupied space: %1").arg( KIO::convertSize( m_thread->getTotalSize() ) );
+ if (m_thread->getTotalSize() >= 1024)
+ msg += " (" + KRpermHandler::parseSize( m_thread->getTotalSize() ) + "bytes)";
+ msg += "\n";
+ msg += i18n("in %n directory", "in %n directories", m_thread->getTotalDirs() );
+ msg += " ";
+ msg += i18n("and %n file", "and %n files", m_thread->getTotalFiles() );
+ m_label->setText(msg);
+}
+
+void KrCalcSpaceDialog::slotCancel(){
+ m_thread->stop(); // notify teh thread to stop
+ m_canceled = true; // set the cancel flag
+ KDialogBase::slotCancel(); // close the dialog
+}
+
+KrCalcSpaceDialog::~KrCalcSpaceDialog(){
+ CalcThread * tmp = m_thread;
+ m_thread = 0; // do not access the thread anymore or core dump if smoe piece of code wrongly does
+ tmp->deleteInstance(); // Notify the thread, that the dialog does not need anymore.
+}
+
+void KrCalcSpaceDialog::exec(){
+ m_thread->start(); // start the thread
+ if (m_autoClose){ // autoclose
+ // set the cursor to busy mode and wait 3 seconds or until the thread finishes
+ krApp->setCursor( KCursor::waitCursor() );
+ bool result = m_thread->wait(3000);
+ krApp->setCursor( KCursor::arrowCursor() ); // return the cursor to normal mode
+ if (result) return;// thread finished: do not show the dialog
+ showResult(); // fill the invisible dialog with usefull data
+ }
+ // prepare and start the poll timer
+ connect(m_pollTimer, SIGNAL(timeout()), this, SLOT(timer()));
+ m_pollTimer->start(100);
+ KDialogBase::exec(); // show the dialog
+}
+/* --=={ End of patch by Heiner <h.eichmann@gmx.de> }==-- */
+
+
+#include "krcalcspacedialog.moc"
diff --git a/krusader/Panel/krcalcspacedialog.h b/krusader/Panel/krcalcspacedialog.h
new file mode 100644
index 0000000..fcdbdce
--- /dev/null
+++ b/krusader/Panel/krcalcspacedialog.h
@@ -0,0 +1,106 @@
+/***************************************************************************
+ krcalcspacedialog.h - description
+ -------------------
+ begin : Fri Jan 2 2004
+ copyright : (C) 2004 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KRCALCSPACEDIALOG_H
+#define KRCALCSPACEDIALOG_H
+
+/* --=={ Patch by Heiner <h.eichmann@gmx.de> }==-- */
+
+// KDE Includes
+#include <kdialogbase.h>
+#include <kio/jobclasses.h>
+// Qt Includes
+#include <qthread.h>
+// Krusader Includes
+#include "../VFS/vfs.h"
+#include "krdetailedviewitem.h"
+class ListPanel;
+class KrView;
+
+
+/* Dialog calculating showing the number of files and directories and its total size
+ in a dialog. If wanted, the dialog appears after 3 seconds of calculation, to
+ avoid a short appearence if the result was found quickly. Computes teh result in
+ a different thread.
+ */
+class KrCalcSpaceDialog : public KDialogBase{
+ Q_OBJECT
+ /* Thread which does the actual calculation. Deletes itself, if no longer
+ needed. Creator must call finished(), if the thread is no longer needed.
+ */
+ class CalcThread : public QThread{
+ KIO::filesize_t m_totalSize, m_currentSize;
+ unsigned long m_totalFiles;
+ unsigned long m_totalDirs;
+ const QStringList m_items;
+ vfs * m_files;
+ KrView *m_view;
+ KrCalcSpaceDialog * m_parent;
+ QMutex m_synchronizeUsageAccess;
+ bool m_threadInUse; // true: caller needs the thread
+ bool m_stop;
+ void cleanUp(); // Deletes this, if possible
+ public:
+ KIO::filesize_t getTotalSize() const {return m_totalSize + m_currentSize;} // the result
+ unsigned long getTotalFiles() const {return m_totalFiles;} // the result
+ unsigned long getTotalDirs() const {return m_totalDirs;} // the result
+ const QStringList & getItems() const {return m_items;} // list of directories to calculate
+ CalcThread(KrCalcSpaceDialog * parent, ListPanel * panel, const QStringList & items);
+ void deleteInstance(); // thread is no longer needed.
+ void run(); // start calculation
+ void stop(); // stop it. Thread continues until vfs_calcSpace returns
+ } * m_thread;
+ friend class CalcThread;
+ class QTimer * m_pollTimer;
+ QLabel * m_label;
+ bool m_autoClose; // true: wait 3 sec. before showing the dialog. Close it, when done
+ bool m_canceled; // true: cancel was pressed
+ int m_timerCounter; // internal counter. The timer runs faster as the rehresh (see comment there)
+ void calculationFinished(); // called if the calulation is done
+ void showResult(); // show the current result in teh dialog
+ static void setDirSize(KrDetailedViewItem * viewItem, KIO::filesize_t size) {viewItem->setSize(size);}
+protected slots:
+ void timer(); // poll timer was fired
+ void slotCancel(); // cancel was pressed
+public:
+ // autoclose: wait 3 sec. before showing the dialog. Close it, when done
+ KrCalcSpaceDialog(QWidget *parent, ListPanel * panel, const QStringList & items, bool autoclose);
+ ~KrCalcSpaceDialog();
+ KIO::filesize_t getTotalSize() const {return m_thread->getTotalSize();} // the result
+ unsigned long getTotalFiles() const {return m_thread->getTotalFiles();} // the result
+ unsigned long getTotalDirs() const {return m_thread->getTotalDirs();} // the result
+ bool wasCanceled() const {return m_canceled;} // cancel was pressed; result is probably wrong
+public slots:
+ void exec(); // start calculation
+};
+/* End of patch by Heiner <h.eichmann@gmx.de> */
+
+#endif
diff --git a/krusader/Panel/krcolorcache.cpp b/krusader/Panel/krcolorcache.cpp
new file mode 100644
index 0000000..2c3351a
--- /dev/null
+++ b/krusader/Panel/krcolorcache.cpp
@@ -0,0 +1,761 @@
+/***************************************************************************
+ krcolorcache.cpp
+ -------------------
+copyright : (C) 2000-2002 by Shie Erlich & Rafi Yanai
+e-mail : krusader@users.sourceforge.net
+web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+Description
+***************************************************************************
+
+A
+
+db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+#include "krcolorcache.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include <kglobalsettings.h>
+#include <qfile.h>
+
+
+// Macro: set target = col, if col is valid
+#define SETCOLOR(target, col) { if (col.isValid()) target = col; }
+
+/*
+Static class, which lists all allowed keywords for a quick access. Just call a method to initialize it.
+*/
+class KrColorSettingNames
+{
+ static QMap<QString, bool> s_colorNames;
+ static QMap<QString, bool> s_numNames;
+ static QMap<QString, bool> s_boolNames;
+ static void initialize();
+public:
+ static QValueList<QString> getColorNames();
+ static bool isColorNameValid(const QString & settingName);
+ static QValueList<QString> getNumNames();
+ static bool isNumNameValid(const QString & settingName);
+ static QValueList<QString> getBoolNames();
+ static bool isBoolNameValid(const QString & settingName);
+} krColorSettingNames;
+
+QMap<QString, bool> KrColorSettingNames::s_colorNames;
+QMap<QString, bool> KrColorSettingNames::s_numNames;
+QMap<QString, bool> KrColorSettingNames::s_boolNames;
+
+void KrColorSettingNames::initialize()
+{
+ if (!s_colorNames.empty())
+ return;
+ s_colorNames["Foreground"] = true;
+ s_colorNames["Inactive Foreground"] = true;
+ s_colorNames["Directory Foreground"] = true;
+ s_colorNames["Inactive Directory Foreground"] = true;
+ s_colorNames["Executable Foreground"] = true;
+ s_colorNames["Inactive Executable Foreground"] = true;
+ s_colorNames["Symlink Foreground"] = true;
+ s_colorNames["Inactive Symlink Foreground"] = true;
+ s_colorNames["Invalid Symlink Foreground"] = true;
+ s_colorNames["Inactive Invalid Symlink Foreground"] = true;
+ s_colorNames["Marked Foreground"] = true;
+ s_colorNames["Inactive Marked Foreground"] = true;
+ s_colorNames["Marked Background"] = true;
+ s_colorNames["Inactive Marked Background"] = true;
+ s_colorNames["Current Foreground"] = true;
+ s_colorNames["Inactive Current Foreground"] = true;
+ s_colorNames["Current Background"] = true;
+ s_colorNames["Inactive Current Background"] = true;
+ s_colorNames["Marked Current Foreground"] = true;
+ s_colorNames["Inactive Marked Current Foreground"] = true;
+ s_colorNames["Alternate Background"] = true;
+ s_colorNames["Inactive Alternate Background"] = true;
+ s_colorNames["Background"] = true;
+ s_colorNames["Inactive Background"] = true;
+ s_colorNames["Alternate Marked Background"] = true;
+ s_colorNames["Inactive Alternate Marked Background"] = true;
+ s_colorNames["Dim Target Color"] = true;
+
+ s_numNames["Dim Factor"] = true;
+
+ s_boolNames["KDE Default"] = true;
+ s_boolNames["Enable Alternate Background"] = true;
+ s_boolNames["Show Current Item Always"] = true;
+ s_boolNames["Dim Inactive Colors"] = true;
+}
+
+QValueList<QString> KrColorSettingNames::getColorNames()
+{
+ initialize();
+ return s_colorNames.keys();
+}
+
+bool KrColorSettingNames::isColorNameValid(const QString & settingName)
+{
+ initialize();
+ return s_colorNames.contains(settingName);
+}
+
+QValueList<QString> KrColorSettingNames::getNumNames()
+{
+ initialize();
+ return s_numNames.keys();
+}
+
+bool KrColorSettingNames::isNumNameValid(const QString & settingName)
+{
+ initialize();
+ return s_numNames.contains(settingName);
+}
+
+QValueList<QString> KrColorSettingNames::getBoolNames()
+{
+ initialize();
+ return s_boolNames.keys();
+}
+
+bool KrColorSettingNames::isBoolNameValid(const QString & settingName)
+{
+ initialize();
+ return s_boolNames.contains(settingName);
+}
+
+
+
+/*
+KrColorSettings implementation. Contains all properties in QMaps. loadFromConfig initializes them from krConfig.
+*/
+class KrColorSettingsImpl
+{
+ friend class KrColorSettings;
+ QMap<QString, QString> m_colorTextValues;
+ QMap<QString, QColor> m_colorValues;
+ QMap<QString, int> m_numValues;
+ QMap<QString, bool> m_boolValues;
+ void loadFromConfig();
+};
+
+void KrColorSettingsImpl::loadFromConfig()
+{
+ krConfig->setGroup("Colors");
+ QValueList<QString> names = KrColorSettingNames::getColorNames();
+ for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it )
+ {
+ m_colorTextValues[*it] = krConfig->readEntry(*it, "");
+ m_colorValues[*it] = krConfig->readColorEntry(*it);
+ }
+ names = KrColorSettingNames::getNumNames();
+ for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it )
+ {
+ if (krConfig->readEntry(*it) != QString::null)
+ m_numValues[*it] = krConfig->readNumEntry(*it);
+ }
+ names = KrColorSettingNames::getBoolNames();
+ for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it )
+ {
+ if (krConfig->readEntry(*it) != QString::null)
+ m_boolValues[*it] = krConfig->readBoolEntry(*it);
+ }
+}
+
+
+
+KrColorSettings::KrColorSettings()
+{
+ m_impl = new KrColorSettingsImpl();
+ m_impl->loadFromConfig();
+}
+
+KrColorSettings::KrColorSettings(const KrColorSettings & src)
+{
+ m_impl = new KrColorSettingsImpl();
+ operator =(src);
+}
+
+KrColorSettings::~KrColorSettings()
+{
+ delete m_impl;
+}
+
+const KrColorSettings & KrColorSettings::operator= (const KrColorSettings & src)
+{
+ if (this == & src)
+ return * this;
+ QValueList<QString> names = KrColorSettingNames::getColorNames();
+ for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it )
+ {
+ m_impl->m_colorTextValues[*it] = src.m_impl->m_colorTextValues[*it];
+ m_impl->m_colorValues[*it] = src.m_impl->m_colorValues[*it];
+ }
+ for ( QMap<QString, int>::Iterator it = src.m_impl->m_numValues.begin(); it != src.m_impl->m_numValues.end(); ++it )
+ {
+ m_impl->m_numValues[it.key()] = it.data();
+ }
+ for ( QMap<QString, bool>::Iterator it = src.m_impl->m_boolValues.begin(); it != src.m_impl->m_boolValues.end(); ++it )
+ {
+ m_impl->m_boolValues[it.key()] = it.data();
+ }
+ return * this;
+}
+
+QValueList<QString> KrColorSettings::getColorNames()
+{
+ return KrColorSettingNames::getColorNames();
+}
+
+bool KrColorSettings::isColorNameValid(const QString & settingName)
+{
+ return KrColorSettingNames::isColorNameValid(settingName);
+}
+
+bool KrColorSettings::setColorValue(const QString & settingName, const QColor & color)
+{
+ if (!isColorNameValid(settingName))
+ {
+ krOut << "Invalid color setting name: " << settingName << endl;
+ return false;
+ }
+ m_impl->m_colorValues[settingName] = color;
+ return true;
+}
+
+QColor KrColorSettings::getColorValue(const QString & settingName) const
+{
+ if (!isColorNameValid(settingName))
+ {
+ krOut << "Invalid color setting name: " << settingName << endl;
+ return QColor();
+ }
+ return m_impl->m_colorValues[settingName];
+}
+
+bool KrColorSettings::setColorTextValue(const QString & settingName, const QString & colorText)
+{
+ if (!isColorNameValid(settingName))
+ {
+ krOut << "Invalid color setting name: " << settingName << endl;
+ return false;
+ }
+ m_impl->m_colorTextValues[settingName] = colorText;
+ return true;
+}
+
+QString KrColorSettings::getColorTextValue(const QString & settingName) const
+{
+ if (!isColorNameValid(settingName))
+ {
+ krOut << "Invalid color setting name: " << settingName << endl;
+ return QString();
+ }
+ return m_impl->m_colorTextValues[settingName];
+}
+
+QValueList<QString> KrColorSettings::getNumNames()
+{
+ return KrColorSettingNames::getNumNames();
+}
+
+bool KrColorSettings::isNumNameValid(const QString & settingName)
+{
+ return KrColorSettingNames::isNumNameValid(settingName);
+}
+
+bool KrColorSettings::setNumValue(const QString & settingName, int value)
+{
+ if (!isNumNameValid(settingName))
+ {
+ krOut << "Invalid number setting name: " << settingName << endl;
+ return false;
+ }
+ m_impl->m_numValues[settingName] = value;
+ return true;
+}
+
+int KrColorSettings::getNumValue(const QString & settingName, int defaultValue) const
+{
+ if (!isNumNameValid(settingName))
+ {
+ krOut << "Invalid number setting name: " << settingName << endl;
+ return 0;
+ }
+ if (!m_impl->m_numValues.contains(settingName))
+ return defaultValue;
+ return m_impl->m_numValues[settingName];
+}
+
+QValueList<QString> KrColorSettings::getBoolNames()
+{
+ return KrColorSettingNames::getBoolNames();
+}
+
+bool KrColorSettings::isBoolNameValid(const QString & settingName)
+{
+ return KrColorSettingNames::isBoolNameValid(settingName);
+}
+
+bool KrColorSettings::setBoolValue(const QString & settingName, bool value)
+{
+ if (!isBoolNameValid(settingName))
+ {
+ krOut << "Invalid bool setting name: " << settingName << endl;
+ return false;
+ }
+ m_impl->m_boolValues[settingName] = value;
+ return true;
+}
+
+int KrColorSettings::getBoolValue(const QString & settingName, bool defaultValue) const
+{
+ if (!isBoolNameValid(settingName))
+ {
+ krOut << "Invalid bool setting name: " << settingName << endl;
+ return false;
+ }
+ if (!m_impl->m_boolValues.contains(settingName))
+ return defaultValue;
+ return m_impl->m_boolValues[settingName];
+}
+
+
+
+KrColorItemType::KrColorItemType()
+{
+ m_fileType = File;
+ m_alternateBackgroundColor = false;
+ m_activePanel = false;
+ m_currentItem = false;
+ m_selectedItem = false;
+}
+
+KrColorItemType::KrColorItemType(FileType type, bool alternateBackgroundColor, bool activePanel, bool currentItem, bool selectedItem)
+{
+ m_fileType = type;
+ m_alternateBackgroundColor = alternateBackgroundColor;
+ m_activePanel = activePanel;
+ m_currentItem = currentItem;
+ m_selectedItem = selectedItem;
+}
+
+KrColorItemType::KrColorItemType(const KrColorItemType & src)
+{
+ operator= (src);
+}
+
+const KrColorItemType & KrColorItemType::operator= (const KrColorItemType & src)
+{
+ if (this == & src)
+ return * this;
+ m_fileType = src.m_fileType;
+ m_alternateBackgroundColor = src.m_alternateBackgroundColor;
+ m_activePanel = src.m_activePanel;
+ m_currentItem = src.m_currentItem;
+ m_selectedItem = src.m_selectedItem;
+ return * this;
+}
+
+
+
+
+/*
+KrColorCache implementation. Contains the KrColorSettings used for teh calculation and the cache for the results.
+getColors is the only method to call. All other are taken from the previous versions.
+*/
+class KrColorCacheImpl
+{
+ friend class KrColorCache;
+ QMap<QString, QColorGroup> m_cachedColors;
+ KrColorSettings m_colorSettings;
+ QColorGroup getColors(const KrColorItemType & type) const;
+ static const QColor & setColorIfContrastIsSufficient(const QColor & background, const QColor & color1, const QColor & color2);
+ QColor getForegroundColor(bool isActive) const;
+ QColor getSpecialForegroundColor(const QString & type, bool isActive) const;
+ QColor getBackgroundColor(bool isActive) const;
+ QColor getAlternateBackgroundColor(bool isActive) const;
+ QColor getMarkedForegroundColor(bool isActive) const;
+ QColor getMarkedBackgroundColor(bool isActive) const;
+ QColor getAlternateMarkedBackgroundColor(bool isActive) const;
+ QColor getCurrentForegroundColor(bool isActive) const;
+ QColor getCurrentBackgroundColor(bool isActive) const;
+ QColor getCurrentMarkedForegroundColor(bool isActive) const;
+ QColor dimColor(QColor color, bool isBackgroundColor) const;
+};
+
+QColorGroup KrColorCacheImpl::getColors(const KrColorItemType & type) const
+{
+ QColorGroup result;
+ if (m_colorSettings.getBoolValue("KDE Default", _KDEDefaultColors))
+ {
+ // KDE default? Getcolors from KGlobalSettings.
+ bool enableAlternateBackground = m_colorSettings.getBoolValue("Enable Alternate Background", _AlternateBackground);
+ QColor background = enableAlternateBackground && type.m_alternateBackgroundColor ?
+ KGlobalSettings::alternateBackgroundColor()
+ : KGlobalSettings::baseColor();
+ result.setColor(QColorGroup::Base, background);
+ result.setColor(QColorGroup::Background, background);
+ result.setColor(QColorGroup::Text, KGlobalSettings::textColor());
+ result.setColor(QColorGroup::HighlightedText, KGlobalSettings::highlightedTextColor());
+ result.setColor(QColorGroup::Highlight, KGlobalSettings::highlightColor());
+ return result;
+ }
+ bool markCurrentAlways = m_colorSettings.getBoolValue("Show Current Item Always", _ShowCurrentItemAlways);
+ bool dimBackground = m_colorSettings.getBoolValue("Dim Inactive Colors", false);
+
+ // cache m_activePanel flag. If color dimming is turned on, it is set to true, as the inactive colors
+ // are calculated from the active ones at the end.
+ bool isActive = type.m_activePanel;
+ if (dimBackground)
+ isActive = true;
+
+ // First calculate fore- and background.
+ QColor background = type.m_alternateBackgroundColor ?
+ getAlternateBackgroundColor(isActive)
+ : getBackgroundColor(isActive);
+ QColor foreground;
+ switch(type.m_fileType)
+ {
+ case KrColorItemType::Directory :
+ foreground = getSpecialForegroundColor("Directory", isActive);
+ break;
+ case KrColorItemType::Executable :
+ foreground = getSpecialForegroundColor("Executable", isActive);
+ break;
+ case KrColorItemType::InvalidSymlink :
+ foreground = getSpecialForegroundColor("Invalid Symlink", isActive);
+ break;
+ case KrColorItemType::Symlink :
+ foreground = getSpecialForegroundColor("Symlink", isActive);
+ break;
+ default:
+ foreground = getForegroundColor(isActive);
+ }
+
+ // set the background color
+ result.setColor(QColorGroup::Base, background);
+ result.setColor(QColorGroup::Background, background);
+
+ // set the foreground color
+ result.setColor(QColorGroup::Text, foreground);
+
+ // now the color of a marked item
+ QColor markedBackground = type.m_alternateBackgroundColor ?
+ getAlternateMarkedBackgroundColor(isActive)
+ : getMarkedBackgroundColor(isActive);
+ QColor markedForeground = getMarkedForegroundColor(isActive);
+ if (!markedForeground.isValid()) // transparent
+ // choose fore- or background, depending on its contrast compared to markedBackground
+ markedForeground = setColorIfContrastIsSufficient(markedBackground, foreground, background);
+
+ // set it in the color group (different group color than normal foreground!)
+ result.setColor(QColorGroup::HighlightedText, markedForeground);
+ result.setColor(QColorGroup::Highlight, markedBackground);
+
+ // In case the current item is a selected one, set the fore- and background colors for the contrast calculation below
+ if (type.m_selectedItem)
+ {
+ background = markedBackground;
+ foreground = markedForeground;
+ }
+
+ // finally the current item
+ if (type.m_currentItem && (markCurrentAlways || isActive))
+ {
+ // if this is the current item AND the panels has the focus OR the current should be marked always
+ QColor currentBackground = getCurrentBackgroundColor(isActive);
+
+ if (!currentBackground.isValid()) // transparent
+ currentBackground = background;
+
+ // set the background
+ result.setColor(QColorGroup::Highlight, currentBackground);
+ result.setColor(QColorGroup::Base, currentBackground);
+ result.setColor(QColorGroup::Background, currentBackground);
+
+ QColor color;
+ if (type.m_selectedItem)
+ color = getCurrentMarkedForegroundColor(isActive);
+ if (!color.isValid()) // not used
+ {
+ color = getCurrentForegroundColor(isActive);
+ if (!color.isValid()) // transparent
+ // choose fore- or background, depending on its contrast compared to markedBackground
+ color = setColorIfContrastIsSufficient(currentBackground, foreground, background);
+ }
+
+ // set the foreground
+ result.setColor(QColorGroup::Text, color);
+ result.setColor(QColorGroup::HighlightedText, color);
+ }
+
+ if (dimBackground && !type.m_activePanel)
+ {
+ // if color dimming is choosen, dim the colors for the inactive panel
+ result.setColor(QColorGroup::Base, dimColor(result.base(), true));
+ result.setColor(QColorGroup::Background, dimColor(result.base(), true));
+ result.setColor(QColorGroup::Text, dimColor(result.text(), false));
+ result.setColor(QColorGroup::HighlightedText, dimColor(result.highlightedText(), false));
+ result.setColor(QColorGroup::Highlight, dimColor(result.highlight(), true));
+ }
+ return result;
+}
+
+const QColor & KrColorCacheImpl::setColorIfContrastIsSufficient(const QColor & background, const QColor & color1, const QColor & color2)
+{
+ #define sqr(x) ((x)*(x))
+ int contrast = sqr(color1.red() - background.red()) + sqr(color1.green() - background.green()) + sqr(color1.blue() - background.blue());
+
+ // if the contrast between background and color1 is too small, take color2 instead.
+ if (contrast < 1000)
+ return color2;
+ return color1;
+}
+
+QColor KrColorCacheImpl::getForegroundColor(bool isActive) const
+{
+ QColor color = KGlobalSettings::textColor();
+ SETCOLOR(color, m_colorSettings.getColorValue("Foreground"));
+ if (!isActive) SETCOLOR(color, m_colorSettings.getColorValue("Inactive Foreground"));
+ return color;
+}
+
+QColor KrColorCacheImpl::getSpecialForegroundColor(const QString & type, bool isActive) const
+{
+ QString colorName = "Inactive " + type + " Foreground";
+ if (!isActive && m_colorSettings.getColorTextValue(colorName) == "Inactive Foreground")
+ return getForegroundColor(false);
+ QColor color = m_colorSettings.getColorValue(type + " Foreground");
+ if (!isActive) SETCOLOR(color, m_colorSettings.getColorValue(colorName));
+ if (!color.isValid())
+ return getForegroundColor(isActive);
+ return color;
+}
+
+QColor KrColorCacheImpl::getBackgroundColor(bool isActive) const
+{
+ QColor color = KGlobalSettings::baseColor();
+ SETCOLOR(color, m_colorSettings.getColorValue("Background"));
+ if (!isActive) SETCOLOR(color, m_colorSettings.getColorValue("Inactive Background"));
+ return color;
+}
+
+QColor KrColorCacheImpl::getAlternateBackgroundColor(bool isActive) const
+{
+ if (isActive && m_colorSettings.getColorTextValue("Alternate Background") == "Background")
+ return getBackgroundColor(true);
+ if (!isActive && m_colorSettings.getColorTextValue("Inactive Alternate Background") == "")
+ return getAlternateBackgroundColor(true);
+ if (!isActive && m_colorSettings.getColorTextValue("Inactive Alternate Background") == "Inactive Background")
+ return getBackgroundColor(false);
+ QColor color = isActive ?
+ m_colorSettings.getColorValue("Alternate Background")
+ : m_colorSettings.getColorValue("Inactive Alternate Background");
+ if (!color.isValid())
+ color = KGlobalSettings::alternateBackgroundColor();
+ if (!color.isValid())
+ color = KGlobalSettings::baseColor();
+ return color;
+}
+
+QColor KrColorCacheImpl::getMarkedForegroundColor(bool isActive) const
+{
+ QString colorName = isActive?"Marked Foreground":"Inactive Marked Foreground";
+ if (m_colorSettings.getColorTextValue(colorName) == "transparent")
+ return QColor();
+ if (isActive && m_colorSettings.getColorTextValue(colorName) == "")
+ return KGlobalSettings::highlightedTextColor();
+ if (!isActive && m_colorSettings.getColorTextValue(colorName) == "")
+ return getMarkedForegroundColor(true);
+ return m_colorSettings.getColorValue(colorName);
+}
+
+QColor KrColorCacheImpl::getMarkedBackgroundColor(bool isActive) const
+{
+ if (isActive && m_colorSettings.getColorTextValue("Marked Background") == "")
+ return KGlobalSettings::highlightColor();
+ if (isActive && m_colorSettings.getColorTextValue("Marked Background") == "Background")
+ return getBackgroundColor(true);
+ if (!isActive && m_colorSettings.getColorTextValue("Inactive Marked Background") == "")
+ return getMarkedBackgroundColor(true);
+ if (!isActive && m_colorSettings.getColorTextValue("Inactive Marked Background") == "Inactive Background")
+ return getBackgroundColor(false);
+ return isActive ?
+ m_colorSettings.getColorValue("Marked Background")
+ : m_colorSettings.getColorValue("Inactive Marked Background");
+}
+
+QColor KrColorCacheImpl::getAlternateMarkedBackgroundColor(bool isActive) const
+{
+ if (isActive && m_colorSettings.getColorTextValue("Alternate Marked Background") == "Alternate Background")
+ return getAlternateBackgroundColor(true);
+ if (isActive && m_colorSettings.getColorTextValue("Alternate Marked Background") == "")
+ return getMarkedBackgroundColor(true);
+ if (!isActive && m_colorSettings.getColorTextValue("Inactive Alternate Marked Background") == "")
+ return getAlternateMarkedBackgroundColor(true);
+ if (!isActive && m_colorSettings.getColorTextValue("Inactive Alternate Marked Background") == "Inactive Alternate Background")
+ return getAlternateBackgroundColor(false);
+ if (!isActive && m_colorSettings.getColorTextValue("Inactive Alternate Marked Background") == "Inactive Marked Background")
+ return getMarkedBackgroundColor(false);
+ return isActive ?
+ m_colorSettings.getColorValue("Alternate Marked Background")
+ : m_colorSettings.getColorValue("Inactive Alternate Marked Background");
+}
+
+QColor KrColorCacheImpl::getCurrentForegroundColor(bool isActive) const
+{
+ QColor color = m_colorSettings.getColorValue("Current Foreground");
+ if (!isActive) SETCOLOR(color, m_colorSettings.getColorValue("Inactive Current Foreground"));
+ return color;
+}
+
+QColor KrColorCacheImpl::getCurrentBackgroundColor(bool isActive) const
+{
+ if (isActive && m_colorSettings.getColorTextValue("Current Background") == "")
+ return QColor();
+ if (isActive && m_colorSettings.getColorTextValue("Current Background") == "Background")
+ return getBackgroundColor(true);
+ if (!isActive && m_colorSettings.getColorTextValue("Inactive Current Background") == "")
+ return getCurrentBackgroundColor(true);
+ if (!isActive && m_colorSettings.getColorTextValue("Inactive Current Background") == "Inactive Background")
+ return getBackgroundColor(false);
+ return isActive ?
+ m_colorSettings.getColorValue("Current Background")
+ : m_colorSettings.getColorValue("Inactive Current Background");
+}
+
+QColor KrColorCacheImpl::getCurrentMarkedForegroundColor(bool isActive) const
+{
+ QString colorName = isActive?"Marked Current Foreground":"Inactive Marked Current Foreground";
+ if (isActive && m_colorSettings.getColorTextValue(colorName) == "")
+ return QColor();
+ if (isActive && m_colorSettings.getColorTextValue(colorName) == "Marked Foreground")
+ return getMarkedForegroundColor(true);
+ if (!isActive && m_colorSettings.getColorTextValue(colorName) == "")
+ return getCurrentMarkedForegroundColor(true);
+ if (!isActive && m_colorSettings.getColorTextValue(colorName) == "Inactive Marked Foreground")
+ return getMarkedForegroundColor(false);
+ return m_colorSettings.getColorValue(colorName);
+}
+
+QColor KrColorCacheImpl::dimColor(QColor color, bool /* isBackgroundColor */) const
+{
+ krConfig->setGroup("Colors");
+ int dimFactor = m_colorSettings.getNumValue("Dim Factor", 100);
+ QColor targetColor = m_colorSettings.getColorValue("Dim Target Color");
+ if (!targetColor.isValid())
+ targetColor = QColor(255, 255, 255);
+ bool dimBackground = m_colorSettings.getBoolValue("Dim Inactive Colors", false);
+ bool dim = dimFactor >= 0 && dimFactor < 100 && dimBackground;
+ if (dim)
+ color = KrColorCache::dimColor(color, dimFactor, targetColor);
+ return color;
+}
+
+
+
+
+
+
+KrColorCache * KrColorCache::m_instance = 0;
+
+KrColorCache::KrColorCache()
+{
+ m_impl = new KrColorCacheImpl;
+}
+
+KrColorCache::~KrColorCache()
+{
+ delete m_impl;
+}
+
+KrColorCache & KrColorCache::getColorCache()
+{
+ if (!m_instance)
+ {
+ m_instance = new KrColorCache;
+ m_instance->refreshColors();
+ }
+ return * m_instance;
+}
+
+void KrColorCache::getColors(QColorGroup & result, const KrColorItemType & type) const
+{
+ // for the cache lookup: calculate a unique key from the type
+ char hashKey[128];
+ switch(type.m_fileType)
+ {
+ case KrColorItemType::Directory :
+ strcpy(hashKey, "Directory");
+ break;
+ case KrColorItemType::Executable :
+ strcpy(hashKey, "Executable");
+ break;
+ case KrColorItemType::InvalidSymlink :
+ strcpy(hashKey, "InvalidSymlink");
+ break;
+ case KrColorItemType::Symlink :
+ strcpy(hashKey, "Symlink");
+ break;
+ default:
+ strcpy(hashKey, "File");
+ }
+ if (type.m_activePanel)
+ strcat(hashKey, "-Active");
+ if (type.m_alternateBackgroundColor)
+ strcat(hashKey, "-Alternate");
+ if (type.m_currentItem)
+ strcat(hashKey, "-Current");
+ if (type.m_selectedItem)
+ strcat(hashKey, "-Selected");
+
+ // lookup in cache
+ if (!m_impl->m_cachedColors.contains(hashKey))
+ // not found: calculate color group and store it in cache
+ m_impl->m_cachedColors[hashKey] = m_impl->getColors(type);
+
+ // get color group from cache
+ const QColorGroup & col = m_impl->m_cachedColors[hashKey];
+
+ // copy colors in question to result color group
+ result.setColor(QColorGroup::Base, col.base());
+ result.setColor(QColorGroup::Background, col.base());
+ result.setColor(QColorGroup::Text, col.text());
+ result.setColor(QColorGroup::HighlightedText, col.highlightedText());
+ result.setColor(QColorGroup::Highlight, col.highlight());
+}
+
+QColor KrColorCache::dimColor(const QColor & color, int dim, const QColor & targetColor)
+{
+ return QColor((targetColor.red() * (100 - dim) + color.red() * dim) / 100,
+ (targetColor.green() * (100 - dim) + color.green() * dim) / 100,
+ (targetColor.blue() * (100 - dim) + color.blue() * dim) / 100);
+}
+
+void KrColorCache::refreshColors()
+{
+ m_impl->m_cachedColors.clear();
+ m_impl->m_colorSettings = KrColorSettings();
+ colorsRefreshed();
+}
+
+void KrColorCache::setColors(const KrColorSettings & colorSettings)
+{
+ m_impl->m_cachedColors.clear();
+ m_impl->m_colorSettings = colorSettings;
+ colorsRefreshed();
+}
+
+#include "krcolorcache.moc"
diff --git a/krusader/Panel/krcolorcache.h b/krusader/Panel/krcolorcache.h
new file mode 100644
index 0000000..a213319
--- /dev/null
+++ b/krusader/Panel/krcolorcache.h
@@ -0,0 +1,101 @@
+#ifndef KRCOLORCACHE_H
+#define KRCOLORCACHE_H
+
+#include <qobject.h>
+#include <qdict.h>
+
+/*
+Design goals: Color calculation is done on one place only. Configuration through krConfig OR through local settings.
+Calculation must be fast through cacheing.
+
+This implementation exposes 3 classes:
+
+KrColorSettings: holds the color settings from krConfig, which can be changed locally
+KrColorItemType: specifies the colors to be calculated
+KrColorCache: perfomes the color calculation and caches the result. Uses KrColorSettings for the calculation
+*/
+
+
+/*
+Copies all used color settings from krConfig into a local cache on creation. It contains 3 types of properties:
+color, numeric (int) and boolean. Color properties can have string or color values. Property values can be
+changed. These changes does not go into krConfig!
+
+is*Valid checks, if a protery name is valid
+get*Names returns a list of all allowed property names
+set*Value overwrites a property with a new value
+get*Value retunrs the current value
+
+For colors teh value can be returned as text or as color. If a text representation is not a valid color,
+setColorValue(QColor()) should be called.
+*/
+class KrColorSettings
+{
+ class KrColorSettingsImpl * m_impl;
+public:
+ KrColorSettings();
+ KrColorSettings(const KrColorSettings &);
+ ~KrColorSettings();
+ const KrColorSettings & operator= (const KrColorSettings &);
+
+ static bool isColorNameValid(const QString & settingName);
+ static QValueList<QString> getColorNames();
+ bool setColorValue(const QString & settingName, const QColor & color);
+ QColor getColorValue(const QString & settingName) const;
+ bool setColorTextValue(const QString & settingName, const QString & colorText);
+ QString getColorTextValue(const QString & settingName) const;
+
+ static bool isNumNameValid(const QString & settingName);
+ static QValueList<QString> getNumNames();
+ bool setNumValue(const QString & settingName, int value);
+ int getNumValue(const QString & settingName, int defaultValue = 0) const;
+
+ static bool isBoolNameValid(const QString & settingName);
+ static QValueList<QString> getBoolNames();
+ bool setBoolValue(const QString & settingName, bool value);
+ int getBoolValue(const QString & settingName, bool defaultValue = false) const;
+};
+
+/*
+A colletcion of properties which describe the color group to be calculated
+*/
+class KrColorItemType
+{
+public:
+ enum FileType {File, InvalidSymlink, Symlink, Directory, Executable};
+ FileType m_fileType;
+ bool m_alternateBackgroundColor, m_activePanel, m_currentItem, m_selectedItem;
+ KrColorItemType();
+ KrColorItemType(FileType type, bool alternateBackgroundColor, bool activePanel, bool currentItem, bool selectedItem);
+ KrColorItemType(const KrColorItemType &);
+ const KrColorItemType & operator= (const KrColorItemType &);
+};
+
+/*
+The color calculation. It bases on an internal KrColorSettings instance. Via setColors it can be changed.
+getColors does the color calculation. It sets the colors Base, Background, Text, HighlightedText and Highlight.
+All calculated values are cached. The cache is deleted on refreshColors and setColors, which also trigger
+colorsRefreshed. getColorCache returns a statis color cached for painting the panels. On the color cache
+setColors should NEVER be called!
+*/
+class KrColorCache : public QObject
+{
+ Q_OBJECT
+ static KrColorCache * m_instance;
+ class KrColorCacheImpl * m_impl;
+ KrColorCache(const KrColorCache &);
+ const KrColorCache & operator= (const KrColorCache &);
+public:
+ KrColorCache();
+ ~KrColorCache();
+ static KrColorCache & getColorCache();
+ void getColors(QColorGroup & result, const KrColorItemType & type) const;
+ static QColor dimColor(const QColor & color, int dim, const QColor & targetColor);
+public slots:
+ void refreshColors();
+ void setColors(const KrColorSettings &);
+signals:
+ void colorsRefreshed();
+};
+
+#endif
diff --git a/krusader/Panel/krdetailedview.cpp b/krusader/Panel/krdetailedview.cpp
new file mode 100644
index 0000000..633c2d7
--- /dev/null
+++ b/krusader/Panel/krdetailedview.cpp
@@ -0,0 +1,1587 @@
+/***************************************************************************
+ krdetailedview.cpp
+ -------------------
+copyright : (C) 2000-2002 by Shie Erlich & Rafi Yanai
+e-mail : krusader@users.sourceforge.net
+web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+Description
+***************************************************************************
+
+A
+
+db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+#include "krdetailedview.h"
+#include "krdetailedviewitem.h"
+#include "krcolorcache.h"
+#include "krselectionmode.h"
+#include "../krusader.h"
+#include "../kicons.h"
+#include "../defaults.h"
+#include "../krusaderview.h"
+#include "../krslots.h"
+#include "../VFS/krpermhandler.h"
+#include "../VFS/krarchandler.h"
+#include "../GUI/kcmdline.h"
+#include "../Dialogs/krspecialwidgets.h"
+#include "../panelmanager.h"
+#include <qlayout.h>
+#include <qdir.h>
+#include <qwhatsthis.h>
+#include <qheader.h>
+#include <qstyle.h>
+#include <kprogress.h>
+#include <kstatusbar.h>
+#include <kinputdialog.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kpopupmenu.h>
+#include <qdict.h>
+
+//////////////////////////////////////////////////////////////////////////
+// The following is KrDetailedView's settings in KConfig:
+// Group name: KrDetailedView
+//
+// Ext Column
+#define _ExtColumn true
+// Mime Column
+#define _MimeColumn false
+// Size Column
+#define _SizeColumn true
+// DateTime Column
+#define _DateTimeColumn true
+// Perm Column
+#define _PermColumn false
+// KrPerm Column
+#define _KrPermColumn true
+// Owner Column
+#define _OwnerColumn false
+// Group Column
+#define _GroupColumn false
+// Do Quicksearch
+#define _DoQuicksearch true
+//////////////////////////////////////////////////////////////////////////
+
+#define CANCEL_TWO_CLICK_RENAME {singleClicked = false;renameTimer.stop();}
+#define COLUMN(X) static_cast<KrDetailedViewProperties*>(_properties)->column[ KrDetailedViewProperties::X ]
+#define PROPS static_cast<KrDetailedViewProperties*>(_properties)
+#define VF getVfile()
+
+#define COLUMN_POPUP_IDS 91
+
+QString KrDetailedView::ColumnName[ KrDetailedViewProperties::MAX_COLUMNS ];
+
+KrDetailedView::KrDetailedView( QWidget *parent, bool &left, KConfig *cfg, const char *name ) :
+ KListView( parent, name ), KrView( cfg ), _currDragItem( 0L ), currentlyRenamedItem( 0 ),
+ pressedItem( 0 ) {
+ setWidget( this );
+ _nameInKConfig=QString( "KrDetailedView" ) + QString( ( left ? "Left" : "Right" ) ) ;
+ krConfig->setGroup("Private");
+ if (krConfig->readBoolEntry("Enable Input Method", true))
+ setInputMethodEnabled(true);
+}
+
+void KrDetailedView::setup() {
+ lastSwushPosition = 0;
+ if ( ColumnName[ 0 ].isEmpty() ) {
+ ColumnName[ 0 ] = i18n( "Name" );
+ ColumnName[ 1 ] = i18n( "Ext" );
+ ColumnName[ 2 ] = i18n( "Type" );
+ ColumnName[ 3 ] = i18n( "Size" );
+ ColumnName[ 4 ] = i18n( "Modified" );
+ ColumnName[ 5 ] = i18n( "Perms" );
+ ColumnName[ 6 ] = i18n( "rwx" );
+ ColumnName[ 7 ] = i18n( "Owner" );
+ ColumnName[ 8 ] = i18n( "Group" );
+ }
+
+ /////////////////////////////// listview ////////////////////////////////////
+ { // use the {} so that KConfigGroupSaver will work correctly!
+ KConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ setFont( _config->readFontEntry( "Filelist Font", _FilelistFont ) );
+ // decide on single click/double click selection
+ if ( _config->readBoolEntry( "Single Click Selects", _SingleClickSelects ) &&
+ KGlobalSettings::singleClick() ) {
+ connect( this, SIGNAL( executed( QListViewItem* ) ), this, SLOT( slotExecuted( QListViewItem* ) ) );
+ } else {
+ connect( this, SIGNAL( clicked( QListViewItem* ) ), this, SLOT( slotClicked( QListViewItem* ) ) );
+ connect( this, SIGNAL( doubleClicked( QListViewItem* ) ), this, SLOT( slotDoubleClicked( QListViewItem* ) ) );
+ }
+
+ // a change in the selection needs to update totals
+ connect( this, SIGNAL( onItem( QListViewItem* ) ), this, SLOT( slotItemDescription( QListViewItem* ) ) );
+ connect( this, SIGNAL( contextMenuRequested( QListViewItem*, const QPoint&, int ) ),
+ this, SLOT( handleContextMenu( QListViewItem*, const QPoint&, int ) ) );
+ connect( this, SIGNAL( rightButtonPressed(QListViewItem*, const QPoint&, int)),
+ this, SLOT(slotRightButtonPressed(QListViewItem*, const QPoint&, int)));
+ connect( this, SIGNAL( currentChanged( QListViewItem* ) ), this, SLOT( setNameToMakeCurrent( QListViewItem* ) ) );
+ connect( this, SIGNAL( currentChanged( QListViewItem* ) ), this, SLOT( transformCurrentChanged( QListViewItem* ) ) );
+ connect( this, SIGNAL( mouseButtonClicked ( int, QListViewItem *, const QPoint &, int ) ),
+ this, SLOT( slotMouseClicked ( int, QListViewItem *, const QPoint &, int ) ) );
+ connect( &KrColorCache::getColorCache(), SIGNAL( colorsRefreshed() ), this, SLOT( refreshColors() ) );
+ connect( header(), SIGNAL(clicked(int)), this, SLOT(sortOrderChanged(int )));
+ }
+
+ // add whatever columns are needed to the listview
+ krConfig->setGroup( nameInKConfig() );
+
+ newColumn( KrDetailedViewProperties::Name ); // we always have a name
+ setColumnWidthMode( COLUMN(Name), QListView::Manual );
+ if ( _config->readBoolEntry( "Ext Column", _ExtColumn ) ) {
+ newColumn( KrDetailedViewProperties::Extention );
+ setColumnWidthMode( COLUMN(Extention), QListView::Manual );
+ setColumnWidth( COLUMN(Extention), QFontMetrics( font() ).width( "tar.bz2" ) );
+ }
+ if ( _config->readBoolEntry( "Mime Column", _MimeColumn ) ) {
+ newColumn( KrDetailedViewProperties::Mime );
+ setColumnWidthMode( COLUMN(Mime), QListView::Manual );
+ setColumnWidth( COLUMN(Mime), QFontMetrics( font() ).width( 'X' ) * 6 );
+ }
+ if ( _config->readBoolEntry( "Size Column", _SizeColumn ) ) {
+ newColumn( KrDetailedViewProperties::Size );
+ setColumnWidthMode( COLUMN(Size), QListView::Manual );
+ setColumnWidth( COLUMN(Size), QFontMetrics( font() ).width( "9" ) * 10 );
+ setColumnAlignment( COLUMN(Size), Qt::AlignRight ); // right-align numbers
+ }
+ if ( _config->readBoolEntry( "DateTime Column", _DateTimeColumn ) ) {
+ newColumn( KrDetailedViewProperties::DateTime );
+ setColumnWidthMode( COLUMN(DateTime), QListView::Manual );
+ //setColumnWidth( column( DateTime ), QFontMetrics( font() ).width( "99/99/99 99:99" ) );
+ setColumnWidth( COLUMN(DateTime), QFontMetrics( font() ).width( KGlobal::locale() ->formatDateTime(
+ QDateTime ( QDate( 2099, 12, 29 ), QTime( 23, 59 ) ) ) ) + 3 );
+ }
+ if ( _config->readBoolEntry( "Perm Column", _PermColumn ) ) {
+ newColumn( KrDetailedViewProperties::Permissions );
+ setColumnWidthMode( COLUMN(Permissions), QListView::Manual );
+ setColumnWidth( COLUMN(Permissions), QFontMetrics( font() ).width( "drwxrwxrwx" ) );
+ }
+ if ( _config->readBoolEntry( "KrPerm Column", _KrPermColumn ) ) {
+ newColumn( KrDetailedViewProperties::KrPermissions );
+ setColumnWidthMode( COLUMN(KrPermissions), QListView::Manual );
+ setColumnWidth( COLUMN(KrPermissions), QFontMetrics( font() ).width( "RWX" ) );
+ }
+ if ( _config->readBoolEntry( "Owner Column", _OwnerColumn ) ) {
+ newColumn( KrDetailedViewProperties::Owner );
+ setColumnWidthMode( COLUMN(Owner), QListView::Manual );
+ setColumnWidth( COLUMN(Owner), QFontMetrics( font() ).width( 'X' ) * 6 );
+ }
+ if ( _config->readBoolEntry( "Group Column", _GroupColumn ) ) {
+ newColumn( KrDetailedViewProperties::Group );
+ setColumnWidthMode( COLUMN(Group), QListView::Manual );
+ setColumnWidth( COLUMN(Group), QFontMetrics( font() ).width( 'X' ) * 6 );
+ }
+
+ // determine basic settings for the listview
+ setAcceptDrops( true );
+ setDragEnabled( true );
+ setTooltipColumn( COLUMN(Name) );
+ setDropVisualizer(false);
+ setDropHighlighter(true);
+ setSelectionModeExt( KListView::FileManager );
+ setAllColumnsShowFocus( true );
+ setShowSortIndicator( true );
+ header() ->setStretchEnabled( true, COLUMN(Name) );
+
+ //---- don't enable these lines, as it causes an ugly bug with inplace renaming
+ //--> setItemsRenameable( true );
+ //--> setRenameable( column( Name ), true );
+ //-------------------------------------------------------------------------------
+
+ header()->installEventFilter( this );
+ renameLineEdit()->installEventFilter( this );
+
+ // allow in-place renaming
+ connect( renameLineEdit(), SIGNAL( done( QListViewItem *, int ) ),
+ this, SLOT( inplaceRenameFinished( QListViewItem*, int ) ) );
+ connect( &renameTimer, SIGNAL( timeout() ), this, SLOT( renameCurrentItem() ) );
+ connect( &contextMenuTimer, SIGNAL (timeout()), this, SLOT (showContextMenu()));
+
+ connect( header(), SIGNAL(clicked(int)), this, SLOT(slotSortOrderChanged(int )));
+
+ setFocusPolicy( StrongFocus );
+ restoreSettings();
+ refreshColors();
+
+ CANCEL_TWO_CLICK_RENAME;
+}
+
+KrDetailedView::~KrDetailedView() {
+ delete _properties; _properties = 0;
+ delete _operator; _operator = 0;
+}
+
+void KrDetailedView::newColumn( KrDetailedViewProperties::ColumnType type ) {
+ // get the next available column
+ int max = KrDetailedViewProperties::Unused;
+ for (int i=0; i<KrDetailedViewProperties::MAX_COLUMNS; ++i) {
+ if (PROPS->column[i]>=max)
+ max = PROPS->column[i]+1;
+ }
+ if ( max >= KrDetailedViewProperties::MAX_COLUMNS )
+ perror( "KrDetailedView::newColumn() - too many columns" );
+
+ PROPS->column[type] = max;
+ addColumn( ColumnName[type], -1 );
+}
+
+/**
+ * returns the number of column which holds values of type 'type'.
+ * if such values are not presented in the view, -1 is returned.
+ */
+int KrDetailedView::column( KrDetailedViewProperties::ColumnType type ) {
+ return PROPS->column[type];
+}
+
+// if vfile passes the filter, create an item, otherwise, drop it
+KrViewItem *KrDetailedView::preAddItem( vfile *vf ) {
+ QString size = KRpermHandler::parseSize( vf->vfile_getSize() );
+ QString name = vf->vfile_getName();
+ bool isDir = vf->vfile_isDir();
+ if ( !isDir || ( isDir && ( _properties->filter & KrViewProperties::ApplyToDirs ) ) ) {
+ switch ( _properties->filter ) {
+ case KrViewProperties::All :
+ break;
+ case KrViewProperties::Custom :
+ if ( !_properties->filterMask.match( vf ) ) return 0;
+ break;
+ case KrViewProperties::Dirs:
+ if ( !vf->vfile_isDir() ) return 0;
+ break;
+ case KrViewProperties::Files:
+ if ( vf->vfile_isDir() ) return 0;
+ break;
+ case KrViewProperties::ApplyToDirs :
+ break; // no-op, stop compiler complaints
+ }
+ }
+ // passed the filter ...
+ return new KrDetailedViewItem( this, lastItem(), vf );
+}
+
+bool KrDetailedView::preDelItem(KrViewItem *item) {
+ /* KDE HACK START - the renaming item is not disappeared after delete */
+ /* solution: we send an ESC key event to terminate the rename */
+ if( item ) {
+ QListViewItem * viewItem = dynamic_cast<QListViewItem*>( item );
+ if( viewItem == currentlyRenamedItem ) {
+ currentlyRenamedItem = 0;
+ QKeyEvent escEvent( QEvent::KeyPress, Key_Escape, 27, 0 );
+ QApplication::sendEvent( renameLineEdit(), &escEvent );
+ }
+ }
+ /* KDE HACK END */
+ return true;
+}
+
+void KrDetailedView::addItems( vfs *v, bool addUpDir ) {
+ QListViewItem * item = firstChild();
+ QListViewItem *currentItem = item;
+ QString size, name;
+
+ // add the up-dir arrow if needed
+ if ( addUpDir ) {
+ new KrDetailedViewItem( this, ( QListViewItem* ) 0L, ( vfile* ) 0L );
+ }
+
+ // text for updating the status bar
+ QString statusText = QString("%1/ ").arg( v->vfs_getOrigin().fileName() ) + i18n("Directory");
+
+ int cnt = 0;
+ int cl = columnSorted();
+ bool as = ascendingSort();
+ setSorting( -1 ); // disable sorting
+
+ for ( vfile * vf = v->vfs_getFirstFile(); vf != 0 ; vf = v->vfs_getNextFile() ) {
+ size = KRpermHandler::parseSize( vf->vfile_getSize() );
+ name = vf->vfile_getName();
+ bool isDir = vf->vfile_isDir();
+ if ( !isDir || ( isDir && ( _properties->filter & KrViewProperties::ApplyToDirs ) ) ) {
+ switch ( _properties->filter ) {
+ case KrViewProperties::All :
+ break;
+ case KrViewProperties::Custom :
+ if ( !_properties->filterMask.match( vf ) )
+ continue;
+ break;
+ case KrViewProperties::Dirs:
+ if ( !vf->vfile_isDir() )
+ continue;
+ break;
+ case KrViewProperties::Files:
+ if ( vf->vfile_isDir() )
+ continue;
+ break;
+
+ case KrViewProperties::ApplyToDirs :
+ break; // no-op, stop compiler complaints
+ }
+ }
+
+ KrDetailedViewItem *dvitem = new KrDetailedViewItem( this, item, vf );
+ _dict.insert( vf->vfile_getName(), dvitem );
+ if ( isDir )
+ ++_numDirs;
+ else
+ _countSize += dvitem->VF->vfile_getSize();
+ ++_count;
+ // if the item should be current - make it so
+ if ( dvitem->name() == nameToMakeCurrent() )
+ {
+ currentItem = static_cast<QListViewItem*>(dvitem);
+ statusText = dvitem->description();
+ }
+
+ cnt++;
+ }
+
+
+ // re-enable sorting
+ setSorting( cl, as );
+ sort();
+
+ if ( !currentItem )
+ currentItem = firstChild();
+ KListView::setCurrentItem( currentItem );
+ ensureItemVisible( currentItem );
+
+ op()->emitItemDescription( statusText );
+}
+
+QString KrDetailedView::getCurrentItem() const {
+ QListViewItem * it = currentItem();
+ if ( !it )
+ return QString::null;
+ else
+ return dynamic_cast<KrViewItem*>( it ) ->name();
+}
+
+void KrDetailedView::setCurrentItem( const QString& name ) {
+ KrDetailedViewItem * it = dynamic_cast<KrDetailedViewItem*>(_dict[ name ]);
+ if ( it )
+ KListView::setCurrentItem( it );
+}
+
+void KrDetailedView::clear() {
+ /* KDE HACK START - the renaming item is not disappeared after clear */
+ /* solution: we send an ESC key event to terminate the rename */
+ if( currentlyRenamedItem ) {
+ currentlyRenamedItem = 0;
+ QKeyEvent escEvent( QEvent::KeyPress, Key_Escape, 27, 0 );
+ QApplication::sendEvent( renameLineEdit(), &escEvent );
+ }
+ /* KDE HACK END */
+
+ op()->emitSelectionChanged(); /* to avoid rename crash at refresh */
+ KListView::clear();
+ KrView::clear();
+}
+
+void KrDetailedView::setSortMode( KrViewProperties::SortSpec mode ) {
+ KrView::setSortMode(mode); // the KrViewItems will check it by themselves
+ bool ascending = !( mode & KrViewProperties::Descending );
+ int cl = -1;
+ if ( mode & KrViewProperties::Name )
+ cl = COLUMN( Name );
+ else
+ if ( mode & KrViewProperties::Ext )
+ cl = COLUMN( Extention );
+ else
+ if ( mode & KrViewProperties::Size )
+ cl = COLUMN( Size );
+ else
+ if ( mode & KrViewProperties::Type )
+ cl = COLUMN( Mime );
+ else
+ if ( mode & KrViewProperties::Modified )
+ cl = COLUMN( DateTime );
+ else
+ if ( mode & KrViewProperties::Permissions )
+ cl = COLUMN( Permissions );
+ else
+ if ( mode & KrViewProperties::KrPermissions )
+ cl = COLUMN( KrPermissions );
+ else
+ if ( mode & KrViewProperties::Owner )
+ cl = COLUMN( Owner );
+ else
+ if ( mode & KrViewProperties::Group )
+ cl = COLUMN( Group );
+ setSorting( cl, ascending );
+ KListView::sort();
+}
+
+void KrDetailedView::slotClicked( QListViewItem *item ) {
+ if ( !item ) return ;
+
+ if ( !modifierPressed ) {
+ if ( singleClicked && !renameTimer.isActive() ) {
+ KConfig * config = KGlobal::config();
+ config->setGroup( "KDE" );
+ int doubleClickInterval = config->readNumEntry( "DoubleClickInterval", 400 );
+
+ int msecsFromLastClick = clickTime.msecsTo( QTime::currentTime() );
+
+ if ( msecsFromLastClick > doubleClickInterval && msecsFromLastClick < 5 * doubleClickInterval ) {
+ singleClicked = false;
+ renameTimer.start( doubleClickInterval, true );
+ return ;
+ }
+ }
+
+ CANCEL_TWO_CLICK_RENAME;
+ singleClicked = true;
+ clickTime = QTime::currentTime();
+ clickedItem = item;
+ }
+}
+
+void KrDetailedView::slotDoubleClicked( QListViewItem *item ) {
+ CANCEL_TWO_CLICK_RENAME;
+ if ( !item )
+ return ;
+ QString tmp = dynamic_cast<KrViewItem*>( item ) ->name();
+ op()->emitExecuted(tmp);
+}
+
+void KrDetailedView::prepareForActive() {
+ KrView::prepareForActive();
+ setFocus();
+ slotItemDescription( currentItem() );
+}
+
+void KrDetailedView::prepareForPassive() {
+ KrView::prepareForPassive();
+ CANCEL_TWO_CLICK_RENAME;
+ if ( renameLineEdit() ->isVisible() )
+ renameLineEdit() ->clearFocus();
+ KConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ if ( _config->readBoolEntry( "New Style Quicksearch", _NewStyleQuicksearch ) ) {
+ if ( MAIN_VIEW ) {
+ if ( ACTIVE_PANEL ) {
+ if ( ACTIVE_PANEL->quickSearch ) {
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ stopQuickSearch( 0 );
+ }
+ }
+ }
+ }
+ }
+}
+
+void KrDetailedView::slotItemDescription( QListViewItem * item ) {
+ KrViewItem * it = static_cast<KrDetailedViewItem*>( item );
+ if ( !it )
+ return ;
+ QString desc = it->description();
+ op()->emitItemDescription(desc);
+}
+
+void KrDetailedView::handleQuickSearchEvent( QKeyEvent * e ) {
+ switch ( e->key() ) {
+ case Key_Insert:
+ {
+ QKeyEvent ev = QKeyEvent( QKeyEvent::KeyPress, Key_Space, 0, 0 );
+ KListView::keyPressEvent( & ev );
+ ev = QKeyEvent( QKeyEvent::KeyPress, Key_Down, 0, 0 );
+ keyPressEvent( & ev );
+ break;
+ }
+ case Key_Home:
+ {
+ QListView::setCurrentItem( firstChild() );
+ QKeyEvent ev = QKeyEvent( QKeyEvent::KeyPress, Key_Down, 0, 0 );
+ keyPressEvent( & ev );
+ break;
+ }
+ case Key_End:
+ {
+ QListView::setCurrentItem( firstChild() );
+ QKeyEvent ev = QKeyEvent( QKeyEvent::KeyPress, Key_Up, 0, 0 );
+ keyPressEvent( & ev );
+ break;
+ }
+ }
+}
+
+
+void KrDetailedView::slotCurrentChanged( QListViewItem * item ) {
+ CANCEL_TWO_CLICK_RENAME;
+ if ( !item )
+ return ;
+ _nameToMakeCurrent = static_cast<KrDetailedViewItem*>( item ) ->name();
+}
+
+void KrDetailedView::contentsMousePressEvent( QMouseEvent * e ) {
+ bool callDefaultHandler = true, processEvent = true, selectionChanged = false;
+ pressedItem = 0;
+
+ QListViewItem * oldCurrent = currentItem();
+ QListViewItem *newCurrent = itemAt( contentsToViewport( e->pos() ) );
+ if (e->button() == RightButton)
+ {
+ if (KrSelectionMode::getSelectionHandler()->rightButtonSelects() ||
+ (((e->state() & ShiftButton) || (e->state() & ControlButton))) && KrSelectionMode::getSelectionHandler()->shiftCtrlRightButtonSelects())
+ {
+ if (KrSelectionMode::getSelectionHandler()->rightButtonPreservesSelection() && !(e->state() & ShiftButton)
+ && !(e->state() & ControlButton) && !(e->state() & AltButton))
+ {
+ if (newCurrent)
+ {
+ if (KrSelectionMode::getSelectionHandler()->showContextMenu() >= 0)
+ {
+ swushSelects = !newCurrent->isSelected();
+ lastSwushPosition = newCurrent;
+ }
+ newCurrent->setSelected(!newCurrent->isSelected());
+ newCurrent->repaint();
+ selectionChanged = true;
+ }
+ callDefaultHandler = false;
+ processEvent = false;
+ e->accept();
+ }
+
+ if( !KrSelectionMode::getSelectionHandler()->rightButtonPreservesSelection() && KrSelectionMode::getSelectionHandler()->showContextMenu() >= 0)
+ {
+ if( (e->state() & ControlButton) && !(e->state() & AltButton) )
+ {
+ if( newCurrent )
+ {
+ newCurrent->setSelected(!newCurrent->isSelected());
+ newCurrent->repaint();
+ selectionChanged = true;
+ callDefaultHandler = false;
+ e->accept();
+ }
+ }
+ else if( !(e->state() & ControlButton) && !(e->state() & AltButton) )
+ {
+ clearSelection();
+ if( newCurrent )
+ {
+ newCurrent->setSelected( true );
+ newCurrent->repaint();
+ }
+ selectionChanged = true;
+ callDefaultHandler = false;
+ e->accept();
+ }
+ }
+ }
+ else
+ {
+ callDefaultHandler = false;
+ processEvent = false;
+ e->accept();
+ }
+ }
+ if (e->button() == LeftButton)
+ {
+ dragStartPos = e->pos();
+ if (KrSelectionMode::getSelectionHandler()->leftButtonSelects() ||
+ (((e->state() & ShiftButton) || (e->state() & ControlButton))) &&
+ KrSelectionMode::getSelectionHandler()->shiftCtrlLeftButtonSelects())
+ {
+ if (KrSelectionMode::getSelectionHandler()->leftButtonPreservesSelection() && !(e->state() & ShiftButton)
+ && !(e->state() & ControlButton) && !(e->state() & AltButton))
+ {
+ if (newCurrent)
+ {
+ newCurrent->setSelected(!newCurrent->isSelected());
+ newCurrent->repaint();
+ selectionChanged = true;
+ }
+ callDefaultHandler = false;
+ processEvent = false;
+ e->accept();
+ }
+ }
+ else
+ {
+ callDefaultHandler = false;
+ processEvent = false;
+ e->accept();
+ }
+ }
+
+ modifierPressed = false;
+ if ( (e->state() & ShiftButton) || (e->state() & ControlButton) || (e->state() & AltButton) ) {
+ CANCEL_TWO_CLICK_RENAME;
+ modifierPressed = true;
+ }
+
+ // stop quick search in case a mouse click occured
+ KConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ if ( _config->readBoolEntry( "New Style Quicksearch", _NewStyleQuicksearch ) ) {
+ if ( MAIN_VIEW ) {
+ if ( ACTIVE_PANEL ) {
+ if ( ACTIVE_PANEL->quickSearch ) {
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ stopQuickSearch( 0 );
+ }
+ }
+ }
+ }
+ }
+
+ if ( !_focused )
+ op()->emitNeedFocus();
+ if (processEvent && ( (e->state() & ShiftButton) || (e->state() & ControlButton) || (e->state() & AltButton) ) && !KrSelectionMode::getSelectionHandler()->useQTSelection()){
+ if ( oldCurrent && newCurrent && oldCurrent != newCurrent && e->state() & ShiftButton ) {
+ int oldPos = oldCurrent->itemPos();
+ int newPos = newCurrent->itemPos();
+ QListViewItem *top = 0, *bottom = 0;
+ if ( oldPos > newPos ) {
+ top = newCurrent;
+ bottom = oldCurrent;
+ } else {
+ top = oldCurrent;
+ bottom = newCurrent;
+ }
+ QListViewItemIterator it( top );
+ for ( ; it.current(); ++it ) {
+ if ( !it.current() ->isSelected() ) {
+ it.current() ->setSelected( true );
+ selectionChanged = true;
+ }
+ if ( it.current() == bottom )
+ break;
+ }
+ QListView::setCurrentItem( newCurrent );
+ callDefaultHandler = false;
+ }
+ }
+
+ if (selectionChanged)
+ updateView(); // don't call triggerUpdate directly!
+
+ // QListViewItem * i = itemAt( contentsToViewport( e->pos() ) );
+ if (callDefaultHandler)
+ {
+ dragStartPos = QPoint( -1, -1 );
+
+ QString name = QString::null; // will the file be deleted by the mouse event?
+ if( newCurrent ) // save the name of the file
+ name = static_cast<KrDetailedViewItem*>( newCurrent ) ->name();
+
+ KListView::contentsMousePressEvent( e );
+
+ if( name.isEmpty() || _dict.find( name ) == 0 ) // is the file still valid?
+ newCurrent = 0; // if not, don't do any crash...
+ } else {
+ // emitting the missing signals from QListView::contentsMousePressEvent();
+ // the right click signal is not emitted as it is used for selection
+
+ QPoint vp = contentsToViewport( e->pos() );
+
+ if( !newCurrent || ( newCurrent && newCurrent->isEnabled() ) ) {
+ emit pressed( pressedItem = newCurrent );
+ emit pressed( newCurrent, viewport()->mapToGlobal( vp ), 0 );
+ }
+
+ emit mouseButtonPressed( e->button(), newCurrent, viewport()->mapToGlobal( vp ), 0 );
+ }
+
+ // if (i != 0) // comment in, if click sould NOT select
+ // setSelected(i, FALSE);
+ if (newCurrent) QListView::setCurrentItem(newCurrent);
+
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ ACTIVE_PANEL->quickSearch->hide();
+ ACTIVE_PANEL->quickSearch->clear();
+ krDirUp->setEnabled( true );
+ }
+ if ( OTHER_PANEL->quickSearch->isShown() ) {
+ OTHER_PANEL->quickSearch->hide();
+ OTHER_PANEL->quickSearch->clear();
+ krDirUp->setEnabled( true );
+ }
+}
+
+void KrDetailedView::contentsMouseReleaseEvent( QMouseEvent * e ) {
+ if (e->button() == RightButton)
+ contextMenuTimer.stop();
+ KListView::contentsMouseReleaseEvent( e );
+
+ if( pressedItem ) {
+ QPoint vp = contentsToViewport( e->pos() );
+ QListViewItem *newCurrent = itemAt( vp );
+
+ if( pressedItem == newCurrent ) {
+ // emitting the missing signals from QListView::contentsMouseReleaseEvent();
+ // the right click signal is not emitted as it is used for selection
+
+ if( !newCurrent || ( newCurrent && newCurrent->isEnabled() ) ) {
+ emit clicked( newCurrent );
+ emit clicked( newCurrent, viewport()->mapToGlobal( vp ), 0 );
+ }
+
+ emit mouseButtonClicked( e->button(), newCurrent, viewport()->mapToGlobal( vp ), 0 );
+ }
+
+ pressedItem = 0;
+ }
+}
+
+void KrDetailedView::contentsMouseMoveEvent ( QMouseEvent * e ) {
+ if ( ( singleClicked || renameTimer.isActive() ) && itemAt( contentsToViewport( e->pos() ) ) != clickedItem )
+ CANCEL_TWO_CLICK_RENAME;
+ if ( dragStartPos != QPoint( -1, -1 ) &&
+ e->state() & LeftButton && ( dragStartPos - e->pos() ).manhattanLength() > QApplication::startDragDistance() )
+ startDrag();
+ if (KrSelectionMode::getSelectionHandler()->rightButtonPreservesSelection()
+ && KrSelectionMode::getSelectionHandler()->rightButtonSelects()
+ && KrSelectionMode::getSelectionHandler()->showContextMenu() >= 0 && e->state() == Qt::RightButton)
+ {
+ QListViewItem *newItem = itemAt( contentsToViewport( e->pos() ) );
+ e->accept();
+ if (newItem != lastSwushPosition && newItem)
+ {
+ // is the new item above or below the previous one?
+ QListViewItem * above = newItem;
+ QListViewItem * below = newItem;
+ for (;(above || below) && above != lastSwushPosition && below != lastSwushPosition;)
+ {
+ if (above)
+ above = above->itemAbove();
+ if (below)
+ below = below->itemBelow();
+ }
+ if (above && (above == lastSwushPosition))
+ {
+ for (; above != newItem; above = above->itemBelow())
+ above->setSelected(swushSelects);
+ newItem->setSelected(swushSelects);
+ lastSwushPosition = newItem;
+ updateView();
+ }
+ else if (below && (below == lastSwushPosition))
+ {
+ for (; below != newItem; below = below->itemAbove())
+ below->setSelected(swushSelects);
+ newItem->setSelected(swushSelects);
+ lastSwushPosition = newItem;
+ updateView();
+ }
+ contextMenuTimer.stop();
+ }
+ // emitting the missing signals from QListView::contentsMouseMoveEvent();
+ if( newItem )
+ emit onItem( newItem );
+ else
+ emit onViewport();
+ }
+ else
+ KListView::contentsMouseMoveEvent( e );
+}
+
+void KrDetailedView::contentsWheelEvent( QWheelEvent * e ) {
+ if ( !_focused )
+ op()->emitNeedFocus();
+ KListView::contentsWheelEvent( e );
+}
+
+void KrDetailedView::handleContextMenu( QListViewItem * it, const QPoint & pos, int ) {
+ if ( !_focused )
+ op()->emitNeedFocus();
+ if ( !it )
+ return ;
+ if ( static_cast<KrDetailedViewItem*>( it ) ->
+ name() == ".." )
+ return ;
+ int i = KrSelectionMode::getSelectionHandler()->showContextMenu();
+ contextMenuPoint = QPoint( pos.x(), pos.y() - header() ->height() );
+ if (i < 0)
+ showContextMenu();
+ else if (i > 0)
+ contextMenuTimer.start(i, true);
+}
+
+void KrDetailedView::showContextMenu()
+{
+ if (lastSwushPosition)
+ lastSwushPosition->setSelected(true);
+ op()->emitContextMenu( contextMenuPoint );
+}
+
+KrViewItem *KrDetailedView::getKrViewItemAt( const QPoint & vp ) {
+ return dynamic_cast<KrViewItem*>( KListView::itemAt( vp ) );
+}
+
+bool KrDetailedView::acceptDrag( QDropEvent* ) const {
+ return true;
+}
+
+QRect KrDetailedView::drawItemHighlighter(QPainter *painter, QListViewItem *item)
+{
+ QRect r;
+ if( _currDragItem && item ) {
+ r = itemRect(item);
+
+ if (painter)
+ style().drawPrimitive(QStyle::PE_FocusRect, painter, r, colorGroup(),
+ QStyle::Style_FocusAtBorder, colorGroup().highlight());
+ }
+ return r;
+}
+
+void KrDetailedView::contentsDropEvent( QDropEvent * e ) {
+ e->setPoint( contentsToViewport( e->pos() ) );
+ op()->emitGotDrop(e);
+ e->ignore();
+ KListView::contentsDropEvent( e );
+}
+
+void KrDetailedView::contentsDragMoveEvent( QDragMoveEvent * e ) {
+ _currDragItem = getKrViewItemAt(contentsToViewport(e->pos()));
+ if( _currDragItem && !_currDragItem->VF->vfile_isDir() )
+ _currDragItem = 0;
+
+ KListView::contentsDragMoveEvent( e );
+}
+
+void KrDetailedView::imStartEvent(QIMEvent* e)
+{
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ ACTIVE_PANEL->quickSearch->myIMStartEvent( e );
+ return ;
+ }else {
+ KConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ if ( !_config->readBoolEntry( "New Style Quicksearch", _NewStyleQuicksearch ) )
+ KListView::imStartEvent( e );
+ else {
+ // first, show the quicksearch if its hidden
+ if ( ACTIVE_PANEL->quickSearch->isHidden() ) {
+ ACTIVE_PANEL->quickSearch->show();
+ // hack: if the pressed key requires a scroll down, the selected
+ // item is "below" the quick search window, as the list view will
+ // realize its new size after the key processing. The following line
+ // will resize the list view immediately.
+ ACTIVE_PANEL->layout->activate();
+ // second, we need to disable the dirup action - hack!
+ krDirUp->setEnabled( false );
+ }
+ // now, send the key to the quicksearch
+ ACTIVE_PANEL->quickSearch->myIMStartEvent( e );
+ }
+ }
+}
+
+void KrDetailedView::imEndEvent(QIMEvent* e)
+{
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ ACTIVE_PANEL->quickSearch->myIMEndEvent( e );
+ return ;
+ }
+}
+
+void KrDetailedView::imComposeEvent(QIMEvent* e)
+{
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ ACTIVE_PANEL->quickSearch->myIMComposeEvent( e );
+ return ;
+ }
+}
+
+// TODO: for brief mode, move as much of this as possible to the viewOperator
+void KrDetailedView::keyPressEvent( QKeyEvent * e ) {
+ if ( !e || !firstChild() )
+ return ; // subclass bug
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ ACTIVE_PANEL->quickSearch->myKeyPressEvent( e );
+ return ;
+ }
+ switch ( e->key() ) {
+ case Key_Up :
+ if ( e->state() == ControlButton ) { // let the panel handle it - jump to the Location Bar
+ e->ignore();
+ break;
+ } else if (!KrSelectionMode::getSelectionHandler()->useQTSelection()) {
+ QListViewItem * i = currentItem();
+ if ( !i ) break;
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected() );
+ i = i->itemAbove();
+ if ( i ) {
+ QListView::setCurrentItem( i );
+ QListView::ensureItemVisible( i );
+ }
+ } else KListView::keyPressEvent(e);
+ break;
+ case Key_Down :
+ if ( e->state() == ControlButton || e->state() == ( ControlButton | ShiftButton ) ) { // let the panel handle it - jump to command line
+ e->ignore();
+ break;
+ } else if (!KrSelectionMode::getSelectionHandler()->useQTSelection()){
+ QListViewItem * i = currentItem();
+ if ( !i ) break;
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected() );
+ i = i->itemBelow();
+ if ( i ) {QListView::setCurrentItem( i ); QListView::ensureItemVisible( i ); }
+ } else KListView::keyPressEvent(e);
+ break;
+ case Key_Next: if (!KrSelectionMode::getSelectionHandler()->useQTSelection()){
+ QListViewItem * i = currentItem(), *j;
+ if ( !i ) break;
+ QRect r( itemRect( i ) );
+ if ( !r.height() ) break;
+ for ( int page = visibleHeight() / r.height() - 1; page > 0 && ( j = i->itemBelow() ); --page )
+ i = j;
+ if ( i ) {QListView::setCurrentItem( i ); QListView::ensureItemVisible( i ); }
+ } else KListView::keyPressEvent(e);
+ break;
+ case Key_Prior: if (!KrSelectionMode::getSelectionHandler()->useQTSelection()){
+ QListViewItem * i = currentItem(), *j;
+ if ( !i ) break;
+ QRect r( itemRect( i ) );
+ if ( !r.height() ) break;
+ for ( int page = visibleHeight() / r.height() - 1; page > 0 && ( j = i->itemAbove() ); --page )
+ i = j;
+ if ( i ) {QListView::setCurrentItem( i ); QListView::ensureItemVisible( i ); }
+ } else KListView::keyPressEvent(e);
+ break;
+ case Key_Home: if (!KrSelectionMode::getSelectionHandler()->useQTSelection()){
+ if ( e->state() & ShiftButton ) /* Shift+Home */
+ {
+ clearSelection();
+ KListView::keyPressEvent( e );
+ op()->emitSelectionChanged();
+ triggerUpdate();
+ break;
+ } else {
+ QListViewItem * i = firstChild();
+ if ( i ) {QListView::setCurrentItem( i ); QListView::ensureItemVisible( i ); }
+ }
+ } else KListView::keyPressEvent(e);
+ break;
+ case Key_End: if (!KrSelectionMode::getSelectionHandler()->useQTSelection()){
+ if ( e->state() & ShiftButton ) /* Shift+End */
+ {
+ clearSelection();
+ KListView::keyPressEvent( e );
+ op()->emitSelectionChanged();
+ triggerUpdate();
+ break;
+ } else {
+ QListViewItem *i = firstChild(), *j;
+ while ( ( j = i->nextSibling() ) )
+ i = j;
+ while ( ( j = i->itemBelow() ) )
+ i = j;
+ if ( i ) {QListView::setCurrentItem( i ); QListView::ensureItemVisible( i ); }
+ break;
+ }
+ } else KListView::keyPressEvent(e);
+ break;
+ case Key_Enter :
+ case Key_Return : {
+ if ( e->state() & ControlButton ) // let the panel handle it
+ e->ignore();
+ else {
+ KrViewItem * i = getCurrentKrViewItem();
+ QString tmp = i->name();
+ op()->emitExecuted(tmp);
+ }
+ break;
+ }
+ case Key_QuoteLeft : // Terminal Emulator bugfix
+ if ( e->state() == ControlButton ) { // let the panel handle it
+ e->ignore();
+ break;
+ } else { // a normal click - do a lynx-like moving thing
+ SLOTS->home(); // ask krusader to move up a directory
+ return ; // safety
+ }
+ break;
+ case Key_Right :
+ if ( e->state() == ControlButton || e->state() == ShiftButton ) { // let the panel handle it
+ e->ignore();
+ break;
+ } else { // just a normal click - do a lynx-like moving thing
+ KrViewItem *i = getCurrentKrViewItem();
+ if ( i->name() == ".." ) { // if clicking on the ".." entry
+ SLOTS->dirUp(); // ask krusader to move up a directory
+ return ;
+ }
+ if ( i->VF->vfile_isDir() ) { // we create a return-pressed event,
+ QString tmp = i->name();
+ op()->emitExecuted(tmp); // thereby emulating a chdir
+ } else if( i->VF->vfile_getUrl().isLocalFile() ) {
+ bool encrypted;
+ KURL url = i->VF->vfile_getUrl();
+ QString mime = ((vfile *)(i->VF))->vfile_getMime();
+ QString type = KRarcHandler::getType( encrypted, url.path(), mime, false );
+
+ if( KRarcHandler::arcSupported( type ) ) {
+ KURL url = i->VF->vfile_getUrl();
+ if( type == "-tar" || type == "-tgz" || type == "-tbz" )
+ url.setProtocol( "tar" );
+ else
+ url.setProtocol( "krarc" );
+ ACTIVE_FUNC->openUrl( url );
+ }
+ }
+ return ; // safety
+ }
+ case Key_Backspace : // Terminal Emulator bugfix
+ case Key_Left :
+ if ( e->state() == ControlButton || e->state() == ShiftButton ) { // let the panel handle it
+ e->ignore();
+ break;
+ } else { // a normal click - do a lynx-like moving thing
+ SLOTS->dirUp(); // ask krusader to move up a directory
+ return ; // safety
+ }
+ //case Key_Up :
+ //KListView::keyPressEvent( e );
+ //break;
+/*#ifndef _newSelectionHandling
+ case Key_Down :
+ if ( e->state() == ControlButton ) { // let the panel handle it
+ e->ignore();
+ break;
+ } else
+ KListView::keyPressEvent( e );
+ break;
+#endif*/
+ case Key_Delete : // kill file
+ SLOTS->deleteFiles( e->state() == ShiftButton || e->state() == ControlButton );
+
+ break ;
+ case Key_Insert : {
+ if (KrSelectionMode::getSelectionHandler()->insertMovesDown())
+ KListView::keyPressEvent( e );
+ else
+ {
+ QKeyEvent ev = QKeyEvent( QKeyEvent::KeyPress, Key_Space, 0, 0 );
+ KListView::keyPressEvent( & ev );
+ }
+ break ;
+ }
+ case Key_Space : {
+ KrDetailedViewItem * viewItem = static_cast<KrDetailedViewItem *> ( getCurrentKrViewItem() );
+ if ( !viewItem || viewItem->name() == ".." ) { // wrong type, just mark(unmark it)
+ if (KrSelectionMode::getSelectionHandler()->spaceMovesDown())
+ {
+ QKeyEvent ev = QKeyEvent( QKeyEvent::KeyPress, Key_Insert, 0, 0 );
+ KListView::keyPressEvent( & ev );
+ }
+ else
+ KListView::keyPressEvent( e );
+ break ;
+ }
+ if ( viewItem->VF->vfile_isDir() && viewItem->VF->vfile_getSize() <= 0 &&
+ KrSelectionMode::getSelectionHandler()->spaceCalculatesDiskSpace()) {
+ //
+ // NOTE: this is buggy incase somewhere down in the folder we're calculating,
+ // there's a folder we can't enter (permissions). in that case, the returned
+ // size will not be correct.
+ //
+ KIO::filesize_t totalSize = 0;
+ unsigned long totalFiles = 0, totalDirs = 0;
+ QStringList items;
+ items.push_back( viewItem->name() );
+ if ( ACTIVE_PANEL->func->calcSpace( items, totalSize, totalFiles, totalDirs ) ) {
+ // did we succeed to calcSpace? we'll fail if we don't have permissions
+ if ( totalSize == 0 ) { // just mark it, and bail out
+ goto mark;
+ }
+ viewItem->setSize( totalSize );
+ viewItem->repaintItem();
+ }
+ }
+mark: if (KrSelectionMode::getSelectionHandler()->spaceMovesDown())
+ {
+ QKeyEvent ev = QKeyEvent( QKeyEvent::KeyPress, Key_Insert, 0, 0 );
+ KListView::keyPressEvent( & ev );
+ }
+ else
+ KListView::keyPressEvent( e );
+ }
+ break;
+ case Key_A : // mark all
+ if ( e->state() == ControlButton ) {
+ KListView::keyPressEvent( e );
+ updateView();
+ break;
+ }
+ default:
+ if ( e->key() == Key_Escape ) {
+ QListView::keyPressEvent( e ); return ; // otherwise the selection gets lost??!??
+ }
+ // if the key is A..Z or 1..0 do quick search otherwise...
+ if ( e->text().length() > 0 && e->text() [ 0 ].isPrint() ) // better choice. Otherwise non-ascii characters like can not be the first character of a filename
+ /* if ( ( e->key() >= Key_A && e->key() <= Key_Z ) ||
+ ( e->key() >= Key_0 && e->key() <= Key_9 ) ||
+ ( e->key() == Key_Backspace ) ||
+ ( e->key() == Key_Down ) ||
+ ( e->key() == Key_Period ) ) */{
+ // are we doing quicksearch? if not, send keys to panel
+ //if ( _config->readBoolEntry( "Do Quicksearch", _DoQuicksearch ) ) {
+ // are we using krusader's classic quicksearch, or wincmd style?
+ {
+ KConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ if ( !_config->readBoolEntry( "New Style Quicksearch", _NewStyleQuicksearch ) )
+ KListView::keyPressEvent( e );
+ else {
+ // first, show the quicksearch if its hidden
+ if ( ACTIVE_PANEL->quickSearch->isHidden() ) {
+ ACTIVE_PANEL->quickSearch->show();
+ // hack: if the pressed key requires a scroll down, the selected
+ // item is "below" the quick search window, as the list view will
+ // realize its new size after the key processing. The following line
+ // will resize the list view immediately.
+ ACTIVE_PANEL->layout->activate();
+ // second, we need to disable the dirup action - hack!
+ krDirUp->setEnabled( false );
+ }
+ // now, send the key to the quicksearch
+ ACTIVE_PANEL->quickSearch->myKeyPressEvent( e );
+ }
+ }
+ //} else
+ // e->ignore(); // send to panel
+ } else {
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ ACTIVE_PANEL->quickSearch->hide();
+ ACTIVE_PANEL->quickSearch->clear();
+ krDirUp->setEnabled( true );
+ }
+ KListView::keyPressEvent( e );
+ }
+ }
+ // emit the new item description
+ slotItemDescription( currentItem() ); // actually send the QListViewItem
+}
+
+// overridden to make sure EXTENTION won't be lost during rename
+void KrDetailedView::rename( QListViewItem * item, int c ) {
+ // do we have an EXT column? if so, handle differently:
+ // copy the contents of the EXT column over to the name
+ if ( COLUMN( Extention ) != -1 ) {
+ item->setText( COLUMN( Name ), static_cast<KrDetailedViewItem*>( item ) ->name() );
+ item->setText( COLUMN( Extention ), QString::null );
+ repaintItem( item );
+ }
+
+ currentlyRenamedItem = item;
+ renameLineEdit()->setBackgroundMode(Qt::FixedColor);
+ renameLineEdit()->setPaletteBackgroundColor(Qt::white);
+ renameLineEdit()->setPaletteForegroundColor(Qt::black);
+ KListView::rename( item, c );
+ renameLineEdit() ->selectAll();
+}
+
+void KrDetailedView::renameCurrentItem() {
+ int c;
+ QString newName, fileName;
+
+ // handle inplace renaming, if possible
+
+ KrDetailedViewItem *it = static_cast<KrDetailedViewItem*>(getCurrentKrViewItem());
+ if ( it )
+ fileName = it->name();
+ else
+ return ; // quit if no current item available
+ // don't allow anyone to rename ..
+ if ( fileName == ".." )
+ return ;
+
+ // determine which column is inplace renameable
+ for ( c = 0; c < columns(); c++ )
+ if ( isRenameable( c ) )
+ break; // one MUST be renamable
+ if ( !isRenameable( c ) )
+ c = -1; // failsafe
+
+ if ( c >= 0 ) {
+ rename( static_cast<QListViewItem*>( it ), c );
+ // if applicable, select only the name without extension
+ KConfigGroupSaver svr(krConfig,"Look&Feel");
+ if (!krConfig->readBoolEntry("Rename Selects Extension", true)) {
+ if (it->hasExtension() && !it->VF->vfile_isDir() )
+ renameLineEdit()->setSelection(0, it->name().findRev(it->extension())-1);
+ }
+ // signal will be emited when renaming is done, and finalization
+ // will occur in inplaceRenameFinished()
+ } else {
+ // do this in case inplace renaming is disabled
+ // this actually does the good old dialog box rename
+ KrView::renameCurrentItem();
+ }
+}
+
+void KrDetailedView::inplaceRenameFinished( QListViewItem * it, int ) {
+ if( currentlyRenamedItem == 0 )
+ return;
+
+ if ( !it ) { // major failure - call developers
+ krOut << "Major failure at inplaceRenameFinished(): item is null" << endl;
+ return;
+ }
+
+ if( COLUMN( Extention ) != -1 && !currentlyRenamedItem )
+ return; /* does the event filter restored the original state? */
+
+ // check if the item was indeed renamed
+ bool restoreView = false;
+ if ( it->text( COLUMN( Name ) ) != static_cast<KrDetailedViewItem*>( it ) ->name() ) { // was renamed
+ op()->emitRenameItem( static_cast<KrDetailedViewItem*>( it ) ->name(), it->text( COLUMN( Name ) ) );
+ } else restoreView = true;
+
+ // restore the view always! if the file was indeed renamed, we'll get a signal from the vfs about
+ // it, and update the view when needed
+#if 0
+ if ( COLUMN( Extention ) != -1 && restoreView ) { // nothing happened, restore the view (if needed)
+#endif
+
+ QString ext, name = static_cast<KrDetailedViewItem*>( it ) ->name();
+ if ( !static_cast<KrDetailedViewItem*>( it ) ->VF->vfile_isDir() && COLUMN( Extention ) != -1 ) {
+ ext = static_cast<KrDetailedViewItem*>( it ) ->extension();
+ name = static_cast<KrDetailedViewItem*>( it ) ->name( false );
+ }
+ it->setText( COLUMN( Name ), name );
+ it->setText( COLUMN( Extention ), ext );
+ repaintItem( it );
+#if 0
+ }
+#endif
+
+ setFocus();
+
+ currentlyRenamedItem = 0;
+}
+
+// TODO: move the whole quicksearch mess out of here and into krview
+void KrDetailedView::quickSearch( const QString & str, int direction ) {
+ KrViewItem * item = getCurrentKrViewItem();
+ if (!item)
+ return;
+ KConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ bool caseSensitive = _config->readBoolEntry( "Case Sensitive Quicksearch", _CaseSensitiveQuicksearch );
+ if ( !direction ) {
+ if ( caseSensitive ? item->name().startsWith( str ) : item->name().lower().startsWith( str.lower() ) )
+ return ;
+ direction = 1;
+ }
+ KrViewItem * startItem = item;
+ while ( true ) {
+ item = ( direction > 0 ) ? getNext( item ) : getPrev( item );
+ if ( !item )
+ item = ( direction > 0 ) ? getFirst() : getLast();
+ if ( item == startItem )
+ return ;
+ if ( caseSensitive ? item->name().startsWith( str ) : item->name().lower().startsWith( str.lower() ) ) {
+ setCurrentItem( item->name() );
+ makeItemVisible( item );
+ return ;
+ }
+ }
+}
+
+void KrDetailedView::stopQuickSearch( QKeyEvent * e ) {
+ if( ACTIVE_PANEL && ACTIVE_PANEL->quickSearch ) {
+ ACTIVE_PANEL->quickSearch->hide();
+ ACTIVE_PANEL->quickSearch->clear();
+ krDirUp->setEnabled( true );
+ if ( e )
+ keyPressEvent( e );
+ }
+}
+
+// internal: converts signal from qlistview to krview
+void KrDetailedView::setNameToMakeCurrent( QListViewItem * it ) {
+ if (!it) return;
+ KrView::setNameToMakeCurrent( static_cast<KrDetailedViewItem*>( it ) ->name() );
+}
+
+void KrDetailedView::slotMouseClicked( int button, QListViewItem * item, const QPoint&, int ) {
+ pressedItem = 0; // if the signals are emitted, don't emit twice at contentsMouseReleaseEvent
+ if ( button == Qt::MidButton )
+ emit middleButtonClicked( dynamic_cast<KrViewItem *>( item ) );
+}
+
+void KrDetailedView::refreshColors() {
+ krConfig->setGroup("Colors");
+ bool kdeDefault = krConfig->readBoolEntry("KDE Default");
+ bool alternateBackgroundEnabled = krConfig->readBoolEntry("Enable Alternate Background");
+ if ( !kdeDefault ) {
+ // KDE default is not choosen: set the background color (as this paints the empty areas) and the alternate color
+ bool isActive = hasFocus();
+ if ( MAIN_VIEW && ACTIVE_PANEL && ACTIVE_PANEL->view )
+ isActive = ( static_cast<KrView *>( this ) == ACTIVE_PANEL->view );
+ QColorGroup cg;
+ KrColorCache::getColorCache().getColors(cg, KrColorItemType(KrColorItemType::File, false, isActive, false, false));
+ setPaletteBackgroundColor( cg.background() );
+
+ KrColorCache::getColorCache().getColors(cg, KrColorItemType(KrColorItemType::File, true, isActive, false, false));
+ setAlternateBackground( cg.background() );
+ } else {
+ // KDE default is choosen: set back the background color
+ setPaletteBackgroundColor( KGlobalSettings::baseColor() );
+ // Set the alternate color to its default or to an invalid color, to turn alternate the background off.
+ setAlternateBackground( alternateBackgroundEnabled ? KGlobalSettings::alternateBackgroundColor() : QColor() );
+ }
+}
+
+bool KrDetailedView::event( QEvent *e ) {
+ modifierPressed = false;
+
+ switch ( e->type() ) {
+ case QEvent::Timer:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ break;
+ default:
+ CANCEL_TWO_CLICK_RENAME;
+ }
+ return KListView::event( e );
+}
+
+bool KrDetailedView::eventFilter( QObject * watched, QEvent * e )
+{
+ if( watched == renameLineEdit() )
+ {
+ if( currentlyRenamedItem && e->type() == QEvent::Hide )
+ {
+ /* checking if the currentlyRenamedItem pointer is valid (vfs_refresh can delete this item) */
+ for( QListViewItem *it = firstChild(); it; it = it->nextSibling() )
+ if( it == currentlyRenamedItem )
+ {
+ if ( it->text( COLUMN( Name ) ) == dynamic_cast<KrDetailedViewItem*>( it ) ->name() && COLUMN( Extention ) != -1 )
+ inplaceRenameFinished( it, COLUMN( Name ) );
+ break;
+ }
+ }
+ return FALSE;
+ }
+ else if( watched == header() )
+ {
+ if( e->type() == QEvent::MouseButtonPress && ((QMouseEvent *)e )->button() == Qt::RightButton )
+ {
+ selectColumns();
+ return TRUE;
+ }
+ return FALSE;
+ }
+ return KListView::eventFilter( watched, e );
+}
+
+void KrDetailedView::makeItemVisible( const KrViewItem *item ) {
+// qApp->processEvents(); // Please don't remove the comment. Causes crash if it is inserted!
+ ensureItemVisible( static_cast<const KrDetailedViewItem*>( item ) );
+}
+
+void KrDetailedView::initOperator() {
+ _operator = new KrViewOperator(this, this);
+ // klistview emits selection changed, so chain them to operator
+ connect(this, SIGNAL(selectionChanged()), _operator, SIGNAL(selectionChanged()));
+}
+
+void KrDetailedView::initProperties() {
+ _properties = new KrDetailedViewProperties;
+ KConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ for (int i=0; i<KrDetailedViewProperties::MAX_COLUMNS;++i)
+ PROPS->column[i]=-1;
+ PROPS->displayIcons = _config->readBoolEntry( "With Icons", _WithIcons );
+ bool dirsByNameAlways = _config->readBoolEntry("Always sort dirs by name", false);
+ PROPS->sortMode = static_cast<KrViewProperties::SortSpec>( KrViewProperties::Name |
+ KrViewProperties::Descending | KrViewProperties::DirsFirst |
+ (dirsByNameAlways ? KrViewProperties::AlwaysSortDirsByName : 0) );
+ PROPS->numericPermissions = _config->readBoolEntry("Numeric permissions", _NumericPermissions);
+ if ( !_config->readBoolEntry( "Case Sensative Sort", _CaseSensativeSort ) )
+ PROPS->sortMode = static_cast<KrViewProperties::SortSpec>( _properties->sortMode |
+ KrViewProperties::IgnoreCase );
+ PROPS->humanReadableSize = krConfig->readBoolEntry("Human Readable Size", _HumanReadableSize);
+ PROPS->localeAwareCompareIsCaseSensitive = QString( "a" ).localeAwareCompare( "B" ) > 0; // see KDE bug #40131
+ QStringList defaultAtomicExtensions;
+ defaultAtomicExtensions += ".tar.gz";
+ defaultAtomicExtensions += ".tar.bz2";
+ defaultAtomicExtensions += ".moc.cpp";
+ QStringList atomicExtensions = krConfig->readListEntry("Atomic Extensions", defaultAtomicExtensions);
+ for (QStringList::iterator i = atomicExtensions.begin(); i != atomicExtensions.end(); )
+ {
+ QString & ext = *i;
+ ext = ext.stripWhiteSpace();
+ if (!ext.length())
+ {
+ i = atomicExtensions.remove(i);
+ continue;
+ }
+ if (!ext.startsWith("."))
+ ext.insert(0, '.');
+ ++i;
+ }
+ PROPS->atomicExtensions = atomicExtensions;
+}
+
+void KrDetailedView::selectColumns()
+{
+ KPopupMenu popup( this );
+ popup.insertTitle( i18n("Columns"));
+
+ bool refresh = false;
+
+ bool hasExtention = COLUMN( Extention ) != -1;
+ bool hasMime = COLUMN( Mime ) != -1;
+ bool hasSize = COLUMN( Size ) != -1;
+ bool hasDate = COLUMN( DateTime ) != -1;
+ bool hasPerms = COLUMN( Permissions ) != -1;
+ bool hasKrPerms = COLUMN( KrPermissions ) != -1;
+ bool hasOwner = COLUMN( Owner ) != -1;
+ bool hasGroup = COLUMN( Group ) != -1;
+
+ popup.insertItem( i18n( "Ext" ), COLUMN_POPUP_IDS + KrDetailedViewProperties::Extention );
+ popup.setItemChecked( COLUMN_POPUP_IDS + KrDetailedViewProperties::Extention, hasExtention );
+
+ popup.insertItem( i18n( "Type" ), COLUMN_POPUP_IDS + KrDetailedViewProperties::Mime );
+ popup.setItemChecked( COLUMN_POPUP_IDS + KrDetailedViewProperties::Mime, hasMime );
+
+ popup.insertItem( i18n( "Size" ), COLUMN_POPUP_IDS + KrDetailedViewProperties::Size );
+ popup.setItemChecked( COLUMN_POPUP_IDS + KrDetailedViewProperties::Size, hasSize );
+
+ popup.insertItem( i18n( "Modified" ), COLUMN_POPUP_IDS + KrDetailedViewProperties::DateTime );
+ popup.setItemChecked( COLUMN_POPUP_IDS + KrDetailedViewProperties::DateTime, hasDate );
+
+ popup.insertItem( i18n( "Perms" ), COLUMN_POPUP_IDS + KrDetailedViewProperties::Permissions );
+ popup.setItemChecked( COLUMN_POPUP_IDS + KrDetailedViewProperties::Permissions, hasPerms );
+
+ popup.insertItem( i18n( "rwx" ), COLUMN_POPUP_IDS + KrDetailedViewProperties::KrPermissions );
+ popup.setItemChecked( COLUMN_POPUP_IDS + KrDetailedViewProperties::KrPermissions, hasKrPerms );
+
+ popup.insertItem( i18n( "Owner" ), COLUMN_POPUP_IDS + KrDetailedViewProperties::Owner );
+ popup.setItemChecked( COLUMN_POPUP_IDS + KrDetailedViewProperties::Owner, hasOwner );
+
+ popup.insertItem( i18n( "Group" ), COLUMN_POPUP_IDS + KrDetailedViewProperties::Group );
+ popup.setItemChecked( COLUMN_POPUP_IDS + KrDetailedViewProperties::Group, hasGroup );
+
+ int result=popup.exec(QCursor::pos());
+
+ krConfig->setGroup( nameInKConfig() );
+
+ switch( result - COLUMN_POPUP_IDS )
+ {
+ case KrDetailedViewProperties::Extention:
+ krConfig->writeEntry( "Ext Column", !hasExtention );
+ refresh = true;
+ break;
+ case KrDetailedViewProperties::Mime:
+ krConfig->writeEntry( "Mime Column", !hasMime );
+ refresh = true;
+ break;
+ case KrDetailedViewProperties::Size:
+ krConfig->writeEntry( "Size Column", !hasSize );
+ refresh = true;
+ break;
+ case KrDetailedViewProperties::DateTime:
+ krConfig->writeEntry( "DateTime Column", !hasDate );
+ refresh = true;
+ break;
+ case KrDetailedViewProperties::Permissions:
+ krConfig->writeEntry( "Perm Column", !hasPerms );
+ refresh = true;
+ break;
+ case KrDetailedViewProperties::KrPermissions:
+ krConfig->writeEntry( "KrPerm Column", !hasKrPerms );
+ refresh = true;
+ break;
+ case KrDetailedViewProperties::Owner:
+ krConfig->writeEntry( "Owner Column", !hasOwner );
+ refresh = true;
+ break;
+ case KrDetailedViewProperties::Group:
+ krConfig->writeEntry( "Group Column", !hasGroup );
+ refresh = true;
+ break;
+ }
+
+ if( refresh )
+ {
+ PanelManager *p = ACTIVE_PANEL->view == this ? ACTIVE_MNG : OTHER_MNG;
+ QTimer::singleShot( 0, p, SLOT( slotRecreatePanels() ) );
+ }
+}
+
+void KrDetailedView::sortOrderChanged(int) {
+ ensureItemVisible(currentItem());
+}
+
+void KrDetailedView::updateView() {
+ triggerUpdate();
+ op()->emitSelectionChanged();
+}
+
+void KrDetailedView::updateItem(KrViewItem* item) {
+ dynamic_cast<KrDetailedViewItem*>(item)->repaintItem();
+}
+
+void KrDetailedView::slotRightButtonPressed(QListViewItem*, const QPoint& point, int) {
+ op()->emitEmptyContextMenu(point);
+}
+
+// hack: this needs to be done in a more cross-view way
+void KrDetailedView::slotSortOrderChanged(int col) {
+ // map the column to a sort specification
+ KrViewProperties::SortSpec sp = KrViewProperties::Name;
+ int i;
+ for (i = 0; i < KrDetailedViewProperties::MAX_COLUMNS; ++i) {
+ if (PROPS->column[i] == col) break;
+ }
+ switch (i) {
+ case KrDetailedViewProperties::Name:
+ sp = KrViewProperties::Name; break;
+ case KrDetailedViewProperties::Extention:
+ sp = KrViewProperties::Ext; break;
+ case KrDetailedViewProperties::Mime:
+ sp = KrViewProperties::Type; break;
+ case KrDetailedViewProperties::Size:
+ sp = KrViewProperties::Size; break;
+ case KrDetailedViewProperties::DateTime:
+ sp = KrViewProperties::Modified; break;
+ case KrDetailedViewProperties::Permissions:
+ sp = KrViewProperties::Permissions; break;
+ case KrDetailedViewProperties::KrPermissions:
+ sp = KrViewProperties::KrPermissions; break;
+ case KrDetailedViewProperties::Owner:
+ sp = KrViewProperties::Owner; break;
+ case KrDetailedViewProperties::Group:
+ sp = KrViewProperties::Group; break;
+ default: qFatal("slotSortOrderChanged: unknown column");
+ }
+ if (sortMode() & KrViewProperties::DirsFirst)
+ sp = static_cast<KrViewProperties::SortSpec>(sp | KrViewProperties::DirsFirst);
+ if (sortMode() & KrViewProperties::IgnoreCase)
+ sp = static_cast<KrViewProperties::SortSpec>(sp | KrViewProperties::IgnoreCase);
+ if (sortMode() & KrViewProperties::Descending)
+ sp = static_cast<KrViewProperties::SortSpec>(sp | KrViewProperties::Descending);
+ if (sortMode() & KrViewProperties::AlwaysSortDirsByName)
+ sp = static_cast<KrViewProperties::SortSpec>(sp | KrViewProperties::AlwaysSortDirsByName);
+ // fix the ascending/decending stuff
+ if (sortMode() == sp) {
+ if (sp & KrViewProperties::Descending)
+ sp = static_cast<KrViewProperties::SortSpec>(sp &~ KrViewProperties::Descending);
+ else sp = static_cast<KrViewProperties::SortSpec>(sp | KrViewProperties::Descending);
+ }
+ PROPS->sortMode = sp;
+
+ if( !_focused )
+ op()->emitNeedFocus();
+}
+
+#include "krdetailedview.moc"
diff --git a/krusader/Panel/krdetailedview.h b/krusader/Panel/krdetailedview.h
new file mode 100644
index 0000000..f0616fb
--- /dev/null
+++ b/krusader/Panel/krdetailedview.h
@@ -0,0 +1,180 @@
+/***************************************************************************
+ krdetailedview.h
+ -------------------
+ copyright : (C) 2000-2002 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+Description
+***************************************************************************
+
+A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+#ifndef KRDETAILEDVIEW_H
+#define KRDETAILEDVIEW_H
+
+#include <klistview.h>
+#include <ksqueezedtextlabel.h>
+#include <klocale.h>
+#include <qwidget.h>
+#include <qtimer.h>
+#include <qdatetime.h>
+#include "krview.h"
+#include "krviewitem.h"
+
+// extends KrViewProperties to add detailedview-only properties
+class KrDetailedViewProperties: public KrViewProperties {
+public:
+ enum ColumnType { Unused = -1, Name = 0x0, Extention = 0x1, Mime = 0x2, Size = 0x3, DateTime = 0x4,
+ Permissions = 0x5, KrPermissions = 0x6, Owner = 0x7, Group = 0x8 };
+ static const int MAX_COLUMNS = 9;
+ int column[ MAX_COLUMNS ]; // column[ColumnType] contains the number of the requested column.
+ // This is used by column() and whenever item uses text() or setText()
+ bool numericPermissions; // show full permission column as octal numbers
+
+ KrDetailedViewProperties() {
+ for ( int i = 0; i < MAX_COLUMNS; i++ ) column[i] = Unused;
+ filter = KrViewProperties::All;
+ filterMask = KRQuery( "*" );
+ }
+};
+
+
+class QDragMoveEvent;
+class KrRenameTimerObject;
+class ListPanel;
+class KrDetailedViewItem;
+
+/**
+ * KrDetailedView implements everthing and anything regarding a detailed view in a filemananger.
+ * IT MUST USE KrViewItem as the children to it's *KListView. KrDetailedView and KrViewItem are
+ * tightly coupled and the view will not work with other kinds of items.
+ * Apart from this, the view is self-reliant and you can use the vast interface to get whatever
+ * information is necessery from it.
+ */
+class KrDetailedView : public KListView, public KrView {
+ Q_OBJECT
+ friend class KrDetailedViewItem;
+
+public:
+ KrDetailedView( QWidget *parent, bool &left, KConfig *cfg = krConfig, const char *name = 0 );
+ virtual ~KrDetailedView();
+ virtual int column( KrDetailedViewProperties::ColumnType type );
+ virtual inline KrViewItem *getFirst() { return dynamic_cast<KrViewItem*>( firstChild() ); }
+ virtual inline KrViewItem *getLast() { return dynamic_cast<KrViewItem*>( lastChild() ); }
+ virtual inline KrViewItem *getNext( KrViewItem *current ) { return dynamic_cast<KrViewItem*>( dynamic_cast<KListViewItem*>( current ) ->itemBelow() ); }
+ virtual inline KrViewItem *getPrev( KrViewItem *current ) { return dynamic_cast<KrViewItem*>( dynamic_cast<KListViewItem*>( current ) ->itemAbove() ); }
+ virtual inline KrViewItem *getCurrentKrViewItem() { return dynamic_cast<KrViewItem*>( currentItem() ); }
+ virtual KrViewItem *getKrViewItemAt( const QPoint &vp );
+ virtual inline KrViewItem *findItemByName( const QString &name ) { return dynamic_cast<KrViewItem*>( findItem( name, 0 ) ); }
+ virtual void addItems( vfs *v, bool addUpDir = true );
+ virtual QString getCurrentItem() const;
+ virtual void makeItemVisible( const KrViewItem *item );
+ virtual void setCurrentItem( const QString& name );
+ virtual void updateView();
+ virtual void updateItem(KrViewItem* item);
+ virtual void clear();
+ virtual void sort() { KListView::sort(); }
+ virtual void setSortMode( KrViewProperties::SortSpec mode );
+ virtual void prepareForActive();
+ virtual void prepareForPassive();
+ virtual inline void saveSettings() { KListView::saveLayout( _config, nameInKConfig() ); }
+ virtual inline void restoreSettings() { KListView::restoreLayout( _config, nameInKConfig() ); }
+
+signals:
+ void middleButtonClicked( KrViewItem *item );
+ void currentChanged( KrViewItem *item );
+
+protected:
+ virtual void setup();
+ virtual void initProperties();
+ virtual void initOperator();
+ virtual KrViewItem *preAddItem(vfile *vf);
+ virtual bool preDelItem(KrViewItem *item);
+
+ void newColumn( KrDetailedViewProperties::ColumnType type );
+ void selectColumns();
+
+ virtual void keyPressEvent( QKeyEvent *e );
+ virtual void imStartEvent( QIMEvent* e );
+ virtual void imEndEvent( QIMEvent *e );
+ virtual void imComposeEvent( QIMEvent *e );
+ virtual void contentsMousePressEvent( QMouseEvent *e );
+ virtual void contentsMouseReleaseEvent (QMouseEvent *e);
+ virtual void contentsMouseMoveEvent ( QMouseEvent * e );
+ virtual void contentsWheelEvent( QWheelEvent *e );
+ virtual bool acceptDrag( QDropEvent* e ) const;
+ virtual void contentsDropEvent( QDropEvent *e );
+ virtual void contentsDragMoveEvent( QDragMoveEvent *e );
+ virtual QRect drawItemHighlighter(QPainter *painter, QListViewItem *item);
+ virtual void startDrag() { op()->startDrag(); }
+ virtual bool event( QEvent *e );
+ virtual bool eventFilter( QObject * watched, QEvent * e );
+
+protected slots:
+ void rename( QListViewItem *item, int c );
+ void slotClicked( QListViewItem *item );
+ void slotDoubleClicked( QListViewItem *item );
+ void slotItemDescription( QListViewItem *item );
+ void slotCurrentChanged( QListViewItem *item );
+ void handleContextMenu( QListViewItem*, const QPoint&, int );
+ virtual void renameCurrentItem();
+ virtual void showContextMenu( );
+ void inplaceRenameFinished( QListViewItem *it, int col );
+ void setNameToMakeCurrent( QListViewItem *it );
+ void sortOrderChanged(int);
+ void slotRightButtonPressed(QListViewItem*, const QPoint& point, int);
+ void slotSortOrderChanged(int col);
+ void transformCurrentChanged( QListViewItem * item ) { emit currentChanged( dynamic_cast<KrViewItem *>(item ) ); }
+
+ /**
+ * used internally to produce the signal middleButtonClicked()
+ */
+ void slotMouseClicked( int button, QListViewItem * item, const QPoint & pos, int c );
+ inline void slotExecuted( QListViewItem* i ) {
+ QString tmp = dynamic_cast<KrViewItem*>( i ) ->name();
+ op()->emitExecuted( tmp );
+ }
+
+public slots:
+ void refreshColors();
+ void quickSearch( const QString &, int = 0 );
+ void stopQuickSearch( QKeyEvent* );
+ void handleQuickSearchEvent( QKeyEvent* );
+
+private:
+ static QString ColumnName[ KrDetailedViewProperties::MAX_COLUMNS ];
+ bool swushSelects;
+ QPoint dragStartPos;
+ QListViewItem *lastSwushPosition;
+ bool caseSensitiveSort;
+ KrViewItem *_currDragItem;
+ bool singleClicked;
+ bool modifierPressed;
+ QTime clickTime;
+ QListViewItem *clickedItem;
+ QTimer renameTimer;
+ QTimer contextMenuTimer;
+ QPoint contextMenuPoint;
+ QListViewItem *currentlyRenamedItem;
+ QListViewItem *pressedItem;
+};
+
+#endif /* KRDETAILEDVIEW_H */
diff --git a/krusader/Panel/krdetailedviewitem.cpp b/krusader/Panel/krdetailedviewitem.cpp
new file mode 100644
index 0000000..4d37854
--- /dev/null
+++ b/krusader/Panel/krdetailedviewitem.cpp
@@ -0,0 +1,313 @@
+/***************************************************************************
+ krdetailedviewitem.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "../krusader.h"
+#include "../defaults.h"
+#include "../kicons.h"
+#include "../krusaderview.h"
+#include "krdetailedviewitem.h"
+#include "krdetailedview.h"
+#include "krcolorcache.h"
+#include "listpanel.h"
+#include "../VFS/krpermhandler.h"
+#include <sys/types.h>
+#include <time.h>
+#include <qpainter.h>
+#include <pwd.h>
+#include <grp.h>
+#include <stdlib.h>
+#include <qpalette.h>
+#include <kdebug.h>
+#include <kmimetype.h>
+
+#define COLUMN(X) static_cast<const KrDetailedViewProperties*>(_viewProperties)-> \
+ column[ KrDetailedViewProperties::X ]
+#define PROPS static_cast<const KrDetailedViewProperties*>(_viewProperties)
+#define PERM_BITMASK (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
+#define VF getVfile()
+
+#ifdef FASTER
+int KrDetailedViewItem::expHeight = 0;
+#endif // FASTER
+
+KrDetailedViewItem::KrDetailedViewItem(KrDetailedView *parent, QListViewItem *after, vfile *vf):
+ KListViewItem(parent, after), KrViewItem(vf, parent->properties()) {
+#ifdef FASTER
+ initiated = false;
+ // get the expected height of an item - should be done only once
+ if (expHeight == 0) {
+ KConfigGroupSaver svr(krConfig, "Look&Feel");
+ expHeight = 2 + (krConfig->readEntry("Filelist Icon Size",_FilelistIconSize)).toInt();
+ }
+
+#endif
+ // there's a special case, where if _vf is null, then we've got the ".." (updir) item
+ // in that case, create a special vfile for that item, and delete it, if needed
+ if (!_vf) {
+ dummyVfile = true;
+ _vf = new vfile("..", 0, "drw-r--r--", 0, false, 0, 0, QString::null, QString::null, 0);
+
+ setText(COLUMN(Name), "..");
+ setText(COLUMN(Size), i18n("<DIR>") );
+ if ( PROPS->displayIcons )
+ setPixmap( COLUMN(Name), FL_LOADICON( "up" ) );
+ setSelectable( false );
+#ifdef FASTER
+ initiated = true;
+#endif
+ }
+
+ repaintItem();
+}
+
+#ifdef FASTER
+void KrDetailedViewItem::setup() {
+ // idea: when not having pixmaps in the first place, the height of the item is smaller then with
+ // the pixmap. when the pixmap is inserted, the item resizes, thereby making ensureItemVisible()
+ // become 'confused' and stop working. therefore, we set the correct height here and avoid the issue
+ KListViewItem::setup();
+ setHeight(expHeight);
+}
+#endif
+
+void KrDetailedViewItem::repaintItem() {
+ if ( dummyVfile ) return;
+ QString tmp;
+ // set text in columns, according to what columns are available
+ int id = KrDetailedViewProperties::Unused;
+ if ((id = COLUMN(Mime)) != -1) {
+ tmp = KMimeType::mimeType(_vf->vfile_getMime())->comment();
+ setText( id, tmp );
+ }
+ if ((id = COLUMN(Size)) != -1) {
+ if (_vf->vfile_isDir() && _vf->vfile_getSize() <= 0) setText(id, i18n("<DIR>"));
+ else setText(id, PROPS->humanReadableSize ? KIO::convertSize(_vf->vfile_getSize())+" " :
+ KRpermHandler::parseSize(_vf->vfile_getSize())+" ");
+ }
+
+ if ((id = COLUMN(DateTime)) != -1)
+ setText(id, dateTime());
+ if ((id = COLUMN(KrPermissions)) != -1) {
+ // first, build the krusader permissions
+ tmp=QString::null;
+ switch (_vf->vfile_isReadable()){
+ case ALLOWED_PERM: tmp+='r'; break;
+ case UNKNOWN_PERM: tmp+='?'; break;
+ case NO_PERM: tmp+='-'; break;
+ }
+ switch (_vf->vfile_isWriteable()){
+ case ALLOWED_PERM: tmp+='w'; break;
+ case UNKNOWN_PERM: tmp+='?'; break;
+ case NO_PERM: tmp+='-'; break;
+ }
+ switch (_vf->vfile_isExecutable()){
+ case ALLOWED_PERM: tmp+='x'; break;
+ case UNKNOWN_PERM: tmp+='?'; break;
+ case NO_PERM: tmp+='-'; break;
+ }
+ setText(id, tmp);
+ }
+ if ((id = COLUMN(Permissions) ) != -1) {
+ if (PROPS->numericPermissions) {
+ setText(id, tmp.sprintf("%.4o", _vf->vfile_getMode() & PERM_BITMASK));
+ } else setText(id, _vf->vfile_getPerm());
+ }
+ if ((id = COLUMN(Owner)) != -1) {
+ setText(id, _vf->vfile_getOwner());
+ }
+ if ((id = COLUMN(Group)) != -1) {
+ setText(id, _vf->vfile_getGroup());
+ }
+ // if we've got an extention column, clip the name accordingly
+ QString name = this->name(), ext = "";
+ if ((id = COLUMN(Extention)) != -1 && !_vf->vfile_isDir()) {
+ ext = this->extension();
+ name = this->name(false); // request name without extension
+ setText(id, ext);
+ }
+ setText(COLUMN(Name), name);
+#ifndef FASTER
+ // display an icon if needed
+ if (PROPS->displayIcons)
+ setPixmap(COLUMN(Name),KrView::getIcon(_vf));
+#endif
+}
+
+QString num2qstring(KIO::filesize_t num){
+ QString buf;
+ buf.sprintf("%025llu",num);
+ return buf;
+}
+
+void KrDetailedViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int align) {
+#ifdef FASTER
+ if (!initiated && !dummyVfile) {
+ // display an icon if needed
+ if (PROPS->displayIcons)
+ setPixmap(COLUMN(Name),KrView::getIcon(_vf));
+
+ initiated = true;
+ }
+#endif
+
+ QColorGroup _cg(cg);
+
+ // This is ugly! I had to dublicate KListViewItem::paintCell() code, as the
+ // KListViewItem::paintCell() overwrites my color settings. So KrDetailedViewItem::paintCell
+ // must dublicate the KListViewItem::paintCell() code, do the required color settings
+ // and call QListViewItem::paintCell() afterwards (the base class of KListViewItem).
+ // This tabooed in the object oriented heaven, but necessary here. Blame the KDE team for
+ // this really poor paintCell implementation!
+
+ const QPixmap *pm = listView()->viewport()->backgroundPixmap();
+ if (pm && !pm->isNull())
+ {
+ _cg.setBrush(QColorGroup::Base, QBrush(backgroundColor(), *pm));
+ p->setBrushOrigin( -listView()->contentsX(), -listView()->contentsY() );
+ }
+ else if (isAlternate())
+ if (listView()->viewport()->backgroundMode()==Qt::FixedColor)
+ _cg.setColor(QColorGroup::Background, static_cast< KListView* >(listView())->alternateBackground());
+ else
+ _cg.setColor(QColorGroup::Base, static_cast< KListView* >(listView())->alternateBackground());
+
+ // end of uglyness
+
+ KrColorItemType colorItemType;
+ colorItemType.m_activePanel = (dynamic_cast<KrView *>(listView()) == ACTIVE_PANEL->view);
+ colorItemType.m_alternateBackgroundColor = isAlternate();
+ colorItemType.m_currentItem = (listView()->currentItem() == this);
+ colorItemType.m_selectedItem = isSelected();
+ if (VF->vfile_isSymLink())
+ {
+ if (_vf->vfile_getMime() == "Broken Link !" )
+ colorItemType.m_fileType = KrColorItemType::InvalidSymlink;
+ else
+ colorItemType.m_fileType = KrColorItemType::Symlink;
+ }
+ else if (VF->vfile_isDir())
+ colorItemType.m_fileType = KrColorItemType::Directory;
+ else if (VF->vfile_isExecutable())
+ colorItemType.m_fileType = KrColorItemType::Executable;
+ else
+ colorItemType.m_fileType = KrColorItemType::File;
+ KrColorCache::getColorCache().getColors(_cg, colorItemType);
+ // center the <DIR> thing if needed
+ if(column != COLUMN(Size))
+ QListViewItem::paintCell(p, _cg, column, width, align);
+ else {
+ if (dummyVfile) {
+ QListViewItem::paintCell(p, _cg, column, width, Qt::AlignHCenter); // updir
+ } else {
+ if (_vf->vfile_isDir() && _vf->vfile_getSize()<=0)
+ QListViewItem::paintCell(p, _cg, column, width, Qt::AlignHCenter);
+ else QListViewItem::paintCell(p, _cg, column, width, align); // size
+ }
+ }
+}
+
+const QColor & KrDetailedViewItem::setColorIfContrastIsSufficient(const QColor & background, const QColor & color1, const QColor & color2)
+{
+ #define sqr(x) ((x)*(x))
+ int contrast = sqr(color1.red() - background.red()) + sqr(color1.green() - background.green()) + sqr(color1.blue() - background.blue());
+
+ // if the contrast between background and color1 is too small, take color2 instead.
+ if (contrast < 1000)
+ return color2;
+ return color1;
+}
+
+int KrDetailedViewItem::compare(QListViewItem *i,int col,bool ascending ) const {
+ bool ignoreCase = (PROPS->sortMode & KrViewProperties::IgnoreCase);
+ bool alwaysSortDirsByName = (PROPS->sortMode & KrViewProperties::AlwaysSortDirsByName);
+ int asc = ( ascending ? -1 : 1 );
+ KrDetailedViewItem *other = (KrDetailedViewItem *)(i);
+
+ bool thisDir = VF->vfile_isDir();
+ bool otherDir = other->VF->vfile_isDir();
+
+ // handle directory sorting
+ if ( thisDir ){
+ if ( !otherDir ) return 1*asc;
+ } else if( otherDir ) return -1*asc;
+
+ if ( isDummy() ) return 1*asc;
+ if ( other->isDummy() ) return -1*asc;
+
+ if (col == COLUMN(Name) ||
+ (alwaysSortDirsByName && thisDir && otherDir )) {
+ // localeAwareCompare doesn't handle names that start with a dot
+ QString text0 = name();
+ QString itext0 = other->name();
+
+ if( ignoreCase )
+ {
+ text0 = text0.lower();
+ itext0 = itext0.lower();
+ }
+
+ if ( isHidden() ) {
+ if ( !other->isHidden() ) return 1*asc;
+ } else if ( other->isHidden() ) return -1*asc;
+ if (!ignoreCase && !PROPS->localeAwareCompareIsCaseSensitive) {
+ // sometimes, localeAwareCompare is not case sensative. in that case,
+ // we need to fallback to a simple string compare (KDE bug #40131)
+ return QString::compare(text0, itext0);
+ } else return QString::localeAwareCompare(text0,itext0);
+ } else if (col == COLUMN(Size) ) {
+ if( VF->vfile_getSize() == other->VF->vfile_getSize() )
+ return 0;
+ return (VF->vfile_getSize() > other->VF->vfile_getSize() ? 1 : -1);
+ } else if (col == COLUMN(DateTime) ) {
+ if( VF->vfile_getTime_t() == other->VF->vfile_getTime_t() )
+ return 0;
+ return (VF->vfile_getTime_t() > other->VF->vfile_getTime_t() ? 1 : -1);
+ } else if (col == COLUMN(Permissions) && PROPS->numericPermissions) {
+ int thisPerm = VF->vfile_getMode() & PERM_BITMASK;
+ int otherPerm = other->VF->vfile_getMode() & PERM_BITMASK;
+ if( thisPerm == otherPerm )
+ return 0;
+ return ((thisPerm > otherPerm) ? 1 : -1);
+ } else {
+ QString e1 = (!ignoreCase ? text(col) : text(col).lower());
+ QString e2 = (!ignoreCase ? i->text(col) : i->text(col).lower());
+ if (!ignoreCase && !PROPS->localeAwareCompareIsCaseSensitive) {
+ // sometimes, localeAwareCompare is not case sensative. in that case,
+ // we need to fallback to a simple string compare (KDE bug #40131)
+ return QString::compare(e1, e2);
+ } else return QString::localeAwareCompare(e1, e2);
+ }
+}
+
+void KrDetailedViewItem::itemHeightChanged() {
+#ifdef FASTER
+ expHeight = 0;
+#endif
+}
diff --git a/krusader/Panel/krdetailedviewitem.h b/krusader/Panel/krdetailedviewitem.h
new file mode 100644
index 0000000..3ef9fcf
--- /dev/null
+++ b/krusader/Panel/krdetailedviewitem.h
@@ -0,0 +1,73 @@
+/***************************************************************************
+ krdetailedviewitem.h
+ -------------------
+ copyright : (C) 2000-2002 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KRDETAILEDVIEWITEM_H
+#define KRDETAILEDVIEWITEM_H
+
+#include "krviewitem.h"
+#include <sys/types.h>
+#include "../VFS/vfile.h"
+#include <klistview.h>
+#include <qguardedptr.h>
+
+#define FASTER
+
+class QPixmap;
+class KrDetailedView;
+
+class KrDetailedViewItem : public KListViewItem, public KrViewItem {
+friend class KrDetailedView;
+friend class KrCalcSpaceDialog;
+public:
+ KrDetailedViewItem(KrDetailedView *parent, QListViewItem *after, vfile *vf);
+ inline bool isSelected() const { return KListViewItem::isSelected(); }
+ inline void setSelected(bool s) { KListViewItem::setSelected(s); }
+ int compare(QListViewItem *i,int col,bool ascending ) const;
+ void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int align);
+ void repaintItem();
+ static void itemHeightChanged(); // force the items to resize when icon/font size change
+#ifdef FASTER
+ virtual void setup(); // called when listview needs to know the height of the item
+#endif
+
+protected:
+ // text() was made protected in order to catch every place where text(x) is used
+ // to gain unlawful information on the object
+ virtual inline QString text(int column) const { return KListViewItem::text(column); }
+
+private:
+ static const QColor & setColorIfContrastIsSufficient(const QColor & background, const QColor & color1, const QColor & color2);
+#ifdef FASTER
+ bool initiated;
+ static int expHeight;
+#endif
+};
+
+#endif
diff --git a/krusader/Panel/krdrag.cpp b/krusader/Panel/krdrag.cpp
new file mode 100644
index 0000000..5e80b36
--- /dev/null
+++ b/krusader/Panel/krdrag.cpp
@@ -0,0 +1,103 @@
+/***************************************************************************
+ krdrag.cpp
+ -------------------
+copyright : (C) 2003 by Heiner Eichmann
+e-mail : krusader@users.sourceforge.net
+web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+Description
+***************************************************************************
+
+A
+
+db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+#include "krdrag.h"
+#include <kurldrag.h>
+
+KRDrag * KRDrag::newDrag( const KURL::List & urls, bool move, QWidget * dragSource, const char* name )
+{
+ // See KURLDrag::newDrag
+ QStrList uris;
+ KURL::List::ConstIterator uit = urls.begin();
+ KURL::List::ConstIterator uEnd = urls.end();
+ // Get each URL encoded in utf8 - and since we get it in escaped
+ // form on top of that, .latin1() is fine.
+ for ( ; uit != uEnd ; ++uit )
+ uris.append( KURLDrag::urlToString( *uit ).latin1() );
+ return new KRDrag( uris, move, dragSource, name );
+}
+
+KRDrag::KRDrag( const QStrList & urls, bool move, QWidget * dragSource, const char* name )
+ : QUriDrag( urls, dragSource, name ),
+ m_bCutSelection( move ), m_urls( urls )
+{}
+
+const char* KRDrag::format( int i ) const
+{
+ if ( i == 0 )
+ return "text/uri-list";
+ else if ( i == 1 )
+ return "application/x-kde-cutselection";
+ else if ( i == 2 )
+ return "text/plain";
+ else return 0;
+}
+
+QByteArray KRDrag::encodedData( const char* mime ) const
+{
+ QByteArray a;
+ QCString mimetype( mime );
+ if ( mimetype == "text/uri-list" )
+ return QUriDrag::encodedData( mime );
+ else if ( mimetype == "application/x-kde-cutselection" ) {
+ QCString s ( m_bCutSelection ? "1" : "0" );
+ a.resize( s.length() + 1 ); // trailing zero
+ memcpy( a.data(), s.data(), s.length() + 1 );
+ }
+ else if ( mimetype == "text/plain" )
+ {
+ QStringList uris;
+ for (QStrListIterator it(m_urls); *it; ++it)
+ uris.append(KURLDrag::stringToUrl(*it).prettyURL());
+ QCString s = uris.join( "\n" ).local8Bit();
+ if( uris.count() > 1 )
+ s.append( "\n" );
+ a.resize( s.length() + 1 ); // trailing zero
+ memcpy( a.data(), s.data(), s.length() + 1 );
+ }
+ return a;
+}
+
+//
+
+// Used for KonqIconDrag too
+
+bool KRDrag::decodeIsCutSelection( const QMimeSource *e )
+{
+ QByteArray a = e->encodedData( "application/x-kde-cutselection" );
+ if ( a.isEmpty() )
+ return false;
+ else
+ {
+ return (a.at(0) == '1'); // true if "1", or similar
+ }
+ }
+
+#include "krdrag.moc"
diff --git a/krusader/Panel/krdrag.h b/krusader/Panel/krdrag.h
new file mode 100644
index 0000000..1aa264f
--- /dev/null
+++ b/krusader/Panel/krdrag.h
@@ -0,0 +1,62 @@
+/***************************************************************************
+ krdrag.h
+ -------------------
+copyright : (C) 2003 by Heiner Eichmann
+e-mail : krusader@users.sourceforge.net
+web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+Description
+***************************************************************************
+
+A
+
+db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+#ifndef KRDRAG_H
+#define KRDRAG_H
+
+#include <qdragobject.h>
+#include <kurl.h>
+
+class KRDrag : public QUriDrag
+{
+ Q_OBJECT
+public:
+ static KRDrag * newDrag( const KURL::List & urls, bool move, QWidget * dragSource = 0, const char* name = 0 );
+
+protected:
+ KRDrag( const QStrList & urls, bool move, QWidget * dragSource, const char* name );
+
+public:
+ virtual ~KRDrag() {}
+
+ virtual const char* format( int i ) const;
+ virtual QByteArray encodedData( const char* mime ) const;
+
+ void setMoveSelection( bool move ) { m_bCutSelection = move; }
+
+ // Returns true if the data was cut (used for KonqIconDrag too)
+ static bool decodeIsCutSelection( const QMimeSource *e );
+
+protected:
+ bool m_bCutSelection;
+ QStrList m_urls;
+};
+
+#endif /* KRDRAG_H */
diff --git a/krusader/Panel/krpopupmenu.cpp b/krusader/Panel/krpopupmenu.cpp
new file mode 100644
index 0000000..fda6296
--- /dev/null
+++ b/krusader/Panel/krpopupmenu.cpp
@@ -0,0 +1,354 @@
+/***************************************************************************
+ krpopupmenu.cpp - description
+ -------------------
+ begin : Tue Aug 26 2003
+ copyright : (C) 2003 by Shie Erlich & Rafi Yanai
+ email :
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <klocale.h>
+#include <kprocess.h>
+#include <kshred.h>
+#include <krun.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+#include "../krservices.h"
+#include "../defaults.h"
+#include "../MountMan/kmountman.h"
+#include "../krslots.h"
+#include "krpopupmenu.h"
+#include "krview.h"
+#include "krviewitem.h"
+#include "panelfunc.h"
+#include "../krusaderview.h"
+#include "../panelmanager.h"
+
+void KrPopupMenu::run(const QPoint &pos, ListPanel *panel) {
+ KrPopupMenu menu(panel);
+ int result = menu.exec(pos);
+ menu.performAction(result);
+}
+
+KrPopupMenu::KrPopupMenu(ListPanel *thePanel, QWidget *parent) : KPopupMenu(parent), panel(thePanel), empty(false),
+ multipleSelections(false),actions(0) {
+#ifdef __LIBKONQ__
+ konqMenu = 0;
+#endif
+
+ panel->view->getSelectedKrViewItems( &items );
+ if ( items.empty() ) {
+ addCreateNewMenu();
+ insertSeparator();
+ addEmptyMenuEntries();
+ return;
+ } else if ( items.size() > 1 ) multipleSelections = true;
+
+ item = items.first();
+ vfile *vf = panel->func->getVFile(item);
+
+ // ------------ the OPEN option - open prefered service
+ insertItem( i18n("Open/Run"), OPEN_ID );
+ if ( !multipleSelections ) { // meaningful only if one file is selected
+ changeItem( OPEN_ID, item->icon(), vf->vfile_isExecutable() && !vf->vfile_isDir() ? i18n("Run") : i18n("Open") );
+ // open in a new tab (if folder)
+ if ( vf->vfile_isDir() ) {
+ insertItem( i18n( "Open in New Tab" ), OPEN_TAB_ID );
+ changeItem( OPEN_TAB_ID, krLoader->loadIcon( "tab_new", KIcon::Panel ), i18n( "Open in New Tab" ) );
+ }
+ insertSeparator();
+ }
+
+ // ------------- Preview - normal vfs only ?
+ if ( panel->func->files()->vfs_getType() == vfs::NORMAL ) {
+ // create the preview popup
+ QStringList names;
+ panel->getSelectedNames( &names );
+ preview.setUrls( panel->func->files() ->vfs_getFiles( &names ) );
+ insertItem( i18n("Preview"), &preview, PREVIEW_ID );
+ }
+
+ // -------------- Open with: try to find-out which apps can open the file
+ // this too, is meaningful only if one file is selected or if all the files
+ // have the same mimetype !
+ QString mime = panel->func->getVFile(item)->vfile_getMime();
+ // check if all the list have the same mimetype
+ for ( unsigned int i = 1; i < items.size(); ++i ) {
+ if ( panel->func->getVFile(( *items.at( i ) )) ->vfile_getMime() != mime ) {
+ mime = QString::null;
+ break;
+ }
+ }
+ if ( !mime.isEmpty() ) {
+ offers = KServiceTypeProfile::offers( mime );
+ for ( unsigned int i = 0; i < offers.count(); ++i ) {
+ KService::Ptr service = offers[ i ].service();
+ if ( service->isValid() && service->type() == "Application" ) {
+ openWith.insertItem( service->name(), SERVICE_LIST_ID + i );
+ openWith.changeItem( SERVICE_LIST_ID + i, service->pixmap( KIcon::Small ), service->name() );
+ }
+ }
+ openWith.insertSeparator();
+ if ( vf->vfile_isDir() )
+ openWith.insertItem( krLoader->loadIcon( "konsole", KIcon::Small ), i18n( "Terminal" ), OPEN_TERM_ID );
+ openWith.insertItem( i18n( "Other..." ), CHOOSE_ID );
+ insertItem( QPixmap(), &openWith, OPEN_WITH_ID );
+ changeItem( OPEN_WITH_ID, i18n( "Open With" ) );
+ insertSeparator();
+ }
+
+ // --------------- user actions
+ insertItem( i18n("User Actions"), new UserActionPopupMenu( panel->func->files()->vfs_getFile( item->name() ).url() ) );
+ _items.setAutoDelete( true );
+ for ( KrViewItemList::Iterator it = items.begin(); it != items.end(); ++it ) {
+ vfile *file = panel->func->files()->vfs_search(((*it)->name()));
+ KURL url = file->vfile_getUrl();
+ _items.append( new KFileItem( url, file->vfile_getMime(), file->vfile_getMode() ) );
+ }
+
+#ifdef __LIBKONQ__
+ // -------------- konqueror menu
+ actions = new KActionCollection(this);
+ konqMenu = new KonqPopupMenu( KonqBookmarkManager::self(), _items, panel->func->files()->vfs_getOrigin(), *actions, 0, this,
+ KonqPopupMenu::NoFlags, KParts::BrowserExtension::DefaultPopupItems );
+ insertItem( QPixmap(), konqMenu, KONQ_MENU_ID );
+ changeItem( KONQ_MENU_ID, i18n( "Konqueror Menu" ) );
+#endif
+
+ // ------------- 'create new' submenu
+ addCreateNewMenu();
+ insertSeparator();
+
+ // ---------- COPY
+ insertItem( i18n( "Copy..." ), COPY_ID );
+ if ( panel->func->files() ->vfs_isWritable() ) {
+ // ------- MOVE
+ insertItem( i18n( "Move..." ), MOVE_ID );
+ // ------- RENAME - only one file
+ if ( !multipleSelections )
+ insertItem( i18n( "Rename" ), RENAME_ID );
+
+ // -------- MOVE TO TRASH
+ KConfigGroupSaver saver(krConfig, "General");
+ bool trash = krConfig->readBoolEntry( "Move To Trash", _MoveToTrash );
+ if( trash )
+ insertItem( i18n( "Move to Trash" ), TRASH_ID );
+ // -------- DELETE
+ insertItem( i18n( "Delete" ), DELETE_ID );
+ // -------- SHRED - only one file
+ if ( panel->func->files() ->vfs_getType() == vfs::NORMAL &&
+ !vf->vfile_isDir() && !multipleSelections )
+ insertItem( i18n( "Shred" ), SHRED_ID );
+ }
+
+ // ---------- link handling
+ // create new shortcut or redirect links - only on local directories:
+ if ( panel->func->files() ->vfs_getType() == vfs::NORMAL ) {
+ insertSeparator();
+ linkPopup.insertItem( i18n( "New Symlink..." ), NEW_SYMLINK_ID );
+ linkPopup.insertItem( i18n( "New Hardlink..." ), NEW_LINK_ID );
+ if ( panel->func->getVFile(item)->vfile_isSymLink() )
+ linkPopup.insertItem( i18n( "Redirect Link..." ), REDIRECT_LINK_ID);
+ insertItem( QPixmap(), &linkPopup, LINK_HANDLING_ID );
+ changeItem( LINK_HANDLING_ID, i18n( "Link Handling" ) );
+ }
+ insertSeparator();
+
+ // ---------- calculate space
+ if ( panel->func->files() ->vfs_getType() == vfs::NORMAL && ( vf->vfile_isDir() || multipleSelections ) )
+ krCalculate->plug( this );
+
+ // ---------- mount/umount/eject
+ if ( panel->func->files() ->vfs_getType() == vfs::NORMAL && vf->vfile_isDir() && !multipleSelections ) {
+ if ( krMtMan.getStatus( panel->func->files() ->vfs_getFile( item->name() ).path( -1 ) ) == KMountMan::MOUNTED )
+ insertItem( i18n( "Unmount" ), UNMOUNT_ID );
+ else if ( krMtMan.getStatus( panel->func->files() ->vfs_getFile( item->name() ).path( -1 ) ) == KMountMan::NOT_MOUNTED )
+ insertItem( i18n( "Mount" ), MOUNT_ID );
+ if ( krMtMan.ejectable( panel->func->files() ->vfs_getFile( item->name() ).path( -1 ) ) )
+ insertItem( i18n( "Eject" ), EJECT_ID );
+ }
+
+ // --------- send by mail
+ if ( Krusader::supportedTools().contains( "MAIL" ) && !vf->vfile_isDir() ) {
+ insertItem( i18n( "Send by Email" ), SEND_BY_EMAIL_ID );
+ }
+
+ // --------- synchronize
+ if ( panel->view->numSelected() ) {
+ insertItem( i18n( "Synchronize Selected Files..." ), SYNC_SELECTED_ID );
+ }
+
+ // --------- copy/paste
+ insertSeparator();
+ insertItem( i18n( "Copy to Clipboard" ), COPY_CLIP_ID );
+ if ( panel->func->files() ->vfs_isWritable() )
+ {
+ insertItem( i18n( "Cut to Clipboard" ), MOVE_CLIP_ID );
+ insertItem( i18n( "Paste from Clipboard" ), PASTE_CLIP_ID );
+ }
+ insertSeparator();
+
+ // --------- properties
+ krProperties->plug( this );
+}
+
+KrPopupMenu::~KrPopupMenu() {
+ if (actions) delete actions;
+#ifdef __LIBKONQ__
+ if (konqMenu) delete konqMenu;
+#endif
+}
+
+void KrPopupMenu::addEmptyMenuEntries() {
+ insertItem( i18n( "Paste from Clipboard" ), PASTE_CLIP_ID );
+}
+
+void KrPopupMenu::addCreateNewMenu() {
+ createNewPopup.insertItem( krLoader->loadIcon( "folder", KIcon::Small ), i18n("Folder..."), MKDIR_ID);
+ createNewPopup.insertItem( krLoader->loadIcon( "txt", KIcon::Small ), i18n("Text File..."), NEW_TEXT_FILE_ID);
+
+ insertItem( QPixmap(), &createNewPopup, CREATE_NEW_ID);
+ changeItem( CREATE_NEW_ID, i18n( "Create New" ) );
+
+}
+
+void KrPopupMenu::performAction(int id) {
+ KURL u;
+ KURL::List lst;
+
+ switch ( id ) {
+ case - 1 : // the user clicked outside of the menu
+ return ;
+ case OPEN_TAB_ID :
+ // assuming only 1 file is selected (otherwise we won't get here)
+ ( ACTIVE_PANEL == LEFT_PANEL ? LEFT_MNG : RIGHT_MNG )->
+ slotNewTab( panel->func->files()->vfs_getFile( item->name() ).url() );
+ break;
+ case OPEN_ID :
+ for ( KrViewItemList::Iterator it = items.begin(); it != items.end(); ++it ) {
+ u = panel->func->files()->vfs_getFile( ( *it ) ->name() );
+ KRun::runURL( u, panel->func->getVFile(item)->vfile_getMime() );
+ }
+ break;
+ case COPY_ID :
+ panel->func->copyFiles();
+ break;
+ case MOVE_ID :
+ panel->func->moveFiles();
+ break;
+ case RENAME_ID :
+ SLOTS->rename();
+ break;
+ case TRASH_ID :
+ panel->func->deleteFiles( false );
+ break;
+ case DELETE_ID :
+ panel->func->deleteFiles( true );
+ break;
+ case EJECT_ID :
+ KMountMan::eject( panel->func->files() ->vfs_getFile( item->name() ).path( -1 ) );
+ break;
+ case SHRED_ID :
+ if ( KMessageBox::warningContinueCancel( krApp,
+ i18n("<qt>Do you really want to shred <b>%1</b>? Once shred, the file is gone forever!</qt>").arg(item->name()),
+ QString::null, KStdGuiItem::cont(), "Shred" ) == KMessageBox::Continue )
+ KShred::shred( panel->func->files() ->vfs_getFile( item->name() ).path( -1 ) );
+ break;
+ case OPEN_KONQ_ID :
+ kapp->startServiceByDesktopName( "konqueror", panel->func->files() ->vfs_getFile( item->name() ).url() );
+ break;
+ case CHOOSE_ID : // open-with dialog
+ u = panel->func->files() ->vfs_getFile( item->name() );
+ lst.append( u );
+ KRun::displayOpenWithDialog( lst );
+ break;
+ case MOUNT_ID :
+ krMtMan.mount( panel->func->files() ->vfs_getFile( item->name() ).path( -1 ) );
+ break;
+ case NEW_LINK_ID :
+ panel->func->krlink( false );
+ break;
+ case NEW_SYMLINK_ID :
+ panel->func->krlink( true );
+ break;
+ case REDIRECT_LINK_ID :
+ panel->func->redirectLink();
+ break;
+ case UNMOUNT_ID :
+ krMtMan.unmount( panel->func->files() ->vfs_getFile( item->name() ).path( -1 ) );
+ break;
+ case COPY_CLIP_ID :
+ panel->func->copyToClipboard();
+ break;
+ case MOVE_CLIP_ID :
+ panel->func->copyToClipboard( true );
+ break;
+ case PASTE_CLIP_ID :
+ panel->func->pasteFromClipboard();
+ break;
+ case SEND_BY_EMAIL_ID :
+ SLOTS->sendFileByEmail( panel->func->files() ->vfs_getFile( item->name() ).url() );
+ break;
+ case MKDIR_ID :
+ SLOTS->mkdir();
+ break;
+ case NEW_TEXT_FILE_ID:
+ SLOTS->editDlg();
+ break;
+ case SYNC_SELECTED_ID :
+ {
+ QStringList selectedNames;
+ for ( KrViewItemList::Iterator it = items.begin(); it != items.end(); ++it )
+ selectedNames.append( ( *it ) ->name() );
+ if( panel->otherPanel->view->numSelected() ) {
+ KrViewItemList otherItems;
+ panel->otherPanel->view->getSelectedKrViewItems( &otherItems );
+
+ for ( KrViewItemList::Iterator it2 = otherItems.begin(); it2 != otherItems.end(); ++it2 ) {
+ QString name = ( *it2 ) ->name();
+ if( !selectedNames.contains( name ) )
+ selectedNames.append( name );
+ }
+ }
+ SLOTS->slotSynchronizeDirs( selectedNames );
+ }
+ break;
+ case OPEN_TERM_ID :
+ QString save = getcwd( 0, 0 );
+ chdir( panel->func->files() ->vfs_getFile( item->name() ).path( -1 ).local8Bit() );
+ KProcess proc;
+ {
+ KConfigGroupSaver saver(krConfig, "General");
+ QString term = krConfig->readEntry( "Terminal", _Terminal );
+ proc << KrServices::separateArgs( term );
+ if ( !panel->func->getVFile(item)->vfile_isDir() ) proc << "-e" << item->name();
+ if ( term.contains( "konsole" ) ) { /* KDE 3.2 bug (konsole is killed by pressing Ctrl+C) */
+ /* Please remove the patch if the bug is corrected */
+ proc << "&";
+ proc.setUseShell( true );
+ }
+ if ( !proc.start( KProcess::DontCare ) )
+ KMessageBox::sorry( krApp, i18n( "Can't open \"%1\"" ).arg(term) );
+ } // group-saver is blown out of scope here
+ chdir( save.local8Bit() );
+ break;
+ }
+
+ // check if something from the open-with-offered-services was selected
+ if ( id >= SERVICE_LIST_ID ) {
+ QStringList names;
+ panel->getSelectedNames( &names );
+ KRun::run( *( offers[ id - SERVICE_LIST_ID ].service() ),
+ *( panel->func->files() ->vfs_getFiles( &names ) ) );
+ }
+}
+
+#include "krpopupmenu.moc"
diff --git a/krusader/Panel/krpopupmenu.h b/krusader/Panel/krpopupmenu.h
new file mode 100644
index 0000000..13157b4
--- /dev/null
+++ b/krusader/Panel/krpopupmenu.h
@@ -0,0 +1,77 @@
+#ifndef KRPOPUPMENU_H
+#define KRPOPUPMENU_H
+
+#include <kpopupmenu.h>
+#include <kurl.h>
+#include <kuserprofile.h>
+#include "listpanel.h"
+#include "krpreviewpopup.h"
+#include "../UserAction/useractionpopupmenu.h"
+#ifdef __LIBKONQ__
+#include <konq_popupmenu.h>
+#include <konqbookmarkmanager.h>
+#endif
+
+// should be renamed to KrContextMenu or similar
+class KrPopupMenu : public KPopupMenu {
+ Q_OBJECT
+public:
+ static void run(const QPoint &pos, ListPanel *panel);
+
+protected:
+ KrPopupMenu(ListPanel *thePanel, QWidget *parent=0);
+ ~KrPopupMenu();
+ void performAction(int id);
+ void addEmptyMenuEntries(); // adds the choices for a menu without selected items
+ void addCreateNewMenu(); // adds a "create new" submenu
+
+ enum ID {
+ OPEN_ID,
+ OPEN_WITH_ID,
+ OPEN_KONQ_ID,
+ OPEN_TERM_ID,
+ OPEN_TAB_ID,
+ PREVIEW_ID,
+ KONQ_MENU_ID,
+ CHOOSE_ID,
+ DELETE_ID,
+ COPY_ID,
+ MOVE_ID,
+ RENAME_ID,
+ PROPERTIES_ID,
+ MOUNT_ID,
+ UNMOUNT_ID,
+ TRASH_ID,
+ SHRED_ID,
+ NEW_LINK_ID,
+ NEW_SYMLINK_ID,
+ REDIRECT_LINK_ID,
+ SYNC_SELECTED_ID,
+ SEND_BY_EMAIL_ID,
+ LINK_HANDLING_ID,
+ EJECT_ID,
+ COPY_CLIP_ID,
+ MOVE_CLIP_ID,
+ PASTE_CLIP_ID,
+ MKDIR_ID,
+ NEW_TEXT_FILE_ID,
+ CREATE_NEW_ID,
+ SERVICE_LIST_ID // ALWAYS KEEP THIS ONE LAST!!!
+ };
+
+private:
+ ListPanel *panel;
+ bool empty, multipleSelections;
+ KPopupMenu openWith, linkPopup, createNewPopup;
+ KrPreviewPopup preview;
+ KActionCollection *actions;
+ KrViewItemList items; // list of selected items
+ KrViewItem *item; // the (first) selected item
+ KFileItemList _items;
+ QValueList<KServiceOffer> offers;
+#ifdef __LIBKONQ__
+ KonqPopupMenu *konqMenu;
+#endif
+};
+
+#endif
diff --git a/krusader/Panel/krpreviewpopup.cpp b/krusader/Panel/krpreviewpopup.cpp
new file mode 100644
index 0000000..53f4afd
--- /dev/null
+++ b/krusader/Panel/krpreviewpopup.cpp
@@ -0,0 +1,68 @@
+/***************************************************************************
+ krpreviewpopup.cpp - description
+ -------------------
+ begin : Sun Dec 29 2002
+ copyright : (C) 2002 by Shie Erlich & Rafi Yanai
+ web site : http://krusader.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <kio/previewjob.h>
+#include "krpreviewpopup.h"
+#include <kdebug.h>
+#include <klocale.h>
+#include <keditcl.h>
+#include "../KViewer/krviewer.h"
+#include "../krusader.h"
+
+KrPreviewPopup::KrPreviewPopup(): id(1),noPreview(true){
+ connect(this,SIGNAL(activated(int)),this,SLOT(view(int)));
+}
+
+void KrPreviewPopup::setUrls(const KURL::List* urls){
+ //insertItem(i18n("Configure preview"),0);
+ insertItem(i18n("Preview not available"),0);
+
+ KIO::PreviewJob* pjob;
+ QStringList plugins = KIO::PreviewJob::availablePlugins();
+
+ for( unsigned int i=0; i< urls->count(); ++i){
+ KFileItem* kfi = new KFileItem(KFileItem::Unknown,KFileItem::Unknown,*(urls->at(i)));
+ files.append(kfi);
+ }
+
+ pjob = new KIO::PreviewJob(files,200,200,200,1,true,true,0);
+ connect(pjob,SIGNAL(gotPreview(const KFileItem*,const QPixmap&)),
+ this,SLOT(addPreview(const KFileItem*,const QPixmap&)));
+}
+
+KrPreviewPopup::~KrPreviewPopup(){}
+
+void KrPreviewPopup::addPreview(const KFileItem* file,const QPixmap& preview){
+ if(noPreview){
+ removeItem(0);
+ noPreview = false;
+ }
+ insertItem(preview,id);
+ insertItem(file->text(),id++);
+ insertSeparator();
+ availablePreviews.append(file->url());
+}
+
+void KrPreviewPopup::view(int id){
+ if( id==0 ) return;
+ else {
+ KURL url = *(availablePreviews.at(id-1));
+ KrViewer::view(url);
+ }
+}
+
+#include "krpreviewpopup.moc"
diff --git a/krusader/Panel/krpreviewpopup.h b/krusader/Panel/krpreviewpopup.h
new file mode 100644
index 0000000..91b852c
--- /dev/null
+++ b/krusader/Panel/krpreviewpopup.h
@@ -0,0 +1,48 @@
+/***************************************************************************
+ krpreviewpopup.h - description
+ -------------------
+ begin : Sun Dec 29 2002
+ copyright : (C) 2002 by Shie Erlich & Rafi Yanai
+ web site : http://krusader.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KRPREVIEWPOPUP_H
+#define KRPREVIEWPOPUP_H
+
+#include <qpopupmenu.h>
+#include <qpixmap.h>
+#include <kfileitem.h>
+#include <kurl.h>
+
+/**
+ *@author Shie Erlich & Rafi Yanai
+ */
+
+class KrPreviewPopup : public QPopupMenu {
+ Q_OBJECT
+public:
+ KrPreviewPopup();
+ ~KrPreviewPopup();
+
+ void setUrls(const KURL::List* urls);
+public slots:
+ void addPreview(const KFileItem* file,const QPixmap& preview);
+ void view(int id);
+
+protected:
+ KFileItemList files;
+ int id;
+ bool noPreview;
+ KURL::List availablePreviews;
+};
+
+#endif
diff --git a/krusader/Panel/krselectionmode.cpp b/krusader/Panel/krselectionmode.cpp
new file mode 100644
index 0000000..02d95b1
--- /dev/null
+++ b/krusader/Panel/krselectionmode.cpp
@@ -0,0 +1,61 @@
+#include "krselectionmode.h"
+#include "../krusader.h"
+#include "../defaults.h"
+
+static KrSelectionMode *__currentSelectionMode = 0; // uninitiated, at first
+
+
+KonqSelectionMode konqSelectionMode;
+OriginalSelectionMode originalSelectionMode;
+TCSelectionMode tcSelectionMode;
+UserSelectionMode userSelectionMode;
+
+KrSelectionMode* KrSelectionMode::getSelectionHandler()
+{
+ if (__currentSelectionMode) { // don't check krConfig every time
+ return __currentSelectionMode;
+ } else { // nothing yet, set the correct one
+ krConfig->setGroup( "Look&Feel" );
+ QString mode = krConfig->readEntry("Mouse Selection", "");
+ switch (mode.toInt()) {
+ case 0:
+ __currentSelectionMode = &originalSelectionMode;
+ break;
+ case 1:
+ __currentSelectionMode = &konqSelectionMode;
+ break;
+ case 2:
+ __currentSelectionMode = &tcSelectionMode;
+ break;
+ case 3:
+ __currentSelectionMode = &userSelectionMode;
+ userSelectionMode.init();
+ break;
+ default:
+ break;
+ }
+ // init and return
+ __currentSelectionMode->init();
+ return __currentSelectionMode;
+ }
+}
+
+void KrSelectionMode::resetSelectionHandler() {
+ __currentSelectionMode = 0;
+}
+
+void UserSelectionMode::init() {
+ krConfig->setGroup("Custom Selection Mode");
+ _useQTSelection = krConfig->readBoolEntry("QT Selection", _QtSelection);
+ _leftButtonSelects = krConfig->readBoolEntry("Left Selects", _LeftSelects);
+ _leftButtonPreservesSelection = krConfig->readBoolEntry("Left Preserves", _LeftPreserves);
+ _shiftCtrlLeftButtonSelects = krConfig->readBoolEntry("ShiftCtrl Left Selects", _ShiftCtrlLeft);
+ _rightButtonSelects = krConfig->readBoolEntry("Right Selects", _RightSelects);
+ _rightButtonPreservesSelection = krConfig->readBoolEntry("Right Preserves", _RightPreserves);
+ _shiftCtrlRightButtonSelects = krConfig->readBoolEntry("ShiftCtrl Right Selects", _ShiftCtrlRight);
+ _spaceMovesDown = krConfig->readBoolEntry("Space Moves Down", _SpaceMovesDown);
+ _spaceCalculatesDiskSpace = krConfig->readBoolEntry("Space Calc Space", _SpaceCalcSpace);
+ _insertMovesDown = krConfig->readBoolEntry("Insert Moves Down", _InsertMovesDown);
+ _showContextMenu = (krConfig->readBoolEntry("Immediate Context Menu", _ImmediateContextMenu) ? -1 : 500);
+}
+
diff --git a/krusader/Panel/krselectionmode.h b/krusader/Panel/krselectionmode.h
new file mode 100644
index 0000000..4f9de2e
--- /dev/null
+++ b/krusader/Panel/krselectionmode.h
@@ -0,0 +1,97 @@
+#ifndef KR_SELECTION_MODE_H
+#define KR_SELECTION_MODE_H
+
+/**
+ Every selection mode inherits this class, and has to implement init().
+ Usage:
+ KrSelectionMode::getSelectionHandler()->whateverFunctionYouNeed()
+
+ \note You can call KrSelectionMode::resetSelectionHandler() if you want the
+ selection mode to be re-read. This is useful after a configuration where you
+ changed the selection mode. calling resetSelectionHandler() will cause the next
+ call to getSelectionHandler() to (possibly) select a different mode.
+*/
+class KrSelectionMode {
+public:
+ static KrSelectionMode * getSelectionHandler();
+ static void resetSelectionHandler();
+
+ virtual void init() = 0; // everyone must implement this in order to be a selection mode
+ inline bool useQTSelection() { return _useQTSelection; }
+ inline bool spaceMovesDown() { return _spaceMovesDown; }
+ inline bool insertMovesDown() { return _insertMovesDown; }
+ inline bool spaceCalculatesDiskSpace() { return _spaceCalculatesDiskSpace; }
+ inline bool rightButtonSelects() { return _rightButtonSelects; }
+ inline bool leftButtonSelects() { return _leftButtonSelects; }
+ inline bool rightButtonPreservesSelection() { return _rightButtonPreservesSelection; }
+ inline bool leftButtonPreservesSelection() { return _leftButtonPreservesSelection; }
+ inline bool shiftCtrlRightButtonSelects() { return _shiftCtrlRightButtonSelects; }
+ inline bool shiftCtrlLeftButtonSelects() { return _shiftCtrlLeftButtonSelects; }
+ inline int showContextMenu() { return _showContextMenu; } // 0: no, -1: yes, n>0: after n milliseconds
+
+ virtual ~KrSelectionMode() {}
+
+protected:
+ bool _useQTSelection, _spaceMovesDown, _insertMovesDown, _spaceCalculatesDiskSpace;
+ bool _rightButtonSelects, _leftButtonSelects, _rightButtonPreservesSelection;
+ bool _leftButtonPreservesSelection, _shiftCtrlRightButtonSelects, _shiftCtrlLeftButtonSelects;
+ int _showContextMenu;
+};
+
+class KonqSelectionMode : public KrSelectionMode {
+public:
+ void init() {
+ _useQTSelection = true;
+ _spaceMovesDown = false;
+ _insertMovesDown = true;
+ _spaceCalculatesDiskSpace = false;
+ _rightButtonSelects = true;
+ _leftButtonSelects = true;
+ _rightButtonPreservesSelection = false;
+ _leftButtonPreservesSelection = false;
+ _shiftCtrlRightButtonSelects = false;
+ _shiftCtrlLeftButtonSelects = false;
+ _showContextMenu = -1;
+ }
+};
+
+class OriginalSelectionMode : public KrSelectionMode {
+public:
+ void init() {
+ _useQTSelection = false;
+ _spaceMovesDown = true;
+ _insertMovesDown = true;
+ _spaceCalculatesDiskSpace = true;
+ _rightButtonSelects = true;
+ _leftButtonSelects = true;
+ _rightButtonPreservesSelection = false;
+ _leftButtonPreservesSelection = false;
+ _shiftCtrlRightButtonSelects = false;
+ _shiftCtrlLeftButtonSelects = false;
+ _showContextMenu = -1;
+ }
+};
+
+class TCSelectionMode : public KrSelectionMode {
+public:
+ void init() {
+ _useQTSelection = false;
+ _spaceMovesDown = false;
+ _insertMovesDown = true;
+ _spaceCalculatesDiskSpace = true;
+ _rightButtonSelects = true;
+ _leftButtonSelects = false;
+ _rightButtonPreservesSelection = true;
+ _leftButtonPreservesSelection = false;
+ _shiftCtrlRightButtonSelects = false;
+ _shiftCtrlLeftButtonSelects = true;
+ _showContextMenu = 500;
+ }
+};
+
+class UserSelectionMode: public KrSelectionMode {
+public:
+ void init();
+};
+
+#endif // KR_SELECTION_MODE_H
diff --git a/krusader/Panel/krview.cpp b/krusader/Panel/krview.cpp
new file mode 100644
index 0000000..c44bcb6
--- /dev/null
+++ b/krusader/Panel/krview.cpp
@@ -0,0 +1,332 @@
+/***************************************************************************
+ krview.cpp
+ -------------------
+ copyright : (C) 2000-2002 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+ Description
+***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+#include "krview.h"
+#include "../kicons.h"
+#include "../defaults.h"
+#include "../VFS/krpermhandler.h"
+#include "krviewitem.h"
+#include <qnamespace.h>
+#include <qpixmapcache.h>
+#include <qdir.h>
+#include <qbitmap.h>
+#include <kmimetype.h>
+#include <klocale.h>
+#include <kinputdialog.h>
+
+
+#define VF getVfile()
+
+
+// ----------------------------- operator
+KrViewOperator::KrViewOperator(KrView *view, QWidget *widget): _view(view), _widget(widget) {
+}
+
+KrViewOperator::~KrViewOperator() {
+}
+
+void KrViewOperator::startDrag() {
+ QStringList items;
+ _view->getSelectedItems( &items );
+ if ( items.empty() )
+ return ; // don't drag an empty thing
+ QPixmap px;
+ if ( items.count() > 1 )
+ px = FL_LOADICON( "queue" ); // how much are we dragging
+ else
+ px = _view->getCurrentKrViewItem() ->icon();
+ emit letsDrag( items, px );
+}
+
+// ----------------------------- krview
+
+KrView::KrView( KConfig *cfg ) : _config( cfg ), _widget(0), _nameToMakeCurrent( QString::null ), _nameToMakeCurrentIfAdded( QString::null ),
+_numSelected( 0 ), _count( 0 ), _numDirs( 0 ), _countSize( 0 ), _selectedSize( 0 ), _properties(0), _focused( false ), _nameInKConfig(QString::null) {
+}
+
+KrView::~KrView() {
+ if (_properties)
+ qFatal("A class inheriting KrView didn't delete _properties!");
+ if (_operator)
+ qFatal("A class inheriting KrView didn't delete _operator!");
+}
+
+void KrView::init() {
+ // sanity checks:
+ if (_nameInKConfig.isEmpty())
+ qFatal("_nameInKConfig must be set during construction of KrView inheritors");
+ if (!_widget)
+ qFatal("_widget must be set during construction of KrView inheritors");
+ // ok, continue
+ initProperties();
+ initOperator();
+ setup();
+}
+
+QPixmap KrView::getIcon( vfile *vf /*, KRListItem::cmpColor color*/ ) {
+ //krConfig->setGroup("Advanced");
+ //////////////////////////////
+ QPixmap icon;
+ QString icon_name = vf->vfile_getIcon();
+ //QPixmapCache::setCacheLimit( krConfig->readNumEntry("Icon Cache Size",_IconCacheSize) );
+
+ if( icon_name.isNull() )
+ icon_name="";
+
+ // first try the cache
+ if ( !QPixmapCache::find( icon_name, icon ) ) {
+ icon = FL_LOADICON( icon_name );
+ // insert it into the cache
+ QPixmapCache::insert( icon_name, icon );
+ }
+ // if it's a symlink - add an arrow overlay
+ if ( vf->vfile_isSymLink() ) {
+ QPixmap link( link_xpm );
+ bitBlt ( &icon, 0, icon.height() - 11, &link, 0, 21, 10, 11, Qt::CopyROP, false );
+ icon.setMask( icon.createHeuristicMask( false ) );
+ }
+
+ return icon;
+}
+
+/**
+ * this function ADDs a list of selected item names into 'names'.
+ * it assumes the list is ready and doesn't initialize it, or clears it
+ */
+void KrView::getItemsByMask( QString mask, QStringList* names, bool dirs, bool files ) {
+ for ( KrViewItem * it = getFirst(); it != 0; it = getNext( it ) ) {
+ if ( ( it->name() == ".." ) || !QDir::match( mask, it->name() ) ) continue;
+ // if we got here, than the item fits the mask
+ if ( it->getVfile()->vfile_isDir() && !dirs ) continue; // do we need to skip folders?
+ if ( !it->getVfile()->vfile_isDir() && !files ) continue; // do we need to skip files
+ names->append( it->name() );
+ }
+}
+
+/**
+ * this function ADDs a list of selected item names into 'names'.
+ * it assumes the list is ready and doesn't initialize it, or clears it
+ */
+void KrView::getSelectedItems( QStringList *names ) {
+ for ( KrViewItem * it = getFirst(); it != 0; it = getNext( it ) )
+ if ( it->isSelected() && ( it->name() != ".." ) ) names->append( it->name() );
+
+ // if all else fails, take the current item
+ QString item = getCurrentItem();
+ if ( names->empty() && item!=QString::null && item!=".." ) names->append( item );
+}
+
+void KrView::getSelectedKrViewItems( KrViewItemList *items ) {
+ for ( KrViewItem * it = getFirst(); it != 0; it = getNext( it ) )
+ if ( it->isSelected() && ( it->name() != ".." ) ) items->append( it );
+
+ // if all else fails, take the current item
+ QString item = getCurrentItem();
+ if ( items->empty() && item!=QString::null && item!=".." ) items->append( getCurrentKrViewItem() );
+}
+
+QString KrView::statistics() {
+ _countSize = _numSelected = _selectedSize = 0;
+
+ for ( KrViewItem * it = getFirst(); it != 0; it = getNext( it ) ){
+ if ( it->isSelected() ) {
+ ++_numSelected;
+ _selectedSize += it->getVfile()->vfile_getSize();
+ }
+ if (it->getVfile()->vfile_getSize() > 0)
+ _countSize += it->getVfile()->vfile_getSize();
+ }
+ QString tmp = QString(i18n("%1 out of %2, %3 (%4) out of %5 (%6)"))
+ .arg( _numSelected ).arg( _count ).arg( KIO::convertSize( _selectedSize ) )
+ .arg( KRpermHandler::parseSize(_selectedSize) )
+ .arg( KIO::convertSize( _countSize ) ).arg( KRpermHandler::parseSize(_countSize) );
+ // notify if we're running a filtered view
+ if (filter() != KrViewProperties::All)
+ tmp = ">> [ " + filterMask().nameFilter() + " ] "+tmp;
+ return tmp;
+}
+
+void KrView::changeSelection( const KRQuery& filter, bool select, bool includeDirs ) {
+ KConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ bool markDirs = _config->readBoolEntry( "Mark Dirs", _MarkDirs ) || includeDirs;
+
+ KrViewItem *temp = getCurrentKrViewItem();
+ for ( KrViewItem * it = getFirst(); it != 0; it = getNext( it ) ) {
+ if ( it->name() == ".." ) continue;
+ if ( it->getVfile()->vfile_isDir() && !markDirs ) continue;
+
+ vfile * file = it->getMutableVfile(); // filter::match calls getMimetype which isn't const
+ if( file == 0 ) continue;
+
+ if( filter.match( file ) ) {
+ // we're increasing/decreasing the number of selected files
+ if ( select ) {
+ if ( !it->isSelected() ) {
+ ++_numSelected;
+ _selectedSize += it->getVfile()->vfile_getSize();
+ }
+ } else {
+ if ( it->isSelected() ) {
+ --_numSelected;
+ _selectedSize -= it->getVfile()->vfile_getSize();
+ }
+ }
+ it->setSelected( select );
+ }
+ }
+ updateView();
+ makeItemVisible( temp );
+}
+
+void KrView::invertSelection() {
+ KConfigGroupSaver grpSvr( _config, "Look&Feel" /*nameInKConfig()*/ );
+ bool markDirs = _config->readBoolEntry( "Mark Dirs", _MarkDirs );
+
+ KrViewItem *temp = getCurrentKrViewItem();
+ for ( KrViewItem * it = getFirst(); it != 0; it = getNext( it ) ) {
+ if ( it->name() == ".." ) continue;
+ if ( it->getVfile()->vfile_isDir() && !markDirs && !it->isSelected() ) continue;
+ if ( it->isSelected() ) {
+ --_numSelected;
+ _selectedSize -= it->getVfile()->vfile_getSize();
+ } else {
+ ++_numSelected;
+ _selectedSize += it->getVfile()->vfile_getSize();
+ }
+ it->setSelected( !it->isSelected() );
+ }
+ updateView();
+ makeItemVisible( temp );
+}
+
+QString KrView::firstUnmarkedBelowCurrent() {
+ KrViewItem * iterator = getNext( getCurrentKrViewItem() );
+ while ( iterator && iterator->isSelected() )
+ iterator = getNext( iterator );
+ if ( !iterator ) {
+ iterator = getPrev( getCurrentKrViewItem() );
+ while ( iterator && iterator->isSelected() )
+ iterator = getPrev( iterator );
+ }
+ if ( !iterator ) return QString::null;
+ return iterator->name();
+}
+
+void KrView::delItem(const QString &name) {
+ KrViewItem * it = _dict[ name ];
+ if ( !it ) {
+ krOut << "got signal deletedVfile(" << name << ") but can't find KrViewItem" << endl;
+ return;
+ }
+ if (!preDelItem(it)) return; // do not delete this after all
+
+ // remove from dict
+ if (it->VF->vfile_isDir()) {
+ --_numDirs;
+ } else {
+ _countSize -= it->VF->vfile_getSize();
+ }
+ --_count;
+ _dict.remove( name );
+ delete it;
+ op()->emitSelectionChanged();
+}
+
+KrViewItem *KrView::addItem( vfile *vf ) {
+ KrViewItem *item = preAddItem(vf);
+ if (!item) return 0; // don't add it after all
+
+ // add to dictionary
+ _dict.insert( vf->vfile_getName(), item );
+ if ( vf->vfile_isDir() )
+ ++_numDirs;
+ else _countSize += vf->vfile_getSize();
+ ++_count;
+
+ if (item->name() == nameToMakeCurrent() ) {
+ setCurrentItem(item->name()); // dictionary based - quick
+ makeItemVisible( item );
+ }
+ if (item->name() == nameToMakeCurrentIfAdded() ) {
+ setCurrentItem(item->name());
+ setNameToMakeCurrentIfAdded(QString::null);
+ makeItemVisible( item );
+ }
+
+
+ op()->emitSelectionChanged();
+ return item;
+}
+
+void KrView::updateItem(vfile *vf) {
+ // since we're deleting the item, make sure we keep
+ // it's properties first and repair it later
+ KrViewItem * it = _dict[ vf->vfile_getName() ];
+ if ( !it ) {
+ krOut << "got signal updatedVfile(" << vf->vfile_getName() << ") but can't find KrViewItem" << endl;
+ } else {
+ bool selected = it->isSelected();
+ bool current = ( getCurrentKrViewItem() == it );
+ delItem( vf->vfile_getName() );
+ KrViewItem *updatedItem = addItem( vf );
+ // restore settings
+ ( _dict[ vf->vfile_getName() ] ) ->setSelected( selected );
+ if ( current ) {
+ setCurrentItem( vf->vfile_getName() );
+ makeItemVisible( updatedItem );
+ }
+ }
+ op()->emitSelectionChanged();
+}
+
+void KrView::clear() {
+ _count = _numSelected = _numDirs = _selectedSize = _countSize = 0;
+ _dict.clear();
+}
+
+// good old dialog box
+void KrView::renameCurrentItem() {
+ QString newName, fileName;
+
+ KrViewItem *it = getCurrentKrViewItem();
+ if ( it ) fileName = it->name();
+ else return ; // quit if no current item available
+
+ // don't allow anyone to rename ..
+ if ( fileName == ".." ) return ;
+
+ bool ok = false;
+ newName = KInputDialog::getText( i18n( "Rename" ), i18n( "Rename " ) + fileName + i18n( " to:" ),
+ fileName, &ok, krApp );
+ // if the user canceled - quit
+ if ( !ok || newName == fileName )
+ return ;
+ op()->emitRenameItem(it->name(), newName);
+}
+
diff --git a/krusader/Panel/krview.h b/krusader/Panel/krview.h
new file mode 100644
index 0000000..a7c0932
--- /dev/null
+++ b/krusader/Panel/krview.h
@@ -0,0 +1,245 @@
+/***************************************************************************
+ krview.h
+ -------------------
+ copyright : (C) 2000-2002 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef KRVIEW_H
+#define KRVIEW_H
+
+#include <qpixmap.h>
+#include <qvariant.h>
+#include <qdict.h>
+#include "../krusader.h"
+#include "../VFS/vfile.h"
+#include "../VFS/vfs.h"
+#include "../VFS/krquery.h"
+
+#include <kdebug.h>
+
+class KrView;
+class KrViewItem;
+typedef QValueList<KrViewItem*> KrViewItemList;
+
+// KrViewProperties
+// This class is an interface class between KrView and KrViewItem
+// In order for KrViewItem to be as independant as possible, KrView holds
+// an instance of this class, and fills it with the correct data. A reference
+// to this should be given to each KrViewItem, which then queries it for
+// information regarding how things should be displayed in the current view.
+//
+// Every property that the item needs to know about the view must be here!
+class KrViewProperties {
+public:
+ enum SortSpec { Name=0x1, Ext=0x2, Size=0x4, Type=0x8, Modified=0x10, Permissions=0x20,
+ KrPermissions=0x40, Owner=0x80, Group=0x100, Descending=0x200,
+ DirsFirst=0x400, IgnoreCase=0x800, AlwaysSortDirsByName=0x1000 };
+ enum FilterSpec { Dirs=0x1, Files=0x2, All=0x3, Custom=0x4, ApplyToDirs=0x8 };
+
+ bool displayIcons; // true if icons should be displayed in this view
+ SortSpec sortMode; // sort specifications
+ FilterSpec filter; // what items to show (all, custom, exec)
+ KRQuery filterMask; // what items to show (*.cpp, *.h etc)
+ bool localeAwareCompareIsCaseSensitive; // mostly, it is not! depends on LC_COLLATE
+ bool humanReadableSize; // display size as KB, MB or just as a long number
+ QStringList atomicExtensions; // list of strings, which will be treated as one extension. Must start with a dot.
+};
+
+// operator can handle two ways of doing things:
+// 1. if the view is a widget (inherits krview and klistview for example)
+// 2. if the view HAS A widget (a krview-son has a member of klistview)
+// this is done by specifying the view and the widget in the constructor,
+// even if they are actually the same object (specify it twice in that case)
+class KrViewOperator: public QObject {
+ Q_OBJECT
+public:
+ KrViewOperator(KrView *view, QWidget *widget);
+ ~KrViewOperator();
+ KrView *view() const { return _view; }
+ QWidget *widget() const { return _widget; }
+ void startDrag();
+
+ void emitSelectionChanged() { emit selectionChanged(); }
+ void emitGotDrop(QDropEvent *e) { emit gotDrop(e); }
+ void emitLetsDrag(QStringList items, QPixmap icon ) { emit letsDrag(items, icon); }
+ void emitItemDescription(QString &desc) { emit itemDescription(desc); }
+ void emitContextMenu(const QPoint &point) { emit contextMenu(point); }
+ void emitEmptyContextMenu(const QPoint &point) { emit emptyContextMenu(point); }
+ void emitRenameItem(const QString &oldName, const QString &newName) { emit renameItem(oldName, newName); }
+ void emitExecuted( QString &name ) { emit executed(name); }
+ void emitNeedFocus() { emit needFocus(); }
+
+signals:
+ void selectionChanged();
+ void gotDrop( QDropEvent *e );
+ void letsDrag( QStringList items, QPixmap icon );
+ void itemDescription( QString &desc );
+ void contextMenu( const QPoint &point );
+ void emptyContextMenu( const QPoint& point );
+ void renameItem( const QString &oldName, const QString &newName );
+ void executed( QString &name );
+ void needFocus();
+
+
+protected:
+ // never delete those
+ KrView *_view;
+ QWidget *_widget;
+};
+
+/****************************************************************************
+ * READ THIS FIRST: Using the view
+ *
+ * You always hold a pointer to KrView, thus you can only use functions declared
+ * in this class. If you need something else, either this class is missing something
+ * or you are ;-) Using a true name (like dynamic_cast<KrDetailedViewItem*>) should be
+ * needed only when doing new(), or connect() - see example in listpanel.cpp
+ *
+ * The functions you'd usually want:
+ * 1) getSelectedItems - returns all selected items, or (if none) the current item.
+ * it never returns anything which includes the "..", and thus can return an empty list!
+ * 2) getSelectedKrViewItems - the same as (1), but returns a QValueList with KrViewItems
+ * 3) getCurrentItem, setCurrentItem - work with QString
+ * 4) getFirst, getNext, getPrev, getCurrentKrViewItem - all work with KrViewItems, and
+ * used to iterate through a list of items. note that getNext and getPrev accept a pointer
+ * to the current item (used in detailedview for safe iterating), thus your loop should be:
+ * for (KrViewItem *it = view->getFirst(); it!=0; it = view->getNext(it)) { blah; }
+ * 5) nameToMakeCurrent(), setNameToMakeCurrent() - work with QString
+ *
+ * IMPORTANT NOTE: every one who subclasses this must call initProperties() in the constructor !!!
+ */
+class KrView {
+friend class KrViewItem;
+public:
+ // instantiating a new view
+ // 1. new KrView
+ // 2. view->init()
+ // notes: constructor does as little as possible, setup() does the rest. esp, note that
+ // if you need something from operator or properties, move it into setup()
+ virtual void init();
+
+protected:
+ virtual void initProperties() { qFatal("Please implement your own initProperties() method"); }
+ virtual void initOperator() { qFatal("Please implement your own initOperator() method"); }
+ virtual void setup() { qFatal("Please implement your own setup() method"); }
+
+ ///////////////////////////////////////////////////////
+ // Every view must implement the following functions //
+ ///////////////////////////////////////////////////////
+public:
+ virtual KrViewItem *getFirst() = 0;
+ virtual KrViewItem *getLast() = 0;
+ virtual KrViewItem *getNext(KrViewItem *current) = 0;
+ virtual KrViewItem *getPrev(KrViewItem *current) = 0;
+ virtual KrViewItem *getCurrentKrViewItem() = 0;
+ virtual KrViewItem *getKrViewItemAt(const QPoint &vp) = 0;
+ virtual KrViewItem *findItemByName(const QString &name) = 0;
+ virtual void addItems(vfs* v, bool addUpDir = true) = 0; // kill me, kill me now
+ virtual QString getCurrentItem() const = 0;
+ virtual void setCurrentItem(const QString& name) = 0;
+ virtual void makeItemVisible(const KrViewItem *item) = 0;
+ virtual void clear();
+ virtual void updateView() = 0;
+ virtual void updateItem(KrViewItem* item) = 0;
+ virtual void sort() = 0;
+ virtual void saveSettings() = 0;
+ virtual void restoreSettings() = 0;
+ virtual void prepareForActive() { _focused = true; }
+ virtual void prepareForPassive() { _focused = false; }
+ virtual void renameCurrentItem(); // Rename current item. returns immediatly
+ virtual QString nameInKConfig() const { return _nameInKConfig; }
+
+protected:
+ virtual KrViewItem *preAddItem(vfile *vf) = 0;
+ virtual bool preDelItem(KrViewItem *item) = 0;
+
+public:
+ //////////////////////////////////////////////////////
+ // the following functions are already implemented, //
+ // and normally - should NOT be re-implemented. //
+ //////////////////////////////////////////////////////
+ virtual KrViewItem *addItem(vfile *vf);
+ virtual void updateItem(vfile *vf);
+ virtual void delItem(const QString &name);
+ virtual uint numSelected() const { return _numSelected; }
+ virtual KIO::filesize_t selectedSize() const { return _selectedSize; }
+ virtual uint numFiles() const { return _count-_numDirs; }
+ virtual uint numDirs() const { return _numDirs; }
+ virtual uint count() const { return _count; }
+ virtual KIO::filesize_t countSize() const { return _countSize; }
+ virtual void getSelectedItems(QStringList* names);
+ virtual void getItemsByMask(QString mask, QStringList* names, bool dirs = true, bool files = true);
+ virtual void getSelectedKrViewItems(KrViewItemList *items);
+ virtual void selectAllIncludingDirs() { changeSelection( KRQuery( "*" ), true, true); }
+ virtual void select( const KRQuery& filter = KRQuery( "*" ) ) { changeSelection(filter, true); }
+ virtual void unselect(const KRQuery& filter = KRQuery( "*" ) ) { changeSelection(filter, false); }
+ virtual void invertSelection();
+ virtual QString nameToMakeCurrent() const { return _nameToMakeCurrent; }
+ virtual void setNameToMakeCurrent(const QString name) { _nameToMakeCurrent = name; }
+ virtual QString nameToMakeCurrentIfAdded() const { return _nameToMakeCurrentIfAdded; }
+ virtual void setNameToMakeCurrentIfAdded(const QString name) { _nameToMakeCurrentIfAdded = name; }
+ virtual QString firstUnmarkedBelowCurrent();
+ virtual QString statistics();
+ virtual const KrViewProperties* properties() const { return _properties; }
+ virtual KrViewOperator* op() const { return _operator; }
+
+ /////////////////////////////////////////////////////////////
+ // the following functions have a default and minimalistic //
+ // implementation, and may be re-implemented if needed //
+ /////////////////////////////////////////////////////////////
+ virtual void setSortMode(KrViewProperties::SortSpec mode) { _properties->sortMode = mode; }
+ virtual KrViewProperties::SortSpec sortMode() const { return _properties->sortMode; }
+ virtual void setFilter(KrViewProperties::FilterSpec filter) { _properties->filter = filter; }
+ virtual KrViewProperties::FilterSpec filter() const { return _properties->filter; }
+ virtual void setFilterMask( KRQuery mask ) { _properties->filterMask = mask; }
+ virtual const KRQuery& filterMask() const { return _properties->filterMask; }
+ inline QWidget *widget() { return _widget; }
+ inline void setWidget(QWidget *w) { _widget = w; }
+
+ // todo: what about selection modes ???
+ virtual ~KrView();
+protected:
+ KrView(KConfig *cfg = krConfig);
+ static QPixmap getIcon(vfile *vf);
+ void changeSelection(const KRQuery& filter, bool select, bool includeDirs = false);
+
+
+protected:
+ KConfig *_config;
+ QWidget *_widget;
+ QString _nameToMakeCurrent;
+ QString _nameToMakeCurrentIfAdded;
+ uint _numSelected, _count, _numDirs;
+ KIO::filesize_t _countSize, _selectedSize;
+ bool _left;
+ KrViewProperties *_properties;
+ KrViewOperator *_operator;
+ QDict<KrViewItem> _dict;
+ bool _focused;
+ QString _nameInKConfig;
+};
+
+#endif /* KRVIEW_H */
diff --git a/krusader/Panel/krviewitem.cpp b/krusader/Panel/krviewitem.cpp
new file mode 100644
index 0000000..28500d4
--- /dev/null
+++ b/krusader/Panel/krviewitem.cpp
@@ -0,0 +1,105 @@
+#include "krviewitem.h"
+#include "../VFS/krpermhandler.h"
+#include <klocale.h>
+#include <kmimetype.h>
+#include <sys/types.h>
+#include <time.h>
+#include <stdlib.h>
+
+#define PROPS static_cast<const KrViewProperties*>(_viewProperties)
+
+QString atomicExtensions[] = {
+ ".tar.gz",
+ ".tar.bz2",
+ ".moc.cpp"
+};
+
+KrViewItem::KrViewItem(vfile *vf, const KrViewProperties* properties):
+ _vf(vf), dummyVfile(false), _viewProperties(properties), _hasExtension(false), _hidden(false), _extension("") {
+ if (vf) {
+ // check if the file has an extension
+ const QString& vfName = vf->vfile_getName();
+ int loc = vfName.findRev('.');
+ if (loc>0) { // avoid mishandling of .bashrc and friend
+ // check if it has one of the predefined 'atomic extensions'
+ for (QStringList::const_iterator i = PROPS->atomicExtensions.begin(); i != PROPS->atomicExtensions.end(); ++i) {
+ if (vfName.endsWith(*i)){
+ loc = vfName.length() - (*i).length();
+ break;
+ }
+ }
+ _name = vfName.left(loc);
+ _extension = vfName.mid(loc+1);
+ _hasExtension=true;
+ }
+
+ if( vfName.startsWith(".") )
+ _hidden = true;
+ }
+}
+
+const QString& KrViewItem::name(bool withExtension) const {
+ if (!withExtension && _hasExtension) return _name;
+ else return _vf->vfile_getName();
+}
+
+QString KrViewItem::description() const {
+ if (dummyVfile) return i18n("Climb up the directory tree");
+ // else is implied
+ QString text = _vf->vfile_getName();
+ QString comment = KMimeType::mimeType(_vf->vfile_getMime())->comment(text, false);
+ QString myLinkDest = _vf->vfile_getSymDest();
+ KIO::filesize_t mySize = _vf->vfile_getSize();
+
+ QString text2 = text.copy();
+ mode_t m_fileMode = _vf->vfile_getMode();
+
+ if (_vf->vfile_isSymLink() ){
+ QString tmp;
+ if ( comment.isEmpty() ) tmp = i18n ( "Symbolic Link" ) ;
+ else if( _vf->vfile_getMime() == "Broken Link !" ) tmp = i18n("(broken link !)");
+ else tmp = i18n("%1 (Link)").arg(comment);
+
+ text += "->";
+ text += myLinkDest;
+ text += " ";
+ text += tmp;
+ } else if ( S_ISREG( m_fileMode ) ){
+ text = QString("%1 (%2)").arg(text2).arg( PROPS->humanReadableSize ?
+ KRpermHandler::parseSize(_vf->vfile_getSize()) : KIO::convertSize( mySize ) );
+ text += " ";
+ text += comment;
+ } else if ( S_ISDIR ( m_fileMode ) ){
+ text += "/ ";
+ text += comment;
+ } else {
+ text += " ";
+ text += comment;
+ }
+ return text;
+}
+
+QString KrViewItem::dateTime() const {
+ // convert the time_t to struct tm
+ time_t time = _vf->vfile_getTime_t();
+ struct tm* t=localtime((time_t *)&time);
+
+ QDateTime tmp(QDate(t->tm_year+1900, t->tm_mon+1, t->tm_mday), QTime(t->tm_hour, t->tm_min));
+ return KGlobal::locale()->formatDateTime(tmp);
+}
+
+QPixmap KrViewItem::icon() {
+#if 0
+ QPixmap *p;
+
+ // This is bad - very bad. the function must return a valid reference,
+ // This is an interface flow - shie please fix it with a function that return QPixmap*
+ // this way we can return 0 - and do our error checking...
+
+ // shie answers: why? what's the difference? if we return an empty pixmap, others can use it as it
+ // is, without worrying or needing to do error checking. empty pixmap displays nothing
+#endif
+ if (dummyVfile || !_viewProperties->displayIcons)
+ return QPixmap();
+ else return KrView::getIcon(_vf);
+}
diff --git a/krusader/Panel/krviewitem.h b/krusader/Panel/krviewitem.h
new file mode 100644
index 0000000..2294b28
--- /dev/null
+++ b/krusader/Panel/krviewitem.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+ krviewitem.h
+ -------------------
+ copyright : (C) 2000-2002 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+ Description
+***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+#ifndef KRVIEWITEM_H
+#define KRVIEWITEM_H
+
+#include <sys/types.h>
+#include <kio/global.h>
+#include "../VFS/vfile.h"
+#include "krview.h"
+
+class QString;
+class QPixmap;
+
+class KrViewItem {
+ friend class KrView;
+
+public:
+ virtual const QString& name(bool withExtension=true) const;
+ virtual inline bool hasExtension() const { return _hasExtension; }
+ virtual inline const QString& extension() const { return _extension; }
+ virtual QString dateTime() const;
+ virtual QString description() const;
+ virtual bool isSelected() const = 0;
+ virtual void setSelected( bool s ) = 0;
+ virtual QPixmap icon();
+
+ KrViewItem(vfile *vf, const KrViewProperties* properties);
+ virtual ~KrViewItem() { if (dummyVfile) delete _vf; }
+
+ // DON'T USE THOSE OUTSIDE THE VIEWS!!!
+ inline const vfile* getVfile() const { return _vf; }
+ inline vfile* getMutableVfile() { return _vf; }
+ inline bool isDummy() const { return dummyVfile; }
+ inline bool isHidden() const { return _hidden; }
+
+protected:
+ // used INTERNALLY when calculation of dir size changes the displayed size of the item
+ inline void setSize(KIO::filesize_t size) { _vf->vfile_setSize(size); }
+
+ vfile* _vf; // each view item holds a pointer to a corrosponding vfile for fast access
+ bool dummyVfile; // used in case our item represents the ".." (updir) item
+ const KrViewProperties* _viewProperties;
+ bool _hasExtension;
+ bool _hidden;
+ QString _name;
+ QString _extension;
+};
+
+#endif
diff --git a/krusader/Panel/listpanel.cpp b/krusader/Panel/listpanel.cpp
new file mode 100644
index 0000000..5972eaf
--- /dev/null
+++ b/krusader/Panel/listpanel.cpp
@@ -0,0 +1,1115 @@
+/***************************************************************************
+ listpanel.cpp
+ -------------------
+copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+e-mail : krusader@users.sourceforge.net
+web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+Description
+***************************************************************************
+
+A
+
+db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+#include <unistd.h>
+#include <sys/param.h>
+// QT includes
+#include <qbitmap.h>
+#include <qwhatsthis.h>
+#include <qstringlist.h>
+#include <qstrlist.h>
+#include <kurldrag.h>
+#include <qheader.h>
+#include <qtimer.h>
+#include <qregexp.h>
+#include <qsplitter.h>
+// KDE includes
+#include <kpopupmenu.h>
+#include <kprocess.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kmimetype.h>
+#include <kurl.h>
+#include <ktrader.h>
+#include <kopenwith.h>
+#include <kuserprofile.h>
+#include <kiconloader.h>
+#include <kcursor.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kglobalsettings.h>
+#include <qtooltip.h>
+#include <kdeversion.h>
+#include <qimage.h>
+#include <qtabbar.h>
+#include <kdebug.h>
+#include <kurlrequester.h>
+#include <kurl.h>
+#include <kmountpoint.h>
+
+// Krusader includes
+#include "../krusader.h"
+#include "../krslots.h"
+#include "panelfunc.h"
+#include "../kicons.h"
+#include "../VFS/krpermhandler.h"
+#include "listpanel.h"
+#include "../krusaderview.h"
+#include "../panelmanager.h"
+#include "../defaults.h"
+#include "../resources.h"
+#include "../MountMan/kmountman.h"
+#include "../Dialogs/krdialogs.h"
+#include "../BookMan/krbookmarkbutton.h"
+#include "../Dialogs/krspwidgets.h"
+#include "../Dialogs/krspecialwidgets.h"
+#include "../GUI/kcmdline.h"
+#include "../Dialogs/percentalsplitter.h"
+#include "krdetailedview.h"
+#include "krbriefview.h"
+#include "krpreviewpopup.h"
+#include "../GUI/dirhistorybutton.h"
+#include "../GUI/dirhistoryqueue.h"
+#include "../GUI/mediabutton.h"
+#include "../GUI/syncbrowsebutton.h"
+#include "../krservices.h"
+#include "panelpopup.h"
+#include "../UserAction/useractionpopupmenu.h"
+#include "../Dialogs/popularurls.h"
+#include "krpopupmenu.h"
+
+#ifdef __LIBKONQ__
+#include <konq_popupmenu.h>
+#include <konqbookmarkmanager.h>
+#endif
+
+typedef QValueList<KServiceOffer> OfferList;
+
+#define URL(X) KURL::fromPathOrURL(X)
+
+/////////////////////////////////////////////////////
+// The list panel constructor //
+/////////////////////////////////////////////////////
+ListPanel::ListPanel( QString typeIn, QWidget *parent, bool &left, const char *name ) :
+ QWidget( parent, name ), panelType( typeIn ), colorMask( 255 ), compareMode( false ), currDragItem( 0 ), statsAgent( 0 ),
+ quickSearch( 0 ), cdRootButton( 0 ), cdUpButton( 0 ), popupBtn(0), popup(0),inlineRefreshJob(0), _left( left ) {
+
+ func = new ListPanelFunc( this );
+ setAcceptDrops( true );
+ layout = new QGridLayout( this, 3, 3 );
+
+ mediaButton = new MediaButton( this, "mediaButton" );
+ connect( mediaButton, SIGNAL( pressed() ), this, SLOT( slotFocusOnMe() ) );
+ connect( mediaButton, SIGNAL( openUrl( const KURL& ) ), func, SLOT( openUrl( const KURL& ) ) );
+
+ status = new KrSqueezedTextLabel( this );
+ krConfig->setGroup( "Look&Feel" );
+ status->setFont( krConfig->readFontEntry( "Filelist Font", _FilelistFont ) );
+ status->setBackgroundMode( PaletteBackground );
+ status->setFrameStyle( QFrame::Box | QFrame::Raised );
+ status->setLineWidth( 1 ); // a nice 3D touch :-)
+ status->setText( "" ); // needed for initialization code!
+ status->enableDrops( true );
+ int sheight = QFontMetrics( status->font() ).height() + 4;
+ status->setMaximumHeight( sheight );
+ QWhatsThis::add
+ ( status, i18n( "The statusbar displays information about the FILESYSTEM "
+ "which holds your current directory: Total size, free space, "
+ "type of filesystem, etc." ) );
+ connect( status, SIGNAL( clicked() ), this, SLOT( slotFocusOnMe() ) );
+ connect( status, SIGNAL( dropped( QDropEvent *) ), this, SLOT( handleDropOnStatus(QDropEvent *) ) );
+
+ // ... create the history button
+ dirHistoryQueue = new DirHistoryQueue( this );
+ historyButton = new DirHistoryButton( dirHistoryQueue, this, "historyButton" );
+ connect( historyButton, SIGNAL( pressed() ), this, SLOT( slotFocusOnMe() ) );
+ connect( historyButton, SIGNAL( openUrl( const KURL& ) ), func, SLOT( openUrl( const KURL& ) ) );
+
+ bookmarksButton = new KrBookmarkButton(this);
+ connect( bookmarksButton, SIGNAL( pressed() ), this, SLOT( slotFocusOnMe() ) );
+ connect( bookmarksButton, SIGNAL( openUrl( const KURL& ) ), func, SLOT( openUrl( const KURL& ) ) );
+ QWhatsThis::add
+ ( bookmarksButton, i18n( "Open menu with bookmarks. You can also add "
+ "current location to the list, edit bookmarks "
+ "or add subfolder to the list." ) );
+
+ QHBoxLayout *totalsLayout = new QHBoxLayout;
+ totals = new KrSqueezedTextLabel( this );
+ krConfig->setGroup( "Look&Feel" );
+ totals->setFont( krConfig->readFontEntry( "Filelist Font", _FilelistFont ) );
+ totals->setFrameStyle( QFrame::Box | QFrame::Raised );
+ totals->setBackgroundMode( PaletteBackground );
+ totals->setLineWidth( 1 ); // a nice 3D touch :-)
+ totals->setMaximumHeight( sheight );
+ totals->enableDrops( true );
+ QWhatsThis::add
+ ( totals, i18n( "The totals bar shows how many files exist, "
+ "how many selected and the bytes math" ) );
+ connect( totals, SIGNAL( clicked() ), this, SLOT( slotFocusOnMe() ) );
+ connect( totals, SIGNAL( dropped( QDropEvent *) ), this, SLOT( handleDropOnTotals(QDropEvent *) ) );
+
+ // a cancel button for the inplace refresh mechanism
+ inlineRefreshCancelButton = new KPushButton(this);
+ inlineRefreshCancelButton->setFixedSize( 22, 20 );
+ inlineRefreshCancelButton->setPixmap(krLoader->loadIcon("cancel", KIcon::Toolbar, 16));
+ connect(inlineRefreshCancelButton, SIGNAL(clicked()), this, SLOT(inlineRefreshCancel()));
+
+ // a quick button to open the popup panel
+ popupBtn = new QToolButton( this, "popupbtn" );
+ popupBtn->setFixedSize( 22, 20 );
+ popupBtn->setPixmap(krLoader->loadIcon("1uparrow", KIcon::Toolbar, 16));
+ connect(popupBtn, SIGNAL(clicked()), this, SLOT(togglePanelPopup()));
+ QToolTip::add( popupBtn, i18n( "Open the popup panel" ) );
+ totalsLayout->addWidget(totals);
+ totalsLayout->addWidget(inlineRefreshCancelButton); inlineRefreshCancelButton->hide();
+ totalsLayout->addWidget(popupBtn);
+
+ quickSearch = new KrQuickSearch( this );
+ krConfig->setGroup( "Look&Feel" );
+ quickSearch->setFont( krConfig->readFontEntry( "Filelist Font", _FilelistFont ) );
+ quickSearch->setFrameStyle( QFrame::Box | QFrame::Raised );
+ quickSearch->setLineWidth( 1 ); // a nice 3D touch :-)
+ quickSearch->setMaximumHeight( sheight );
+
+ QHBox * hbox = new QHBox( this );
+
+ // clear-origin button
+ bool clearButton = krConfig->readBoolEntry("Clear Location Bar Visible", _ClearLocation);
+ if (clearButton){
+ clearOrigin = new QToolButton(hbox, "clearorigin");
+ clearOrigin->setPixmap(krLoader->loadIcon("locationbar_erase", KIcon::Toolbar, 16));
+ QToolTip::add( clearOrigin, i18n( "Clear the location bar" ) );
+ }
+
+ QuickNavLineEdit *qnle = new QuickNavLineEdit(this);
+ origin = new KURLRequester( qnle, hbox );
+ QPixmap pixMap = origin->button() ->iconSet() ->pixmap( QIconSet::Small, QIconSet::Normal );
+ origin->button() ->setFixedSize( pixMap.width() + 4, pixMap.height() + 4 );
+ QWhatsThis::add
+ ( origin, i18n( "Use superb KDE file dialog to choose location. " ) );
+ origin->setShowLocalProtocol( false );
+ origin->lineEdit() ->setURLDropsEnabled( true );
+ origin->lineEdit() ->installEventFilter( this );
+ QWhatsThis::add
+ ( origin->lineEdit(), i18n( "Name of directory where you are. You can also "
+ "enter name of desired location to move there. "
+ "Use of Net protocols like ftp or fish is possible." ) );
+ origin->setMode( KFile::Directory | KFile::ExistingOnly );
+ connect( origin, SIGNAL( returnPressed( const QString& ) ), func, SLOT( openUrl( const QString& ) ) );
+ connect( origin, SIGNAL( returnPressed( const QString& ) ), this, SLOT( slotFocusOnMe() ) );
+ connect( origin, SIGNAL( urlSelected( const QString& ) ), func, SLOT( openUrl( const QString& ) ) );
+ connect( origin, SIGNAL( urlSelected( const QString& ) ), this, SLOT( slotFocusOnMe() ) );
+
+ // this is here on purpose, do not move up!
+ if (clearButton) {
+ clearOrigin->setFixedSize( 20, origin->button() ->height() );
+ connect(clearOrigin, SIGNAL(clicked()), origin->lineEdit(), SLOT(clear()));
+ connect(clearOrigin, SIGNAL(clicked()), origin->lineEdit(), SLOT(setFocus()));
+ }
+ //
+
+ cdOtherButton = new QToolButton( hbox, "cdOtherButton" );
+ cdOtherButton->setFixedSize( 20, origin->button() ->height() );
+ cdOtherButton->setText( i18n( "=" ) );
+ QToolTip::add( cdOtherButton, i18n( "Equal" ) );
+ connect( cdOtherButton, SIGNAL( clicked() ), this, SLOT( slotFocusAndCDOther() ) );
+
+ cdUpButton = new QToolButton( hbox, "cdUpButton" );
+ cdUpButton->setFixedSize( 20, origin->button() ->height() );
+ cdUpButton->setText( i18n( ".." ) );
+ QToolTip::add( cdUpButton, i18n( "Up" ) );
+ connect( cdUpButton, SIGNAL( clicked() ), this, SLOT( slotFocusAndCDup() ) );
+
+ cdHomeButton = new QToolButton( hbox, "cdHomeButton" );
+ cdHomeButton->setFixedSize( 20, origin->button() ->height() );
+ cdHomeButton->setText( i18n( "~" ) );
+ QToolTip::add( cdHomeButton, i18n( "Home" ) );
+ connect( cdHomeButton, SIGNAL( clicked() ), this, SLOT( slotFocusAndCDHome() ) );
+
+ cdRootButton = new QToolButton( hbox, "cdRootButton" );
+ cdRootButton->setFixedSize( 20, origin->button() ->height() );
+ cdRootButton->setText( i18n( "/" ) );
+ QToolTip::add( cdRootButton, i18n( "Root" ) );
+ connect( cdRootButton, SIGNAL( clicked() ), this, SLOT( slotFocusAndCDRoot() ) );
+
+ // ... creates the button for sync-browsing
+ syncBrowseButton = new SyncBrowseButton( hbox );
+
+ setPanelToolbar();
+
+ header = new QHeader( this );
+ header->hide();
+
+ // create a splitter to hold the view and the popup
+ splt = new PercentalSplitter(this);
+ splt->setChildrenCollapsible(true);
+ splt->setOrientation(QObject::Vertical);
+
+ createView();
+
+ // make sure that a focus/path change reflects in the command line and activePanel
+ connect( this, SIGNAL( cmdLineUpdate( QString ) ), SLOTS, SLOT( slotCurrentChanged( QString ) ) );
+ connect( this, SIGNAL( activePanelChanged( ListPanel * ) ), SLOTS, SLOT( slotSetActivePanel( ListPanel * ) ) );
+
+ // add a popup
+ popup = new PanelPopup(splt, left);
+ connect(popup, SIGNAL(selection(const KURL&)), SLOTS, SLOT(refresh(const KURL&)));
+ connect(popup, SIGNAL(hideMe()), this, SLOT(togglePanelPopup()));
+ popup->hide();
+
+ // finish the layout
+ layout->addMultiCellWidget( hbox, 0, 0, 0, 3 );
+ layout->addWidget( mediaButton, 1, 0 );
+ layout->addWidget( status, 1, 1 );
+ layout->addWidget( historyButton, 1, 2 );
+ layout->addWidget( bookmarksButton, 1, 3 );
+ layout->addMultiCellWidget( header, 2, 2, 0, 3 );
+ layout->addMultiCellWidget( splt, 3, 3, 0, 3 );
+ layout->addMultiCellWidget( quickSearch, 4, 4, 0, 3 );
+ quickSearch->hide();
+ layout->addMultiCellLayout( totalsLayout, 5, 5, 0, 3 );
+ //filter = ALL;
+}
+
+void ListPanel::createView()
+{
+ header->hide();
+ if( panelType == "Brief" )
+ {
+ view = new KrBriefView( header, splt, _left, krConfig );
+ view->init();
+
+ connect( dynamic_cast<KrBriefView*>( view ), SIGNAL( middleButtonClicked( KrViewItem * ) ), SLOTS, SLOT( newTab( KrViewItem * ) ) );
+ connect( dynamic_cast<KrBriefView*>( view ), SIGNAL( currentChanged( KrViewItem * ) ),
+ SLOTS, SLOT( updatePopupPanel( KrViewItem* ) ) );
+
+ // connect quicksearch
+ connect( quickSearch, SIGNAL( textChanged( const QString& ) ),
+ dynamic_cast<KrBriefView*>( view ), SLOT( quickSearch( const QString& ) ) );
+ connect( quickSearch, SIGNAL( otherMatching( const QString&, int ) ),
+ dynamic_cast<KrBriefView*>( view ), SLOT( quickSearch( const QString& , int ) ) );
+ connect( quickSearch, SIGNAL( stop( QKeyEvent* ) ),
+ dynamic_cast<KrBriefView*>( view ), SLOT( stopQuickSearch( QKeyEvent* ) ) );
+ connect( quickSearch, SIGNAL( process( QKeyEvent* ) ),
+ dynamic_cast<KrBriefView*>( view ), SLOT( handleQuickSearchEvent( QKeyEvent* ) ) );
+ } else { /* Detailed */
+ panelType = "Detailed";
+ view = new KrDetailedView( splt, _left, krConfig );
+ view->init();
+ connect( dynamic_cast<KrDetailedView*>( view ), SIGNAL( middleButtonClicked( KrViewItem * ) ), SLOTS, SLOT( newTab( KrViewItem * ) ) );
+ connect( dynamic_cast<KrDetailedView*>( view ), SIGNAL( currentChanged( KrViewItem * ) ),
+ SLOTS, SLOT( updatePopupPanel( KrViewItem * ) ) );
+ // connect quicksearch
+ connect( quickSearch, SIGNAL( textChanged( const QString& ) ),
+ dynamic_cast<KrDetailedView*>( view ), SLOT( quickSearch( const QString& ) ) );
+ connect( quickSearch, SIGNAL( otherMatching( const QString&, int ) ),
+ dynamic_cast<KrDetailedView*>( view ), SLOT( quickSearch( const QString& , int ) ) );
+ connect( quickSearch, SIGNAL( stop( QKeyEvent* ) ),
+ dynamic_cast<KrDetailedView*>( view ), SLOT( stopQuickSearch( QKeyEvent* ) ) );
+ connect( quickSearch, SIGNAL( process( QKeyEvent* ) ),
+ dynamic_cast<KrDetailedView*>( view ), SLOT( handleQuickSearchEvent( QKeyEvent* ) ) );
+ }
+
+ connect( view->op(), SIGNAL( renameItem( const QString &, const QString & ) ),
+ func, SLOT( rename( const QString &, const QString & ) ) );
+ connect( view->op(), SIGNAL( executed( QString& ) ), func, SLOT( execute( QString& ) ) );
+ connect( view->op(), SIGNAL( needFocus() ), this, SLOT( slotFocusOnMe() ) );
+ connect( view->op(), SIGNAL( selectionChanged() ), this, SLOT( slotUpdateTotals() ) );
+ connect( view->op(), SIGNAL( itemDescription( QString& ) ), krApp, SLOT( statusBarUpdate( QString& ) ) );
+ connect( view->op(), SIGNAL( contextMenu( const QPoint & ) ), this, SLOT( popRightClickMenu( const QPoint & ) ) );
+ connect( view->op(), SIGNAL( emptyContextMenu( const QPoint &) ),
+ this, SLOT( popEmptyRightClickMenu( const QPoint & ) ) );
+ connect( view->op(), SIGNAL( letsDrag( QStringList, QPixmap ) ), this, SLOT( startDragging( QStringList, QPixmap ) ) );
+ connect( view->op(), SIGNAL( gotDrop( QDropEvent * ) ), this, SLOT( handleDropOnView( QDropEvent * ) ) );
+}
+
+void ListPanel::changeType( const QString & type )
+{
+ if( panelType != type )
+ {
+ panelType = type;
+ delete view;
+ createView();
+
+ slotStartUpdate();
+
+ if( panelType == "Brief" )
+ dynamic_cast<KrBriefView*>( view )->show();
+ else /* Detailed */
+ dynamic_cast<KrDetailedView*>( view )->show();
+ }
+}
+
+ListPanel::~ListPanel() {
+ delete func;
+ delete view;
+ delete status;
+ delete bookmarksButton;
+ delete totals;
+ delete quickSearch;
+ delete origin;
+ delete cdRootButton;
+ delete cdHomeButton;
+ delete cdUpButton;
+ delete cdOtherButton;
+ delete syncBrowseButton;
+ delete layout;
+}
+
+int ListPanel::getProperties()
+{
+ int props = 0;
+ if( syncBrowseButton->state() == SYNCBROWSE_CD )
+ props |= PROP_SYNC_BUTTON_ON;
+ return props;
+}
+
+void ListPanel::setProperties( int prop )
+{
+ if( prop & PROP_SYNC_BUTTON_ON )
+ syncBrowseButton->setOn( true );
+ else
+ syncBrowseButton->setOn( false );
+}
+
+bool ListPanel::eventFilter ( QObject * watched, QEvent * e ) {
+ if( e->type() == QEvent::KeyPress && origin->lineEdit() == watched ) {
+ QKeyEvent *ke = (QKeyEvent *)e;
+
+ if( ( ke->key() == Key_Down ) && ( ke->state() == ControlButton ) ) {
+ slotFocusOnMe();
+ return true;
+ }
+ }
+ return false;
+}
+
+
+void ListPanel::togglePanelPopup() {
+ if (popup->isHidden()) {
+ if (popupSizes.count() > 0) {
+ dynamic_cast<QSplitter*>(popup->parent())->setSizes(popupSizes);
+ } else { // on the first time, resize to 50%
+ QValueList<int> lst;
+ lst << height()/2 << height()/2;
+ dynamic_cast<QSplitter*>(popup->parent())->setSizes(lst);
+ }
+
+ popup->show();
+ popupBtn->setPixmap(krLoader->loadIcon("1downarrow", KIcon::Toolbar, 16));
+ QToolTip::add( popupBtn, i18n( "Close the popup panel" ) );
+ } else {
+ popupSizes.clear();
+ popupSizes = dynamic_cast<QSplitter*>(popup->parent())->sizes();
+ popup->hide();
+ popupBtn->setPixmap(krLoader->loadIcon("1uparrow", KIcon::Toolbar, 16));
+ QToolTip::add( popupBtn, i18n( "Open the popup panel" ) );
+
+ QValueList<int> lst;
+ lst << height() << 0;
+ dynamic_cast<QSplitter*>(popup->parent())->setSizes(lst);
+ if( ACTIVE_PANEL )
+ ACTIVE_PANEL->slotFocusOnMe();
+ }
+}
+
+KURL ListPanel::virtualPath() const {
+ return func->files()->vfs_getOrigin();
+}
+
+QString ListPanel::realPath() const {
+ return _realPath.path();
+}
+
+
+void ListPanel::setPanelToolbar() {
+ krConfig->setGroup( "Look&Feel" );
+
+ bool panelToolBarVisible = krConfig->readBoolEntry( "Panel Toolbar visible", _PanelToolBar );
+
+ if ( panelToolBarVisible && ( krConfig->readBoolEntry( "Root Button Visible", _cdRoot ) ) )
+ cdRootButton->show();
+ else
+ cdRootButton->hide();
+
+ if ( panelToolBarVisible && ( krConfig->readBoolEntry( "Home Button Visible", _cdHome ) ) )
+ cdHomeButton->show();
+ else
+ cdHomeButton->hide();
+
+ if ( panelToolBarVisible && ( krConfig->readBoolEntry( "Up Button Visible", _cdUp ) ) )
+ cdUpButton->show();
+ else
+ cdUpButton->hide();
+
+ if ( panelToolBarVisible && ( krConfig->readBoolEntry( "Equal Button Visible", _cdOther ) ) )
+ cdOtherButton->show();
+ else
+ cdOtherButton->hide();
+
+ if ( !panelToolBarVisible || ( krConfig->readBoolEntry( "Open Button Visible", _Open ) ) )
+ origin->button() ->show();
+ else
+ origin->button() ->hide();
+
+ if ( panelToolBarVisible && ( krConfig->readBoolEntry( "SyncBrowse Button Visible", _syncBrowseButton ) ) )
+ syncBrowseButton->show();
+ else
+ syncBrowseButton->hide();
+}
+
+void ListPanel::slotUpdateTotals() {
+ totals->setText( view->statistics() );
+}
+
+void ListPanel::slotFocusAndCDOther() {
+ slotFocusOnMe();
+ func->openUrl( otherPanel->func->files() ->vfs_getOrigin() );
+
+}
+
+void ListPanel::slotFocusAndCDHome() {
+ slotFocusOnMe();
+ func->openUrl( QString( "~" ), QString::null );
+}
+
+void ListPanel::slotFocusAndCDup() {
+ slotFocusOnMe();
+ func->dirUp();
+}
+
+void ListPanel::slotFocusAndCDRoot() {
+ slotFocusOnMe();
+ func->openUrl( QString( "/" ), QString::null );
+}
+
+void ListPanel::select( KRQuery query, bool select) {
+ if ( !query.isNull() ) {
+ if ( select )
+ view->select( query );
+ else
+ view->unselect( query );
+ }
+}
+
+void ListPanel::select( bool select, bool all ) {
+ if ( all )
+ {
+ if ( select )
+ view->select( KRQuery( "*" ) );
+ else
+ view->unselect( KRQuery( "*" ) );
+ }
+ else {
+ KRQuery query = KRSpWidgets::getMask( ( select ? i18n( " Select Files " ) : i18n( " Unselect Files " ) ) );
+ // if the user canceled - quit
+ if ( query.isNull() )
+ return ;
+ if ( select )
+ view->select( query );
+ else
+ view->unselect( query );
+ }
+}
+
+void ListPanel::invertSelection() {
+ view->invertSelection();
+}
+
+void ListPanel::compareDirs() {
+ krConfig->setGroup( "Private" );
+ int compareMode = krConfig->readNumEntry( "Compare Mode", 0 );
+ krConfig->setGroup( "Look&Feel" );
+ bool selectDirs = krConfig->readBoolEntry( "Mark Dirs", false );
+
+ KrViewItem *item, *otherItem;
+
+ for( item = view->getFirst(); item != 0; item = view->getNext( item ) )
+ {
+ if( item->name() == ".." )
+ continue;
+
+ for( otherItem = otherPanel->view->getFirst(); otherItem != 0 && otherItem->name() != item->name() ;
+ otherItem = otherPanel->view->getNext( otherItem ) );
+
+ bool isSingle = ( otherItem == 0 ), isDifferent = false, isNewer = false;
+
+ if( func->getVFile(item)->vfile_isDir() && !selectDirs )
+ {
+ item->setSelected( false );
+ continue;
+ }
+
+ if( otherItem )
+ {
+ if( !func->getVFile(item)->vfile_isDir() )
+ isDifferent = ITEM2VFILE(otherPanel,otherItem)->vfile_getSize() != func->getVFile(item)->vfile_getSize();
+ isNewer = func->getVFile(item)->vfile_getTime_t() > ITEM2VFILE(otherPanel, otherItem)->vfile_getTime_t();
+ }
+
+ switch( compareMode )
+ {
+ case 0:
+ item->setSelected( isNewer || isSingle );
+ break;
+ case 1:
+ item->setSelected( isNewer );
+ break;
+ case 2:
+ item->setSelected( isSingle );
+ break;
+ case 3:
+ item->setSelected( isDifferent || isSingle );
+ break;
+ case 4:
+ item->setSelected( isDifferent );
+ break;
+ }
+ }
+
+ view->updateView();
+}
+
+void ListPanel::slotFocusOnMe() {
+ // give this VFS the focus (the path bar)
+ // we start by calling the KVFS function
+ krConfig->setGroup( "Look&Feel" );
+
+ // take care of the 'otherpanel'
+ QPalette q( otherPanel->status->palette() );
+ q.setColor( QColorGroup::Foreground, KGlobalSettings::textColor() );
+ q.setColor( QColorGroup::Background, KGlobalSettings::baseColor() );
+
+ otherPanel->status->setPalette( q );
+ otherPanel->totals->setPalette( q );
+ otherPanel->view->prepareForPassive();
+
+ // now, take care of this panel
+ QPalette p( status->palette() );
+ p.setColor( QColorGroup::Foreground, KGlobalSettings::highlightedTextColor() );
+ p.setColor( QColorGroup::Background, KGlobalSettings::highlightColor() );
+ status->setPalette( p );
+ totals->setPalette( p );
+
+ view->prepareForActive();
+ emit cmdLineUpdate( realPath() );
+ emit activePanelChanged( this );
+
+ func->refreshActions();
+
+ Krusader::actDetailedView->setEnabled( panelType != "Detailed" ); // enable/disable the detailed view action
+ Krusader::actBriefView->setEnabled( panelType != "Brief" ); // enable/disable the brief view action
+
+ if( panelType == "Brief" )
+ {
+ KrBriefView * v = dynamic_cast<KrBriefView *>( view );
+ if ( v )
+ v->refreshColors();
+ }
+ else /* detailed */
+ {
+ KrDetailedView * v = dynamic_cast<KrDetailedView *>( view );
+ if ( v )
+ v->refreshColors();
+ }
+
+ if( otherPanel->panelType == "Brief" )
+ {
+ KrBriefView * v = dynamic_cast<KrBriefView *>( otherPanel->view );
+ if ( v )
+ v->refreshColors();
+ }
+ else /* detailed */
+ {
+ KrDetailedView *v = dynamic_cast<KrDetailedView *>( otherPanel->view );
+ if ( v )
+ v->refreshColors();
+ }
+}
+
+// this is used to start the panel, AFTER setOther() has been used
+//////////////////////////////////////////////////////////////////
+void ListPanel::start( KURL url, bool immediate ) {
+ KURL virt;
+
+ virt = url;
+
+ if ( !virt.isValid() )
+ virt = URL("/");
+ if( virt.isLocalFile() ) _realPath = virt;
+ else _realPath = URL("/");
+
+ if( immediate )
+ func->immediateOpenUrl( virt );
+ else
+ func->openUrl( virt );
+
+ slotFocusOnMe();
+ setJumpBack( virt );
+}
+
+void ListPanel::slotStartUpdate() {
+ while ( func->inRefresh )
+ ; // wait until the last refresh finish
+ func->inRefresh = true; // make sure the next refresh wait for this one
+ if (inlineRefreshJob)
+ inlineRefreshListResult(0);
+
+ if( this == ACTIVE_PANEL ){
+ slotFocusOnMe();
+ }
+
+ setCursor( KCursor::workingCursor() );
+ view->clear();
+
+ if ( func->files() ->vfs_getType() == vfs::NORMAL )
+ _realPath = virtualPath();
+ this->origin->setURL( vfs::pathOrURL( virtualPath() ) );
+ emit pathChanged( this );
+ emit cmdLineUpdate( realPath() ); // update the command line
+
+ slotGetStats( virtualPath() );
+ slotUpdate();
+ if ( compareMode ) {
+ otherPanel->view->clear();
+ otherPanel->slotUpdate();
+ }
+ // return cursor to normal arrow
+ setCursor( KCursor::arrowCursor() );
+ slotUpdateTotals();
+ krApp->popularUrls->addUrl(virtualPath());
+}
+
+void ListPanel::slotUpdate() {
+ // if we are not at the root add the ".." entery
+ QString protocol = func->files() ->vfs_getOrigin().protocol();
+ bool isFtp = ( protocol == "ftp" || protocol == "smb" || protocol == "sftp" || protocol == "fish" );
+
+ QString origin = virtualPath().prettyURL(-1);
+ if ( origin.right( 1 ) != "/" && !( ( func->files() ->vfs_getType() == vfs::FTP ) && isFtp &&
+ origin.find( '/', origin.find( ":/" ) + 3 ) == -1 ) ) {
+ view->addItems( func->files() );
+ } else
+ view->addItems( func->files(), false );
+
+ func->inRefresh = false;
+}
+
+
+void ListPanel::slotGetStats( const KURL& url ) {
+ if ( !url.isLocalFile() ) {
+ status->setText( i18n( "No space information on non-local filesystems" ) );
+ return ;
+ }
+
+ // check for special filesystems;
+ QString path = url.path(); // must be local url
+ if ( path.left(4) == "/dev") {
+ status->setText(i18n( "No space information on [dev]" ));
+ return;
+ }
+#if defined(BSD)
+ if ( path.left( 5 ) == "/procfs" ) { // /procfs is a special case - no volume information
+ status->setText(i18n( "No space information on [procfs]" ));
+ return;
+ }
+#else
+ if ( path.left( 5 ) == "/proc" ) { // /proc is a special case - no volume information
+ status->setText(i18n( "No space information on [proc]" ));
+ return;
+ }
+#endif
+
+ status->setText( i18n( "Mt.Man: working ..." ) );
+ statsAgent = KDiskFreeSp::findUsageInfo( path );
+ connect( statsAgent, SIGNAL( foundMountPoint( const QString &, unsigned long, unsigned long, unsigned long ) ),
+ this, SLOT( gotStats( const QString &, unsigned long, unsigned long, unsigned long ) ) );
+}
+
+void ListPanel::gotStats( const QString &mountPoint, unsigned long kBSize,
+ unsigned long, unsigned long kBAvail ) {
+ int perc = 0;
+ if (kBSize != 0) { // make sure that if totalsize==0, then perc=0
+ perc = (int)(((float)kBAvail / (float)kBSize)*100.0);
+ }
+ // mount point information - find it in the list first
+ KMountPoint::List lst = KMountPoint::currentMountPoints();
+ QString fstype = i18n("unknown");
+ for (KMountPoint::List::iterator it = lst.begin(); it != lst.end(); ++it) {
+ if ((*it)->mountPoint() == mountPoint) {
+ fstype = (*it)->mountType();
+ break;
+ }
+ }
+
+ QString stats = i18n( "%1 free out of %2 (%3%) on %4 [ (%5) ]" )
+ .arg( KIO::convertSizeFromKB( kBAvail ) )
+ .arg( KIO::convertSizeFromKB( kBSize ) ).arg( perc )
+ .arg( mountPoint ).arg( fstype );
+ status->setText( stats );
+}
+
+void ListPanel::handleDropOnTotals( QDropEvent *e ) {
+ handleDropOnView( e, totals );
+}
+
+void ListPanel::handleDropOnStatus( QDropEvent *e ) {
+ handleDropOnView( e, status );
+}
+
+void ListPanel::handleDropOnView( QDropEvent *e, QWidget *widget ) {
+ // if copyToPanel is true, then we call a simple vfs_addfiles
+ bool copyToDirInPanel = false;
+ bool dragFromOtherPanel = false;
+ bool dragFromThisPanel = false;
+ bool isWritable = func->files() ->vfs_isWritable();
+
+ vfs* tempFiles = func->files();
+ vfile *file;
+ KrViewItem *i = 0;
+ if( widget == 0 )
+ {
+ i = view->getKrViewItemAt( e->pos() );
+ widget = this;
+ }
+
+ if ( e->source() == otherPanel )
+ dragFromOtherPanel = true;
+ if ( e->source() == this )
+ dragFromThisPanel = true;
+
+ if ( i ) {
+ file = func->files() ->vfs_search( i->name() );
+
+ if ( !file ) { // trying to drop on the ".."
+ copyToDirInPanel = true;
+ } else {
+ if ( file->vfile_isDir() ) {
+ copyToDirInPanel = true;
+ isWritable = file->vfile_isWriteable();
+ if ( isWritable ) {
+ // keep the folder_open icon until we're finished, do it only
+ // if the folder is writeable, to avoid flicker
+ }
+ } else
+ if ( e->source() == this )
+ return ; // no dragging onto ourselves
+ }
+ } else // if dragged from this panel onto an empty spot in the panel...
+ if ( dragFromThisPanel ) { // leave!
+ e->ignore();
+ return ;
+ }
+
+ if ( !isWritable && getuid() != 0 ) {
+ e->ignore();
+ KMessageBox::sorry( 0, i18n( "Can't drop here, no write permissions." ) );
+ return ;
+ }
+ //////////////////////////////////////////////////////////////////////////////
+ // decode the data
+ KURL::List URLs;
+ if ( !KURLDrag::decode( e, URLs ) ) {
+ e->ignore(); // not for us to handle!
+ return ;
+ }
+
+ bool isLocal = true;
+ for( unsigned u = 0; u != URLs.count(); u++ )
+ if( !URLs[ u ].isLocalFile() ) {
+ isLocal = false;
+ break;
+ }
+
+ KIO::CopyJob::CopyMode mode = KIO::CopyJob::Copy;
+
+ // the KURL::List is finished, let's go
+ // --> display the COPY/MOVE/LINK menu
+ QPopupMenu popup( this );
+ popup.insertItem( i18n( "Copy Here" ), 1 );
+ if ( func->files() ->vfs_isWritable() )
+ popup.insertItem( i18n( "Move Here" ), 2 );
+ if ( func->files() ->vfs_getType() == vfs::NORMAL &&
+ isLocal )
+ popup.insertItem( i18n( "Link Here" ), 3 );
+ popup.insertItem( i18n( "Cancel" ), 4 );
+ QPoint tmp = widget->mapToGlobal( e->pos() );
+ int result = popup.exec( tmp );
+ switch ( result ) {
+ case 1 :
+ mode = KIO::CopyJob::Copy;
+ break;
+ case 2 :
+ mode = KIO::CopyJob::Move;
+ break;
+ case 3 :
+ mode = KIO::CopyJob::Link;
+ break;
+ case - 1 : // user pressed outside the menu
+ case 4:
+ return ; // cancel was pressed;
+ }
+
+ QString dir = "";
+ if ( copyToDirInPanel ) {
+ dir = i->name();
+ }
+ QWidget *notify = ( !e->source() ? 0 : e->source() );
+ tempFiles->vfs_addFiles( &URLs, mode, notify, dir );
+}
+
+void ListPanel::startDragging( QStringList names, QPixmap px ) {
+ KURL::List * urls = func->files() ->vfs_getFiles( &names );
+
+ if ( urls->isEmpty() ) { // avoid draging empty urls
+ delete urls;
+ return ;
+ }
+
+ KURLDrag *d = new KURLDrag(*urls, this);
+ d->setPixmap( px, QPoint( -7, 0 ) );
+ d->dragCopy();
+
+ delete urls; // free memory
+}
+
+// pops a right-click menu for items
+void ListPanel::popRightClickMenu( const QPoint &loc ) {
+ // run it, on the mouse location
+ int j = QFontMetrics( font() ).height() * 2;
+ KrPopupMenu::run(QPoint( loc.x() + 5, loc.y() + j ), this);
+}
+
+void ListPanel::popEmptyRightClickMenu( const QPoint &loc ) {
+ KrPopupMenu::run(loc, this);
+}
+
+void ListPanel::setFilter( KrViewProperties::FilterSpec f ) {
+ switch ( f ) {
+ case KrViewProperties::All :
+ //case KrView::EXEC:
+ break;
+ case KrViewProperties::Custom :
+ filterMask = KRSpWidgets::getMask( i18n( " Select Files " ) );
+ // if the user canceled - quit
+ if ( filterMask.isNull() )
+ return;
+ view->setFilterMask( filterMask );
+ break;
+ default:
+ return ;
+ }
+ view->setFilter( f ); // do that in any case
+ func->files()->vfs_invalidate();
+ func->refresh();
+}
+
+QString ListPanel::getCurrentName() {
+ QString name = view->getCurrentItem();
+ if ( name != ".." )
+ return name;
+ else
+ return QString::null;
+}
+
+void ListPanel::prepareToDelete() {
+ view->setNameToMakeCurrent( view->firstUnmarkedBelowCurrent() );
+}
+
+void ListPanel::keyPressEvent( QKeyEvent *e ) {
+ switch ( e->key() ) {
+ case Key_Enter :
+ case Key_Return :
+ if ( e->state() & ControlButton ) {
+ if (e->state() & AltButton) {
+ vfile *vf = func->files()->vfs_search(view->getCurrentKrViewItem()->name());
+ if (vf && vf->vfile_isDir()) SLOTS->newTab(vf->vfile_getUrl());
+ } else {
+ SLOTS->insertFileName( ( e->state() & ShiftButton ) != 0 );
+ }
+ } else e->ignore();
+ break;
+ case Key_Right :
+ case Key_Left :
+ if ( e->state() == ControlButton ) {
+ // user pressed CTRL+Right/Left - refresh other panel to the selected path if it's a
+ // directory otherwise as this one
+ if ( ( _left && e->key() == Key_Right ) || ( !_left && e->key() == Key_Left ) ) {
+ KURL newPath;
+ KrViewItem *it = view->getCurrentKrViewItem();
+
+ if( it->name() == ".." ) {
+ newPath = func->files()->vfs_getOrigin().upURL();
+ } else {
+ vfile *v = func->getVFile( it );
+ if ( v && v->vfile_isDir() && v->vfile_getName() != ".." ) {
+ newPath = v->vfile_getUrl();
+ } else {
+ newPath = func->files() ->vfs_getOrigin();
+ }
+ }
+ otherPanel->func->openUrl( newPath );
+ } else func->openUrl( otherPanel->func->files() ->vfs_getOrigin() );
+ return ;
+ } else
+ e->ignore();
+ break;
+
+ case Key_Down :
+ if ( e->state() == ControlButton ) { // give the keyboard focus to the command line
+ if ( MAIN_VIEW->cmdLine->isVisible() )
+ MAIN_VIEW->cmdLineFocus();
+ else
+ MAIN_VIEW->focusTerminalEmulator();
+ return ;
+ } else if ( e->state() == ( ControlButton | ShiftButton ) ) { // give the keyboard focus to TE
+ MAIN_VIEW->focusTerminalEmulator();
+ } else
+ e->ignore();
+ break;
+
+ case Key_Up :
+ if ( e->state() == ControlButton ) { // give the keyboard focus to the command line
+ origin->lineEdit()->setFocus();
+ return ;
+ } else
+ e->ignore();
+ break;
+
+ default:
+ // if we got this, it means that the view is not doing
+ // the quick search thing, so send the characters to the commandline, if normal key
+ if ( e->state() == NoButton )
+ MAIN_VIEW->cmdLine->addText( e->text() );
+
+ //e->ignore();
+ }
+}
+
+void ListPanel::slotItemAdded(vfile *vf) {
+ view->addItem(vf);
+}
+
+void ListPanel::slotItemDeleted(const QString& name) {
+ view->delItem(name);
+}
+
+void ListPanel::slotItemUpdated(vfile *vf) {
+ view->updateItem(vf);
+}
+
+void ListPanel::slotCleared() {
+ view->clear();
+}
+
+void ListPanel::showEvent( QShowEvent *e ) {
+ panelActive();
+ QWidget::showEvent(e);
+}
+
+void ListPanel::hideEvent( QHideEvent *e ) {
+ panelInactive();
+ QWidget::hideEvent(e);
+}
+
+void ListPanel::panelActive() {
+ // don't refresh when not active (ie: hidden, application isn't focussed ...)
+ func->files()->vfs_enableRefresh(true);
+}
+
+void ListPanel::panelInactive() {
+ func->files()->vfs_enableRefresh(false);
+}
+
+void ListPanel::slotJobStarted(KIO::Job* job) {
+ // disable the parts of the panel we don't want touched
+ //static_cast<KrDetailedView*>(view)->setEnabled(false);
+ status->setEnabled(false);
+ origin->setEnabled(false);
+ cdRootButton->setEnabled(false);
+ cdHomeButton->setEnabled(false);
+ cdUpButton->setEnabled(false);
+ cdOtherButton->setEnabled(false);
+ popupBtn->setEnabled(false);
+ popup->setEnabled(false);
+ bookmarksButton->setEnabled(false);
+ historyButton->setEnabled(false);
+ syncBrowseButton->setEnabled(false);
+
+ // connect to the job interface to provide in-panel refresh notification
+ connect( job, SIGNAL( infoMessage( KIO::Job*, const QString & ) ),
+ SLOT( inlineRefreshInfoMessage( KIO::Job*, const QString & ) ) );
+ connect( job, SIGNAL( percent( KIO::Job*, unsigned long ) ),
+ SLOT( inlineRefreshPercent( KIO::Job*, unsigned long ) ) );
+ connect(job,SIGNAL(result(KIO::Job*)),
+ this,SLOT(inlineRefreshListResult(KIO::Job*)));
+ connect(job,SIGNAL(canceled(KIO::Job*)),
+ this,SLOT(inlineRefreshListResult(KIO::Job*)));
+
+ inlineRefreshJob = job;
+
+ totals->setText(i18n(">> Reading..."));
+ inlineRefreshCancelButton->show();
+}
+
+void ListPanel::inlineRefreshCancel() {
+ if (inlineRefreshJob) {
+ inlineRefreshJob->kill(false);
+ inlineRefreshJob = 0;
+ }
+}
+
+void ListPanel::inlineRefreshPercent( KIO::Job*, unsigned long perc) {
+ QString msg = QString(">> %1: %2 % complete...").arg(i18n("Reading")).arg(perc);
+ totals->setText(msg);
+}
+
+void ListPanel::inlineRefreshInfoMessage( KIO::Job*, const QString &msg ) {
+ totals->setText(">> " + i18n("Reading: ") + msg);
+}
+
+void ListPanel::inlineRefreshListResult(KIO::Job*) {
+ inlineRefreshJob = 0;
+ // reenable everything
+ //static_cast<KrDetailedView*>(view)->setEnabled(true);
+ status->setEnabled(true);
+ origin->setEnabled(true);
+ cdRootButton->setEnabled(true);
+ cdHomeButton->setEnabled(true);
+ cdUpButton->setEnabled(true);
+ cdOtherButton->setEnabled(true);
+ popupBtn->setEnabled(true);
+ popup->setEnabled(true);
+ bookmarksButton->setEnabled(true);
+ historyButton->setEnabled(true);
+ syncBrowseButton->setEnabled(true);
+
+ inlineRefreshCancelButton->hide();
+}
+
+void ListPanel::jumpBack() {
+ func->openUrl( _jumpBackURL );
+}
+
+void ListPanel::setJumpBack( KURL url ) {
+ _jumpBackURL = url;
+}
+
+#include "listpanel.moc"
diff --git a/krusader/Panel/listpanel.h b/krusader/Panel/listpanel.h
new file mode 100644
index 0000000..088fdfd
--- /dev/null
+++ b/krusader/Panel/listpanel.h
@@ -0,0 +1,211 @@
+/***************************************************************************
+ listpanel.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+ Description
+***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+
+#ifndef LISTPANEL_H
+#define LISTPANEL_H
+
+#include <kpropsdlg.h>
+#include <kfileitem.h>
+#include <kurl.h>
+#include <qwidget.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qstring.h>
+#include <qpixmap.h>
+#include <qtoolbutton.h>
+#include <qpopupmenu.h>
+#include <qdir.h>
+#include <qpixmapcache.h>
+#include <qiconset.h>
+#include <qptrstack.h>
+#include <qtextbrowser.h>
+#include <keditcl.h>
+#include <klineedit.h>
+#include <qguardedptr.h>
+#include "krview.h"
+#include "../Dialogs/krsqueezedtextlabel.h"
+
+// use our version of it, until kde fixes theirs
+#include "../MountMan/kdiskfreesp.h"
+
+#define PROP_SYNC_BUTTON_ON 1
+
+class vfs;
+class vfile;
+class KRdirWatch;
+class KrView;
+class KURLRequester;
+class BookmarksButton;
+class KrQuickSearch;
+class DirHistoryButton;
+class DirHistoryQueue;
+class MediaButton;
+class PanelPopup;
+class SyncBrowseButton;
+class KrBookmarkButton;
+class KPushButton;
+class ListPanelFunc;
+class QHeader;
+
+class ListPanel : public QWidget {
+ friend class ListPanelFunc;
+ Q_OBJECT
+public:
+ #define ITEM2VFILE(PANEL_PTR, KRVIEWITEM) PANEL_PTR->func->files()->vfs_search(KRVIEWITEM->name())
+ #define NAME2VFILE(PANEL_PTR, STRING_NAME) PANEL_PTR->func->files()->vfs_search(STRING_NAME)
+ // constructor create the panel, but DOESN'T fill it with data, use start()
+ ListPanel( QString panelType, QWidget *parent, bool &left, const char *name = 0 );
+ ~ListPanel();
+ void start( KURL url = KURL(), bool immediate = false );
+
+ const QString & getType() { return panelType; }
+ void changeType( const QString & );
+
+ KURL virtualPath() const;
+ QString realPath() const;
+ QString getCurrentName();
+ void getSelectedNames( QStringList* fileNames ) {
+ view->getSelectedItems( fileNames );
+ }
+ void setPanelToolbar();
+ bool isLeft() {return _left;}
+ void jumpBack();
+ void setJumpBack( KURL url );
+
+ int getProperties();
+ void setProperties( int );
+
+public slots:
+ void gotStats( const QString &mountPoint, unsigned long kBSize, unsigned long kBUsed, unsigned long kBAvail); // displays filesystem status
+ void popRightClickMenu( const QPoint& );
+ void popEmptyRightClickMenu( const QPoint & );
+ void select( KRQuery query, bool select);
+ void select( bool, bool ); // see doc in ListPanel
+ void invertSelection(); // see doc in ListPanel
+ void compareDirs();
+ void slotFocusOnMe(); // give this VFS the focus (the path bar)
+ void slotUpdate(); // when the vfs finish to update...
+ void slotUpdateTotals();
+ void slotStartUpdate(); // internal
+ void slotGetStats( const KURL& url ); // get the disk-free stats
+ void setFilter( KrViewProperties::FilterSpec f );
+ void slotFocusAndCDRoot();
+ void slotFocusAndCDHome();
+ void slotFocusAndCDup();
+ void slotFocusAndCDOther();
+ void togglePanelPopup();
+ // for signals from vfs' dirwatch
+ void slotItemAdded(vfile *vf);
+ void slotItemDeleted(const QString& name);
+ void slotItemUpdated(vfile *vf);
+ void slotCleared();
+ void panelActive(); // called when the panel becomes active
+ void panelInactive(); // called when panel becomes inactive
+
+
+ ///////////////////////// service functions - called internally ////////////////////////
+ inline void setOther( ListPanel *panel ) {
+ otherPanel = panel;
+ }
+ void prepareToDelete(); // internal use only
+
+protected:
+ virtual void keyPressEvent( QKeyEvent *e );
+ virtual void showEvent( QShowEvent * );
+ virtual void hideEvent( QHideEvent * );
+ virtual bool eventFilter ( QObject * watched, QEvent * e );
+
+ void createView();
+
+protected slots:
+ void handleDropOnView(QDropEvent *, QWidget *destWidget=0); // handles drops on the view only
+ void handleDropOnTotals( QDropEvent * ); // handles drops on the totals line
+ void handleDropOnStatus( QDropEvent * ); // handles drops on the status line
+ void startDragging( QStringList, QPixmap );
+ // those handle the in-panel refresh notifications
+ void slotJobStarted(KIO::Job* job);
+ void inlineRefreshInfoMessage( KIO::Job* job, const QString &msg );
+ void inlineRefreshListResult(KIO::Job* job);
+ void inlineRefreshPercent( KIO::Job*, unsigned long );
+ void inlineRefreshCancel();
+
+signals:
+ void signalStatus( QString msg ); // emmited when we need to update the status bar
+ void cmdLineUpdate( QString p ); // emitted when we need to update the command line
+ void pathChanged( ListPanel *panel );
+ void activePanelChanged( ListPanel *p ); // emitted when the user changes panels
+ void finishedDragging(); // currently
+
+public:
+ QString panelType;
+ ListPanelFunc *func;
+ KrView *view;
+ ListPanel *otherPanel;
+ int colorMask;
+ bool compareMode;
+ //FilterSpec filter;
+ KRQuery filterMask;
+ QPixmap currDragPix;
+ QListViewItem *currDragItem;
+ KDiskFreeSp* statsAgent;
+ KrSqueezedTextLabel *status, *totals;
+ KrQuickSearch *quickSearch;
+ KURLRequester *origin;
+ QGridLayout *layout;
+ QToolButton *cdRootButton;
+ QToolButton *cdHomeButton;
+ QToolButton *cdUpButton;
+ QToolButton *cdOtherButton;
+ QToolButton *popupBtn;
+ QToolButton *clearOrigin;
+ PanelPopup *popup;
+ KrBookmarkButton *bookmarksButton;
+ DirHistoryQueue* dirHistoryQueue;
+ DirHistoryButton* historyButton;
+ MediaButton *mediaButton;
+ SyncBrowseButton *syncBrowseButton;
+ KPushButton *inlineRefreshCancelButton;
+ KIO::Job *inlineRefreshJob;
+ QSplitter *splt;
+ QHeader * header;
+
+protected:
+ KURL _realPath; // named with _ to keep realPath() compatability
+ KURL _jumpBackURL;
+
+
+private:
+ bool &_left;
+ QValueList<int> popupSizes;
+};
+
+#endif
diff --git a/krusader/Panel/panelfunc.cpp b/krusader/Panel/panelfunc.cpp
new file mode 100755
index 0000000..735a0cf
--- /dev/null
+++ b/krusader/Panel/panelfunc.cpp
@@ -0,0 +1,1186 @@
+/***************************************************************************
+ panelfunc.cpp
+ -------------------
+copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+e-mail : krusader@users.sourceforge.net
+web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+Description
+***************************************************************************
+
+A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+#include <unistd.h>
+// Qt Includes
+#include <qdir.h>
+#include <qtextstream.h>
+#include <qeventloop.h>
+#include <qclipboard.h>
+// KDE Includes
+#include <klocale.h>
+#include <kprocess.h>
+#include <kpropertiesdialog.h>
+#include <kopenwith.h>
+#include <kmessagebox.h>
+#include <kcursor.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kurl.h>
+#include <krun.h>
+#include <kinputdialog.h>
+#include <kdebug.h>
+#include <kio/netaccess.h>
+#include <kstandarddirs.h>
+#include <ktempdir.h>
+#include <kurlrequester.h>
+#include <kprocio.h>
+#include <kdesktopfile.h>
+// Krusader Includes
+#include "panelfunc.h"
+#include "krcalcspacedialog.h"
+#include "krdetailedview.h"
+#include "../krusader.h"
+#include "../krslots.h"
+#include "../defaults.h"
+#include "../VFS/vfile.h"
+#include "../VFS/vfs.h"
+#include "../VFS/virt_vfs.h"
+#include "../VFS/krarchandler.h"
+#include "../VFS/krpermhandler.h"
+#include "../VFS/krvfshandler.h"
+#include "../VFS/preservingcopyjob.h"
+#include "../VFS/virtualcopyjob.h"
+#include "../Dialogs/packgui.h"
+#include "../Dialogs/krdialogs.h"
+#include "../Dialogs/krpleasewait.h"
+#include "../Dialogs/krspwidgets.h"
+#include "../Dialogs/checksumdlg.h"
+#include "../KViewer/krviewer.h"
+#include "../resources.h"
+#include "../krservices.h"
+#include "../GUI/syncbrowsebutton.h"
+#include "../Queue/queue_mgr.h"
+#include "krdrag.h"
+#include <kurldrag.h>
+
+//////////////////////////////////////////////////////////
+////// ---------- List Panel ------------- ////////
+//////////////////////////////////////////////////////////
+
+ListPanelFunc::ListPanelFunc( ListPanel *parent ) :
+panel( parent ), inRefresh( false ), vfsP( 0 ) {
+ urlStack.push( "file:/" );
+ connect( &delayTimer, SIGNAL( timeout() ), this, SLOT( doOpenUrl() ) );
+}
+
+void ListPanelFunc::openUrl( const QString& url, const QString& nameToMakeCurrent ) {
+ openUrl( vfs::fromPathOrURL(
+ // KURLRequester is buggy: it should return a string containing "/home/shie/downloads"
+ // but it returns "~/downloads" which is parsed incorrectly by vfs::fromPathOrURL.
+ // replacedPath should replace ONLY $HOME and environment variables
+ panel->origin->completionObject()->replacedPath(url) )
+ , nameToMakeCurrent );
+}
+
+void ListPanelFunc::immediateOpenUrl( const KURL& urlIn ) {
+ KURL url = urlIn;
+ url.cleanPath();
+
+ // check for special cases first - don't refresh here !
+ // you may call openUrl or vfs_refresh()
+ if ( !url.isValid() ) {
+ if ( url.url() == "~" ) {
+ return openUrl( QDir::homeDirPath() );
+ } else if ( !url.url().startsWith( "/" ) ) {
+ // possible relative URL - translate to full URL
+ url = files() ->vfs_getOrigin();
+ url.addPath( urlIn.url() );
+ //kdDebug()<< urlIn.url() << "," << url.url() <<endl;
+ } else {
+ panel->slotStartUpdate(); // refresh the panel
+ return ;
+ }
+ }
+
+ // if we are not refreshing to current URL
+ bool is_equal_url = files() ->vfs_getOrigin().equals( url, true );
+
+ if ( !is_equal_url ) {
+ // change the cursor to busy
+ panel->setCursor( KCursor::waitCursor() );
+ }
+
+ if ( !nameToMakeCurrent.isEmpty() ) {
+ panel->view->setNameToMakeCurrent( nameToMakeCurrent );
+ // if the url we're refreshing into is the current one, then the
+ // partial url will not generate the needed signals to actually allow the
+ // view to use nameToMakeCurrent. do it here instead (patch by Thomas Jarosch)
+ if ( is_equal_url ) {
+ panel->view->setCurrentItem( nameToMakeCurrent );
+ panel->view->makeItemVisible( panel->view->getCurrentKrViewItem() );
+ }
+ }
+
+ vfs* v = 0;
+ if ( !urlStack.top().equals( url ) )
+ urlStack.push( url );
+ // count home many urls is in the stack, so later on, we'll know if the refresh was a success
+ uint stackSize = urlStack.size();
+ bool refreshFailed = true; // assume the worst
+ while ( true ) {
+ KURL u = urlStack.pop();
+ //u.adjustPath(-1); // remove trailing "/"
+ u.cleanPath(); // Resolves "." and ".." components in path.
+ v = KrVfsHandler::getVfs( u, panel, files() );
+ if ( !v )
+ continue; //this should not happen !
+ if ( v != vfsP ) {
+ if( vfsP->vfs_canDelete() )
+ delete vfsP;
+ else {
+ connect( vfsP, SIGNAL( deleteAllowed() ), vfsP, SLOT( deleteLater() ) );
+ vfsP->vfs_requestDelete();
+ }
+ vfsP = v; // v != 0 so this is safe
+ } else {
+ if( vfsP->vfs_isBusy() )
+ {
+ delayURL = url; /* this function is useful for FTP url-s and bookmarks */
+ delayTimer.start( 100, true ); /* if vfs is busy try refreshing later */
+ return;
+ }
+ }
+ connect( files(), SIGNAL(startJob(KIO::Job* )),
+ panel, SLOT(slotJobStarted(KIO::Job* )));
+ if ( vfsP->vfs_refresh( u ) ) {
+ break; // we have a valid refreshed URL now
+ }
+ if ( vfsP == 0 ) // the object was deleted during vfs_refresh? Hoping the best...
+ return;
+ // prevent repeated error messages
+ if ( vfsP->vfs_isDeleting() )
+ break;
+ vfsP->vfs_setQuiet( true );
+ }
+ vfsP->vfs_setQuiet( false );
+
+ // if we popped exactly 1 url from the stack, it means the url we were
+ // given was refreshed successfully.
+ if (stackSize == urlStack.size() + 1)
+ refreshFailed = false;
+
+ // update the urls stack
+ if ( !files() ->vfs_getOrigin().equals( urlStack.top() ) ) {
+ urlStack.push( files() ->vfs_getOrigin() );
+ }
+ // disconnect older signals
+ disconnect( files(), SIGNAL( addedVfile( vfile* ) ), 0, 0 );
+ disconnect( files(), SIGNAL( updatedVfile( vfile* ) ), 0, 0 );
+ disconnect( files(), SIGNAL( deletedVfile( const QString& ) ), 0, 0 );
+ disconnect( files(), SIGNAL( cleared() ), 0, 0 );
+ // connect to the vfs's dirwatch signals
+ connect( files(), SIGNAL( addedVfile( vfile* ) ),
+ panel, SLOT( slotItemAdded( vfile* ) ) );
+ connect( files(), SIGNAL( updatedVfile( vfile* ) ),
+ panel, SLOT( slotItemUpdated( vfile* ) ) );
+ connect( files(), SIGNAL( deletedVfile( const QString& ) ),
+ panel, SLOT( slotItemDeleted( const QString& ) ) );
+ connect( files(), SIGNAL( cleared() ),
+ panel, SLOT( slotCleared() ) );
+
+ // on local file system change the working directory
+ if ( files() ->vfs_getType() == vfs::NORMAL )
+ chdir( files() ->vfs_getOrigin().path().local8Bit() );
+
+ // see if the open url operation failed, and if so,
+ // put the attempted url in the origin bar and let the user change it
+ if (refreshFailed) {
+ panel->origin->setURL(urlIn.prettyURL());
+ panel->origin->setFocus();
+ }
+}
+
+void ListPanelFunc::openUrl( const KURL& url, const QString& nameToMakeCurrent ) {
+ panel->inlineRefreshCancel();
+ // first the other dir, then the active! Else the focus changes and the other becomes active
+ if ( panel->syncBrowseButton->state() == SYNCBROWSE_CD ) {
+ // prevents that the sync-browsing circles itself to death
+ static bool inSync = false;
+ if( ! inSync ){
+ inSync = true;
+ //do sync-browse stuff....
+ KURL otherDir = OTHER_PANEL->virtualPath();
+ OTHER_FUNC->files() ->vfs_setQuiet( true );
+ // the trailing slash is nessesary because krusader provides Dir's without it
+ // we can't use openUrl because the delay don't allow a check if the panel has realy changed!
+ OTHER_FUNC->immediateOpenUrl( KURL::relativeURL( panel->virtualPath().url() + "/", url.url() ) );
+ OTHER_FUNC->files() ->vfs_setQuiet( false );
+ // now we need to test ACTIVE_PANEL because the openURL has changed the active panel!!
+ if ( ACTIVE_PANEL->virtualPath().equals( otherDir ) ) {
+ // deactivating the sync-browse if syncbrowse not possible
+ panel->syncBrowseButton->setOn( false );
+ }
+ inSync = false;
+ }
+ }
+ this->nameToMakeCurrent = nameToMakeCurrent;
+ delayURL = url; /* this function is useful for FTP url-s and bookmarks */
+ delayTimer.start( 0, true ); /* to avoid qApp->processEvents() deadlock situaltion */
+}
+
+void ListPanelFunc::refresh() {
+ openUrl(panel->virtualPath()); // re-read the files
+}
+
+void ListPanelFunc::doOpenUrl() {
+ immediateOpenUrl( delayURL );
+}
+
+void ListPanelFunc::goBack() {
+ if ( urlStack.isEmpty() )
+ return ;
+
+ if ( urlStack.top().equals( files() ->vfs_getOrigin() ) )
+ urlStack.pop();
+ openUrl( urlStack.top(), files() ->vfs_getOrigin().fileName() );
+
+ if ( urlStack.isEmpty() )
+ krBack->setEnabled( false );
+}
+
+void ListPanelFunc::redirectLink() {
+ if ( files() ->vfs_getType() != vfs::NORMAL ) {
+ KMessageBox::sorry( krApp, i18n( "You can edit links only on local file systems" ) );
+ return ;
+ }
+
+ vfile *vf = files() ->vfs_search( panel->getCurrentName() );
+ if ( !vf )
+ return ;
+
+ QString file = files() ->vfs_getFile( vf->vfile_getName() ).path( -1 );
+ QString currentLink = vf->vfile_getSymDest();
+ if ( currentLink.isEmpty() ) {
+ KMessageBox::sorry( krApp, i18n( "The current file is not a link, so I can't redirect it." ) );
+ return ;
+ }
+
+ // ask the user for a new destination
+ bool ok = false;
+ QString newLink =
+ KInputDialog::getText( i18n( "Link Redirection" ),
+ i18n( "Please enter the new link destination:" ), currentLink, &ok, krApp );
+
+ // if the user canceled - quit
+ if ( !ok || newLink == currentLink )
+ return ;
+ // delete the current link
+ if ( unlink( file.local8Bit() ) == -1 ) {
+ KMessageBox::sorry( krApp, i18n( "Can't remove old link: " ) + file );
+ return ;
+ }
+ // try to create a new symlink
+ if ( symlink( newLink.local8Bit(), file.local8Bit() ) == -1 ) {
+ KMessageBox:: /* --=={ Patch by Heiner <h.eichmann@gmx.de> }==-- */sorry( krApp, i18n( "Failed to create a new link: " ) + file );
+ return ;
+ }
+}
+
+void ListPanelFunc::krlink( bool sym ) {
+ if ( files() ->vfs_getType() != vfs::NORMAL ) {
+ KMessageBox::sorry( krApp, i18n( "You can create links only on local file systems" ) );
+ return ;
+ }
+
+ QString name = panel->getCurrentName();
+
+ // ask the new link name..
+ bool ok = false;
+ QString linkName =
+ KInputDialog::getText( i18n( "New link" ), i18n( "Create a new link to: " ) + name, name, &ok, krApp );
+
+ // if the user canceled - quit
+ if ( !ok || linkName == name )
+ return ;
+
+ // if the name is already taken - quit
+ if ( files() ->vfs_search( linkName ) != 0 ) {
+ KMessageBox::sorry( krApp, i18n( "A directory or a file with this name already exists." ) );
+ return ;
+ }
+
+ if ( linkName.left( 1 ) != "/" )
+ linkName = files() ->vfs_workingDir() + "/" + linkName;
+
+ if ( linkName.contains( "/" ) )
+ name = files() ->vfs_getFile( name ).path( -1 );
+
+ if ( sym ) {
+ if ( symlink( name.local8Bit(), linkName.local8Bit() ) == -1 )
+ KMessageBox::sorry( krApp, i18n( "Failed to create a new symlink: " ) + linkName +
+ i18n( " To: " ) + name );
+ } else {
+ if ( link( name.local8Bit(), linkName.local8Bit() ) == -1 )
+ KMessageBox::sorry( krApp, i18n( "Failed to create a new link: " ) + linkName +
+ i18n( " To: " ) + name );
+ }
+}
+
+void ListPanelFunc::view() {
+ QString fileName = panel->getCurrentName();
+ if ( fileName.isNull() )
+ return ;
+
+ // if we're trying to view a directory, just exit
+ vfile * vf = files() ->vfs_search( fileName );
+ if ( !vf || vf->vfile_isDir() )
+ return ;
+ if ( !vf->vfile_isReadable() ) {
+ KMessageBox::sorry( 0, i18n( "No permissions to view this file." ) );
+ return ;
+ }
+ // call KViewer.
+ KrViewer::view( files() ->vfs_getFile( fileName ) );
+ // nothing more to it!
+}
+
+void ListPanelFunc::terminal() {
+ QString save = getcwd( 0, 0 );
+ chdir( panel->realPath().local8Bit() );
+
+ KProcess proc;
+ krConfig->setGroup( "General" );
+ QString term = krConfig->readEntry( "Terminal", _Terminal );
+ proc << KrServices::separateArgs( term );
+
+ if ( term.contains( "konsole" ) ) /* KDE 3.2 bug (konsole is killed by pressing Ctrl+C) */
+ { /* Please remove the patch if the bug is corrected */
+ proc << "&";
+ proc.setUseShell( true );
+ }
+
+ if ( !proc.start( KProcess::DontCare ) )
+ KMessageBox::sorry( krApp, i18n( "<qt>Can't open <b>%1</b></qt>" ).arg(term) );
+
+ chdir( save.local8Bit() );
+}
+
+void ListPanelFunc::editFile() {
+ QString name = panel->getCurrentName();
+ if ( name.isNull() )
+ return ;
+
+ if ( files() ->vfs_search( name ) ->vfile_isDir() ) {
+ KMessageBox::sorry( krApp, i18n( "You can't edit a directory" ) );
+ return ;
+ }
+
+ if ( !files() ->vfs_search( name ) ->vfile_isReadable() ) {
+ KMessageBox::sorry( 0, i18n( "No permissions to edit this file." ) );
+ return ;
+ }
+
+ KrViewer::edit( files() ->vfs_getFile( name ) );
+}
+
+void ListPanelFunc::moveFiles() {
+ PreserveMode pmode = PM_DEFAULT;
+
+ QStringList fileNames;
+ panel->getSelectedNames( &fileNames );
+ if ( fileNames.isEmpty() )
+ return ; // safety
+
+ KURL dest = panel->otherPanel->virtualPath();
+ KURL virtualBaseURL;
+
+ QString destProtocol = dest.protocol();
+ if ( destProtocol == "krarc" || destProtocol == "tar" || destProtocol == "zip" ) {
+ KMessageBox::sorry( krApp, i18n( "Moving into archive is disabled" ) );
+ return ;
+ }
+
+ krConfig->setGroup( "Advanced" );
+ if ( krConfig->readBoolEntry( "Confirm Move", _ConfirmMove ) ) {
+ bool preserveAttrs = krConfig->readBoolEntry( "PreserveAttributes", _PreserveAttributes );
+ QString s;
+
+ if( fileNames.count() == 1 )
+ s = i18n("Move %1 to:").arg(fileNames.first());
+ else
+ s = i18n("Move %n file to:", "Move %n files to:", fileNames.count());
+
+ // ask the user for the copy dest
+ virtualBaseURL = getVirtualBaseURL();
+ dest = KChooseDir::getDir(s, dest, panel->virtualPath(), preserveAttrs, virtualBaseURL);
+ if ( dest.isEmpty() ) return ; // the user canceled
+ if( preserveAttrs )
+ pmode = PM_PRESERVE_ATTR;
+ else
+ pmode = PM_NONE;
+ }
+
+ if ( fileNames.isEmpty() )
+ return ; // nothing to copy
+
+ KURL::List* fileUrls = files() ->vfs_getFiles( &fileNames );
+
+ // after the delete return the cursor to the first unmarked
+ // file above the current item;
+ panel->prepareToDelete();
+
+ if( !virtualBaseURL.isEmpty() ) {
+ // keep the directory structure for virtual paths
+ VirtualCopyJob *vjob = new VirtualCopyJob( &fileNames, files(), dest, virtualBaseURL, pmode, KIO::CopyJob::Move, false, true );
+ connect( vjob, SIGNAL( result( KIO::Job* ) ), this, SLOT( refresh() ) );
+ if ( dest.equals( panel->otherPanel->virtualPath(), true ) )
+ connect( vjob, SIGNAL( result( KIO::Job* ) ), panel->otherPanel->func, SLOT( refresh() ) );
+ }
+ // if we are not moving to the other panel :
+ else if ( !dest.equals( panel->otherPanel->virtualPath(), true ) ) {
+ // you can rename only *one* file not a batch,
+ // so a batch dest must alwayes be a directory
+ if ( fileNames.count() > 1 ) dest.adjustPath(1);
+ KIO::Job* job = PreservingCopyJob::createCopyJob( pmode, *fileUrls, dest, KIO::CopyJob::Move, false, true );
+ job->setAutoErrorHandlingEnabled( true );
+ // refresh our panel when done
+ connect( job, SIGNAL( result( KIO::Job* ) ), this, SLOT( refresh() ) );
+ // and if needed the other panel as well
+ if ( dest.equals( panel->otherPanel->virtualPath(), true ) )
+ connect( job, SIGNAL( result( KIO::Job* ) ), panel->otherPanel->func, SLOT( refresh() ) );
+
+ } else { // let the other panel do the dirty job
+ //check if copy is supported
+ if ( !otherFunc() ->files() ->vfs_isWritable() ) {
+ KMessageBox::sorry( krApp, i18n( "You can't move files to this file system" ) );
+ return ;
+ }
+ // finally..
+ otherFunc() ->files() ->vfs_addFiles( fileUrls, KIO::CopyJob::Move, files(), "", pmode );
+ }
+}
+
+// called from SLOTS to begin the renaming process
+void ListPanelFunc::rename() {
+ panel->view->renameCurrentItem();
+}
+
+// called by signal itemRenamed() from the view to complete the renaming process
+void ListPanelFunc::rename( const QString &oldname, const QString &newname ) {
+ if ( oldname == newname )
+ return ; // do nothing
+ panel->view->setNameToMakeCurrentIfAdded( newname );
+ // as always - the vfs do the job
+ files() ->vfs_rename( oldname, newname );
+}
+
+void ListPanelFunc::mkdir() {
+ // ask the new dir name..
+ bool ok = false;
+ QString dirName =
+ KInputDialog::getText( i18n( "New directory" ), i18n( "Directory's name:" ), "", &ok, krApp );
+
+ // if the user canceled - quit
+ if ( !ok || dirName.isEmpty() )
+ return ;
+
+ QStringList dirTree = QStringList::split( "/", dirName );
+
+ for ( QStringList::Iterator it = dirTree.begin(); it != dirTree.end(); ++it ) {
+ // check if the name is already taken
+ if ( files() ->vfs_search( *it ) ) {
+ // if it is the last dir to be created - quit
+ if ( *it == dirTree.last() ) {
+ KMessageBox::sorry( krApp, i18n( "A directory or a file with this name already exists." ) );
+ return ;
+ }
+ // else go into this dir
+ else {
+ immediateOpenUrl( *it );
+ continue;
+ }
+ }
+
+ panel->view->setNameToMakeCurrent( *it );
+ // as always - the vfs do the job
+ files() ->vfs_mkdir( *it );
+ if ( dirTree.count() > 1 )
+ immediateOpenUrl( *it );
+ } // for
+}
+
+KURL ListPanelFunc::getVirtualBaseURL() {
+ if( files()->vfs_getType() != vfs::VIRT || otherFunc()->files()->vfs_getType() == vfs::VIRT )
+ return KURL();
+
+ QStringList fileNames;
+ panel->getSelectedNames( &fileNames );
+
+ KURL::List* fileUrls = files() ->vfs_getFiles( &fileNames );
+ if( fileUrls->count() == 0 )
+ return KURL();
+
+ KURL base = (*fileUrls)[ 0 ].upURL();
+
+ if( base.protocol() == "virt" ) // is it a virtual subfolder?
+ return KURL(); // --> cannot keep the directory structure
+
+ for( unsigned i=1; i < fileUrls->count(); i++ ) {
+ if( base.isParentOf( (*fileUrls)[ i ] ) )
+ continue;
+ if( base.protocol() != (*fileUrls)[ i ].protocol() )
+ return KURL();
+
+ do {
+ KURL oldBase = base;
+ base = base.upURL();
+ if( oldBase.equals( base, true ) )
+ return KURL();
+ if( base.isParentOf( (*fileUrls)[ i ] ) )
+ break;
+ }while( true );
+ }
+ return base;
+}
+
+void ListPanelFunc::copyFiles() {
+ PreserveMode pmode = PM_DEFAULT;
+
+ QStringList fileNames;
+ panel->getSelectedNames( &fileNames );
+ if ( fileNames.isEmpty() )
+ return ; // safety
+
+ KURL dest = panel->otherPanel->virtualPath();
+ KURL virtualBaseURL;
+
+ // confirm copy
+ krConfig->setGroup( "Advanced" );
+ if ( krConfig->readBoolEntry( "Confirm Copy", _ConfirmCopy ) ) {
+ bool preserveAttrs = krConfig->readBoolEntry( "PreserveAttributes", _PreserveAttributes );
+ QString s;
+
+ if( fileNames.count() == 1 )
+ s = i18n("Copy %1 to:").arg(fileNames.first());
+ else
+ s = i18n("Copy %n file to:", "Copy %n files to:", fileNames.count());
+
+ // ask the user for the copy dest
+ virtualBaseURL = getVirtualBaseURL();
+ dest = KChooseDir::getDir(s, dest, panel->virtualPath(), preserveAttrs, virtualBaseURL );
+ if ( dest.isEmpty() ) return ; // the user canceled
+ if( preserveAttrs )
+ pmode = PM_PRESERVE_ATTR;
+ else
+ pmode = PM_NONE;
+ }
+
+ KURL::List* fileUrls = files() ->vfs_getFiles( &fileNames );
+
+ if( !virtualBaseURL.isEmpty() ) {
+ // keep the directory structure for virtual paths
+ VirtualCopyJob *vjob = new VirtualCopyJob( &fileNames, files(), dest, virtualBaseURL, pmode, KIO::CopyJob::Copy, false, true );
+ connect( vjob, SIGNAL( result( KIO::Job* ) ), this, SLOT( refresh() ) );
+ if ( dest.equals( panel->otherPanel->virtualPath(), true ) )
+ connect( vjob, SIGNAL( result( KIO::Job* ) ), panel->otherPanel->func, SLOT( refresh() ) );
+ }
+ // if we are not copying to the other panel :
+ else if ( !dest.equals( panel->otherPanel->virtualPath(), true ) ) {
+ // you can rename only *one* file not a batch,
+ // so a batch dest must alwayes be a directory
+ if ( fileNames.count() > 1 ) dest.adjustPath(1);
+ KIO::Job* job = PreservingCopyJob::createCopyJob( pmode, *fileUrls, dest, KIO::CopyJob::Copy, false, true );
+ job->setAutoErrorHandlingEnabled( true );
+ if ( dest.equals( panel->virtualPath(), true ) ||
+ dest.upURL().equals( panel->virtualPath(), true ) )
+ // refresh our panel when done
+ connect( job, SIGNAL( result( KIO::Job* ) ), this, SLOT( refresh() ) );
+ // let the other panel do the dirty job
+ } else {
+ //check if copy is supported
+ if ( !otherFunc() ->files() ->vfs_isWritable() ) {
+ KMessageBox::sorry( krApp, i18n( "You can't copy files to this file system" ) );
+ return ;
+ }
+ // finally..
+ otherFunc() ->files() ->vfs_addFiles( fileUrls, KIO::CopyJob::Copy, 0, "", pmode );
+ }
+}
+
+void ListPanelFunc::deleteFiles(bool reallyDelete) {
+ // check that the you have write perm
+ if ( !files() ->vfs_isWritable() ) {
+ KMessageBox::sorry( krApp, i18n( "You do not have write permission to this directory" ) );
+ return ;
+ }
+
+ // first get the selected file names list
+ QStringList fileNames;
+ panel->getSelectedNames( &fileNames );
+ if ( fileNames.isEmpty() )
+ return ;
+
+ krConfig->setGroup( "General" );
+ bool trash = krConfig->readBoolEntry( "Move To Trash", _MoveToTrash );
+ // now ask the user if he want to delete:
+ krConfig->setGroup( "Advanced" );
+ if ( krConfig->readBoolEntry( "Confirm Delete", _ConfirmDelete ) ) {
+ QString s, b;
+
+ if ( !reallyDelete && trash && files() ->vfs_getType() == vfs::NORMAL ) {
+ s = i18n( "Do you really want to move this item to the trash?", "Do you really want to move these %n items to the trash?", fileNames.count() );
+ b = i18n( "&Trash" );
+ } else if( files() ->vfs_getType() == vfs::VIRT && files()->vfs_getOrigin().equals( KURL("virt:/"), true ) ) {
+ s = i18n( "Do you really want to delete this virtual item (physical files stay untouched)?", "Do you really want to delete these virtual items (physical files stay untouched)?", fileNames.count() );
+ b = i18n( "&Delete" );
+ } else if( files() ->vfs_getType() == vfs::VIRT ) {
+ s = i18n( "<qt>Do you really want to delete this item <b>physically</b> (not just removing it from the virtual items)?</qt>", "<qt>Do you really want to delete these %n items <b>physically</b> (not just removing them from the virtual items)?</qt>", fileNames.count() );
+ b = i18n( "&Delete" );
+ } else {
+ s = i18n( "Do you really want to delete this item?", "Do you really want to delete these %n items?", fileNames.count() );
+ b = i18n( "&Delete" );
+ }
+
+ // show message
+ // note: i'm using continue and not yes/no because the yes/no has cancel as default button
+ if ( KMessageBox::warningContinueCancelList( krApp, s, fileNames,
+ i18n( "Warning" ), b ) != KMessageBox::Continue )
+ return ;
+ }
+ //we want to warn the user about non empty dir
+ // and files he don't have permission to delete
+ krConfig->setGroup( "Advanced" );
+ bool emptyDirVerify = krConfig->readBoolEntry( "Confirm Unempty Dir", _ConfirmUnemptyDir );
+ emptyDirVerify = ( ( emptyDirVerify ) && ( files() ->vfs_getType() == vfs::NORMAL ) );
+
+ QDir dir;
+ for ( QStringList::Iterator name = fileNames.begin(); name != fileNames.end(); ) {
+ vfile * vf = files() ->vfs_search( *name );
+
+ // verify non-empty dirs delete... (only for normal vfs)
+ if ( emptyDirVerify && vf->vfile_isDir() && !vf->vfile_isSymLink() ) {
+ dir.setPath( panel->virtualPath().path() + "/" + ( *name ) );
+ if ( dir.entryList(QDir::All | QDir::System | QDir::Hidden ).count() > 2 ) {
+ switch ( KMessageBox::warningYesNoCancel( krApp,
+ i18n( "<qt><p>Directory <b>%1</b> is not empty!</p><p>Skip this one or Delete All?</p></qt>" ).arg(*name),
+ QString::null, i18n( "&Skip" ), i18n( "&Delete All" ) ) ) {
+ case KMessageBox::Cancel :
+ return ;
+ case KMessageBox::No :
+ emptyDirVerify = false;
+ break;
+ case KMessageBox::Yes :
+ name = fileNames.remove( name );
+ continue;
+ }
+ }
+ }
+ ++name;
+ }
+
+ if ( fileNames.count() == 0 )
+ return ; // nothing to delete
+
+ // after the delete return the cursor to the first unmarked
+ // file above the current item;
+ panel->prepareToDelete();
+
+ // let the vfs do the job...
+ if (reallyDelete) {
+ // if reallyDelete, then make sure nothing gets moved to trash
+ krConfig->setGroup("General");
+ krConfig->writeEntry( "Move To Trash", false );
+ }
+ files() ->vfs_delFiles( &fileNames );
+ if (reallyDelete) {
+ krConfig->setGroup("General");
+ krConfig->writeEntry( "Move To Trash", trash);
+ }
+}
+
+// this is done when you double click on a file
+void ListPanelFunc::execute( QString& name ) {
+ if ( name == ".." ) {
+ dirUp();
+ return ;
+ }
+
+ vfile *vf = files() ->vfs_search( name );
+ if ( vf == 0 )
+ return ;
+
+ KURL origin = files() ->vfs_getOrigin();
+
+ QString protocol = origin.isLocalFile() ? KrServices::registerdProtocol( vf->vfile_getMime() ) : "";
+
+ if ( protocol == "tar" || protocol == "krarc" ) {
+ bool encrypted;
+ QString type = KRarcHandler::getType( encrypted, vf->vfile_getUrl().path(), vf->vfile_getMime(), false );
+ if ( !KRarcHandler::arcHandled( type ) ) // if the specified archive is disabled delete the protocol
+ protocol = "";
+ }
+
+ if ( vf->vfile_isDir() ) {
+ origin = files() ->vfs_getFile( name );
+ panel->view->setNameToMakeCurrent( QString::null );
+ openUrl( origin );
+ } else if ( !protocol.isEmpty() ) {
+ KURL path = files() ->vfs_getFile( vf->vfile_getName() );
+ path.setProtocol( protocol );
+ openUrl( path );
+ } else {
+ KURL url = files() ->vfs_getFile( name );
+ KFileItem kfi( vf->vfile_getEntry(), url,true );
+ kfi.run();
+ }
+}
+
+void ListPanelFunc::dirUp() {
+ openUrl( files() ->vfs_getOrigin().upURL(), files() ->vfs_getOrigin().fileName() );
+}
+
+void ListPanelFunc::pack() {
+ QStringList fileNames;
+ panel->getSelectedNames( &fileNames );
+ if ( fileNames.isEmpty() )
+ return ; // safety
+
+ if ( fileNames.count() == 0 )
+ return ; // nothing to pack
+
+ // choose the default name
+ QString defaultName = panel->virtualPath().fileName();
+ if ( defaultName == "" )
+ defaultName = "pack";
+ if ( fileNames.count() == 1 )
+ defaultName = fileNames.first();
+ // ask the user for archive name and packer
+ new PackGUI( defaultName, vfs::pathOrURL( panel->otherPanel->virtualPath(), -1 ), fileNames.count(), fileNames.first() );
+ if ( PackGUI::type == QString::null )
+ return ; // the user canceled
+
+ // check for partial URLs
+ if( !PackGUI::destination.contains(":/") && !PackGUI::destination.startsWith("/") ){
+ PackGUI::destination = panel->virtualPath().prettyURL()+"/"+PackGUI::destination;
+ }
+
+ QString destDir = PackGUI::destination;
+ if( !destDir.endsWith( "/" ) )
+ destDir += "/";
+
+ bool packToOtherPanel = ( destDir == panel->otherPanel->virtualPath().prettyURL(1) );
+
+ // on remote URL-s first pack into a temp file then copy to its right place
+ KURL destURL = vfs::fromPathOrURL( destDir + PackGUI::filename + "." + PackGUI::type );
+ KTempFile *tempDestFile = 0;
+ QString arcFile;
+ if ( destURL.isLocalFile() )
+ arcFile = destURL.path();
+ else if( destURL.protocol() == "virt" ) {
+ KMessageBox::error( krApp, i18n( "Cannot pack files onto a virtual destination!" ) );
+ return;
+ }
+ else {
+ tempDestFile = new KTempFile( QString::null, "." + PackGUI::type );
+ tempDestFile->setAutoDelete( true );
+ arcFile = tempDestFile->name();
+ QFile::remove
+ ( arcFile );
+ }
+
+ if ( QFileInfo( arcFile ).exists() ) {
+ QString msg = i18n( "<qt><p>The archive <b>%1.%2</b> already exists. Do you want to overwrite it?</p><p>All data in the previous archive will be lost!</p></qt>").arg(PackGUI::filename).arg(PackGUI::type);
+ if( PackGUI::type == "zip" ) {
+ msg = i18n( "<qt><p>The archive <b>%1.%2</b> already exists. Do you want to overwrite it?</p><p>Zip will replace identically named entries in the zip archive or add entries for new names.</p></qt>").arg(PackGUI::filename).arg(PackGUI::type);
+ }
+ if ( KMessageBox::warningContinueCancel( krApp,msg,QString::null,i18n( "&Overwrite" ))
+ == KMessageBox::Cancel )
+ return ; // stop operation
+ }
+ // tell the user to wait
+ krApp->startWaiting( i18n( "Counting files to pack" ), 0, true );
+
+ // get the files to be packed:
+ files() ->vfs_getFiles( &fileNames );
+
+ KIO::filesize_t totalSize = 0;
+ unsigned long totalDirs = 0, totalFiles = 0;
+ if( !calcSpace( fileNames, totalSize, totalFiles, totalDirs ) )
+ return;
+
+ // download remote URL-s if necessary
+ QString arcDir;
+ KTempDir *tempDir = 0;
+
+ if ( files() ->vfs_getOrigin().isLocalFile() )
+ arcDir = files() ->vfs_workingDir();
+ else {
+ tempDir = new KTempDir();
+ tempDir->setAutoDelete( true );
+ arcDir = tempDir->name();
+ KURL::List *urlList = files() ->vfs_getFiles( &fileNames );
+ KIO::NetAccess::dircopy( *urlList, vfs::fromPathOrURL( arcDir ), 0 );
+ delete urlList;
+ }
+
+ // pack the files
+ // we must chdir() first because we supply *names* not URL's
+ QString save = getcwd( 0, 0 );
+ chdir( arcDir.local8Bit() );
+ KRarcHandler::pack( fileNames, PackGUI::type, arcFile, totalFiles + totalDirs, PackGUI::extraProps );
+ chdir( save.local8Bit() );
+
+ // delete the temporary directory if created
+ if ( tempDir )
+ delete tempDir;
+
+ // copy from the temp file to it's right place
+ if ( tempDestFile ) {
+ KIO::NetAccess::file_move( vfs::fromPathOrURL( arcFile ), destURL );
+ delete tempDestFile;
+ }
+
+ if ( packToOtherPanel )
+ panel->otherPanel->func->refresh();
+}
+
+void ListPanelFunc::testArchive() {
+ QString arcName = panel->getCurrentName();
+ if ( arcName.isNull() )
+ return ;
+ if ( arcName == ".." )
+ return ; // safety
+
+ KURL arcURL = files() ->vfs_getFile( arcName );
+ QString url = QString::null;
+
+ // download the file if it's on a remote filesystem
+ if ( !arcURL.isLocalFile() ) {
+ url = locateLocal( "tmp", QString( arcName ) );
+ if ( !KIO::NetAccess::download( arcURL, url, 0 ) ) {
+ KMessageBox::sorry( krApp, i18n( "Krusader is unable to download: " ) + arcURL.fileName() );
+ return ;
+ }
+ } else
+ url = arcURL.path( -1 );
+
+ QString mime = files() ->vfs_search( arcName ) ->vfile_getMime();
+ bool encrypted = false;
+ QString type = KRarcHandler::getType( encrypted, url, mime );
+
+ // check we that archive is supported
+ if ( !KRarcHandler::arcSupported( type ) ) {
+ KMessageBox::sorry( krApp, i18n( "%1, unknown archive type." ).arg( arcName ) );
+ return ;
+ }
+
+ QString password = encrypted ? KRarcHandler::getPassword( url ) : QString::null;
+
+ // test the archive
+ if ( KRarcHandler::test( url, type, password ) )
+ KMessageBox::information( krApp, i18n( "%1, test passed." ).arg( arcName ) );
+ else
+ KMessageBox::error( krApp, i18n( "%1, test failed!" ).arg( arcName ) );
+
+ // remove the downloaded file if necessary
+ if ( url != arcURL.path( -1 ) )
+ QFile( url ).remove();
+}
+
+void ListPanelFunc::unpack() {
+
+ QStringList fileNames;
+ panel->getSelectedNames( &fileNames );
+ if ( fileNames.isEmpty() )
+ return ; // safety
+
+ QString s;
+ if(fileNames.count() == 1)
+ s = i18n("Unpack %1 to:").arg(fileNames[0]);
+ else
+ s = i18n("Unpack %n file to:", "Unpack %n files to:", fileNames.count());
+
+ // ask the user for the copy dest
+ KURL dest = KChooseDir::getDir(s, panel->otherPanel->virtualPath(), panel->virtualPath());
+ if ( dest.isEmpty() ) return ; // the user canceled
+
+ bool packToOtherPanel = ( dest.equals( panel->otherPanel->virtualPath(), true ) );
+
+ for ( unsigned int i = 0; i < fileNames.count(); ++i ) {
+ QString arcName = fileNames[ i ];
+ if ( arcName.isNull() )
+ return ;
+ if ( arcName == ".." )
+ return ; // safety
+
+ // download the file if it's on a remote filesystem
+ KURL arcURL = files() ->vfs_getFile( arcName );
+ QString url = QString::null;
+ if ( !arcURL.isLocalFile() ) {
+ url = locateLocal( "tmp", QString( arcName ) );
+ if ( !KIO::NetAccess::download( arcURL, url, 0 ) ) {
+ KMessageBox::sorry( krApp, i18n( "Krusader is unable to download: " ) + arcURL.fileName() );
+ continue;
+ }
+ } else
+ url = arcURL.path( -1 );
+
+ // if the destination is in remote directory use temporary one instead
+ dest.adjustPath(1);
+ KURL originalDestURL;
+ KTempDir *tempDir = 0;
+
+ if ( !dest.isLocalFile() ) {
+ originalDestURL = dest;
+ tempDir = new KTempDir();
+ tempDir->setAutoDelete( true );
+ dest = tempDir->name();
+ }
+
+ // determining the type
+ QString mime = files() ->vfs_search( arcName ) ->vfile_getMime();
+ bool encrypted = false;
+ QString type = KRarcHandler::getType( encrypted, url, mime );
+
+ // check we that archive is supported
+ if ( !KRarcHandler::arcSupported( type ) ) {
+ KMessageBox::sorry( krApp, i18n( "%1, unknown archive type" ).arg( arcName ) );
+ continue;
+ }
+
+ QString password = encrypted ? KRarcHandler::getPassword( url ) : QString::null;
+
+ // unpack the files
+ KRarcHandler::unpack( url, type, password, dest.path( -1 ) );
+
+ // remove the downloaded file if necessary
+ if ( url != arcURL.path( -1 ) )
+ QFile( url ).remove();
+
+ // copy files to the destination directory at remote files
+ if ( tempDir ) {
+ QStringList nameList = QDir( dest.path( -1 ) ).entryList();
+ KURL::List urlList;
+ for ( unsigned int i = 0; i != nameList.count(); i++ )
+ if ( nameList[ i ] != "." && nameList[ i ] != ".." )
+ urlList.append( vfs::fromPathOrURL( dest.path( 1 ) + nameList[ i ] ) );
+ if ( urlList.count() > 0 )
+ KIO::NetAccess::dircopy( urlList, originalDestURL, 0 );
+ delete tempDir;
+ }
+ }
+ if ( packToOtherPanel )
+ panel->otherPanel->func->refresh();
+}
+
+// a small ugly function, used to prevent duplication of EVERY line of
+// code (maybe except 3) from createChecksum and matchChecksum
+static void checksum_wrapper(ListPanel *panel, QStringList& args, bool &folders) {
+ KrViewItemList items;
+ panel->view->getSelectedKrViewItems( &items );
+ if ( items.isEmpty() ) return ; // nothing to do
+ // determine if we need recursive mode (md5deep)
+ folders=false;
+ for ( KrViewItemList::Iterator it = items.begin(); it != items.end(); ++it ) {
+ if (panel->func->getVFile(*it)->vfile_isDir()) {
+ folders = true;
+ args << (*it)->name();
+ } else args << (*it)->name();
+ }
+}
+
+void ListPanelFunc::createChecksum() {
+ QStringList args;
+ bool folders;
+ checksum_wrapper(panel, args, folders);
+ CreateChecksumDlg dlg(args, folders, panel->realPath());
+}
+
+void ListPanelFunc::matchChecksum() {
+ QStringList args;
+ bool folders;
+ checksum_wrapper(panel, args, folders);
+ QValueList<vfile*> checksumFiles = files()->vfs_search(
+ KRQuery(MatchChecksumDlg::checksumTypesFilter)
+ );
+ MatchChecksumDlg dlg(args, folders, panel->realPath(),
+ (checksumFiles.size()==1 ? checksumFiles[0]->vfile_getUrl().prettyURL() : QString::null));
+}
+
+void ListPanelFunc::calcSpace() {
+ QStringList items;
+ panel->view->getSelectedItems( &items );
+ if ( items.isEmpty() ) {
+ panel->view->selectAllIncludingDirs();
+ panel->view->getSelectedItems( &items );
+ if ( items.isEmpty() )
+ return ; // nothing to do
+ }
+
+ KrCalcSpaceDialog calc( krApp, panel, items, false );
+ calc.exec();
+ for ( QStringList::ConstIterator it = items.begin(); it != items.end(); ++it ) {
+ KrViewItem *viewItem = panel->view->findItemByName( *it );
+ if ( viewItem )
+ panel->view->updateItem(viewItem);
+ }
+ panel->slotUpdateTotals();
+}
+
+bool ListPanelFunc::calcSpace( const QStringList & items, KIO::filesize_t & totalSize, unsigned long & totalFiles, unsigned long & totalDirs ) {
+ KrCalcSpaceDialog calc( krApp, panel, items, true );
+ calc.exec();
+ totalSize = calc.getTotalSize();
+ totalFiles = calc.getTotalFiles();
+ totalDirs = calc.getTotalDirs();
+ return !calc.wasCanceled();
+}
+
+void ListPanelFunc::FTPDisconnect() {
+ // you can disconnect only if connected !
+ if ( files() ->vfs_getType() == vfs::FTP ) {
+ krFTPDiss->setEnabled( false );
+ panel->view->setNameToMakeCurrent( QString::null );
+ openUrl( panel->realPath() ); // open the last local URL
+ }
+}
+
+void ListPanelFunc::newFTPconnection() {
+ KURL url = KRSpWidgets::newFTP();
+ // if the user canceled - quit
+ if ( url.isEmpty() )
+ return ;
+
+ krFTPDiss->setEnabled( true );
+ openUrl( url );
+}
+
+void ListPanelFunc::properties() {
+ QStringList names;
+ panel->getSelectedNames( &names );
+ if ( names.isEmpty() )
+ return ; // no names...
+ KFileItemList fi;
+ fi.setAutoDelete( true );
+
+ for ( unsigned int i = 0 ; i < names.count() ; ++i ) {
+ vfile* vf = files() ->vfs_search( names[ i ] );
+ if ( !vf )
+ continue;
+ KURL url = files()->vfs_getFile( names[i] );
+ fi.append( new KFileItem( vf->vfile_getEntry(), url ) );
+ }
+
+ if ( fi.isEmpty() )
+ return ;
+
+ // Show the properties dialog
+ KPropertiesDialog *dlg = new KPropertiesDialog( fi );
+ connect( dlg, SIGNAL( applied() ), SLOTS, SLOT( refresh() ) );
+}
+
+void ListPanelFunc::refreshActions() {
+ vfs::VFS_TYPE vfsType = files() ->vfs_getType();
+
+ // set up actions
+ krMultiRename->setEnabled( vfsType == vfs::NORMAL ); // batch rename
+ //krProperties ->setEnabled( vfsType == vfs::NORMAL || vfsType == vfs::FTP ); // file properties
+ krFTPDiss ->setEnabled( vfsType == vfs::FTP ); // disconnect an FTP session
+ krCreateCS->setEnabled( vfsType == vfs::NORMAL );
+ /*
+ krUnpack->setEnabled(true); // unpack archive
+ krTest->setEnabled(true); // test archive
+ krSelect->setEnabled(true); // select a group by filter
+ krSelectAll->setEnabled(true); // select all files
+ krUnselect->setEnabled(true); // unselect by filter
+ krUnselectAll->setEnabled( true); // remove all selections
+ krInvert->setEnabled(true); // invert the selection
+ krFTPConnect->setEnabled(true); // connect to an ftp
+ krFTPNew->setEnabled(true); // create a new connection
+ krAllFiles->setEnabled(true); // show all files in list
+ krCustomFiles->setEnabled(true); // show a custom set of files
+ krBack->setEnabled(func->canGoBack()); // go back
+ krRoot->setEnabled(true); // go all the way up
+ krExecFiles->setEnabled(true); // show only executables
+ */
+}
+
+ListPanelFunc::~ListPanelFunc() {
+ if( !vfsP ) {
+ if( vfsP->vfs_canDelete() )
+ delete vfsP;
+ else {
+ connect( vfsP, SIGNAL( deleteAllowed() ), vfsP, SLOT( deleteLater() ) );
+ vfsP->vfs_requestDelete();
+ }
+ }
+ vfsP = 0;
+}
+
+vfs* ListPanelFunc::files() {
+ if ( !vfsP )
+ vfsP = KrVfsHandler::getVfs( "/", panel, 0 );
+ return vfsP;
+}
+
+
+void ListPanelFunc::copyToClipboard( bool move ) {
+ if( files()->vfs_getOrigin().equals( KURL("virt:/"), true ) ) {
+ if( move )
+ KMessageBox::error( krApp, i18n( "Cannot cut a virtual URL collection to the clipboard!" ) );
+ else
+ KMessageBox::error( krApp, i18n( "Cannot copy a virtual URL collection onto the clipboard!" ) );
+ return;
+ }
+
+ QStringList fileNames;
+
+ panel->getSelectedNames( &fileNames );
+ if ( fileNames.isEmpty() )
+ return ; // safety
+
+ KURL::List* fileUrls = files() ->vfs_getFiles( &fileNames );
+ if ( fileUrls ) {
+ KRDrag * urlData = KRDrag::newDrag( *fileUrls, move, krApp->mainView, "krusader" );
+ QApplication::clipboard() ->setData( urlData );
+
+ if( move && files()->vfs_getType() == vfs::VIRT )
+ ( static_cast<virt_vfs*>( files() ) )->vfs_removeFiles( &fileNames );
+
+ delete fileUrls;
+ }
+}
+
+void ListPanelFunc::pasteFromClipboard() {
+ QClipboard * cb = QApplication::clipboard();
+ QMimeSource * data = cb->data();
+ KURL::List urls;
+ if ( KURLDrag::canDecode( data ) ) {
+ KURLDrag::decode( data, urls );
+ bool cutSelection = KRDrag::decodeIsCutSelection( data );
+
+ KURL destUrl = panel->virtualPath();
+
+ files()->vfs_addFiles( &urls, cutSelection ? KIO::CopyJob::Move : KIO::CopyJob::Copy, otherFunc()->files(),
+ "", PM_DEFAULT );
+ }
+}
+
+#include "panelfunc.moc"
diff --git a/krusader/Panel/panelfunc.h b/krusader/Panel/panelfunc.h
new file mode 100644
index 0000000..1274e11
--- /dev/null
+++ b/krusader/Panel/panelfunc.h
@@ -0,0 +1,105 @@
+/***************************************************************************
+ panelfunc.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef PANELFUNC_H
+#define PANELFUNC_H
+#include "listpanel.h"
+#include "krviewitem.h"
+#include <qobject.h>
+#include <qvaluestack.h>
+#include <qtimer.h>
+
+class ListPanelFunc : public QObject{
+friend class ListPanel;
+ Q_OBJECT
+public slots:
+ inline vfile* getVFile(KrViewItem *item) { return files()->vfs_search(item->name()); }
+ inline vfile* getVFile(const QString& name) { return files()->vfs_search(name); }
+ void execute(QString&);
+ void openUrl(const KURL& path, const QString& nameToMakeCurrent = QString::null);
+ void openUrl(const QString& path, const QString& nameToMakeCurrent = QString::null);
+ void immediateOpenUrl( const KURL& path);
+ void doOpenUrl();
+ void refresh();
+ void rename(const QString &oldname, const QString &newname);
+
+public:
+ ListPanelFunc(class ListPanel *parent);
+ ~ListPanelFunc();
+
+ vfs* files(); // return a pointer to the vfs
+
+ void refreshActions();
+ void redirectLink();
+ void krlink(bool sym);
+ void goBack();
+ void dirUp();
+ void properties();
+ void terminal();
+ void editFile();
+ void view();
+ void rename();
+ void mkdir();
+ void moveFiles();
+ void pack();
+ void unpack();
+ void testArchive();
+ void copyFiles();
+ void deleteFiles(bool reallyDelete=false);
+ void calcSpace(); // calculate the occupied space and show it in a dialog
+ void createChecksum();
+ void matchChecksum();
+ void copyToClipboard( bool move=false );
+ void pasteFromClipboard();
+
+ // calculate the occupied space. A dialog appears, if calculation lasts more than 3 seconds
+ // and disappears, if the calculation is done. Returns true, if the result is ok and false
+ // otherwise (Cancel was pressed).
+ bool calcSpace(const QStringList & items,KIO::filesize_t & totalSize,unsigned long & totalFiles,unsigned long & totalDirs);
+ void FTPDisconnect();
+ void newFTPconnection();
+ inline ListPanelFunc* otherFunc(){ return panel->otherPanel->func; }
+
+private:
+ KURL getVirtualBaseURL();
+
+protected:
+ ListPanel* panel; // our ListPanel
+ QValueStack<KURL> urlStack; // Path stack for the "back" button
+ bool inRefresh; // true when we are in refresh()
+ vfs* vfsP; // pointer to vfs.
+ QTimer delayTimer;
+ KURL delayURL;
+ QString nameToMakeCurrent;
+};
+
+#endif
diff --git a/krusader/Panel/panelpopup.cpp b/krusader/Panel/panelpopup.cpp
new file mode 100644
index 0000000..deaec38
--- /dev/null
+++ b/krusader/Panel/panelpopup.cpp
@@ -0,0 +1,400 @@
+#include "../krusader.h"
+#include "panelpopup.h"
+#include "../kicons.h"
+#include "../Dialogs/krsqueezedtextlabel.h"
+#include "../defaults.h"
+#include "../krslots.h"
+#include "panelfunc.h"
+#include <qtooltip.h>
+#include <qbuttongroup.h>
+#include <qtoolbutton.h>
+#include <kfiletreeview.h>
+#include <klocale.h>
+#include <qcursor.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qheader.h>
+#include <krview.h>
+#include <krviewitem.h>
+#include <klineedit.h>
+#include <kio/jobclasses.h>
+#include "../KViewer/kimagefilepreview.h"
+#include "../KViewer/panelviewer.h"
+#include "../KViewer/diskusageviewer.h"
+
+PanelPopup::PanelPopup( QSplitter *parent, bool left ) : QWidget( parent ),
+ _left( left ), _hidden(true), stack( 0 ), viewer( 0 ), pjob( 0 ), splitterSizes() {
+ splitter = parent;
+ QGridLayout * layout = new QGridLayout(this, 1, 1);
+
+ // loading the splitter sizes
+ krConfig->setGroup( "Private" );
+ if( left )
+ splitterSizes = krConfig->readIntListEntry( "Left PanelPopup Splitter Sizes" );
+ else
+ splitterSizes = krConfig->readIntListEntry( "Right PanelPopup Splitter Sizes" );
+
+ if( splitterSizes.count() < 2 ) {
+ splitterSizes.clear();
+ splitterSizes.push_back( 100 );
+ splitterSizes.push_back( 100 );
+ }
+
+ // create the label+buttons setup
+ dataLine = new KrSqueezedTextLabel(this);
+ dataLine->setText("blah blah");
+ connect( dataLine, SIGNAL( clicked() ), this, SLOT( setFocus() ) );
+ krConfig->setGroup( "Look&Feel" );
+ dataLine->setFont( krConfig->readFontEntry( "Filelist Font", _FilelistFont ) );
+ // --- hack: setup colors to be the same as an inactive panel
+ dataLine->setBackgroundMode( PaletteBackground );
+ QPalette q( dataLine->palette() );
+ q.setColor( QColorGroup::Foreground, KGlobalSettings::textColor() );
+ q.setColor( QColorGroup::Background, KGlobalSettings::baseColor() );
+ dataLine->setPalette( q );
+ dataLine->setFrameStyle( QFrame::Box | QFrame::Raised );
+ dataLine->setLineWidth( 1 ); // a nice 3D touch :-)
+ int sheight = QFontMetrics( dataLine->font() ).height() + 4;
+ dataLine->setMaximumHeight( sheight );
+
+ btns = new QButtonGroup(this);
+ btns->setExclusive(true);
+ btns->hide(); // it should be invisible
+ connect(btns, SIGNAL(clicked(int)), this, SLOT(tabSelected(int)));
+
+ treeBtn = new QToolButton(this);
+ QToolTip::add(treeBtn, i18n("Tree Panel: a tree view of the local file system"));
+ treeBtn->setPixmap(krLoader->loadIcon( "view_tree", KIcon::Toolbar, 16 ));
+ treeBtn->setFixedSize(20, 20);
+ treeBtn->setToggleButton(true);
+ btns->insert(treeBtn, Tree);
+
+
+ previewBtn = new QToolButton(this);
+ QToolTip::add(previewBtn, i18n("Preview Panel: display a preview of the current file"));
+ previewBtn->setPixmap(krLoader->loadIcon( "thumbnail", KIcon::Toolbar, 16 ));
+ previewBtn->setFixedSize(20, 20);
+ previewBtn->setToggleButton(true);
+ btns->insert(previewBtn, Preview);
+
+ quickBtn = new QToolButton(this);
+ QToolTip::add(quickBtn, i18n("Quick Panel: quick way to perform actions"));
+ quickBtn->setPixmap(krLoader->loadIcon( "misc", KIcon::Toolbar, 16 ));
+ quickBtn->setFixedSize(20, 20);
+ quickBtn->setToggleButton(true);
+ btns->insert(quickBtn, QuickPanel);
+
+ viewerBtn = new QToolButton(this);
+ QToolTip::add(viewerBtn, i18n("View Panel: view the current file"));
+ viewerBtn->setPixmap(krLoader->loadIcon( "viewmag", KIcon::Toolbar, 16 ));
+ viewerBtn->setFixedSize(20, 20);
+ viewerBtn->setToggleButton(true);
+ btns->insert(viewerBtn, View);
+
+ duBtn = new QToolButton(this);
+ QToolTip::add(duBtn, i18n("Disk Usage Panel: view the usage of a directory"));
+ duBtn->setPixmap(krLoader->loadIcon( "kr_diskusage", KIcon::Toolbar, 16 ));
+ duBtn->setFixedSize(20, 20);
+ duBtn->setToggleButton(true);
+ btns->insert(duBtn, DskUsage);
+
+ layout->addWidget(dataLine,0,0);
+ layout->addWidget(treeBtn,0,1);
+ layout->addWidget(previewBtn,0,2);
+ layout->addWidget(quickBtn,0,3);
+ layout->addWidget(viewerBtn,0,4);
+ layout->addWidget(duBtn,0,5);
+
+ // create a widget stack on which to put the parts
+ stack = new QWidgetStack( this );
+
+ // create the tree part ----------
+ tree = new KFileTreeView( stack );
+ tree->setAcceptDrops(true);
+ connect(tree, SIGNAL(dropped (QWidget *, QDropEvent *, KURL::List &, KURL &)),
+ this, SLOT(slotDroppedOnTree(QWidget *, QDropEvent *, KURL::List&, KURL& )));
+ stack->addWidget( tree, Tree );
+ tree->addColumn( "" );
+ // add ~
+ tree->addBranch( QDir::home().absPath(), i18n("Home"));
+ tree->setDirOnlyMode( tree->branch(i18n("Home")), true);
+ tree->branch(i18n("Home"))->setChildRecurse(false);
+ // add /
+ tree->addBranch( "/", i18n( "Root" ) );
+ tree->setDirOnlyMode( tree->branch( i18n( "Root" ) ), true );
+ tree->setShowFolderOpenPixmap(true);
+ tree->branch( i18n( "Root" ) ) ->setChildRecurse(false);
+ tree->branch( i18n( "Root" ) ) ->setOpen( true );
+ tree->header() ->setHidden( true );
+ connect(tree, SIGNAL(doubleClicked(QListViewItem*)), this, SLOT(treeSelection(QListViewItem*)));
+ // start listing the tree
+ tree->branch( i18n( "Root" ) ) ->root();
+ tree->branch( i18n( "Home" ) ) ->root();
+
+ // create the quickview part ------
+ viewer = new KrusaderImageFilePreview(stack);
+ stack->addWidget( viewer, Preview );
+
+ // create the panelview
+
+ panelviewer = new PanelViewer(stack);
+ stack->addWidget(panelviewer, View);
+ connect(panelviewer, SIGNAL(openURLRequest(const KURL &)), this, SLOT(handleOpenURLRequest(const KURL &)));
+
+ // create the disk usage view
+
+ diskusage = new DiskUsageViewer( stack );
+ diskusage->setStatusLabel( dataLine, i18n("Disk Usage: ") );
+ stack->addWidget( diskusage, DskUsage );
+ connect(diskusage, SIGNAL(openURLRequest(const KURL &)), this, SLOT(handleOpenURLRequest(const KURL &)));
+
+ // create the quick-panel part ----
+
+ QWidget *quickPanel = new QWidget(stack);
+ QGridLayout *qlayout = new QGridLayout(quickPanel);
+ // --- quick select
+ QLabel *selectLabel = new QLabel(i18n("Quick Select"), quickPanel);
+ quickSelectCombo = new KComboBox( quickPanel );
+ quickSelectCombo->setEditable( true );
+ krConfig->setGroup( "Private" );
+ QStrList lst;
+ int i = krConfig->readListEntry( "Predefined Selections", lst );
+ if ( i > 0 )
+ quickSelectCombo->insertStrList( lst );
+ quickSelectCombo->setCurrentText( "*" );
+ quickSelectCombo->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ) );
+
+ connect(quickSelectCombo, SIGNAL(returnPressed(const QString& )),
+ this, SLOT(quickSelect(const QString& )));
+
+ QToolButton *qselectBtn = new QToolButton(quickPanel);
+ qselectBtn->setPixmap(krLoader->loadIcon( "kr_selectall", KIcon::Toolbar, 16 ));
+ qselectBtn->setFixedSize(20, 20);
+ QToolTip::add( qselectBtn, i18n("apply the selection") );
+ connect(qselectBtn, SIGNAL(clicked()), this, SLOT(quickSelect()));
+
+ QToolButton *qstoreBtn = new QToolButton(quickPanel);
+ qstoreBtn->setPixmap(krLoader->loadIcon( "filesave", KIcon::Toolbar, 16 ));
+ qstoreBtn->setFixedSize(20, 20);
+ QToolTip::add( qstoreBtn, i18n("store the current selection") );
+ connect(qstoreBtn, SIGNAL(clicked()), this, SLOT(quickSelectStore()));
+
+ QToolButton *qsettingsBtn = new QToolButton(quickPanel);
+ qsettingsBtn->setPixmap(krLoader->loadIcon( "configure", KIcon::Toolbar, 16 ));
+ qsettingsBtn->setFixedSize(20, 20);
+ QToolTip::add( qsettingsBtn, i18n("select group dialog") );
+ connect(qsettingsBtn, SIGNAL(clicked()), krSelect, SLOT(activate()));
+
+ qlayout->addWidget(selectLabel,0,0);
+ qlayout->addWidget(quickSelectCombo,0,1);
+ qlayout->addWidget(qselectBtn,0,2);
+ qlayout->addWidget(qstoreBtn,0,3);
+ qlayout->addWidget(qsettingsBtn,0,4);
+ stack->addWidget(quickPanel, QuickPanel);
+
+ // -------- finish the layout (General one)
+ layout->addMultiCellWidget(stack,1,1,0,5);
+
+ // set the wanted widget
+ // ugly: are we left or right?
+ int id;
+ krConfig->setGroup("Startup");
+ if (left) {
+ id = krConfig->readNumEntry("Left Panel Popup", _LeftPanelPopup);
+ } else {
+ id = krConfig->readNumEntry("Right Panel Popup", _RightPanelPopup);
+ }
+ btns->setButton(id);
+
+ hide(); // for not to open the 3rd hand tool at start (selecting the last used tab)
+ tabSelected(id);
+}
+
+PanelPopup::~PanelPopup() {}
+
+void PanelPopup::show() {
+ QWidget::show();
+ if( _hidden )
+ splitter->setSizes( splitterSizes );
+ _hidden = false;
+ tabSelected( stack->id(stack->visibleWidget()) );
+}
+
+
+void PanelPopup::hide() {
+ if( !_hidden )
+ splitterSizes = splitter->sizes();
+ QWidget::hide();
+ _hidden = true;
+ if (stack->id(stack->visibleWidget()) == View) panelviewer->closeURL();
+ if (stack->id(stack->visibleWidget()) == DskUsage) diskusage->closeURL();
+}
+
+void PanelPopup::setFocus() {
+ switch ( stack->id( stack->visibleWidget() ) ) {
+ case Preview:
+ if( !isHidden() )
+ viewer->setFocus();
+ break;
+ case View:
+ if( !isHidden() && panelviewer->part() && panelviewer->part()->widget() )
+ panelviewer->part()->widget()->setFocus();
+ break;
+ case DskUsage:
+ if( !isHidden() && diskusage->getWidget() && diskusage->getWidget()->visibleWidget() )
+ diskusage->getWidget()->visibleWidget()->setFocus();
+ break;
+ case Tree:
+ if( !isHidden() )
+ tree->setFocus();
+ break;
+ case QuickPanel:
+ if( !isHidden() )
+ quickSelectCombo->setFocus();
+ break;
+ }
+}
+
+void PanelPopup::saveSizes() {
+ krConfig->setGroup( "Private" );
+
+ if( !isHidden() )
+ splitterSizes = splitter->sizes();
+
+ if( _left )
+ krConfig->writeEntry( "Left PanelPopup Splitter Sizes", splitterSizes );
+ else
+ krConfig->writeEntry( "Right PanelPopup Splitter Sizes", splitterSizes );
+}
+
+void PanelPopup::handleOpenURLRequest(const KURL &url) {
+ if (KMimeType::findByURL(url.url())->name() == "inode/directory") ACTIVE_PANEL->func->openUrl(url);
+}
+
+
+void PanelPopup::tabSelected( int id ) {
+ KURL url = "";
+ if ( ACTIVE_PANEL && ACTIVE_PANEL->func && ACTIVE_PANEL->func->files() && ACTIVE_PANEL->view ) {
+ url = ACTIVE_PANEL->func->files()->vfs_getFile( ACTIVE_PANEL->view->getCurrentItem());
+ }
+
+ stack->raiseWidget( id );
+
+ // if tab is tree, set something logical in the data line
+ switch (id) {
+ case Tree:
+ dataLine->setText( i18n("Tree:") );
+ if( !isHidden() )
+ tree->setFocus();
+ break;
+ case Preview:
+ dataLine->setText( i18n("Preview:") );
+ update(url);
+ break;
+ case QuickPanel:
+ dataLine->setText( i18n("Quick Select:") );
+ if( !isHidden() )
+ quickSelectCombo->setFocus();
+ break;
+ case View:
+ dataLine->setText( i18n("View:") );
+ update(url);
+ if( !isHidden() && panelviewer->part() && panelviewer->part()->widget() )
+ panelviewer->part()->widget()->setFocus();
+ break;
+ case DskUsage:
+ dataLine->setText( i18n("Disk Usage:") );
+ update(url);
+ if( !isHidden() && diskusage->getWidget() && diskusage->getWidget()->visibleWidget() )
+ diskusage->getWidget()->visibleWidget()->setFocus();
+ break;
+ }
+ if (id != View) panelviewer->closeURL();
+}
+
+// decide which part to update, if at all
+void PanelPopup::update( KURL url ) {
+ if ( isHidden() || url.url()=="" ) return ; // failsafe
+
+ KFileItemList lst;
+
+ switch ( stack->id( stack->visibleWidget() ) ) {
+ case Preview:
+ viewer->showPreview(url);
+ dataLine->setText( i18n("Preview: ")+url.fileName() );
+ break;
+ case View:
+ panelviewer->openURL(url);
+ dataLine->setText( i18n("View: ")+url.fileName() );
+ break;
+ case DskUsage:
+ if( url.fileName() == ".." )
+ url.setFileName( "" );
+ if (KMimeType::findByURL(url.url())->name() != "inode/directory")
+ url = url.upURL();
+ dataLine->setText( i18n("Disk Usage: ")+url.fileName() );
+ diskusage->openURL(url);
+ break;
+ case Tree: // nothing to do
+ break;
+ }
+}
+
+// ------------------- tree
+
+void PanelPopup::treeSelection(QListViewItem*) {
+ emit selection(tree->currentURL());
+ //emit hideMe();
+}
+
+// ------------------- quick panel
+
+void PanelPopup::quickSelect() {
+ SLOTS->markGroup(quickSelectCombo->currentText(), true);
+}
+
+void PanelPopup::quickSelect(const QString &mask) {
+ SLOTS->markGroup(mask, true);
+}
+
+void PanelPopup::quickSelectStore() {
+ krConfig->setGroup( "Private" );
+ QStringList lst = krConfig->readListEntry( "Predefined Selections" );
+ if ( lst.find(quickSelectCombo->currentText()) == lst.end() )
+ lst.append( quickSelectCombo->currentText() );
+ krConfig->writeEntry( "Predefined Selections", lst );
+}
+
+void PanelPopup::slotDroppedOnTree(QWidget *widget, QDropEvent *e, KURL::List &lst, KURL &) {
+ // KFileTreeView is buggy: when dropped, it might not give us the correct
+ // destination, but actually, it's parent. workaround: don't use
+ // the destination in the signal, but take the current item
+ KURL dest = tree->currentURL();
+
+ // ask the user what to do: copy, move or link?
+ QPopupMenu popup( this );
+ popup.insertItem( i18n( "Copy Here" ), 1 );
+ popup.insertItem( i18n( "Move Here" ), 2 );
+ popup.insertItem( i18n( "Link Here" ), 3 );
+ popup.insertItem( i18n( "Cancel" ), 4 );
+ QPoint tmp = widget->mapToGlobal( e->pos() );
+ int result = popup.exec( QCursor::pos() );
+
+ KIO::CopyJob *job;
+ switch ( result ) {
+ case 1 :
+ job = KIO::copy(lst, dest, true);
+ break;
+ case 2 :
+ job = KIO::move(lst, dest, true);
+ break;
+ case 3 :
+ job = KIO::link(lst, dest, true);
+ break;
+ case - 1 : // user pressed outside the menu
+ case 4:
+ return ; // cancel was pressed;
+ }
+}
+
+#include "panelpopup.moc"
diff --git a/krusader/Panel/panelpopup.h b/krusader/Panel/panelpopup.h
new file mode 100644
index 0000000..3c09a0b
--- /dev/null
+++ b/krusader/Panel/panelpopup.h
@@ -0,0 +1,73 @@
+#ifndef _PANELPOPUP_H
+#define _PANELPOPUP_H
+
+#include <qwidget.h>
+#include <qwidgetstack.h>
+#include <qpixmap.h>
+#include <qvaluelist.h>
+#include <kfileitem.h>
+#include <qguardedptr.h>
+#include <kio/previewjob.h>
+#include <kurl.h>
+
+class QButtonGroup;
+class QLabel;
+class QListViewItem;
+class QSplitter;
+class KFileTreeView;
+class QToolButton;
+class KrSqueezedTextLabel;
+class KLineEdit;
+class KComboBox;
+class KrusaderImageFilePreview;
+class PanelViewer;
+class DiskUsageViewer;
+
+class PanelPopup: public QWidget {
+ Q_OBJECT
+ enum Parts { Tree, Preview, QuickPanel, View, DskUsage, Last=0xFF };
+public:
+ PanelPopup( QSplitter *splitter, bool left );
+ ~PanelPopup();
+ inline int currentPage() const { return stack->id(stack->visibleWidget()); }
+
+ void saveSizes();
+
+public slots:
+ void update(KURL url);
+ void show();
+ void hide();
+
+signals:
+ void selection(const KURL &url);
+ void hideMe();
+
+protected slots:
+ virtual void setFocus();
+ void tabSelected(int id);
+ void treeSelection(QListViewItem*);
+ void slotDroppedOnTree(QWidget *widget, QDropEvent *e, KURL::List &lst, KURL &);
+ void handleOpenURLRequest(const KURL &url);
+ void quickSelect();
+ void quickSelect(const QString &);
+ void quickSelectStore();
+
+protected:
+ bool _left;
+ bool _hidden;
+ QWidgetStack *stack;
+ KrusaderImageFilePreview *viewer;
+ KrSqueezedTextLabel *dataLine;
+ QGuardedPtr<KIO::PreviewJob> pjob;
+ KFileTreeView *tree;
+ QToolButton *treeBtn, *previewBtn, *quickBtn, *viewerBtn, *duBtn;
+ QButtonGroup *btns;
+ KLineEdit *quickFilter;
+ KComboBox *quickSelectCombo;
+ PanelViewer *panelviewer;
+ DiskUsageViewer *diskusage;
+ QValueList<int> splitterSizes;
+ QSplitter *splitter;
+};
+
+#endif // _PANELPOPUP_H
diff --git a/krusader/Queue/Makefile.am b/krusader/Queue/Makefile.am
new file mode 100644
index 0000000..1630c6a
--- /dev/null
+++ b/krusader/Queue/Makefile.am
@@ -0,0 +1,10 @@
+noinst_LIBRARIES = libQueue.a
+
+INCLUDES = $(all_includes)
+
+libQueue_a_METASOURCES = AUTO
+
+libQueue_a_SOURCES = \
+ queue.cpp \
+ queue_mgr.cpp \
+ queuewidget.cpp
diff --git a/krusader/Queue/queue.cpp b/krusader/Queue/queue.cpp
new file mode 100644
index 0000000..3232778
--- /dev/null
+++ b/krusader/Queue/queue.cpp
@@ -0,0 +1,22 @@
+#include "queue.h"
+
+Queue::Queue(const QString& name): _name(name)
+{
+}
+
+Queue::~Queue()
+{
+ // TODO: save queue on delete? or just delete jobs
+}
+
+void Queue::enqueue(KIO::Job *job)
+{
+ _jobs.append(job);
+
+ dumpQueue();
+}
+
+void Queue::dumpQueue()
+{
+ qDebug("Queue: %s", name().latin1());
+}
diff --git a/krusader/Queue/queue.h b/krusader/Queue/queue.h
new file mode 100644
index 0000000..093998a
--- /dev/null
+++ b/krusader/Queue/queue.h
@@ -0,0 +1,32 @@
+#ifndef QUEUE_H
+#define QUEUE_H
+
+#include <qobject.h>
+#include <kio/jobclasses.h>
+#include <qptrlist.h>
+
+/**
+ * Queue can hold anything which inherits KIO::Job, and schedule it, start it, stop etc...
+ * the main reason to hold the Job itself (at least for phase 1) is to keep the code
+ * in krusader relatively unchaged, and allow to create the job as usual and choose if
+ * to start it, or queue it.
+ *
+ */
+class Queue: public QObject
+{
+ Q_OBJECT
+public:
+ Queue(const QString& name);
+ virtual ~Queue();
+
+ inline const QString& name() const { return _name; }
+ void enqueue(KIO::Job *job);
+
+protected:
+ void dumpQueue();
+
+ QString _name;
+ QPtrList<KIO::Job> _jobs;
+};
+
+#endif // QUEUE_H
diff --git a/krusader/Queue/queue_mgr.cpp b/krusader/Queue/queue_mgr.cpp
new file mode 100644
index 0000000..875f9cc
--- /dev/null
+++ b/krusader/Queue/queue_mgr.cpp
@@ -0,0 +1,31 @@
+#include "queue_mgr.h"
+
+const QString QueueManager::defaultName="default";
+QMap<QString, Queue*> QueueManager::_queues;
+
+QueueManager::QueueManager()
+{
+ Queue *defaultQ = new Queue(defaultName);
+ _queues.insert(defaultQ->name(), defaultQ);
+}
+
+QueueManager::~QueueManager()
+{
+ QMap<QString, Queue*>::iterator it;
+ for (it = _queues.begin(); it != _queues.end(); ++it )
+ delete it.data();
+ _queues.clear();
+}
+
+Queue* QueueManager::queue(const QString& queueName)
+{
+ if (!_queues.contains(queueName))
+ return 0;
+ return _queues[queueName];
+}
+
+QValueList<QString> QueueManager::queues() const
+{
+ return _queues.keys();
+}
+
diff --git a/krusader/Queue/queue_mgr.h b/krusader/Queue/queue_mgr.h
new file mode 100644
index 0000000..7bc474f
--- /dev/null
+++ b/krusader/Queue/queue_mgr.h
@@ -0,0 +1,26 @@
+#ifndef QUEUE_MGR_H
+#define QUEUE_MGR_H
+
+#include "queue.h"
+#include <qmap.h>
+
+/**
+ * QueueManager holds multiple queues and has a static
+ * method that fetches a queue by name. calling it with
+ * no arguments will fetch the default queue
+ */
+class QueueManager
+{
+ static const QString defaultName;
+public:
+ QueueManager();
+ ~QueueManager();
+
+ static Queue* queue(const QString& queueName=defaultName);
+ QValueList<QString> queues() const;
+
+protected:
+ static QMap<QString, Queue*> _queues;
+};
+
+#endif // QUEUE_MGR_H
diff --git a/krusader/Queue/queuewidget.cpp b/krusader/Queue/queuewidget.cpp
new file mode 100644
index 0000000..65c11da
--- /dev/null
+++ b/krusader/Queue/queuewidget.cpp
@@ -0,0 +1,10 @@
+#include "queuewidget.h"
+
+QueueWidget::QueueWidget(): KTabWidget()
+{
+}
+
+
+QueueWidget::~QueueWidget()
+{
+}
diff --git a/krusader/Queue/queuewidget.h b/krusader/Queue/queuewidget.h
new file mode 100644
index 0000000..aa58477
--- /dev/null
+++ b/krusader/Queue/queuewidget.h
@@ -0,0 +1,14 @@
+#ifndef QUEUE_WIDGET_H
+#define QUEUE_WIDGET_H
+
+#include <ktabwidget.h>
+
+class QueueWidget: public KTabWidget
+{
+ Q_OBJECT
+public:
+ QueueWidget();
+ ~QueueWidget();
+};
+
+#endif // QUEUE_WIDGET_H
diff --git a/krusader/RemoteMan/Makefile.am b/krusader/RemoteMan/Makefile.am
new file mode 100644
index 0000000..cff7637
--- /dev/null
+++ b/krusader/RemoteMan/Makefile.am
@@ -0,0 +1,9 @@
+noinst_LIBRARIES = libRemoteMan.a
+
+INCLUDES = $(all_includes)
+
+libRemoteMan_a_METASOURCES = AUTO
+
+libRemoteMan_a_SOURCES = \
+ remoteman.cpp \
+ remotemanbase.cpp
diff --git a/krusader/RemoteMan/remoteman.cpp b/krusader/RemoteMan/remoteman.cpp
new file mode 100644
index 0000000..848bba6
--- /dev/null
+++ b/krusader/RemoteMan/remoteman.cpp
@@ -0,0 +1,385 @@
+/***************************************************************************
+ remoteman.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+
+#include "remoteman.h"
+#include "../kicons.h"
+#include "../resources.h"
+#include "../krusader.h"
+#include <qlineedit.h>
+#include <klocale.h>
+#include <qpixmap.h>
+#include <qspinbox.h>
+#include <qmultilineedit.h>
+#include <qpushbutton.h>
+#include <qstringlist.h>
+#include <qmessagebox.h>
+#include <qcheckbox.h>
+#include <kstandarddirs.h>
+
+QString remoteMan::url=QString::null;
+
+remoteMan::remoteMan() : remoteManBase(0,0,true), currentItem(0) {
+ // Read the connection list from the configuration file and re-create the tree
+ config2tree();
+ sessions->setCurrentItem(sessions->firstChild());
+ // some minor fixes, left out of the designer - do again in next version !
+ password->setEchoMode(QLineEdit::Password);
+ // ===> should be moved to remoteManBase <=====
+ connect( hostName, SIGNAL( textChanged(const QString&) ),
+ this, SLOT( updateConnect(const QString&) ) );
+ connect( sessions, SIGNAL(doubleClicked(QListViewItem *)), this, SLOT(connection()));
+ connect( sessions, SIGNAL(returnPressed(QListViewItem *)), this, SLOT(connection()));
+ // execute the main dialog
+ exec();
+}
+
+void remoteMan::expandDecos(QListViewItem* i) {
+ if (i->text(1)!="SESSION") i->setPixmap(0,LOADICON("folder_open"));
+}
+void remoteMan::collapseDecos(QListViewItem* i) {
+ if (i->text(1)!="SESSION") i->setPixmap(0,LOADICON("folder_open"));
+}
+
+// This is the static memeber, you'd want to call this directly !
+QString remoteMan::getHost() {
+ remoteMan *p=new remoteMan();
+ delete p;
+ return url;
+}
+
+// adds a new group submenu
+void remoteMan::addGroup() {
+ QListViewItem *i=0,*current;
+ current=sessions->currentItem();
+ if (!current) // no item is current, or the list is empty (shouldn't happen)
+ i=new QListViewItem(sessions,i18n("New group"),"GROUP"); // insert into the backplane
+ else
+ if (current->text(1).left(5)=="GROUP")
+ i=new QListViewItem(current,i18n("New group"),"GROUP"); // insert under the current item
+ else return; // cannot create a new group under an item
+ // set an open folder pixmap for the group
+ i->setPixmap(0,LOADICON("folder_open"));
+ // make the new item current and refresh the view
+ sessions->setCurrentItem(i); sessions->ensureItemVisible(i);
+}
+
+// add an actual session
+void remoteMan::addSession() {
+ QListViewItem *i=0,*current;
+ current=sessions->currentItem();
+ // if we are pointing to a session, then the new session will be
+ // created under the current session's parent group
+ if (current->text(1)=="SESSION") current=current->parent();
+ // create a new item and give it the appropriate pixmap
+ i=new QListViewItem(current,i18n("New session"),"SESSION");
+ i->setPixmap(0,LOADICON("kr_ftp_new"));
+ // make the new item current and refresh the view
+ sessions->setCurrentItem(i); sessions->ensureItemVisible(i);
+}
+
+// called upon a selection change to update the view
+void remoteMan::refreshData() {
+ // first, update the last changes the user made
+ if (currentItem) {
+ currentItem->setText(2,hostName->text());
+ currentItem->setText(3,portNum->cleanText());
+ currentItem->setText(4,userName->text());
+ currentItem->setText(5,password->text());
+ currentItem->setText(6,remoteDir->text());
+ currentItem->setText(7,description->text());
+ currentItem->setText(8,protocol->currentText());
+ // we have to check if there's another brother-session with
+ // the same name, if so, we add a <2> to it
+ QListViewItem *i;
+ if (currentItem->parent()) i=currentItem->parent()->firstChild();
+ else i=sessions->firstChild();
+ while (i) {
+ if (i->text(0)==currentItem->text(0) && i!=currentItem) {
+ QString temp=currentItem->text(0).right(4);
+ if (temp.left(1)=="<" && temp.right(1)==">") {
+ int h=temp.mid(1,1).toInt();
+ int l=temp.mid(2,1).toInt();
+ if ((++l)==10) { ++h; l=0; }
+ temp=QString("<%1%2>").arg(h).arg(l);
+ temp=currentItem->text(0).replace(currentItem->text(0).length()-4,4,temp);
+ currentItem->setText(0,temp);
+ } else currentItem->setText(0,currentItem->text(0)+"<02>");
+ i=currentItem->parent()->firstChild();
+ } else i=i->nextSibling();
+ }
+ }
+ // here begins the actual function
+ removeBtn->setEnabled(true); // just incase we turned it off last time
+ connectBtn->setEnabled(true);
+ QListViewItem *current=sessions->currentItem();
+ if (!current) return; // if no item is current yet
+ if (current->text(1).left(5)=="GROUP") { // disable all that don't belong to a group
+ // first, disable all the fields a user cannot change
+ hostName->setEnabled(false);
+ password->setEnabled(false);
+ portNum->setEnabled(false);
+ remoteDir->setEnabled(false);
+ userName->setEnabled(false);
+ if (current->text(1)=="GROUP!") {
+ sessionName->setEnabled(false); // even name can't be changed here!
+ description->setEnabled(false);
+ removeBtn->setEnabled(false);
+ connectBtn->setEnabled(false);
+ } else sessionName->setEnabled(true);
+ } else { // otherwise, a normal url is under the cursor
+ if( !current->text(8).isEmpty() )
+ protocol->setCurrentText(current->text(8));
+ else
+ protocol->setCurrentItem(0);
+ hostName->setEnabled(true);
+ // anonymous connection ??
+ userName->setEnabled(!anonymous->isChecked());
+ password->setEnabled(!anonymous->isChecked());
+ // for now, don't allow port settings for smb://
+ portNum->setEnabled( protocol->currentText()=="ftp://" );
+ remoteDir->setEnabled(true);
+ sessionName->setEnabled(true);
+ description->setEnabled(true);
+ }
+ // now, update the session name (or group name) and needed info
+ sessionName->setText(current->text(0));
+ hostName->setText(current->text(2));
+ portNum->setValue(current->text(3).toInt());
+ if (portNum->value()==0) portNum->setValue(21);
+ userName->setText(current->text(4));
+ password->setText(current->text(5));
+ remoteDir->setText(current->text(6));
+ description->setText(current->text(7));
+ sessions->setSorting(1); sessions->sort(); // resort the tree
+ currentItem=current; // keep the active item for other jobs
+ // disable connect button if no host name is defined
+ if (hostName->text().simplifyWhiteSpace().isEmpty())
+ connectBtn->setEnabled(false);
+}
+
+// called when we are changing the session/group name, so that remoteMan
+// is able to change it in the corrosponding listview at the same time
+void remoteMan::updateName(const QString &text) {
+ QListViewItem *i=sessions->currentItem();
+ i->setText(0,text);
+}
+
+void remoteMan::updateConnect(const QString &) {
+ // disable connect button if no host name is defined
+ if (hostName->text().simplifyWhiteSpace().isEmpty())
+ connectBtn->setEnabled(false);
+ else connectBtn->setEnabled(true);
+}
+
+// take an item, and create a "connection", built of the full
+// path of folders to the item, seperated by the ` character
+QString item2connection(QListViewItem *item) {
+ QString con=item->text(0);
+ QListViewItem *iterator=item->parent();
+ while (iterator!=0) {
+ //////////////////////// explanation: ///////////////////////////
+ // since the` char is special to us, we use it to seperate items
+ // in the connection, we cannot allow it to be inside a name, so
+ // we find it (if it exists) and replace it with a ' character
+ QString temp=iterator->text(0);
+ int i=temp.find('`'); // are there any ` in the name ?
+ while (i>-1) { // if so, change them until none are left
+ temp.replace(i,1,QChar('\''));
+ i=temp.find('`');
+ }
+ con=temp+'`'+con;
+ iterator=iterator->parent();
+ }
+ return con;
+}
+
+// find an item with a specific path - if the path doesn't exist, create it
+QListViewItem* remoteMan::findItem(const QString &name, QListViewItem *p) {
+ QListViewItem *it;
+ if (name.isEmpty()) return p; // the end of the recursion has been reached!!!
+ if (p==0) it=sessions->firstChild(); else it=p->firstChild();
+ int loc=name.find('`');
+ while (it) {
+ if (it->text(0)==name.left(loc)) break;
+ it=it->nextSibling();
+ }
+ if (!it) // item has not been found, create it
+ if (!p) it=new QListViewItem(sessions,name.left(loc),"GROUP");
+ else it=new QListViewItem(p,name.left(loc),"GROUP");
+ // now, it points to the item we want, so let's go down one level
+ it=findItem(name.mid(loc+1),it);
+ return it;
+}
+
+// re-create the tree from a config file
+void remoteMan::config2tree() {
+ // attempt to read the tree from krusader's config file
+ krConfig->setGroup("RemoteMan");
+ QStringList lst=krConfig->readListEntry("Connections");
+ if (lst.count()<1) { // no such list in the config file - create the basics
+ // add the default groups
+ QListViewItem *i;
+ i=new QListViewItem(sessions,i18n("Sessions"),"GROUP!");
+ // the GROUP text signifies a group (duh), the GROUP! signifies a group
+ // that the user cannot change
+ i->setPixmap(0,LOADICON("folder_open"));
+ sessions->setCurrentItem(i);
+//# i=new QListViewItem(sessions,i18n("Samba sessions (comming soon)"),"GROUP!");
+//# i->setPixmap(0,LOADICON("folder"));
+ return;
+ }
+ // if we got here, we have a connection entry in the config file
+ // let's work on it...
+ QStringList::Iterator it;
+ QListViewItem *item=0;
+ for( it = lst.begin(); it != lst.end(); ++it ) {
+ QString t=(*it); // easier to work with
+ // this part creates the path to the session
+ int loc=t.findRev('`');
+ if (loc>-1) item=findItem(t.left(loc+1),0);
+ // at this point we have the complete path to the object
+ // let's keep only the item's name
+ t=t.mid(loc+1);
+ // now, we are left with only the session name itself
+ // so, we create it as a son of the active item
+ QStringList newLst=krConfig->readListEntry(*it); // and fill in
+ bool group=(newLst[1]!="SESSION");
+ QListViewItem *newItem;
+ if (item==0) // if this item originating from the backplane
+ newItem=new QListViewItem(sessions,t,group ? "GROUP" : "SESSION");
+ else
+ newItem=new QListViewItem(item,t,group ? "GROUP" : "SESSION");
+ newItem->setPixmap(0,group ? LOADICON("folder") : LOADICON("kr_ftp_new")); // update a pixmap
+ newItem->setText(0,t);
+ // expand the item, if needed
+ ++it; if ((*it) == "expanded") newItem->setOpen(true);
+ for (int i=1; i<9; ++i) newItem->setText(i,newLst[i]);// the details
+ item=0; // clean up pointers
+ }
+}
+
+// make a single pass on the tree and create a configuration file
+void remoteMan::tree2config() {
+ // first, set the stage
+ krConfig->setGroup("RemoteMan");
+ QStringList lst;
+ QListViewItemIterator it(sessions);
+ while (it.current()) { // while there are still items in the tree
+ QString temp=item2connection((it.current()));
+ lst.append(temp); // write the connection into the "connection-index"
+ if (it.current()->isOpen())
+ lst.append("expanded"); else lst.append("collapsed");
+ QStringList data;
+ for (int i=0; i<9; ++i) data.append((it.current())->text(i));
+ // write the specific entry into the config file
+ krConfig->writeEntry(temp,data);
+ ++it;
+ }
+ // now we write the index
+ krConfig->writeEntry("Connections",lst);
+ krConfig->sync(); // force an immediate write to the disk
+}
+
+void remoteMan::connection() {
+ // if clicked on a group...
+ QListViewItem *i=sessions->currentItem();
+ if (i->text(1)!="SESSION") {
+ i->setOpen(i->isOpen());
+ return;
+ }
+ // build a url
+ if (anonymous->isChecked()) {
+ userName->setText(QString::null);
+ password->setText(QString::null);
+ } else {
+ userName->setText(userName->text().simplifyWhiteSpace());
+ password->setText(password->text().simplifyWhiteSpace());
+ }
+ hostName->setText(hostName->text().simplifyWhiteSpace().lower());
+ if (hostName->text().left(6)=="ftp://" || hostName->text().left(6)=="smb://")
+ hostName->setText(hostName->text().mid(6));
+ remoteDir->setText(remoteDir->text().simplifyWhiteSpace());
+ if ( !remoteDir->text().isEmpty() && remoteDir->text().left(1)!="/")
+ remoteDir->setText("/"+remoteDir->text());
+
+ QString port="";
+ if (protocol->currentText()=="ftp://" && portNum->value()!=21 )
+ port=":"+portNum->cleanText();
+
+ url=protocol->currentText();
+
+ if( !userName->text().isEmpty() ){
+ url = url+userName->text();
+ if( !password->text().isEmpty() );
+ url = url+":"+password->text();
+ url = url+"@";
+ }
+ url=url+ hostName->text()+port+remoteDir->text();
+
+ // now, let's close cleanly
+ refreshData(); // make sure all is updated
+ tree2config(); // write the sessions to a configuration file
+ remoteManBase::accept(); // tidy up
+}
+
+// remove a connection or a group of connections
+void remoteMan::removeSession() {
+
+ QListViewItem *it=sessions->currentItem();
+ if (!it) return; // don't do anything if no item is selected
+ switch( QMessageBox::warning( this, i18n("RemoteMan"),
+ i18n("Are you sure you want to delete this item ???"),
+ QMessageBox::Yes,
+ QMessageBox::No | QMessageBox::Default | QMessageBox::Escape)) {
+ case QMessageBox::No : return;
+ }
+ // since we're here, the user must have pressed YES, let's delete
+ delete it;
+ sessions->triggerUpdate();
+}
+
+// what we do when the user clicked the close button
+void remoteMan::accept() {
+ refreshData(); // make sure all is updated
+ tree2config(); // write the sessions to a configuration file
+ url=QString::null; // this signals getHost() we didn't click CONNECT
+ remoteManBase::accept(); // tidy up
+}
+
+void remoteMan::reject() {
+ refreshData(); // make sure all is updated
+ tree2config(); // write the sessions to a configuration file
+ url=QString::null; // this signals getHost() we didn't click CONNECT
+ remoteManBase::reject();
+}
+
+#include "remoteman.moc"
diff --git a/krusader/RemoteMan/remoteman.h b/krusader/RemoteMan/remoteman.h
new file mode 100644
index 0000000..385ef86
--- /dev/null
+++ b/krusader/RemoteMan/remoteman.h
@@ -0,0 +1,70 @@
+/***************************************************************************
+ remoteman.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef REMOTEMAN_H
+#define REMOTEMAN_H
+
+#include "remotemanbase.h"
+#include <qlistview.h>
+
+class remoteMan : public remoteManBase {
+ Q_OBJECT
+public:
+ remoteMan();
+ static QString getHost(); // we call remoteMan mainly with this function
+
+protected:
+ void config2tree(); // internal
+ void tree2config(); // internal
+ QListViewItem *findItem(const QString &name, QListViewItem *p);
+
+public slots:
+ void addGroup();
+ void refreshData() ; // called whenver the current session changes
+ void updateName(const QString&); // update the session/group name in real-time
+ void updateConnect(const QString&); // enable/disable the connect button in real-time
+ void addSession();
+ void connection();
+ void removeSession();
+ void expandDecos(QListViewItem*);
+ void collapseDecos(QListViewItem*);
+
+protected slots:
+ void accept();
+ void reject();
+
+private:
+ QListViewItem *currentItem;
+ static QString url;
+};
+
+#endif
diff --git a/krusader/RemoteMan/remotemanbase.cpp b/krusader/RemoteMan/remotemanbase.cpp
new file mode 100644
index 0000000..2baf3d6
--- /dev/null
+++ b/krusader/RemoteMan/remotemanbase.cpp
@@ -0,0 +1,331 @@
+/****************************************************************************
+** Form implementation generated from reading ui file 'remotemanbase.ui'
+**
+** Created: Thu Jun 7 16:24:11 2001
+** by: The User Interface Compiler (uic)
+**
+** WARNING! All changes made in this file will be lost!
+****************************************************************************/
+#include "remotemanbase.h"
+
+#include <klocale.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qheader.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qlistview.h>
+#include <qmultilineedit.h>
+#include <qpushbutton.h>
+#include <qspinbox.h>
+#include <qlayout.h>
+#include <qvariant.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <kprotocolinfo.h>
+
+
+/*
+ * Constructs a remoteManBase which is a child of 'parent', with the
+ * name 'name' and widget flags set to 'f'
+ *
+ * The dialog will by default be modeless, unless you set 'modal' to
+ * TRUE to construct a modal dialog.
+ */
+remoteManBase::remoteManBase( QWidget* parent, const char* name, bool modal, WFlags fl )
+ : QDialog( parent, name, modal, fl )
+{
+ if ( !name )
+ setName( "remoteManBase" );
+ resize( 670, 502 );
+ setCaption( i18n( "RemoteMan: Connection Manager" ) );
+ setSizeGripEnabled( TRUE );
+ remoteManBaseLayout = new QGridLayout( this );
+ remoteManBaseLayout->setSpacing( 6 );
+ remoteManBaseLayout->setMargin( 11 );
+
+ Layout23 = new QVBoxLayout;
+ Layout23->setSpacing( 6 );
+ Layout23->setMargin( 0 );
+
+ TextLabel1 = new QLabel( this, "TextLabel1" );
+ TextLabel1->setText( i18n( "Session name:" ) );
+ Layout23->addWidget( TextLabel1 );
+
+ sessionName = new QLineEdit( this, "sessionName" );
+ Layout23->addWidget( sessionName );
+
+ remoteManBaseLayout->addLayout( Layout23, 0, 1 );
+
+ Layout12 = new QHBoxLayout;
+ Layout12->setSpacing( 6 );
+ Layout12->setMargin( 0 );
+ QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ Layout12->addItem( spacer );
+
+ moreBtn = new QPushButton( this, "moreBtn" );
+ moreBtn->setText( i18n( "&More" ) );
+ moreBtn->setAutoDefault( FALSE );
+ moreBtn->setDefault( FALSE );
+ Layout12->addWidget( moreBtn );
+
+ closeBtn = new QPushButton( this, "closeBtn" );
+ closeBtn->setText( i18n( "&Close" ) );
+ closeBtn->setAutoDefault( FALSE );
+ closeBtn->setDefault( FALSE );
+ Layout12->addWidget( closeBtn );
+
+ remoteManBaseLayout->addMultiCellLayout( Layout12, 7, 7, 0, 1 );
+
+ sessions = new QListView( this, "sessions" );
+ sessions->addColumn( i18n( "Sessions" ) );
+ sessions->header()->setClickEnabled( FALSE, sessions->header()->count() - 1 );
+ sessions->header()->setResizeEnabled( FALSE, sessions->header()->count() - 1 );
+ sessions->setMinimumSize( QSize( 300, 400 ) );
+ sessions->setVScrollBarMode( QListView::AlwaysOn );
+ sessions->setHScrollBarMode( QListView::Auto );
+ sessions->setRootIsDecorated( TRUE );
+
+ remoteManBaseLayout->addMultiCellWidget( sessions, 0, 6, 0, 0 );
+
+ Layout9 = new QVBoxLayout;
+ Layout9->setSpacing( 6 );
+ Layout9->setMargin( 0 );
+
+ Layout10 = new QGridLayout;
+ Layout10->setSpacing( 6 );
+ Layout10->setMargin( 0 );
+
+ TextLabel1_3_3 = new QLabel( this, "TextLabel1_3_3" );
+ TextLabel1_3_3->setText( i18n( "Password:" ) );
+
+ Layout10->addWidget( TextLabel1_3_3, 0, 1 );
+
+ password = new QLineEdit( this, "password" );
+
+ Layout10->addWidget( password, 1, 1 );
+
+ TextLabel1_3 = new QLabel( this, "TextLabel1_3" );
+ TextLabel1_3->setText( i18n( "User name:" ) );
+
+ Layout10->addWidget( TextLabel1_3, 0, 0 );
+
+ userName = new QLineEdit( this, "userName" );
+
+ Layout10->addWidget( userName, 1, 0 );
+ Layout9->addLayout( Layout10 );
+
+ anonymous = new QCheckBox( this, "anonymous" );
+ anonymous->setText( i18n( "Anonymous" ) );
+ Layout9->addWidget( anonymous );
+
+ remoteManBaseLayout->addLayout( Layout9, 2, 1 );
+
+ Layout26 = new QVBoxLayout;
+ Layout26->setSpacing( 6 );
+ Layout26->setMargin( 0 );
+
+ TextLabel1_3_2 = new QLabel( this, "TextLabel1_3_2" );
+ TextLabel1_3_2->setText( i18n( "Remote directory:" ) );
+ Layout26->addWidget( TextLabel1_3_2 );
+
+ remoteDir = new QLineEdit( this, "remoteDir" );
+ Layout26->addWidget( remoteDir );
+
+ remoteManBaseLayout->addLayout( Layout26, 4, 1 );
+
+ Layout27 = new QVBoxLayout;
+ Layout27->setSpacing( 6 );
+ Layout27->setMargin( 0 );
+
+ TextLabel1_3_2_2 = new QLabel( this, "TextLabel1_3_2_2" );
+ TextLabel1_3_2_2->setText( i18n( "Description:" ) );
+ Layout27->addWidget( TextLabel1_3_2_2 );
+
+ description = new QMultiLineEdit( this, "description" );
+ Layout27->addWidget( description );
+
+ remoteManBaseLayout->addLayout( Layout27, 5, 1 );
+
+ layout = new QGridLayout;
+ layout->setSpacing( 6 );
+ layout->setMargin( 0 );
+
+ removeBtn = new QPushButton( this, "removeBtn" );
+ removeBtn->setText( i18n( "&Remove" ) );
+ removeBtn->setAutoDefault( FALSE );
+ removeBtn->setDefault( FALSE );
+
+ layout->addWidget( removeBtn, 0, 2 );
+
+ connectBtn = new QPushButton( this, "connectBtn" );
+ connectBtn->setText( i18n( "Co&nnect" ) );
+ connectBtn->setAutoDefault( FALSE );
+ connectBtn->setDefault( FALSE );
+
+ layout->addMultiCellWidget( connectBtn, 1, 1, 0, 2 );
+
+ newGroupBtn = new QPushButton( this, "newGroupBtn" );
+ newGroupBtn->setEnabled( TRUE );
+ newGroupBtn->setText( i18n( "New &Group" ) );
+ newGroupBtn->setAutoDefault( FALSE );
+ newGroupBtn->setDefault( FALSE );
+ newGroupBtn->setFlat( FALSE );
+
+ layout->addWidget( newGroupBtn, 0, 0 );
+
+ addBtn = new QPushButton( this, "addBtn" );
+ addBtn->setEnabled( TRUE );
+ addBtn->setText( i18n( "New Connec&tion" ) );
+ addBtn->setAutoDefault( FALSE );
+ addBtn->setDefault( FALSE );
+ addBtn->setFlat( FALSE );
+
+ layout->addWidget( addBtn, 0, 1 );
+
+ remoteManBaseLayout->addLayout( layout, 6, 1 );
+
+ Layout11 = new QGridLayout;
+ Layout11->setSpacing( 6 );
+ Layout11->setMargin( 0 );
+
+ TextLabel1_2 = new QLabel( this, "TextLabel1_2" );
+ TextLabel1_2->setText( i18n( "Host:" ) );
+
+ Layout11->addMultiCellWidget( TextLabel1_2, 0, 0, 0, 1 );
+
+ QStringList protocols = KProtocolInfo::protocols();
+
+ protocol = new QComboBox( FALSE, this, "protocol" );
+ if( protocols.contains("ftp") )
+ protocol->insertItem( i18n( "ftp://" ) );
+ if( protocols.contains("smb") )
+ protocol->insertItem( i18n( "smb://" ) );
+ if( protocols.contains("fish") )
+ protocol->insertItem( i18n( "fish://" ));
+ if( protocols.contains("sftp") )
+ protocol->insertItem( i18n( "sftp://" ));
+ protocol->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, protocol->sizePolicy().hasHeightForWidth() ) );
+
+ Layout11->addWidget( protocol, 1, 0 );
+
+ hostName = new QLineEdit( this, "hostName" );
+ hostName->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7, (QSizePolicy::SizeType)0, hostName->sizePolicy().hasHeightForWidth() ) );
+ hostName->setMinimumSize( QSize( 0, 0 ) );
+
+ Layout11->addWidget( hostName, 1, 1 );
+
+ portNum = new QSpinBox( this, "portNum" );
+ portNum->setMaxValue( 99999 );
+ portNum->setValue( 21 );
+
+ Layout11->addWidget( portNum, 1, 2 );
+
+ TextLabel1_2_2 = new QLabel( this, "TextLabel1_2_2" );
+ TextLabel1_2_2->setText( i18n( "Port: " ) );
+
+ Layout11->addWidget( TextLabel1_2_2, 0, 2 );
+
+ remoteManBaseLayout->addLayout( Layout11, 1, 1 );
+
+ TextLabel1_4 = new QLabel( this, "TextLabel1_4" );
+ QFont TextLabel1_4_font( TextLabel1_4->font() );
+ TextLabel1_4_font.setPointSize( 10 );
+ TextLabel1_4->setFont( TextLabel1_4_font );
+ TextLabel1_4->setText( i18n( "* Warning: Storing your password is not secure !!!" ) );
+ TextLabel1_4->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) );
+
+ remoteManBaseLayout->addWidget( TextLabel1_4, 3, 1 );
+
+ // signals and slots connections
+ connect( closeBtn, SIGNAL( clicked() ), this, SLOT( accept() ) );
+ connect( addBtn, SIGNAL( clicked() ), this, SLOT( addSession() ) );
+ connect( removeBtn, SIGNAL( clicked() ), this, SLOT( removeSession() ) );
+ connect( sessions, SIGNAL( selectionChanged(QListViewItem*) ), this, SLOT( refreshData() ) );
+ connect( sessions, SIGNAL( selectionChanged() ), this, SLOT( refreshData() ) );
+ connect( sessions, SIGNAL( expanded(QListViewItem*) ), this, SLOT( refreshData() ) );
+ connect( sessions, SIGNAL( currentChanged(QListViewItem*) ), this, SLOT( refreshData() ) );
+ connect( sessions, SIGNAL( mouseButtonClicked(int,QListViewItem*,const
+QPoint&,int) ), this, SLOT( refreshData() ) );
+ connect( sessions, SIGNAL( collapsed(QListViewItem*) ), this, SLOT( refreshData() ) );
+ connect( connectBtn, SIGNAL( clicked() ), this, SLOT( connection() ) );
+ connect( sessionName, SIGNAL( textChanged(const QString&) ), this, SLOT( updateName(const QString&) ) );
+ connect( newGroupBtn, SIGNAL( clicked() ), this, SLOT( addGroup() ) );
+ connect( anonymous, SIGNAL( clicked() ), this, SLOT( refreshData() ) );
+ connect( protocol, SIGNAL(activated(int)), this, SLOT(refreshData()));
+
+ // tab order
+ setTabOrder( sessionName, hostName );
+ setTabOrder( hostName, userName );
+ setTabOrder( userName, password );
+ setTabOrder( password, remoteDir );
+ setTabOrder( remoteDir, description );
+ setTabOrder( description, connectBtn );
+ setTabOrder( connectBtn, addBtn );
+ setTabOrder( addBtn, newGroupBtn );
+ setTabOrder( newGroupBtn, removeBtn );
+ setTabOrder( removeBtn, moreBtn );
+ setTabOrder( moreBtn, closeBtn );
+ setTabOrder( closeBtn, sessions );
+ setTabOrder( sessions, portNum );
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+remoteManBase::~remoteManBase()
+{
+ // no need to delete child widgets, Qt does it all for us
+}
+
+/*
+ * Main event handler. Reimplemented to handle application
+ * font changes
+ */
+bool remoteManBase::event( QEvent* ev )
+{
+ bool ret = QDialog::event( ev );
+ if ( ev->type() == QEvent::ApplicationFontChange ) {
+ QFont TextLabel1_4_font( TextLabel1_4->font() );
+ TextLabel1_4_font.setPointSize( 10 );
+ TextLabel1_4->setFont( TextLabel1_4_font );
+ }
+ return ret;
+}
+
+void remoteManBase::addSession()
+{
+ qWarning( "remoteManBase::addSession(): Not implemented yet!" );
+}
+
+void remoteManBase::connection()
+{
+ qWarning( "remoteManBase::connection(): Not implemented yet!" );
+}
+
+void remoteManBase::moreInfo()
+{
+ qWarning( "remoteManBase::moreInfo(): Not implemented yet!" );
+}
+
+void remoteManBase::addGroup()
+{
+ qWarning( "remoteManBase::addGroup(): Not implemented yet!" );
+}
+
+void remoteManBase::refreshData()
+{
+ qWarning( "remoteManBase::refreshData(): Not implemented yet!" );
+}
+
+void remoteManBase::removeSession()
+{
+ qWarning( "remoteManBase::removeSession(): Not implemented yet!" );
+}
+
+void remoteManBase::updateName(const QString&)
+{
+ qWarning( "remoteManBase::updateName(const QString&): Not implemented yet!" );
+}
+
+#include "remotemanbase.moc"
diff --git a/krusader/RemoteMan/remotemanbase.h b/krusader/RemoteMan/remotemanbase.h
new file mode 100644
index 0000000..7fcc65e
--- /dev/null
+++ b/krusader/RemoteMan/remotemanbase.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+** Form interface generated from reading ui file 'remotemanbase.ui'
+**
+** Created: Thu Jun 7 16:23:59 2001
+** by: The User Interface Compiler (uic)
+**
+** WARNING! All changes made in this file will be lost!
+****************************************************************************/
+#ifndef REMOTEMANBASE_H
+#define REMOTEMANBASE_H
+
+#include <qvariant.h>
+#include <qdialog.h>
+class QVBoxLayout;
+class QHBoxLayout;
+class QGridLayout;
+class QCheckBox;
+class QComboBox;
+class QLabel;
+class QLineEdit;
+class QListView;
+class QListViewItem;
+class QMultiLineEdit;
+class QPushButton;
+class QSpinBox;
+
+class remoteManBase : public QDialog
+{
+ Q_OBJECT
+
+public:
+ remoteManBase( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 );
+ ~remoteManBase();
+
+ QLabel* TextLabel1;
+ QLineEdit* sessionName;
+ QPushButton* moreBtn;
+ QPushButton* closeBtn;
+ QListView* sessions;
+ QLabel* TextLabel1_3_3;
+ QLineEdit* password;
+ QLabel* TextLabel1_3;
+ QLineEdit* userName;
+ QCheckBox* anonymous;
+ QLabel* TextLabel1_3_2;
+ QLineEdit* remoteDir;
+ QLabel* TextLabel1_3_2_2;
+ QMultiLineEdit* description;
+ QPushButton* removeBtn;
+ QPushButton* connectBtn;
+ QPushButton* newGroupBtn;
+ QPushButton* addBtn;
+ QLabel* TextLabel1_2;
+ QComboBox* protocol;
+ QLineEdit* hostName;
+ QSpinBox* portNum;
+ QLabel* TextLabel1_2_2;
+ QLabel* TextLabel1_4;
+
+public slots:
+ virtual void addSession();
+ virtual void connection();
+ virtual void moreInfo();
+ virtual void addGroup();
+ virtual void refreshData();
+ virtual void removeSession();
+ virtual void updateName(const QString&);
+
+protected:
+ QGridLayout* remoteManBaseLayout;
+ QVBoxLayout* Layout23;
+ QHBoxLayout* Layout12;
+ QVBoxLayout* Layout9;
+ QGridLayout* Layout10;
+ QVBoxLayout* Layout26;
+ QVBoxLayout* Layout27;
+ QGridLayout* layout;
+ QGridLayout* Layout11;
+ bool event( QEvent* );
+};
+
+#endif // REMOTEMANBASE_H
diff --git a/krusader/Search/Makefile.am b/krusader/Search/Makefile.am
new file mode 100644
index 0000000..e43b3de
--- /dev/null
+++ b/krusader/Search/Makefile.am
@@ -0,0 +1,9 @@
+noinst_LIBRARIES = libSearch.a
+
+INCLUDES = $(all_includes)
+
+libSearch_a_METASOURCES = AUTO
+
+libSearch_a_SOURCES = \
+ krsearchmod.cpp \
+ krsearchdialog.cpp
diff --git a/krusader/Search/krsearchdialog.cpp b/krusader/Search/krsearchdialog.cpp
new file mode 100644
index 0000000..632b78e
--- /dev/null
+++ b/krusader/Search/krsearchdialog.cpp
@@ -0,0 +1,628 @@
+/***************************************************************************
+ krsearchdialog.cpp
+ -------------------
+ copyright : (C) 2001 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "../krusader.h"
+#include "../defaults.h"
+#include "../panelmanager.h"
+#include "../VFS/vfs.h"
+#include "../krusaderview.h"
+#include "../Panel/listpanel.h"
+#include "../Panel/panelfunc.h"
+#include "../Dialogs/krdialogs.h"
+#include "../VFS/virt_vfs.h"
+#include "../KViewer/krviewer.h"
+#include "krsearchmod.h"
+#include "krsearchdialog.h"
+
+#include <kinputdialog.h>
+#include <qregexp.h>
+#include <qfontmetrics.h>
+#include <kmessagebox.h>
+#include <kpopupmenu.h>
+#include <qcursor.h>
+#include <qclipboard.h>
+#include <qheader.h>
+#include <kurldrag.h>
+#include <../kicons.h>
+
+class SearchListView : public QListView
+{
+public:
+ SearchListView( QWidget * parent, const char * name ) : QListView( parent, name )
+ {
+ }
+
+ void startDrag()
+ {
+ KURL::List urls;
+
+ QListViewItem * item = firstChild();
+ while( item )
+ {
+ if( item->isSelected() )
+ {
+ QString name = item->text(1);
+ name += (name.endsWith( "/" ) ? item->text(0) : "/" + item->text(0) );
+ urls.push_back( vfs::fromPathOrURL( name ) );
+ }
+ item = item->nextSibling();
+ }
+
+ if( urls.count() == 0 )
+ return;
+
+ KURLDrag *d = new KURLDrag(urls, this);
+ d->setPixmap( FL_LOADICON( "file" ), QPoint( -7, 0 ) );
+ d->dragCopy();
+ }
+};
+
+
+
+KrSearchDialog *KrSearchDialog::SearchDialog = 0;
+
+QString KrSearchDialog::lastSearchText = "*";
+int KrSearchDialog::lastSearchType = 0;
+bool KrSearchDialog::lastSearchForCase = false;
+bool KrSearchDialog::lastRemoteContentSearch = false;
+bool KrSearchDialog::lastContainsWholeWord = false;
+bool KrSearchDialog::lastContainsWithCase = true;
+bool KrSearchDialog::lastSearchInSubDirs = true;
+bool KrSearchDialog::lastSearchInArchives = false;
+bool KrSearchDialog::lastFollowSymLinks = false;
+
+// class starts here /////////////////////////////////////////
+KrSearchDialog::KrSearchDialog( QString profile, QWidget* parent, const char* name, bool modal, WFlags fl )
+ : QDialog( parent, name, modal, fl ), query(0), searcher(0)
+{
+ setCaption( i18n( "Krusader::Search" ) );
+
+ QGridLayout* searchBaseLayout = new QGridLayout( this );
+ searchBaseLayout->setSpacing( 6 );
+ searchBaseLayout->setMargin( 11 );
+
+ // creating the dialog buttons ( Search, Stop, Close )
+
+ QHBoxLayout* buttonsLayout = new QHBoxLayout();
+ buttonsLayout->setSpacing( 6 );
+ buttonsLayout->setMargin( 0 );
+
+ profileManager = new ProfileManager( "SearcherProfile", this, "profileManager" );
+ buttonsLayout->addWidget( profileManager );
+
+ QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ buttonsLayout->addItem( spacer );
+
+ mainFeedToListBoxBtn = new QPushButton( this, "mainFeedToListBoxBtn" );
+ mainFeedToListBoxBtn->setText( i18n( "Feed to listbox" ) );
+ mainFeedToListBoxBtn->setEnabled(false);
+ buttonsLayout->addWidget( mainFeedToListBoxBtn );
+
+ mainSearchBtn = new QPushButton( this, "mainSearchBtn" );
+ mainSearchBtn->setText( i18n( "Search" ) );
+ mainSearchBtn->setDefault(true);
+ buttonsLayout->addWidget( mainSearchBtn );
+
+ mainStopBtn = new QPushButton( this, "mainStopBtn" );
+ mainStopBtn->setEnabled( false );
+ mainStopBtn->setText( i18n( "Stop" ) );
+ buttonsLayout->addWidget( mainStopBtn );
+
+ mainCloseBtn = new QPushButton( this, "mainCloseBtn" );
+ mainCloseBtn->setText( i18n( "Close" ) );
+ buttonsLayout->addWidget( mainCloseBtn );
+
+ searchBaseLayout->addLayout( buttonsLayout, 1, 0 );
+
+ // creating the searcher tabs
+
+ searcherTabs = new QTabWidget( this, "searcherTabs" );
+
+ filterTabs = FilterTabs::addTo( searcherTabs, FilterTabs::Default | FilterTabs::HasRemoteContentSearch );
+ generalFilter = (GeneralFilter *)filterTabs->get( "GeneralFilter" );
+
+ resultTab = new QWidget( searcherTabs, "resultTab" );
+ resultLayout = new QGridLayout( resultTab );
+ resultLayout->setSpacing( 6 );
+ resultLayout->setMargin( 11 );
+
+ // creating the result tab
+
+ QHBoxLayout* resultLabelLayout = new QHBoxLayout();
+ resultLabelLayout->setSpacing( 6 );
+ resultLabelLayout->setMargin( 0 );
+
+ foundLabel = new QLabel( resultTab, "foundLabel" );
+ foundLabel->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)1, foundLabel->sizePolicy().hasHeightForWidth() ) );
+ foundLabel->setFrameShape( QLabel::StyledPanel );
+ foundLabel->setFrameShadow( QLabel::Sunken );
+ foundLabel->setText( i18n( "Found 0 matches." ) );
+ resultLabelLayout->addWidget( foundLabel );
+
+ searchingLabel = new KSqueezedTextLabel( resultTab, "searchingLabel" );
+ searchingLabel->setFrameShape( QLabel::StyledPanel );
+ searchingLabel->setFrameShadow( QLabel::Sunken );
+ searchingLabel->setText( "" );
+ resultLabelLayout->addWidget( searchingLabel );
+
+ resultLayout->addLayout( resultLabelLayout, 2, 0 );
+
+ // creating the result list view
+
+ resultsList = new SearchListView( resultTab, "resultsList" );
+ resultsList->addColumn( i18n( "Name" ) );
+ resultsList->addColumn( i18n( "Location" ) );
+ resultsList->addColumn( i18n( "Size" ) );
+ resultsList->addColumn( i18n( "Date" ) );
+ resultsList->addColumn( i18n( "Permissions" ) );
+
+ resultsList->setSorting(1); // sort by location
+ resultsList->setSelectionMode( QListView::Extended );
+
+ // fix the results list
+ // => make the results font smaller
+ QFont resultsFont( resultsList->font() );
+ resultsFont.setPointSize(resultsFont.pointSize()-1);
+ resultsList->setFont(resultsFont);
+
+ resultsList->setAllColumnsShowFocus(true);
+ for (int i=0; i<5; ++i) // don't let it resize automatically
+ resultsList->setColumnWidthMode(i, QListView::Manual);
+
+ int i=QFontMetrics(resultsList->font()).width("W");
+ int j=QFontMetrics(resultsList->font()).width("0");
+ j=(i>j ? i : j);
+
+ resultsList->setColumnWidth(0, krConfig->readNumEntry("Name Width", j*14) );
+ resultsList->setColumnWidth(1, krConfig->readNumEntry("Path Width", j*25) );
+ resultsList->setColumnWidth(2, krConfig->readNumEntry("Size Width", j*6) );
+ resultsList->setColumnWidth(3, krConfig->readNumEntry("Date Width", j*7) );
+ resultsList->setColumnWidth(4, krConfig->readNumEntry("Perm Width", j*7) );
+ resultsList->setColumnAlignment( 2, AlignRight );
+
+ resultsList->header()->setStretchEnabled( true, 1 );
+
+ resultLayout->addWidget( resultsList, 0, 0 );
+
+ QHBoxLayout* foundTextLayout = new QHBoxLayout();
+ foundTextLayout->setSpacing( 6 );
+ foundTextLayout->setMargin( 0 );
+
+ QLabel *l1 = new QLabel(resultTab);
+ l1->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)1, l1->sizePolicy().hasHeightForWidth() ) );
+ l1->setFrameShape( QLabel::StyledPanel );
+ l1->setFrameShadow( QLabel::Sunken );
+ l1->setText(i18n("Text found:"));
+ foundTextLayout->addWidget( l1 );
+
+ foundTextLabel = new KrSqueezedTextLabel(resultTab);
+ foundTextLabel->setFrameShape( QLabel::StyledPanel );
+ foundTextLabel->setFrameShadow( QLabel::Sunken );
+ foundTextLabel->setText("");
+ foundTextLayout->addWidget( foundTextLabel );
+ resultLayout->addLayout(foundTextLayout, 1, 0);
+
+ searcherTabs->insertTab( resultTab, i18n( "&Results" ) );
+
+ searchBaseLayout->addWidget( searcherTabs, 0, 0 );
+
+ // signals and slots connections
+
+ connect( mainSearchBtn, SIGNAL( clicked() ), this, SLOT( startSearch() ) );
+ connect( mainStopBtn, SIGNAL( clicked() ), this, SLOT( stopSearch() ) );
+ connect( resultsList, SIGNAL( returnPressed(QListViewItem*) ), this,
+ SLOT( resultDoubleClicked(QListViewItem*) ) );
+ connect( resultsList, SIGNAL( doubleClicked(QListViewItem*) ), this,
+ SLOT( resultDoubleClicked(QListViewItem*) ) );
+ connect( resultsList, SIGNAL( currentChanged(QListViewItem*) ), this,
+ SLOT( resultClicked(QListViewItem*) ) );
+ connect( resultsList, SIGNAL( clicked(QListViewItem*) ), this,
+ SLOT( resultClicked(QListViewItem*) ) );
+ connect( resultsList, SIGNAL( rightButtonClicked(QListViewItem*,const QPoint&,int) ), this, SLOT( rightClickMenu(QListViewItem*, const QPoint&, int) ) );
+ connect( mainCloseBtn, SIGNAL( clicked() ), this, SLOT( closeDialog() ) );
+ connect( mainFeedToListBoxBtn, SIGNAL( clicked() ), this, SLOT( feedToListBox() ) );
+
+ connect( profileManager, SIGNAL( loadFromProfile( QString ) ), filterTabs, SLOT( loadFromProfile( QString ) ) );
+ connect( profileManager, SIGNAL( saveToProfile( QString ) ), filterTabs, SLOT( saveToProfile( QString ) ) );
+
+ // tab order
+
+ setTabOrder( mainSearchBtn, mainCloseBtn );
+ setTabOrder( mainCloseBtn, mainStopBtn );
+ setTabOrder( mainStopBtn, searcherTabs );
+ setTabOrder( searcherTabs, resultsList );
+
+ krConfig->setGroup( "Search" );
+ int sx = krConfig->readNumEntry( "Window Width", -1 );
+ int sy = krConfig->readNumEntry( "Window Height", -1 );
+
+ if( sx != -1 && sy != -1 )
+ resize( sx, sy );
+
+ if( krConfig->readBoolEntry( "Window Maximized", false ) )
+ showMaximized();
+ else
+ show();
+
+ generalFilter->searchFor->setFocus();
+
+ isSearching = closed = false;
+
+ // finaly, load a profile of apply defaults:
+
+ if ( profile.isEmpty() ) {
+ // load the last used values
+ generalFilter->searchFor->setEditText( lastSearchText );
+ generalFilter->searchFor->lineEdit()->selectAll();
+ generalFilter->ofType->setCurrentItem( lastSearchType );
+ generalFilter->searchForCase->setChecked( lastSearchForCase );
+ generalFilter->remoteContentSearch->setChecked( lastRemoteContentSearch );
+ generalFilter->containsWholeWord->setChecked( lastContainsWholeWord );
+ generalFilter->containsTextCase->setChecked( lastContainsWithCase );
+ generalFilter->searchInDirs->setChecked( lastSearchInSubDirs );
+ generalFilter->searchInArchives->setChecked( lastSearchInArchives );
+ generalFilter->followLinks->setChecked( lastFollowSymLinks );
+ // the path in the active panel should be the default search location
+ generalFilter->searchIn->lineEdit()->setText( ACTIVE_PANEL->virtualPath().prettyURL() );
+ }
+ else
+ profileManager->loadProfile( profile ); // important: call this _after_ you've connected profileManager ot the loadFromProfile!!
+}
+
+void KrSearchDialog::closeDialog( bool isAccept )
+{
+ // stop the search if it's on-going
+ if (searcher!=0) {
+ delete searcher;
+ searcher = 0;
+ }
+
+ // saving the searcher state
+
+ krConfig->setGroup( "Search" );
+
+ krConfig->writeEntry("Window Width", sizeX );
+ krConfig->writeEntry("Window Height", sizeY );
+ krConfig->writeEntry("Window Maximized", isMaximized() );
+
+ krConfig->writeEntry("Name Width", resultsList->columnWidth( 0 ) );
+ krConfig->writeEntry("Path Width", resultsList->columnWidth( 1 ) );
+ krConfig->writeEntry("Size Width", resultsList->columnWidth( 2 ) );
+ krConfig->writeEntry("Date Width", resultsList->columnWidth( 3 ) );
+ krConfig->writeEntry("Perm Width", resultsList->columnWidth( 4 ) );
+
+ lastSearchText = generalFilter->searchFor->currentText();
+ lastSearchType = generalFilter->ofType->currentItem();
+ lastSearchForCase = generalFilter->searchForCase->isChecked();
+ lastRemoteContentSearch = generalFilter->remoteContentSearch->isChecked();
+ lastContainsWholeWord = generalFilter->containsWholeWord->isChecked();
+ lastContainsWithCase = generalFilter->containsTextCase->isChecked();
+ lastSearchInSubDirs = generalFilter->searchInDirs->isChecked();
+ lastSearchInArchives = generalFilter->searchInArchives->isChecked();
+ lastFollowSymLinks = generalFilter->followLinks->isChecked();
+ hide();
+
+ SearchDialog = 0;
+ if( isAccept )
+ QDialog::accept();
+ else
+ QDialog::reject();
+
+ this->deleteLater();
+}
+
+void KrSearchDialog::reject() {
+ closeDialog( false );
+}
+
+void KrSearchDialog::resizeEvent( QResizeEvent *e )
+{
+ if( !isMaximized() )
+ {
+ sizeX = e->size().width();
+ sizeY = e->size().height();
+ }
+}
+
+void KrSearchDialog::found(QString what, QString where, KIO::filesize_t size, time_t mtime, QString perm, QString foundText){
+ // convert the time_t to struct tm
+ struct tm* t=localtime((time_t *)&mtime);
+ QDateTime tmp(QDate(t->tm_year+1900, t->tm_mon+1, t->tm_mday), QTime(t->tm_hour, t->tm_min));
+ ResultListViewItem *it =new ResultListViewItem(resultsList, what,
+ where.replace(QRegExp("\\\\"),"#"), size, tmp, perm);
+ QString totals = QString(i18n("Found %1 matches.")).arg(resultsList->childCount());
+ foundLabel->setText(totals);
+
+ if (!foundText.isEmpty()) it->setFoundText(foundText);
+}
+
+bool KrSearchDialog::gui2query() {
+ // prepare the query ...
+ /////////////////// names, locations and greps
+ if (query!=0) { delete query; query = 0; }
+ query = new KRQuery();
+
+ return filterTabs->fillQuery( query );
+}
+
+void KrSearchDialog::startSearch() {
+
+ // prepare the query /////////////////////////////////////////////
+ if (!gui2query()) return;
+
+ // first, informative messages
+ if ( query->searchInArchives() ) {
+ KMessageBox::information(this, i18n("Since you chose to also search in archives, "
+ "note the following limitations:\n"
+ "You cannot search for text (grep) while doing"
+ " a search that includes archives."), 0, "searchInArchives");
+ }
+
+ // prepare the gui ///////////////////////////////////////////////
+ mainSearchBtn->setEnabled(false);
+ mainCloseBtn->setEnabled(false);
+ mainStopBtn->setEnabled(true);
+ mainFeedToListBoxBtn->setEnabled(false);
+ resultsList->clear();
+ searchingLabel->setText("");
+ foundLabel->setText(i18n("Found 0 matches."));
+ searcherTabs->setCurrentPage(2); // show the results page
+ foundTextLabel->setText("");
+ qApp->processEvents();
+
+ // start the search.
+ if (searcher != 0) {
+ delete searcher;
+ searcher = 0;
+ }
+ searcher = new KRSearchMod(query);
+ connect(searcher, SIGNAL(searching(const QString&)),
+ searchingLabel, SLOT(setText(const QString&)));
+ connect(searcher, SIGNAL(found(QString,QString,KIO::filesize_t,time_t,QString,QString)),
+ this, SLOT(found(QString,QString,KIO::filesize_t,time_t,QString,QString)));
+ connect(searcher, SIGNAL(finished()), this, SLOT(stopSearch()));
+
+ isSearching = true;
+ searcher->start();
+ isSearching = false;
+ if( closed )
+ emit closeDialog();
+}
+
+void KrSearchDialog::stopSearch() {
+ if (searcher!=0) {
+ searcher->stop();
+ disconnect(searcher,0,0,0);
+ delete query;
+ query = 0;
+ }
+
+ // gui stuff
+ mainSearchBtn->setEnabled(true);
+ mainCloseBtn->setEnabled(true);
+ mainStopBtn->setEnabled(false);
+ if( resultsList->childCount() )
+ mainFeedToListBoxBtn->setEnabled( true );
+ searchingLabel->setText(i18n("Finished searching."));
+}
+
+void KrSearchDialog::resultDoubleClicked(QListViewItem* i) {
+ ACTIVE_FUNC->openUrl(vfs::fromPathOrURL(i->text(1)),i->text(0));
+ showMinimized();
+}
+
+void KrSearchDialog::resultClicked(QListViewItem* i) {
+ ResultListViewItem *it = dynamic_cast<ResultListViewItem*>(i);
+ if( it == 0 )
+ return;
+ if (!it->foundText().isEmpty()) {
+ // ugly hack: find the <b> and </b> in the text, then
+ // use it to set the are which we don't want squeezed
+ int idx = it->foundText().find("<b>")-4; // take "<qt>" into account
+ int length = it->foundText().find("</b>")-idx+4;
+ foundTextLabel->setText(it->foundText(), idx, length);
+ }
+}
+
+void KrSearchDialog::closeEvent(QCloseEvent *e)
+{ /* if searching is in progress we must not close the window */
+ if( isSearching ) /* because qApp->processEvents() is called by the searcher and */
+ { /* at window desruction, the searcher object will be deleted */
+ stopSearch(); /* instead we stop searching */
+ closed = true; /* and after stopping: startSearch can close the window */
+ e->ignore(); /* ignoring the close event */
+ }
+ else
+ QDialog::closeEvent( e ); /* if no searching, let QDialog handle the event */
+}
+
+void KrSearchDialog::keyPressEvent(QKeyEvent *e)
+{
+ KKey pressedKey( e );
+
+ if( isSearching && e->key() == Key_Escape ) /* at searching we must not close the window */
+ {
+ stopSearch(); /* so we simply stop searching */
+ return;
+ }
+ if( resultsList->hasFocus() )
+ {
+ if( e->key() == Key_F4 )
+ {
+ if (!generalFilter->containsText->currentText().isEmpty() && QApplication::clipboard()->text() != generalFilter->containsText->currentText())
+ QApplication::clipboard()->setText(generalFilter->containsText->currentText());
+ editCurrent();
+ return;
+ }
+ else if( e->key() == Key_F3 )
+ {
+ if (!generalFilter->containsText->currentText().isEmpty() && QApplication::clipboard()->text() != generalFilter->containsText->currentText())
+ QApplication::clipboard()->setText(generalFilter->containsText->currentText());
+ viewCurrent();
+ return;
+ }
+ else if( Krusader::actCopy->shortcut().contains( pressedKey ) )
+ {
+ copyToClipBoard();
+ return;
+ }
+ }
+
+ QDialog::keyPressEvent( e );
+}
+
+void KrSearchDialog::editCurrent()
+{
+ QListViewItem *current = resultsList->currentItem();
+ if( current )
+ {
+ QString name = current->text(1);
+ name += (name.endsWith( "/" ) ? current->text(0) : "/" + current->text(0) );
+ KURL url = vfs::fromPathOrURL( name );
+ KrViewer::edit( url, this );
+ }
+}
+
+void KrSearchDialog::viewCurrent()
+{
+ QListViewItem *current = resultsList->currentItem();
+ if( current )
+ {
+ QString name = current->text(1);
+ name += (name.endsWith( "/" ) ? current->text(0) : "/" + current->text(0) );
+ KURL url = vfs::fromPathOrURL( name );
+ KrViewer::view( url, this );
+ }
+}
+
+void KrSearchDialog::rightClickMenu(QListViewItem *item, const QPoint&, int)
+{
+ // these are the values that will exist in the menu
+ #define EDIT_FILE_ID 110
+ #define VIEW_FILE_ID 111
+ #define COPY_SELECTED_TO_CLIPBOARD 112
+ //////////////////////////////////////////////////////////
+ if (!item)
+ return;
+
+ // create the menu
+ KPopupMenu popup;
+ popup.insertTitle(i18n("Krusader Search"));
+
+ popup.insertItem(i18n("View File (F3)"), VIEW_FILE_ID);
+ popup.insertItem(i18n("Edit File (F4)"), EDIT_FILE_ID);
+ popup.insertItem(i18n("Copy selected to clipboard"),COPY_SELECTED_TO_CLIPBOARD);
+
+ int result=popup.exec(QCursor::pos());
+
+ // check out the user's option
+ switch (result)
+ {
+ case VIEW_FILE_ID:
+ viewCurrent();
+ break;
+ case EDIT_FILE_ID:
+ editCurrent();
+ break;
+ case COPY_SELECTED_TO_CLIPBOARD:
+ copyToClipBoard();
+ break;
+ default: // the user clicked outside of the menu
+ break;
+ }
+}
+
+void KrSearchDialog::feedToListBox()
+{
+ virt_vfs v(0,true);
+ v.vfs_refresh( KURL( "/" ) );
+
+ krConfig->setGroup( "Search" );
+ int listBoxNum = krConfig->readNumEntry( "Feed To Listbox Counter", 1 );
+ QString queryName;
+ do {
+ queryName = i18n("Search results")+QString( " %1" ).arg( listBoxNum++ );
+ }while( v.vfs_search( queryName ) != 0 );
+ krConfig->writeEntry( "Feed To Listbox Counter", listBoxNum );
+
+ krConfig->setGroup( "Advanced" );
+ if ( krConfig->readBoolEntry( "Confirm Feed to Listbox", _ConfirmFeedToListbox ) ) {
+ bool ok;
+ queryName = KInputDialog::getText(
+ i18n("Query name"), // Caption
+ i18n("Here you can name the file collection"), // Questiontext
+ queryName, // Default
+ &ok );
+ if ( ! ok)
+ return;
+ }
+
+ KURL::List urlList;
+ QListViewItem * item = resultsList->firstChild();
+ while( item )
+ {
+ QString name = item->text(1);
+ name += (name.endsWith( "/" ) ? item->text(0) : "/" + item->text(0) );
+ urlList.push_back( vfs::fromPathOrURL( name ) );
+ item = item->nextSibling();
+ }
+ KURL url = KURL::fromPathOrURL( QString("virt:/") + queryName );
+ v.vfs_refresh( url );
+ v.vfs_addFiles( &urlList, KIO::CopyJob::Copy, 0 );
+ //ACTIVE_FUNC->openUrl(url);
+ ACTIVE_MNG->slotNewTab(url.prettyURL());
+ closeDialog();
+}
+
+void KrSearchDialog::copyToClipBoard()
+{
+ KURL::List urls;
+
+ QListViewItem * item = resultsList->firstChild();
+ while( item )
+ {
+ if( item->isSelected() )
+ {
+ QString name = item->text(1);
+ name += (name.endsWith( "/" ) ? item->text(0) : "/" + item->text(0) );
+ urls.push_back( vfs::fromPathOrURL( name ) );
+ }
+ item = item->nextSibling();
+ }
+
+ if( urls.count() == 0 )
+ return;
+
+ KURLDrag *d = new KURLDrag(urls, this);
+ d->setPixmap( FL_LOADICON( "file" ), QPoint( -7, 0 ) );
+ QApplication::clipboard()->setData( d );
+}
+
+#include "krsearchdialog.moc"
diff --git a/krusader/Search/krsearchdialog.h b/krusader/Search/krsearchdialog.h
new file mode 100644
index 0000000..7bd78c0
--- /dev/null
+++ b/krusader/Search/krsearchdialog.h
@@ -0,0 +1,183 @@
+/***************************************************************************
+ krsearchdialog.h
+ -------------------
+ copyright : (C) 2001 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+
+#ifndef KRSEARCHDIALOG_H
+#define KRSEARCHDIALOG_H
+
+#include "../Filter/filtertabs.h"
+#include "../Filter/generalfilter.h"
+#include "../VFS/krquery.h"
+#include "../VFS/krpermhandler.h"
+#include "krsearchmod.h"
+#include "../GUI/profilemanager.h"
+
+#include <qwidget.h>
+#include <ksqueezedtextlabel.h>
+#include <qstringlist.h>
+#include <sys/types.h>
+#include <time.h>
+#include <qstring.h>
+#include <qtabwidget.h>
+#include <qlistview.h>
+#include <qstringlist.h>
+#include <kglobal.h>
+#include <klocale.h>
+
+class KrSearchDialog : public QDialog {
+ Q_OBJECT
+public:
+ KrSearchDialog(QString profile = 0, QWidget* parent = 0, const char* name = 0, bool modal = false, WFlags fl = 0 );
+
+ void prepareGUI();
+
+ static KrSearchDialog *SearchDialog;
+
+public slots:
+ void startSearch();
+ void stopSearch();
+ void feedToListBox();
+ void copyToClipBoard();
+ void found(QString what, QString where, KIO::filesize_t size, time_t mtime, QString perm, QString foundText);
+ void closeDialog( bool isAccept = true );
+ void resultDoubleClicked(QListViewItem*);
+ void resultClicked(QListViewItem*);
+
+ virtual void keyPressEvent(QKeyEvent *e);
+ virtual void closeEvent(QCloseEvent *e);
+ virtual void rightClickMenu(QListViewItem*, const QPoint&, int);
+ virtual void resizeEvent( QResizeEvent *e );
+
+protected slots:
+ void reject();
+
+private:
+ bool gui2query();
+ void editCurrent();
+ void viewCurrent();
+
+private:
+ ProfileManager *profileManager;
+
+ FilterTabs * filterTabs;
+ GeneralFilter * generalFilter;
+
+ QPushButton* mainHelpBtn;
+ QPushButton* mainSearchBtn;
+ QPushButton* mainStopBtn;
+ QPushButton* mainCloseBtn;
+ QPushButton* mainFeedToListBoxBtn;
+
+ QTabWidget* searcherTabs;
+ QWidget* resultTab;
+ QGridLayout* resultLayout;
+ QLabel* foundLabel;
+ KrSqueezedTextLabel *foundTextLabel;
+ KSqueezedTextLabel *searchingLabel;
+
+ QListView* resultsList;
+
+ KRQuery *query;
+ KRSearchMod *searcher;
+ QStringList savedSearches;
+ bool isSearching;
+ bool closed;
+
+ static QString lastSearchText;
+ static int lastSearchType;
+ static bool lastSearchForCase;
+ static bool lastRemoteContentSearch;
+ static bool lastContainsWholeWord;
+ static bool lastContainsWithCase;
+ static bool lastSearchInSubDirs;
+ static bool lastSearchInArchives;
+ static bool lastFollowSymLinks;
+
+ int sizeX;
+ int sizeY;
+};
+
+class ResultListViewItem : public QListViewItem
+{
+public:
+ ResultListViewItem( QListView *resultsList, QString name, QString where, KIO::filesize_t size,
+ QDateTime date, QString perm ) : QListViewItem( resultsList, name, where,
+ KRpermHandler::parseSize(size),
+ KGlobal::locale()->formatDateTime( date ), perm )
+ {
+ fileSize = size;
+ fileDate = date;
+ setDragEnabled( true );
+ }
+
+ void setFoundText(QString text) { _foundText=text; }
+ const QString& foundText() const { return _foundText; }
+
+ virtual int compare(QListViewItem *i,int col,bool ascending ) const
+ {
+ if( col == 2 ) {
+ ResultListViewItem *other = (ResultListViewItem *)i;
+ KIO::filesize_t otherSize = other->getSize();
+
+ if( fileSize == otherSize )
+ return 0;
+ if( fileSize > otherSize )
+ return 1;
+ return -1;
+ }
+ if( col == 3 ) {
+ ResultListViewItem *other = (ResultListViewItem *)i;
+ QDateTime otherDate = other->getDate();
+
+ if( fileDate == otherDate )
+ return 0;
+ if( fileDate > otherDate )
+ return 1;
+ return -1;
+ }
+ return QListViewItem::compare( i, col, ascending );
+ }
+
+ KIO::filesize_t getSize() {
+ return fileSize;
+ }
+
+ QDateTime getDate() {
+ return fileDate;
+ }
+
+private:
+ KIO::filesize_t fileSize;
+ QDateTime fileDate;
+ QString _foundText;
+};
+
+#endif
diff --git a/krusader/Search/krsearchmod.cpp b/krusader/Search/krsearchmod.cpp
new file mode 100644
index 0000000..c4e8fdd
--- /dev/null
+++ b/krusader/Search/krsearchmod.cpp
@@ -0,0 +1,253 @@
+/***************************************************************************
+ krsearchmod.cpp
+ -------------------
+ copyright : (C) 2001 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+ Description
+***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+#include "krsearchmod.h"
+#include "../VFS/krquery.h"
+#include "../krusader.h"
+#include "../resources.h"
+#include "../VFS/vfile.h"
+#include "../VFS/krpermhandler.h"
+#include "../VFS/krarchandler.h"
+
+#include <klocale.h>
+#include <qdir.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <qtextstream.h>
+#include <qregexp.h>
+#include <klargefile.h>
+#include <kurlrequesterdlg.h>
+
+#include <kmimetype.h>
+
+#define EVENT_PROCESS_DELAY 250
+
+KRSearchMod::KRSearchMod( const KRQuery* q )
+{
+ stopSearch = false; /// ===> added
+ query = new KRQuery( *q );
+ connect( query, SIGNAL( status( const QString & ) ),
+ this, SIGNAL( searching(const QString&) ) );
+ connect( query, SIGNAL( processEvents( bool & ) ),
+ this, SLOT ( slotProcessEvents( bool & ) ) );
+
+ remote_vfs = 0;
+ virtual_vfs = 0;
+}
+
+KRSearchMod::~KRSearchMod()
+{
+ delete query;
+ if( remote_vfs )
+ delete remote_vfs;
+ if( virtual_vfs )
+ delete virtual_vfs;
+}
+
+void KRSearchMod::start()
+{
+ unScannedUrls.clear();
+ scannedUrls.clear();
+ timer.start();
+
+ KURL::List whereToSearch = query->searchInDirs();
+
+ // search every dir that needs to be searched
+ for ( unsigned int i = 0; i < whereToSearch.count(); ++i )
+ scanURL( whereToSearch [ i ] );
+
+ emit finished();
+}
+
+void KRSearchMod::stop()
+{
+ stopSearch = true;
+}
+
+void KRSearchMod::scanURL( KURL url )
+{
+ if( stopSearch ) return;
+
+ unScannedUrls.push( url );
+ while ( !unScannedUrls.isEmpty() )
+ {
+ KURL urlToCheck = unScannedUrls.pop();
+
+ if( stopSearch ) return;
+
+ if( query->isExcluded( urlToCheck ) ) {
+ if( !query->searchInDirs().contains( urlToCheck ) )
+ continue;
+ }
+
+ if( scannedUrls.contains( urlToCheck ) )
+ continue;
+ scannedUrls.push( urlToCheck );
+
+ emit searching( vfs::pathOrURL( urlToCheck ) );
+
+ if ( urlToCheck.isLocalFile() )
+ scanLocalDir( urlToCheck );
+ else
+ scanRemoteDir( urlToCheck );
+ }
+}
+
+void KRSearchMod::scanLocalDir( KURL urlToScan )
+{
+ QString dir = urlToScan.path( 1 );
+
+ DIR* d = opendir( dir.local8Bit() );
+ if ( !d ) return ;
+
+ struct dirent* dirEnt;
+
+ while ( ( dirEnt = readdir( d ) ) != NULL )
+ {
+ QString name = QString::fromLocal8Bit( dirEnt->d_name );
+
+ // we dont scan the ".",".." enteries
+ if ( name == "." || name == ".." ) continue;
+
+ KDE_struct_stat stat_p;
+ KDE_lstat( ( dir + name ).local8Bit(), &stat_p );
+
+ KURL url = vfs::fromPathOrURL( dir + name );
+
+ QString mime = QString::null;
+ if ( query->searchInArchives() || !query->hasMimeType() )
+ mime = KMimeType::findByURL( url, stat_p.st_mode, true, false ) ->name();
+
+ // creating a vfile object for matching with krquery
+ vfile * vf = new vfile(name, (KIO::filesize_t)stat_p.st_size, KRpermHandler::mode2QString(stat_p.st_mode),
+ stat_p.st_mtime, S_ISLNK(stat_p.st_mode), stat_p.st_uid, stat_p.st_gid,
+ mime, "", stat_p.st_mode);
+ vf->vfile_setUrl( url );
+
+ if ( query->isRecursive() )
+ {
+ if ( S_ISLNK( stat_p.st_mode ) && query->followLinks() )
+ unScannedUrls.push( vfs::fromPathOrURL( QDir( dir + name ).canonicalPath() ) );
+ else if ( S_ISDIR( stat_p.st_mode ) )
+ unScannedUrls.push( url );
+ }
+ if ( query->searchInArchives() )
+ {
+ QString type = mime.right( 4 );
+ if ( mime.contains( "-rar" ) ) type = "-rar";
+
+ if ( KRarcHandler::arcSupported( type ) )
+ {
+ KURL archiveURL = url;
+ bool encrypted;
+ QString realType = KRarcHandler::getType( encrypted, url.path(), mime );
+
+ if( !encrypted ) {
+ if ( realType == "-tbz" || realType == "-tgz" || realType == "tarz" || realType == "-tar" )
+ archiveURL.setProtocol( "tar" );
+ else
+ archiveURL.setProtocol( "krarc" );
+
+ unScannedUrls.push( archiveURL );
+ }
+ }
+ }
+
+ if( query->match( vf ) )
+ {
+ // if we got here - we got a winner
+ results.append( dir + name );
+ emit found( name, dir, ( KIO::filesize_t ) stat_p.st_size, stat_p.st_mtime, KRpermHandler::mode2QString( stat_p.st_mode ), query->foundText() );
+ }
+ delete vf;
+
+ if( timer.elapsed() >= EVENT_PROCESS_DELAY ) {
+ qApp->processEvents();
+ timer.start();
+ if( stopSearch ) return;
+ }
+ }
+ // clean up
+ closedir( d );
+}
+
+void KRSearchMod::scanRemoteDir( KURL url )
+{
+ vfs * vfs_;
+
+
+ if( url.protocol() == "virt" )
+ {
+ if( virtual_vfs == 0 )
+ virtual_vfs = new virt_vfs( 0 );
+ vfs_ = virtual_vfs;
+ }
+ else
+ {
+ if( remote_vfs == 0 )
+ remote_vfs = new ftp_vfs( 0 );
+ vfs_ = remote_vfs;
+ }
+
+ if ( !vfs_->vfs_refresh( url ) ) return ;
+
+ for ( vfile * vf = vfs_->vfs_getFirstFile(); vf != 0 ; vf = vfs_->vfs_getNextFile() )
+ {
+ QString name = vf->vfile_getName();
+ KURL fileURL = vfs_->vfs_getFile( name );
+
+ if ( query->isRecursive() && (( vf->vfile_isSymLink() && query->followLinks() ) || vf->vfile_isDir() ) )
+ unScannedUrls.push( fileURL );
+
+ if( query->match( vf ) )
+ {
+ // if we got here - we got a winner
+ results.append( vfs::pathOrURL( fileURL, -1 ) );
+
+ emit found( fileURL.fileName(), vfs::pathOrURL( fileURL.upURL(), -1 ), vf->vfile_getSize(), vf->vfile_getTime_t(), vf->vfile_getPerm(), query->foundText() );
+ }
+
+ if( timer.elapsed() >= EVENT_PROCESS_DELAY ) {
+ qApp->processEvents();
+ timer.start();
+ if( stopSearch ) return;
+ }
+ }
+}
+
+void KRSearchMod::slotProcessEvents( bool & stopped ) {
+ qApp->processEvents();
+ stopped = stopSearch;
+}
+
+#include "krsearchmod.moc"
diff --git a/krusader/Search/krsearchmod.h b/krusader/Search/krsearchmod.h
new file mode 100644
index 0000000..8d66df4
--- /dev/null
+++ b/krusader/Search/krsearchmod.h
@@ -0,0 +1,85 @@
+/***************************************************************************
+ krsearchmod.h
+ -------------------
+ copyright : (C) 2001 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+
+#ifndef KRSEARCHMOD_H
+#define KRSEARCHMOD_H
+
+#include <qobject.h>
+#include <qvaluestack.h>
+#include <qstringlist.h>
+#include <qdatetime.h>
+#include <time.h>
+#include <kio/global.h>
+#include <kurl.h>
+#include "../VFS/ftp_vfs.h"
+#include "../VFS/virt_vfs.h"
+
+
+class KRQuery;
+class ftp_vfs;
+
+class KRSearchMod : public QObject {
+ Q_OBJECT
+public:
+ KRSearchMod(const KRQuery *q);
+ ~KRSearchMod();
+
+ void scanURL( KURL url );
+ void start();
+ void stop();
+
+private:
+ void scanLocalDir( KURL url );
+ void scanRemoteDir( KURL url );
+
+signals:
+ void finished();
+ void searching(const QString&);
+ void found(QString what, QString where, KIO::filesize_t size, time_t mtime, QString perm, QString textFound);
+
+private slots:
+ void slotProcessEvents( bool & stopped );
+
+private:
+ bool stopSearch;
+ QValueStack<KURL> scannedUrls;
+ QValueStack<KURL> unScannedUrls;
+ KRQuery *query;
+ QStringList results;
+
+ ftp_vfs *remote_vfs;
+ virt_vfs *virtual_vfs;
+
+ QTime timer;
+};
+
+#endif
diff --git a/krusader/Splitter/Makefile.am b/krusader/Splitter/Makefile.am
new file mode 100644
index 0000000..756ea94
--- /dev/null
+++ b/krusader/Splitter/Makefile.am
@@ -0,0 +1,11 @@
+noinst_LIBRARIES = libSplitter.a
+
+INCLUDES = $(all_includes)
+
+libSplitter_a_METASOURCES = AUTO
+
+libSplitter_a_SOURCES = \
+ crc32.cpp \
+ splittergui.cpp \
+ splitter.cpp \
+ combiner.cpp
diff --git a/krusader/Splitter/combiner.cpp b/krusader/Splitter/combiner.cpp
new file mode 100644
index 0000000..e32db05
--- /dev/null
+++ b/krusader/Splitter/combiner.cpp
@@ -0,0 +1,328 @@
+/***************************************************************************
+ combiner.cpp - description
+ -------------------
+ copyright : (C) 2003 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "combiner.h"
+#include "../VFS/vfs.h"
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kfileitem.h>
+#include <kio/job.h>
+#include <qfileinfo.h>
+
+Combiner::Combiner( QWidget* parent, KURL baseURLIn, KURL destinationURLIn, bool unixNamingIn ) :
+ QProgressDialog( parent, "Krusader::Combiner", true, 0 ), baseURL( baseURLIn ), destinationURL( destinationURLIn ),
+ hasValidSplitFile( false ), fileCounter ( 0 ), permissions( -1 ), receivedSize( 0 ),
+ combineReadJob( 0 ), combineWriteJob( 0 ), unixNaming( unixNamingIn )
+{
+ crcContext = new CRC32();
+
+ splitFile = "";
+
+ setTotalSteps( 100 );
+ setAutoClose( false ); /* don't close or reset the dialog automatically */
+ setAutoReset( false );
+}
+
+Combiner::~Combiner()
+{
+ combineAbortJobs();
+ delete crcContext;
+}
+
+void Combiner::combine()
+{
+ setCaption( i18n("Krusader::Combining...") );
+ setLabelText( i18n("Combining the file %1...").arg( vfs::pathOrURL( baseURL ) ));
+
+ /* check whether the .crc file exists */
+ splURL = baseURL;
+ splURL.setFileName( baseURL.fileName() + ".crc" );
+ KFileItem file(KFileItem::Unknown, KFileItem::Unknown, splURL );
+ file.refresh();
+
+ if( !file.isReadable() )
+ {
+ int ret = KMessageBox::questionYesNo(0, i18n("The CRC information file (%1) is missing!\n"
+ "Validity checking is impossible without it. Continue combining?")
+ .arg( vfs::pathOrURL( splURL ) ) );
+
+ if( ret == KMessageBox::No )
+ {
+ emit reject();
+ return;
+ }
+
+ openNextFile();
+ }
+ else
+ {
+ permissions = file.permissions() | QFileInfo::WriteUser;
+
+ combineReadJob = KIO::get( splURL, false, false );
+
+ connect(combineReadJob, SIGNAL(data(KIO::Job *, const QByteArray &)),
+ this, SLOT(combineSplitFileDataReceived(KIO::Job *, const QByteArray &)));
+ connect(combineReadJob, SIGNAL(result(KIO::Job*)),
+ this, SLOT(combineSplitFileFinished(KIO::Job *)));
+ }
+
+ exec();
+}
+
+void Combiner::combineSplitFileDataReceived(KIO::Job *, const QByteArray &byteArray)
+{
+ splitFile += QString( byteArray );
+}
+
+void Combiner::combineSplitFileFinished(KIO::Job *job)
+{
+ combineReadJob = 0;
+ QString error;
+
+ if( job->error() )
+ error = i18n("Error at reading the CRC file (%1)!").arg( vfs::pathOrURL( splURL ) );
+ else
+ {
+ splitFile.remove( '\r' ); // Windows compatibility
+ QStringList splitFileContent = QStringList::split( '\n', splitFile );
+
+ bool hasFileName = false, hasSize = false, hasCrc = false;
+
+ for(unsigned int i = 0; i != splitFileContent.count(); i++ )
+ {
+ int ndx = splitFileContent[i].find( '=' );
+ if( ndx == -1 )
+ continue;
+ QString token = splitFileContent[i].left( ndx ).stripWhiteSpace();
+ QString value = splitFileContent[i].mid( ndx + 1 );
+
+ if( token == "filename" )
+ {
+ expectedFileName = value;
+ hasFileName = true;
+ }
+ else if( token == "size" )
+ {
+ sscanf( value.stripWhiteSpace().ascii(), "%llu", &expectedSize );
+ hasSize = true;
+ }
+ if( token == "crc32" )
+ {
+ expectedCrcSum = value.stripWhiteSpace().rightJustify( 8, '0' );
+ hasCrc = true;
+ }
+ }
+
+ if( !hasFileName || !hasSize || !hasCrc )
+ error = i18n("Not a valid CRC file!");
+ else
+ hasValidSplitFile = true;
+ }
+
+ if( !error.isEmpty() )
+ {
+ int ret = KMessageBox::questionYesNo( 0, error+ "\n" +
+ i18n("Validity checking is impossible without a good CRC file. Continue combining?") );
+ if( ret == KMessageBox::No )
+ {
+ emit reject();
+ return;
+ }
+ }
+
+ openNextFile();
+}
+
+void Combiner::openNextFile()
+{
+ if( unixNaming )
+ {
+ if( readURL.isEmpty() )
+ readURL = baseURL;
+ else
+ {
+ QString name = readURL.fileName();
+ int pos = name.length()-1;
+ QChar ch;
+
+ do
+ {
+ ch = name.at( pos ).latin1() + 1;
+ if( ch == QChar( 'Z' + 1 ) )
+ ch = 'A';
+ if( ch == QChar( 'z' + 1 ) )
+ ch = 'a';
+ name[ pos ] = ch;
+ pos--;
+ } while( pos >=0 && ch.upper() == QChar( 'A' ) );
+
+ readURL.setFileName( name );
+ }
+ }
+ else
+ {
+ QString index( "%1" ); /* determining the filename */
+ index = index.arg(++fileCounter).rightJustify( 3, '0' );
+ readURL = baseURL;
+ readURL.setFileName( baseURL.fileName() + "." + index );
+ }
+
+ /* creating a write job */
+ combineReadJob = KIO::get( readURL, false, false );
+
+ connect(combineReadJob, SIGNAL(data(KIO::Job *, const QByteArray &)),
+ this, SLOT(combineDataReceived(KIO::Job *, const QByteArray &)));
+ connect(combineReadJob, SIGNAL(result(KIO::Job*)),
+ this, SLOT(combineReceiveFinished(KIO::Job *)));
+ if( hasValidSplitFile )
+ connect(combineReadJob, SIGNAL(percent (KIO::Job *, unsigned long)),
+ this, SLOT(combineWritePercent(KIO::Job *, unsigned long)));
+
+}
+
+void Combiner::combineDataReceived(KIO::Job *, const QByteArray &byteArray)
+{
+ if( byteArray.size() == 0 )
+ return;
+
+ crcContext->update( (unsigned char *)byteArray.data(), byteArray.size() );
+ transferArray = byteArray.copy();
+
+ receivedSize += byteArray.size();
+
+ if( combineWriteJob == 0 )
+ {
+ writeURL = destinationURL;
+ writeURL.addPath( baseURL.fileName() );
+ if( hasValidSplitFile )
+ writeURL.setFileName( expectedFileName );
+ else if( unixNaming )
+ writeURL.setFileName( baseURL.fileName() + ".out" );
+
+ combineWriteJob = KIO::put( writeURL, permissions, true, false, false );
+
+ connect(combineWriteJob, SIGNAL(dataReq(KIO::Job *, QByteArray &)),
+ this, SLOT(combineDataSend(KIO::Job *, QByteArray &)));
+ connect(combineWriteJob, SIGNAL(result(KIO::Job*)),
+ this, SLOT(combineSendFinished(KIO::Job *)));
+ }
+
+ if( combineWriteJob )
+ {
+ if( combineReadJob ) combineReadJob->suspend(); /* start writing */
+ combineWriteJob->resume();
+ }
+}
+
+void Combiner::combineReceiveFinished(KIO::Job *job)
+{
+ combineReadJob = 0; /* KIO automatically deletes the object after Finished signal */
+
+ if( job->error() )
+ {
+ if( combineWriteJob ) /* write out the remaining part of the file */
+ combineWriteJob->resume();
+
+ if( fileCounter == 1 )
+ {
+ combineAbortJobs();
+ KMessageBox::questionYesNo(0, i18n("Can't open the first split file of %1!")
+ .arg( vfs::pathOrURL( baseURL ) ) );
+ emit reject();
+ return;
+ }
+
+ if( hasValidSplitFile )
+ {
+ QString crcResult = QString( "%1" ).arg( crcContext->result(), 0, 16 ).upper().stripWhiteSpace()
+ .rightJustify(8, '0');
+
+ if( receivedSize != expectedSize )
+ error = i18n("Incorrect filesize! The file might have been corrupted!");
+ else if ( crcResult != expectedCrcSum.upper().stripWhiteSpace() )
+ error = i18n("Incorrect CRC checksum! The file might have been corrupted!");
+ }
+ return;
+ }
+ openNextFile();
+}
+
+void Combiner::combineDataSend(KIO::Job *, QByteArray &byteArray)
+{
+ byteArray = transferArray;
+ transferArray = QByteArray();
+
+ if( combineReadJob )
+ {
+ combineReadJob->resume(); /* start reading */
+ combineWriteJob->suspend();
+ }
+}
+
+void Combiner::combineSendFinished(KIO::Job *job)
+{
+ combineWriteJob = 0; /* KIO automatically deletes the object after Finished signal */
+
+ if( job->error() ) /* any error occurred? */
+ {
+ combineAbortJobs();
+ KMessageBox::error(0, i18n("Error writing file %1!").arg( vfs::pathOrURL( writeURL ) ) );
+ emit reject();
+ return;
+ }
+
+ if( !error.isEmpty() ) /* was any error message at reading ? */
+ {
+ combineAbortJobs(); /* we cannot write out it in combineReceiveFinished */
+ KMessageBox::error(0, error ); /* because emit accept closes it in this function */
+ emit reject();
+ return;
+ }
+
+ emit accept();
+}
+
+void Combiner::combineAbortJobs()
+{
+ if( combineReadJob )
+ combineReadJob->kill();
+ if( combineWriteJob )
+ combineWriteJob->kill();
+
+ combineReadJob = combineWriteJob = 0;
+}
+
+void Combiner::combineWritePercent(KIO::Job *, unsigned long)
+{
+ int percent = (int)((((double)receivedSize / expectedSize ) * 100. ) + 0.5 );
+ setProgress( percent );
+}
+
+#include "combiner.moc"
diff --git a/krusader/Splitter/combiner.h b/krusader/Splitter/combiner.h
new file mode 100644
index 0000000..e1eaac6
--- /dev/null
+++ b/krusader/Splitter/combiner.h
@@ -0,0 +1,92 @@
+/***************************************************************************
+ combiner.h - description
+ -------------------
+ copyright : (C) 2003 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __COMBINER_H__
+#define __COMBINER_H__
+
+#include "crc32.h"
+#include <qstring.h>
+#include <qprogressdialog.h>
+#include <kurl.h>
+#include <kio/jobclasses.h>
+
+class Combiner : public QProgressDialog
+{
+ Q_OBJECT
+
+private:
+ KURL splURL;
+ KURL readURL;
+ KURL writeURL;
+
+ KURL baseURL;
+ KURL destinationURL;
+ CRC32 *crcContext;
+ QByteArray transferArray;
+
+ QString splitFile;
+ QString error;
+
+
+ bool hasValidSplitFile;
+ QString expectedFileName;
+ KIO::filesize_t expectedSize;
+ QString expectedCrcSum;
+
+ int fileCounter;
+ int permissions;
+ KIO::filesize_t receivedSize;
+
+ KIO::TransferJob *combineReadJob;
+ KIO::TransferJob *combineWriteJob;
+
+ bool unixNaming;
+
+public:
+ Combiner( QWidget* parent, KURL baseURLIn, KURL destinationURLIn, bool unixNamingIn=false );
+ ~Combiner();
+
+ void combine();
+
+public slots:
+ void combineSplitFileDataReceived(KIO::Job *, const QByteArray &byteArray);
+ void combineSplitFileFinished(KIO::Job *job);
+ void combineDataReceived(KIO::Job *, const QByteArray &);
+ void combineReceiveFinished(KIO::Job *);
+ void combineDataSend(KIO::Job *, QByteArray &);
+ void combineSendFinished(KIO::Job *);
+ void combineWritePercent(KIO::Job *, unsigned long);
+
+private:
+ void openNextFile();
+ void combineAbortJobs();
+};
+
+#endif /* __COMBINER_H__ */
diff --git a/krusader/Splitter/crc32.cpp b/krusader/Splitter/crc32.cpp
new file mode 100755
index 0000000..b6b807b
--- /dev/null
+++ b/krusader/Splitter/crc32.cpp
@@ -0,0 +1,69 @@
+/***************************************************************************
+ crc32.cpp - description
+ -------------------
+ copyright : (C) 2003 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "crc32.h"
+
+#define MASK1 0x00FFFFFF
+#define MASK2 0xFFFFFFFF
+#define POLYNOMIAL 0xEDB88320
+
+bool CRC32::crc_initialized = false;
+unsigned long CRC32::crc_table[ 256 ];
+
+CRC32::CRC32( unsigned long initialValue )
+{
+ crc_accum = initialValue;
+
+ if( !crc_initialized )
+ {
+ for( int byte = 0; byte != 256; byte++ )
+ {
+ unsigned long data = byte;
+
+ for( int i = 8; i > 0 ; --i )
+ data = data & 1 ? ( data >> 1 ) ^ POLYNOMIAL : data >> 1;
+
+ crc_table[ byte ] = data;
+ }
+
+ crc_initialized = true;
+ }
+}
+
+void CRC32::update( unsigned char *buffer, int bufferLen )
+{
+ while( bufferLen-- > 0 )
+ crc_accum = ( (crc_accum >> 8) & MASK1 ) ^ crc_table[ (crc_accum & 0xff) ^ *buffer++ ];
+}
+
+unsigned long CRC32::result()
+{
+ return ( ~crc_accum ) & MASK2;
+}
diff --git a/krusader/Splitter/crc32.h b/krusader/Splitter/crc32.h
new file mode 100755
index 0000000..696603a
--- /dev/null
+++ b/krusader/Splitter/crc32.h
@@ -0,0 +1,48 @@
+/***************************************************************************
+ crc32.h - description
+ -------------------
+ copyright : (C) 2003 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __CRC32_H__
+#define __CRC32_H__
+
+class CRC32
+{
+private:
+ unsigned long crc_accum;
+ static unsigned long crc_table[ 256 ];
+ static bool crc_initialized;
+
+public:
+ CRC32( unsigned long initialValue = (unsigned long)-1 );
+
+ void update( unsigned char *buffer, int bufferLen );
+ unsigned long result();
+};
+
+#endif /* __CRC32_H__ */
diff --git a/krusader/Splitter/splitter.cpp b/krusader/Splitter/splitter.cpp
new file mode 100644
index 0000000..5543d64
--- /dev/null
+++ b/krusader/Splitter/splitter.cpp
@@ -0,0 +1,252 @@
+/***************************************************************************
+ splitter.cpp - description
+ -------------------
+ copyright : (C) 2003 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "splitter.h"
+#include "../VFS/vfs.h"
+#include <qlayout.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kio/job.h>
+#include <kfileitem.h>
+#include <qfileinfo.h>
+
+Splitter::Splitter( QWidget* parent, KURL fileNameIn, KURL destinationDirIn ) :
+ QProgressDialog( parent, "Krusader::Splitter", true, 0 ), splitSize( 0 )
+{
+ fileName = fileNameIn;
+
+ destinationDir = destinationDirIn;
+
+ crcContext = new CRC32();
+
+ setTotalSteps( 100 );
+ setAutoClose( false ); /* don't close or reset the dialog automatically */
+ setAutoReset( false );
+}
+
+Splitter::~Splitter()
+{
+ splitAbortJobs();
+ delete crcContext;
+}
+
+void Splitter::split( KIO::filesize_t splitSizeIn )
+{
+ KFileItem file(KFileItem::Unknown, KFileItem::Unknown, fileName );
+ file.refresh();
+
+ permissions = file.permissions() | QFileInfo::WriteUser;
+
+ splitSize = splitSizeIn;
+
+ setCaption( i18n("Krusader::Splitting...") );
+ setLabelText( i18n("Splitting the file %1...").arg( vfs::pathOrURL( fileName ) ) );
+
+ if( file.isDir() )
+ {
+ KMessageBox::error(0, i18n("Can't split a directory!"));
+ return;
+ }
+
+ fileSize = 0;
+ fileNumber = 0;
+
+ splitReadJob = KIO::get( fileName, false, false );
+
+ connect(splitReadJob, SIGNAL(data(KIO::Job *, const QByteArray &)),
+ this, SLOT(splitDataReceived(KIO::Job *, const QByteArray &)));
+ connect(splitReadJob, SIGNAL(result(KIO::Job*)),
+ this, SLOT(splitReceiveFinished(KIO::Job *)));
+ connect(splitReadJob, SIGNAL(percent (KIO::Job *, unsigned long)),
+ this, SLOT(splitReceivePercent(KIO::Job *, unsigned long)));
+
+ splitWriteJob = 0;
+ noValidWriteJob = true;
+
+ exec();
+}
+
+void Splitter::splitDataReceived(KIO::Job *, const QByteArray &byteArray)
+{
+ if( byteArray.size() == 0 )
+ return;
+
+ crcContext->update( (unsigned char *)byteArray.data(), byteArray.size() );
+ fileSize += byteArray.size();
+
+ if( noValidWriteJob )
+ splitCreateWriteJob();
+
+ transferArray = byteArray.copy();
+ if(splitWriteJob)
+ {
+ splitReadJob->suspend(); /* start writing */
+ splitWriteJob->resume();
+ }
+}
+
+void Splitter::splitReceiveFinished(KIO::Job *job)
+{
+ splitReadJob = 0; /* KIO automatically deletes the object after Finished signal */
+
+ if( splitWriteJob ) /* write out the end of the file */
+ splitWriteJob->resume();
+
+ if( job->error() ) /* any error occurred? */
+ {
+ splitAbortJobs();
+ KMessageBox::error(0, i18n("Error reading file %1!").arg( vfs::pathOrURL( fileName ) ) );
+ emit reject();
+ return;
+ }
+
+ QString crcResult = QString( "%1" ).arg( crcContext->result(), 0, 16 ).upper().stripWhiteSpace()
+ .rightJustify(8, '0');
+
+ splitFile = QString( "filename=%1\n" ).arg( fileName.fileName() )+
+ QString( "size=%1\n" ) .arg( KIO::number( fileSize ) )+
+ QString( "crc32=%1\n" ) .arg( crcResult );
+}
+
+void Splitter::splitReceivePercent (KIO::Job *, unsigned long percent)
+{
+ setProgress( percent );
+}
+
+void Splitter::splitCreateWriteJob()
+{
+ QString index( "%1" ); /* making the splitted filename */
+ index = index.arg(++fileNumber).rightJustify( 3, '0' );
+ QString outFileName = fileName.fileName() + "." + index;
+
+ writeURL = destinationDir;
+ writeURL.addPath( outFileName );
+
+ /* creating a write job */
+ splitWriteJob = KIO::put( writeURL, permissions, true, false, false );
+ outputFileSize = 0;
+ connect(splitWriteJob, SIGNAL(dataReq(KIO::Job *, QByteArray &)),
+ this, SLOT(splitDataSend(KIO::Job *, QByteArray &)));
+ connect(splitWriteJob, SIGNAL(result(KIO::Job*)),
+ this, SLOT(splitSendFinished(KIO::Job *)));
+ noValidWriteJob = false;
+}
+
+void Splitter::splitDataSend(KIO::Job *, QByteArray &byteArray)
+{
+ int bufferLen = transferArray.size();
+
+ if( noValidWriteJob ) /* splitted file should be closed ? */
+ {
+ byteArray = QByteArray(); /* giving empty buffer which indicates closing */
+ }
+ else if( outputFileSize + bufferLen > splitSize ) /* maximum length reached? */
+ {
+ int shortLen = splitSize - outputFileSize;
+
+ byteArray.duplicate( transferArray.data(), shortLen );
+ transferArray.duplicate( transferArray.data() + shortLen, bufferLen - shortLen );
+
+ noValidWriteJob = true; /* close the current segment */
+ }
+ else
+ {
+ outputFileSize += bufferLen; /* write the whole buffer out to the split file */
+
+ byteArray = transferArray;
+ transferArray = QByteArray();
+
+ if(splitReadJob)
+ {
+ splitReadJob->resume(); /* start reading */
+ splitWriteJob->suspend();
+ }
+ }
+}
+
+void Splitter::splitSendFinished(KIO::Job *job)
+{
+ splitWriteJob = 0; /* KIO automatically deletes the object after Finished signal */
+
+ if( job->error() ) /* any error occurred? */
+ {
+ splitAbortJobs();
+ KMessageBox::error(0, i18n("Error writing file %1!").arg( vfs::pathOrURL( writeURL ) ) );
+ emit reject();
+ return;
+ }
+
+ if( transferArray.size() ) /* any data remained in the transfer buffer? */
+ splitCreateWriteJob(); /* create a new write job */
+ else
+ {
+ /* writing the split information file out */
+ writeURL = destinationDir;
+ writeURL.addPath( fileName.fileName() + ".crc" );
+ splitWriteJob = KIO::put( writeURL, permissions, true, false, false );
+ connect(splitWriteJob, SIGNAL(dataReq(KIO::Job *, QByteArray &)),
+ this, SLOT(splitFileSend(KIO::Job *, QByteArray &)));
+ connect(splitWriteJob, SIGNAL(result(KIO::Job*)),
+ this, SLOT(splitFileFinished(KIO::Job *)));
+ }
+}
+
+void Splitter::splitAbortJobs()
+{
+ if( splitReadJob )
+ splitReadJob->kill();
+ if( splitWriteJob )
+ splitWriteJob->kill();
+
+ splitReadJob = splitWriteJob = 0;
+}
+
+void Splitter::splitFileSend(KIO::Job *, QByteArray &byteArray)
+{
+ const char *content = splitFile.ascii();
+ byteArray.duplicate( content, strlen ( content ) );
+ splitFile = "";
+}
+
+void Splitter::splitFileFinished(KIO::Job *job)
+{
+ splitWriteJob = 0; /* KIO automatically deletes the object after Finished signal */
+
+ if( job->error() ) /* any error occurred? */
+ {
+ KMessageBox::error(0, i18n("Error at writing file %1!").arg( vfs::pathOrURL( writeURL ) ) );
+ emit reject();
+ return;
+ }
+
+ emit accept();
+}
+
+#include "splitter.moc"
diff --git a/krusader/Splitter/splitter.h b/krusader/Splitter/splitter.h
new file mode 100644
index 0000000..fd19c68
--- /dev/null
+++ b/krusader/Splitter/splitter.h
@@ -0,0 +1,83 @@
+/***************************************************************************
+ splitter.h - description
+ -------------------
+ copyright : (C) 2003 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __SPLITTER_H__
+#define __SPLITTER_H__
+
+#include "crc32.h"
+#include <qstring.h>
+#include <qprogressdialog.h>
+#include <kurl.h>
+#include <kio/jobclasses.h>
+
+class Splitter : public QProgressDialog
+{
+ Q_OBJECT
+
+private:
+ KURL fileName;
+ KURL destinationDir;
+ KIO::filesize_t splitSize;
+
+ KIO::filesize_t fileSize;
+ int permissions;
+ QString splitFile;
+
+ KURL writeURL;
+ int fileNumber;
+ KIO::filesize_t outputFileSize;
+ bool noValidWriteJob;
+ CRC32 *crcContext;
+ QByteArray transferArray;
+
+ KIO::TransferJob *splitReadJob;
+ KIO::TransferJob *splitWriteJob;
+
+public:
+ Splitter( QWidget* parent, KURL fileNameIn, KURL destinationDirIn );
+ ~Splitter();
+
+ void split( KIO::filesize_t splitSizeIn );
+
+private:
+ void splitCreateWriteJob();
+ void splitAbortJobs();
+
+public slots:
+ void splitDataReceived(KIO::Job *, const QByteArray &);
+ void splitDataSend(KIO::Job *, QByteArray &);
+ void splitSendFinished(KIO::Job *);
+ void splitReceiveFinished(KIO::Job *);
+ void splitReceivePercent (KIO::Job *, unsigned long);
+ void splitFileSend(KIO::Job *, QByteArray &);
+ void splitFileFinished(KIO::Job *);
+};
+
+#endif /* __SPLITTER_H__ */
diff --git a/krusader/Splitter/splittergui.cpp b/krusader/Splitter/splittergui.cpp
new file mode 100644
index 0000000..39a8e4f
--- /dev/null
+++ b/krusader/Splitter/splittergui.cpp
@@ -0,0 +1,213 @@
+/***************************************************************************
+ splittergui.cpp - description
+ -------------------
+ copyright : (C) 2003 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "splittergui.h"
+#include "../VFS/vfs.h"
+#include <klocale.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <kmessagebox.h>
+
+PredefinedDevice SplitterGUI::predefinedDevices[] = {
+ {i18n( "1.44 MB (3.5\")" ), 1457664},
+ {i18n( "1.2 MB (5.25\")" ), 1213952},
+ {i18n( "720 kB (3.5\")" ), 730112},
+ {i18n( "360 kB (5.25\")" ), 362496},
+ {i18n( "100 MB (ZIP)" ), 100431872},
+ {i18n( "250 MB (ZIP)" ), 250331136},
+ {i18n( "650 MB (CD-R)" ), 650*0x100000},
+ {i18n( "700 MB (CD-R)" ), 700*0x100000}
+ };
+
+SplitterGUI::SplitterGUI( QWidget* parent, KURL fileURL, KURL defaultDir ) :
+ QDialog( parent, "Krusader::SplitterGUI", true, 0 ),
+ userDefinedSize ( 0x100000 ), lastSelectedDevice( 0 ), resultCode( QDialog::Rejected )
+{
+ predefinedDeviceNum = sizeof( predefinedDevices ) / sizeof( PredefinedDevice );
+
+ QGridLayout *grid = new QGridLayout( this );
+ grid->setSpacing( 6 );
+ grid->setMargin( 11 );
+
+ QLabel *splitterLabel = new QLabel( this, "SplitterLabel" );
+ splitterLabel->setText( i18n( "Split the file %1 to directory:" ).arg( vfs::pathOrURL( fileURL ) ) );
+ splitterLabel->setMinimumWidth( 400 );
+ grid->addWidget( splitterLabel,0 ,0 );
+
+ urlReq = new KURLRequester( this, "DestinationDirectory" );
+ urlReq->setURL( vfs::pathOrURL( defaultDir ) );
+ urlReq->setMode( KFile::Directory );
+ grid->addWidget( urlReq, 1 ,0 );
+
+ QHBox *splitSizeLine = new QHBox( this, "splitSizeLine" );
+
+ deviceCombo = new QComboBox( splitSizeLine, "deviceCombo" );
+ for( int i=0; i != predefinedDeviceNum; i++ )
+ deviceCombo->insertItem( predefinedDevices[i].name );
+ deviceCombo->insertItem( i18n( "User Defined" ) );
+
+ QLabel *spacer = new QLabel( splitSizeLine );
+ spacer->setText( " " );
+ spacer->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
+
+ QLabel *bytesPerFile = new QLabel( splitSizeLine, "BytesPerFile" );
+ bytesPerFile->setText( i18n( "Max file size:" ) );
+
+ spinBox = new SplitterSpinBox( splitSizeLine, "spinbox" );
+ spinBox->setMinimumWidth( 85 );
+ spinBox->setEnabled( false );
+
+ sizeCombo = new QComboBox( splitSizeLine, "sizeCombo" );
+ sizeCombo->insertItem( i18n( "Byte" ) );
+ sizeCombo->insertItem( i18n( "kByte" ) );
+ sizeCombo->insertItem( i18n( "MByte" ) );
+ sizeCombo->insertItem( i18n( "GByte" ) );
+
+ grid->addWidget( splitSizeLine,2 ,0 );
+
+ QFrame *separator = new QFrame( this, "separatorLine" );
+ separator->setFrameStyle( QFrame::HLine | QFrame::Sunken );
+ separator->setFixedHeight( separator->sizeHint().height() );
+
+ grid->addWidget( separator,3 ,0 );
+
+ QHBoxLayout *splitButtons = new QHBoxLayout;
+ splitButtons->setSpacing( 6 );
+ splitButtons->setMargin( 0 );
+
+ QSpacerItem* spacer2 = new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ splitButtons->addItem( spacer2 );
+
+ QPushButton *splitBtn = new QPushButton( this, "splitBtn" );
+ splitBtn->setText( i18n("&Split") );
+ splitButtons->addWidget( splitBtn );
+
+ QPushButton *cancelBtn = new QPushButton( this, "cancelBtn" );
+ cancelBtn->setText( i18n("&Cancel") );
+ splitButtons->addWidget( cancelBtn );
+
+ grid->addLayout( splitButtons,4 ,0 );
+
+ setCaption(i18n("Krusader::Splitter"));
+
+ connect( sizeCombo, SIGNAL( activated(int) ), this, SLOT( sizeComboActivated( int ) ) );
+ connect( deviceCombo, SIGNAL( activated(int) ), this, SLOT( predefinedComboActivated( int ) ) );
+ connect( cancelBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
+ connect( splitBtn , SIGNAL( clicked() ), this, SLOT( splitPressed() ) );
+
+ predefinedComboActivated( 0 );
+ resultCode = exec();
+}
+
+void SplitterGUI::sizeComboActivated( int item )
+{
+ switch ( item )
+ {
+ case 0:
+ spinBox->setDivision( 1 ); /* byte */
+ break;
+ case 1:
+ spinBox->setDivision( 0x400 ); /* kbyte */
+ break;
+ case 2:
+ spinBox->setDivision( 0x100000 ); /* Mbyte */
+ break;
+ case 3:
+ spinBox->setDivision( 0x40000000 ); /* Gbyte */
+ break;
+ }
+}
+
+void SplitterGUI::predefinedComboActivated( int item )
+{
+ int capacity = userDefinedSize;
+
+ if( item < predefinedDeviceNum )
+ {
+ if( lastSelectedDevice == predefinedDeviceNum )
+ userDefinedSize = spinBox->longValue();
+
+ spinBox->setEnabled( false );
+ capacity = predefinedDevices[item].capacity;
+ }
+ else
+ spinBox->setEnabled( true );
+
+ spinBox->setLongValue( capacity );
+
+ if( capacity >= 0x40000000 ) /* Gbyte */
+ {
+ sizeCombo->setCurrentItem( 3 );
+ spinBox->setDivision( 0x40000000 );
+ }
+ else if( capacity >= 0x100000 ) /* Mbyte */
+ {
+ sizeCombo->setCurrentItem( 2 );
+ spinBox->setDivision( 0x100000 );
+ }
+ else if( capacity >= 0x400 ) /* kbyte */
+ {
+ sizeCombo->setCurrentItem( 1 );
+ spinBox->setDivision( 0x400 );
+ }
+ else
+ {
+ sizeCombo->setCurrentItem( 0 ); /* byte */
+ spinBox->setDivision( 1 );
+ }
+
+ lastSelectedDevice = item;
+}
+
+void SplitterGUI::splitPressed()
+{
+ if( !vfs::fromPathOrURL( urlReq->url() ).isValid() )
+ {
+ KMessageBox::error( this, i18n("The directory path URL is malformed!") );
+ return;
+ }
+
+ emit accept();
+}
+
+void SplitterGUI::keyPressEvent( QKeyEvent *e )
+{
+ switch ( e->key() )
+ {
+ case Key_Enter :
+ case Key_Return :
+ emit splitPressed();
+ return;
+ default:
+ QDialog::keyPressEvent( e );
+ }
+}
+
+#include "splittergui.moc"
diff --git a/krusader/Splitter/splittergui.h b/krusader/Splitter/splittergui.h
new file mode 100644
index 0000000..fa5953c
--- /dev/null
+++ b/krusader/Splitter/splittergui.h
@@ -0,0 +1,178 @@
+/***************************************************************************
+ splittergui.h - description
+ -------------------
+ copyright : (C) 2003 by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __SPLITTERGUI_H__
+#define __SPLITTERGUI_H__
+
+#include <qdialog.h>
+#include <qstring.h>
+#include <qspinbox.h>
+#include <qvalidator.h>
+#include <qcombobox.h>
+#include <kurlrequester.h>
+#include <kio/global.h>
+
+#include "../VFS/vfs.h"
+
+struct PredefinedDevice
+{
+ QString name;
+ KIO::filesize_t capacity;
+};
+
+class SplitterGUI : QDialog
+{
+ Q_OBJECT
+
+public:
+ class SplitterSpinBox;
+
+private:
+ int predefinedDeviceNum;
+ KIO::filesize_t userDefinedSize;
+ int lastSelectedDevice;
+ int resultCode;
+
+ static PredefinedDevice predefinedDevices[];
+
+ SplitterSpinBox *spinBox;
+ QComboBox *deviceCombo;
+ QComboBox *sizeCombo;
+ KURLRequester *urlReq;
+
+public:
+ SplitterGUI( QWidget* parent, KURL fileURL, KURL defaultDir );
+
+ KURL getDestinationDir() {return vfs::fromPathOrURL( urlReq->url() );}
+ KIO::filesize_t getSplitSize() {return spinBox->longValue();}
+ int result() {return resultCode;}
+
+public slots:
+ virtual void sizeComboActivated( int item );
+ virtual void predefinedComboActivated( int item );
+ virtual void splitPressed();
+
+protected:
+ virtual void keyPressEvent( QKeyEvent *e );
+
+public:
+ class SplitterSpinBox : public QSpinBox
+ {
+ private:
+ KIO::filesize_t division;
+ KIO::filesize_t value;
+
+ public:
+ SplitterSpinBox ( QWidget * parent = 0, const char * name = 0 ) : QSpinBox( parent, name ), division( 1 ), value( 1 )
+ {
+ setMaxValue( 0x7FFFFFFF ); /* setting the minimum and maximum values */
+ setMinValue( 1 );
+ QDoubleValidator *dval = new QDoubleValidator( this );
+ setValidator ( dval );
+ }
+
+ void setLongValue( KIO::filesize_t valueIn ) {
+ value = valueIn;
+ if( value == 0 )
+ value++;
+ updateDisplay();
+ }
+
+ KIO::filesize_t longValue() {
+ KIO::filesize_t val = (KIO::filesize_t)( division * text().toDouble() + 0.5 ) ;
+ if( val == 0 )
+ val++;
+ return val;
+ }
+
+ QString mapValueToText( int )
+ {
+ QString frac("");
+
+ KIO::filesize_t int_part = value / division;
+ KIO::filesize_t frac_mod = value % division;
+
+ if( frac_mod )
+ {
+ KIO::filesize_t frac_part = (KIO::filesize_t)((1000. * frac_mod) /division + 0.5);
+
+ if( frac_part )
+ {
+ frac = QString( "%1" ).arg( frac_part ).rightJustify( 3, '0' );
+ frac = "." + frac;
+ while( frac.endsWith("0") )
+ frac.truncate( frac.length() - 1 );
+ }
+ }
+
+ return QString( "%1%2" ).arg( int_part ).arg( frac );
+ }
+
+ int mapTextToValue( bool * )
+ {
+ value = longValue();
+
+ if( value > 0x7FFFFFFF )
+ return 0x7FFFFFFF;
+ else
+ return value;
+ }
+
+ void setDivision( KIO::filesize_t div )
+ {
+ division = div;
+ updateDisplay();
+ }
+
+ public slots:
+
+ void stepUp()
+ {
+ value = longValue();
+
+ if( value + division > value )
+ value += division;
+ updateDisplay();
+ }
+
+ void stepDown()
+ {
+ value = longValue();
+
+ if( value < division + 1 )
+ value = 1;
+ else
+ value -= division;
+ updateDisplay();
+ }
+ };
+};
+
+#endif /* __SPLITTERGUI_H__ */
diff --git a/krusader/Synchronizer/Makefile.am b/krusader/Synchronizer/Makefile.am
new file mode 100755
index 0000000..f270b65
--- /dev/null
+++ b/krusader/Synchronizer/Makefile.am
@@ -0,0 +1,13 @@
+noinst_LIBRARIES = libSynchronizer.a
+
+INCLUDES = $(all_includes)
+
+libSynchronizer_a_METASOURCES = AUTO
+
+libSynchronizer_a_SOURCES = \
+ synchronizedialog.cpp \
+ synchronizer.cpp \
+ synchronizergui.cpp \
+ feedtolistboxdialog.cpp \
+ synchronizertask.cpp \
+ synchronizerdirlist.cpp
diff --git a/krusader/Synchronizer/feedtolistboxdialog.cpp b/krusader/Synchronizer/feedtolistboxdialog.cpp
new file mode 100644
index 0000000..b1bec38
--- /dev/null
+++ b/krusader/Synchronizer/feedtolistboxdialog.cpp
@@ -0,0 +1,200 @@
+/***************************************************************************
+ feedtolistboxdialog.cpp - description
+ -------------------
+ copyright : (C) 2006 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "feedtolistboxdialog.h"
+#include "synchronizer.h"
+#include "synchronizergui.h"
+#include "../VFS/vfs.h"
+#include "../VFS/virt_vfs.h"
+#include "../krusader.h"
+#include "../krusaderview.h"
+#include "../panelmanager.h"
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <qcheckbox.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qlabel.h>
+#include <qhbox.h>
+#include <qcombobox.h>
+#include <qframe.h>
+
+#define S_LEFT 0
+#define S_RIGHT 1
+#define S_BOTH 2
+
+FeedToListBoxDialog::FeedToListBoxDialog(QWidget *parent, const char *name, Synchronizer *sync,
+ QListView *syncL, bool equOK) : KDialogBase( parent, name, true, i18n( "Krusader::Feed to listbox" ),
+ KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::User1, Ok, true, KStdGuiItem::clear() ),
+ synchronizer( sync ), syncList( syncL ), equalAllowed( equOK ), accepted( false ) {
+
+ // autodetecting the parameters
+
+ int selectedNum = 0;
+ int itemNum = 0;
+ int leftExistingNum = 0;
+ int rightExistingNum = 0;
+
+ QListViewItemIterator it( syncList );
+ while( it.current() ) {
+ SynchronizerGUI::SyncViewItem *item = (SynchronizerGUI::SyncViewItem *) it.current();
+ SynchronizerFileItem *syncItem = item->synchronizerItemRef();
+
+ if( syncItem && syncItem->isMarked() ) {
+ if( item->isSelected() || syncItem->task() != TT_EQUALS || equalAllowed ) {
+ itemNum++;
+ if( item->isSelected() )
+ selectedNum++;
+
+ if( syncItem->existsInLeft() )
+ leftExistingNum++;
+ if( syncItem->existsInRight() )
+ rightExistingNum++;
+ }
+ }
+ it++;
+ }
+
+ if( itemNum == 0 ) {
+ hide();
+ KMessageBox::error( parent, i18n( "No elements to feed!" ) );
+ return;
+ }
+
+ // guessing the collection name
+
+ virt_vfs v(0,true);
+ if( !v.vfs_refresh( KURL( "virt:/" ) ) )
+ return;
+
+ krConfig->setGroup( "Synchronize" );
+ int listBoxNum = krConfig->readNumEntry( "Feed To Listbox Counter", 1 );
+ QString queryName;
+ do {
+ queryName = i18n("Synchronize results")+QString( " %1" ).arg( listBoxNum++ );
+ }while( v.vfs_search( queryName ) != 0 );
+ krConfig->writeEntry( "Feed To Listbox Counter", listBoxNum );
+
+ // creating the widget
+
+ QWidget *widget=new QWidget(this, "feedToListBoxMainWidget");
+ QVBoxLayout *layout = new QVBoxLayout( widget, 0, 10, "FeedToListBoxDialogLayout" );
+
+ QLabel *label = new QLabel( i18n("Here you can name the file collection"), widget, "fbLabel" );
+ layout->addWidget( label );
+
+ lineEdit = new QLineEdit( widget, "fbLineEdit" );
+ lineEdit->setText( queryName );
+ lineEdit->selectAll();
+ layout->addWidget( lineEdit );
+
+ QHBox *hbox = new QHBox( widget, "fbHBox" );
+
+ QLabel *label2 = new QLabel( i18n( "Side to feed:" ), hbox, "fbSideLabel" );
+ label2->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
+
+ sideCombo = new QComboBox( hbox, "fbSideCombo" );
+ sideCombo->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ sideCombo->insertItem( i18n( "Left" ) );
+ sideCombo->insertItem( i18n( "Right" ) );
+ sideCombo->insertItem( i18n( "Both" ) );
+ if( leftExistingNum == 0 ) {
+ sideCombo->setCurrentItem( 1 );
+ sideCombo->setEnabled( false );
+ } else if( rightExistingNum == 0 ) {
+ sideCombo->setCurrentItem( 0 );
+ sideCombo->setEnabled( false );
+ } else
+ sideCombo->setCurrentItem( 2 );
+
+ QFrame *line = new QFrame( hbox, "fbVLine" );
+ line->setFrameStyle( QFrame::VLine | QFrame::Sunken );
+ line->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
+
+ cbSelected = new QCheckBox( i18n( "Selected files only" ), hbox, "cbSelected" );
+ cbSelected->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ cbSelected->setEnabled( selectedNum != 0 );
+ cbSelected->setChecked( selectedNum != 0 );
+
+ layout->addWidget( hbox );
+
+ setMainWidget(widget);
+
+ exec();
+}
+
+void FeedToListBoxDialog::slotUser1() {
+ lineEdit->clear();
+}
+
+void FeedToListBoxDialog::slotOk() {
+ int side = sideCombo->currentItem();
+ bool selected = cbSelected->isChecked();
+ QString name = lineEdit->text();
+ KURL::List urlList;
+
+ QListViewItemIterator it( syncList );
+ for( ;it.current(); it++ ) {
+ SynchronizerGUI::SyncViewItem *item = (SynchronizerGUI::SyncViewItem *) it.current();
+ SynchronizerFileItem *syncItem = item->synchronizerItemRef();
+
+ if( !syncItem || !syncItem->isMarked() )
+ continue;
+ if( selected && !item->isSelected() )
+ continue;
+ if( !equalAllowed && syncItem->task() == TT_EQUALS && (!selected || !item->isSelected() ) )
+ continue;
+
+ if( ( side == S_BOTH || side == S_LEFT ) && syncItem->existsInLeft() ) {
+ QString leftDirName = syncItem->leftDirectory().isEmpty() ? "" : syncItem->leftDirectory() + "/";
+ KURL leftURL = vfs::fromPathOrURL( synchronizer->leftBaseDirectory() + leftDirName + syncItem->leftName() );
+ urlList.push_back( leftURL );
+ }
+
+ if( ( side == S_BOTH || side == S_RIGHT ) && syncItem->existsInRight() ) {
+ QString rightDirName = syncItem->rightDirectory().isEmpty() ? "" : syncItem->rightDirectory() + "/";
+ KURL leftURL = vfs::fromPathOrURL( synchronizer->rightBaseDirectory() + rightDirName + syncItem->rightName() );
+ urlList.push_back( leftURL );
+ }
+ }
+
+ KURL url = KURL::fromPathOrURL(QString("virt:/")+ name);
+ virt_vfs v(0,true);
+ if( !v.vfs_refresh( url ) ) {
+ KMessageBox::error( parentWidget(), i18n( "Cannot open %1!" ).arg( url.prettyURL() ) );
+ return;
+ }
+ v.vfs_addFiles( &urlList, KIO::CopyJob::Copy, 0 );
+ ACTIVE_MNG->slotNewTab(url.prettyURL());
+ accepted = true;
+ accept();
+}
+
+#include "feedtolistboxdialog.moc"
diff --git a/krusader/Synchronizer/feedtolistboxdialog.h b/krusader/Synchronizer/feedtolistboxdialog.h
new file mode 100644
index 0000000..40de3d5
--- /dev/null
+++ b/krusader/Synchronizer/feedtolistboxdialog.h
@@ -0,0 +1,65 @@
+/***************************************************************************
+ feedtolistboxdialog.h - description
+ -------------------
+ copyright : (C) 2006 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __FEED_TO_LISTBOX_DIALOG__
+#define __FEED_TO_LISTBOX_DIALOG__
+
+#include <kdialogbase.h>
+
+class Synchronizer;
+class QCheckBox;
+class QLineEdit;
+class QComboBox;
+class QListView;
+
+class FeedToListBoxDialog : public KDialogBase {
+ Q_OBJECT
+
+ public:
+ FeedToListBoxDialog( QWidget*, const char*, Synchronizer *, QListView *, bool);
+ virtual ~FeedToListBoxDialog() {};
+
+ bool isAccepted() {return accepted;};
+
+ protected:
+ void slotUser1();
+ void slotOk();
+
+ private:
+ Synchronizer * synchronizer;
+ QListView * syncList;
+ QCheckBox * cbSelected;
+ QLineEdit * lineEdit;
+ QComboBox * sideCombo;
+ bool equalAllowed;
+ bool accepted;
+};
+
+#endif /* __FEED_TO_LISTBOX_DIALOG__ */
diff --git a/krusader/Synchronizer/synchronizedialog.cpp b/krusader/Synchronizer/synchronizedialog.cpp
new file mode 100755
index 0000000..41d4d92
--- /dev/null
+++ b/krusader/Synchronizer/synchronizedialog.cpp
@@ -0,0 +1,199 @@
+/***************************************************************************
+ synchronizedialog.cpp - description
+ -------------------
+ copyright : (C) 2003 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "synchronizedialog.h"
+#include "../VFS/krpermhandler.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include <qlayout.h>
+#include <qhbox.h>
+#include <klocale.h>
+
+SynchronizeDialog::SynchronizeDialog( QWidget* parent, const char* name, bool modal, WFlags fl,
+ Synchronizer *sync, int pleftCopyNr, KIO::filesize_t pleftCopySize,
+ int prightCopyNr, KIO::filesize_t prightCopySize, int pdeleteNr,
+ KIO::filesize_t pdeleteSize, int parThreads ) : QDialog( parent, name, modal, fl ),
+ synchronizer( sync ), leftCopyNr ( pleftCopyNr ),
+ leftCopySize( pleftCopySize ), rightCopyNr ( prightCopyNr ),
+ rightCopySize( prightCopySize ), deleteNr( pdeleteNr ),
+ deleteSize( pdeleteSize ), parallelThreads( parThreads ),
+ isPause( true ), syncStarted( false )
+{
+ setCaption( i18n("Krusader::Synchronize") );
+
+ QVBoxLayout *layout = new QVBoxLayout( this, 11, 6, "SynchronizeDialogLayout" );
+
+ cbRightToLeft = new QCheckBox( i18n( "Right to left: Copy 1 file", "Right to left: Copy %n files", leftCopyNr) + " " +
+ i18n( "(1 byte)", "(%n bytes)", KRpermHandler::parseSize( leftCopySize ).stripWhiteSpace().toInt() ),
+ this, "labelRightToLeft" );
+ cbRightToLeft->setChecked( leftCopyNr != 0 );
+ cbRightToLeft->setEnabled( leftCopyNr != 0 );
+ layout->addWidget( cbRightToLeft );
+
+ lbRightToLeft = new QLabel( "\t" + i18n( "Ready: %1/1 file, %3/%4", "Ready: %1/%n files, %3/%4", leftCopyNr).arg( 0 )
+ .arg( 0 ).arg( KRpermHandler::parseSize( leftCopySize ).stripWhiteSpace() ),
+ this, "lbRightToLeft" );
+ lbRightToLeft->setEnabled( leftCopyNr != 0 );
+ layout->addWidget( lbRightToLeft );
+
+ cbLeftToRight = new QCheckBox( i18n( "Left to right: Copy 1 file", "Left to right: Copy %n files", rightCopyNr) + " " +
+ i18n( "(1 byte)", "(%n bytes)", KRpermHandler::parseSize( rightCopySize ).stripWhiteSpace().toInt() ),
+ this, "cbLeftToRight" );
+ cbLeftToRight->setChecked( rightCopyNr != 0 );
+ cbLeftToRight->setEnabled( rightCopyNr != 0 );
+ layout->addWidget( cbLeftToRight );
+
+ lbLeftToRight = new QLabel( "\t" + i18n( "Ready: %1/1 file, %3/%4", "Ready: %1/%n files, %3/%4", rightCopyNr ).arg( 0 )
+ .arg( 0 ).arg( KRpermHandler::parseSize( rightCopySize ).stripWhiteSpace() ),
+ this, "lbLeftToRight" );
+ lbLeftToRight->setEnabled( rightCopyNr != 0 );
+ layout->addWidget( lbLeftToRight );
+
+ cbDeletable = new QCheckBox( i18n( "Left: Delete 1 file", "Left: Delete %n files", deleteNr) + " " +
+ i18n( "(1 byte)", "(%n bytes)", KRpermHandler::parseSize( deleteSize ).stripWhiteSpace().toInt() ),
+ this, "cbDeletable" );
+ cbDeletable->setChecked( deleteNr != 0 );
+ cbDeletable->setEnabled( deleteNr != 0 );
+ layout->addWidget( cbDeletable );
+
+ lbDeletable = new QLabel( "\t" + i18n( "Ready: %1/1 file, %3/%4", "Ready: %1/%n files, %3/%4", deleteNr ).arg( 0 )
+ .arg( 0 ).arg( KRpermHandler::parseSize( deleteSize ).stripWhiteSpace() ),
+ this, "lbDeletable" );
+ lbDeletable->setEnabled( deleteNr != 0 );
+ layout->addWidget( lbDeletable );
+
+ progress = new QProgressBar(1000, this);
+ progress->setCenterIndicator(true);
+ progress->setProgress( 0 );
+ progress->setMinimumWidth( 400 );
+ layout->addWidget( progress );
+
+ QHBox *hbox = new QHBox( this, "SynchronizeDialogHBox" );
+ hbox->setSpacing( 6 );
+
+ cbOverwrite = new QCheckBox( i18n( "Confirm overwrites" ), this, "cbOverWrite" );
+ krConfig->setGroup("Synchronize");
+ cbOverwrite->setChecked( krConfig->readBoolEntry( "Confirm overwrites", _ConfirmOverWrites ) );
+ layout->addWidget( cbOverwrite );
+
+ QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ hbox->layout()->addItem( spacer );
+
+ btnStart = new QPushButton( hbox, "btnStart" );
+ btnStart->setText( i18n( "&Start" ) );
+
+ btnPause = new QPushButton( hbox, "btnPause" );
+ btnPause->setEnabled( false );
+ btnPause->setText( i18n( "&Pause" ) );
+
+ QPushButton *btnClose = new QPushButton( hbox, "btnClose" );
+ btnClose->setText( i18n( "&Close" ) );
+
+ layout->addWidget( hbox );
+
+ connect( btnStart, SIGNAL( clicked() ), this, SLOT( startSynchronization() ) );
+ connect( btnPause, SIGNAL( clicked() ), this, SLOT( pauseOrResume() ) );
+ connect( btnClose, SIGNAL( clicked() ), this, SLOT( reject() ) );
+
+ exec();
+}
+
+SynchronizeDialog::~SynchronizeDialog()
+{
+ krConfig->writeEntry("Confirm overwrites", cbOverwrite->isChecked() );
+}
+
+void SynchronizeDialog::startSynchronization()
+{
+ btnStart->setEnabled( false );
+ btnPause->setEnabled( syncStarted = true );
+ connect( synchronizer, SIGNAL( synchronizationFinished() ), this, SLOT( synchronizationFinished() ) );
+ connect( synchronizer, SIGNAL( processedSizes( int, KIO::filesize_t, int, KIO::filesize_t, int, KIO::filesize_t ) ),
+ this, SLOT( processedSizes( int, KIO::filesize_t, int, KIO::filesize_t, int, KIO::filesize_t) ) );
+ connect( synchronizer, SIGNAL( pauseAccepted() ), this, SLOT( pauseAccepted() ) );
+
+ if( !cbRightToLeft->isChecked() ) leftCopySize = 0;
+ if( !cbLeftToRight->isChecked() ) rightCopySize = 0;
+ if( !cbDeletable->isChecked() ) deleteSize = 0;
+
+ synchronizer->synchronize( this, cbRightToLeft->isChecked(), cbLeftToRight->isChecked(),
+ cbDeletable->isChecked(), !cbOverwrite->isChecked(), parallelThreads );
+}
+
+void SynchronizeDialog::synchronizationFinished()
+{
+ QDialog::reject();
+}
+
+void SynchronizeDialog::processedSizes( int leftNr, KIO::filesize_t leftSize, int rightNr,
+ KIO::filesize_t rightSize, int delNr, KIO::filesize_t delSize )
+{
+ lbRightToLeft->setText( i18n( "\tReady: %1/%2 files, %3/%4" ).arg( leftNr ).arg( leftCopyNr )
+ .arg( KRpermHandler::parseSize( leftSize ).stripWhiteSpace() )
+ .arg( KRpermHandler::parseSize( leftCopySize ).stripWhiteSpace() ) );
+ lbLeftToRight->setText( i18n( "\tReady: %1/%2 files, %3/%4" ).arg( rightNr ).arg( rightCopyNr )
+ .arg( KRpermHandler::parseSize( rightSize ).stripWhiteSpace() )
+ .arg( KRpermHandler::parseSize( rightCopySize ).stripWhiteSpace() ) );
+ lbDeletable->setText ( i18n( "\tReady: %1/%2 files, %3/%4" ).arg( delNr ).arg( deleteNr )
+ .arg( KRpermHandler::parseSize( delSize ).stripWhiteSpace() )
+ .arg( KRpermHandler::parseSize( deleteSize ).stripWhiteSpace() ) );
+
+ KIO::filesize_t totalSum = leftCopySize + rightCopySize + deleteSize;
+ KIO::filesize_t processedSum = leftSize + rightSize + delSize;
+
+ if( totalSum == 0 )
+ totalSum++;
+
+ progress->setProgress( (int)(((double)processedSum / (double)totalSum )*1000) );
+}
+
+void SynchronizeDialog::pauseOrResume()
+{
+ if( isPause )
+ {
+ btnPause->setEnabled( false );
+ synchronizer->pause();
+ }
+ else
+ {
+ btnPause->setText( i18n( "Pause" ) );
+ synchronizer->resume();
+ isPause = true;
+ }
+}
+
+void SynchronizeDialog::pauseAccepted()
+{
+ btnPause->setText( i18n( "Resume" ) );
+ btnPause->setEnabled( true );
+ isPause = false;
+}
+
+#include "synchronizedialog.moc"
diff --git a/krusader/Synchronizer/synchronizedialog.h b/krusader/Synchronizer/synchronizedialog.h
new file mode 100755
index 0000000..7c21aef
--- /dev/null
+++ b/krusader/Synchronizer/synchronizedialog.h
@@ -0,0 +1,91 @@
+/***************************************************************************
+ synchronizedialog.h - description
+ -------------------
+ copyright : (C) 2003 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __SYNCHRONIZE_DIALOG__
+#define __SYNCHRONIZE_DIALOG__
+
+#include "../VFS/vfs.h"
+#include "synchronizer.h"
+#include <qdialog.h>
+#include <qpushbutton.h>
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qprogressbar.h>
+
+class SynchronizeDialog : QDialog
+{
+ Q_OBJECT
+
+ public:
+ SynchronizeDialog( QWidget*, const char*, bool, WFlags, Synchronizer *sync,
+ int, KIO::filesize_t, int, KIO::filesize_t, int, KIO::filesize_t, int);
+ ~SynchronizeDialog();
+
+ inline bool wasSyncronizationStarted() { return syncStarted; }
+
+ public slots:
+ void startSynchronization();
+ void synchronizationFinished();
+ void processedSizes( int, KIO::filesize_t, int, KIO::filesize_t, int, KIO::filesize_t);
+ void pauseOrResume();
+ void pauseAccepted();
+
+ private:
+ QProgressBar *progress;
+
+ QCheckBox *cbRightToLeft;
+ QCheckBox *cbLeftToRight;
+ QCheckBox *cbDeletable;
+
+ QLabel *lbRightToLeft;
+ QLabel *lbLeftToRight;
+ QLabel *lbDeletable;
+
+ QCheckBox *cbOverwrite;
+
+ QPushButton *btnStart;
+ QPushButton *btnPause;
+
+ Synchronizer *synchronizer;
+
+ int leftCopyNr;
+ KIO::filesize_t leftCopySize;
+ int rightCopyNr;
+ KIO::filesize_t rightCopySize;
+ int deleteNr;
+ KIO::filesize_t deleteSize;
+
+ int parallelThreads;
+
+ bool isPause;
+ bool syncStarted;
+};
+
+#endif /* __SYNCHRONIZE_DIALOG__ */
diff --git a/krusader/Synchronizer/synchronizer.cpp b/krusader/Synchronizer/synchronizer.cpp
new file mode 100755
index 0000000..1568f60
--- /dev/null
+++ b/krusader/Synchronizer/synchronizer.cpp
@@ -0,0 +1,1493 @@
+/***************************************************************************
+ synchronizer.cpp - description
+ -------------------
+ copyright : (C) 2003 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "synchronizer.h"
+#include "synchronizerdirlist.h"
+#include "../krusader.h"
+#include "../krservices.h"
+#include "../VFS/vfs.h"
+#include "../VFS/krquery.h"
+#include "config.h"
+#include <kurl.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <qapplication.h>
+#include <qregexp.h>
+#include <qdir.h>
+#include <qtimer.h>
+#include <kio/job.h>
+#include <kdialogbase.h>
+#include <kio/observer.h>
+#include <kio/renamedlg.h>
+#include <kio/skipdlg.h>
+#include <unistd.h>
+#include <qeventloop.h>
+#include <qpushbutton.h>
+#include <qdatetime.h>
+#include <kprocess.h>
+#include <kdialogbase.h>
+#include <kprogress.h>
+#include <qlayout.h>
+#include <kurlcompletion.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <utime.h>
+#include <pwd.h>
+#include <grp.h>
+#include <qlabel.h>
+
+
+
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+#include <sys/acl.h>
+#ifdef HAVE_NON_POSIX_ACL_EXTENSIONS
+#include <acl/libacl.h>
+#endif
+#endif
+
+
+#define DISPLAY_UPDATE_PERIOD 2
+
+Synchronizer::Synchronizer() : displayUpdateCount( 0 ), markEquals( true ),
+ markDiffers ( true ), markCopyToLeft( true ), markCopyToRight( true ), markDeletable( true ),
+ stack(), jobMap(), receivedMap(), parentWidget( 0 )
+{
+ resultList.setAutoDelete( true );
+ stack.setAutoDelete( true );
+}
+
+void Synchronizer::reset()
+{
+ displayUpdateCount = 0;
+ markEquals = markDiffers = markCopyToLeft = markCopyToRight = markDeletable = true;
+ stopped = false;
+ recurseSubDirs = followSymLinks = ignoreDate = asymmetric = cmpByContent = ignoreCase = autoScroll = false;
+ markEquals = markDiffers = markCopyToLeft = markCopyToRight = markDeletable = markDuplicates = markSingles = false;
+ leftCopyEnabled = rightCopyEnabled = deleteEnabled = overWrite = autoSkip = paused = false;
+ leftCopyNr = rightCopyNr = deleteNr = 0;
+ leftCopySize = rightCopySize = deleteSize = 0;
+ comparedDirs = fileCount = 0;
+ leftBaseDir = rightBaseDir = QString::null;
+ resultList.clear();
+ temporaryList.clear();
+ stack.clear();
+}
+
+int Synchronizer::compare( QString leftURL, QString rightURL, KRQuery *query, bool subDirs,
+ bool symLinks, bool igDate, bool asymm, bool cmpByCnt, bool igCase,
+ bool autoSc, QStringList &selFiles, int equThres, int timeOffs, int parThreads, bool hiddenFiles )
+{
+ resultList.clear();
+ temporaryList.clear();
+
+ recurseSubDirs = subDirs;
+ followSymLinks = symLinks;
+ ignoreDate = igDate;
+ asymmetric = asymm;
+ cmpByContent = cmpByCnt;
+ autoScroll = autoSc;
+ ignoreCase = igCase;
+ selectedFiles = selFiles;
+ equalsThreshold= equThres;
+ timeOffset = timeOffs;
+ parallelThreads= parThreads;
+ ignoreHidden = hiddenFiles;
+
+ stopped = false;
+
+ this->query = query;
+
+ leftURL = KURLCompletion::replacedPath( leftURL, true, true );
+ rightURL = KURLCompletion::replacedPath( rightURL, true, true );
+
+ if( !leftURL.endsWith("/" )) leftURL+="/";
+ if( !rightURL.endsWith("/" )) rightURL+="/";
+
+ excludedPaths = query->dontSearchInDirs().toStringList();
+ for( unsigned i = 0; i != excludedPaths.count(); i++ )
+ if( excludedPaths[ i ].endsWith( "/" ) )
+ excludedPaths[ i ].truncate( excludedPaths[ i ].length() - 1 );
+
+ comparedDirs = fileCount = 0;
+
+ stack.append( new CompareTask( 0, leftBaseDir = leftURL, rightBaseDir = rightURL, "", "", ignoreHidden ) );
+ compareLoop();
+
+ SynchronizerFileItem *item = temporaryList.first();
+ while( item )
+ {
+ if( item->isTemporary() )
+ delete item;
+ item = temporaryList.next();
+ }
+ temporaryList.clear();
+
+
+ if( !autoScroll )
+ refresh( true );
+
+ emit statusInfo( i18n( "Number of files: %1" ).arg( fileCount ) );
+ return fileCount;
+}
+
+void Synchronizer::compareLoop() {
+ while( !stopped && !stack.isEmpty() ) {
+ for( int thread=0; thread < (int)stack.count() && thread < parallelThreads; thread++ ) {
+ SynchronizerTask * entry = stack.at( thread );
+
+ if( entry->state() == ST_STATE_NEW )
+ entry->start( parentWidget );
+
+ if( entry->inherits("CompareTask") ) {
+ if( entry->state() == ST_STATE_READY ) {
+ CompareTask *ctentry = (CompareTask *) entry;
+ if( ctentry->isDuplicate() )
+ compareDirectory( ctentry->parent(), ctentry->leftDirList(), ctentry->rightDirList(),
+ ctentry->leftDir(), ctentry->rightDir() );
+ else
+ addSingleDirectory( ctentry->parent(), ctentry->dirList(), ctentry->dir(),
+ ctentry->isLeft() );
+ }
+ if( entry->state() == ST_STATE_READY || entry->state() == ST_STATE_ERROR )
+ comparedDirs++;
+ }
+ switch( entry->state() ) {
+ case ST_STATE_STATUS:
+ emit statusInfo( entry->status() );
+ break;
+ case ST_STATE_READY:
+ case ST_STATE_ERROR:
+ emit statusInfo( i18n( "Number of compared directories: %1" ).arg( comparedDirs ) );
+ stack.removeRef( entry );
+ continue;
+ default:
+ break;
+ }
+ }
+ if( !stack.isEmpty() )
+ qApp->processEvents();
+ }
+ stack.clear();
+}
+
+void Synchronizer::compareDirectory( SynchronizerFileItem *parent, SynchronizerDirList * left_directory,
+ SynchronizerDirList * right_directory, const QString &leftDir,
+ const QString &rightDir )
+{
+ const QString &leftURL = left_directory->url();
+ const QString &rightURL = right_directory->url();
+ vfile * left_file;
+ vfile * right_file;
+
+ QString file_name;
+ bool checkIfSelected = false;
+
+ if( leftDir.isEmpty() && rightDir.isEmpty() && selectedFiles.count() )
+ checkIfSelected = true;
+
+ /* walking through in the left directory */
+ for( left_file=left_directory->first(); left_file != 0 && !stopped ;
+ left_file=left_directory->next() )
+ {
+ if ( isDir( left_file ) )
+ continue;
+
+ file_name = left_file->vfile_getName();
+
+ if( checkIfSelected && !selectedFiles.contains( file_name ) )
+ continue;
+
+ if( !query->match( left_file ) )
+ continue;
+
+ if( (right_file = right_directory->search( file_name, ignoreCase )) == 0 )
+ addLeftOnlyItem( parent, file_name, leftDir, left_file->vfile_getSize(), left_file->vfile_getTime_t(),
+ readLink( left_file ), left_file->vfile_getOwner(), left_file->vfile_getGroup(),
+ left_file->vfile_getMode(), left_file->vfile_getACL() );
+ else
+ {
+ if( isDir( right_file ) )
+ continue;
+
+ addDuplicateItem( parent, file_name, right_file->vfile_getName(), leftDir, rightDir, left_file->vfile_getSize(), right_file->vfile_getSize(),
+ left_file->vfile_getTime_t(), right_file->vfile_getTime_t(), readLink( left_file ),
+ readLink( right_file ), left_file->vfile_getOwner(), right_file->vfile_getOwner(),
+ left_file->vfile_getGroup(), right_file->vfile_getGroup(),
+ left_file->vfile_getMode(), right_file->vfile_getMode(),
+ left_file->vfile_getACL(), right_file->vfile_getACL() );
+ }
+ }
+
+ /* walking through in the right directory */
+ for( right_file=right_directory->first(); right_file != 0 && !stopped ;
+ right_file=right_directory->next() )
+ {
+ if( isDir( right_file ) )
+ continue;
+
+ file_name = right_file->vfile_getName();
+
+ if( checkIfSelected && !selectedFiles.contains( file_name ) )
+ continue;
+
+ if( !query->match( right_file ) )
+ continue;
+
+ if( left_directory->search( file_name, ignoreCase ) == 0 )
+ addRightOnlyItem( parent, file_name, rightDir, right_file->vfile_getSize(), right_file->vfile_getTime_t(),
+ readLink( right_file ), right_file->vfile_getOwner(), right_file->vfile_getGroup(),
+ right_file->vfile_getMode(), right_file->vfile_getACL() );
+ }
+
+ /* walking through the subdirectories */
+ if( recurseSubDirs )
+ {
+ for( left_file=left_directory->first(); left_file != 0 && !stopped ;
+ left_file=left_directory->next() )
+ {
+ if ( left_file->vfile_isDir() && ( followSymLinks || !left_file->vfile_isSymLink()) )
+ {
+ QString left_file_name = left_file->vfile_getName();
+
+ if( checkIfSelected && !selectedFiles.contains( left_file_name ) )
+ continue;
+
+ if( excludedPaths.contains( leftDir.isEmpty() ? left_file_name : leftDir+"/"+left_file_name ) )
+ continue;
+
+ if( !query->matchDirName( left_file_name ) )
+ continue;
+
+ if( (right_file = right_directory->search( left_file_name, ignoreCase )) == 0 )
+ {
+ SynchronizerFileItem *me = addLeftOnlyItem( parent, left_file_name, leftDir, 0,
+ left_file->vfile_getTime_t(), readLink( left_file ),
+ left_file->vfile_getOwner(), left_file->vfile_getGroup(),
+ left_file->vfile_getMode(), left_file->vfile_getACL(),
+ true, !query->match( left_file ) );
+ stack.append( new CompareTask( me, leftURL+left_file_name+"/",
+ leftDir.isEmpty() ? left_file_name : leftDir+"/"+left_file_name, true, ignoreHidden ) );
+ } else {
+ QString right_file_name = right_file->vfile_getName();
+ SynchronizerFileItem *me = addDuplicateItem( parent, left_file_name, right_file_name,
+ leftDir, rightDir, 0, 0,
+ left_file->vfile_getTime_t(), right_file->vfile_getTime_t(),
+ readLink( left_file ), readLink( right_file ),
+ left_file->vfile_getOwner(), right_file->vfile_getOwner(),
+ left_file->vfile_getGroup(), right_file->vfile_getGroup(),
+ left_file->vfile_getMode(), right_file->vfile_getMode(),
+ left_file->vfile_getACL(), right_file->vfile_getACL(),
+ true, !query->match( left_file ) );
+ stack.append( new CompareTask( me, leftURL+left_file_name+"/", rightURL+right_file_name+"/",
+ leftDir.isEmpty() ? left_file_name : leftDir+"/"+left_file_name,
+ rightDir.isEmpty() ? right_file_name : rightDir+"/"+right_file_name, ignoreHidden ) );
+ }
+ }
+ }
+
+ /* walking through the the right side subdirectories */
+ for( right_file=right_directory->first(); right_file != 0 && !stopped ;
+ right_file=right_directory->next() )
+ {
+ if ( right_file->vfile_isDir() && (followSymLinks || !right_file->vfile_isSymLink()) )
+ {
+ file_name = right_file->vfile_getName();
+
+ if( checkIfSelected && !selectedFiles.contains( file_name ) )
+ continue;
+
+ if( excludedPaths.contains( rightDir.isEmpty() ? file_name : rightDir+"/"+file_name ) )
+ continue;
+
+ if( !query->matchDirName( file_name ) )
+ continue;
+
+ if( left_directory->search( file_name, ignoreCase ) == 0 )
+ {
+ SynchronizerFileItem *me = addRightOnlyItem( parent, file_name, rightDir, 0,
+ right_file->vfile_getTime_t(), readLink( right_file ),
+ right_file->vfile_getOwner(), right_file->vfile_getGroup(),
+ right_file->vfile_getMode(), right_file->vfile_getACL(),
+ true, !query->match( right_file ) );
+ stack.append( new CompareTask( me, rightURL+file_name+"/",
+ rightDir.isEmpty() ? file_name : rightDir+"/"+file_name, false, ignoreHidden ) );
+ }
+ }
+ }
+ }
+}
+
+QString Synchronizer::getTaskTypeName( TaskType taskType )
+{
+ static QString names[] = {"=","!=","<-","->","DEL","?","?","?","?","?"};
+
+ return names[taskType];
+}
+
+SynchronizerFileItem * Synchronizer::addItem( SynchronizerFileItem *parent, const QString &leftFile,
+ const QString &rightFile, const QString &leftDir,
+ const QString &rightDir, bool existsLeft, bool existsRight,
+ KIO::filesize_t leftSize, KIO::filesize_t rightSize,
+ time_t leftDate, time_t rightDate, const QString &leftLink,
+ const QString &rightLink, const QString &leftOwner,
+ const QString &rightOwner, const QString &leftGroup,
+ const QString &rightGroup, mode_t leftMode, mode_t rightMode,
+ const QString &leftACL, const QString &rightACL, TaskType tsk,
+ bool isDir, bool isTemp )
+{
+ bool marked = autoScroll ? !isTemp && isMarked( tsk, existsLeft && existsRight ) : false;
+ SynchronizerFileItem *item = new SynchronizerFileItem( leftFile, rightFile, leftDir, rightDir, marked,
+ existsLeft, existsRight, leftSize, rightSize, leftDate, rightDate, leftLink, rightLink,
+ leftOwner, rightOwner, leftGroup, rightGroup, leftMode, rightMode, leftACL, rightACL, tsk, isDir,
+ isTemp, parent );
+
+ if( !isTemp )
+ {
+ while( parent && parent->isTemporary() )
+ setPermanent( parent );
+
+ bool doRefresh = false;
+
+ if( marked )
+ {
+ fileCount++;
+ if( autoScroll && markParentDirectories( item ) )
+ doRefresh = true;
+ }
+
+ resultList.append( item );
+ emit comparedFileData( item );
+
+ if( doRefresh )
+ refresh( true );
+
+ if( marked && (displayUpdateCount++ % DISPLAY_UPDATE_PERIOD == (DISPLAY_UPDATE_PERIOD-1) ) )
+ qApp->processEvents();
+ }
+ else
+ temporaryList.append( item );
+
+ return item;
+}
+
+void Synchronizer::compareContentResult( SynchronizerFileItem * item, bool res ) {
+ item->compareContentResult( res );
+ bool marked = autoScroll ? isMarked( item->task(), item->existsInLeft() && item->existsInRight() ) : false;
+ item->setMarked( marked );
+ if( marked ) {
+ markParentDirectories( item );
+ fileCount++;
+ emit markChanged( item, true );
+ }
+}
+
+void Synchronizer::setPermanent( SynchronizerFileItem *item )
+{
+ if( item->parent() && item->parent()->isTemporary() )
+ setPermanent( item->parent() );
+
+ item->setPermanent();
+ resultList.append( item );
+ emit comparedFileData( item );
+}
+
+SynchronizerFileItem * Synchronizer::addLeftOnlyItem( SynchronizerFileItem *parent,
+ const QString &file_name, const QString &dir, KIO::filesize_t size,
+ time_t date, const QString &link, const QString &owner,
+ const QString &group, mode_t mode, const QString &acl, bool isDir,
+ bool isTemp )
+{
+ return addItem( parent, file_name, file_name, dir, dir, true, false, size, 0, date, 0, link, QString::null,
+ owner, QString::null, group, QString::null, mode, (mode_t)-1, acl, QString::null,
+ asymmetric ? TT_DELETE : TT_COPY_TO_RIGHT, isDir, isTemp );
+}
+
+SynchronizerFileItem * Synchronizer::addRightOnlyItem( SynchronizerFileItem *parent,
+ const QString &file_name, const QString &dir, KIO::filesize_t size,
+ time_t date, const QString &link, const QString &owner,
+ const QString &group, mode_t mode, const QString &acl, bool isDir,
+ bool isTemp )
+{
+ return addItem( parent, file_name, file_name, dir, dir, false, true, 0, size, 0, date, QString::null, link,
+ QString::null, owner, QString::null, group, (mode_t)-1, mode, QString::null, acl,
+ TT_COPY_TO_LEFT, isDir, isTemp );
+}
+
+SynchronizerFileItem * Synchronizer::addDuplicateItem( SynchronizerFileItem *parent,
+ const QString &leftName, const QString &rightName,
+ const QString &leftDir, const QString &rightDir,
+ KIO::filesize_t leftSize, KIO::filesize_t rightSize, time_t leftDate, time_t rightDate,
+ const QString &leftLink, const QString &rightLink,
+ const QString &leftOwner, const QString &rightOwner,
+ const QString &leftGroup, const QString &rightGroup,
+ mode_t leftMode, mode_t rightMode,
+ const QString &leftACL, const QString &rightACL,
+ bool isDir, bool isTemp )
+{
+ TaskType task;
+
+ int checkedRightDate = rightDate - timeOffset;
+ int uncertain = 0;
+
+ do
+ {
+ if( isDir )
+ {
+ task = TT_EQUALS;
+ break;
+ }
+ if( leftSize == rightSize )
+ {
+ if( !leftLink.isNull() || !rightLink.isNull() ) {
+ if( leftLink == rightLink ) {
+ task = TT_EQUALS;
+ break;
+ }
+ } else if( cmpByContent )
+ uncertain = TT_UNKNOWN;
+ else {
+ if( ignoreDate || leftDate == checkedRightDate ) {
+ task = TT_EQUALS;
+ break;
+ }
+ time_t diff = ( leftDate > checkedRightDate ) ? leftDate - checkedRightDate : checkedRightDate - leftDate;
+ if( diff <= equalsThreshold ) {
+ task = TT_EQUALS;
+ break;
+ }
+ }
+ }
+
+ if( asymmetric )
+ task = TT_COPY_TO_LEFT;
+ else if( ignoreDate )
+ task = TT_DIFFERS;
+ else if( leftDate > checkedRightDate )
+ task = TT_COPY_TO_RIGHT;
+ else if( leftDate < checkedRightDate )
+ task = TT_COPY_TO_LEFT;
+ else
+ task = TT_DIFFERS;
+
+ }while( false );
+
+ SynchronizerFileItem * item = addItem( parent, leftName, rightName, leftDir, rightDir, true, true,
+ leftSize, rightSize, leftDate, rightDate, leftLink, rightLink,
+ leftOwner, rightOwner, leftGroup, rightGroup,
+ leftMode, rightMode, leftACL, rightACL,
+ (TaskType)(task + uncertain), isDir, isTemp );
+
+ if( uncertain == TT_UNKNOWN ) {
+ KURL leftURL = vfs::fromPathOrURL( leftDir.isEmpty() ? leftBaseDir + leftName : leftBaseDir + leftDir + "/" + leftName );
+ KURL rightURL = vfs::fromPathOrURL( rightDir.isEmpty() ? rightBaseDir + rightName : rightBaseDir + rightDir + "/" + rightName );
+ stack.append( new CompareContentTask( this, item, leftURL, rightURL, leftSize ) );
+ }
+
+ return item;
+}
+
+void Synchronizer::addSingleDirectory( SynchronizerFileItem *parent, SynchronizerDirList *directory,
+ const QString &dirName, bool isLeft )
+{
+ const QString &url = directory->url();
+ vfile * file;
+ QString file_name;
+
+ /* walking through the directory files */
+ for( file=directory->first(); file != 0 && !stopped; file = directory->next() )
+ {
+ if ( isDir( file ) )
+ continue;
+
+ file_name = file->vfile_getName();
+
+ if( !query->match( file ) )
+ continue;
+
+ if( isLeft )
+ addLeftOnlyItem( parent, file_name, dirName, file->vfile_getSize(), file->vfile_getTime_t(), readLink( file ),
+ file->vfile_getOwner(), file->vfile_getGroup(), file->vfile_getMode(), file->vfile_getACL() );
+ else
+ addRightOnlyItem( parent, file_name, dirName, file->vfile_getSize(), file->vfile_getTime_t(), readLink( file ),
+ file->vfile_getOwner(), file->vfile_getGroup(), file->vfile_getMode(), file->vfile_getACL() );
+ }
+
+ /* walking through the subdirectories */
+ for( file=directory->first(); file != 0 && !stopped; file=directory->next() )
+ {
+ if ( file->vfile_isDir() && (followSymLinks || !file->vfile_isSymLink()) )
+ {
+ file_name = file->vfile_getName();
+
+ if( excludedPaths.contains( dirName.isEmpty() ? file_name : dirName+"/"+file_name ) )
+ continue;
+
+ if( !query->matchDirName( file_name ) )
+ continue;
+
+ SynchronizerFileItem *me;
+
+ if( isLeft )
+ me = addLeftOnlyItem( parent, file_name, dirName, 0, file->vfile_getTime_t(), readLink( file ),
+ file->vfile_getOwner(), file->vfile_getGroup(), file->vfile_getMode(),
+ file->vfile_getACL(), true, !query->match( file ) );
+ else
+ me = addRightOnlyItem( parent, file_name, dirName, 0, file->vfile_getTime_t(), readLink( file ),
+ file->vfile_getOwner(), file->vfile_getGroup(), file->vfile_getMode(),
+ file->vfile_getACL(), true, !query->match( file ) );
+ stack.append( new CompareTask( me, url+file_name+"/",
+ dirName.isEmpty() ? file_name : dirName+"/"+file_name, isLeft, ignoreHidden ) );
+ }
+ }
+}
+
+void Synchronizer::setMarkFlags( bool left, bool equal, bool differs, bool right, bool dup, bool sing,
+ bool del )
+{
+ markEquals = equal;
+ markDiffers = differs;
+ markCopyToLeft = left;
+ markCopyToRight = right;
+ markDeletable = del;
+ markDuplicates = dup;
+ markSingles = sing;
+}
+
+bool Synchronizer::isMarked( TaskType task, bool isDuplicate )
+{
+ if( (isDuplicate && !markDuplicates) || (!isDuplicate && !markSingles) )
+ return false;
+
+ switch( task )
+ {
+ case TT_EQUALS:
+ return markEquals;
+ case TT_DIFFERS:
+ return markDiffers;
+ case TT_COPY_TO_LEFT:
+ return markCopyToLeft;
+ case TT_COPY_TO_RIGHT:
+ return markCopyToRight;
+ case TT_DELETE:
+ return markDeletable;
+ default:
+ return false;
+ }
+}
+
+bool Synchronizer::markParentDirectories( SynchronizerFileItem *item )
+{
+ if( item->parent() == 0 || item->parent()->isMarked() )
+ return false;
+
+ markParentDirectories( item->parent() );
+
+ item->parent()->setMarked( true );
+
+ fileCount++;
+ emit markChanged( item->parent(), false );
+ return true;
+}
+
+int Synchronizer::refresh(bool nostatus)
+{
+ fileCount = 0;
+
+ SynchronizerFileItem *item = resultList.first();
+
+ while( item )
+ {
+ bool marked = isMarked( item->task(), item->existsInLeft() && item->existsInRight() );
+ item->setMarked( marked );
+
+ if( marked )
+ {
+ markParentDirectories( item );
+ fileCount++;
+ }
+
+ item = resultList.next();
+ }
+
+ item = resultList.first();
+ while( item )
+ {
+ emit markChanged( item, false );
+ item = resultList.next();
+ }
+
+ if( !nostatus )
+ emit statusInfo( i18n( "Number of files: %1" ).arg( fileCount ) );
+
+ return fileCount;
+}
+
+void Synchronizer::operate( SynchronizerFileItem *item,
+ void (*executeOperation)(SynchronizerFileItem *) )
+{
+ executeOperation( item );
+
+ if( item->isDir() )
+ {
+ QString leftDirName = ( item->leftDirectory() == "" ) ?
+ item->leftName() : item->leftDirectory() + "/" + item->leftName() ;
+ QString rightDirName = ( item->rightDirectory() == "" ) ?
+ item->rightName() : item->rightDirectory() + "/" + item->rightName() ;
+
+ item = resultList.first();
+ while( item )
+ {
+ if( item->leftDirectory() == leftDirName || item->leftDirectory().startsWith( leftDirName + "/" ) ||
+ item->rightDirectory() == rightDirName || item->rightDirectory().startsWith( rightDirName + "/" ) )
+ executeOperation( item );
+
+ item = resultList.next();
+ }
+ }
+}
+
+void Synchronizer::excludeOperation( SynchronizerFileItem *item )
+{
+ item->setTask( TT_DIFFERS );
+}
+
+void Synchronizer::exclude( SynchronizerFileItem *item )
+{
+ if( !item->parent() || item->parent()->task() != TT_DELETE )
+ operate( item, excludeOperation ); /* exclude only if the parent task is not DEL */
+}
+
+void Synchronizer::restoreOperation( SynchronizerFileItem *item )
+{
+ item->restoreOriginalTask();
+}
+
+void Synchronizer::restore( SynchronizerFileItem *item )
+{
+ operate( item, restoreOperation );
+
+ while( ( item = item->parent() ) != 0 ) /* in case of restore, the parent directories */
+ { /* must be changed for being consistent */
+ if( item->task() != TT_DIFFERS )
+ break;
+
+ if( item->originalTask() == TT_DELETE ) /* if the parent original task is delete */
+ break; /* don't touch it */
+
+ item->restoreOriginalTask(); /* restore */
+ }
+}
+
+void Synchronizer::reverseDirectionOperation( SynchronizerFileItem *item )
+{
+ if( item->existsInRight() && item->existsInLeft() )
+ {
+ if( item->task() == TT_COPY_TO_LEFT )
+ item->setTask( TT_COPY_TO_RIGHT );
+ else if( item->task() == TT_COPY_TO_RIGHT )
+ item->setTask( TT_COPY_TO_LEFT );
+ }
+}
+
+void Synchronizer::reverseDirection( SynchronizerFileItem *item )
+{
+ operate( item, reverseDirectionOperation );
+}
+
+void Synchronizer::deleteLeftOperation( SynchronizerFileItem *item )
+{
+ if( !item->existsInRight() && item->existsInLeft() )
+ item->setTask( TT_DELETE );
+}
+
+void Synchronizer::deleteLeft( SynchronizerFileItem *item )
+{
+ operate( item, deleteLeftOperation );
+}
+
+void Synchronizer::copyToLeftOperation( SynchronizerFileItem *item )
+{
+ if( item->existsInRight() )
+ {
+ if( !item->isDir() )
+ item->setTask( TT_COPY_TO_LEFT );
+ else
+ {
+ if( item->existsInLeft() && item->existsInRight() )
+ item->setTask( TT_EQUALS );
+ else if( !item->existsInLeft() && item->existsInRight() )
+ item->setTask( TT_COPY_TO_LEFT );
+ }
+ }
+}
+
+void Synchronizer::copyToLeft( SynchronizerFileItem *item )
+{
+ operate( item, copyToLeftOperation );
+
+ while( ( item = item->parent() ) != 0 )
+ {
+ if( item->task() != TT_DIFFERS )
+ break;
+
+ if( item->existsInLeft() && item->existsInRight() )
+ item->setTask( TT_EQUALS );
+ else if( !item->existsInLeft() && item->existsInRight() )
+ item->setTask( TT_COPY_TO_LEFT );
+ }
+}
+
+void Synchronizer::copyToRightOperation( SynchronizerFileItem *item )
+{
+ if( item->existsInLeft() )
+ {
+ if( !item->isDir() )
+ item->setTask( TT_COPY_TO_RIGHT );
+ else
+ {
+ if( item->existsInLeft() && item->existsInRight() )
+ item->setTask( TT_EQUALS );
+ else if( item->existsInLeft() && !item->existsInRight() )
+ item->setTask( TT_COPY_TO_RIGHT );
+ }
+ }
+}
+
+void Synchronizer::copyToRight( SynchronizerFileItem *item )
+{
+ operate( item, copyToRightOperation );
+
+ while( ( item = item->parent() ) != 0 )
+ {
+ if( item->task() != TT_DIFFERS && item->task() != TT_DELETE )
+ break;
+
+ if( item->existsInLeft() && item->existsInRight() )
+ item->setTask( TT_EQUALS );
+ else if( item->existsInLeft() && !item->existsInRight() )
+ item->setTask( TT_COPY_TO_RIGHT );
+ }
+}
+
+bool Synchronizer::totalSizes( int * leftCopyNr, KIO::filesize_t *leftCopySize, int * rightCopyNr,
+ KIO::filesize_t *rightCopySize, int *deleteNr, KIO::filesize_t *deletableSize )
+{
+ bool hasAnythingToDo = false;
+
+ *leftCopySize = *rightCopySize = *deletableSize = 0;
+ *leftCopyNr = *rightCopyNr = *deleteNr = 0;
+
+ SynchronizerFileItem *item = resultList.first();
+
+ while( item )
+ {
+ if( item->isMarked() )
+ {
+ switch( item->task() )
+ {
+ case TT_COPY_TO_LEFT:
+ *leftCopySize += item->rightSize();
+ (*leftCopyNr)++;
+ hasAnythingToDo = true;
+ break;
+ case TT_COPY_TO_RIGHT:
+ *rightCopySize += item->leftSize();
+ (*rightCopyNr)++;
+ hasAnythingToDo = true;
+ break;
+ case TT_DELETE:
+ *deletableSize += item->leftSize();
+ (*deleteNr)++;
+ hasAnythingToDo = true;
+ break;
+ default:
+ break;
+ }
+ }
+ item = resultList.next();
+ }
+
+ return hasAnythingToDo;
+}
+
+void Synchronizer::swapSides()
+{
+ QString leftTmp = leftBaseDir;
+ leftBaseDir = rightBaseDir;
+ rightBaseDir = leftTmp;
+
+ SynchronizerFileItem *item = resultList.first();
+
+ while( item )
+ {
+ item->swap( asymmetric );
+ item = resultList.next();
+ }
+}
+
+void Synchronizer::setScrolling( bool scroll )
+{
+ if( autoScroll = scroll )
+ {
+ int oldFileCount = fileCount;
+ refresh( true );
+ fileCount = oldFileCount;
+ }
+}
+
+void Synchronizer::synchronize( QWidget *syncWdg, bool leftCopyEnabled, bool rightCopyEnabled,
+ bool deleteEnabled, bool overWrite, int parThreads )
+{
+ this->leftCopyEnabled = leftCopyEnabled;
+ this->rightCopyEnabled = rightCopyEnabled;
+ this->deleteEnabled = deleteEnabled;
+ this->overWrite = overWrite;
+ this->parallelThreads = parThreads;
+ this->syncDlgWidget = syncWdg;
+
+ autoSkip = paused = disableNewTasks = false;
+
+ leftCopyNr = rightCopyNr = deleteNr = 0;
+ leftCopySize = rightCopySize = deleteSize = 0;
+
+ inTaskFinished = 0;
+ lastTask = 0;
+
+ jobMap.clear();
+ receivedMap.clear();
+
+ resultList.first();
+ synchronizeLoop();
+}
+
+void Synchronizer::synchronizeLoop() {
+ if( disableNewTasks ) {
+ if( resultList.current() == 0 && jobMap.count() == 0 )
+ emit synchronizationFinished();
+ return;
+ }
+
+ while( (int)jobMap.count() < parallelThreads ) {
+ SynchronizerFileItem *task = getNextTask();
+ if( task == 0 ) {
+ if( jobMap.count() == 0 )
+ emit synchronizationFinished();
+ return;
+ }
+ executeTask( task );
+ if( disableNewTasks )
+ break;
+ }
+}
+
+SynchronizerFileItem * Synchronizer::getNextTask() {
+ TaskType task;
+ SynchronizerFileItem * currentTask = resultList.current();
+
+ do {
+ if( currentTask == 0 )
+ return 0;
+
+ if( currentTask->isMarked() )
+ {
+ task = currentTask->task();
+
+ if( leftCopyEnabled && task == TT_COPY_TO_LEFT )
+ break;
+ else if( rightCopyEnabled && task == TT_COPY_TO_RIGHT )
+ break;
+ else if( deleteEnabled && task == TT_DELETE )
+ break;
+ }
+
+ currentTask = resultList.next();
+ }while( true );
+
+ resultList.next();
+ return lastTask = currentTask;
+}
+
+
+void Synchronizer::executeTask( SynchronizerFileItem * task )
+{
+ QString leftDirName = task->leftDirectory();
+ if( !leftDirName.isEmpty() )
+ leftDirName += "/";
+ QString rightDirName = task->rightDirectory();
+ if( !rightDirName.isEmpty() )
+ rightDirName += "/";
+
+ KURL leftURL = vfs::fromPathOrURL( leftBaseDir + leftDirName + task->leftName() );
+ KURL rightURL = vfs::fromPathOrURL( rightBaseDir + rightDirName + task->rightName() );
+
+ switch( task->task() )
+ {
+ case TT_COPY_TO_LEFT:
+ if( task->isDir() )
+ {
+ KIO::SimpleJob *job = KIO::mkdir( leftURL );
+ connect(job,SIGNAL(result(KIO::Job*)),this,SLOT(slotTaskFinished(KIO::Job*)));
+ jobMap[ job ] = task;
+ disableNewTasks = true;
+ }
+ else
+ {
+ KURL destURL( leftURL );
+ if( !task->destination().isNull() )
+ destURL = vfs::fromPathOrURL( task->destination() );
+
+ if( task->rightLink().isNull() ) {
+ KIO::FileCopyJob *job = KIO::file_copy(rightURL, destURL, -1,
+ overWrite || task->overWrite(), false, false );
+ connect(job,SIGNAL(processedSize (KIO::Job *, KIO::filesize_t )), this,
+ SLOT (slotProcessedSize (KIO::Job *, KIO::filesize_t )));
+ connect(job,SIGNAL(result(KIO::Job*)),this,SLOT(slotTaskFinished(KIO::Job*)));
+ jobMap[ job ] = task;
+ } else {
+ KIO::SimpleJob *job = KIO::symlink( task->rightLink(), destURL,
+ overWrite || task->overWrite(), false );
+ connect(job,SIGNAL(result(KIO::Job*)),this,SLOT(slotTaskFinished(KIO::Job*)));
+ jobMap[ job ] = task;
+ }
+ }
+ break;
+ case TT_COPY_TO_RIGHT:
+ if( task->isDir() )
+ {
+ KIO::SimpleJob *job = KIO::mkdir( rightURL );
+ connect(job,SIGNAL(result(KIO::Job*)),this,SLOT(slotTaskFinished(KIO::Job*)));
+ jobMap[ job ] = task;
+ disableNewTasks = true;
+ }
+ else
+ {
+ KURL destURL( rightURL );
+ if( !task->destination().isNull() )
+ destURL = vfs::fromPathOrURL( task->destination() );
+
+ if( task->leftLink().isNull() ) {
+ KIO::FileCopyJob *job = KIO::file_copy(leftURL, destURL, -1,
+ overWrite || task->overWrite(), false, false );
+ connect(job,SIGNAL(processedSize (KIO::Job *, KIO::filesize_t )), this,
+ SLOT (slotProcessedSize (KIO::Job *, KIO::filesize_t )));
+ connect(job,SIGNAL(result(KIO::Job*)),this,SLOT(slotTaskFinished(KIO::Job*)));
+ jobMap[ job ] = task;
+ } else {
+ KIO::SimpleJob *job = KIO::symlink( task->leftLink(), destURL,
+ overWrite || task->overWrite(), false );
+ connect(job,SIGNAL(result(KIO::Job*)),this,SLOT(slotTaskFinished(KIO::Job*)));
+ jobMap[ job ] = task;
+ }
+ }
+ break;
+ case TT_DELETE:
+ {
+ KIO::DeleteJob *job = KIO::del( leftURL, false );
+ connect(job,SIGNAL(result(KIO::Job*)),this,SLOT(slotTaskFinished(KIO::Job*)));
+ jobMap[ job ] = task;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void Synchronizer::slotTaskFinished(KIO::Job *job )
+{
+ inTaskFinished++;
+
+ SynchronizerFileItem * item = jobMap[ job ];
+ jobMap.remove( job );
+
+ KIO::filesize_t receivedSize = 0;
+
+ if( receivedMap.contains( job ) ) {
+ receivedSize = receivedMap[ job ];
+ receivedMap.remove( job );
+ }
+
+ if( disableNewTasks && item == lastTask )
+ disableNewTasks = false; // the blocker task finished
+
+ QString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + "/";
+ QString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + "/";
+ KURL leftURL = vfs::fromPathOrURL( leftBaseDir + leftDirName + item->leftName() );
+ KURL rightURL = vfs::fromPathOrURL( rightBaseDir + rightDirName + item->rightName() );
+
+ do {
+ if( !job->error() )
+ {
+ switch( item->task() )
+ {
+ case TT_COPY_TO_LEFT:
+ if( leftURL.isLocalFile() )
+ {
+ struct utimbuf timestamp;
+
+ timestamp.actime = time( 0 );
+ timestamp.modtime = item->rightDate() - timeOffset;
+
+ utime( (const char *)( leftURL.path( -1 ).local8Bit() ), &timestamp );
+
+ uid_t newOwnerID = (uid_t)-1; // chown(2) : -1 means no change
+ if ( !item->rightOwner().isEmpty() )
+ {
+ struct passwd* pw = getpwnam(QFile::encodeName(item->rightOwner()));
+ if ( pw != 0L )
+ newOwnerID = pw->pw_uid;
+ }
+ gid_t newGroupID = (gid_t)-1; // chown(2) : -1 means no change
+ if ( !item->rightGroup().isEmpty() )
+ {
+ struct group* g = getgrnam(QFile::encodeName(item->rightGroup()));
+ if ( g != 0L )
+ newGroupID = g->gr_gid;
+ }
+ chown( (const char *)( leftURL.path( -1 ).local8Bit() ), newOwnerID, (gid_t)-1 );
+ chown( (const char *)( leftURL.path( -1 ).local8Bit() ), (uid_t)-1, newGroupID );
+
+ chmod( (const char *)( leftURL.path( -1 ).local8Bit() ), item->rightMode() & 07777 );
+
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+ if( !item->rightACL().isNull() )
+ {
+ acl_t acl = acl_from_text( item->rightACL().latin1() );
+ if( acl && !acl_valid( acl ) )
+ acl_set_file( leftURL.path( -1 ).local8Bit(), ACL_TYPE_ACCESS, acl );
+ if( acl )
+ acl_free( acl );
+ }
+#endif
+ }
+ break;
+ case TT_COPY_TO_RIGHT:
+ if( rightURL.isLocalFile() )
+ {
+ struct utimbuf timestamp;
+
+ timestamp.actime = time( 0 );
+ timestamp.modtime = item->leftDate() + timeOffset;
+
+ utime( (const char *)( rightURL.path( -1 ).local8Bit() ), &timestamp );
+
+ uid_t newOwnerID = (uid_t)-1; // chown(2) : -1 means no change
+ if ( !item->leftOwner().isEmpty() )
+ {
+ struct passwd* pw = getpwnam(QFile::encodeName(item->leftOwner()));
+ if ( pw != 0L )
+ newOwnerID = pw->pw_uid;
+ }
+ gid_t newGroupID = (gid_t)-1; // chown(2) : -1 means no change
+ if ( !item->leftGroup().isEmpty() )
+ {
+ struct group* g = getgrnam(QFile::encodeName(item->leftGroup()));
+ if ( g != 0L )
+ newGroupID = g->gr_gid;
+ }
+ chown( (const char *)( rightURL.path( -1 ).local8Bit() ), newOwnerID, (uid_t)-1 );
+ chown( (const char *)( rightURL.path( -1 ).local8Bit() ), (uid_t)-1, newGroupID );
+
+ chmod( (const char *)( rightURL.path( -1 ).local8Bit() ), item->leftMode() & 07777 );
+
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+ if( !item->leftACL().isNull() )
+ {
+ acl_t acl = acl_from_text( item->leftACL().latin1() );
+ if( acl && !acl_valid( acl ) )
+ acl_set_file( rightURL.path( -1 ).local8Bit(), ACL_TYPE_ACCESS, acl );
+ if( acl )
+ acl_free( acl );
+ }
+#endif
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ if( job->error() == KIO::ERR_FILE_ALREADY_EXIST && item->task() != TT_DELETE )
+ {
+ KIO::RenameDlg_Result result;
+ QString newDest;
+
+ if( autoSkip )
+ break;
+
+ if ( item->task() == TT_COPY_TO_LEFT )
+ {
+ QWidget *mainWidget = qApp->mainWidget(); // WORKAROUND, don't give focus to the main widget
+ qApp->setMainWidget( syncDlgWidget );
+
+ result = Observer::self()->open_RenameDlg ( job, i18n("File Already Exists"),
+ vfs::pathOrURL( rightURL ), vfs::pathOrURL( leftURL ),
+ (KIO::RenameDlg_Mode)( KIO::M_OVERWRITE | KIO::M_SKIP | KIO::M_MULTI ), newDest,
+ item->rightSize(), item->leftSize(), (time_t)-1, (time_t)-1,
+ item->rightDate(), item->leftDate());
+
+ qApp->setMainWidget( mainWidget );
+ }
+ else
+ {
+ QWidget *mainWidget = qApp->mainWidget(); // WORKAROUND, don't give focus to the main widget
+ qApp->setMainWidget( syncDlgWidget );
+
+ result = Observer::self()->open_RenameDlg ( job, i18n("File Already Exists"),
+ vfs::pathOrURL( leftURL ), vfs::pathOrURL( rightURL ),
+ (KIO::RenameDlg_Mode)( KIO::M_OVERWRITE | KIO::M_SKIP | KIO::M_MULTI ), newDest,
+ item->leftSize(), item->rightSize(), (time_t)-1, (time_t)-1,
+ item->leftDate(), item->rightDate());
+
+ qApp->setMainWidget( mainWidget );
+ }
+
+ switch ( result )
+ {
+ case KIO::R_RENAME:
+ item->setDestination( newDest );
+ executeTask( item );
+ inTaskFinished--;
+ return;
+ case KIO::R_OVERWRITE:
+ item->setOverWrite();
+ executeTask( item );
+ inTaskFinished--;
+ return;
+ case KIO::R_OVERWRITE_ALL:
+ overWrite = true;
+ executeTask( item );
+ inTaskFinished--;
+ return;
+ case KIO::R_AUTO_SKIP:
+ autoSkip = true;
+ case KIO::R_SKIP:
+ default:
+ break;
+ }
+ break;
+ }
+
+ if( job->error() != KIO::ERR_DOES_NOT_EXIST || item->task() != TT_DELETE )
+ {
+ if( autoSkip )
+ break;
+
+ QString error;
+
+ switch( item->task() )
+ {
+ case TT_COPY_TO_LEFT:
+ error = i18n("Error at copying file %1 to %2!")
+ .arg( vfs::pathOrURL( rightURL ) )
+ .arg( vfs::pathOrURL( leftURL ) );
+ break;
+ case TT_COPY_TO_RIGHT:
+ error = i18n("Error at copying file %1 to %2!")
+ .arg( vfs::pathOrURL( leftURL ) )
+ .arg( vfs::pathOrURL( rightURL ) );
+ break;
+ case TT_DELETE:
+ error = i18n("Error at deleting file %1!").arg( vfs::pathOrURL( leftURL ) );
+ break;
+ default:
+ break;
+ }
+
+ QWidget *mainWidget = qApp->mainWidget(); // WORKAROUND, don't give focus to the main widget
+ qApp->setMainWidget( syncDlgWidget );
+
+ KIO::SkipDlg_Result result = Observer::self()->open_SkipDlg( job, true, error );
+
+ qApp->setMainWidget( mainWidget );
+
+ switch( result )
+ {
+ case KIO::S_CANCEL:
+ executeTask( item ); /* simply retry */
+ inTaskFinished--;
+ return;
+ case KIO::S_AUTO_SKIP:
+ autoSkip = true;
+ default:
+ break;
+ }
+ }
+ }
+ }while( false );
+
+ switch( item->task() )
+ {
+ case TT_COPY_TO_LEFT:
+ leftCopyNr++;
+ leftCopySize += item->rightSize() - receivedSize;
+ break;
+ case TT_COPY_TO_RIGHT:
+ rightCopyNr++;
+ rightCopySize += item->leftSize() - receivedSize;
+ break;
+ case TT_DELETE:
+ deleteNr++;
+ deleteSize += item->leftSize() - receivedSize;
+ break;
+ default:
+ break;
+ }
+
+ emit processedSizes( leftCopyNr, leftCopySize, rightCopyNr, rightCopySize, deleteNr, deleteSize );
+
+ if( --inTaskFinished == 0 ) {
+ if( paused )
+ emit pauseAccepted();
+ else
+ synchronizeLoop();
+ }
+}
+
+void Synchronizer::slotProcessedSize( KIO::Job * job , KIO::filesize_t size)
+{
+ KIO::filesize_t dl = 0, dr = 0, dd = 0;
+ SynchronizerFileItem * item = jobMap[ job ];
+
+ KIO::filesize_t lastProcessedSize = 0;
+ if( receivedMap.contains( job ) )
+ lastProcessedSize = receivedMap[ job ];
+
+ receivedMap[ job ] = size;
+
+ switch( item->task() )
+ {
+ case TT_COPY_TO_LEFT:
+ dl = size - lastProcessedSize;
+ break;
+ case TT_COPY_TO_RIGHT:
+ dr = size - lastProcessedSize;
+ break;
+ case TT_DELETE:
+ dd = size - lastProcessedSize;
+ break;
+ default:
+ break;
+ }
+
+ emit processedSizes( leftCopyNr, leftCopySize+=dl, rightCopyNr, rightCopySize+=dr, deleteNr, deleteSize+=dd );
+}
+
+void Synchronizer::pause()
+{
+ paused = true;
+}
+
+void Synchronizer::resume()
+{
+ paused = false;
+ synchronizeLoop();
+}
+
+QString Synchronizer::leftBaseDirectory()
+{
+ return leftBaseDir;
+}
+
+QString Synchronizer::rightBaseDirectory()
+{
+ return rightBaseDir;
+}
+
+class KgetProgressDialog : public KDialogBase
+{
+public:
+ KgetProgressDialog( QWidget *parent=0, const char *name=0, const QString &caption=QString::null,
+ const QString &text=QString::null, bool modal=false) : KDialogBase( KDialogBase::Plain,
+ caption, KDialogBase::User1 | KDialogBase::Cancel, KDialogBase::Cancel, parent, name, modal )
+ {
+ showButton(KDialogBase::Close, false);
+
+ QFrame* mainWidget = plainPage();
+ QVBoxLayout* layout = new QVBoxLayout(mainWidget, 10);
+
+ QLabel *mLabel = new QLabel(text, mainWidget);
+ layout->addWidget(mLabel);
+
+ mProgressBar = new KProgress(mainWidget);
+ layout->addWidget(mProgressBar);
+
+ setButtonText( KDialogBase::User1, i18n( "Pause" ) );
+
+ mCancelled = mPaused = false;
+ }
+
+ KProgress *progressBar() { return mProgressBar; }
+
+ void slotUser1()
+ {
+ if( ( mPaused = !mPaused ) == false )
+ setButtonText( KDialogBase::User1, i18n( "Pause" ) );
+ else
+ setButtonText( KDialogBase::User1, i18n( "Resume" ) );
+ }
+
+ void slotCancel()
+ {
+ mCancelled = true;
+
+ KDialogBase::slotCancel();
+ }
+
+ bool wasCancelled() { return mCancelled; }
+ bool isPaused() { return mPaused; }
+
+private:
+ KProgress *mProgressBar;
+ bool mCancelled;
+ bool mPaused;
+};
+
+
+void Synchronizer::synchronizeWithKGet()
+{
+ bool isLeftLocal = vfs::fromPathOrURL( leftBaseDirectory() ).isLocalFile();
+ KgetProgressDialog *progDlg = 0;
+ int processedCount = 0, totalCount = 0;
+
+ SynchronizerFileItem *item = resultList.first();
+ for(; item; item = resultList.next() )
+ if( item->isMarked() )
+ totalCount++;
+
+ item = resultList.first();
+ while( item )
+ {
+ if( item->isMarked() )
+ {
+ KURL downloadURL, destURL;
+ QString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + "/";
+ QString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + "/";
+ QString destDir;
+
+ if( progDlg == 0 )
+ {
+ progDlg = new KgetProgressDialog( krApp, "Synchronizer Progress Dlg", i18n("Krusader::Synchronizer"),
+ i18n( "Feeding the URLs to Kget" ), true );
+ progDlg->progressBar()->setTotalSteps( totalCount );
+ progDlg->show();
+ qApp->processEvents();
+ }
+
+ if( item->task() == TT_COPY_TO_RIGHT && !isLeftLocal )
+ {
+ downloadURL = vfs::fromPathOrURL( leftBaseDirectory() + leftDirName + item->leftName() );
+ destDir = rightBaseDirectory() + rightDirName;
+ destURL = vfs::fromPathOrURL( destDir + item->rightName() );
+
+ if( item->isDir() )
+ destDir += item->leftName();
+ }
+ if( item->task() == TT_COPY_TO_LEFT && isLeftLocal )
+ {
+ downloadURL = vfs::fromPathOrURL( rightBaseDirectory() + rightDirName + item->rightName() );
+ destDir = leftBaseDirectory() + leftDirName;
+ destURL = vfs::fromPathOrURL( destDir + item->leftName() );
+
+ if( item->isDir() )
+ destDir += item->rightName();
+ }
+
+ // creating the directory system
+ for( int i=0; i >= 0 ; i= destDir.find('/',i+1) )
+ if( !QDir( destDir.left(i) ).exists() )
+ QDir().mkdir( destDir.left(i) );
+
+ if( !item->isDir() && !downloadURL.isEmpty() )
+ {
+ if( QFile( destURL.path() ).exists() )
+ QFile( destURL.path() ).remove();
+
+ QString source = downloadURL.prettyURL();
+ if( source.contains( '@' ) >= 2 ) /* is this an ftp proxy URL? */
+ {
+ int lastAt = source.findRev( '@' );
+ QString startString = source.left( lastAt );
+ QString endString = source.mid( lastAt );
+ startString.replace( "@", "%40" );
+ source = startString+endString;
+ }
+
+ KProcess p;
+
+ p << KrServices::fullPathName( "kget" ) << source << destURL.path();
+ if (!p.start(KProcess::Block))
+ KMessageBox::error(parentWidget,i18n("Error executing ")+KrServices::fullPathName( "kget" )+" !");
+ else
+ p.detach();
+ }
+
+ progDlg->progressBar()->setProgress( ++processedCount );
+
+ do
+ {
+ qApp->processEvents();
+
+ if( progDlg->wasCancelled() )
+ break;
+
+ if( progDlg->isPaused() )
+ usleep( 100000 );
+
+ }while( progDlg->isPaused() );
+
+ if( progDlg->wasCancelled() )
+ break;
+ }
+ item = resultList.next();
+ }
+
+ if( progDlg )
+ delete progDlg;
+}
+
+bool Synchronizer::isDir( const vfile * file ) {
+ if( followSymLinks ) {
+ return file->vfile_isDir();
+ }
+ else {
+ return file->vfile_isDir() && !file->vfile_isSymLink();
+ }
+}
+
+QString Synchronizer::readLink( const vfile * file ) {
+ if( file->vfile_isSymLink() )
+ return file->vfile_getSymDest();
+ else
+ return QString::null;
+}
+
+#include "synchronizer.moc"
diff --git a/krusader/Synchronizer/synchronizer.h b/krusader/Synchronizer/synchronizer.h
new file mode 100755
index 0000000..ac4e338
--- /dev/null
+++ b/krusader/Synchronizer/synchronizer.h
@@ -0,0 +1,204 @@
+/***************************************************************************
+ synchronizer.h - description
+ -------------------
+ copyright : (C) 2003 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __SYNCHRONIZER_H__
+#define __SYNCHRONIZER_H__
+
+#include "synchronizertask.h"
+#include "synchronizerfileitem.h"
+#include <qobject.h>
+#include <qptrvector.h>
+#include <qmap.h>
+#include <qcolor.h>
+#include <kio/job.h>
+
+class KRQuery;
+class vfile;
+
+#define DECLARE_COLOR_NAME_ARRAY QString COLOR_NAMES[] = { "Equals", "Differs", "LeftCopy", "RightCopy", "Delete", \
+ "Equals", "Equals", "Equals", "Equals", "Equals" }
+#define DECLARE_BACKGROUND_DFLTS QColor BCKG_DFLTS[] = { QColor(), QColor(), QColor(), QColor(), Qt::red, \
+ QColor(), QColor(), QColor(), QColor(), QColor() }
+#define DECLARE_FOREGROUND_DFLTS QColor FORE_DFLTS[] = { Qt::black, Qt::red, Qt::blue, Qt::darkGreen, Qt::white, \
+ Qt::black, Qt::black, Qt::black, Qt::black, Qt::black }
+
+class Synchronizer : public QObject
+{
+ Q_OBJECT
+
+ private:
+ int displayUpdateCount; // the display is refreshed after every x-th change
+
+ public:
+ Synchronizer();
+ int compare( QString leftURL, QString rightURL, KRQuery *query, bool subDirs, bool symLinks,
+ bool igDate, bool asymm, bool cmpByCnt, bool igCase, bool autoSc, QStringList &selFiles,
+ int equThres, int timeOffs, int parThreads, bool hiddenFiles );
+ void stop() {stopped = true;}
+ void setMarkFlags( bool left, bool equal, bool differs, bool right, bool dup, bool sing, bool del );
+ int refresh( bool nostatus=false );
+ bool totalSizes( int *, KIO::filesize_t *, int *, KIO::filesize_t *, int *, KIO::filesize_t * );
+ void synchronize( QWidget *,bool leftCopyEnabled, bool rightCopyEnabled, bool deleteEnabled,
+ bool overWrite, int parThreads );
+ void synchronizeWithKGet();
+ void setScrolling( bool scroll );
+ void pause();
+ void resume();
+ void swapSides();
+ void reset();
+
+ void exclude( SynchronizerFileItem * );
+ void restore( SynchronizerFileItem * );
+ void reverseDirection( SynchronizerFileItem * );
+ void copyToLeft( SynchronizerFileItem * );
+ void copyToRight( SynchronizerFileItem * );
+ void deleteLeft( SynchronizerFileItem * );
+
+ QString leftBaseDirectory();
+ QString rightBaseDirectory();
+ static QString getTaskTypeName( TaskType taskType );
+
+ SynchronizerFileItem *getItemAt( unsigned ndx ) {return resultList.at(ndx);}
+
+ void setParentWidget( QWidget * widget ) {parentWidget = widget;}
+ void compareContentResult( SynchronizerFileItem * item, bool result );
+
+ signals:
+ void comparedFileData( SynchronizerFileItem * );
+ void markChanged( SynchronizerFileItem *, bool );
+ void synchronizationFinished();
+ void processedSizes( int, KIO::filesize_t, int, KIO::filesize_t, int, KIO::filesize_t );
+ void pauseAccepted();
+ void statusInfo( QString );
+
+ public slots:
+ void slotTaskFinished(KIO::Job*);
+ void slotProcessedSize( KIO::Job * , KIO::filesize_t );
+
+ private:
+ bool isDir( const vfile * file );
+ QString readLink( const vfile * file );
+
+ void compareDirectory( SynchronizerFileItem *,SynchronizerDirList *, SynchronizerDirList *,
+ const QString &leftDir, const QString &rightDir );
+ void addSingleDirectory( SynchronizerFileItem *, SynchronizerDirList *, const QString &, bool );
+ SynchronizerFileItem * addItem( SynchronizerFileItem *, const QString &, const QString &,
+ const QString &, const QString &, bool, bool, KIO::filesize_t,
+ KIO::filesize_t, time_t, time_t, const QString &, const QString &,
+ const QString &, const QString &, const QString &, const QString &,
+ mode_t, mode_t, const QString &, const QString &, TaskType, bool, bool);
+ SynchronizerFileItem * addLeftOnlyItem( SynchronizerFileItem *, const QString &, const QString &,
+ KIO::filesize_t, time_t, const QString &, const QString &,
+ const QString &, mode_t, const QString &, bool isDir = false, bool isTemp = false );
+ SynchronizerFileItem * addRightOnlyItem( SynchronizerFileItem *, const QString &, const QString &,
+ KIO::filesize_t, time_t, const QString &, const QString &,
+ const QString &, mode_t, const QString &, bool isDir = false, bool isTemp = false );
+ SynchronizerFileItem * addDuplicateItem( SynchronizerFileItem *, const QString &, const QString &,
+ const QString &, const QString &, KIO::filesize_t,
+ KIO::filesize_t, time_t, time_t, const QString &,
+ const QString &, const QString &, const QString &,
+ const QString &, const QString &, mode_t, mode_t, const QString &,
+ const QString &, bool isDir = false, bool isTemp = false );
+ bool isMarked( TaskType task, bool dupl );
+ bool markParentDirectories( SynchronizerFileItem * );
+ void synchronizeLoop();
+ SynchronizerFileItem * getNextTask();
+ void executeTask( SynchronizerFileItem * task );
+ void setPermanent( SynchronizerFileItem * );
+ void operate( SynchronizerFileItem *item, void (*)(SynchronizerFileItem *) );
+ void compareLoop();
+
+ static void excludeOperation( SynchronizerFileItem *item );
+ static void restoreOperation( SynchronizerFileItem *item );
+ static void reverseDirectionOperation( SynchronizerFileItem *item );
+ static void copyToLeftOperation( SynchronizerFileItem *item );
+ static void copyToRightOperation( SynchronizerFileItem *item );
+ static void deleteLeftOperation( SynchronizerFileItem *item );
+
+ protected:
+ bool recurseSubDirs; // walk through subdirectories also
+ bool followSymLinks; // follow the symbolic links
+ bool ignoreDate; // don't use date info at comparing
+ bool asymmetric; // asymmetric directory update
+ bool cmpByContent; // compare the files by content
+ bool ignoreCase; // case insensitive synchronization for Windows fs
+ bool autoScroll; // automatic update of the directory
+ QPtrList<SynchronizerFileItem> resultList; // the found files
+ QPtrList<SynchronizerFileItem> temporaryList; // temporary files
+ QString leftBaseDir; // the left-side base directory
+ QString rightBaseDir; // the right-side base directory
+ QStringList excludedPaths; // list of the excluded paths
+ KRQuery *query; // the filter used for the query
+ bool stopped; // 'Stop' button was pressed
+
+ int equalsThreshold;// threshold to treat files equal
+ int timeOffset; // time offset between the left and right sides
+ bool ignoreHidden; // ignores the hidden files
+
+ bool markEquals; // show the equal files
+ bool markDiffers; // show the different files
+ bool markCopyToLeft; // show the files to copy from right to left
+ bool markCopyToRight;// show the files to copy from left to right
+ bool markDeletable; // show the files to be deleted
+ bool markDuplicates; // show the duplicated items
+ bool markSingles; // show the single items
+
+ bool leftCopyEnabled;// copy to left is enabled at synchronize
+ bool rightCopyEnabled;// copy to right is enabled at synchronize
+ bool deleteEnabled; // delete is enabled at synchronize
+ bool overWrite; // overwrite or query each modification
+ bool autoSkip; // automatic skipping
+ bool paused; // pause flag
+ bool disableNewTasks;// at mkdir the further task creation is disabled
+
+ int leftCopyNr; // the file number copied to left
+ int rightCopyNr; // the file number copied to right
+ int deleteNr; // the number of the deleted files
+ int parallelThreads;// the number of the parallel procesing threads
+ KIO::filesize_t leftCopySize; // the total size copied to left
+ KIO::filesize_t rightCopySize; // the total size copied to right
+ KIO::filesize_t deleteSize; // the size of the deleted files
+
+ int comparedDirs; // the number of the compared directories
+ int fileCount; // the number of counted files
+
+ private:
+ QPtrList<SynchronizerTask> stack; // stack for comparing
+ QMap<KIO::Job *,SynchronizerFileItem *> jobMap; // job maps
+ QMap<KIO::Job *,KIO::filesize_t> receivedMap; // the received file size
+ SynchronizerFileItem *lastTask; // reference to the last stack
+ int inTaskFinished; // counter of quasy 'threads' in slotTaskFinished
+
+ QStringList selectedFiles; // the selected files to compare
+ QWidget *parentWidget; // the parent widget
+ QWidget *syncDlgWidget; // the synchronizer dialog widget
+};
+
+#endif /* __SYNCHRONIZER_H__ */
diff --git a/krusader/Synchronizer/synchronizerdirlist.cpp b/krusader/Synchronizer/synchronizerdirlist.cpp
new file mode 100644
index 0000000..67decd6
--- /dev/null
+++ b/krusader/Synchronizer/synchronizerdirlist.cpp
@@ -0,0 +1,216 @@
+/***************************************************************************
+ synchronizerdirlist.cpp - description
+ -------------------
+ copyright : (C) 2006 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "synchronizerdirlist.h"
+#include "../VFS/vfs.h"
+#include "../VFS/krpermhandler.h"
+#include <dirent.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kfileitem.h>
+#include <klargefile.h>
+#include <qapplication.h>
+#include <qdir.h>
+#include <kdeversion.h>
+
+
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+#include <sys/acl.h>
+#ifdef HAVE_NON_POSIX_ACL_EXTENSIONS
+#include <acl/libacl.h>
+#endif
+#endif
+
+SynchronizerDirList::SynchronizerDirList( QWidget *w, bool hidden ) : QObject(), QDict<vfile>(), fileIterator( 0 ),
+ parentWidget( w ), busy( false ), result( false ), ignoreHidden( hidden ), currentUrl() {
+ setAutoDelete( true );
+}
+
+SynchronizerDirList::~SynchronizerDirList() {
+ if( fileIterator )
+ delete fileIterator;
+}
+
+vfile * SynchronizerDirList::search( const QString &name, bool ignoreCase ) {
+ if( !ignoreCase )
+ return (*this)[ name ];
+
+ vfile *item = first();
+ QString file = name.lower();
+
+ while( item )
+ {
+ if( file == item->vfile_getName().lower() )
+ return item;
+ item = next();
+ }
+ return 0;
+}
+
+vfile * SynchronizerDirList::first() {
+ return fileIterator->toFirst();
+}
+
+vfile * SynchronizerDirList::next() {
+ return ++(*fileIterator);
+}
+
+bool SynchronizerDirList::load( const QString &urlIn, bool wait ) {
+ if( busy )
+ return false;
+
+ currentUrl = urlIn;
+ KURL url = vfs::fromPathOrURL( urlIn );
+
+ if( fileIterator == 0 )
+ fileIterator = new QDictIterator<vfile> ( *this );
+
+ clear();
+
+ if( url.isLocalFile() ) {
+ QString path = url.path( -1 );
+ DIR* dir = opendir(path.local8Bit());
+ if(!dir) {
+ KMessageBox::error(parentWidget, i18n("Can't open the %1 directory!").arg( path ), i18n("Error"));
+ emit finished( result = false );
+ return false;
+ }
+
+ struct dirent* dirEnt;
+ QString name;
+
+ while( (dirEnt=readdir(dir)) != NULL ){
+ name = QString::fromLocal8Bit(dirEnt->d_name);
+
+ if (name=="." || name == "..") continue;
+ if (ignoreHidden && name.startsWith( "." ) ) continue;
+
+ QString fullName = path + "/" + name;
+
+ KDE_struct_stat stat_p;
+ KDE_lstat(fullName.local8Bit(),&stat_p);
+
+ QString perm = KRpermHandler::mode2QString(stat_p.st_mode);
+
+ bool symLink= S_ISLNK(stat_p.st_mode);
+ QString symlinkDest;
+
+ if( symLink ){ // who the link is pointing to ?
+ char symDest[256];
+ bzero(symDest,256);
+ int endOfName=0;
+ endOfName=readlink(fullName.local8Bit(),symDest,256);
+ if ( endOfName != -1 ) {
+ QString absSymDest = symlinkDest = QString::fromLocal8Bit( symDest );
+
+ if( !absSymDest.startsWith( "/" ) )
+ absSymDest = QDir::cleanDirPath( path + "/" + absSymDest );
+
+ if ( QDir( absSymDest ).exists() )
+ perm[0] = 'd';
+ }
+ }
+
+ QString mime = QString::null;
+
+ KURL fileURL = KURL::fromPathOrURL( fullName );
+
+ vfile* item=new vfile(name,stat_p.st_size,perm,stat_p.st_mtime,symLink,stat_p.st_uid,
+ stat_p.st_gid,mime,symlinkDest,stat_p.st_mode);
+ item->vfile_setUrl( fileURL );
+
+ insert( name, item );
+ }
+
+ closedir( dir );
+ emit finished( result = true );
+ return true;
+ } else {
+ KIO::Job *job = KIO::listDir( url, false, true );
+ connect( job, SIGNAL( entries( KIO::Job*, const KIO::UDSEntryList& ) ),
+ this, SLOT( slotEntries( KIO::Job*, const KIO::UDSEntryList& ) ) );
+ connect( job, SIGNAL( result( KIO::Job* ) ),
+ this, SLOT( slotListResult( KIO::Job* ) ) );
+ busy = true;
+
+ if( !wait )
+ return true;
+
+ while( busy )
+ qApp->processEvents();
+ return result;
+ }
+}
+
+void SynchronizerDirList::slotEntries( KIO::Job * job, const KIO::UDSEntryList& entries )
+{
+ KIO::UDSEntryListConstIterator it = entries.begin();
+ KIO::UDSEntryListConstIterator end = entries.end();
+
+ int rwx = -1;
+ QString prot = (( KIO::ListJob *)job )->url().protocol();
+
+ if( prot == "krarc" || prot == "tar" || prot == "zip" )
+ rwx = PERM_ALL;
+
+ while( it != end )
+ {
+ KFileItem kfi( *it, (( KIO::ListJob *)job )->url(), true, true );
+ QString key = kfi.text();
+ if( key != "." && key != ".." && (!ignoreHidden || !key.startsWith(".") ) ) {
+ mode_t mode = kfi.mode() | kfi.permissions();
+ QString perm = KRpermHandler::mode2QString( mode );
+ if ( kfi.isDir() )
+ perm[ 0 ] = 'd';
+
+ vfile *item = new vfile( kfi.text(), kfi.size(), perm, kfi.time( KIO::UDS_MODIFICATION_TIME ),
+ kfi.isLink(), kfi.user(), kfi.group(), kfi.user(),
+ kfi.mimetype(), kfi.linkDest(), mode, rwx
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+ , kfi.ACL().asString()
+#endif
+ );
+ insert( key, item );
+ }
+ ++it;
+ }
+}
+
+void SynchronizerDirList::slotListResult( KIO::Job *job ) {
+ busy = false;
+ if ( job && job->error() ) {
+ job->showErrorDialog( parentWidget );
+ emit finished( result = false );
+ return;
+ }
+ emit finished( result = true );
+}
+
+#include "synchronizerdirlist.moc"
diff --git a/krusader/Synchronizer/synchronizerdirlist.h b/krusader/Synchronizer/synchronizerdirlist.h
new file mode 100644
index 0000000..5cccd5c
--- /dev/null
+++ b/krusader/Synchronizer/synchronizerdirlist.h
@@ -0,0 +1,72 @@
+/***************************************************************************
+ synchronizerdirlist.h - description
+ -------------------
+ copyright : (C) 2006 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __SYNCHRONIZER_DIR_LIST_H__
+#define __SYNCHRONIZER_DIR_LIST_H__
+
+#include <qobject.h>
+#include <qdict.h>
+#include "../VFS/vfile.h"
+#include <kio/job.h>
+
+
+class SynchronizerDirList : public QObject, public QDict<vfile>
+{
+ Q_OBJECT
+
+public:
+ SynchronizerDirList( QWidget *w, bool ignoreHidden );
+ ~SynchronizerDirList();
+
+ vfile * search( const QString &name, bool ignoreCase = false );
+ vfile * first();
+ vfile * next();
+
+ inline const QString & url() { return currentUrl; }
+ bool load( const QString &urlIn, bool wait=false );
+
+public slots:
+
+ void slotEntries( KIO::Job * job, const KIO::UDSEntryList& entries );
+ void slotListResult( KIO::Job *job );
+
+signals:
+ void finished( bool err );
+
+private:
+ QDictIterator<vfile> *fileIterator; //< Point to a dictionary of virtual files (vfile).
+ QWidget *parentWidget;
+ bool busy;
+ bool result;
+ bool ignoreHidden;
+ QString currentUrl;
+};
+
+#endif /* __SYNCHRONIZER_DIR_LIST_H__ */
diff --git a/krusader/Synchronizer/synchronizerfileitem.h b/krusader/Synchronizer/synchronizerfileitem.h
new file mode 100644
index 0000000..0a2268a
--- /dev/null
+++ b/krusader/Synchronizer/synchronizerfileitem.h
@@ -0,0 +1,170 @@
+/***************************************************************************
+ synchronizerfileitem.h - description
+ -------------------
+ copyright : (C) 2006 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __SYNCHRONIZER_FILE_ITEM_H__
+#define __SYNCHRONIZER_FILE_ITEM_H__
+
+#include <qstring.h>
+#include <kio/global.h>
+
+typedef enum
+{
+ TT_EQUALS = 0, // the files are equals -> do nothing
+ TT_DIFFERS = 1, // the files are differents -> don't know what to do
+ TT_COPY_TO_LEFT = 2, // the right file is newer -> copy from right to left
+ TT_COPY_TO_RIGHT = 3, // the left file is newer -> copy from left to right
+ TT_DELETE = 4, // the left file is single -> delete it
+ TT_UNKNOWN = 5, // (5-9) the type of the task is not yet known
+ TT_MAX = 10 // the maximum number of task types
+} TaskType;
+
+#define SWAP( A, B, TYPE ) {TYPE TMP = A; A = B; B = TMP;}
+#define REVERSE_TASK( A, asym ) {switch( A ) \
+ { \
+ case TT_COPY_TO_LEFT: \
+ if( asym ) \
+ A = !m_existsRight ? TT_DELETE : TT_COPY_TO_LEFT; \
+ else \
+ A = TT_COPY_TO_RIGHT; \
+ break; \
+ case TT_COPY_TO_RIGHT: \
+ case TT_DELETE: \
+ A = TT_COPY_TO_LEFT; \
+ default: \
+ break; \
+ }};
+
+class SynchronizerFileItem
+{
+ private:
+ QString m_leftName; // the left file name
+ QString m_rightName; // the right file name
+ QString m_leftDirectory;// the left relative directory path from the base
+ QString m_rightDirectory;// the left relative directory path from the base
+ bool m_marked; // flag, indicates to show the file
+ bool m_existsLeft; // flag, the file exists in the left directory
+ bool m_existsRight; // flag, the file exists in the right directory
+ KIO::filesize_t m_leftSize; // the file size at the left directory
+ KIO::filesize_t m_rightSize; // the file size at the right directory
+ time_t m_leftDate; // the file date at the left directory
+ time_t m_rightDate; // the file date at the left directory
+ QString m_leftLink; // the left file's symbolic link destination
+ QString m_rightLink; // the right file's symbolic link destination
+ QString m_leftOwner; // the left file's owner
+ QString m_rightOwner; // the right file's owner
+ QString m_leftGroup; // the left file's group
+ QString m_rightGroup; // the right file's group
+ mode_t m_leftMode; // mode for left
+ mode_t m_rightMode; // mode for right
+ QString m_leftACL; // ACL of the left file
+ QString m_rightACL; // ACL of the right file
+ TaskType m_task; // the task with the file
+ bool m_isDir; // flag, indicates that the file is a directory
+ SynchronizerFileItem *m_parent; // pointer to the parent directory item or 0
+ void *m_userData; // user data
+ bool m_overWrite; // overwrite flag
+ QString m_destination; // the destination URL at rename
+ bool m_temporary; // flag indicates temporary directory
+ TaskType m_originalTask; // the original task type
+
+ public:
+ SynchronizerFileItem(const QString &leftNam, const QString &rightNam, const QString &leftDir,
+ const QString &rightDir, bool mark, bool exL, bool exR, KIO::filesize_t leftSize,
+ KIO::filesize_t rightSize, time_t leftDate, time_t rightDate,
+ const QString &leftLink, const QString &rightLink, const QString &leftOwner,
+ const QString &rightOwner, const QString &leftGroup, const QString &rightGroup,
+ mode_t leftMode, mode_t rightMode, const QString &leftACL, const QString &rightACL,
+ TaskType tsk, bool isDir, bool tmp, SynchronizerFileItem *parent ) :
+ m_leftName( leftNam ), m_rightName( rightNam ), m_leftDirectory( leftDir ), m_rightDirectory( rightDir ),
+ m_marked( mark ), m_existsLeft( exL ), m_existsRight( exR ), m_leftSize( leftSize ),
+ m_rightSize( rightSize ), m_leftDate( leftDate ), m_rightDate( rightDate ),
+ m_leftLink( leftLink ), m_rightLink( rightLink ), m_leftOwner( leftOwner ),
+ m_rightOwner( rightOwner ), m_leftGroup( leftGroup ), m_rightGroup( rightGroup ),
+ m_leftMode( leftMode ), m_rightMode( rightMode ), m_leftACL( leftACL ),
+ m_rightACL( rightACL ), m_task( tsk ), m_isDir( isDir ), m_parent(parent),
+ m_userData( 0 ), m_overWrite( false ), m_destination( QString::null ),
+ m_temporary( tmp ), m_originalTask( tsk ) {}
+
+ inline bool isMarked() {return m_marked;}
+ inline void setMarked( bool flag ) {m_marked = flag;}
+ inline const QString & leftName() {return m_leftName;}
+ inline const QString & rightName() {return m_rightName;}
+ inline const QString & leftDirectory() {return m_leftDirectory;}
+ inline const QString & rightDirectory() {return m_rightDirectory;}
+ inline bool existsInLeft() {return m_existsLeft;}
+ inline bool existsInRight() {return m_existsRight;}
+ inline bool overWrite() {return m_overWrite;}
+ inline KIO::filesize_t leftSize() {return m_leftSize;}
+ inline KIO::filesize_t rightSize() {return m_rightSize;}
+ inline time_t leftDate() {return m_leftDate;}
+ inline time_t rightDate() {return m_rightDate;}
+ inline const QString & leftLink() {return m_leftLink;}
+ inline const QString & rightLink() {return m_rightLink;}
+ inline const QString & leftOwner() {return m_leftOwner;}
+ inline const QString & rightOwner() {return m_rightOwner;}
+ inline const QString & leftGroup() {return m_leftGroup;}
+ inline const QString & rightGroup() {return m_rightGroup;}
+ inline mode_t leftMode() {return m_leftMode;}
+ inline mode_t rightMode() {return m_rightMode;}
+ inline const QString & leftACL() {return m_leftACL;}
+ inline const QString & rightACL() {return m_rightACL;}
+ inline TaskType task() {return m_task;}
+ inline void compareContentResult( bool res )
+ {if( res == true )
+ m_task = m_originalTask = TT_EQUALS;
+ else if( m_originalTask >= TT_UNKNOWN )
+ m_task = m_originalTask = (TaskType)(m_originalTask - TT_UNKNOWN);
+ }
+ inline bool isDir() {return m_isDir;}
+ inline SynchronizerFileItem * parent() {return m_parent;}
+ inline void * userData() {return m_userData;}
+ inline void setUserData( void *ud) {m_userData = ud;}
+ inline void setOverWrite() {m_overWrite = true;}
+ inline const QString & destination() {return m_destination;}
+ inline void setDestination(QString d) {m_destination = d;}
+ inline bool isTemporary() {return m_temporary;}
+ inline void setPermanent() {m_temporary = false;}
+ inline TaskType originalTask() {return m_originalTask;}
+ inline void restoreOriginalTask() {m_task = m_originalTask;}
+ inline void setTask( TaskType t ) {m_task = t;}
+ inline void swap( bool asym=false ) {SWAP( m_existsLeft, m_existsRight, bool );
+ SWAP( m_leftName, m_rightName, QString );
+ SWAP( m_leftDirectory, m_rightDirectory, QString );
+ SWAP( m_leftSize, m_rightSize, KIO::filesize_t );
+ SWAP( m_leftDate, m_rightDate, time_t );
+ SWAP( m_leftLink, m_rightLink, QString );
+ SWAP( m_leftOwner, m_rightOwner, QString );
+ SWAP( m_leftGroup, m_rightGroup, QString );
+ SWAP( m_leftACL, m_rightACL, QString );
+ REVERSE_TASK( m_originalTask, asym );
+ REVERSE_TASK( m_task, asym );}
+};
+
+#endif /* __SYNCHRONIZER_FILE_ITEM_H__ */
diff --git a/krusader/Synchronizer/synchronizergui.cpp b/krusader/Synchronizer/synchronizergui.cpp
new file mode 100755
index 0000000..639b568
--- /dev/null
+++ b/krusader/Synchronizer/synchronizergui.cpp
@@ -0,0 +1,2478 @@
+/***************************************************************************
+ synchronizergui.cpp - description
+ -------------------
+ copyright : (C) 2003 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "synchronizergui.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include "../VFS/krpermhandler.h"
+#include "../KViewer/krviewer.h"
+#include "../Dialogs/krspwidgets.h"
+#include "../VFS/krquery.h"
+#include "../krservices.h"
+#include "../krslots.h"
+#include "../kicons.h"
+#include "synchronizedialog.h"
+#include "feedtolistboxdialog.h"
+#include <qlayout.h>
+#include <kurlrequester.h>
+#include <klocale.h>
+#include <qgrid.h>
+#include <kpopupmenu.h>
+#include <qcursor.h>
+#include <time.h>
+#include <kmessagebox.h>
+#include <kio/netaccess.h>
+#include <qeventloop.h>
+#include <qwhatsthis.h>
+#include <qregexp.h>
+#include <qheader.h>
+#include <qspinbox.h>
+#include <kinputdialog.h>
+#include <kurldrag.h>
+#include <qclipboard.h>
+
+static const char * const right_arrow_button_data[] = {
+"18 18 97 2",
+" c None",
+". c #000000",
+"+ c #030D03",
+"@ c #184F16",
+"# c #5DB45A",
+"$ c #2E6C2A",
+"% c #90D28D",
+"& c #9CD59A",
+"* c #32732E",
+"= c #92CF8F",
+"- c #BDE9BB",
+"; c #C4E5C3",
+"> c #447F41",
+", c #108F08",
+"' c #0F8E08",
+") c #108E08",
+"! c #14970B",
+"~ c #8DD289",
+"{ c #87DF7F",
+"] c #D6F1D3",
+"^ c #C3E1C1",
+"/ c #488844",
+"( c #73D56C",
+"_ c #D1F4D0",
+": c #F3FCF3",
+"< c #F7FEF7",
+"[ c #EFFCEF",
+"} c #DCF6DB",
+"| c #B4EAB0",
+"1 c #70D965",
+"2 c #2AC71B",
+"3 c #68D85D",
+"4 c #CFF1CB",
+"5 c #DCEFDB",
+"6 c #589955",
+"7 c #74D46D",
+"8 c #9DDF98",
+"9 c #ABE8A5",
+"0 c #B8EEB4",
+"a c #9EE797",
+"b c #74DD6A",
+"c c #62D758",
+"d c #23C512",
+"e c #15BC07",
+"f c #27C519",
+"g c #73DC69",
+"h c #BAEDB6",
+"i c #B8E7B6",
+"j c #499145",
+"k c #77D671",
+"l c #7BD874",
+"m c #3AC72C",
+"n c #42C437",
+"o c #34C526",
+"p c #1FC40F",
+"q c #24C516",
+"r c #1AB70E",
+"s c #1ABC0D",
+"t c #20C411",
+"u c #5AD94B",
+"v c #5DE24A",
+"w c #36C229",
+"x c #177B11",
+"y c #7DDA75",
+"z c #84E07B",
+"A c #2BC519",
+"B c #2FBF1F",
+"C c #33C623",
+"D c #28C716",
+"E c #22CC11",
+"F c #20C511",
+"G c #23CC13",
+"H c #31D81C",
+"I c #4FE03B",
+"J c #34C725",
+"K c #137F0D",
+"L c #157C0E",
+"M c #126B0F",
+"N c #126A0E",
+"O c #116C0C",
+"P c #13760E",
+"Q c #179A0E",
+"R c #37DC22",
+"S c #4DDF38",
+"T c #2AB71D",
+"U c #12720D",
+"V c #010C00",
+"W c #28C715",
+"X c #47DF32",
+"Y c #2DBD1F",
+"Z c #116B0D",
+"` c #2CB122",
+" . c #23AD18",
+".. c #10620C",
+"+. c #289023",
+"@. c #125B0E",
+"#. c #094706",
+" ",
+" . + ",
+" . @ . ",
+" . # $ . ",
+" . % & * . ",
+" . . . . . . . . = - ; > . ",
+" . , ' ' ' ) , ! ~ { ] ^ / . ",
+" . ( _ : < [ } | 1 2 3 4 5 6 . ",
+" . 7 8 9 0 a b c d e f g h i j . ",
+" . k l m n o p q r s t u v w x . ",
+" . y z A B C D E F G H I J K . ",
+" . L M N M O P Q p R S T U . ",
+" V . . . . . . . W X Y Z . ",
+" . ` .... ",
+" . +.@.. ",
+" . #.. ",
+" . . ",
+" "};
+
+static const char * const equals_button_data[] = {
+"18 18 5 1",
+" c None",
+". c #414100",
+"+ c #E0E0E0",
+"@ c #A8A8A8",
+"# c #808080",
+" ",
+" ",
+" ",
+" .............. ",
+" .++++++++++++. ",
+" .@@@@@@@@@@@@. ",
+" .############. ",
+" .............. ",
+" ",
+" .............. ",
+" .++++++++++++. ",
+" .@@@@@@@@@@@@. ",
+" .############. ",
+" .............. ",
+" ",
+" ",
+" ",
+" "};
+
+static const char * const differents_button_data[] = {
+"18 18 5 1",
+" c None",
+". c #FF0000",
+"+ c #FFC0C0",
+"@ c #FF8080",
+"# c #FF4040",
+" ",
+" ... ",
+" ... ",
+" .............. ",
+" .+++++++...++. ",
+" .@@@@@@...@@@. ",
+" .######...###. ",
+" .............. ",
+" ... ",
+" .............. ",
+" .++++...+++++. ",
+" .@@@...@@@@@@. ",
+" .###...######. ",
+" .............. ",
+" ... ",
+" ... ",
+" ... ",
+" "};
+
+static const char * const left_arrow_button_data[] = {
+"18 18 137 2",
+" c None",
+". c #03090E",
+"+ c #0D3A57",
+"@ c #041F2B",
+"# c #073347",
+"$ c #0D3C5A",
+"% c #051C26",
+"& c #0F455C",
+"* c #237191",
+"= c #104363",
+"- c #04121A",
+"; c #0C4A62",
+"> c #198AAD",
+", c #2291B2",
+"' c #104564",
+") c #062332",
+"! c #0D506B",
+"~ c #209FBD",
+"{ c #33CBDF",
+"] c #16ACC8",
+"^ c #0C4968",
+"/ c #061F2D",
+"( c #031721",
+"_ c #041621",
+": c #051721",
+"< c #021621",
+"[ c #031B27",
+"} c #01090D",
+"| c #04151E",
+"1 c #0D5672",
+"2 c #1E99B8",
+"3 c #39CEDF",
+"4 c #22C5DC",
+"5 c #10A1C4",
+"6 c #0E799B",
+"7 c #0E5976",
+"8 c #0D516D",
+"9 c #0F4E6B",
+"0 c #0F4D6A",
+"a c #0F607D",
+"b c #031D25",
+"c c #052837",
+"d c #0D617F",
+"e c #25ABC7",
+"f c #3BD0E1",
+"g c #1DC0D9",
+"h c #14A8CC",
+"i c #11A3C5",
+"j c #11ABCC",
+"k c #17AAC8",
+"l c #23ACC6",
+"m c #1FA8C0",
+"n c #1AAAC5",
+"o c #7CCDE1",
+"p c #76C4DB",
+"q c #032832",
+"r c #061D28",
+"s c #125F7C",
+"t c #29A6C3",
+"u c #4BD4E3",
+"v c #4BC5DA",
+"w c #129FC4",
+"x c #0D95BC",
+"y c #0F90B7",
+"z c #16A2C5",
+"A c #0FA3C4",
+"B c #26A8C5",
+"C c #37A8C4",
+"D c #2DA9C7",
+"E c #75C1D9",
+"F c #71BED6",
+"G c #0A212C",
+"H c #467B92",
+"I c #B6D9E8",
+"J c #B6E2ED",
+"K c #69C7DC",
+"L c #19A2C5",
+"M c #0796BC",
+"N c #13A5C5",
+"O c #59BBD7",
+"P c #6BC5DD",
+"Q c #98D8E8",
+"R c #B4E2EE",
+"S c #A6DCE9",
+"T c #98CFDF",
+"U c #6DBCD4",
+"V c #143341",
+"W c #56859A",
+"X c #DCEAF0",
+"Y c #CCEAF2",
+"Z c #5EC2D9",
+"` c #1BA7C8",
+" . c #66C4DA",
+".. c #B1DBEB",
+"+. c #DBEEF6",
+"@. c #EFF6FC",
+"#. c #F7FAFE",
+"$. c #F3F8FC",
+"%. c #D0EAF4",
+"&. c #6CBCD5",
+"*. c #091A21",
+"=. c #457589",
+"-. c #C2D8E2",
+";. c #D4ECF2",
+">. c #80CCDF",
+",. c #8ABFD3",
+"'. c #0C7497",
+"). c #086E90",
+"!. c #086C8E",
+"~. c #086B8E",
+"{. c #086D90",
+"]. c #021E27",
+"^. c #0D2B38",
+"/. c #426D80",
+"(. c #C3DAE5",
+"_. c #BCDCEA",
+":. c #90BDD0",
+"<. c #144361",
+"[. c #002745",
+"}. c #00213F",
+"|. c #001F3E",
+"1. c #00203F",
+"2. c #002643",
+"3. c #000B13",
+"4. c #03161D",
+"5. c #2F5F73",
+"6. c #9AC3D5",
+"7. c #8EBED3",
+"8. c #1A4A68",
+"9. c #0C222B",
+"0. c #2B5A6D",
+"a. c #5A98B4",
+"b. c #164867",
+"c. c #0F2731",
+"d. c #163E50",
+"e. c #0E3E5C",
+"f. c #0C3652",
+" ",
+" . f. ",
+" c.d.e. ",
+" 9.0.a.b. ",
+" 4.5.6.7.8. ",
+" ^./.(._.:.<.[.}.|.|.1.2.3. ",
+" *.=.-.;.>.,.'.).!.~.~.~.{.]. ",
+" V W X Y Z ` ...+.@.#.$.%.&.q ",
+" G H I J K L M N O P Q R S T U q ",
+" r s t u v w x y z A B C D E F q ",
+" c d e f g h i j k l m n o p q ",
+" | 1 2 3 4 5 6 7 8 9 0 9 a b ",
+" ) ! ~ { ] ^ / ( _ : < [ } ",
+" - ; > , ' ",
+" % & * = ",
+" @ # $ ",
+" . + ",
+" "};
+
+static const char * const trash_button_data[] = {
+"18 18 140 2",
+" c None",
+". c #BFBFBF",
+"+ c #BABAB9",
+"@ c #AEAEAE",
+"# c #A2A2A3",
+"$ c #959595",
+"% c #8B8B8C",
+"& c #868687",
+"* c #D3D5D5",
+"= c #E1E1E1",
+"- c #CCCCCD",
+"; c #BDBEBD",
+"> c #B1B2B1",
+", c #A3A2A2",
+"' c #959597",
+") c #8E8E8F",
+"! c #818282",
+"~ c #727171",
+"{ c #838384",
+"] c #D1D1D1",
+"^ c #F3F3F3",
+"/ c #C6C7C6",
+"( c #B8B9B9",
+"_ c #ABABAB",
+": c #9F9FA0",
+"< c #949394",
+"[ c #8E8E8E",
+"} c #7E8080",
+"| c #717071",
+"1 c #5C5C5B",
+"2 c #555556",
+"3 c #A7A7A7",
+"4 c #FAFAFA",
+"5 c #CACACA",
+"6 c #BABBBB",
+"7 c #B5B6B6",
+"8 c #A9A9AA",
+"9 c #9E9E9D",
+"0 c #929293",
+"a c #8E8C8D",
+"b c #7F7F7F",
+"c c #6F6F70",
+"d c #525151",
+"e c #414141",
+"f c #A1A2A2",
+"g c #C3C3C2",
+"h c #D5D4D4",
+"i c #ECECEC",
+"j c #E7E7E7",
+"k c #D6D6D6",
+"l c #C5C5C6",
+"m c #B0B0B0",
+"n c #AAAAAA",
+"o c #989898",
+"p c #6D6D6E",
+"q c #494949",
+"r c #9E9E9E",
+"s c #C0C1C1",
+"t c #BABABA",
+"u c #B2B2B2",
+"v c #AEAEAD",
+"w c #A4A4A4",
+"x c #9B9B9B",
+"y c #8E8F8F",
+"z c #888888",
+"A c #767676",
+"B c #616161",
+"C c #B3B3B3",
+"D c #B9B9BA",
+"E c #A4A5A4",
+"F c #979797",
+"G c #888788",
+"H c #6D6D6D",
+"I c #4D4D4D",
+"J c #4B4A4B",
+"K c #F6F6F6",
+"L c #B1B1B1",
+"M c #A7A8A7",
+"N c #939394",
+"O c #8D8D8E",
+"P c #727272",
+"Q c #505050",
+"R c #484848",
+"S c #EEEEEE",
+"T c #EBEBEB",
+"U c #9D9D9C",
+"V c #919292",
+"W c #8C8C8C",
+"X c #808080",
+"Y c #6C6B6C",
+"Z c #E5E5E5",
+"` c #AFAFAF",
+" . c #A6A6A6",
+".. c #8F908F",
+"+. c #888989",
+"@. c #7B7B7B",
+"#. c #676667",
+"$. c #4F4F4F",
+"%. c #AFB0AF",
+"&. c #D8D8D8",
+"*. c #D4D4D4",
+"=. c #A5A5A4",
+"-. c #9A9A9A",
+";. c #8D8D8D",
+">. c #777777",
+",. c #5F5F5F",
+"'. c #4B4B4B",
+"). c #B0AFAF",
+"!. c #D3D2D2",
+"~. c #CDCDCD",
+"{. c #A4A5A5",
+"]. c #8D8D8B",
+"^. c #868685",
+"/. c #747474",
+"(. c #5D5D5D",
+"_. c #AEAFAE",
+":. c #C4C4C4",
+"<. c #BEBEBE",
+"[. c #A3A4A3",
+"}. c #8B8A8A",
+"|. c #838282",
+"1. c #707070",
+"2. c #565656",
+"3. c #444444",
+"4. c #000000",
+"5. c #B2B1B1",
+"6. c #ADADAD",
+"7. c #A3A3A3",
+"8. c #979697",
+"9. c #6C6C6C",
+"0. c #403F3F",
+"a. c #B1B2B2",
+"b. c #9F9F9F",
+"c. c #A6A6A7",
+"d. c #9E9F9F",
+"e. c #949494",
+"f. c #828282",
+"g. c #787979",
+"h. c #3D3D3C",
+"i. c #2F2F2F",
+" ",
+" . + @ # $ % & % ",
+" * = - ; > , ' ) ! ~ { ",
+" ] ^ / ; ( _ : < [ } | 1 2 ",
+" 3 4 5 6 7 8 9 0 a b c d e ",
+" f g h i j k l m n o p q e ",
+" r s t u v w x y z A B e 2 ",
+" [ C D C E F G b H I J ",
+" C K ^ L M r N O P Q R ",
+" L S T m 3 U V W X Y R ",
+" m Z = ` .x ..+.@.#.$. ",
+" %.&.*.@ =.-.;.& >.,.'. ",
+" ).!.~.@ {.-.].^./.(.R ",
+" _.:.<.@ [.o }.|.1.2.3.4.4.4. ",
+" @ D 5.6.7.8.z b 9.Q 0.4.4.4.4. ",
+" a.b.c.3 d.e.f.g.(.h.i.4.4.4.4. ",
+" 4.4.4.4.4.4.4.4. ",
+" "};
+
+static const char * const file_data[] = {
+"16 16 42 1",
+" c None",
+". c #D0D0DF",
+"+ c #9C9CB6",
+"@ c #FFFFFF",
+"# c #F9F9FE",
+"$ c #F5F5FC",
+"% c #E9E9F2",
+"& c #EBEBF4",
+"* c #FCFCFF",
+"= c #F8F8FE",
+"- c #ECECF4",
+"; c #D3D3E1",
+"> c #EFEFF6",
+", c #FDFDFF",
+"' c #F1F1F8",
+") c #E6E6F0",
+"! c #D7D7E5",
+"~ c #C9C9DA",
+"{ c #FEFEFF",
+"] c #F2F2F9",
+"^ c #EEEEF5",
+"/ c #DADAE7",
+"( c #CECEDD",
+"_ c #CCCCDB",
+": c #F3F3F9",
+"< c #D5D5E4",
+"[ c #D2D2E0",
+"} c #E7E7F0",
+"| c #E0E0EC",
+"1 c #DCDCE9",
+"2 c #DBDBE8",
+"3 c #D8D8E6",
+"4 c #F6F6FD",
+"5 c #E5E5EF",
+"6 c #DEDEEB",
+"7 c #F0F0F7",
+"8 c #EAEAF3",
+"9 c #E8E8F1",
+"0 c #E1E1ED",
+"a c #F4F4FA",
+"b c #E4E4EE",
+"c c #FAFAFF",
+" ........+ ",
+" .@@@#$%&.+ ",
+" .@@@*=-&.;+ ",
+" .@@@*#>&++++ ",
+" .@@@,#'&)!~+ ",
+" .@@@{*]^/(_+ ",
+" .@@@@*:&<[.+ ",
+" .@@{#$}|123+ ",
+" .@{,4^)5|61+ ",
+" .@@#7^8950|+ ",
+" .@,a'>&8)b|+ ",
+" .@c:'>&8}50+ ",
+" .@$:'7^8}50+ ",
+" .@:]7>-8)50+ ",
+" .*::'>&8}50+ ",
+" ++++++++++++ "};
+
+static const char * const folder_data[] = {
+"16 16 132 2",
+" c None",
+". c #2C87EF",
+"+ c #64A6F7",
+"@ c #357CE3",
+"# c #D9E1F8",
+"$ c #B1BADE",
+"% c #8BA2D9",
+"& c #4392E3",
+"* c #B8D9F8",
+"= c #4F9BED",
+"- c #126EE0",
+"; c #0A43A8",
+"> c #C6CBDA",
+", c #FFFFFF",
+"' c #F1F0F6",
+") c #80ADE2",
+"! c #4F95E4",
+"~ c #1876DF",
+"{ c #0C6ADF",
+"] c #0C4CB9",
+"^ c #CCCFDA",
+"/ c #F8F4F7",
+"( c #89B7E7",
+"_ c #78ACE4",
+": c #B4D8F8",
+"< c #97CAFF",
+"[ c #6FAEFC",
+"} c #3175D8",
+"| c #0E51B4",
+"1 c #002374",
+"2 c #D0D0D7",
+"3 c #8EC1F0",
+"4 c #85BBED",
+"5 c #DAF0F9",
+"6 c #BDE2FB",
+"7 c #9CCCF8",
+"8 c #84BBF8",
+"9 c #6FAAF4",
+"0 c #4780D4",
+"a c #0851AA",
+"b c #0035A9",
+"c c #CFD0D4",
+"d c #51A2E9",
+"e c #FFFFFE",
+"f c #EEFCFD",
+"g c #CEECFB",
+"h c #B1D9F9",
+"i c #9AC9F9",
+"j c #7EB3F2",
+"k c #568CDA",
+"l c #1156BA",
+"m c #004595",
+"n c #003293",
+"o c #EFEFEE",
+"p c #84BCEE",
+"q c #E2F8FC",
+"r c #C9E8FB",
+"s c #B0D8FA",
+"t c #90C0F3",
+"u c #6B9FE5",
+"v c #3375CC",
+"w c #2A71C7",
+"x c #003B96",
+"y c #0651AE",
+"z c #0E3DAC",
+"A c #E5E3E0",
+"B c #DFD8D5",
+"C c #FFF7F2",
+"D c #DEEFFE",
+"E c #BEDCF6",
+"F c #E5FCFD",
+"G c #C4E6FB",
+"H c #A8D4F8",
+"I c #85B6EC",
+"J c #437DCE",
+"K c #2170C9",
+"L c #397CC8",
+"M c #A3B6D4",
+"N c #E3D3D2",
+"O c #295BC3",
+"P c #4AACFF",
+"Q c #74A7D5",
+"R c #CBC7CE",
+"S c #7EB0E7",
+"T c #F5FFFF",
+"U c #C1E7FE",
+"V c #9AC8F3",
+"W c #4B84D3",
+"X c #5490D9",
+"Y c #B3C7E3",
+"Z c #E9DFDF",
+"` c #D3CED8",
+" . c #D7CFD3",
+".. c #7488C1",
+"+. c #002A95",
+"@. c #6FCDFF",
+"#. c #CBEAFF",
+"$. c #D9F9FF",
+"%. c #70AAE1",
+"&. c #C7E0EE",
+"*. c #9DCBF1",
+"=. c #84AEE4",
+"-. c #D0E1F4",
+";. c #FFF9F4",
+">. c #EEE9EB",
+",. c #E6E2E5",
+"'. c #D9D1D6",
+"). c #637DC0",
+"!. c #2D63D3",
+"~. c #001251",
+"{. c #439FF0",
+"]. c #B4DBF9",
+"^. c #D6F8FF",
+"/. c #75ACE3",
+"(. c #F0FAFF",
+"_. c #FCF9F8",
+":. c #91A5D4",
+"<. c #2A5FCE",
+"[. c #002B91",
+"}. c #3E9DEF",
+"|. c #A4CEF4",
+"1. c #77AFE8",
+"2. c #E1EBFC",
+"3. c #3F73D7",
+"4. c #043BAE",
+"5. c #3188DE",
+"6. c #75A9E3",
+"7. c #A8C6EC",
+"8. c #6195E7",
+"9. c #1450C5",
+"0. c #7AB0FB",
+"a. c #155ED2",
+" ",
+" . + @ ",
+" # $ % & * = - ; ",
+" > , , ' ) ! ~ { ] ",
+" ^ , / ( _ : < [ } | 1 ",
+" 2 , 3 4 5 6 7 8 9 0 a b ",
+" c , d e f g h i j k l m n ",
+"o , , p , q r s t u v w x y z ",
+"A B C D E F G H I J K L M N O ",
+" P Q R S T U V W X Y Z ` ...+.",
+" @.#.$.%.&.*.=.-.;.>.,.'.).!.~.",
+" {.].^./.(., , _.C :.<.[. ",
+" }.|.1., , , 2.3.4. ",
+" 5.6.7., 8.9. ",
+" 0.a. ",
+" "};
+
+static const char * const swap_sides_data[] = {
+"27 20 228 2",
+" c None",
+". c #03090E",
+"+ c #0C3652",
+"@ c #000000",
+"# c #030D03",
+"$ c #0F2731",
+"% c #163E50",
+"& c #0E3E5C",
+"* c #184F16",
+"= c #0C222B",
+"- c #2B5A6D",
+"; c #5A98B4",
+"> c #164867",
+", c #5DB45A",
+"' c #2E6C2A",
+") c #03161D",
+"! c #2F5F73",
+"~ c #9AC3D5",
+"{ c #8EBED3",
+"] c #1A4A68",
+"^ c #90D28D",
+"/ c #9CD59A",
+"( c #32732E",
+"_ c #0D2B38",
+": c #426D80",
+"< c #C3DAE5",
+"[ c #BCDCEA",
+"} c #90BDD0",
+"| c #144361",
+"1 c #002745",
+"2 c #00213F",
+"3 c #001F3E",
+"4 c #00203F",
+"5 c #002643",
+"6 c #92CF8F",
+"7 c #BDE9BB",
+"8 c #C4E5C3",
+"9 c #447F41",
+"0 c #091A21",
+"a c #457589",
+"b c #C2D8E2",
+"c c #D4ECF2",
+"d c #80CCDF",
+"e c #8ABFD3",
+"f c #0C7497",
+"g c #086E90",
+"h c #086C8E",
+"i c #086B8E",
+"j c #086D90",
+"k c #108F08",
+"l c #0F8E08",
+"m c #108E08",
+"n c #14970B",
+"o c #8DD289",
+"p c #87DF7F",
+"q c #D6F1D3",
+"r c #C3E1C1",
+"s c #488844",
+"t c #143341",
+"u c #56859A",
+"v c #DCEAF0",
+"w c #CCEAF2",
+"x c #5EC2D9",
+"y c #1BA7C8",
+"z c #66C4DA",
+"A c #B1DBEB",
+"B c #DBEEF6",
+"C c #EFF6FC",
+"D c #F7FAFE",
+"E c #F3F8FC",
+"F c #D0EAF4",
+"G c #6CBCD5",
+"H c #73D56C",
+"I c #D1F4D0",
+"J c #F3FCF3",
+"K c #F7FEF7",
+"L c #EFFCEF",
+"M c #DCF6DB",
+"N c #B4EAB0",
+"O c #70D965",
+"P c #2AC71B",
+"Q c #68D85D",
+"R c #CFF1CB",
+"S c #DCEFDB",
+"T c #589955",
+"U c #0A212C",
+"V c #467B92",
+"W c #B6D9E8",
+"X c #B6E2ED",
+"Y c #69C7DC",
+"Z c #19A2C5",
+"` c #0796BC",
+" . c #13A5C5",
+".. c #59BBD7",
+"+. c #6BC5DD",
+"@. c #98D8E8",
+"#. c #B4E2EE",
+"$. c #A6DCE9",
+"%. c #98CFDF",
+"&. c #6DBCD4",
+"*. c #74D46D",
+"=. c #9DDF98",
+"-. c #ABE8A5",
+";. c #B8EEB4",
+">. c #9EE797",
+",. c #74DD6A",
+"'. c #62D758",
+"). c #23C512",
+"!. c #15BC07",
+"~. c #27C519",
+"{. c #73DC69",
+"]. c #BAEDB6",
+"^. c #B8E7B6",
+"/. c #499145",
+"(. c #061D28",
+"_. c #125F7C",
+":. c #29A6C3",
+"<. c #4BD4E3",
+"[. c #4BC5DA",
+"}. c #129FC4",
+"|. c #0D95BC",
+"1. c #0F90B7",
+"2. c #16A2C5",
+"3. c #0FA3C4",
+"4. c #26A8C5",
+"5. c #37A8C4",
+"6. c #2DA9C7",
+"7. c #75C1D9",
+"8. c #71BED6",
+"9. c #77D671",
+"0. c #7BD874",
+"a. c #3AC72C",
+"b. c #42C437",
+"c. c #34C526",
+"d. c #1FC40F",
+"e. c #24C516",
+"f. c #1AB70E",
+"g. c #1ABC0D",
+"h. c #20C411",
+"i. c #5AD94B",
+"j. c #5DE24A",
+"k. c #36C229",
+"l. c #177B11",
+"m. c #052837",
+"n. c #0D617F",
+"o. c #25ABC7",
+"p. c #3BD0E1",
+"q. c #1DC0D9",
+"r. c #14A8CC",
+"s. c #11A3C5",
+"t. c #11ABCC",
+"u. c #17AAC8",
+"v. c #23ACC6",
+"w. c #1FA8C0",
+"x. c #1AAAC5",
+"y. c #7CCDE1",
+"z. c #76C4DB",
+"A. c #7DDA75",
+"B. c #84E07B",
+"C. c #2BC519",
+"D. c #2FBF1F",
+"E. c #33C623",
+"F. c #28C716",
+"G. c #22CC11",
+"H. c #20C511",
+"I. c #23CC13",
+"J. c #31D81C",
+"K. c #4FE03B",
+"L. c #34C725",
+"M. c #137F0D",
+"N. c #04151E",
+"O. c #0D5672",
+"P. c #1E99B8",
+"Q. c #39CEDF",
+"R. c #22C5DC",
+"S. c #10A1C4",
+"T. c #0E799B",
+"U. c #0E5976",
+"V. c #0D516D",
+"W. c #0F4E6B",
+"X. c #0F4D6A",
+"Y. c #0F607D",
+"Z. c #157C0E",
+"`. c #126B0F",
+" + c #126A0E",
+".+ c #116C0C",
+"++ c #13760E",
+"@+ c #179A0E",
+"#+ c #37DC22",
+"$+ c #4DDF38",
+"%+ c #2AB71D",
+"&+ c #12720D",
+"*+ c #062332",
+"=+ c #0D506B",
+"-+ c #209FBD",
+";+ c #33CBDF",
+">+ c #16ACC8",
+",+ c #0C4968",
+"'+ c #061F2D",
+")+ c #031721",
+"!+ c #041621",
+"~+ c #051721",
+"{+ c #021621",
+"]+ c #031B27",
+"^+ c #010C00",
+"/+ c #28C715",
+"(+ c #47DF32",
+"_+ c #2DBD1F",
+":+ c #116B0D",
+"<+ c #04121A",
+"[+ c #0C4A62",
+"}+ c #198AAD",
+"|+ c #2291B2",
+"1+ c #104564",
+"2+ c #2CB122",
+"3+ c #23AD18",
+"4+ c #10620C",
+"5+ c #051C26",
+"6+ c #0F455C",
+"7+ c #237191",
+"8+ c #104363",
+"9+ c #289023",
+"0+ c #125B0E",
+"a+ c #041F2B",
+"b+ c #073347",
+"c+ c #0D3C5A",
+"d+ c #094706",
+"e+ c #0D3A57",
+" ",
+" ",
+" . + @ # ",
+" $ % & @ * @ ",
+" = - ; > @ , ' @ ",
+" ) ! ~ { ] @ ^ / ( @ ",
+" _ : < [ } | 1 3 4 5 @ @ @ @ @ @ 6 7 8 9 @ ",
+" 0 a b c d e f g i i j @ k l l k n o p q r s @ ",
+" t u v w x y z A B E F G @ H I K M N O P Q R S T @ ",
+"U V W X Y Z ` ...+.$.%.&.@ *.=.;.,.'.).!.~.{.].^./.@ ",
+"(._.:.<.[.}.|.1.2.3.6.7.8.@ 9.0.b.d.e.f.g.h.i.j.k.l.@ ",
+" m.n.o.p.q.r.s.t.u.x.y.z.@ A.B.D.F.G.H.I.J.K.L.M.@ ",
+" N.O.P.Q.R.S.T.U.X.W.Y.@ Z.`.`.++@+d.#+$+%+&+@ ",
+" *+=+-+;+>+,+'+~+{+]+^+@ @ @ @ @ /+(+_+:+@ ",
+" <+[+}+|+1+ @ 2+3+4+@ ",
+" 5+6+7+8+ @ 9+0+@ ",
+" a+b+c+ @ d+@ ",
+" . e+ @ @ ",
+" ",
+" "};
+
+class SynchronizerListView : public QListView
+{
+private:
+ Synchronizer *synchronizer;
+ bool isLeft;
+
+public:
+ SynchronizerListView( Synchronizer * sync, QWidget * parent ) : QListView( parent ), synchronizer( sync )
+ {
+ }
+
+ void contentsMouseMoveEvent ( QMouseEvent * e )
+ {
+ isLeft = (( e->state() & ShiftButton ) == 0 );
+ QListView::contentsMouseMoveEvent( e );
+ }
+ void startDrag()
+ {
+ KURL::List urls;
+
+ unsigned ndx = 0;
+ SynchronizerFileItem *currentItem;
+
+ while( ( currentItem = synchronizer->getItemAt( ndx++ ) ) != 0 )
+ {
+ SynchronizerGUI::SyncViewItem *viewItem = (SynchronizerGUI::SyncViewItem *)currentItem->userData();
+
+ if( !viewItem || !viewItem->isSelected() || !viewItem->isVisible() )
+ continue;
+
+ SynchronizerFileItem *item = viewItem->synchronizerItemRef();
+ if( item )
+ {
+ if( isLeft && item->existsInLeft() )
+ {
+ QString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + "/";
+ KURL leftURL = vfs::fromPathOrURL( synchronizer->leftBaseDirectory() + leftDirName + item->leftName() );
+ urls.push_back( leftURL );
+ }
+ else if( !isLeft && item->existsInRight() )
+ {
+ QString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + "/";
+ KURL rightURL = vfs::fromPathOrURL( synchronizer->rightBaseDirectory() + rightDirName + item->rightName() );
+ urls.push_back( rightURL );
+ }
+ }
+ }
+
+ if( urls.count() == 0 )
+ return;
+
+ KURLDrag *d = new KURLDrag(urls, this);
+ d->setPixmap( FL_LOADICON( isLeft ? "2leftarrow" : "2rightarrow" ), QPoint( -7, 0 ) );
+ d->dragCopy();
+ }
+};
+
+SynchronizerGUI::SynchronizerGUI(QWidget* parent, KURL leftURL, KURL rightURL, QStringList selList ) :
+ QDialog( parent, "Krusader::SynchronizerGUI", false, 0 ) {
+ initGUI( parent, QString::null, leftURL, rightURL, selList );
+}
+
+SynchronizerGUI::SynchronizerGUI(QWidget* parent, QString profile ) :
+ QDialog( parent, "Krusader::SynchronizerGUI", false, 0 ) {
+ initGUI( parent, profile, KURL(), KURL(), QStringList() );
+}
+
+void SynchronizerGUI::initGUI(QWidget* /* parent */, QString profileName, KURL leftURL, KURL rightURL, QStringList selList) {
+ selectedFiles = selList;
+ isComparing = wasClosed = wasSync = false;
+ firstResize = true;
+ sizeX = sizeY = -1;
+
+ hasSelectedFiles = ( selectedFiles.count() != 0 );
+
+ if( leftURL.isEmpty() )
+ leftURL = KURL("/");
+ if( rightURL.isEmpty() )
+ rightURL = KURL("/");
+
+ setCaption( i18n("Krusader::Synchronize Directories") );
+ QGridLayout *synchGrid = new QGridLayout( this );
+ synchGrid->setSpacing( 6 );
+ synchGrid->setMargin( 11 );
+
+ folderIcon = QPixmap( ( const char** ) folder_data );
+ fileIcon = QPixmap( ( const char** ) file_data );
+
+ synchronizerTabs = new QTabWidget( this, "synchronizerTabs" );
+
+ /* ============================== Compare groupbox ============================== */
+
+ QWidget *synchronizerTab = new QWidget( this, "syncronizerTab" );
+ QGridLayout *synchronizerGrid = new QGridLayout( synchronizerTab );
+ synchronizerGrid->setSpacing( 6 );
+ synchronizerGrid->setMargin( 11 );
+
+ QGroupBox *compareDirs = new QGroupBox( synchronizerTab, "SyncCompareDirectories" );
+ compareDirs->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed);
+ compareDirs->setTitle( i18n( "Directory Comparison" ) );
+ compareDirs->setColumnLayout(0, Qt::Vertical );
+ compareDirs->layout()->setSpacing( 0 );
+ compareDirs->layout()->setMargin( 0 );
+
+ QGridLayout *grid = new QGridLayout( compareDirs->layout() );
+ grid->setSpacing( 6 );
+ grid->setMargin( 11 );
+
+ leftDirLabel = new QLabel( compareDirs, "leftDirLabel" );
+ leftDirLabel->setAlignment( Qt::AlignHCenter );
+ grid->addWidget( leftDirLabel, 0 ,0 );
+
+ QLabel *filterLabel = new QLabel( compareDirs, "filterLabel" );
+ filterLabel->setText( i18n( "File &Filter:" ) );
+ filterLabel->setAlignment( Qt::AlignHCenter );
+ grid->addWidget( filterLabel, 0 ,1 );
+
+ rightDirLabel = new QLabel( compareDirs, "rightDirLabel" );
+ rightDirLabel->setAlignment( Qt::AlignHCenter );
+ grid->addWidget( rightDirLabel, 0 ,2 );
+
+ krConfig->setGroup("Synchronize");
+
+ leftLocation = new KHistoryCombo(false, compareDirs, "SynchronizerHistoryLeft");
+ leftLocation->setMaxCount(25); // remember 25 items
+ leftLocation->setDuplicatesEnabled( false );
+ leftLocation->setEditable( true );
+ leftLocation->setSizePolicy(QSizePolicy::Ignored,QSizePolicy::Fixed);
+ QStringList list = krConfig->readListEntry("Left Directory History");
+ leftLocation->setHistoryItems(list);
+ KURLRequester *leftUrlReq = new KURLRequester( leftLocation, compareDirs, "LeftDirectory" );
+ leftUrlReq->setURL( vfs::pathOrURL( leftURL ) );
+ leftUrlReq->setMode( KFile::Directory );
+ leftUrlReq->setMinimumWidth( 250 );
+ grid->addWidget( leftUrlReq, 1 ,0 );
+ QWhatsThis::add( leftLocation, i18n( "The left base directory used during the synchronisation process." ) );
+ leftUrlReq->setEnabled( !hasSelectedFiles );
+ leftLocation->setEnabled( !hasSelectedFiles );
+ leftDirLabel->setBuddy( leftLocation );
+
+ fileFilter = new KHistoryCombo(false, compareDirs, "SynchronizerFilter");
+ fileFilter->setMaxCount(25); // remember 25 items
+ fileFilter->setDuplicatesEnabled( false );
+ fileFilter->setMinimumWidth( 100 );
+ fileFilter->setMaximumWidth( 100 );
+ fileFilter->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);
+ list = krConfig->readListEntry("File Filter");
+ fileFilter->setHistoryItems(list);
+ fileFilter->setEditText("*");
+ grid->addWidget( fileFilter, 1 ,1 );
+ filterLabel->setBuddy( fileFilter );
+
+ QString wtFilter = "<p><img src='toolbar|find'></p>" + i18n("<p>The filename filtering criteria is defined here.</p><p>You can make use of wildcards. Multiple patterns are separated by space (means logical OR) and patterns are excluded from the search using the pipe symbol.</p><p>If the pattern is ended with a slash (<code>*pattern*/</code>), that means that pattern relates to recursive search of directories.<ul><li><code>pattern</code> - means to search those files/directories that name is <code>pattern</code>, recursive search goes through all subdirectories independently of the value of <code>pattern</code></li><li><code>pattern/</code> - means to search all files/directories, but recursive search goes through/excludes the directories that name is <code>pattern</code></li></ul><p></p><p>It's allowed to use quotation marks for names that contain space. Filter <code>\"Program&nbsp;Files\"</code> searches out those files/directories that name is <code>Program&nbsp;Files</code>.</p><p>Examples:<ul><code><li>*.o</li><li>*.h *.c\?\?</li><li>*.cpp *.h | *.moc.cpp</li><li>* | CVS/ .svn/</li></code></ul><b>Note</b>: the search term '<code>text</code>' is equivalent to '<code>*text*</code>'.</p>");
+ QWhatsThis::add(fileFilter, wtFilter);
+ QWhatsThis::add(filterLabel, wtFilter);
+
+ rightLocation = new KHistoryCombo(compareDirs, "SynchronizerHistoryRight");
+ rightLocation->setMaxCount(25); // remember 25 items
+ rightLocation->setDuplicatesEnabled( false );
+ rightLocation->setEditable( true );
+ rightLocation->setSizePolicy(QSizePolicy::Ignored,QSizePolicy::Fixed);
+ list = krConfig->readListEntry("Right Directory History");
+ rightLocation->setHistoryItems(list);
+ KURLRequester *rightUrlReq = new KURLRequester( rightLocation, compareDirs, "RightDirectory" );
+ rightUrlReq->setURL( vfs::pathOrURL( rightURL ) );
+ rightUrlReq->setMode( KFile::Directory );
+ rightUrlReq->setMinimumWidth( 250 );
+ grid->addWidget( rightUrlReq, 1 ,2 );
+ QWhatsThis::add( rightLocation, i18n( "The right base directory used during the synchronisation process." ) );
+ rightUrlReq->setEnabled( !hasSelectedFiles );
+ rightLocation->setEnabled( !hasSelectedFiles );
+ rightDirLabel->setBuddy( rightLocation );
+
+ QHBox *optionBox = new QHBox( compareDirs );
+ QGrid *optionGrid = new QGrid( 3, optionBox );
+ cbSubdirs = new QCheckBox( i18n( "Recurse subdirectories" ), optionGrid, "cbSubdirs" );
+ cbSubdirs->setChecked( krConfig->readBoolEntry( "Recurse Subdirectories", _RecurseSubdirs ) );
+ QWhatsThis::add( cbSubdirs, i18n( "Compare not only the base directories but their subdirectories as well." ) );
+ cbSymlinks = new QCheckBox( i18n( "Follow symlinks" ), optionGrid, "cbSymlinks" );
+ cbSymlinks->setChecked( krConfig->readBoolEntry( "Follow Symlinks", _FollowSymlinks ) );
+ cbSymlinks->setEnabled( cbSubdirs->isChecked() );
+ QWhatsThis::add( cbSymlinks, i18n( "Follow symbolic links during the compare process." ) );
+ cbByContent = new QCheckBox( i18n( "Compare by content" ), optionGrid, "cbByContent" );
+ cbByContent->setChecked( krConfig->readBoolEntry( "Compare By Content", _CompareByContent ) );
+ QWhatsThis::add( cbByContent, i18n( "Compare duplicated files with same size by content." ) );
+ cbIgnoreDate = new QCheckBox( i18n( "Ignore Date" ), optionGrid, "cbIgnoreDate" );
+ cbIgnoreDate->setChecked( krConfig->readBoolEntry( "Ignore Date", _IgnoreDate ) );
+ QWhatsThis::add( cbIgnoreDate, i18n( "<p>Ignore date information during the compare process.</p><p><b>Note</b>: useful if the files are located on network filesystems or in archives.</p>" ) );
+ cbAsymmetric = new QCheckBox( i18n( "Asymmetric" ), optionGrid, "cbAsymmetric" );
+ cbAsymmetric->setChecked( krConfig->readBoolEntry( "Asymmetric", _Asymmetric ) );
+ QWhatsThis::add( cbAsymmetric, i18n( "<p><b>Asymmetric mode</b></p><p>The left side is the destination, the right is the source directory. Files existing only in the left directory will be deleted, the other differing ones will be copied from right to left.</p><p><b>Note</b>: useful when updating a directory from a file server.</p>" ) );
+ cbIgnoreCase = new QCheckBox( i18n( "Ignore Case" ), optionGrid, "cbIgnoreCase" );
+ cbIgnoreCase->setChecked( krConfig->readBoolEntry( "Ignore Case", _IgnoreCase ) );
+ QWhatsThis::add( cbIgnoreCase, i18n( "<p>Case insensitive filename compare.</p><p><b>Note</b>: useful when synchronizing Windows filesystems.</p>" ) );
+
+ /* =========================== Show options groupbox ============================= */
+
+ QGroupBox *showOptions = new QGroupBox( optionBox, "SyncOptionBox" );
+ showOptions->setTitle( i18n( "S&how options" ) );
+ showOptions->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed);
+ showOptions->setColumnLayout(0, Qt::Vertical );
+ showOptions->layout()->setSpacing( 0 );
+ showOptions->layout()->setMargin( 0 );
+ QGridLayout *showOptionsLayout = new QGridLayout( showOptions->layout() );
+ showOptionsLayout->setSpacing( 6 );
+ showOptionsLayout->setMargin( 11 );
+
+ QPixmap showLeftToRight( ( const char** ) right_arrow_button_data );
+ QPixmap showEquals ( ( const char** ) equals_button_data );
+ QPixmap showDifferents ( ( const char** ) differents_button_data );
+ QPixmap showRightToLeft( ( const char** ) left_arrow_button_data );
+ QPixmap showDeletable ( ( const char** ) trash_button_data );
+
+ btnLeftToRight = new QPushButton( showOptions, "btnLeftToRight" );
+ btnLeftToRight->setText( "" );
+ btnLeftToRight->setPixmap( showLeftToRight );
+ btnLeftToRight->setToggleButton( true );
+ btnLeftToRight->setOn( krConfig->readBoolEntry( "LeftToRight Button", _BtnLeftToRight ) );
+ btnLeftToRight->setAccel( CTRL + Key_L );
+ QWhatsThis::add( btnLeftToRight, i18n( "Show files marked to <i>Copy from left to right</i> (CTRL+L)." ) );
+ showOptionsLayout->addWidget( btnLeftToRight, 0, 0);
+
+ btnEquals = new QPushButton( showOptions, "btnEquals" );
+ btnEquals->setText( "" );
+ btnEquals->setPixmap( showEquals );
+ btnEquals->setToggleButton( true );
+ btnEquals->setOn( krConfig->readBoolEntry( "Equals Button", _BtnEquals ) );
+ btnEquals->setAccel( CTRL + Key_E );
+ QWhatsThis::add( btnEquals, i18n( "Show files considered to be identical (CTRL+E)." ) );
+ showOptionsLayout->addWidget( btnEquals, 0, 1);
+
+ btnDifferents = new QPushButton( showOptions, "btnDifferents" );
+ btnDifferents->setText( "" );
+ btnDifferents->setPixmap( showDifferents );
+ btnDifferents->setToggleButton( true );
+ btnDifferents->setOn( krConfig->readBoolEntry( "Differents Button", _BtnDifferents ) );
+ btnDifferents->setAccel( CTRL + Key_D );
+ QWhatsThis::add( btnDifferents, i18n( "Show excluded files (CTRL+D)." ) );
+ showOptionsLayout->addWidget( btnDifferents, 0, 2);
+
+ btnRightToLeft = new QPushButton( showOptions, "btnRightToLeft" );
+ btnRightToLeft->setText( "" );
+ btnRightToLeft->setPixmap( showRightToLeft );
+ btnRightToLeft->setToggleButton( true );
+ btnRightToLeft->setOn( krConfig->readBoolEntry( "RightToLeft Button", _BtnRightToLeft ) );
+ btnRightToLeft->setAccel( CTRL + Key_R );
+ QWhatsThis::add( btnRightToLeft, i18n( "Show files marked to <i>Copy from right to left</i> (CTRL+R)." ) );
+ showOptionsLayout->addWidget( btnRightToLeft, 0, 3);
+
+ btnDeletable = new QPushButton( showOptions, "btnDeletable" );
+ btnDeletable->setText( "" );
+ btnDeletable->setPixmap( showDeletable );
+ btnDeletable->setToggleButton( true );
+ btnDeletable->setOn( krConfig->readBoolEntry( "Deletable Button", _BtnDeletable ) );
+ btnDeletable->setAccel( CTRL + Key_T );
+ QWhatsThis::add( btnDeletable, i18n( "Show files marked to delete. (CTRL+T)" ) );
+ showOptionsLayout->addWidget( btnDeletable, 0, 4);
+
+ btnDuplicates = new QPushButton( showOptions, "btnDuplicates" );
+ btnDuplicates->setText( i18n("Duplicates") );
+ btnDuplicates->setMinimumHeight( btnLeftToRight->height() );
+ btnDuplicates->setToggleButton( true );
+ btnDuplicates->setOn( krConfig->readBoolEntry( "Duplicates Button", _BtnDuplicates ) );
+ QWhatsThis::add( btnDuplicates, i18n( "Show files that exist on both sides." ) );
+ showOptionsLayout->addWidget( btnDuplicates, 0, 5);
+
+ btnSingles = new QPushButton( showOptions, "btnSingles" );
+ btnSingles->setText( i18n("Singles") );
+ btnSingles->setMinimumHeight( btnLeftToRight->height() );
+ btnSingles->setToggleButton( true );
+ btnSingles->setOn( krConfig->readBoolEntry( "Singles Button", _BtnSingles ) );
+ QWhatsThis::add( btnSingles, i18n( "Show files that exist on one side only." ) );
+ showOptionsLayout->addWidget( btnSingles, 0, 6);
+
+ grid->addMultiCellWidget( optionBox, 2, 2, 0, 2 );
+
+ synchronizerGrid->addWidget( compareDirs, 0, 0 );
+
+ /* ========================= Synchronization list view ========================== */
+ syncList=new SynchronizerListView( &synchronizer, synchronizerTab ); // create the main container
+ QWhatsThis::add( syncList, i18n( "The compare results of the synchronizer (CTRL+M)." ) );
+
+ krConfig->setGroup("Look&Feel");
+ syncList->setFont(krConfig->readFontEntry("Filelist Font",_FilelistFont));
+
+ syncList->setAllColumnsShowFocus(true);
+ syncList->setMultiSelection(true);
+ syncList->setSelectionMode(QListView::Extended);
+ syncList->setVScrollBarMode(QScrollView::Auto);
+ syncList->setHScrollBarMode(QScrollView::Auto);
+ syncList->setShowSortIndicator(false);
+ syncList->setSorting(-1);
+ syncList->setRootIsDecorated( true );
+ syncList->setTreeStepSize( 10 );
+ int i=QFontMetrics(syncList->font()).width("W");
+ int j=QFontMetrics(syncList->font()).width("0");
+ j=(i>j ? i : j);
+ int typeWidth = j*7/2;
+
+ krConfig->setGroup("Synchronize");
+
+ int leftNameWidth = krConfig->readNumEntry("Left Name Width", 9*typeWidth/2 );
+ int leftSizeWidth = krConfig->readNumEntry("Left Size Width", 2*typeWidth );
+ int leftDateWidth = krConfig->readNumEntry("Left Date Width", 3*typeWidth );
+ int taskTypeWidth = krConfig->readNumEntry("Task Type Width", typeWidth );
+ int rightDateWidth = krConfig->readNumEntry("Right Date Width", 3*typeWidth );
+ int rightSizeWidth = krConfig->readNumEntry("Right Size Width", 2*typeWidth );
+ int rightNameWidth = krConfig->readNumEntry("Right Name Width", 4*typeWidth );
+
+ syncList->addColumn(i18n("Name"),leftNameWidth);
+ syncList->addColumn(i18n("Size"),leftSizeWidth);
+ syncList->addColumn(i18n("Date"),leftDateWidth);
+ syncList->addColumn(i18n("<=>") ,taskTypeWidth);
+ syncList->addColumn(i18n("Date"),rightDateWidth);
+ syncList->addColumn(i18n("Size"),rightSizeWidth);
+ syncList->addColumn(i18n("Name"),rightNameWidth);
+ syncList->setColumnWidthMode(0,QListView::Manual);
+ syncList->setColumnWidthMode(1,QListView::Manual);
+ syncList->setColumnWidthMode(2,QListView::Manual);
+ syncList->setColumnWidthMode(3,QListView::Manual);
+ syncList->setColumnWidthMode(4,QListView::Manual);
+ syncList->setColumnWidthMode(5,QListView::Manual);
+ syncList->setColumnWidthMode(6,QListView::Manual);
+ syncList->setColumnAlignment(1, Qt::AlignRight );
+ syncList->setColumnAlignment(3, Qt::AlignHCenter );
+ syncList->setColumnAlignment(5, Qt::AlignRight );
+
+ syncList->header()->setStretchEnabled( true, 0 );
+
+ synchronizerGrid->addWidget(syncList,1,0);
+
+ synchronizerTabs->insertTab( synchronizerTab, i18n( "&Synchronizer" ) );
+ synchGrid->addWidget( synchronizerTabs, 0, 0 );
+
+ filterTabs = FilterTabs::addTo( synchronizerTabs, FilterTabs::HasDontSearchIn );
+ generalFilter = (GeneralFilter *)filterTabs->get( "GeneralFilter" );
+ generalFilter->searchFor->setEditText( fileFilter->currentText() );
+ generalFilter->searchForCase->setChecked( true );
+
+ // creating the time shift, equality threshold, hidden files options
+
+ QGroupBox *optionsGroup = new QGroupBox( generalFilter, "options" );
+ optionsGroup->setTitle( i18n( "&Options" ) );
+ optionsGroup->setColumnLayout(0, Qt::Vertical );
+ optionsGroup->layout()->setSpacing( 0 );
+ optionsGroup->layout()->setMargin( 0 );
+ QGridLayout *optionsLayout = new QGridLayout( optionsGroup->layout() );
+ optionsLayout->setAlignment( Qt::AlignTop );
+ optionsLayout->setSpacing( 6 );
+ optionsLayout->setMargin( 11 );
+
+ QLabel * parallelThreadsLabel = new QLabel( i18n( "Parallel threads:" ), optionsGroup );
+ optionsLayout->addWidget( parallelThreadsLabel, 0, 0 );
+ parallelThreadsSpinBox = new QSpinBox( optionsGroup, "parallelThreadsSpinBox" );
+ parallelThreadsSpinBox->setMinValue( 1 );
+ parallelThreadsSpinBox->setMaxValue( 15 );
+ krConfig->setGroup( "Synchronize" );
+ int parThreads = krConfig->readNumEntry( "Parallel Threads", 1 );
+ parallelThreadsSpinBox->setValue( parThreads );
+
+ optionsLayout->addWidget( parallelThreadsSpinBox, 0, 1 );
+
+ QLabel * equalityLabel = new QLabel( i18n( "Equality threshold:" ), optionsGroup );
+ optionsLayout->addWidget( equalityLabel, 1, 0 );
+
+ equalitySpinBox = new QSpinBox( optionsGroup, "equalitySpinBox" );
+ equalitySpinBox->setMaxValue( 9999 );
+ optionsLayout->addWidget( equalitySpinBox, 1, 1 );
+
+ equalityUnitCombo = new QComboBox( optionsGroup, "equalityUnitCombo" );
+ equalityUnitCombo->insertItem( i18n( "sec" ) );
+ equalityUnitCombo->insertItem( i18n( "min" ) );
+ equalityUnitCombo->insertItem( i18n( "hour" ) );
+ equalityUnitCombo->insertItem( i18n( "day" ) );
+ optionsLayout->addWidget( equalityUnitCombo, 1, 2 );
+
+ QLabel * timeShiftLabel = new QLabel( i18n( "Time shift (right-left):" ), optionsGroup );
+ optionsLayout->addWidget( timeShiftLabel, 2, 0 );
+
+ timeShiftSpinBox = new QSpinBox( optionsGroup, "timeShiftSpinBox" );
+ timeShiftSpinBox->setMinValue( -9999 );
+ timeShiftSpinBox->setMaxValue( 9999 );
+ optionsLayout->addWidget( timeShiftSpinBox, 2, 1 );
+
+ timeShiftUnitCombo = new QComboBox( optionsGroup, "timeShiftUnitCombo" );
+ timeShiftUnitCombo->insertItem( i18n( "sec" ) );
+ timeShiftUnitCombo->insertItem( i18n( "min" ) );
+ timeShiftUnitCombo->insertItem( i18n( "hour" ) );
+ timeShiftUnitCombo->insertItem( i18n( "day" ) );
+ optionsLayout->addWidget( timeShiftUnitCombo, 2, 2 );
+
+ QFrame *line = new QFrame( optionsGroup );
+ line->setFrameStyle( QFrame::HLine | QFrame::Sunken );
+ optionsLayout->addMultiCellWidget( line, 3, 3, 0, 2 );
+
+ ignoreHiddenFilesCB = new QCheckBox( i18n( "Ignore hidden files" ), optionsGroup );
+ optionsLayout->addMultiCellWidget( ignoreHiddenFilesCB, 4, 4, 0, 2 );
+
+ generalFilter->middleLayout->addWidget( optionsGroup );
+
+
+ /* ================================== Buttons =================================== */
+
+ QHBoxLayout *buttons = new QHBoxLayout;
+ buttons->setSpacing( 6 );
+ buttons->setMargin( 0 );
+
+ profileManager = new ProfileManager( "SynchronizerProfile", this, "profileManager" );
+ profileManager->setAccel( CTRL + Key_P );
+ QWhatsThis::add( profileManager, i18n( "Profile manager (Ctrl+P)." ) );
+ buttons->addWidget( profileManager );
+
+ QPixmap swapSides( ( const char** ) swap_sides_data );
+ btnSwapSides = new QPushButton( this, "btnSwapSides" );
+ btnSwapSides->setPixmap( swapSides );
+ btnSwapSides->setAccel( CTRL + Key_S );
+ QWhatsThis::add( btnSwapSides, i18n( "Swap sides (Ctrl+S)." ) );
+ buttons->addWidget( btnSwapSides );
+
+ statusLabel = new QLabel( this, "statusLabel" );
+ buttons->addWidget( statusLabel );
+
+ QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ buttons->addItem( spacer );
+
+ btnCompareDirs = new QPushButton( this, "btnCompareDirs" );
+ btnCompareDirs->setText( i18n( "Compare" ) );
+ btnCompareDirs->setDefault(true);
+ buttons->addWidget( btnCompareDirs );
+
+ krConfig->setGroup("Synchronize");
+ btnScrollResults = new QPushButton( this, "btnSynchronize" );
+ btnScrollResults->setToggleButton( true );
+ btnScrollResults->setOn( krConfig->readBoolEntry( "Scroll Results", _ScrollResults ) );
+ btnScrollResults->hide();
+ if( btnScrollResults->isOn() )
+ btnScrollResults->setText( i18n( "Quiet" ) );
+ else
+ btnScrollResults->setText( i18n( "Scroll Results" ) );
+ buttons->addWidget( btnScrollResults );
+
+ btnStopComparing = new QPushButton( this, "btnStopComparing" );
+ btnStopComparing->setText( i18n( "Stop" ) );
+ btnStopComparing->setEnabled(false);
+ buttons->addWidget( btnStopComparing );
+
+ btnFeedToListBox = new QPushButton( this, "btnFeedToListBox" );
+ btnFeedToListBox->setText( i18n( "Feed to listbox" ) );
+ btnFeedToListBox->setEnabled(false);
+ btnFeedToListBox->hide();
+ buttons->addWidget( btnFeedToListBox );
+
+ btnSynchronize = new QPushButton( this, "btnSynchronize" );
+ btnSynchronize->setText( i18n( "Synchronize" ) );
+ btnSynchronize->setEnabled(false);
+ buttons->addWidget( btnSynchronize );
+
+ QPushButton *btnCloseSync = new QPushButton( this, "btnCloseSync" );
+ btnCloseSync->setText( i18n( "Close" ) );
+ buttons->addWidget( btnCloseSync );
+
+ synchGrid->addLayout( buttons, 1, 0 );
+
+ /* =============================== Connect table ================================ */
+
+ connect( syncList,SIGNAL(rightButtonPressed(QListViewItem *, const QPoint &, int)),
+ this, SLOT(rightMouseClicked(QListViewItem *)));
+ connect( syncList,SIGNAL(doubleClicked(QListViewItem *, const QPoint &, int)),
+ this, SLOT(doubleClicked(QListViewItem *)));
+
+ connect( syncList,SIGNAL(contextMenuRequested(QListViewItem *, const QPoint &, int)),
+ this, SLOT(rightMouseClicked(QListViewItem *)));
+
+ connect( profileManager, SIGNAL( loadFromProfile( QString ) ), this, SLOT( loadFromProfile( QString ) ) );
+ connect( profileManager, SIGNAL( saveToProfile( QString ) ), this, SLOT( saveToProfile( QString ) ) );
+
+ connect( btnSwapSides, SIGNAL( clicked() ), this, SLOT( swapSides() ) );
+ connect( btnCompareDirs, SIGNAL( clicked() ), this, SLOT( compare() ) );
+ connect( btnStopComparing, SIGNAL( clicked() ), this, SLOT( stop() ) );
+ connect( btnFeedToListBox, SIGNAL( clicked() ), this, SLOT( feedToListBox() ) );
+ connect( btnSynchronize, SIGNAL( clicked() ), this, SLOT( synchronize() ) );
+ connect( btnScrollResults, SIGNAL( toggled(bool) ), this, SLOT( setScrolling(bool) ) );
+ connect( btnCloseSync, SIGNAL( clicked() ), this, SLOT( closeDialog() ) );
+
+ connect( cbSubdirs, SIGNAL( toggled(bool) ), this, SLOT( subdirsChecked( bool ) ) );
+ connect( cbAsymmetric, SIGNAL( toggled(bool) ), this, SLOT( setPanelLabels() ) );
+
+ connect( &synchronizer, SIGNAL( comparedFileData( SynchronizerFileItem * ) ), this,
+ SLOT( addFile( SynchronizerFileItem * ) ) );
+ connect( &synchronizer, SIGNAL( markChanged( SynchronizerFileItem *, bool ) ), this,
+ SLOT( markChanged( SynchronizerFileItem *, bool ) ) );
+ connect( &synchronizer, SIGNAL( statusInfo( QString ) ), this, SLOT( statusInfo( QString ) ) );
+
+ connect( btnLeftToRight, SIGNAL( toggled(bool) ), this, SLOT( refresh() ) );
+ connect( btnEquals, SIGNAL( toggled(bool) ), this, SLOT( refresh() ) );
+ connect( btnDifferents, SIGNAL( toggled(bool) ), this, SLOT( refresh() ) );
+ connect( btnRightToLeft, SIGNAL( toggled(bool) ), this, SLOT( refresh() ) );
+ connect( btnDeletable, SIGNAL( toggled(bool) ), this, SLOT( refresh() ) );
+ connect( btnDuplicates, SIGNAL( toggled(bool) ), this, SLOT( refresh() ) );
+ connect( btnSingles, SIGNAL( toggled(bool) ), this, SLOT( refresh() ) );
+
+ connect( fileFilter, SIGNAL( textChanged( const QString & ) ), this, SLOT( connectFilters( const QString & ) ) );
+ connect( generalFilter->searchFor, SIGNAL( textChanged( const QString & ) ), this, SLOT( connectFilters( const QString & ) ) );
+ connect( generalFilter->searchFor, SIGNAL( textChanged( const QString & ) ), this, SLOT( setCompletion() ) );
+ connect( generalFilter->dontSearchIn, SIGNAL( checkValidity( QString &, QString & ) ),
+ this, SLOT( checkExcludeURLValidity( QString &, QString & ) ) );
+
+ connect( profileManager, SIGNAL( loadFromProfile( QString ) ), filterTabs, SLOT( loadFromProfile( QString ) ) );
+ connect( profileManager, SIGNAL( saveToProfile( QString ) ), filterTabs, SLOT( saveToProfile( QString ) ) );
+
+ setPanelLabels();
+ setCompletion();
+
+ /* =============================== Loading the colors ================================ */
+
+ krConfig->setGroup("Colors");
+
+ DECLARE_COLOR_NAME_ARRAY;
+ DECLARE_BACKGROUND_DFLTS;
+ DECLARE_FOREGROUND_DFLTS;
+
+ for( int clr = 0; clr != TT_MAX; clr ++ ) {
+ QString foreEntry = QString( "Synchronizer " ) + COLOR_NAMES[ clr ] + QString( " Foreground" );
+ QString bckgEntry = QString( "Synchronizer " ) + COLOR_NAMES[ clr ] + QString( " Background" );
+
+ if( krConfig->readEntry( foreEntry ) == "KDE default" )
+ foreGrounds[ clr ] = QColor();
+ else
+ foreGrounds[ clr ] = krConfig->readColorEntry( foreEntry, &FORE_DFLTS[ clr ] );
+
+ if( krConfig->readEntry( bckgEntry ) == "KDE default" )
+ backGrounds[ clr ] = QColor();
+ else
+ backGrounds[ clr ] = krConfig->readColorEntry( bckgEntry, &BCKG_DFLTS[ clr ] );
+ }
+ if( backGrounds[ TT_EQUALS ].isValid() )
+ syncList->setPaletteBackgroundColor( backGrounds[ TT_EQUALS ] );
+
+ krConfig->setGroup("Synchronize");
+ int sx = krConfig->readNumEntry( "Window Width", -1 );
+ int sy = krConfig->readNumEntry( "Window Height", -1 );
+
+ if( sx != -1 && sy != -1 )
+ resize( sx, sy );
+
+ if( krConfig->readBoolEntry( "Window Maximized", false ) )
+ showMaximized();
+ else
+ show();
+
+ if( !profileName.isNull() )
+ profileManager->loadProfile( profileName );
+
+ synchronizer.setParentWidget( this );
+}
+
+SynchronizerGUI::~SynchronizerGUI()
+{
+ syncList->clear(); // for sanity: deletes the references to the synchronizer list
+}
+
+void SynchronizerGUI::setPanelLabels()
+{
+ if( hasSelectedFiles && cbAsymmetric->isChecked() )
+ {
+ leftDirLabel->setText( i18n( "Selected files from targ&et directory:" ) );
+ rightDirLabel->setText( i18n( "Selected files from sou&rce directory:" ) );
+ }
+ else if( hasSelectedFiles && !cbAsymmetric->isChecked() )
+ {
+ leftDirLabel->setText( i18n( "Selected files from &left directory:" ) );
+ rightDirLabel->setText( i18n( "Selected files from &right directory:" ) );
+ }
+ else if( cbAsymmetric->isChecked() )
+ {
+ leftDirLabel->setText( i18n( "Targ&et directory:" ) );
+ rightDirLabel->setText( i18n( "Sou&rce directory:" ) );
+ }
+ else
+ {
+ leftDirLabel->setText( i18n( "&Left directory:" ) );
+ rightDirLabel->setText( i18n( "&Right directory:" ) );
+ }
+}
+
+void SynchronizerGUI::setCompletion()
+{
+ generalFilter->dontSearchIn->setCompletionDir( rightLocation->currentText() );
+}
+
+void SynchronizerGUI::checkExcludeURLValidity( QString &text, QString &error )
+{
+ KURL url = vfs::fromPathOrURL( text );
+ if( KURL::isRelativeURL( url.url() ) )
+ return;
+
+ QString leftBase = leftLocation->currentText();
+ if( !leftBase.endsWith( "/" ) )
+ leftBase += "/";
+ KURL leftBaseURL = vfs::fromPathOrURL( leftBase );
+ if( leftBaseURL.isParentOf( url ) && !url.isParentOf( leftBaseURL) )
+ {
+ text = KURL::relativeURL( leftBaseURL, url );
+ return;
+ }
+
+ QString rightBase = rightLocation->currentText();
+ if( !rightBase.endsWith( "/" ) )
+ rightBase += "/";
+ KURL rightBaseURL = vfs::fromPathOrURL( rightBase );
+ if( rightBaseURL.isParentOf( url ) && !url.isParentOf( rightBaseURL ) )
+ {
+ text = KURL::relativeURL( rightBaseURL, url );
+ return;
+ }
+
+ error = i18n("URL must be the descendant of either the left or the right base URL!");
+}
+
+void SynchronizerGUI::doubleClicked(QListViewItem *itemIn)
+{
+ if (!itemIn)
+ return;
+
+ SyncViewItem *syncItem = (SyncViewItem *)itemIn;
+ SynchronizerFileItem *item = syncItem->synchronizerItemRef();
+ if( item && item->existsInLeft() && item->existsInRight() && !item->isDir() )
+ {
+ QString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + "/";
+ QString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + "/";
+ KURL leftURL = vfs::fromPathOrURL( synchronizer.leftBaseDirectory() + leftDirName + item->leftName() );
+ KURL rightURL = vfs::fromPathOrURL( synchronizer.rightBaseDirectory() + rightDirName + item->rightName() );
+
+ SLOTS->compareContent( leftURL, rightURL );
+ }
+}
+
+void SynchronizerGUI::rightMouseClicked(QListViewItem *itemIn)
+{
+ // these are the values that will exist in the menu
+ #define EXCLUDE_ID 90
+ #define RESTORE_ID 91
+ #define COPY_TO_LEFT_ID 92
+ #define COPY_TO_RIGHT_ID 93
+ #define REVERSE_DIR_ID 94
+ #define DELETE_ID 95
+ #define VIEW_LEFT_FILE_ID 96
+ #define VIEW_RIGHT_FILE_ID 97
+ #define COMPARE_FILES_ID 98
+ #define SELECT_ITEMS_ID 99
+ #define DESELECT_ITEMS_ID 100
+ #define INVERT_SELECTION_ID 101
+ #define SYNCH_WITH_KGET_ID 102
+ #define COPY_CLPBD_LEFT_ID 103
+ #define COPY_CLPBD_RIGHT_ID 104
+ //////////////////////////////////////////////////////////
+ if (!itemIn)
+ return;
+
+ SyncViewItem *syncItem = (SyncViewItem *)itemIn;
+ if( syncItem == 0 )
+ return;
+
+ SynchronizerFileItem *item = syncItem->synchronizerItemRef();
+
+ bool isDuplicate = item->existsInLeft() && item->existsInRight();
+ bool isDir = item->isDir();
+ QString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + "/";
+ QString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + "/";
+
+ KURL leftURL = vfs::fromPathOrURL( synchronizer.leftBaseDirectory() + leftDirName + item->leftName() );
+ KURL rightURL = vfs::fromPathOrURL( synchronizer.rightBaseDirectory() + rightDirName + item->rightName() );
+
+ // create the menu
+ KPopupMenu popup;
+ popup.insertTitle(i18n("Synchronize Directories"));
+
+ popup.insertItem(i18n("E&xclude"),EXCLUDE_ID);
+ popup.setItemEnabled(EXCLUDE_ID, true );
+ popup.insertItem(i18n("Restore ori&ginal operation"),RESTORE_ID);
+ popup.setItemEnabled(RESTORE_ID, true );
+ popup.insertItem(i18n("Re&verse direction"),REVERSE_DIR_ID);
+ popup.setItemEnabled(REVERSE_DIR_ID, true );
+ popup.insertItem(i18n("Copy from &right to left"),COPY_TO_LEFT_ID);
+ popup.setItemEnabled(COPY_TO_LEFT_ID, true );
+ popup.insertItem(i18n("Copy from &left to right"),COPY_TO_RIGHT_ID);
+ popup.setItemEnabled(COPY_TO_RIGHT_ID, true );
+ popup.insertItem(i18n("&Delete (left single)"),DELETE_ID);
+ popup.setItemEnabled(DELETE_ID, true );
+
+ popup.insertSeparator();
+
+ popup.insertItem(i18n("V&iew left file"),VIEW_LEFT_FILE_ID);
+ popup.setItemEnabled(VIEW_LEFT_FILE_ID, !isDir && item->existsInLeft() );
+ popup.insertItem(i18n("Vi&ew right file"),VIEW_RIGHT_FILE_ID);
+ popup.setItemEnabled(VIEW_RIGHT_FILE_ID, !isDir && item->existsInRight() );
+ popup.insertItem(i18n("&Compare Files"),COMPARE_FILES_ID);
+ popup.setItemEnabled(COMPARE_FILES_ID, !isDir && isDuplicate );
+
+ popup.insertSeparator();
+
+ popup.insertItem(i18n("C&opy selected to clipboard (left)"),COPY_CLPBD_LEFT_ID);
+ popup.insertItem(i18n("Co&py selected to clipboard (right)"),COPY_CLPBD_RIGHT_ID);
+
+ popup.insertSeparator();
+
+ popup.insertItem(i18n("&Select items"),SELECT_ITEMS_ID);
+ popup.setItemEnabled(SELECT_ITEMS_ID, true );
+ popup.insertItem(i18n("Deselec&t items"),DESELECT_ITEMS_ID);
+ popup.setItemEnabled(DESELECT_ITEMS_ID, true );
+ popup.insertItem(i18n("I&nvert selection"),INVERT_SELECTION_ID);
+ popup.setItemEnabled(INVERT_SELECTION_ID, true );
+
+ KURL leftBDir = vfs::fromPathOrURL( synchronizer.leftBaseDirectory() );
+ KURL rightBDir = vfs::fromPathOrURL( synchronizer.rightBaseDirectory() );
+
+ if( KrServices::cmdExist( "kget" ) &&
+ ( ( !leftBDir.isLocalFile() && rightBDir.isLocalFile() && btnLeftToRight->isOn() ) ||
+ ( leftBDir.isLocalFile() && !rightBDir.isLocalFile() && btnRightToLeft->isOn() ) ) )
+ {
+ popup.insertSeparator();
+ popup.insertItem(i18n("Synchronize with &KGet"),SYNCH_WITH_KGET_ID);
+ popup.setItemEnabled(SYNCH_WITH_KGET_ID, true );
+ }
+
+ int result=popup.exec(QCursor::pos());
+
+ // check out the user's option
+ switch (result)
+ {
+ case EXCLUDE_ID:
+ case RESTORE_ID:
+ case COPY_TO_LEFT_ID:
+ case COPY_TO_RIGHT_ID:
+ case REVERSE_DIR_ID:
+ case DELETE_ID:
+ {
+ unsigned ndx = 0;
+ SynchronizerFileItem *currentItem;
+
+ while( ( currentItem = synchronizer.getItemAt( ndx++ ) ) != 0 )
+ {
+ SyncViewItem *viewItem = (SyncViewItem *)currentItem->userData();
+
+ if( !viewItem || !viewItem->isSelected() || !viewItem->isVisible() )
+ continue;
+
+ switch( result )
+ {
+ case EXCLUDE_ID:
+ synchronizer.exclude( viewItem->synchronizerItemRef() );
+ break;
+ case RESTORE_ID:
+ synchronizer.restore( viewItem->synchronizerItemRef() );
+ break;
+ case REVERSE_DIR_ID:
+ synchronizer.reverseDirection( viewItem->synchronizerItemRef() );
+ break;
+ case COPY_TO_LEFT_ID:
+ synchronizer.copyToLeft( viewItem->synchronizerItemRef() );
+ break;
+ case COPY_TO_RIGHT_ID:
+ synchronizer.copyToRight( viewItem->synchronizerItemRef() );
+ break;
+ case DELETE_ID:
+ synchronizer.deleteLeft( viewItem->synchronizerItemRef() );
+ break;
+ }
+ }
+
+ refresh();
+ }
+ break;
+ case VIEW_LEFT_FILE_ID:
+ KrViewer::view( leftURL, this ); // view the file
+ break;
+ case VIEW_RIGHT_FILE_ID:
+ KrViewer::view( rightURL, this ); // view the file
+ break;
+ case COMPARE_FILES_ID:
+ SLOTS->compareContent( leftURL, rightURL );
+ break;
+ case SELECT_ITEMS_ID:
+ case DESELECT_ITEMS_ID:
+ {
+ KRQuery query = KRSpWidgets::getMask( ( result == SELECT_ITEMS_ID ? i18n("Select items") :
+ i18n( "Deselect items" ) ), true );
+ if( query.isNull() )
+ break;
+
+ unsigned ndx = 0;
+ SynchronizerFileItem *currentItem;
+
+ while( ( currentItem = synchronizer.getItemAt( ndx++ ) ) != 0 )
+ {
+ SyncViewItem *viewItem = (SyncViewItem *)currentItem->userData();
+
+ if( !viewItem || !viewItem->isVisible() )
+ continue;
+
+ if( query.match( currentItem->leftName() ) ||
+ query.match( currentItem->rightName() ) )
+ syncList->setSelected( viewItem, result == SELECT_ITEMS_ID );
+ }
+ }
+ break;
+ case INVERT_SELECTION_ID:
+ syncList->invertSelection();
+ break;
+ case SYNCH_WITH_KGET_ID:
+ synchronizer.synchronizeWithKGet();
+ closeDialog();
+ break;
+ case COPY_CLPBD_LEFT_ID:
+ copyToClipboard( true );
+ break;
+ case COPY_CLPBD_RIGHT_ID:
+ copyToClipboard( false );
+ break;
+ case -1 : return; // the user clicked outside of the menu
+ }
+}
+
+void SynchronizerGUI::closeDialog()
+{
+ if( isComparing )
+ {
+ stop();
+ wasClosed = true;
+ return;
+ }
+
+ QStringList list = leftLocation->historyItems();
+ krConfig->setGroup("Synchronize");
+ krConfig->writeEntry("Left Directory History", list);
+ list = rightLocation->historyItems();
+ krConfig->writeEntry("Right Directory History", list);
+ list = fileFilter->historyItems();
+ krConfig->writeEntry("File Filter", list);
+
+ krConfig->writeEntry("Recurse Subdirectories", cbSubdirs->isChecked() );
+ krConfig->writeEntry("Follow Symlinks", cbSymlinks->isChecked() );
+ krConfig->writeEntry("Compare By Content", cbByContent->isChecked() );
+ krConfig->writeEntry("Ignore Date", cbIgnoreDate->isChecked() );
+ krConfig->writeEntry("Asymmetric", cbAsymmetric->isChecked() );
+ krConfig->writeEntry("Ignore Case", cbIgnoreCase->isChecked() );
+ krConfig->writeEntry("LeftToRight Button", btnLeftToRight->isOn() );
+ krConfig->writeEntry("Equals Button", btnEquals->isOn() );
+ krConfig->writeEntry("Differents Button", btnDifferents->isOn() );
+ krConfig->writeEntry("RightToLeft Button", btnRightToLeft->isOn() );
+ krConfig->writeEntry("Deletable Button", btnDeletable->isOn() );
+ krConfig->writeEntry("Duplicates Button", btnDuplicates->isOn() );
+ krConfig->writeEntry("Singles Button", btnSingles->isOn() );
+
+ krConfig->writeEntry("Scroll Results", btnScrollResults->isOn() );
+
+ krConfig->writeEntry("Parallel Threads", parallelThreadsSpinBox->value() );
+
+ krConfig->writeEntry("Window Width", sizeX );
+ krConfig->writeEntry("Window Height", sizeY );
+ krConfig->writeEntry("Window Maximized", isMaximized() );
+
+ krConfig->writeEntry("Left Name Width", syncList->columnWidth( 0 ) );
+ krConfig->writeEntry("Left Size Width", syncList->columnWidth( 1 ) );
+ krConfig->writeEntry("Left Date Width", syncList->columnWidth( 2 ) );
+ krConfig->writeEntry("Task Type Width", syncList->columnWidth( 3 ) );
+ krConfig->writeEntry("Right Date Width", syncList->columnWidth( 4 ) );
+ krConfig->writeEntry("Right Size Width", syncList->columnWidth( 5 ) );
+ krConfig->writeEntry("Right Name Width", syncList->columnWidth( 6 ) );
+
+ QDialog::reject();
+
+ this->deleteLater();
+
+ if( wasSync )
+ {
+ ListPanel *p=ACTIVE_PANEL;
+ MAIN_VIEW->left->func->refresh();
+ MAIN_VIEW->right->func->refresh();
+ p->slotFocusOnMe();
+ }
+}
+
+void SynchronizerGUI::compare()
+{
+ KRQuery query;
+
+ if( !filterTabs->fillQuery( &query ) )
+ return;
+
+ query.setNameFilter( fileFilter->currentText(), query.isCaseSensitive() );
+ synchronizerTabs->setCurrentPage(0);
+
+ syncList->clear();
+ lastItem = 0;
+
+ leftLocation->addToHistory(leftLocation->currentText());
+ rightLocation->addToHistory(rightLocation->currentText());
+ fileFilter->addToHistory(fileFilter->currentText());
+
+ setMarkFlags();
+
+ btnCompareDirs->setEnabled( false );
+ profileManager->setEnabled( false );
+ btnSwapSides->setEnabled( false );
+ btnStopComparing->setEnabled( isComparing = true );
+ btnStopComparing->show();
+ btnFeedToListBox->setEnabled( false );
+ btnFeedToListBox->hide();
+ btnSynchronize->setEnabled( false );
+ btnCompareDirs->hide();
+ btnScrollResults->show();
+ disableMarkButtons();
+
+ int fileCount = synchronizer.compare(leftLocation->currentText(), rightLocation->currentText(),
+ &query, cbSubdirs->isChecked(), cbSymlinks->isChecked(),
+ cbIgnoreDate->isChecked(), cbAsymmetric->isChecked(), cbByContent->isChecked(),
+ cbIgnoreCase->isChecked(), btnScrollResults->isOn(), selectedFiles,
+ convertToSeconds( equalitySpinBox->value(), equalityUnitCombo->currentItem() ),
+ convertToSeconds( timeShiftSpinBox->value(), timeShiftUnitCombo->currentItem() ),
+ parallelThreadsSpinBox->value(), ignoreHiddenFilesCB->isChecked() );
+ enableMarkButtons();
+ btnStopComparing->setEnabled( isComparing = false );
+ btnStopComparing->hide();
+ btnFeedToListBox->show();
+ btnCompareDirs->setEnabled( true );
+ profileManager->setEnabled( true );
+ btnSwapSides->setEnabled( true );
+ btnCompareDirs->show();
+ btnScrollResults->hide();
+ if( fileCount ) {
+ btnSynchronize->setEnabled( true );
+ btnFeedToListBox->setEnabled( true );
+ }
+
+ syncList->setFocus();
+
+ if( wasClosed )
+ closeDialog();
+}
+
+void SynchronizerGUI::stop()
+{
+ synchronizer.stop();
+}
+
+void SynchronizerGUI::feedToListBox()
+{
+ FeedToListBoxDialog listBox( this, "feedToListBoxDialog", &synchronizer, syncList, btnEquals->isOn() );
+ if( listBox.isAccepted() )
+ closeDialog();
+}
+
+void SynchronizerGUI::reject()
+{
+ closeDialog();
+}
+
+void SynchronizerGUI::addFile( SynchronizerFileItem *item )
+{
+ QString leftName="", rightName="", leftDate="", rightDate="", leftSize="", rightSize="";
+ bool isDir = item->isDir();
+
+ QColor textColor = foreGrounds[ item->task() ];
+ QColor baseColor = backGrounds[ item->task() ];
+
+ if( item->existsInLeft() )
+ {
+ leftName = item->leftName();
+ leftSize = isDir ? i18n("<DIR>")+" " : KRpermHandler::parseSize( item->leftSize() );
+ leftDate = SynchronizerGUI::convertTime( item->leftDate() );
+ }
+
+ if( item->existsInRight() )
+ {
+ rightName = item->rightName();
+ rightSize = isDir ? i18n("<DIR>")+" " : KRpermHandler::parseSize( item->rightSize() );
+ rightDate = SynchronizerGUI::convertTime( item->rightDate() );
+ }
+
+ SyncViewItem *listItem = 0;
+ SyncViewItem *dirItem;
+
+ if( item->parent() == 0 )
+ {
+ listItem = new SyncViewItem(item, textColor, baseColor, syncList, lastItem, leftName, leftSize,
+ leftDate, Synchronizer::getTaskTypeName( item->task() ), rightDate,
+ rightSize, rightName );
+ lastItem = listItem;
+ }
+ else
+ {
+ dirItem = (SyncViewItem *)item->parent()->userData();
+ if( dirItem )
+ {
+ dirItem->setOpen( true );
+ listItem = new SyncViewItem(item, textColor, baseColor, dirItem, dirItem->lastItem(), leftName,
+ leftSize, leftDate, Synchronizer::getTaskTypeName( item->task() ),
+ rightDate, rightSize, rightName );
+
+ dirItem->setLastItem( listItem );
+ }
+ }
+
+ if( listItem )
+ {
+ listItem->setPixmap(0, isDir ? folderIcon : fileIcon);
+ if( !item->isMarked() )
+ listItem->setVisible( false );
+ else
+ syncList->ensureItemVisible( listItem );
+ }
+}
+
+void SynchronizerGUI::markChanged( SynchronizerFileItem *item, bool ensureVisible )
+{
+ SyncViewItem *listItem = (SyncViewItem *)item->userData();
+ if( listItem )
+ {
+ if( !item->isMarked() ) {
+ listItem->setVisible( false );
+ } else {
+ QString leftName="", rightName="", leftDate="", rightDate="", leftSize="", rightSize="";
+ bool isDir = item->isDir();
+
+ if( item->existsInLeft() )
+ {
+ leftName = item->leftName();
+ leftSize = isDir ? i18n("<DIR>")+" " : KRpermHandler::parseSize( item->leftSize() );
+ leftDate = SynchronizerGUI::convertTime( item->leftDate() );
+ }
+
+ if( item->existsInRight() )
+ {
+ rightName = item->rightName();
+ rightSize = isDir ? i18n("<DIR>")+" " : KRpermHandler::parseSize( item->rightSize() );
+ rightDate = SynchronizerGUI::convertTime( item->rightDate() );
+ }
+
+ listItem->setVisible( true );
+ listItem->setText( 0, leftName );
+ listItem->setText( 1, leftSize );
+ listItem->setText( 2, leftDate );
+ listItem->setColors( foreGrounds[ item->task() ], backGrounds[ item->task() ] );
+ listItem->setText( 3, Synchronizer::getTaskTypeName( item->task() ) );
+ listItem->setText( 4, rightDate );
+ listItem->setText( 5, rightSize );
+ listItem->setText( 6, rightName );
+
+ if( ensureVisible )
+ syncList->ensureItemVisible( listItem );
+ }
+ }
+}
+
+void SynchronizerGUI::subdirsChecked( bool isOn )
+{
+ cbSymlinks->setEnabled( isOn );
+}
+
+void SynchronizerGUI::disableMarkButtons()
+{
+ btnLeftToRight->setEnabled( false );
+ btnEquals->setEnabled( false );
+ btnDifferents->setEnabled( false );
+ btnRightToLeft->setEnabled( false );
+ btnDeletable->setEnabled( false );
+ btnDuplicates->setEnabled( false );
+ btnSingles->setEnabled( false );
+}
+
+void SynchronizerGUI::enableMarkButtons()
+{
+ btnLeftToRight->setEnabled( true );
+ btnEquals->setEnabled( true );
+ btnDifferents->setEnabled( true );
+ btnRightToLeft->setEnabled( true );
+ btnDeletable->setEnabled( true );
+ btnDuplicates->setEnabled( true );
+ btnSingles->setEnabled( true );
+}
+
+QString SynchronizerGUI::convertTime(time_t time) const
+{
+ // convert the time_t to struct tm
+ struct tm* t=localtime((time_t *)&time);
+
+ QDateTime tmp(QDate(t->tm_year+1900, t->tm_mon+1, t->tm_mday), QTime(t->tm_hour, t->tm_min));
+ return KGlobal::locale()->formatDateTime(tmp);
+}
+
+void SynchronizerGUI::setMarkFlags()
+{
+ synchronizer.setMarkFlags( btnRightToLeft->isOn(), btnEquals->isOn(), btnDifferents->isOn(),
+ btnLeftToRight->isOn(), btnDuplicates->isOn(), btnSingles->isOn(),
+ btnDeletable->isOn() );
+}
+
+void SynchronizerGUI::refresh()
+{
+ if( !isComparing )
+ {
+ syncList->clearSelection();
+ setMarkFlags();
+ btnCompareDirs->setEnabled( false );
+ profileManager->setEnabled( false );
+ btnSwapSides->setEnabled( false );
+ btnSynchronize->setEnabled( false );
+ btnFeedToListBox->setEnabled( false );
+ disableMarkButtons();
+ int fileCount = synchronizer.refresh();
+ enableMarkButtons();
+ btnCompareDirs->setEnabled( true );
+ profileManager->setEnabled( true );
+ btnSwapSides->setEnabled( true );
+ if( fileCount ) {
+ btnFeedToListBox->setEnabled( true );
+ btnSynchronize->setEnabled( true );
+ }
+ }
+}
+
+void SynchronizerGUI::synchronize()
+{
+ int copyToLeftNr, copyToRightNr, deleteNr;
+ KIO::filesize_t copyToLeftSize, copyToRightSize, deleteSize;
+
+ if( !synchronizer.totalSizes( &copyToLeftNr, &copyToLeftSize, &copyToRightNr, &copyToRightSize,
+ &deleteNr, &deleteSize ) )
+ {
+ KMessageBox::sorry(parentWidget(), i18n("Synchronizer has nothing to do!"));
+ return;
+ }
+
+ SynchronizeDialog *sd = new SynchronizeDialog( this, "SychDialog", true, 0, &synchronizer,
+ copyToLeftNr, copyToLeftSize, copyToRightNr,
+ copyToRightSize, deleteNr, deleteSize,
+ parallelThreadsSpinBox->value() );
+
+ wasSync = sd->wasSyncronizationStarted();
+ delete sd;
+
+ if( wasSync )
+ closeDialog();
+}
+
+void SynchronizerGUI::resizeEvent( QResizeEvent *e )
+{
+ if( !isMaximized() )
+ {
+ sizeX = e->size().width();
+ sizeY = e->size().height();
+ }
+
+ if( !firstResize )
+ {
+ int delta = e->size().width() - e->oldSize().width() + (e->size().width() & 1 );
+ int newSize = syncList->header()->sectionSize( 6 ) + delta/2;
+
+ if( newSize > 20 )
+ syncList->header()->resizeSection( 6, newSize );
+
+ syncList->header()->adjustHeaderSize();
+ }
+ firstResize = false;
+ QDialog::resizeEvent( e );
+}
+
+void SynchronizerGUI::statusInfo( QString info )
+{
+ statusLabel->setText( info );
+ qApp->processEvents();
+}
+
+void SynchronizerGUI::swapSides()
+{
+ if( btnCompareDirs->isEnabled() )
+ {
+ QString leftCurrent = leftLocation->currentText();
+ leftLocation->setCurrentText( rightLocation->currentText() );
+ rightLocation->setCurrentText( leftCurrent );
+ synchronizer.swapSides();
+ refresh();
+ }
+}
+
+void SynchronizerGUI::keyPressEvent( QKeyEvent *e )
+{
+ switch ( e->key() )
+ {
+ case Key_M :
+ {
+ if( e->state() == ControlButton )
+ {
+ syncList->setFocus();
+ e->accept();
+ }
+ break;
+ }
+ case Key_F3 :
+ case Key_F4 :
+ {
+ e->accept();
+ QListViewItem *listItem = syncList->currentItem();
+ if( listItem == 0 )
+ break;
+
+ bool isedit = e->key() == Key_F4;
+
+ SynchronizerFileItem *item = ((SyncViewItem *)listItem)->synchronizerItemRef();
+ QString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + "/";
+ QString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + "/";
+
+ if( item->isDir() )
+ return;
+
+ if ( e->state() == ShiftButton && item->existsInRight() )
+ {
+ KURL rightURL = vfs::fromPathOrURL( synchronizer.rightBaseDirectory() + rightDirName + item->rightName() );
+ if( isedit )
+ KrViewer::edit( rightURL, this ); // view the file
+ else
+ KrViewer::view( rightURL, this ); // view the file
+ return;
+ }
+ else if ( e->state() == 0 && item->existsInLeft() )
+ {
+ KURL leftURL = vfs::fromPathOrURL( synchronizer.leftBaseDirectory() + leftDirName + item->leftName() );
+ if( isedit )
+ KrViewer::edit( leftURL, this ); // view the file
+ else
+ KrViewer::view( leftURL, this ); // view the file
+ return;
+ }
+ }
+ break;
+ case Key_U :
+ if( e->state() != ControlButton )
+ break;
+ e->accept();
+ swapSides();
+ return;
+ case Key_Enter:
+ case Key_Return:
+ if( syncList->hasFocus() )
+ {
+ e->accept();
+
+ QListViewItem *listItem = syncList->currentItem();
+ if( listItem == 0 || !listItem->isVisible() )
+ return;
+
+ SynchronizerFileItem *item = ((SyncViewItem *)listItem)->synchronizerItemRef();
+ if( item->isDir() ) {
+ listItem->setOpen( !listItem->isOpen() );
+ return;
+ }
+
+ if( !item->existsInLeft() || !item->existsInRight() )
+ return;
+ // call compare
+ doubleClicked( listItem );
+ return;
+ }
+ break;
+ case Key_Escape:
+ if( btnStopComparing->isShown() && btnStopComparing->isEnabled() ) // is it comparing?
+ {
+ e->accept();
+ btnStopComparing->animateClick(); // just click the stop button
+ }
+ else
+ {
+ e->accept();
+ if( syncList->childCount() != 0 )
+ {
+ int result = KMessageBox::warningYesNo(this, i18n( "The synchronizer window contains data from a previous compare. If you exit, this data will be lost. Do you really want to exit?" ),
+ i18n("Krusader::Synchronize Directories"),
+ KStdGuiItem::yes(), KStdGuiItem::no(), "syncGUIexit" );
+ if( result != KMessageBox::Yes )
+ return;
+ }
+ QDialog::reject();
+ }
+ return;
+ }
+
+ QDialog::keyPressEvent( e );
+}
+
+void SynchronizerGUI::loadFromProfile( QString profile )
+{
+ syncList->clear();
+ synchronizer.reset();
+ isComparing = wasClosed = false;
+ btnSynchronize->setEnabled( false );
+ btnFeedToListBox->setEnabled( false );
+
+ krConfig->setGroup( profile );
+
+ if( !hasSelectedFiles )
+ {
+ leftLocation->setCurrentText( krConfig->readEntry( "Left Location" ) );
+ rightLocation->setCurrentText( krConfig->readEntry( "Right Location" ) );
+ }
+ fileFilter->setCurrentText( krConfig->readEntry( "Search For" ) );
+
+ cbSubdirs-> setChecked( krConfig->readBoolEntry( "Recurse Subdirectories", true ) );
+ cbSymlinks-> setChecked( krConfig->readBoolEntry( "Follow Symlinks", false ) );
+ cbByContent-> setChecked( krConfig->readBoolEntry( "Compare By Content", false ) );
+ cbIgnoreDate->setChecked( krConfig->readBoolEntry( "Ignore Date", false ) );
+ cbAsymmetric->setChecked( krConfig->readBoolEntry( "Asymmetric", false ) );
+ cbIgnoreCase->setChecked( krConfig->readBoolEntry( "Ignore Case", false ) );
+
+ btnScrollResults->setOn( krConfig->readBoolEntry( "Scroll Results", false ) );
+
+ btnLeftToRight->setOn( krConfig->readBoolEntry( "Show Left To Right", true ) );
+ btnEquals ->setOn( krConfig->readBoolEntry( "Show Equals", true ) );
+ btnDifferents ->setOn( krConfig->readBoolEntry( "Show Differents", true ) );
+ btnRightToLeft->setOn( krConfig->readBoolEntry( "Show Right To Left", true ) );
+ btnDeletable ->setOn( krConfig->readBoolEntry( "Show Deletable", true ) );
+ btnDuplicates ->setOn( krConfig->readBoolEntry( "Show Duplicates", true ) );
+ btnSingles ->setOn( krConfig->readBoolEntry( "Show Singles", true ) );
+
+ int equalityThreshold = krConfig->readNumEntry( "Equality Threshold", 0 );
+ int equalityCombo = 0;
+ convertFromSeconds( equalityThreshold, equalityCombo, equalityThreshold );
+ equalitySpinBox->setValue( equalityThreshold );
+ equalityUnitCombo->setCurrentItem( equalityCombo );
+
+ int timeShift = krConfig->readNumEntry( "Time Shift", 0 );
+ int timeShiftCombo = 0;
+ convertFromSeconds( timeShift, timeShiftCombo, timeShift );
+ timeShiftSpinBox->setValue( timeShift );
+ timeShiftUnitCombo->setCurrentItem( timeShiftCombo );
+
+ int parallelThreads = krConfig->readNumEntry( "Parallel Threads", 1 );
+ parallelThreadsSpinBox->setValue( parallelThreads );
+
+ bool ignoreHidden = krConfig->readBoolEntry( "Ignore Hidden Files", FALSE );
+ ignoreHiddenFilesCB->setChecked( ignoreHidden );
+
+ refresh();
+}
+
+void SynchronizerGUI::saveToProfile( QString profile )
+{
+ krConfig->setGroup( profile );
+
+ krConfig->writeEntry( "Left Location", leftLocation->currentText() );
+ krConfig->writeEntry( "Search For", fileFilter->currentText() );
+ krConfig->writeEntry( "Right Location", rightLocation->currentText() );
+
+ krConfig->writeEntry( "Recurse Subdirectories", cbSubdirs->isChecked() );
+ krConfig->writeEntry( "Follow Symlinks", cbSymlinks->isChecked() );
+ krConfig->writeEntry( "Compare By Content", cbByContent->isChecked() );
+ krConfig->writeEntry( "Ignore Date", cbIgnoreDate->isChecked() );
+ krConfig->writeEntry( "Asymmetric", cbAsymmetric->isChecked() );
+ krConfig->writeEntry( "Ignore Case", cbIgnoreCase->isChecked() );
+
+ krConfig->writeEntry( "Scroll Results", btnScrollResults->isOn() );
+
+ krConfig->writeEntry( "Show Left To Right", btnLeftToRight->isOn() );
+ krConfig->writeEntry( "Show Equals", btnEquals->isOn() );
+ krConfig->writeEntry( "Show Differents", btnDifferents->isOn() );
+ krConfig->writeEntry( "Show Right To Left", btnRightToLeft->isOn() );
+ krConfig->writeEntry( "Show Deletable", btnDeletable->isOn() );
+ krConfig->writeEntry( "Show Duplicates", btnDuplicates->isOn() );
+ krConfig->writeEntry( "Show Singles", btnSingles->isOn() );
+
+ krConfig->writeEntry( "Equality Threshold", convertToSeconds( equalitySpinBox->value(), equalityUnitCombo->currentItem() ) );
+ krConfig->writeEntry( "Time Shift", convertToSeconds( timeShiftSpinBox->value(), timeShiftUnitCombo->currentItem() ) );
+ krConfig->writeEntry( "Parallel Threads", parallelThreadsSpinBox->value() );
+
+ krConfig->writeEntry( "Ignore Hidden Files", ignoreHiddenFilesCB->isChecked() );
+}
+
+void SynchronizerGUI::connectFilters( const QString &newString )
+{
+ if( synchronizerTabs->currentPageIndex() )
+ fileFilter->setEditText( newString );
+ else
+ generalFilter->searchFor->setEditText( newString );
+}
+
+void SynchronizerGUI::setScrolling( bool isOn )
+{
+ if( isOn )
+ btnScrollResults->setText( i18n( "Quiet" ) );
+ else
+ btnScrollResults->setText( i18n( "Scroll Results" ) );
+
+ synchronizer.setScrolling( isOn );
+}
+
+int SynchronizerGUI::convertToSeconds( int time, int unit ) {
+ switch( unit ) {
+ case 1:
+ return time * 60;
+ case 2:
+ return time * 3600;
+ case 3:
+ return time * 86400;
+ default:
+ return time;
+ }
+}
+
+void SynchronizerGUI::convertFromSeconds( int &time, int &unit, int second ) {
+ unit = 0;
+ time = second;
+ int absTime = (time < 0 ) ? -time: time;
+
+ if( absTime >= 86400 && ( absTime % 86400 ) == 0 ) {
+ time /= 86400;
+ unit = 3;
+ } else if( absTime >= 3600 && ( absTime % 3600 ) == 0 ) {
+ time /= 3600;
+ unit = 2;
+ } else if( absTime >= 60 && ( absTime % 60 ) == 0 ) {
+ time /= 60;
+ unit = 1;
+ }
+}
+
+void SynchronizerGUI::copyToClipboard( bool isLeft )
+{
+ KURL::List urls;
+
+ unsigned ndx = 0;
+ SynchronizerFileItem *currentItem;
+
+ while( ( currentItem = synchronizer.getItemAt( ndx++ ) ) != 0 )
+ {
+ SynchronizerGUI::SyncViewItem *viewItem = (SynchronizerGUI::SyncViewItem *)currentItem->userData();
+
+ if( !viewItem || !viewItem->isSelected() || !viewItem->isVisible() )
+ continue;
+
+ SynchronizerFileItem *item = viewItem->synchronizerItemRef();
+ if( item )
+ {
+ if( isLeft && item->existsInLeft() )
+ {
+ QString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + "/";
+ KURL leftURL = vfs::fromPathOrURL( synchronizer.leftBaseDirectory() + leftDirName + item->leftName() );
+ urls.push_back( leftURL );
+ }
+ else if( !isLeft && item->existsInRight() )
+ {
+ QString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + "/";
+ KURL rightURL = vfs::fromPathOrURL( synchronizer.rightBaseDirectory() + rightDirName + item->rightName() );
+ urls.push_back( rightURL );
+ }
+ }
+ }
+
+ if( urls.count() == 0 )
+ return;
+
+ KURLDrag *d = new KURLDrag(urls, this);
+ d->setPixmap( FL_LOADICON( isLeft ? "2leftarrow" : "2rightarrow" ), QPoint( -7, 0 ) );
+ QApplication::clipboard()->setData( d );
+}
+
+#include "synchronizergui.moc"
diff --git a/krusader/Synchronizer/synchronizergui.h b/krusader/Synchronizer/synchronizergui.h
new file mode 100755
index 0000000..90f2042
--- /dev/null
+++ b/krusader/Synchronizer/synchronizergui.h
@@ -0,0 +1,224 @@
+/***************************************************************************
+ synchronizergui.h - description
+ -------------------
+ copyright : (C) 2003 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __SYNCHRONIZERGUI_H__
+#define __SYNCHRONIZERGUI_H__
+
+#include "synchronizer.h"
+#include "../GUI/profilemanager.h"
+#include "../Filter/filtertabs.h"
+#include "../Filter/generalfilter.h"
+#include <qdialog.h>
+#include <qlistview.h>
+#include <kcombobox.h>
+#include <qpixmap.h>
+#include <qcheckbox.h>
+#include <qmap.h>
+#include <qlabel.h>
+#include <qtabwidget.h>
+
+class QSpinBox;
+
+class SynchronizerGUI : QDialog
+{
+ Q_OBJECT
+
+public:
+ class SyncViewItem : public QListViewItem
+ {
+ private:
+ SynchronizerFileItem *syncItemRef;
+ SyncViewItem *lastItemRef;
+ QColor textColor;
+ QColor baseColor;
+
+ public:
+ SyncViewItem( SynchronizerFileItem *item, QColor txt, QColor base, QListView * parent, QListViewItem *after, QString label1,
+ QString label2 = QString::null, QString label3 = QString::null, QString label4 = QString::null,
+ QString label5 = QString::null, QString label6 = QString::null,
+ QString label7 = QString::null, QString label8 = QString::null ) :
+ QListViewItem( parent, after, label1, label2, label3, label4, label5, label6,
+ label7, label8 ), syncItemRef( item ), lastItemRef( 0 ), textColor( txt ), baseColor( base )
+ {
+ item->setUserData( (void *)this );
+ setDragEnabled( true );
+ }
+
+ SyncViewItem( SynchronizerFileItem *item, QColor txt, QColor base, QListViewItem * parent, QListViewItem *after, QString label1,
+ QString label2 = QString::null, QString label3 = QString::null, QString label4 = QString::null,
+ QString label5 = QString::null, QString label6 = QString::null,
+ QString label7 = QString::null, QString label8 = QString::null ) :
+ QListViewItem( parent, after, label1, label2, label3, label4, label5, label6,
+ label7, label8 ), syncItemRef( item ), lastItemRef( 0 ), textColor( txt ), baseColor( base )
+ {
+ item->setUserData( (void *)this );
+ setDragEnabled( true );
+ }
+
+ ~SyncViewItem()
+ {
+ syncItemRef->setUserData( 0 );
+ }
+
+ inline SynchronizerFileItem * synchronizerItemRef() {return syncItemRef;}
+ inline SyncViewItem * lastItem() {return lastItemRef;}
+ inline void setLastItem(SyncViewItem*s) {lastItemRef = s;}
+
+ void setColors( QColor fore, QColor back ) {
+ textColor = fore;
+ baseColor = back;
+ }
+
+ void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int align)
+ {
+ QColorGroup _cg = cg;
+ if( textColor.isValid() )
+ _cg.setColor(QColorGroup::Text, textColor );
+ if( baseColor.isValid() )
+ _cg.setColor(QColorGroup::Base, baseColor );
+ QListViewItem::paintCell( p, _cg, column, width, align );
+ };
+ };
+
+public:
+ // if rightDirectory is null, leftDirectory is actually the profile name to load
+ SynchronizerGUI(QWidget* parent, KURL leftDirectory, KURL rightDirectory = QString::null, QStringList selList = QStringList() );
+ SynchronizerGUI(QWidget* parent, QString profile );
+ ~SynchronizerGUI();
+
+ inline bool wasSynchronization() {return wasSync;}
+
+public slots:
+ void rightMouseClicked(QListViewItem *);
+ void doubleClicked(QListViewItem *);
+ void compare();
+ void synchronize();
+ void stop();
+ void feedToListBox();
+ void closeDialog();
+ void refresh();
+ void swapSides();
+ void loadFromProfile( QString );
+ void saveToProfile( QString );
+
+protected slots:
+ void reject();
+ void addFile( SynchronizerFileItem * );
+ void markChanged( SynchronizerFileItem *, bool );
+ void setScrolling( bool );
+ void statusInfo( QString );
+ void subdirsChecked( bool );
+ void setPanelLabels();
+ void setCompletion();
+ void checkExcludeURLValidity( QString &text, QString &error );
+ void connectFilters( const QString & );
+
+private:
+ void initGUI(QWidget* parent, QString profile, KURL leftURL, KURL rightURL, QStringList selList);
+
+ QString convertTime(time_t time) const;
+ void setMarkFlags();
+ void disableMarkButtons();
+ void enableMarkButtons();
+ void copyToClipboard( bool isLeft );
+
+ int convertToSeconds( int time, int unit );
+ void convertFromSeconds( int &time, int &unit, int second );
+
+protected:
+ virtual void keyPressEvent( QKeyEvent * );
+ virtual void resizeEvent( QResizeEvent *e );
+
+ ProfileManager *profileManager;
+ FilterTabs *filterTabs;
+ GeneralFilter *generalFilter;
+
+ QTabWidget *synchronizerTabs;
+
+ KHistoryCombo *leftLocation;
+ KHistoryCombo *rightLocation;
+ KHistoryCombo *fileFilter;
+
+ QListView *syncList;
+ Synchronizer synchronizer;
+
+ QCheckBox *cbSubdirs;
+ QCheckBox *cbSymlinks;
+ QCheckBox *cbByContent;
+ QCheckBox *cbIgnoreDate;
+ QCheckBox *cbAsymmetric;
+ QCheckBox *cbIgnoreCase;
+
+ QPushButton *btnSwapSides;
+ QPushButton *btnCompareDirs;
+ QPushButton *btnStopComparing;
+ QPushButton *btnSynchronize;
+ QPushButton *btnFeedToListBox;
+ QPushButton *btnScrollResults;
+
+ QPushButton *btnLeftToRight;
+ QPushButton *btnEquals;
+ QPushButton *btnDifferents;
+ QPushButton *btnRightToLeft;
+ QPushButton *btnDeletable;
+ QPushButton *btnDuplicates;
+ QPushButton *btnSingles;
+
+ QLabel *statusLabel;
+ QLabel *leftDirLabel;
+ QLabel *rightDirLabel;
+
+ QStringList selectedFiles;
+
+ QSpinBox *parallelThreadsSpinBox;
+ QSpinBox *equalitySpinBox;
+ QComboBox *equalityUnitCombo;
+ QSpinBox *timeShiftSpinBox;
+ QComboBox *timeShiftUnitCombo;
+ QCheckBox *ignoreHiddenFilesCB;
+
+private:
+ QPixmap fileIcon;
+ QPixmap folderIcon;
+ bool isComparing;
+ bool wasClosed;
+ bool wasSync;
+ bool firstResize;
+ bool hasSelectedFiles;
+ SyncViewItem *lastItem;
+
+ int sizeX;
+ int sizeY;
+
+ QColor foreGrounds[ TT_MAX ];
+ QColor backGrounds[ TT_MAX ];
+};
+
+#endif /* __SYNCHRONIZERGUI_H__ */
diff --git a/krusader/Synchronizer/synchronizertask.cpp b/krusader/Synchronizer/synchronizertask.cpp
new file mode 100644
index 0000000..2e07eb0
--- /dev/null
+++ b/krusader/Synchronizer/synchronizertask.cpp
@@ -0,0 +1,343 @@
+/***************************************************************************
+ synchronizertask.cpp - description
+ -------------------
+ copyright : (C) 2006 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "synchronizer.h"
+#include "synchronizertask.h"
+#include "synchronizerfileitem.h"
+#include "synchronizerdirlist.h"
+#include <qtimer.h>
+#include <qfile.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include "../VFS/vfs.h"
+
+CompareTask::CompareTask( SynchronizerFileItem *parentIn, const QString &leftURL,
+ const QString &rightURL, const QString &leftDir,
+ const QString &rightDir, bool hidden ) : SynchronizerTask (), m_parent( parentIn ),
+ m_url( leftURL ), m_dir( leftDir ), m_otherUrl( rightURL ),
+ m_otherDir( rightDir ), m_duplicate( true ),
+ m_dirList( 0 ), m_otherDirList( 0 ) {
+ ignoreHidden = hidden;
+}
+
+CompareTask::CompareTask( SynchronizerFileItem *parentIn, const QString &urlIn,
+ const QString &dirIn, bool isLeftIn, bool hidden ) : SynchronizerTask (),
+ m_parent( parentIn ), m_url( urlIn ), m_dir( dirIn ),
+ m_isLeft( isLeftIn ), m_duplicate( false ),
+ m_dirList( 0 ), m_otherDirList( 0 ) {
+ ignoreHidden = hidden;
+}
+
+CompareTask::~CompareTask() {
+ if( m_dirList ) {
+ delete m_dirList;
+ m_dirList = 0;
+ }
+ if( m_otherDirList ) {
+ delete m_otherDirList;
+ m_otherDirList = 0;
+ }
+}
+
+void CompareTask::start() {
+ if( m_state == ST_STATE_NEW ) {
+ m_state = ST_STATE_PENDING;
+ m_loadFinished = m_otherLoadFinished = false;
+
+ m_dirList = new SynchronizerDirList( parentWidget, ignoreHidden );
+ connect( m_dirList, SIGNAL( finished( bool ) ), this, SLOT( slotFinished( bool ) ));
+ m_dirList->load( m_url, false );
+
+ if( m_duplicate ) {
+ m_otherDirList = new SynchronizerDirList( parentWidget, ignoreHidden );
+ connect( m_otherDirList, SIGNAL( finished( bool ) ), this, SLOT( slotOtherFinished( bool ) ));
+ m_otherDirList->load( m_otherUrl, false );
+ }
+ }
+}
+
+void CompareTask::slotFinished( bool result ) {
+ if( !result ) {
+ m_state = ST_STATE_ERROR;
+ return;
+ }
+ m_loadFinished = true;
+
+ if( m_otherLoadFinished || !m_duplicate )
+ m_state = ST_STATE_READY;
+}
+
+
+void CompareTask::slotOtherFinished( bool result ) {
+ if( !result ) {
+ m_state = ST_STATE_ERROR;
+ return;
+ }
+ m_otherLoadFinished = true;
+
+ if( m_loadFinished )
+ m_state = ST_STATE_READY;
+}
+
+CompareContentTask::CompareContentTask( Synchronizer *syn, SynchronizerFileItem *itemIn, const KURL &leftURLIn,
+ const KURL &rightURLIn, KIO::filesize_t sizeIn ) : SynchronizerTask(),
+ leftURL( leftURLIn ), rightURL( rightURLIn ),
+ size( sizeIn ), errorPrinted(false), leftReadJob( 0 ),
+ rightReadJob( 0 ), compareArray(), item( itemIn ), timer( 0 ),
+ leftFile( 0 ), rightFile( 0 ), received( 0 ), sync( syn ) {
+}
+
+CompareContentTask::~CompareContentTask() {
+ abortContentComparing();
+
+ if( timer )
+ delete timer;
+ if( leftFile )
+ delete leftFile;
+ if( rightFile )
+ delete rightFile;
+}
+
+void CompareContentTask::start() {
+ m_state = ST_STATE_PENDING;
+
+ if( leftURL.isLocalFile() && rightURL.isLocalFile() ) {
+ leftFile = new QFile( leftURL.path() );
+ if( !leftFile->open( IO_ReadOnly ) ) {
+ KMessageBox::error(parentWidget, i18n("Error at opening %1!").arg( leftURL.path() ));
+ m_state = ST_STATE_ERROR;
+ return;
+ }
+
+ rightFile = new QFile( rightURL.path() );
+ if( !rightFile->open( IO_ReadOnly ) ) {
+ KMessageBox::error(parentWidget, i18n("Error at opening %1!").arg( rightURL.path() ));
+ m_state = ST_STATE_ERROR;
+ return;
+ }
+
+ timer = new QTimer( this );
+ connect( timer, SIGNAL(timeout()), this, SLOT(sendStatusMessage()) );
+ timer->start( 1000, true );
+
+ localFileCompareCycle();
+ } else {
+ leftReadJob = KIO::get( leftURL, false, false );
+ rightReadJob = KIO::get( rightURL, false, false );
+
+ connect(leftReadJob, SIGNAL(data(KIO::Job *, const QByteArray &)),
+ this, SLOT(slotDataReceived(KIO::Job *, const QByteArray &)));
+ connect(rightReadJob, SIGNAL(data(KIO::Job *, const QByteArray &)),
+ this, SLOT(slotDataReceived(KIO::Job *, const QByteArray &)));
+ connect(leftReadJob, SIGNAL(result(KIO::Job*)),
+ this, SLOT(slotFinished(KIO::Job *)));
+ connect(rightReadJob, SIGNAL(result(KIO::Job*)),
+ this, SLOT(slotFinished(KIO::Job *)));
+
+ rightReadJob->suspend();
+
+ timer = new QTimer( this );
+ connect( timer, SIGNAL(timeout()), this, SLOT(sendStatusMessage()) );
+ timer->start( 1000, true );
+ }
+}
+
+void CompareContentTask::localFileCompareCycle() {
+
+ bool different = false;
+
+ char leftBuffer[ 1440 ];
+ char rightBuffer[ 1440 ];
+
+ QTime timer;
+ timer.start();
+
+ int cnt = 0;
+
+ while ( !leftFile->atEnd() && !rightFile->atEnd() )
+ {
+ int leftBytes = leftFile->readBlock( leftBuffer, sizeof( leftBuffer ) );
+ int rightBytes = rightFile->readBlock( rightBuffer, sizeof( rightBuffer ) );
+
+ if( leftBytes != rightBytes ) {
+ different = true;
+ break;
+ }
+
+ if( leftBytes <= 0 )
+ break;
+
+ received += leftBytes;
+
+ if( memcmp( leftBuffer, rightBuffer, leftBytes ) ) {
+ different = true;
+ break;
+ }
+
+ if( (++cnt % 16) == 0 && timer.elapsed() >= 250 )
+ break;
+ }
+
+ if( different ) {
+ sync->compareContentResult( item, false );
+ m_state = ST_STATE_READY;
+ return;
+ }
+
+ if( leftFile->atEnd() && rightFile->atEnd() ) {
+ sync->compareContentResult( item, true );
+ m_state = ST_STATE_READY;
+ return;
+ }
+
+ QTimer::singleShot( 0, this, SLOT( localFileCompareCycle() ) );
+}
+
+
+void CompareContentTask::slotDataReceived(KIO::Job *job, const QByteArray &data)
+{
+ int bufferLen = compareArray.size();
+ int dataLen = data.size();
+
+ if( job == leftReadJob )
+ received += dataLen;
+
+ do
+ {
+ if( bufferLen == 0 )
+ {
+ compareArray.duplicate( data.data(), dataLen );
+ break;
+ }
+
+ int minSize = ( dataLen < bufferLen ) ? dataLen : bufferLen;
+
+ for( int i = 0; i != minSize; i++ )
+ if( data[i] != compareArray[i] )
+ {
+ abortContentComparing();
+ return;
+ }
+
+ if( minSize == bufferLen )
+ {
+ compareArray.duplicate( data.data() + bufferLen, dataLen - bufferLen );
+ if( dataLen == bufferLen )
+ return;
+ break;
+ }
+ else
+ {
+ compareArray.duplicate( compareArray.data() + dataLen, bufferLen - dataLen );
+ return;
+ }
+
+ }while ( false );
+
+ KIO::TransferJob *otherJob = ( job == leftReadJob ) ? rightReadJob : leftReadJob;
+
+ if( otherJob == 0 )
+ {
+ if( compareArray.size() )
+ abortContentComparing();
+ }
+ else
+ {
+ if( !((KIO::TransferJob *)job)->isSuspended() )
+ {
+ ((KIO::TransferJob *)job)->suspend();
+ otherJob->resume();
+ }
+ }
+}
+
+void CompareContentTask::slotFinished(KIO::Job *job)
+{
+ KIO::TransferJob *otherJob = ( job == leftReadJob ) ? rightReadJob : leftReadJob;
+
+ if( job == leftReadJob )
+ leftReadJob = 0;
+ else
+ rightReadJob = 0;
+
+ if( otherJob )
+ otherJob->resume();
+
+ if( job->error() )
+ {
+ timer->stop();
+ abortContentComparing();
+ }
+
+ if( job->error() && job->error() != KIO::ERR_USER_CANCELED && !errorPrinted )
+ {
+ errorPrinted = true;
+ KMessageBox::error(parentWidget, i18n("IO error at comparing file %1 with %2!")
+ .arg( vfs::pathOrURL( leftURL ) )
+ .arg( vfs::pathOrURL( rightURL ) ) );
+ }
+
+ if( leftReadJob == 0 && rightReadJob == 0 )
+ {
+ if( !compareArray.size() )
+ sync->compareContentResult( item, true );
+ else
+ sync->compareContentResult( item, false );
+
+ m_state = ST_STATE_READY;
+ }
+}
+
+void CompareContentTask::abortContentComparing()
+{
+ if( timer )
+ timer->stop();
+
+ if( leftReadJob )
+ leftReadJob->kill( false );
+ if( rightReadJob )
+ rightReadJob->kill( false );
+
+ if( item->task() >= TT_UNKNOWN )
+ sync->compareContentResult( item, false );
+
+ m_state = ST_STATE_READY;
+}
+
+void CompareContentTask::sendStatusMessage()
+{
+ double perc = (size == 0) ? 1. : (double)received / (double)size;
+ int percent = (int)(perc * 10000. + 0.5);
+ QString statstr = QString( "%1.%2%3" ).arg( percent / 100 ).arg( ( percent / 10 )%10 ).arg( percent % 10 ) + "%";
+ setStatusMessage( i18n( "Comparing file %1 (%2)..." ).arg( leftURL.fileName() ).arg( statstr ) );
+ timer->start( 500, true );
+}
+
+#include "synchronizertask.moc"
diff --git a/krusader/Synchronizer/synchronizertask.h b/krusader/Synchronizer/synchronizertask.h
new file mode 100644
index 0000000..015f792
--- /dev/null
+++ b/krusader/Synchronizer/synchronizertask.h
@@ -0,0 +1,167 @@
+/***************************************************************************
+ synchronizertask.h - description
+ -------------------
+ copyright : (C) 2006 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __SYNCHRONIZER_TASK_H__
+#define __SYNCHRONIZER_TASK_H__
+
+#include <qobject.h>
+#include <kio/job.h>
+
+class Synchronizer;
+class SynchronizerDirList;
+class SynchronizerFileItem;
+class QProgressDialog;
+class QTimer;
+class QFile;
+
+#define ST_STATE_NEW 0
+#define ST_STATE_PENDING 1
+#define ST_STATE_STATUS 2
+#define ST_STATE_READY 3
+#define ST_STATE_ERROR 4
+
+class SynchronizerTask : public QObject {
+ Q_OBJECT
+
+public:
+ SynchronizerTask() : QObject(), m_state( ST_STATE_NEW ), m_statusMessage( QString::null ) {}
+ virtual ~SynchronizerTask() {};
+
+ inline int start( QWidget *parentWidget ) { this->parentWidget = parentWidget; start(); return state(); }
+
+ inline int state() { return m_state; }
+
+ void setStatusMessage( const QString & statMsg ) {
+ if( m_state == ST_STATE_PENDING || m_state == ST_STATE_STATUS )
+ m_state = ST_STATE_STATUS;
+ m_statusMessage = statMsg;
+ }
+
+ QString status() {
+ if( m_state == ST_STATE_STATUS ) {
+ m_state = ST_STATE_PENDING;
+ return m_statusMessage;
+ }
+ return QString::null;
+ }
+
+protected:
+ virtual void start() {};
+ int m_state;
+ QString m_statusMessage;
+ QWidget *parentWidget;
+};
+
+
+class CompareTask : public SynchronizerTask {
+ Q_OBJECT
+
+public:
+ CompareTask( SynchronizerFileItem *parentIn, const QString &leftURL,
+ const QString &rightURL, const QString &leftDir,
+ const QString &rightDir, bool ignoreHidden );
+ CompareTask( SynchronizerFileItem *parentIn, const QString &urlIn,
+ const QString &dirIn, bool isLeftIn, bool ignoreHidden );
+ virtual ~CompareTask();
+
+ inline bool isDuplicate() { return m_duplicate; }
+ inline bool isLeft() { return !m_duplicate && m_isLeft; }
+ inline const QString & leftURL() { return m_url; }
+ inline const QString & rightURL() { return m_otherUrl; }
+ inline const QString & leftDir() { return m_dir; }
+ inline const QString & rightDir() { return m_otherDir; }
+ inline const QString & url() { return m_url; }
+ inline const QString & dir() { return m_dir; }
+ inline SynchronizerFileItem * parent() { return m_parent; }
+ inline SynchronizerDirList * leftDirList() { return m_dirList; }
+ inline SynchronizerDirList * rightDirList() { return m_otherDirList; }
+ inline SynchronizerDirList * dirList() { return m_dirList; }
+
+protected slots:
+ virtual void start();
+ void slotFinished( bool result );
+ void slotOtherFinished( bool result );
+
+private:
+ SynchronizerFileItem * m_parent;
+ QString m_url;
+ QString m_dir;
+ QString m_otherUrl;
+ QString m_otherDir;
+ bool m_isLeft;
+ bool m_duplicate;
+ SynchronizerDirList * m_dirList;
+ SynchronizerDirList * m_otherDirList;
+ bool m_loadFinished;
+ bool m_otherLoadFinished;
+ bool ignoreHidden;
+};
+
+
+class CompareContentTask : public SynchronizerTask {
+ Q_OBJECT
+
+public:
+ CompareContentTask( Synchronizer *, SynchronizerFileItem *, const KURL &, const KURL &, KIO::filesize_t );
+ virtual ~CompareContentTask();
+
+public slots:
+ void slotDataReceived(KIO::Job *job, const QByteArray &data);
+ void slotFinished(KIO::Job *job);
+ void sendStatusMessage();
+
+protected:
+ virtual void start();
+
+protected slots:
+ void localFileCompareCycle();
+
+private:
+ void abortContentComparing();
+
+ KURL leftURL; // the currently processed URL (left)
+ KURL rightURL; // the currently processed URL (right)
+ KIO::filesize_t size; // the size of the compared files
+
+ bool errorPrinted; // flag indicates error
+ KIO::TransferJob *leftReadJob; // compare left read job
+ KIO::TransferJob *rightReadJob; // compare right read job
+ QByteArray compareArray; // the array for comparing
+ SynchronizerFileItem *item; // the item for content compare
+ QTimer *timer; // timer to show the process dialog at compare by content
+
+ QFile *leftFile; // the left side local file
+ QFile *rightFile; // the right side local file
+
+ KIO::filesize_t received; // the received size
+ Synchronizer *sync;
+};
+
+#endif /* __SYNCHRONIZER_TASK_H__ */
diff --git a/krusader/UserAction/Makefile.am b/krusader/UserAction/Makefile.am
new file mode 100644
index 0000000..691f60a
--- /dev/null
+++ b/krusader/UserAction/Makefile.am
@@ -0,0 +1,17 @@
+if include_libkjsembed
+AM_CPPFLAGS = -D__KJSEMBED__
+endif
+
+noinst_LIBRARIES = libUserAction.a
+
+INCLUDES = $(all_includes)
+
+libUserAction_a_METASOURCES = AUTO
+
+libUserAction_a_SOURCES = useraction.cpp \
+ kraction.cpp \
+ expander.cpp \
+ useractionpopupmenu.cpp \
+ kractionbase.cpp
+
+noinst_HEADERS = tstring.h
diff --git a/krusader/UserAction/expander.cpp b/krusader/UserAction/expander.cpp
new file mode 100644
index 0000000..e18cfe2
--- /dev/null
+++ b/krusader/UserAction/expander.cpp
@@ -0,0 +1,1224 @@
+//
+// C++ Implementation: expander
+//
+// Description:
+//
+//
+// Author: Jonas B�r (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include <algorithm>
+
+#include "expander.h"
+
+#include "../krusader.h"
+#include "../krusaderview.h"
+#include "../panelmanager.h"
+#include "../Panel/listpanel.h"
+#include "../Panel/panelfunc.h"
+#include "../Panel/krview.h"
+#include "../Synchronizer/synchronizergui.h"
+#include "../Search/krsearchdialog.h"
+#include "../GUI/profilemanager.h"
+#include "../VFS/preservingcopyjob.h"
+#include "../KViewer/krviewer.h"
+#include "../krservices.h"
+
+#ifdef __KJSEMBED__
+#include "../KrJS/krjs.h"
+#endif
+
+#include <kdebug.h>
+#include <kinputdialog.h>
+#include <kstandarddirs.h>
+#include <kmessagebox.h>
+#include <ktempfile.h>
+#include <qstringlist.h>
+#include <qclipboard.h>
+
+#include <functional>
+using namespace std;
+
+#define NEED_PANEL if (panel==0) { panelMissingError(_expression,exp); return QString::null; }
+
+#include "tstring.h"
+
+QValueList<const exp_placeholder*>& Expander::_placeholder()
+{
+ static QValueList<const exp_placeholder*> ret;
+ return ret;
+}
+
+void exp_placeholder::panelMissingError(const QString &s, Expander& exp)
+{
+ exp.setError( Error(Error::S_FATAL,Error::C_ARGUMENT,i18n("Needed panel specification missing in expander %1").arg(s)) );
+}
+
+QStringList exp_placeholder::fileList(const ListPanel* const panel,const QString& type,const QString& mask,const bool ommitPath,const bool useUrl,Expander& exp,const QString& error)
+{
+ QStringList items;
+ if ( type.isEmpty() || type == "all" )
+ panel->view->getItemsByMask( mask, &items );
+ else if ( type == "files" )
+ panel->view->getItemsByMask( mask, &items, false, true );
+ else if ( type == "dirs" )
+ panel->view->getItemsByMask( mask, &items, true, false );
+ else if ( type == "selected" )
+ panel->view->getSelectedItems( &items );
+ else {
+ setError(exp, Error(Error::S_FATAL,Error::C_ARGUMENT,i18n("Expander: Bad argument to %1: %2 is not valid item specifier").arg(error,type) ) );
+ return QString::null;
+ }
+ if ( !ommitPath ) { // add the current path
+ // translate to urls using vfs
+ KURL::List* list = panel->func->files()->vfs_getFiles(&items);
+ items.clear();
+ // parse everything to a single qstring
+ for (KURL::List::Iterator it = list->begin(); it != list->end(); ++it) {
+ items.push_back(useUrl ? (*it).url() : (*it).path());
+ }
+ delete list;
+ }
+
+ return items;
+}
+
+namespace {
+
+class exp_simpleplaceholder : public exp_placeholder
+{
+public:
+ EXP_FUNC;
+ virtual TagString expFunc ( const ListPanel*, const QStringList&, const bool&, Expander& ) const=0;
+};
+
+/**
+ * expands %_Path% ('_' is replaced by 'a', 'o', 'r' or 'l' to indicate the active, other, right or left panel) with the path of the specified panel
+ */
+class exp_Path : public exp_simpleplaceholder {
+ static const exp_Path instance;
+ exp_Path();
+public:
+ SIMPLE_EXP_FUNC;
+};
+
+/**
+ * expands %_Count% ('_' is replaced by 'a', 'o', 'r' or 'l' to indicate the active, other, right or left panel) with the number of items, which type is specified by the first Parameter
+ */
+class exp_Count : public exp_simpleplaceholder {
+ static const exp_Count instance;
+ exp_Count();
+public:
+ SIMPLE_EXP_FUNC;
+};
+
+/**
+ * expands %_Filter% ('_' is replaced by 'a', 'o', 'r' or 'l' to indicate the active, other, right or left panel) with the correspondend filter (ie: "*.cpp")
+ */
+class exp_Filter : public exp_simpleplaceholder {
+ static const exp_Filter instance;
+ exp_Filter();
+public:
+ SIMPLE_EXP_FUNC;
+};
+
+/**
+ * expands %_Current% ('_' is replaced by 'a', 'o', 'r' or 'l' to indicate the active, other, right or left panel) with the current item ( != the selected onec)
+ */
+class exp_Current : public exp_simpleplaceholder {
+ static const exp_Current instance;
+ exp_Current();
+public:
+ SIMPLE_EXP_FUNC;
+};
+
+/**
+ * expands %_List% ('_' is replaced by 'a', 'o', 'r' or 'l' to indicate the active, other, right or left panel) with a list of items, which type is specified by the first Parameter
+ */
+class exp_List : public exp_simpleplaceholder {
+ static const exp_List instance;
+ exp_List();
+public:
+ SIMPLE_EXP_FUNC;
+};
+
+/**
+ * expands %_ListFile% ('_' is replaced by 'a', 'o', 'r' or 'l' to indicate the active, other, right or left panel) with the name of a temporary file, containing a list of items, which type is specified by the first Parameter
+ */
+class exp_ListFile : public exp_simpleplaceholder {
+ static const exp_ListFile instance;
+ exp_ListFile();
+public:
+ SIMPLE_EXP_FUNC;
+};
+
+/**
+ * expands %_Ask% ('_' is nessesary because there is no panel needed) with the return of an input-dialog
+ */
+class exp_Ask : public exp_simpleplaceholder {
+ static const exp_Ask instance;
+ exp_Ask();
+public:
+ SIMPLE_EXP_FUNC;
+};
+
+/**
+ * This copies it's first Parameter to the clipboard
+ */
+class exp_Clipboard : public exp_placeholder {
+ static const exp_Clipboard instance;
+ exp_Clipboard();
+public:
+ EXP_FUNC;
+};
+
+/**
+ * This selects all items by the mask given with the first Parameter
+ */
+class exp_Select : public exp_simpleplaceholder {
+ static const exp_Select instance;
+ exp_Select();
+public:
+ SIMPLE_EXP_FUNC;
+};
+
+/**
+ * This changes the panel'spath to the value given with the first Parameter.
+ */
+class exp_Goto : public exp_simpleplaceholder {
+ static const exp_Goto instance;
+ exp_Goto();
+public:
+ SIMPLE_EXP_FUNC;
+};
+
+/**
+ * This is equal to 'cp <first Parameter> <second Parameter>'.
+ */
+class exp_Copy : public exp_placeholder {
+ static const exp_Copy instance;
+ exp_Copy();
+public:
+ EXP_FUNC;
+};
+
+/**
+ * This is equal to 'mv <first Parameter> <second Parameter>'.
+ */
+class exp_Move : public exp_placeholder {
+ static const exp_Move instance;
+ exp_Move();
+public:
+ EXP_FUNC;
+};
+
+/**
+ * This opens the synchronizer with a given profile
+ */
+class exp_Sync : public exp_simpleplaceholder {
+ static const exp_Sync instance;
+ exp_Sync();
+public:
+ SIMPLE_EXP_FUNC;
+};
+
+/**
+ * This opens the searchmodule with a given profile
+ */
+class exp_NewSearch : public exp_simpleplaceholder {
+ static const exp_NewSearch instance;
+ exp_NewSearch();
+public:
+ SIMPLE_EXP_FUNC;
+};
+
+/**
+ * This loads the panel-profile with a given name
+ */
+class exp_Profile : public exp_simpleplaceholder {
+ static const exp_Profile instance;
+ exp_Profile();
+public:
+ SIMPLE_EXP_FUNC;
+};
+
+/**
+ * This is setting marks in the string where he is later splitted up for each {all, selected, files, dirs}
+ */
+class exp_Each : public exp_simpleplaceholder {
+ static const exp_Each instance;
+ exp_Each();
+public:
+ SIMPLE_EXP_FUNC;
+};
+
+/**
+ * This sets the sorting on a specific colunm
+ */
+class exp_ColSort : public exp_simpleplaceholder {
+ static const exp_ColSort instance;
+ exp_ColSort();
+public:
+ SIMPLE_EXP_FUNC;
+};
+
+/**
+ * This sets relation between the left and right panel
+ */
+class exp_PanelSize : public exp_simpleplaceholder {
+ static const exp_PanelSize instance;
+ exp_PanelSize();
+public:
+ SIMPLE_EXP_FUNC;
+};
+
+#ifdef __KJSEMBED__
+/**
+ * This sets relation between the left and right panel
+ */
+class exp_Script : public exp_simpleplaceholder {
+ static const exp_Script instance;
+ exp_Script();
+public:
+ SIMPLE_EXP_FUNC;
+};
+
+const exp_Script exp_Script::instance;
+
+#endif
+
+/**
+ * This loads a file in the internal viewer
+ */
+class exp_View : public exp_simpleplaceholder {
+ static const exp_View instance;
+ exp_View();
+public:
+ SIMPLE_EXP_FUNC;
+};
+
+const exp_View exp_View::instance;
+const exp_PanelSize exp_PanelSize::instance;
+const exp_ColSort exp_ColSort::instance;
+const exp_Each exp_Each::instance;
+const exp_Profile exp_Profile::instance;
+const exp_NewSearch exp_NewSearch::instance;
+const exp_Sync exp_Sync::instance;
+const exp_Move exp_Move::instance;
+const exp_Copy exp_Copy::instance;
+const exp_Goto exp_Goto::instance;
+const exp_Select exp_Select::instance;
+const exp_Clipboard exp_Clipboard::instance;
+const exp_Ask exp_Ask::instance;
+const exp_ListFile exp_ListFile::instance;
+const exp_List exp_List::instance;
+const exp_Current exp_Current::instance;
+const exp_Filter exp_Filter::instance;
+const exp_Count exp_Count::instance;
+const exp_Path exp_Path::instance;
+
+////////////////////////////////////////////////////////////
+//////////////////////// utils ////////////////////////
+////////////////////////////////////////////////////////////
+
+/**
+ * escapes everything that confuses bash in filenames
+ * @param s String to manipulate
+ * @return escaped string
+ */
+QString bashquote( QString s ) {
+ /*
+ // we _can_not_ use this function because it _encloses_ the sting in single-quots!
+ // In this case quotes strings could not be concaternated anymore
+ return KrServices::quote(s);
+ */
+
+ static const QString evilstuff = "\\\"'`()[]{}!?;$&<>| \t\r\n"; // stuff that should get escaped
+
+ for ( unsigned int i = 0; i < evilstuff.length(); ++i )
+ s.replace( evilstuff[ i ], ('\\' + evilstuff[ i ]) );
+
+ return s;
+}
+
+QString separateAndQuote(QStringList list,const QString& separator,const bool quote)
+{
+ if(quote)
+ transform(list.begin(),list.end(),list.begin(),bashquote);
+ return list.join(separator);
+}
+/////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////// expander classes ////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+exp_Path::exp_Path() {
+ _expression = "Path";
+ _description = i18n("Panel's Path...");
+ _needPanel = true;
+
+ addParameter( exp_parameter( i18n("Automatically escape spaces"), "__yes", false ) );
+}
+TagString exp_Path::expFunc( const ListPanel* panel, const QStringList& parameter, const bool& useUrl, Expander& exp ) const {
+ NEED_PANEL
+
+ QString result;
+
+ if ( useUrl )
+ result = panel->func->files()->vfs_getOrigin().url() + "/";
+ else
+ result = panel->func->files()->vfs_getOrigin().path() + "/";
+
+ if ( parameter[0].lower() == "no" ) // don't escape spaces
+ return TagString(result);
+ else
+ return TagString(bashquote(result));
+}
+
+exp_Count::exp_Count() {
+ _expression = "Count";
+ _description = i18n("Number of...");
+ _needPanel = true;
+
+ addParameter( exp_parameter( i18n("Count:"), "__choose:All;Files;Dirs;Selected", false ) );
+}
+TagString exp_Count::expFunc( const ListPanel* panel, const QStringList& parameter, const bool&, Expander& exp ) const {
+ NEED_PANEL
+
+ int n = -1;
+ if ( parameter[ 0 ].isEmpty() || parameter[ 0 ].lower() == "all" )
+ n = panel->view->numDirs() + panel->view->numFiles();
+ else if ( parameter[ 0 ].lower() == "files" )
+ n = panel->view->numFiles();
+ else if ( parameter[ 0 ].lower() == "dirs" )
+ n = panel->view->numDirs();
+ else if ( parameter[ 0 ].lower() == "selected" )
+ n = panel->view->numSelected();
+ else {
+ setError(exp, Error(Error::S_FATAL,Error::C_ARGUMENT,i18n("Expander: Bad argument to Count: %1 is not valid item specifier").arg(parameter[0]) ));
+ return QString::null;
+ }
+
+ return TagString(QString("%1").arg( n ));
+}
+
+exp_Filter::exp_Filter() {
+ _expression = "Filter";
+ _description = i18n("Filter Mask (*.h, *.cpp, etc.)");
+ _needPanel = true;
+}
+TagString exp_Filter::expFunc( const ListPanel* panel, const QStringList&, const bool&, Expander& exp ) const {
+ NEED_PANEL
+
+ return panel->view->filterMask().nameFilter();
+}
+
+exp_Current::exp_Current() {
+ _expression = "Current";
+ _description = i18n("Current File (!= Selected File)...");
+ _needPanel = true;
+
+ addParameter( exp_parameter( i18n("Omit the current path (optional)"), "__no", false ) );
+ addParameter( exp_parameter( i18n("Automatically escape spaces"), "__yes", false ) );
+}
+TagString exp_Current::expFunc( const ListPanel* panel, const QStringList& parameter, const bool& useUrl, Expander& exp ) const {
+ NEED_PANEL
+
+ QString item = panel->view->getCurrentItem();
+
+ QString result;
+
+ if ( parameter[0].lower() == "yes" ) // ommit the current path
+ result = item;
+ else {
+ KURL url = panel->func->files()->vfs_getFile( item );
+ if ( useUrl )
+ result = url.url();
+ else
+ result = url.path();
+ }
+
+ if ( parameter[1].lower() == "no" ) // don't escape spaces
+ return result;
+ else
+ return bashquote(result);
+}
+
+exp_List::exp_List() {
+ _expression = "List";
+ _description = i18n("Item List of...");
+ _needPanel = true;
+
+ addParameter( exp_parameter( i18n("Which items:"), "__choose:All;Files;Dirs;Selected", false ) );
+ addParameter( exp_parameter( i18n("Separator between the items (optional):"), " ", false ) );
+ addParameter( exp_parameter( i18n("Omit the current path (optional)"), "__no", false ) );
+ addParameter( exp_parameter( i18n("Mask (optional, all but 'Selected'):"), "__select", false ) );
+ addParameter( exp_parameter( i18n("Automatically escape spaces"), "__yes", false ) );
+}
+TagString exp_List::expFunc( const ListPanel* panel, const QStringList& parameter, const bool& useUrl, Expander& exp ) const {
+ NEED_PANEL
+
+ // get selected items from view
+ QStringList items;
+ QString mask;
+
+ if ( parameter.count() <= 3 || parameter[3].isEmpty() )
+ mask = "*";
+ else
+ mask = parameter[3];
+
+ return separateAndQuote(
+ fileList(panel,
+ parameter.empty() ? QString::null : parameter[0].lower(),
+ mask, parameter.count() > 2 ? parameter[2].lower()=="yes" : false,
+ useUrl, exp, "List"),
+ parameter.count() > 1 ? parameter[1] : " ",
+ parameter.count() > 4 ? parameter[4].lower()=="yes" : true);
+}
+
+exp_ListFile::exp_ListFile() {
+ _expression = "ListFile";
+ _description = i18n("Filename of an Item List...");
+ _needPanel = true;
+
+ addParameter( exp_parameter( i18n("Which items:"), "__choose:All;Files;Dirs;Selected", false ) );
+ addParameter( exp_parameter( i18n("Separator between the items (optional)"), "\n", false ) );
+ addParameter( exp_parameter( i18n("Omit the current path (optional)"), "__no", false ) );
+ addParameter( exp_parameter( i18n("Mask (optional, all but 'Selected'):"), "__select", false ) );
+ addParameter( exp_parameter( i18n("Automatically escape spaces"), "__no", false ) );
+}
+TagString exp_ListFile::expFunc( const ListPanel* panel, const QStringList& parameter, const bool& useUrl, Expander& exp ) const {
+ NEED_PANEL
+
+ // get selected items from view
+ QStringList items;
+ QString mask;
+
+ if ( parameter.count() <= 3 || parameter[3].isEmpty() )
+ mask = "*";
+ else
+ mask = parameter[3];
+ KTempFile tmpFile( locateLocal("tmp", "krusader"), ".itemlist" );
+
+ if ( tmpFile.status() != 0 ) {
+ setError(exp, Error(Error::S_FATAL,Error::C_WORLD, i18n("Expander: tempfile couldn't be opened (%1)" ).arg(strerror( tmpFile.status() )) ));
+ return QString::null;
+ }
+
+ QTextStream stream( tmpFile.file() );
+ stream << separateAndQuote(
+ fileList(panel,
+ parameter.empty() ? QString::null : parameter[0].lower(),
+ mask, parameter.count()>2 ? parameter[2].lower()=="yes" : false,
+ useUrl, exp, "ListFile"),
+ parameter.count() > 1 ? parameter[1] : "\n",
+ parameter.count() > 4 ? parameter[4].lower()=="yes" : true)
+ << "\n";
+ tmpFile.close();
+
+ return tmpFile.name();
+}
+
+exp_Select::exp_Select() {
+ _expression = "Select";
+ _description = i18n("Manipulate the Selection...");
+ _needPanel = true;
+
+ addParameter( exp_parameter( i18n("Selection mask:"), "__select", true ) );
+ addParameter( exp_parameter( i18n("Manipulate in which way:"), "__choose:Set;Add;Remove", false ) );
+}
+TagString exp_Select::expFunc( const ListPanel* panel, const QStringList& parameter, const bool& , Expander& exp) const {
+ NEED_PANEL
+
+ KRQuery mask;
+ if ( parameter.count() <= 0 || parameter[0].isEmpty() )
+ mask = KRQuery( "*" );
+ else
+ mask = KRQuery( parameter[0] );
+
+ if ( parameter[1].lower() == "add")
+ panel->view->select( mask );
+ else if ( parameter[1].lower() == "remove")
+ panel->view->unselect( mask );
+ else { // parameter[1].lower() == "set" or isEmpty() or whatever
+ panel->view->unselect( KRQuery( "*" ) );
+ panel->view->select( mask );
+ }
+
+ return QString::null; // this doesn't return anything, that's normal!
+}
+
+exp_Goto::exp_Goto() {
+ _expression = "Goto";
+ _description = i18n("Jump to a Location...");
+ _needPanel = true;
+
+ addParameter( exp_parameter( i18n("Choose a path:"), "__goto", true ) );
+ addParameter( exp_parameter( i18n("Open location in a new tab"), "__no", false ) );
+}
+TagString exp_Goto::expFunc( const ListPanel* panel, const QStringList& parameter, const bool&, Expander& exp ) const {
+ NEED_PANEL
+
+ bool newTab = false;
+ if ( parameter[1].lower() == "yes" )
+ newTab = true;
+
+ if ( newTab ) {
+ if ( panel == LEFT_PANEL)
+ krApp->mainView->leftMng->slotNewTab( parameter[0] );
+ else
+ krApp->mainView->rightMng->slotNewTab( parameter[0] );
+ }
+ else {
+ panel->func->openUrl( parameter[0], "" );
+ const_cast<ListPanel*>(panel)->slotFocusOnMe();
+ }
+
+ return QString::null; // this doesn't return anything, that's normal!
+}
+
+/*
+exp_Search::exp_Search() {
+ _expression = "Search";
+ _description = i18n("Search for files");
+ _needPanel = true;
+
+ addParameter( new exp_parameter( i18n("please choose the setting"), "__searchprofile", true ) );
+ addParameter( new exp_parameter( i18n("open the search in a new tab"), "__yes", false ) ); //TODO: add this also to panel-dependent as soon as vfs support the display of search-results
+}
+*/
+
+exp_Ask::exp_Ask() {
+ _expression = "Ask";
+ _description = i18n("Ask Parameter from User...");
+ _needPanel = false;
+
+ addParameter( exp_parameter( i18n("Question:"), "Where do you want do go today?", true ) );
+ addParameter( exp_parameter( i18n("Preset (optional):"), "", false ) );
+ addParameter( exp_parameter( i18n("Caption (optional):"), "", false ) );
+}
+TagString exp_Ask::expFunc( const ListPanel*, const QStringList& parameter, const bool&, Expander& exp ) const {
+ QString caption, preset, result;
+
+ if ( parameter.count() <= 2 || parameter[2].isEmpty() )
+ caption = i18n("User Action");
+ else
+ caption = parameter[2];
+ if ( parameter.count() <= 1 || parameter[1].isEmpty() )
+ preset = QString::null;
+ else
+ preset = parameter[1];
+
+ bool ok;
+ result = KInputDialog::getText(
+ caption,
+ parameter[0],
+ preset,
+ &ok );
+
+ if (ok)
+ return result;
+ else {
+ setError(exp, Error(Error::S_ERROR,Error::C_USER,"User cancelled") );
+ return QString::null;
+ }
+}
+
+exp_Clipboard::exp_Clipboard() {
+ _expression = "Clipboard";
+ _description = i18n("Copy to Clipboard...");
+ _needPanel = false;
+
+ addParameter( exp_parameter( i18n("What to copy:"), "__placeholder", true ) );
+ addParameter( exp_parameter( i18n("Append to current clipboard content with this separator (optional):"), "", false ) );
+}
+TagString exp_Clipboard::expFunc( const ListPanel*, const TagStringList& parameter, const bool&, Expander& exp ) const {
+// kdDebug() << "Expander::exp_Clipboard, parameter[0]: '" << parameter[0] << "', Clipboard: " << KApplication::clipboard()->text() << endl;
+ QStringList lst=splitEach(parameter[0]);
+ if(!parameter[1].isSimple()) {
+ setError(exp,Error(Error::S_FATAL,Error::C_SYNTAX,i18n("Expander: %Each% may not be in the second argument of %Clipboard%")));
+ return QString::null;
+ }
+ if ( parameter.count() <= 1 || parameter[1].string().isEmpty() || KApplication::clipboard()->text().isEmpty() )
+ KApplication::clipboard()->setText( lst.join("\n") );
+ else
+ KApplication::clipboard()->setText( KApplication::clipboard()->text() + parameter[1].string() + lst.join("\n") );
+
+ return QString::null; // this doesn't return anything, that's normal!
+}
+
+exp_Copy::exp_Copy() {
+ _expression = "Copy";
+ _description = i18n("Copy a File/Folder...");
+ _needPanel = false;
+
+ addParameter( exp_parameter( i18n("What to copy:"), "__placeholder", true ) );
+ addParameter( exp_parameter( i18n("Where to copy:"), "__placeholder", true ) );
+}
+TagString exp_Copy::expFunc( const ListPanel*, const TagStringList& parameter, const bool&, Expander& exp ) const {
+
+ // basically the parameter can already be used as URL, but since KURL has problems with ftp-proxy-urls (like ftp://username@proxyusername@url...) this is neccesary:
+ QStringList lst=splitEach( parameter[0] );
+ if(!parameter[1].isSimple()) {
+ setError(exp,Error(Error::S_FATAL,Error::C_SYNTAX,i18n("Expander: %Each% may not be in the second argument of %Copy%")));
+ return QString::null;
+ }
+ KURL::List src;
+ for(QStringList::const_iterator it=lst.begin(),end=lst.end();it!=end;++it)
+ src.push_back(vfs::fromPathOrURL( *it ));
+ // or transform(...) ?
+ KURL dest = vfs::fromPathOrURL( parameter[1].string() );
+
+ if ( !dest.isValid() || find_if(src.constBegin(),src.constEnd(),not1(mem_fun_ref(&KURL::isValid) ))!=src.end()) {
+ setError(exp, Error(Error::S_FATAL,Error::C_ARGUMENT,i18n("Expander: invalid URL's in %_Copy(\"src\", \"dest\")%") ));
+ return QString::null;
+ }
+
+ PreservingCopyJob::createCopyJob( PM_DEFAULT, src, dest, KIO::CopyJob::Copy, false, true );
+
+ return QString::null; // this doesn't return everything, that's normal!
+}
+
+exp_Move::exp_Move() {
+ _expression = "Move";
+ _description = i18n("Move/Rename a File/Folder...");
+ _needPanel = false;
+
+ addParameter( exp_parameter( i18n("What to move/rename:"), "__placeholder", true ) );
+ addParameter( exp_parameter( i18n("New target/name:"), "__placeholder", true ) );
+}
+TagString exp_Move::expFunc( const ListPanel*, const TagStringList& parameter, const bool& , Expander& exp ) const {
+ // basically the parameter can already be used as URL, but since KURL has problems with ftp-proxy-urls (like ftp://username@proxyusername@url...) this is neccesary:
+ QStringList lst=splitEach( parameter[0] );
+ if(!parameter[1].isSimple()) {
+ setError(exp,Error(Error::S_FATAL,Error::C_SYNTAX,i18n("%Each% may not be in the second argument of %Move%")));
+ return QString::null;
+ }
+ KURL::List src;
+ for(QStringList::const_iterator it=lst.begin(),end=lst.end();it!=end;++it)
+ src.push_back(vfs::fromPathOrURL( *it ));
+ // or transform(...) ?
+ KURL dest = vfs::fromPathOrURL( parameter[1].string() );
+
+ if ( !dest.isValid() || find_if(src.constBegin(),src.constEnd(),not1(mem_fun_ref(&KURL::isValid) ))!=src.end()) {
+ setError(exp, Error(Error::S_FATAL,Error::C_ARGUMENT,i18n("Expander: invalid URL's in %_Move(\"src\", \"dest\")%") ));
+ return QString::null;
+ }
+
+ PreservingCopyJob::createCopyJob( PM_DEFAULT, src, dest, KIO::CopyJob::Move, false, true );
+
+ return QString::null; // this doesn't return anything, that's normal!
+}
+
+exp_Sync::exp_Sync() {
+ _expression = "Sync";
+ _description = i18n("Load a Synchronizer Profile...");
+ _needPanel = false;
+
+ addParameter( exp_parameter( i18n("Choose a profile:"), "__syncprofile", true ) );
+}
+TagString exp_Sync::expFunc( const ListPanel*, const QStringList& parameter, const bool&, Expander& exp ) const {
+ if ( parameter[0].isEmpty() ) {
+ setError(exp, Error(Error::S_FATAL,Error::C_ARGUMENT,i18n("Expander: no profile specified for %_Sync(profile)%") ));
+ return QString::null;
+ }
+
+ new SynchronizerGUI( 0, parameter[0] );
+
+ return QString::null; // this doesn't return everything, that's normal!
+}
+
+exp_NewSearch::exp_NewSearch() {
+ _expression = "NewSearch";
+ _description = i18n("Load a Searchmodule Profile...");
+ _needPanel = false;
+
+ addParameter( exp_parameter( i18n("Choose a profile:"), "__searchprofile", true ) );
+}
+TagString exp_NewSearch::expFunc( const ListPanel*, const QStringList& parameter, const bool&, Expander& exp ) const {
+ if ( parameter[0].isEmpty() ) {
+ setError(exp, Error(Error::S_FATAL,Error::C_ARGUMENT,i18n("Expander: no profile specified for %_NewSearch(profile)%") ));
+ return QString::null;
+ }
+
+ new KrSearchDialog( parameter[0], krApp );
+
+ return QString::null; // this doesn't return everything, that's normal!
+}
+
+exp_Profile::exp_Profile() {
+ _expression = "Profile";
+ _description = i18n("Load a Panel Profile...");
+ _needPanel = false;
+
+ addParameter( exp_parameter( i18n("Choose a profile:"), "__panelprofile", true ) );
+}
+TagString exp_Profile::expFunc( const ListPanel*, const QStringList& parameter, const bool&, Expander& exp ) const {
+ if ( parameter[0].isEmpty() ) {
+ setError(exp, Error(Error::S_FATAL,Error::C_ARGUMENT,i18n("Expander: no profile specified for %_Profile(profile)%; abort...") ));
+ return QString::null;
+ }
+
+ MAIN_VIEW->profiles( parameter[0] );
+
+ return QString::null; // this doesn't return everything, that's normal!
+}
+
+exp_Each::exp_Each() {
+ _expression = "Each";
+ _description = i18n("Separate Program Call for Each...");
+ _needPanel = true;
+
+ addParameter( exp_parameter( i18n("Which items:"), "__choose:All;Files;Dirs;Selected", false ) );
+ addParameter( exp_parameter( i18n("Omit the current path (optional)"), "__no", false ) );
+ addParameter( exp_parameter( i18n("Mask (optional, all but 'Selected'):"), "__select", false ) );
+ addParameter( exp_parameter( i18n("Automatically escape spaces"), "__yes", false ) );
+}
+TagString exp_Each::expFunc( const ListPanel* panel, const QStringList& parameter, const bool& useUrl, Expander& exp ) const {
+ NEED_PANEL
+
+ QString mask;
+ if ( parameter.count() <= 2 || parameter[2].isEmpty() )
+ mask = "*";
+ else
+ mask = parameter[2];
+
+ TagString ret;
+ QStringList l = fileList(panel,
+ parameter.empty() ? QString::null : parameter[0].lower(),
+ mask, parameter.count() > 1 && parameter[1].lower()=="yes",
+ useUrl, exp, "Each");
+
+ if(!(parameter.count()<=3 || parameter[3].lower()!="yes"))
+ transform(l.begin(),l.end(),l.begin(),bashquote);
+
+ ret.insertTag(0,l);
+ return ret;
+}
+
+exp_ColSort::exp_ColSort() {
+ _expression = "ColSort";
+ _description = i18n("Set Sorting for This Panel...");
+ _needPanel = true;
+
+ addParameter( exp_parameter( i18n("Choose a column:"), "__choose:Name;Ext;Type;Size;Modified;Perms;rwx;Owner;Group", true ) );
+ addParameter( exp_parameter( i18n("Choose a sort sequence:"), "__choose:Toggle;Asc;Desc", false ) );
+}
+TagString exp_ColSort::expFunc( const ListPanel* panel, const QStringList& parameter, const bool&, Expander& exp ) const {
+ NEED_PANEL
+
+ if ( parameter[0].isEmpty() ) {
+ setError(exp, Error(Error::S_FATAL,Error::C_ARGUMENT,i18n("Expander: no column specified for %_ColSort(column)%") ));
+ return QString::null;
+ }
+
+ int mode = (int) panel->view->sortMode();
+
+ /* from Panel/krview.h:
+ enum SortSpec { Name=0x1,
+ Ext=0x2,
+ Size=0x4,
+ Type=0x8,
+ Modified=0x10,
+ Permissions=0x20,
+ KrPermissions=0x40,
+ Owner=0x80,
+ Group=0x100,
+ Descending=0x200,
+ DirsFirst=0x400,
+ IgnoreCase=0x800 };
+ */
+
+// krOut << "start: exp_ColSort::expFunc" << endl;
+ #define MODE_OUT krOut << QString( "mode: %1" ).arg( mode, 0, 2 ) << endl; // displays mode in base-2
+ //MODE_OUT
+
+ if ( parameter.count() <= 1 || ( parameter[1].lower() != "asc" && parameter[1].lower() != "desc" ) ) { //default == toggle
+ if ( mode & KrViewProperties::Descending )
+ mode &= ~KrViewProperties::Descending; // == asc
+ else
+ mode |= KrViewProperties::Descending; // == desc
+ } else
+ if ( parameter[1].lower() == "asc" ) {
+ mode &= ~KrViewProperties::Descending;
+ }
+ else { // == desc
+ mode |= KrViewProperties::Descending;
+ }
+
+ //MODE_OUT
+
+ // clear all column-infromation:
+ mode &= ~( KrViewProperties::Name | KrViewProperties::Ext | KrViewProperties::Size | KrViewProperties::Type | KrViewProperties::Modified | KrViewProperties::Permissions | KrViewProperties::KrPermissions | KrViewProperties::Owner | KrViewProperties::Group );
+
+ MODE_OUT
+
+ if ( parameter[0].lower() == "name" ) {
+ mode |= KrViewProperties::Name;
+ } else
+ if ( parameter[0].lower() == "ext" ) {
+ mode |= KrViewProperties::Ext;
+ } else
+ if ( parameter[0].lower() == "type" ) {
+ mode |= KrViewProperties::Type;
+ } else
+ if ( parameter[0].lower() == "size" ) {
+ mode |= KrViewProperties::Size;
+ } else
+ if ( parameter[0].lower() == "modified" ) {
+ mode |= KrViewProperties::Modified;
+ } else
+ if ( parameter[0].lower() == "perms" ) {
+ mode |= KrViewProperties::Permissions;
+ } else
+ if ( parameter[0].lower() == "rwx" ) {
+ mode |= KrViewProperties::KrPermissions;
+ } else
+ if ( parameter[0].lower() == "owner" ) {
+ mode |= KrViewProperties::Owner;
+ } else
+ if ( parameter[0].lower() == "group" ) {
+ mode |= KrViewProperties::Group;
+ } else {
+ setError(exp, Error(Error::S_WARNING,Error::C_ARGUMENT,i18n("Expander: unknown column specified for %_ColSort(%1)%").arg(parameter[0]) ));
+ return QString::null;
+ }
+
+ //MODE_OUT
+ panel->view->setSortMode( (KrViewProperties::SortSpec)mode );
+// krOut << "end: exp_ColSort::expFunc" << endl;
+ return QString::null; // this doesn't return anything, that's normal!
+}
+
+exp_PanelSize::exp_PanelSize() {
+ _expression = "PanelSize";
+ _description = i18n("Set Relation Between the Panels...");
+ _needPanel = true;
+
+ addParameter( exp_parameter( i18n("Set the new size in percent:"), "__int:0;100;5;50", true ) );
+}
+TagString exp_PanelSize::expFunc( const ListPanel* panel, const QStringList& parameter, const bool&, Expander& exp ) const {
+ NEED_PANEL
+ int newSize;
+
+ if ( parameter[0].isEmpty() )
+ newSize = 50; //default is 50%
+ else
+ newSize = parameter[0].toInt();
+
+ if ( newSize < 0 || newSize > 100 ) {
+ setError(exp, Error(Error::S_FATAL,Error::C_ARGUMENT,i18n("Expander: Value %1 out of range for %_PanelSize(percent)%. The first parameter has to be >0 and <100").arg(newSize)) );
+ return QString::null;
+ }
+
+ QValueList<int> panelSizes = MAIN_VIEW->horiz_splitter->sizes();
+ int totalSize = panelSizes[0] + panelSizes[1];
+
+ if ( panel == LEFT_PANEL ) {
+ panelSizes[0] = totalSize * newSize / 100;
+ panelSizes[1] = totalSize * (100 - newSize) / 100;
+ }
+ else { // == RIGHT_PANEL
+ panelSizes[0] = totalSize * (100 - newSize) / 100;
+ panelSizes[1] = totalSize * newSize / 100;
+ }
+
+ MAIN_VIEW->horiz_splitter->setSizes( panelSizes );
+
+ return QString::null; // this doesn't return everything, that's normal!
+}
+
+#ifdef __KJSEMBED__
+exp_Script::exp_Script() {
+ _expression = "Script";
+ _description = i18n("Execute a JavaScript Extension...");
+ _needPanel = false;
+
+ addParameter( exp_parameter( i18n("Location of the script"), "", true ) );
+ addParameter( exp_parameter( i18n("Set some variables for the execution (optional).\ni.e. \"return=return_var;foo=bar\", consult the handbook for more information"), "", false ) );
+}
+TagString exp_Script::expFunc( const ListPanel*, const QStringList& parameter, const bool&, Expander& exp ) const {
+ if ( parameter[0].isEmpty() ) {
+ setError(exp, Error(Error::S_FATAL,Error::C_ARGUMENT,i18n("Expander: no script specified for %_Script(script)%")) );
+ return QString::null;
+ }
+
+ QString filename = parameter[0];
+ if ( filename.find('/') && KURL::isRelativeURL(filename) ) {
+ // this return the local version of the file if this exists. else the global one is returnd
+ filename = locate( "data", "krusader/js/"+filename );
+ }
+
+ if ( ! krJS )
+ krJS = new KrJS();
+
+ KJS::ExecState *exec = krJS->globalExec();
+
+ QString jsReturn = QString::null;
+ if ( parameter[1].lower() == "yes" ) // to stay compatible with the old-style parameter
+ jsReturn = "cmd";
+ else {
+ QStringList jsVariables = QStringList::split( ';', parameter[1] );
+ QString jsVariable, jsValue;
+ for ( QStringList::Iterator it = jsVariables.begin(); it != jsVariables.end(); ++it ) {
+ jsVariable = (*it).section('=', 0, 0).stripWhiteSpace();
+ jsValue = (*it).section('=', 1);
+ if ( jsVariable == "return" )
+ jsReturn = jsValue.stripWhiteSpace();
+ else
+ krJS->putValue( jsVariable, KJSEmbed::convertToValue(exec, jsValue ) );
+ }
+ }
+
+ krJS->runFile( filename );
+
+ if ( ! jsReturn.isEmpty() )
+ return krJS->getValue( jsReturn ).toString( krJS->globalExec() ).qstring();
+ else
+ return QString::null;
+}
+#endif
+
+exp_View::exp_View() {
+ _expression = "View";
+ _description = i18n("View File with Krusader's Internal Viewer...");
+ _needPanel = false;
+
+ addParameter( exp_parameter( i18n("Which file to view (normally '%aCurrent%'):"), "__placeholder", true ) );
+ addParameter( exp_parameter( i18n("Choose a view mode:"), "__choose:generic;text;hex", false ) );
+ //addParameter( exp_parameter( i18n("Choose a window-mode"), "__choose:tab;window;panel", false ) );
+ //TODO: window-mode 'panel' should open the file in the third-hand viewer
+ addParameter( exp_parameter( i18n("Choose a window mode:"), "__choose:tab;window", false ) );
+}
+TagString exp_View::expFunc( const ListPanel*, const QStringList& parameter, const bool&, Expander& exp ) const {
+ if ( parameter[0].isEmpty() ) {
+ setError(exp, Error(Error::S_FATAL,Error::C_ARGUMENT,i18n("Expander: no file to view in %_View(filename)%")) );
+ return QString::null;
+ }
+
+ QString viewMode, windowMode;
+ if ( parameter.count() <= 1 || parameter[1].isEmpty() )
+ viewMode = "generic";
+ else
+ viewMode = parameter[1];
+
+ if ( parameter.count() <= 2 || parameter[2].isEmpty() )
+ windowMode = "tab";
+ else
+ windowMode = parameter[2];
+
+ KrViewer::Mode mode = KrViewer::Generic;
+ if( viewMode == "text" ) mode = KrViewer::Text;
+ else if( viewMode == "hex" ) mode = KrViewer::Hex;
+
+ KrViewer::view(parameter[0],mode,(windowMode == "window"));
+ //TODO: Call the viewer with viewMode and windowMode. Filename is in parameter[0].
+ // It would be nice if parameter[0] could also be a space-separated filename-list (provided if the first parameter is %aList(selected)%)
+
+ return QString::null; // this doesn't return everything, that's normal!
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////// end of expander classes ////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+TagString exp_simpleplaceholder::expFunc( const ListPanel* p, const TagStringList& parameter, const bool& useUrl, Expander& exp) const
+{
+ QStringList lst;
+ for(TagStringList::const_iterator it=parameter.begin(),end=parameter.end();it!=end;++it)
+ if((*it).isSimple())
+ lst.push_back((*it).string());
+ else {
+ setError(exp,Error(Error::S_FATAL,Error::C_SYNTAX,i18n("%Each% is not allowed in parameter to %1").arg(description())));
+ return QString::null;
+ }
+ return expFunc(p,lst,useUrl,exp);
+}
+
+}
+
+ListPanel* Expander::getPanel( const char panelIndicator, const exp_placeholder* pl, Expander& exp ) {
+ switch ( panelIndicator ) {
+ case 'a':
+ return ACTIVE_PANEL;
+ case 'o':
+ return OTHER_PANEL;
+ case 'l':
+ return LEFT_PANEL;
+ case 'r':
+ return RIGHT_PANEL;
+ case '_':
+ return 0;
+ default:
+ exp.setError(Error(Error::S_FATAL,Error::C_SYNTAX,i18n("Expander: Bad panel specifier %1 in placeholder %2").arg(panelIndicator).arg(pl->description())));
+ return 0;
+ }
+}
+
+void Expander::expand( const QString& stringToExpand, bool useUrl ) {
+ TagString result = expandCurrent( stringToExpand, useUrl );
+ if ( error() )
+ return;
+
+ if ( !result.isSimple() )
+ resultList = splitEach( result );
+ else
+ resultList.append( result.string() );
+
+// krOut << resultList[0] << endl;
+}
+
+TagString Expander::expandCurrent( const QString& stringToExpand, bool useUrl ) {
+ TagString result;
+ QString exp = QString::null;
+ TagString tmpResult;
+ int begin, end, i;
+// int brackets = 0;
+// bool inQuotes = false;
+ unsigned int idx = 0;
+ while ( idx < stringToExpand.length() ) {
+ if ( ( begin = stringToExpand.find( '%', idx ) ) == -1 ) break;
+ if ( ( end = findEnd( stringToExpand, begin ) ) == -1 ) {
+ setError(Error(Error::S_FATAL,Error::C_SYNTAX,i18n("Error: unterminated % in Expander::expandCurrent")) );
+ return QString::null;
+ }
+
+ result += stringToExpand.mid( idx, begin - idx ); // copy until the start of %exp%
+
+ // get the expression, and expand it using the correct expander function
+ exp = stringToExpand.mid( begin + 1, end - begin - 1 );
+// kdDebug() << "------------- exp: '" << exp << "'" << endl;
+ if ( exp == "" )
+ result += QString(QChar('%'));
+ else {
+ TagStringList parameter = separateParameter( &exp, useUrl );
+ if ( error() )
+ return QString::null;
+ char panelIndicator = exp.lower()[0].latin1();
+ exp.replace( 0, 1, "" );
+ for ( i = 0; i < placeholderCount(); ++i )
+ if ( exp == placeholder( i )->expression() ) {
+// kdDebug() << "---------------------------------------" << endl;
+ tmpResult = placeholder( i )->expFunc( getPanel( panelIndicator,placeholder(i),*this ), parameter, useUrl, *this );
+ if ( error() ) {
+ return QString::null;
+ }
+ else
+ result += tmpResult;
+// kdDebug() << "---------------------------------------" << endl;
+ break;
+ }
+ if ( i == placeholderCount() ) { // didn't find an expander
+ setError(Error(Error::S_FATAL,Error::C_SYNTAX,i18n("Error: unrecognized %%%1%2%% in Expander::expand").arg(panelIndicator).arg(exp)) );
+ return QString::null;
+ }
+ } //else
+ idx = end + 1;
+ }
+ // copy the rest of the string
+ result += stringToExpand.mid( idx );
+// kdDebug() << "============== result '" << result << "'" << endl;
+ return result;
+}
+
+QStringList Expander::splitEach( TagString stringToSplit ) {
+ if(stringToSplit.isSimple()) {
+// krOut << stringToSplit.string() << endl;
+ return stringToSplit.string();
+ }
+ pair<uint,QStringList> pl=*stringToSplit.tagsBegin();
+ stringToSplit.eraseTag(stringToSplit.tagsBegin());
+ QStringList ret;
+ for(QStringList::const_iterator it=pl.second.begin(),end=pl.second.end();it!=end;++it) {
+ TagString s=stringToSplit;
+ s.insert(pl.first,*it);
+ ret+=splitEach(s);
+ }
+ return ret;
+// kdDebug() << "stringToSplit: " << stringToSplit << endl;
+}
+
+TagStringList Expander::separateParameter( QString* const exp, bool useUrl ) {
+ TagStringList parameter;
+ QStringList parameter1;
+ QString result;
+ int begin, end;
+ if ( ( begin = exp->find( '(' ) ) != -1 ) {
+ if ( ( end = exp->findRev( ')' ) ) == -1 ) {
+ setError(Error(Error::S_FATAL,Error::C_SYNTAX,i18n("Error: missing ')' in Expander::separateParameter") ));
+ return TagStringList();
+ }
+ result = exp->mid( begin + 1, end - begin - 1 );
+ *exp = exp->left( begin );
+
+ bool inQuotes = false;
+ unsigned int idx = 0;
+ begin = 0;
+ while ( idx < result.length() ) {
+ if ( result[ idx ].latin1() == '\\' ) {
+ if ( result[ idx+1 ].latin1() == '"')
+ result.replace( idx, 1, "" );
+ }
+ if ( result[ idx ].latin1() == '"' )
+ inQuotes = !inQuotes;
+ if ( result[ idx ].latin1() == ',' && !inQuotes ) {
+ parameter1.append( result.mid( begin, idx - begin) );
+ begin = idx + 1;
+// krOut << " ---- parameter: " << parameter.join(";") << endl;
+ }
+ idx++;
+ }
+ parameter1.append( result.mid( begin, idx - begin) ); //don't forget the last one
+
+ for (QStringList::Iterator it = parameter1.begin(); it != parameter1.end(); ++it) {
+ *it = (*it).stripWhiteSpace();
+ if ( (*it).left(1) == "\"" )
+ *it = (*it).mid(1, (*it).length() - 2 );
+ parameter.push_back(expandCurrent( *it, useUrl ));
+ if ( error() )
+ return TagStringList();
+ }
+ }
+
+// krOut << "------- exp: " << *exp << " ---- parameter: " << parameter.join(";") << endl;
+ return parameter;
+}
+
+int Expander::findEnd( const QString& str, int start ) {
+ int end = str.find( '%', start + 1 );
+ if ( end == -1 )
+ return end;
+ int bracket = str.find( '(', start + 1 );
+ if ( end < bracket || bracket == -1 )
+ return end;
+
+ unsigned int idx = bracket+1;
+ bool inQuotes = false;
+ int depth=1;
+ while ( idx < str.length() ) {
+ switch (str[ idx ].latin1()) {
+ case '\\':
+ idx ++;
+ break;
+ case '"':
+ inQuotes = !inQuotes;
+ break;
+ case '(':
+ if(!inQuotes)
+ depth++;
+ break;
+ case ')':
+ if(!inQuotes)
+ --depth;
+ break;
+ case '%':
+ if(depth==0)
+ return idx;
+ } //switch
+ idx++;
+ } //while
+ // failsafe
+ return -1;
+}
diff --git a/krusader/UserAction/expander.h b/krusader/UserAction/expander.h
new file mode 100644
index 0000000..3d9cf72
--- /dev/null
+++ b/krusader/UserAction/expander.h
@@ -0,0 +1,245 @@
+//
+// C++ Interface: expander
+//
+// Description:
+//
+//
+// Author: Jonas B�r (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#ifndef EXPANDER_H
+#define EXPANDER_H
+
+// class QString;
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qvaluelist.h>
+#include "tstring.h"
+// #include <qstringlist.h>
+class ListPanel;
+class Expander;
+class Error;
+
+typedef TagString_t<QStringList> TagString;
+typedef QValueList<TagString> TagStringList;
+
+/**
+ * This holds informations about each parameter
+ */
+class exp_parameter {
+public:
+ exp_parameter() {}
+ inline exp_parameter( QString desc, QString pre, bool ness)
+ { _description = desc; _preset = pre; _nessesary = ness; }
+ inline QString description() const ///< A description of the parameter
+ { return _description; }
+ inline QString preset() const ///< the default of the parameter
+ { return _preset; }
+ inline bool nessesary() const ///< false if the parameter is optional
+ { return _nessesary; }
+
+private:
+ QString _description;
+ QString _preset;
+ bool _nessesary;
+};
+
+#define EXP_FUNC virtual TagString expFunc ( const ListPanel*, const TagStringList&, const bool&, Expander& ) const
+#define SIMPLE_EXP_FUNC virtual TagString expFunc ( const ListPanel*, const QStringList&, const bool&, Expander& ) const
+/**
+ * Abstract baseclass for all expander-functions (which replace placeholder).
+ * A Placeholder is an entry containing the expression, its expanding function and Parameter.
+ *
+ * Not to be created on the heap
+ *
+ * @author Jonas B�r (http://www.jonas-baehr.de)
+ */
+class exp_placeholder {
+public:
+ inline QString expression() const ///< The placeholder (without '%' or panel-prefix)
+ { return _expression; }
+ inline QString description() const ///< A description of the placeholder
+ { return _description; }
+ inline bool needPanel() const ///< true if the placeholder needs a panel to operate on
+ { return _needPanel; }
+ inline void addParameter( exp_parameter parameter ) ///< adds parameter to the placeholder
+ { _parameter.append(parameter); }
+ inline int parameterCount() const ///< returns the number of placeholders
+ { return _parameter.count(); }
+ inline const exp_parameter& parameter( int id ) const ///< returns a specific parameter
+ { return _parameter[ id ]; }
+
+ EXP_FUNC = 0;
+protected:
+ static void setError(Expander& exp,const Error& e) ;
+ static void panelMissingError(const QString &s, Expander& exp);
+ static QStringList splitEach(const TagString& s);
+ static QStringList fileList(const ListPanel* const panel,const QString& type,const QString& mask,const bool ommitPath,const bool useUrl,Expander&,const QString&);
+ exp_placeholder();
+ exp_placeholder(const exp_placeholder& p);
+ ~exp_placeholder() { }
+ QString _expression;
+ QString _description;
+ QValueList <exp_parameter> _parameter;
+ bool _needPanel;
+};
+
+
+ class Error {
+ public:
+ enum Cause {
+ C_USER, C_SYNTAX, C_WORLD, C_ARGUMENT
+ };
+ enum Severity {
+ S_OK, S_WARNING, S_ERROR, S_FATAL
+ };
+ Error() : s_(S_OK) {}
+ Error(Severity s,Cause c,QString d) : s_(s), c_(c), desc_(d) {}
+ Cause cause() const { return c_; }
+ operator bool() const { return s_!=S_OK; }
+ const QString& what() const { return desc_; }
+ private:
+ Severity s_;
+ Cause c_;
+ QString desc_;
+ };
+
+
+/**
+ * The Expander expands the command of an UserAction by replacing all placeholders by thier current values.@n
+ * Each placeholder begins with a '%'-sign, followed by one char indicating the panel, followed by a command which may have some paramenter enclosed in brackets and also ends with a '%'-sign.
+ * Examples are %aPath% or %rBookmark("/home/jonas/src/krusader_kde3", "yes")%.@n
+ * The panel-indicator has to be either 'a' for the active, 'o' for the other, 'r' for the right, 'l' for the left or '_' for panel-independence.
+ *
+ * Currently sopported are these commands can be ordered in three groups (childs are the parameter in the right order):
+ * - Placeholders for Krusaders panel-data (panel-indicator has to be 'a', 'o', 'r' or 'l')
+ * - @em Path is replaced by the panel's path
+ * - @em Count is replaced by a nomber of
+ * -# Either "All", "Files", "Dirs", "Selected"
+ * .
+ * - @em Filter is preplaced by the panels filter-mask (ex: "*.cpp *.h")
+ * - @em Current is replaced by the current item or, in case of onmultiple="call_each", by each selected item.
+ * -# If "yes", only the filename (without path) is returned
+ * .
+ * - @em List isreplaced by a list of
+ * -# Either "All", "Files", "Dirs", "Selected"
+ * -# A seperator between the items (default: " " [one space])
+ * -# If "yes", only the filename (without path) is returned
+ * -# (for all but "Selected") a filter-mask (default: "*")
+ * .
+ * .
+ * - Access to panel-dependent, krusader-internal, parameter-needed functions (panel-indicator has to be 'a', 'o', 'r' or 'l')
+ * - @em Select manipulates the selection of the panel
+ * -# A filter-mask (nessesary)
+ * -# Either "Add", "Remove", "Set" (default)
+ * .
+ * - @em Bookmark manipulates the selection of the panel
+ * -# A path or URL (nessesary)
+ * -# If "yes", the location is opend in a new tab
+ * .
+ * .
+ * - Access to panel-independent, krusader-internal, parameter-needed functions (panel-indicator doesn't matter but should be set to '_')
+ * - @em Ask displays a lineedit and is replaced by its return
+ * -# The question (nessesary)
+ * -# A default answer
+ * -# A cation for the popup
+ * .
+ * - @em Clipboard manipulates the system-wide clipboard
+ * -# The string copied to clip (ex: "%aCurrent%") (nessesary)
+ * -# A separator. If set, parameter1 is append with this to the current clipboard content
+ * .
+ * .
+ * .
+ * Since all placeholders are expanded in the order they appear in the command, little one-line-scripts are possible
+ *
+ * @author Jonas B�r (http://www.jonas-baehr.de), Shie Erlich
+ */
+class Expander {
+public:
+
+ inline static int placeholderCount() ///< returns the number of placeholders
+ { return _placeholder().count(); }
+ inline static const exp_placeholder* placeholder( int id )
+ { return _placeholder()[ id ]; }
+
+ /**
+ * This expands a whole commandline
+ *
+ * @param stringToExpand the commandline with the placeholder
+ * @param useUrl true iff the path's should be expanded to an URL instead of an local path
+ * @return a list of all commands
+ */
+ void expand( const QString& stringToExpand, bool useUrl );
+
+ /**
+ * Returns the list of all commands to be executed, provided that #expand was called
+ * before, and there was no error (see #error). Otherwise, calls #abort
+ *
+ * @return The list of commands to be executed
+ */
+ const QStringList& result() const { assert(!error()); return resultList; }
+
+ /**
+ * Returns the error object of this Expander. You can test whether there was
+ * any error by
+ * \code
+ * if(exp.error())
+ * error behaviour...
+ * else
+ * no error...
+ * \endcode
+ *
+ * @return The error object
+ */
+ const Error& error() const { return _err; }
+protected:
+ /**
+ * This expands a whole commandline by calling for each Placeholder the corresponding expander
+ *
+ * @param stringToExpand the commandline with the placeholder
+ * @param useUrl true if the path's should be expanded to an URL instead of an local path
+ * @return the expanded commanline for the current item
+ */
+ TagString expandCurrent( const QString& stringToExpand, bool useUrl );
+ /**
+ * This function searches for "@EACH"-marks to splitt the string in a list for each %_Each%-item
+ *
+ * @param stringToSplit the string which should be splitted
+ * @return the splitted list
+ */
+ static QStringList splitEach( TagString stringToSplit );
+ /**
+ * @param panelIndicator either '_' for panel-independent placeholders, 'a', 'o', 'r', or 'l' for the active, other (inactive), right or left panel
+ * @return a pointer to the right panel or NULL if no panel is needed.
+ */
+ static ListPanel* getPanel( const char panelIndicator ,const exp_placeholder*,Expander&);
+ /**
+ * This splits the parameter-string into separate parameter and expands each
+ * @param exp the string holding all parameter
+ * @param useUrl true if the path's should be expanded to an URL instead of an local path
+ * @return a list of all parameter
+ */
+ TagStringList separateParameter( QString* const exp, bool useUrl );
+ /**
+ * This finds the end of a placeholder, taking care of the parameter
+ * @return the position where the placeholder ends
+ */
+ int findEnd( const QString& str, int start );
+
+ void setError(const Error &e) { _err=e; }
+ friend class exp_placeholder;
+
+private:
+ static QValueList <const exp_placeholder*>& _placeholder();
+ Error _err;
+ QStringList resultList;
+};
+
+inline void exp_placeholder::setError(Expander& exp,const Error& e) { exp.setError(e); }
+inline QStringList exp_placeholder::splitEach(const TagString& s) { return Expander::splitEach(s); }
+inline exp_placeholder::exp_placeholder() { Expander::_placeholder().push_back(this); }
+
+#endif // ifndef EXPANDER_H
diff --git a/krusader/UserAction/kraction.cpp b/krusader/UserAction/kraction.cpp
new file mode 100644
index 0000000..9c9c89f
--- /dev/null
+++ b/krusader/UserAction/kraction.cpp
@@ -0,0 +1,586 @@
+//
+// C++ Implementation: kraction
+//
+// Description:
+//
+//
+// Author: Shie Erlich and Rafi Yanai <>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include <kdialogbase.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kinputdialog.h>
+#include <qtextedit.h>
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qsplitter.h>
+#include <qpushbutton.h>
+#include <qcheckbox.h>
+#include <qfile.h>
+#include <qlabel.h>
+#include <kaction.h>
+#include <kurl.h>
+#include <kmessagebox.h>
+#include <kfiledialog.h>
+#include "kraction.h"
+#include "expander.h"
+#include "useraction.h"
+#include "../krusader.h"
+#include "../krusaderview.h"
+#include "../defaults.h"
+
+//for the availabilitycheck:
+#include <kmimetype.h>
+#include <qregexp.h>
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////// KrActionProcDlg /////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+#include <qlayout.h>
+KrActionProcDlg::KrActionProcDlg( QString caption, bool enableStderr, QWidget *parent ) :
+KDialogBase( parent, 0, false, caption, KDialogBase::User1 | KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Cancel ),
+_stdout(0), _stderr(0), _currentTextEdit(0) {
+
+ setButtonOK( i18n( "Close" ) );
+ enableButtonOK( false ); // disable the close button, until the process finishes
+
+ setButtonCancel( KGuiItem(i18n("Kill"), i18n( "Kill the running process" )) );
+
+ setButtonText(KDialogBase::User1, i18n("Save as") );
+
+ QVBox *page = makeVBoxMainWidget();
+ // do we need to separate stderr and stdout?
+ if ( enableStderr ) {
+ QSplitter *splitt = new QSplitter( QSplitter::Vertical, page );
+ // create stdout
+ QVBox *stdoutBox = new QVBox( splitt, "stdout VBox" );
+ stdoutBox->setSpacing( 6 );
+ new QLabel( i18n( "Standard Output (stdout)" ), stdoutBox );
+ _stdout = new QTextEdit( stdoutBox );
+ _stdout->setReadOnly( true );
+ _stdout->setMinimumWidth( fontMetrics().maxWidth() * 40 );
+ // create stderr
+ QVBox *stderrBox = new QVBox( splitt, "stderr VBox" );
+ stderrBox->setSpacing( 6 );
+ new QLabel( i18n( "Standard Error (stderr)" ), stderrBox );
+ _stderr = new QTextEdit( stderrBox );
+ _stderr->setReadOnly( true );
+ _stderr->setMinimumWidth( fontMetrics().maxWidth() * 40 );
+ } else {
+ // create stdout
+ new QLabel( i18n( "Output" ), page );
+ _stdout = new QTextEdit( page );
+ _stdout->setReadOnly( true );
+ _stdout->setMinimumWidth( fontMetrics().maxWidth() * 40 );
+ }
+
+ _currentTextEdit = _stdout;
+ connect( _stdout, SIGNAL( clicked(int, int) ), SLOT( currentTextEditChanged() ) );
+ if (_stderr)
+ connect( _stderr, SIGNAL( clicked(int, int) ), SLOT( currentTextEditChanged() ) );
+
+ krConfig->setGroup( "UserActions" );
+ normalFont = krConfig->readFontEntry( "Normal Font", _UserActions_NormalFont );
+ fixedFont = krConfig->readFontEntry( "Fixed Font", _UserActions_FixedFont );
+ bool startupState = krConfig->readBoolEntry( "Use Fixed Font", _UserActions_UseFixedFont );
+ toggleFixedFont( startupState );
+
+ // HACK This fetches the layout of the buttonbox from KDialogBase, although it is not accessable with KDialogBase's API
+ // None the less it's quite save to use since this implementation hasn't changed since KDE-3.3 (I haven't looked at earlier
+ // versions since we don't support them) and now all work is done in KDE-4.
+ QWidget* buttonBox = static_cast<QWidget*>( actionButton(KDialogBase::Ok)->parent() );
+ QBoxLayout* buttonBoxLayout = static_cast<QBoxLayout*>( buttonBox->layout() );
+ QCheckBox* useFixedFont = new QCheckBox( i18n("Use font with fixed width"), buttonBox );
+ buttonBoxLayout->insertWidget( 0, useFixedFont );
+ useFixedFont->setChecked( startupState );
+ connect( useFixedFont, SIGNAL( toggled(bool) ), SLOT( toggleFixedFont(bool) ) );
+}
+
+void KrActionProcDlg::addStderr( KProcess *, char *buffer, int buflen ) {
+ if (_stderr)
+ _stderr->append( QString::fromLatin1( buffer, buflen ) );
+ else {
+ _stdout->setItalic(true);
+ _stdout->append( QString::fromLatin1( buffer, buflen ) );
+ _stdout->setItalic(false);
+ }
+}
+
+void KrActionProcDlg::addStdout( KProcess *, char *buffer, int buflen ) {
+ _stdout->append( QString::fromLatin1( buffer, buflen ) );
+}
+
+void KrActionProcDlg::toggleFixedFont( bool state ) {
+ if ( state ) {
+ _stdout->setFont( fixedFont );
+ if ( _stderr )
+ _stderr->setFont( fixedFont );
+ }
+ else {
+ _stdout->setFont( normalFont );
+ if ( _stderr )
+ _stderr->setFont( normalFont );
+ }
+}
+
+void KrActionProcDlg::slotUser1() {
+ QString filename = KFileDialog::getSaveFileName(QString::null, i18n("*.txt|Text files\n*|all files"), this);
+ if ( filename.isEmpty() )
+ return;
+ QFile file( filename );
+ int answer = KMessageBox::Yes;
+ if ( file.exists() )
+ answer = KMessageBox::warningYesNoCancel( this, //parent
+ i18n("This file already exists.\nDo you want to overwrite it or append the output?"), //text
+ i18n("Overwrite or append?"), //caption
+ i18n("Overwrite"), //label for Yes-Button
+ i18n("Append") //label for No-Button
+ );
+ if ( answer == KMessageBox::Cancel )
+ return;
+ bool open;
+ if ( answer == KMessageBox::No ) // this means to append
+ open = file.open( IO_WriteOnly | IO_Append );
+ else
+ open = file.open( IO_WriteOnly );
+
+ if ( ! open ) {
+ KMessageBox::error( this,
+ i18n("Can't open %1 for writing!\nNothing exported.").arg(filename),
+ i18n("Export failed!")
+ );
+ return;
+ }
+
+ QTextStream stream( &file );
+ stream << _currentTextEdit->text();
+ file.close();
+}
+
+void KrActionProcDlg::currentTextEditChanged() {
+ if ( _stderr && _stderr->hasFocus() )
+ _currentTextEdit = _stderr;
+ else
+ _currentTextEdit = _stdout;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////// KrActionProc ////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KrActionProc::KrActionProc( KrActionBase* action ) : QObject(), _action( action ), _proc( new KProcess(this) ), _output( 0 ) {
+ _proc->setUseShell( true );
+
+ connect( _proc, SIGNAL( processExited( KProcess* ) ),
+ this, SLOT( processExited( KProcess* ) ) ) ;
+}
+
+KrActionProc::~KrActionProc() {
+ delete _proc;
+}
+
+void KrActionProc::start( QString cmdLine ) {
+ QStringList list = cmdLine;
+ start( list );
+}
+
+void KrActionProc::start( QStringList cmdLineList ) {
+ _proc->clearArguments();
+ QString cmd;
+
+ if ( ! _action->startpath().isEmpty() )
+ _proc->setWorkingDirectory( _action->startpath() );
+
+ if ( _action->execType() == KrAction::Terminal && cmdLineList.count() > 1)
+ KMessageBox::sorry( 0, i18n("Support for more than one command doesn't work in a terminal. Only the first is executed in the terminal.") );
+
+ if ( _action->execType() == KrAction::RunInTE
+ && ( MAIN_VIEW->konsole_part == NULL || MAIN_VIEW->konsole_part->widget() == NULL ) ) {
+ KMessageBox::sorry( 0, i18n("Embedded terminal emulator does not work, using output collection instead.") );
+ }
+
+ if( _action->execType() == KrAction::Normal || _action->execType() == KrAction::Terminal
+ || ( _action->execType() == KrAction::RunInTE && MAIN_VIEW->konsole_part && MAIN_VIEW->konsole_part->widget() )
+ ) { // not collect output
+ //TODO option to run them in paralell (not available for: collect output)
+ for ( QStringList::Iterator it = cmdLineList.begin(); it != cmdLineList.end(); ++it) {
+ if ( ! cmd.isEmpty() )
+ cmd += " ; "; //TODO make this separator configurable (users may want && or || for spec. actions)
+ cmd += *it;
+ }
+ //run in TE
+ if ( _action->execType() == KrAction::RunInTE ) {
+ //send the commandline contents to the terminal emulator
+ QKeyEvent keyEvent( QEvent::KeyPress, 0, -1, 0, cmd+"\n");
+ QApplication::sendEvent( MAIN_VIEW->konsole_part->widget(), &keyEvent );
+ } else { // will start a new process
+ // run in terminal
+ if ( _action->execType() == KrAction::Terminal ) {
+ krConfig->setGroup( "UserActions" );
+ QString term = krConfig->readEntry( "Terminal", _UserActions_Terminal );
+
+ if ( _action->user().isEmpty() )
+ ( *_proc ) << term << cmd;
+ else
+// ( *_proc ) << "kdesu" << "-u" << *_properties->user() << "-c" << KProcess::quote("konsole --noclose -e " + KProcess::quote(cmd) );
+ ( *_proc ) << "kdesu" << "-u" << _action->user() << "-c" << KProcess::quote( term + " " + cmd );
+ } else { // no terminal, no output collection, start&forget
+ if ( _action->user().isEmpty() )
+ ( *_proc ) << cmd;
+ else
+ ( *_proc ) << "kdesu" << "-u" << _action->user() << "-c" << KProcess::quote(cmd);
+ }
+ _proc->start( KProcess::NotifyOnExit, ( KProcess::Communication ) ( KProcess::Stdout | KProcess::Stderr ) );
+ }
+ }
+ else { // collect output
+ bool separateStderr = false;
+ if ( _action->execType() == KrAction::CollectOutputSeparateStderr )
+ separateStderr = true;
+ _output = new KrActionProcDlg( _action->text(), separateStderr );
+ // connect the output to the dialog
+ connect( _proc, SIGNAL( receivedStderr( KProcess*, char*, int ) ), _output, SLOT( addStderr( KProcess*, char *, int ) ) );
+ connect( _proc, SIGNAL( receivedStdout( KProcess*, char*, int ) ), _output, SLOT( addStdout( KProcess*, char *, int ) ) );
+ connect( _output, SIGNAL( cancelClicked() ), this, SLOT( kill() ) );
+ _output->show();
+ for ( QStringList::Iterator it = cmdLineList.begin(); it != cmdLineList.end(); ++it) {
+ if ( ! cmd.isEmpty() )
+ cmd += " ; "; //TODO make this separator configurable (users may want && or ||)
+ //TODO: read header fom config or action-properties and place it on top of each command
+ if ( cmdLineList.count() > 1 )
+ cmd += "echo --------------------------------------- ; ";
+ cmd += *it;
+ }
+ if ( _action->user().isEmpty() )
+ ( *_proc ) << cmd;
+ else
+ // "-t" is nessesary that kdesu displays the terminal-output of the command
+ ( *_proc ) << "kdesu" << "-t" << "-u" << _action->user() << "-c" << KProcess::quote(cmd);
+ _proc->start( KProcess::NotifyOnExit, ( KProcess::Communication ) ( KProcess::Stdout | KProcess::Stderr ) );
+ }
+
+}
+
+void KrActionProc::processExited( KProcess * ) {
+ // enable the 'close' button on the dialog (if active), disable 'kill' button
+ if ( _output ) {
+ _output->enableButtonOK( true );
+ _output->enableButtonCancel( false);
+ }
+ delete this; // banzai!!
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////// KrAction ///////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KrAction::KrAction( KActionCollection *parent, const char* name ) : KAction( parent, name ) {
+ connect(this, SIGNAL(activated()), this, SLOT(exec()) );
+}
+
+KrAction::~KrAction() {
+ unplugAll();
+ krUserAction->removeKrAction( this ); // Importent! Else Krusader will crash when writing the actions to file
+}
+
+bool KrAction::isAvailable( const KURL& currentURL ) {
+ bool available = true; //show per default (FIXME: make the default an attribute of <availability>)
+
+ //check protocol
+ if ( ! _showonlyProtocol.empty() ) {
+ available = false;
+ for ( QStringList::Iterator it = _showonlyProtocol.begin(); it != _showonlyProtocol.end(); ++it ) {
+ //kdDebug() << "KrAction::isAvailable currendProtocol: " << currentURL.protocol() << " =?= " << *it << endl;
+ if ( currentURL.protocol() == *it ) { // FIXME remove trailing slashes at the xml-parsing (faster because done only once)
+ available = true;
+ break;
+ }
+ }
+ } //check protocol: done
+
+ //check the Path-list:
+ if ( ! _showonlyPath.empty() ) {
+ available = false;
+ for ( QStringList::Iterator it = _showonlyPath.begin(); it != _showonlyPath.end(); ++it ) {
+ if ( (*it).right(1) == "*" ){
+ if ( currentURL.path().find( (*it).left( (*it).length() - 1 ) ) == 0 ) {
+ available = true;
+ break;
+ }
+ } else
+ if ( currentURL.directory() == *it ) { // FIXME remove trailing slashes at the xml-parsing (faster because done only once)
+ available = true;
+ break;
+ }
+ }
+ } //check the Path-list: done
+
+ //check mime-type
+ if ( ! _showonlyMime.empty() ) {
+ available = false;
+ KMimeType::Ptr mime = KMimeType::findByURL( currentURL );
+ for ( QStringList::Iterator it = _showonlyMime.begin(); it != _showonlyMime.end(); ++it ) {
+ if ( (*it).contains("/") ) {
+ if ( mime->is( *it ) ) { // don't use ==; use 'is()' instead, which is aware of inheritence (ie: text/x-makefile is also text/plain)
+ available = true;
+ break;
+ }
+ }
+ else {
+ if ( mime->name().find( *it ) == 0 ) { // 0 is the beginning, -1 is not found
+ available = true;
+ break;
+ }
+ }
+ } //for
+ } //check the mime-type: done
+
+ //check filename
+ if ( ! _showonlyFile.empty() ) {
+ available = false;
+ for ( QStringList::Iterator it = _showonlyFile.begin(); it != _showonlyFile.end(); ++it ) {
+ QRegExp regex = QRegExp( *it, false, true ); // case-sensitive = false; wildcards = true
+ if ( regex.exactMatch( currentURL.fileName() ) ) {
+ available = true;
+ break;
+ }
+ }
+ } //check the filename: done
+
+ return available;
+}
+
+
+bool KrAction::xmlRead( const QDomElement& element ) {
+/*
+ This has to be done elsewhere!!
+
+ if ( element.tagName() != "action" )
+ return false;
+
+ Also the name has to be checked before the action is created!
+
+ setName( element.attribute( "name" ).latin1() );
+*/
+
+ for ( QDomNode node = element.firstChild(); !node.isNull(); node = node.nextSibling() ) {
+ QDomElement e = node.toElement();
+ if ( e.isNull() )
+ continue; // this should skip nodes which are not elements ( i.e. comments, <!-- -->, or text nodes)
+
+ if ( e.tagName() == "title" )
+ setText( e.text() );
+ else
+ if ( e.tagName() == "tooltip" )
+ setToolTip( e.text() );
+ else
+ if ( e.tagName() == "icon" )
+ setIcon( e.text() );
+ else
+ if ( e.tagName() == "category" )
+ setCategory( e.text() );
+ else
+ if ( e.tagName() == "description" )
+ setWhatsThis( e.text() );
+ else
+ if (e.tagName() == "command")
+ readCommand( e );
+ else
+ if ( e.tagName() == "startpath" )
+ setStartpath( e.text() );
+ else
+ if (e.tagName() == "availability")
+ readAvailability( e );
+ else
+ if ( e.tagName() == "defaultshortcut" )
+ setShortcut( KShortcut( e.text() ) );
+ else
+
+ // unknown but not empty
+ if ( ! e.tagName().isEmpty() )
+ krOut << "KrAction::xmlRead() - unrecognized tag found: <action name=\"" << name() << "\"><" << e.tagName() << ">" << endl;
+
+ } // for ( QDomNode node = action->firstChild(); !node.isNull(); node = node.nextSibling() )
+
+ return true;
+} //KrAction::xmlRead
+
+QDomElement KrAction::xmlDump( QDomDocument& doc ) const {
+ QDomElement actionElement = doc.createElement("action");
+ actionElement.setAttribute( "name", name() );
+
+#define TEXT_ELEMENT( TAGNAME, TEXT ) \
+ { \
+ QDomElement e = doc.createElement( TAGNAME ); \
+ e.appendChild( doc.createTextNode( TEXT ) ); \
+ actionElement.appendChild( e ); \
+ }
+
+ TEXT_ELEMENT( "title", text() )
+
+ if ( ! toolTip().isEmpty() )
+ TEXT_ELEMENT( "tooltip", toolTip() )
+
+ if ( ! icon().isEmpty() )
+ TEXT_ELEMENT( "icon", icon() )
+
+ if ( ! category().isEmpty() )
+ TEXT_ELEMENT( "category", category() )
+
+ if ( ! whatsThis().isEmpty() )
+ TEXT_ELEMENT( "description", whatsThis() )
+
+ actionElement.appendChild( dumpCommand( doc ) );
+
+ if ( ! startpath().isEmpty() )
+ TEXT_ELEMENT( "startpath", startpath() )
+
+ QDomElement availabilityElement = dumpAvailability( doc );
+ if ( availabilityElement.hasChildNodes() )
+ actionElement.appendChild( availabilityElement );
+
+ if ( ! shortcut().isNull() )
+ TEXT_ELEMENT( "defaultshortcut", shortcut().toStringInternal() ) //.toString() would return a localised string which can't be read again
+
+ return actionElement;
+} //KrAction::xmlDump
+
+void KrAction::readCommand( const QDomElement& element ) {
+ QString attr;
+
+ attr = element.attribute( "executionmode", "normal" ); // default: "normal"
+ if ( attr == "normal")
+ setExecType( Normal );
+ else
+ if ( attr == "terminal" )
+ setExecType( Terminal );
+ else if ( attr == "collect_output")
+ setExecType( CollectOutput );
+ else if ( attr == "collect_output_separate_stderr")
+ setExecType( CollectOutputSeparateStderr );
+ else
+ krOut << "KrAction::readCommand() - unrecognized attribute value found: <action name=\"" << name() << "\"><command executionmode=\"" << attr << "\""<< endl;
+
+ attr = element.attribute( "accept", "local" ); // default: "local"
+ if ( attr == "local" )
+ setAcceptURLs( false );
+ else if ( attr == "url")
+ setAcceptURLs( true );
+ else
+ krOut << "KrAction::readCommand() - unrecognized attribute value found: <action name=\"" << name() << "\"><command accept=\"" << attr << "\""<< endl;
+
+ attr = element.attribute( "confirmexecution", "false" ); // default: "false"
+ if ( attr == "true" )
+ setConfirmExecution( true );
+ else
+ setConfirmExecution( false );
+
+ setUser( element.attribute( "run_as" ) );
+
+ setCommand( element.text() );
+
+} //KrAction::readCommand
+
+QDomElement KrAction::dumpCommand( QDomDocument& doc ) const {
+ QDomElement commandElement = doc.createElement("command");
+
+ switch ( execType() ) {
+ case Terminal:
+ commandElement.setAttribute( "executionmode", "terminal" );
+ break;
+ case CollectOutput:
+ commandElement.setAttribute( "executionmode", "collect_output" );
+ break;
+ case CollectOutputSeparateStderr:
+ commandElement.setAttribute( "executionmode", "collect_output_separate_stderr" );
+ break;
+ default:
+ // don't write the default to file
+ break;
+ }
+
+ if ( acceptURLs() )
+ commandElement.setAttribute( "accept", "url" );
+
+ if ( confirmExecution() )
+ commandElement.setAttribute( "confirmexecution", "true" );
+
+ if ( ! user().isEmpty() )
+ commandElement.setAttribute( "run_as", user() );
+
+ commandElement.appendChild( doc.createTextNode( command() ) );
+
+ return commandElement;
+} //KrAction::dumpCommand
+
+void KrAction::readAvailability( const QDomElement& element ) {
+ for ( QDomNode node = element.firstChild(); ! node.isNull(); node = node.nextSibling() ) {
+ QDomElement e = node.toElement();
+ if ( e.isNull() )
+ continue; // this should skip nodes which are not elements ( i.e. comments, <!-- -->, or text nodes)
+
+ QStringList* showlist = 0;
+
+ if ( e.tagName() == "protocol" )
+ showlist = &_showonlyProtocol;
+ else
+ if ( e.tagName() == "path" )
+ showlist = &_showonlyPath;
+ else
+ if ( e.tagName() == "mimetype" )
+ showlist = & _showonlyMime;
+ else
+ if ( e.tagName() == "filename" )
+ showlist = & _showonlyFile;
+ else {
+ krOut << "KrAction::readAvailability() - unrecognized element found: <action name=\"" << name() << "\"><availability><" << e.tagName() << ">"<< endl;
+ showlist = 0;
+ }
+
+ if ( showlist ) {
+ for ( QDomNode subnode = e.firstChild(); ! subnode.isNull(); subnode = subnode.nextSibling() ) {
+ QDomElement subelement = subnode.toElement();
+ if ( subelement.tagName() == "show" )
+ showlist->append( subelement.text() );
+ } // for
+ } // if ( showlist )
+
+ } // for
+} //KrAction::readAvailability
+
+QDomElement KrAction::dumpAvailability( QDomDocument& doc ) const {
+ QDomElement availabilityElement = doc.createElement("command");
+
+# define LIST_ELEMENT( TAGNAME, LIST ) \
+ { \
+ QDomElement e = doc.createElement( TAGNAME ); \
+ for ( QStringList::const_iterator it = LIST.constBegin(); it != LIST.constEnd(); ++it ) { \
+ QDomElement show = doc.createElement( "show" ); \
+ show.appendChild( doc.createTextNode( *it ) ); \
+ e.appendChild( show ); \
+ } \
+ availabilityElement.appendChild( e ); \
+ }
+
+ if ( ! _showonlyProtocol.isEmpty() )
+ LIST_ELEMENT( "protocol", _showonlyProtocol )
+
+ if ( ! _showonlyPath.isEmpty() )
+ LIST_ELEMENT( "path", _showonlyPath )
+
+ if ( ! _showonlyMime.isEmpty() )
+ LIST_ELEMENT( "mimetype", _showonlyMime )
+
+ if ( ! _showonlyFile.isEmpty() )
+ LIST_ELEMENT( "filename", _showonlyFile )
+
+ return availabilityElement;
+} //KrAction::dumpAvailability
+
+#include "kraction.moc"
diff --git a/krusader/UserAction/kraction.h b/krusader/UserAction/kraction.h
new file mode 100644
index 0000000..2d8b81b
--- /dev/null
+++ b/krusader/UserAction/kraction.h
@@ -0,0 +1,167 @@
+//
+// C++ Interface: kraction
+//
+// Description:
+//
+//
+// Author: Krusader Krew <http://www.krusader.org>, (C) 2004, 2006
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#ifndef KRACTION_H
+#define KRACTION_H
+
+#include <kaction.h>
+#include <kprocess.h>
+#include <kdialogbase.h>
+#include "kractionbase.h"
+
+class UserActionProperties;
+class QTextEdit;
+class KActionCollection;
+class QDomElement;
+class QDomDocument;
+
+/**
+ * This subclass of KAction extends it with an individual executor and a struct UserActionProperties. It is used to integrate useractions into KDE's KAction-System
+ * @author Jonas Bähr (http://www.jonas-baehr.de)
+ */
+class KrAction: public KAction, public KrActionBase {
+ Q_OBJECT
+ public:
+ KrAction( KActionCollection *parent, const char* name );
+ ~KrAction();
+
+ /**
+ * This chekcs if the KrAction is for a specific file / location available
+ * @param currentURL Check for this file
+ * @return true if the KrAction if available
+ */
+ bool isAvailable( const KURL& currentURL );
+
+ bool xmlRead( const QDomElement& element );
+ QDomElement xmlDump( QDomDocument& doc ) const;
+
+ void setName( const char* ) { /* empty reimplementation to prevent a name-change */ };
+
+ QString category() const { return _category; };
+ void setCategory( const QString& category ) { _category = category; };
+
+ QString command() const { return _command; };
+ void setCommand( const QString& command ) { _command = command; };
+
+ QString user() const { return _user; };
+ void setUser( const QString& user ) { _user = user; };
+
+ QString startpath() const { return _startpath; };
+ void setStartpath( const QString& startpath ) { _startpath = startpath; };
+
+ ExecType execType() const { return _execType; };
+ void setExecType( ExecType execType ) { _execType = execType; };
+
+ bool acceptURLs() const { return _acceptURLs; };
+ void setAcceptURLs(const bool& acceptURLs) { _acceptURLs = acceptURLs; };
+
+ bool confirmExecution() const { return _confirmExecution; };
+ void setConfirmExecution(const bool& confirmExecution) { _confirmExecution = confirmExecution; };
+
+ QStringList showonlyProtocol() const { return _showonlyProtocol; };
+ void setShowonlyProtocol( const QStringList& showonlyProtocol ) { _showonlyProtocol = showonlyProtocol; };
+
+ QStringList showonlyPath() const { return _showonlyPath; };
+ void setShowonlyPath( const QStringList& showonlyPath ) { _showonlyPath = showonlyPath; };
+
+ QStringList showonlyMime() const { return _showonlyMime; };
+ void setShowonlyMime( const QStringList& showonlyMime ) { _showonlyMime = showonlyMime; };
+
+ QStringList showonlyFile() const { return _showonlyFile; };
+ void setShowonlyFile( const QStringList& showonlyFile ) { _showonlyFile = showonlyFile; };
+
+ bool doSubstitution() const {
+ return true;
+ }
+
+ QString text() const {
+ return KAction::text();
+ }
+
+ public slots:
+ void exec() {
+ KrActionBase::exec();
+ }
+
+
+ private:
+ void readCommand( const QDomElement& element );
+ QDomElement dumpCommand( QDomDocument& doc ) const;
+
+ void readAvailability( const QDomElement& element );
+ QDomElement dumpAvailability( QDomDocument& doc ) const;
+
+ QString _category;
+ QString _command;
+ QString _user;
+ QString _startpath;
+ ExecType _execType;
+ bool _acceptURLs;
+ bool _confirmExecution;
+ QStringList _showonlyProtocol;
+ QStringList _showonlyPath;
+ QStringList _showonlyMime;
+ QStringList _showonlyFile;
+
+};
+
+class QFont;
+/**
+ * This displays the output of a process
+ * @author Shie Erlich, Jonas Bähr
+ */
+class KrActionProcDlg: public KDialogBase {
+ Q_OBJECT
+ public:
+ KrActionProcDlg( QString caption, bool enableStderr = false, QWidget *parent = 0 );
+
+ protected slots:
+ void addStderr( KProcess *proc, char *buffer, int buflen );
+ void addStdout( KProcess *proc, char *buffer, int buflen );
+ void toggleFixedFont( bool state );
+ void slotUser1(); ///< This is used to save the buffer to disc
+
+ private:
+ QTextEdit *_stdout, *_stderr, *_currentTextEdit;
+ QFont normalFont, fixedFont;
+ private slots:
+ void currentTextEditChanged();
+};
+
+/**
+ * This executes a command of a UserAction
+ * @author Shie Erlich, Jonas Bähr
+ * @todo jonas: call a list of commands separately (I began it but it doesn't work)
+ */
+class KrActionProc: public QObject {
+ Q_OBJECT
+ public:
+
+ KrActionProc( KrActionBase* action );
+ virtual ~KrActionProc();
+ void start( QString cmdLine );
+ void start( QStringList cmdLineList );
+
+ protected slots:
+ void kill() { _proc->kill( SIGINT ); }
+ void processExited( KProcess *proc );
+
+ private:
+ KrActionBase* _action;
+ KProcess *_proc;
+ QString _stdout;
+ QString _stderr;
+ KrActionProcDlg *_output;
+};
+
+
+#endif //KRACTION_H
diff --git a/krusader/UserAction/kractionbase.cpp b/krusader/UserAction/kractionbase.cpp
new file mode 100644
index 0000000..233a218
--- /dev/null
+++ b/krusader/UserAction/kractionbase.cpp
@@ -0,0 +1,77 @@
+//
+// C++ Implementation: kractionbase
+//
+// Description:
+//
+//
+// Author: Shie Erlich and Rafi Yanai <>, (C) 2006
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include <kinputdialog.h>
+#include <klocale.h>
+
+#include <qerrormessage.h>
+
+#include "kraction.h"
+#include "expander.h"
+#include "kractionbase.h"
+
+KrActionBase::~KrActionBase()
+{
+}
+
+void KrActionBase::exec() {
+ KrActionProc *proc;
+
+ // replace %% and prepare string
+ QStringList commandList;
+ if(doSubstitution()) {
+ Expander exp;
+ exp.expand(command(),acceptURLs());
+ if(exp.error()) {
+ handleError(exp.error());
+ return;
+ }
+ commandList=exp.result();
+ } else
+ commandList=command();
+ //TODO: query expander for status and may skip the rest of the function
+
+ // stop here if the commandline is empty
+ if ( commandList.count() == 1 && commandList[0].stripWhiteSpace().isEmpty() )
+ return;
+
+ if ( confirmExecution() ) {
+ for ( QStringList::iterator it = commandList.begin(); it != commandList.end(); ++it ) {
+ bool exec = true;
+ *it = KInputDialog::getText(
+ i18n( "Confirm execution" ),
+ i18n( "Command being executed:" ),
+ *it,
+ &exec, 0
+ );
+ if ( exec ) {
+ proc = actionProcFactoryMethod();
+ proc->start( *it );
+ }
+ } //for
+ } // if ( _properties->confirmExecution() )
+ else {
+ proc = actionProcFactoryMethod();
+ proc->start( commandList );
+ }
+
+}
+
+void KrActionBase::handleError(const Error& err)
+{
+ QErrorMessage::qtHandler()->message(err.what());
+}
+
+KrActionProc* KrActionBase::actionProcFactoryMethod()
+{
+ return new KrActionProc(this);
+}
diff --git a/krusader/UserAction/kractionbase.h b/krusader/UserAction/kractionbase.h
new file mode 100644
index 0000000..271dfb7
--- /dev/null
+++ b/krusader/UserAction/kractionbase.h
@@ -0,0 +1,97 @@
+//
+// C++ Interface: kractionbase
+//
+// Description:
+//
+//
+// Author: Shie Erlich and Rafi Yanai <>, (C) 2006
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef KRACTIONBASE_H
+#define KRACTIONBASE_H
+
+#include <qstring.h>
+#include "expander.h"
+class KrActionProc;
+
+class KrActionBase
+{
+public:
+ KrActionBase() {}
+ virtual ~KrActionBase();
+
+ /** \brief Specifies the mode for executing the action */
+ enum ExecType {
+ Normal, ///< Run the command freely
+ Terminal, ///< Run the command in new terminal window
+ CollectOutput, ///< Collect output from this command
+ CollectOutputSeparateStderr, ///< Like #CollectOutput, but display stderr output separately
+ RunInTE ///< Run in built-in terminal emulator
+ };
+
+ /** \brief Command which runs this action
+ *
+ * The string of the command may contain placeholders
+ * which are parsed by the #Expander class, unless #doSubstitution
+ * returns false
+ *
+ * The command is run by the shell, which should be bash (see #Expander)
+ *
+ * @see Expander
+ * @see doSubstitution
+ *
+ * @return The command to execute
+ */
+ virtual QString command() const =0;
+ /** \brief Execution type of the action
+ *
+ * @see #ExecType
+ */
+ virtual ExecType execType() const =0;
+ /** \brief Working directory of the command
+ *
+ * @return The working directory of the command. May be \a null,
+ * in which case the command is executed in current directory
+ */
+ virtual QString startpath() const =0;
+ /** \brief Username under which the command is run
+ *
+ * @return The username of the command. May be \a null,
+ * in which case the command is executed under the current user
+ */
+ virtual QString user() const=0;
+ /** \brief Name of the action
+ *
+ * @return The name of the action which will be shown to the user
+ * eg. any string will do
+ */
+ virtual QString text() const=0;
+ /** \brief Does the command accept URLs as filenames (like KDE apps)?
+ *
+ * @return \a true iff it does
+ */
+ virtual bool acceptURLs() const=0;
+ /** \brief Confirm execution of this action by the user?
+ *
+ * @return \a true iff execution should be confirmed
+ */
+ virtual bool confirmExecution() const=0;
+ /** \brief Can #command contain placeholders?
+ *
+ * @return \a true iff #command should be expanded by #Expander
+ */
+ virtual bool doSubstitution() const=0;
+ /** \brief A factory method for creating KrActionProc
+ *
+ * @return A new instance of KrActionProc
+ */
+ virtual KrActionProc* actionProcFactoryMethod();
+ virtual void handleError(const Error& err);
+
+ void exec();
+
+};
+
+#endif
diff --git a/krusader/UserAction/tstring.h b/krusader/UserAction/tstring.h
new file mode 100644
index 0000000..2ddd80c
--- /dev/null
+++ b/krusader/UserAction/tstring.h
@@ -0,0 +1,113 @@
+//
+// C++ Interface: tstring
+//
+// Description:
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#ifndef __TAGSTRING__H
+#define __TAGSTRING__H
+
+#include <qstring.h>
+#include <qvaluelist.h>
+#include <utility>
+#include <cassert>
+template <class T>
+class TagString_t
+{
+ QString str;
+ typedef QValueList<std::pair<uint,T> > taglist; // may change
+ taglist tags;
+public:
+ TagString_t(const QString& s) : str(s) {}
+ TagString_t() {}
+ bool isSimple() const { return tags.empty(); }
+ const QString& string() const { return str; }
+ unsigned length() const { return str.length(); }
+ TagString_t mid(unsigned idx,unsigned len=~0) const;
+ TagString_t left(unsigned) const;
+ TagString_t right(unsigned) const;
+ void insert(uint,const QString& s);
+ int find ( QChar c, int index = 0, bool cs = TRUE ) const {
+ return str.find(c,index,cs);
+ }
+ TagString_t& operator+=(const TagString_t& s);
+ typename taglist::const_iterator tagsBegin() const { return tags.begin(); }
+ typename taglist::const_iterator tagsEnd() const { return tags.end(); }
+ typename taglist::iterator tagsBegin() { return tags.begin(); }
+ typename taglist::iterator tagsEnd() { return tags.end(); }
+ void insertTag(uint pos,const T& t);
+ void eraseTag(const typename taglist::iterator& which) { tags.erase(which); }
+/* void insert(uint idx,const QString&);
+ void insert(uint idx,const char*);
+ void addTag(uint);
+ void remove(uint start,uint len);*/
+};
+
+template <class T>
+TagString_t<T> TagString_t<T>::mid(unsigned idx,unsigned len) const
+{
+ TagString_t ret(str.mid(idx,len));
+ unsigned max=idx+len;
+ if(max<idx) max=~0;
+ for(typename taglist::const_iterator it=tags.begin(),end=tags.end();it!=end;++it) {
+ if((*it).first>=idx && (*it).first<max)
+ ret.tags.push_back(*it);
+ }
+ return ret;
+}
+
+template <class T>
+TagString_t<T> TagString_t<T>::left(unsigned len) const
+{
+ TagString_t ret(str.left(len));
+ for(typename taglist::const_iterator it=tags.begin(),end=tags.end();it!=end;++it) {
+ if((*it).first<len)
+ ret.tags.push_back(*it);
+ }
+ return ret;
+}
+
+template <class T>
+TagString_t<T> TagString_t<T>::right(unsigned len) const
+{
+ TagString_t ret(str.right(len));
+ for(typename taglist::const_iterator it=tags.begin(),end=tags.end();it!=end;++it) {
+ if((*it).first>=str.length()-len)
+ ret.tags.push_back(*it);
+ }
+ return ret;
+}
+
+template <class T>
+void TagString_t<T>::insert(uint idx,const QString& s)
+{
+ str.insert(idx,s);
+ const unsigned disp=s.length();
+ for(typename taglist::iterator it=tags.begin(),end=tags.end();it!=end;++it) {
+ if((*it).first>=idx)
+ (*it).first+=disp;
+ }
+}
+
+template <class T>
+TagString_t<T>& TagString_t<T>::operator+=(const TagString_t& s)
+{
+ str+=s.str;
+ const unsigned disp=length();
+ for(typename taglist::const_iterator it=s.tags.begin(),end=s.tags.end();it!=end;++it) {
+ tags.push_back(make_pair((*it).first+disp,(*it).second));
+ }
+ return *this;
+}
+
+template <class T>
+void TagString_t<T>::insertTag(uint pos,const T& t)
+{
+ assert(pos<=length());
+ tags.push_back(make_pair(pos,t));
+}
+
+#endif
diff --git a/krusader/UserAction/useraction.cpp b/krusader/UserAction/useraction.cpp
new file mode 100644
index 0000000..f1a9a4b
--- /dev/null
+++ b/krusader/UserAction/useraction.cpp
@@ -0,0 +1,210 @@
+//
+// C++ Implementation: useraction
+//
+// Description: This manages all useractions
+//
+//
+// Author: Jonas B�r (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include <kdebug.h>
+#include <kurl.h>
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+#include <kmessagebox.h>
+
+#include <qstring.h>
+#include <qdom.h>
+
+#include "useraction.h"
+#include "kraction.h"
+
+#include "../krusader.h"
+#include "../krusaderview.h"
+#include "../Panel/listpanel.h"
+#include "../Panel/panelfunc.h"
+
+
+UserAction::UserAction() {
+ _actions.setAutoDelete( false ); // the actions are "owned" by Krusader's KActionCollection, so they should not be deleted
+ krOut << "Initialisising useractions..." << endl;
+ readAllFiles();
+ krOut << _actions.count() << " useractions read." << endl;
+}
+
+UserAction::~UserAction() {
+ // KrActions are deleted by Krusader's KActionCollection
+}
+
+void UserAction::setAvailability() {
+ setAvailability( ACTIVE_FUNC->files()->vfs_getFile( ACTIVE_PANEL->view->getCurrentItem() ) );
+}
+
+void UserAction::setAvailability( const KURL& currentURL ) {
+ //kdDebug() << "UserAction::setAvailability currendFile: " << currentURL.url() << endl;
+ // disable the entries that should not appear in this folder
+ for ( KrAction* action = _actions.first(); action; action = _actions.next() )
+ action->setEnabled( action->isAvailable( currentURL ) );
+}
+
+void UserAction::populateMenu( KPopupMenu* menu ) {
+ for ( KrAction* action = _actions.first(); action; action = _actions.next() )
+ if ( ! action->isPlugged( menu ) )
+ action->plug( menu );
+}
+
+QStringList UserAction::allCategories() {
+ QStringList actionCategories;
+
+ for ( KrAction* action = _actions.first(); action; action = _actions.next() )
+ if ( actionCategories.find( action->category() ) == actionCategories.end() )
+ actionCategories.append( action->category() );
+
+ return actionCategories;
+}
+
+QStringList UserAction::allNames() {
+ QStringList actionNames;
+
+ for ( KrAction* action = _actions.first(); action; action = _actions.next() )
+ actionNames.append( action->name() );
+
+ return actionNames;
+}
+
+void UserAction::readAllFiles() {
+ QString filename = locate( "data", ACTION_XML ); // locate returns the local file if it exists, else the global one is retrieved.
+ if ( ! filename.isEmpty() )
+ readFromFile( locate( "data", ACTION_XML ), renameDoublicated );
+
+ filename = locate( "data", ACTION_XML_EXAMPLES );
+ if ( ! filename.isEmpty() )
+ readFromFile( locate( "data", ACTION_XML_EXAMPLES ), ignoreDoublicated ); // ignore samples which are already in the normal file
+}
+
+void UserAction::readFromFile( const QString& filename, ReadMode mode, KrActionList* list ) {
+ QDomDocument* doc = new QDomDocument( ACTION_DOCTYPE );
+ QFile file( filename );
+ if( file.open( IO_ReadOnly ) ) {
+ //kdDebug() << "UserAction::readFromFile - " << filename << "could be opened" << endl;
+ if( ! doc->setContent( &file ) ) {
+ //kdDebug() << "UserAction::readFromFile - content set - failed" << endl;
+ // if the file doesn't exist till now, the content CAN be set but is empty.
+ // if the content can't be set, the file exists and is NOT an xml-file.
+ file.close();
+ delete doc; doc = 0;
+ KMessageBox::error( MAIN_VIEW,
+ i18n( "The file %1 does not contain valid UserActions.\n" ).arg( filename ), // text
+ i18n("UserActions - can't read from file!") // caption
+ );
+ }
+ file.close();
+
+ if ( doc ) {
+ QDomElement root = doc->documentElement();
+ // check if the file got the right root-element (ACTION_ROOT) - this finds out if the xml-file read to the DOM is realy an krusader useraction-file
+ if( root.tagName() != ACTION_ROOT ) {
+ KMessageBox::error( MAIN_VIEW,
+ i18n( "The actionfile's root-element isn't called "ACTION_ROOT", using %1").arg( filename ),
+ i18n( "UserActions - can't read from file!" )
+ );
+ delete doc; doc = 0;
+ }
+ readFromElement( root, mode, list );
+ delete doc;
+ }
+
+ } // if ( file.open( IO_ReadOnly ) )
+ else {
+ KMessageBox::error( MAIN_VIEW,
+ i18n( "Unable to open actionfile %1").arg( filename ),
+ i18n( "UserActions - can't read from file!" )
+ );
+ }
+
+}
+
+void UserAction::readFromElement( const QDomElement& element, ReadMode mode, KrActionList* list ) {
+ for ( QDomNode node = element.firstChild(); ! node.isNull(); node = node.nextSibling() ) {
+ QDomElement e = node.toElement();
+ if ( e.isNull() )
+ continue; // this should skip nodes which are not elements ( i.e. comments, <!-- -->, or text nodes)
+
+ if ( e.tagName() == "action" ) {
+ QString name = e.attribute( "name" );
+ if ( name.isEmpty() ) {
+ KMessageBox::error( MAIN_VIEW,
+ i18n( "Action without name detected. This action will not be imported!\nThis is an error in the file, you may want to correct it." ),
+ i18n( "UserActions - invalid action" )
+ );
+ continue;
+ }
+
+ if ( mode == ignoreDoublicated && krApp->actionCollection()->action( name.latin1() ) )
+ continue;
+
+ QString basename = name + "_%1";
+ int i = 0;
+ // appent a counter till the name is unique... (this checks every action, not only useractions)
+ while ( krApp->actionCollection()->action( name.latin1() ) )
+ name = basename.arg( ++i );
+
+ KrAction* act = new KrAction( krApp->actionCollection(), name.latin1() );
+ if ( act->xmlRead( e ) ) {
+ _actions.append( act );
+ if ( list )
+ list->append( act );
+ }
+ else
+ delete act;
+ }
+ } // for
+}
+
+QDomDocument UserAction::createEmptyDoc() {
+ QDomDocument doc = QDomDocument( ACTION_DOCTYPE );
+ // adding: <?xml version="1.0" encoding="UTF-8" ?>
+ doc.appendChild( doc.createProcessingInstruction( "xml", ACTION_PROCESSINSTR ) );
+ //adding root-element
+ doc.appendChild( doc.createElement( ACTION_ROOT ) ); // create new actionfile by adding a root-element ACTION_ROOT
+ return doc;
+}
+
+bool UserAction::writeActionFile() {
+ QString filename = locateLocal( "data", ACTION_XML );
+
+ QDomDocument doc = createEmptyDoc();
+ QDomElement root = doc.documentElement();
+ for ( KrAction* action = _actions.first(); action; action = _actions.next() )
+ root.appendChild( action->xmlDump( doc ) );
+
+ return writeToFile( doc, filename );
+}
+
+bool UserAction::writeToFile( const QDomDocument& doc, const QString& filename ) {
+ QFile file( filename );
+ if( ! file.open( IO_WriteOnly ) )
+ return false;
+
+/* // This is not needed, because each DomDocument created with UserAction::createEmptyDoc already contains the processinstruction
+ if ( ! doc.firstChild().isProcessingInstruction() ) {
+ // adding: <?xml version="1.0" encoding="UTF-8" ?> if not already present
+ QDomProcessingInstruction instr = doc.createProcessingInstruction( "xml", ACTION_PROCESSINSTR );
+ doc.insertBefore( instr, doc.firstChild() );
+ }
+*/
+
+ QTextStream ts( &file );
+ ts.setEncoding(ts.UnicodeUTF8);
+ ts << doc.toString();
+
+ file.close();
+ return true;
+}
+
+
+
+
diff --git a/krusader/UserAction/useraction.h b/krusader/UserAction/useraction.h
new file mode 100644
index 0000000..cfdeee8
--- /dev/null
+++ b/krusader/UserAction/useraction.h
@@ -0,0 +1,145 @@
+//
+// C++ Interface: useraction
+//
+// Description: This manages all useractions
+//
+//
+// Author: Jonas Bähr (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#ifndef USERACTION_H
+#define USERACTION_H
+
+#include <qptrlist.h>
+
+class QDomDocument;
+class QDomElement;
+class QString;
+class QStringList;
+class KrAction;
+class KURL;
+class KPopupMenu;
+
+/**
+ * Useractions are Krusaders backend for user-defined actions on current/selected files in its panels
+ * and for krusader's internal actions which need some parameter. @n
+ * There are several komponents:
+ * - The UserAction class as a Manager
+ * - The interface to KDE's action-system (the KrAction)
+ * - The Expander, which parses the commandline for placeholders and calls the internal actions
+ * - A widget to manipulate the UserAction's Properties via GUI (ActionProperty)
+ * .
+ * The Useractions are stored in XML-files. Currently there are two main files. The first is a global example-file
+ * which is read only (read after the other actionfiles, doublicates are ignored) and a local file where the actions are saved.
+ * This class reads only the container and passes each action-tag to the new KrAction, which reads it's data itself.
+ *
+ * @author Jonas Bähr (http://www.jonas-baehr.de)
+ */
+
+class UserAction {
+public:
+
+ typedef QPtrList<KrAction> KrActionList;
+
+ enum ReadMode { renameDoublicated, ignoreDoublicated };
+
+ /**
+ * The constructor reads all useractions, see readAllFiles()
+ */
+ UserAction();
+ ~UserAction();
+
+ /**
+ * adds an action to the collection.
+ */
+ void addKrAction( KrAction* action ) { _actions.append( action ); };
+
+ /**
+ * Use this to access the whole list of registerd KrActions.
+ * currently only used to fill the usermenu with all available actions. This should change...
+ * @return A reference to the internal KrActionList
+ */
+ const KrActionList &actionList() { return _actions; };
+
+ /**
+ * @return how many useractions exist
+ */
+ int count() const { return _actions.count(); };
+
+ /**
+ * removes a KrAction from the internal list but does not delete it.
+ * @param action the KrAction which should be removed
+ */
+ void removeKrAction( KrAction* action ) { _actions.remove( action ); };
+
+ /**
+ * check for each KrAction if it is available for the currend location / file and disables it if not
+ */
+ void setAvailability();
+ /**
+ * same as above but check for a specitic file
+ * @param currentURL Check for this file
+ */
+ void setAvailability(const KURL& currentURL);
+
+ /**
+ * Fills a KPopupMenu with all available UserActions in the list
+ * @param popupmenu to populate
+ */
+ void populateMenu(KPopupMenu* menu);
+
+ QStringList allCategories();
+ QStringList allNames();
+
+ /**
+ * reads all predefined useractionfiles.
+ */
+ void readAllFiles();
+ /**
+ * writes all actions to the local actionfile
+ */
+ bool writeActionFile();
+ /**
+ * Reads UserActions from a xml-file.
+ * @param list If provided, all new actions will also be added to this list
+ */
+ void readFromFile( const QString& filename, ReadMode mode = renameDoublicated, KrActionList* list = 0 );
+ /**
+ * Reads UserActions from a XML-Element.
+ * @param element a container with action-elements
+ * @param list If provided, all new actions will also be added to this list
+ */
+ void readFromElement( const QDomElement& element, ReadMode mode = renameDoublicated, KrActionList* list = 0 );
+
+ /**
+ * creates an empty QDomDocument for the UserActions
+ */
+ static QDomDocument createEmptyDoc();
+ /**
+ * Writes a QDomDocument to an UTF-8 encodes text-file
+ * @param doc the XML-Tree
+ * @param filename the filename where to save
+ * @return true on success, false otherwise
+ * @warning any existing file will get overwritten!
+ */
+ static bool writeToFile( const QDomDocument& doc, const QString& filename );
+
+private:
+ KrActionList _actions;
+};
+
+
+#define ACTION_XML "krusader/useractions.xml"
+#define ACTION_XML_EXAMPLES "krusader/useraction_examples.xml"
+
+#define ACTION_DOCTYPE "KrusaderUserActions"
+// in well formed XML the root-element has to have the same name then the doctype:
+#define ACTION_ROOT ACTION_DOCTYPE
+#define ACTION_PROCESSINSTR "version=\"1.0\" encoding=\"UTF-8\" "
+
+
+
+#endif // ifndef USERACTION_H
diff --git a/krusader/UserAction/useractionpopupmenu.cpp b/krusader/UserAction/useractionpopupmenu.cpp
new file mode 100644
index 0000000..0b70647
--- /dev/null
+++ b/krusader/UserAction/useractionpopupmenu.cpp
@@ -0,0 +1,26 @@
+//
+// C++ Implementation: UserActionPopupMenu
+//
+// Description:
+//
+//
+// Author: Jonas B�r (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include "useractionpopupmenu.h"
+
+#include <kurl.h>
+
+#include "../krusader.h"
+#include "useraction.h"
+#include "kraction.h"
+
+UserActionPopupMenu::UserActionPopupMenu( KURL currentURL, QWidget *parent ) : KPopupMenu( parent, "useraction popupmenu" ) {
+ UserAction::KrActionList list = krUserAction->actionList();
+ for ( KrAction* action = list.first(); action; action = list.next() )
+ if ( action->isAvailable( currentURL ) )
+ action->plug( this );
+}
diff --git a/krusader/UserAction/useractionpopupmenu.h b/krusader/UserAction/useractionpopupmenu.h
new file mode 100644
index 0000000..8bf36ba
--- /dev/null
+++ b/krusader/UserAction/useractionpopupmenu.h
@@ -0,0 +1,25 @@
+//
+// C++ Interface: UserActionPopupMenu
+//
+// Description:
+//
+//
+// Author: Jonas Bhr, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#ifndef USERACTIONPOPUPMENU_H
+#define USERACTIONPOPUPMENU_H
+
+#include <kpopupmenu.h>
+
+class KURL;
+
+class UserActionPopupMenu : public KPopupMenu {
+public:
+ UserActionPopupMenu( KURL currentURL, QWidget *parent = 0 );
+};
+
+#endif // ifndef USERACTIONPOPUPMENU_H
diff --git a/krusader/UserMenu/Makefile.am b/krusader/UserMenu/Makefile.am
new file mode 100644
index 0000000..1d48899
--- /dev/null
+++ b/krusader/UserMenu/Makefile.am
@@ -0,0 +1,7 @@
+noinst_LIBRARIES = libUserMenu.a
+
+INCLUDES = $(all_includes)
+
+libUserMenu_a_METASOURCES = AUTO
+
+libUserMenu_a_SOURCES = usermenu.cpp
diff --git a/krusader/UserMenu/usermenu.cpp b/krusader/UserMenu/usermenu.cpp
new file mode 100644
index 0000000..ee403f0
--- /dev/null
+++ b/krusader/UserMenu/usermenu.cpp
@@ -0,0 +1,85 @@
+/***************************************************************************
+ _expressionsu.cpp - description
+ -------------------
+begin : Sat Dec 6 2003
+copyright : (C) 2003 by Shie Erlich & Rafi Yanai
+email :
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include "../krusader.h"
+#include "../Konfigurator/konfigurator.h"
+#include "../UserAction/kraction.h"
+#include "../UserAction/useraction.h"
+#include "usermenu.h"
+
+
+void UserMenu::exec() {
+ _popup->run();
+}
+
+UserMenu::UserMenu( QWidget * parent, const char * name ) : QWidget( parent, name ) {
+ _popup = new UserMenuGui(this);
+}
+
+void UserMenu::update() {
+ _popup->createMenu();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+UserMenuGui::UserMenuGui( UserMenu *, QWidget * parent ) : KPopupMenu( parent ) {
+ createMenu();
+}
+
+void UserMenuGui::createMenu() {
+// kdDebug() << "UserMenuGui::createMenu called" << endl;
+ clear();
+ insertTitle( i18n("User Menu") );
+
+ // read entries from config file.
+ readEntries();
+
+ // add the "add new entry" command
+ insertSeparator();
+ insertItem( i18n("Manage user actions"), 0 );
+}
+
+void UserMenuGui::readEntries() {
+ // Note: entries are marked 1..n, so that entry 0 is always
+ // available. It is used by the "add new entry" command.
+ int idx = 1;
+
+ //FIXME: don't plug ALL useractions into the usermenu. TODO: read the usermenu-strukture from an other file (krusaderrc ?)
+ UserAction::KrActionList list = krUserAction->actionList();
+ for ( KrAction* action = list.first(); action; action = list.next() )
+ action->plug( this, idx++ );
+
+}
+
+void UserMenuGui::run() {
+ //disable unwanted actions:
+ // disabled due to conflicts with the toolbar (a check on each file-cursor-movement would be nessesary; hit the performance)
+// krApp->userAction->setAvailability();
+
+ int idx = exec();
+ if ( idx == -1 ) // nothing was selected
+ return;
+ if ( idx == 0 ) {
+ Konfigurator konfigurator( false, 7 ); // page 7 are the UserActions
+ return;
+ }
+}
diff --git a/krusader/UserMenu/usermenu.h b/krusader/UserMenu/usermenu.h
new file mode 100644
index 0000000..f69e0a9
--- /dev/null
+++ b/krusader/UserMenu/usermenu.h
@@ -0,0 +1,46 @@
+/***************************************************************************
+ usermenu.h - description
+ -------------------
+begin : Sat Dec 6 2003
+copyright : (C) 2003 by Shie Erlich & Rafi Yanai
+email :
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef USERMENU_H
+#define USERMENU_H
+
+#include <kpopupmenu.h>
+
+class QWidget;
+class UserMenu;
+
+class UserMenuGui: public KPopupMenu {
+ public:
+ UserMenuGui( UserMenu* menu, QWidget *parent = 0 );
+ void run();
+ void createMenu();
+
+ protected:
+ void readEntries();
+};
+
+class UserMenu : public QWidget {
+ public:
+ UserMenu( QWidget *parent = 0, const char *name = 0 );
+ void exec();
+ void update();
+
+ private:
+ UserMenuGui* _popup;
+};
+
+#endif
diff --git a/krusader/VFS/Makefile.am b/krusader/VFS/Makefile.am
new file mode 100644
index 0000000..63ef663
--- /dev/null
+++ b/krusader/VFS/Makefile.am
@@ -0,0 +1,19 @@
+noinst_LIBRARIES = libVFS.a
+
+INCLUDES = $(all_includes)
+
+libVFS_a_METASOURCES = AUTO
+
+libVFS_a_SOURCES = \
+ krvfshandler.cpp \
+ virt_vfs.cpp \
+ vfs.cpp \
+ vfile.cpp \
+ temp_vfs.cpp \
+ normal_vfs.cpp \
+ krpermhandler.cpp \
+ krdirwatch.cpp \
+ krarchandler.cpp \
+ preservingcopyjob.cpp \
+ virtualcopyjob.cpp \
+ ftp_vfs.cpp krquery.cpp
diff --git a/krusader/VFS/arc_vfs.cpp b/krusader/VFS/arc_vfs.cpp
new file mode 100755
index 0000000..97e32df
--- /dev/null
+++ b/krusader/VFS/arc_vfs.cpp
@@ -0,0 +1,866 @@
+/***************************************************************************
+ arc_vfs.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <time.h>
+// QT includes
+#include <qregexp.h>
+#include <qdir.h>
+#include <qdatetime.h>
+#include <qfileinfo.h>
+// KDE includes
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kprocess.h>
+#include <kio/jobclasses.h>
+#include <qprogressdialog.h>
+#include <kglobalsettings.h>
+#include <kmimetype.h>
+#include <kcursor.h>
+#include <klargefile.h>
+// krusader includes
+#include "arc_vfs.h"
+#include "krpermhandler.h"
+#include "krarchandler.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include "../resources.h"
+#include "../Dialogs/krdialogs.h"
+
+#define MAX_FILES 500
+
+//constructor
+arc_vfs::arc_vfs(QString origin,QString type,QObject* panel,bool write):
+ vfs(panel),arcFile(origin),changed(false),prefix(""),ignoreLines(0){
+
+ if ( type == "tarz" ) type = "-tgz";
+
+ // set the cursor to busy mode
+ if (!quietMode) krApp->setCursor(KCursor::waitCursor());
+
+ // set the writable attribute
+ isWritable = KRpermHandler::fileWriteable(origin);
+ isWritable = ( write && isWritable );
+
+ vfs_type = vfs::ERROR;
+
+ // create the temp dir..
+ tmpDir = krApp->getTempDir();
+ if( tmpDir.isEmpty() ){
+ error = true;
+ return;
+ }
+
+ QString password = QString::null;
+ krConfig->setGroup("Archives");
+ // fill the command options
+ if( type == "gzip" ){
+ cmd = KrServices::fullPathName ( "gzip" );
+ listCmd = "-l";
+ delCmd = "";
+ addCmd = KrServices::fullPathName ( "gzip" ) + " -c";
+ getCmd = "-dc";
+ ignoreLines = -1;
+ isWritable = false;
+ }
+ if(type == "zip2"){
+ cmd = KrServices::fullPathName( "bzip2" );
+ listCmd = "";
+ delCmd = "";
+ addCmd = KrServices::fullPathName( "bzip2" )+ " -c";
+ getCmd = "-dc";
+ ignoreLines = -1;
+ isWritable = false;
+ }
+ if(type == "-tar"){
+ cmd = KrServices::fullPathName( "tar" );
+ listCmd = " -tvf";
+ delCmd = cmd+" --delete -vf";
+ addCmd = cmd+" -uvf";
+ getCmd = " -xvf";
+ }
+ if(type == "-tgz"){
+ cmd = KrServices::fullPathName( "tar" );
+ listCmd = " -tzvf";
+ delCmd = "";
+ addCmd = cmd+" -uvzf";
+ getCmd = " -xzvf";
+ isWritable = false;
+ }
+ if(type == "-tbz"){
+ cmd = KrServices::fullPathName( "tar" );
+ listCmd = " -tjvf";
+ delCmd = "";
+ addCmd = cmd+" -uvjf";
+ getCmd = " -xjvf";
+ isWritable = false;
+ }
+ if(type == "-zip"){
+ password = KRarcHandler::getPassword(arcFile,type);
+ cmd = KrServices::fullPathName( "unzip" );
+ listCmd = "-ZTs ";
+ QString zipcmd = KrServices::fullPathName( "zip" );
+ delCmd = zipcmd+" -d";
+ addCmd = zipcmd+" -ry";
+ getCmd = " -o";
+ if( !password.isEmpty() ){
+ //listCmd = listCmd + " -P "+password;
+ delCmd = delCmd + " -P "+password;
+ addCmd = addCmd + " -P "+password;
+ getCmd = getCmd + " -P "+password;
+ }
+ ignoreLines = 1;
+ }
+ // "-rpm" is used only to list the rpm - to extract files use "+rpm"
+ if(type == "-rpm"){
+ //rpm can't handle files with " " in them so replace " " with "\ "
+ arcFile.replace(QRegExp(" "),"\\ ");
+
+ cmd = KrServices::fullPathName( "rpm" );
+ listCmd = " --dump -lpq ";
+ delCmd = "";
+ addCmd = "";
+ getCmd = "";
+ isWritable = false;
+ }
+ if( type == "+rpm" ){
+ // extract the cpio archive from the rpm
+ KShellProcess rpm;
+ rpm << "rpm2cpio"<<"\""+arcFile+"\""+" > "+tmpDir+"/contents.cpio";
+ rpm.start(KProcess::Block);
+ arcFile = tmpDir+"/contents.cpio";
+ }
+ if(type == "cpio" || type == "+rpm" ){
+ cmd = KrServices::fullPathName( "cpio" );
+ listCmd = "-tvF ";
+ delCmd = "";
+ addCmd = "";
+ getCmd = " --force-local --no-absolute-filenames -ivdF";
+ isWritable = false;
+ }
+ if(type == "-rar"){
+ bool doRar = krConfig->readBoolEntry("Do Rar",_DoRar);
+ cmd = KrServices::fullPathName( "unrar" );
+ listCmd = " -c- v ";
+ delCmd = "";
+ addCmd = (doRar ? QString(KrServices::fullPathName( "rar" ) + " -r a ") : QString("")) ;
+ getCmd = " x -y ";
+ ignoreLines = 8;
+ isWritable = (doRar && isWritable );
+ }
+
+ getDirs();
+ // set the cursor to normal mode
+ if (!quietMode) krApp->setCursor(KCursor::arrowCursor());
+}
+
+// return the working dir
+QString arc_vfs::vfs_workingDir(){
+ // get the path inside the archive
+ QString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ if(path.left(1) != "/") path = "/"+path;
+ QDir().mkdir(tmpDir+path);
+ return tmpDir+path;
+}
+
+arc_vfs::~arc_vfs(){
+ // set the cursor to busy mode
+ if (!quietMode) krApp->setCursor(KCursor::waitCursor());
+ // don't touch messed-up archives
+ if(!error) repack();
+ // delete the temp dir
+ KShellProcess proc;
+ proc<<"rm"<<"-rf"<<tmpDir;
+ proc.start(KProcess::Block);
+
+ // set the cursor to normal mode
+ if (!quietMode) krApp->setCursor(KCursor::arrowCursor());
+}
+
+bool arc_vfs::getDirs(){
+ if( !listCmd.isEmpty() ){
+ // write the temp file
+ KShellProcess proc;
+ proc << cmd << listCmd << "\""+arcFile+"\"" <<" > " << tmpDir+"/tempfilelist";
+ proc.start(KProcess::Block);
+ if( !proc.normalExit() || !proc.exitStatus() == 0 ){
+ if (!quietMode) KMessageBox::error(krApp, i18n("<qt>Can't read <b>%1</b>. Archive "
+ "might be corrupted!</qt>").arg(arcFile.mid(arcFile.findRev('/')+1)));
+ error = true;
+ return false;
+ }
+
+ // clear the dir list
+ dirList.clear();
+
+ // prepare the first dir entry - the "" entry
+ arc_dir *tempdir = new arc_dir("");
+ vfs_filesP = &(tempdir->entries);
+ dirList.append(tempdir);
+
+ // parse the temp file
+ QFile temp(tmpDir+"/tempfilelist");
+ temp.open(IO_ReadOnly);
+ char buf[1000];
+ QString line;
+ if(vfs_type == "gzip" || vfs_type == "-zip" )
+ temp.readLine(line,10000); // skip the first line - it's garbage
+ if( vfs_type == "-rar" ){
+ while(temp.readLine(line,10000) != -1)
+ if ( line.contains("----------") ) break;
+ }
+ while(temp.readLine(buf,1000) != -1){
+ line = QString::fromLocal8Bit(buf);
+ if ( line.contains("----------") ) break;
+ parseLine(line.stripWhiteSpace(),&temp);
+
+ }
+ temp.close();
+ QDir().remove(tmpDir+"/tempfilelist");
+ }
+ else { // bzip2
+ // clear the dir list
+ dirList.clear();
+
+ // prepare the first dir entry - the "" entry
+ arc_dir *tempdir = new arc_dir("");
+ vfs_filesP = &(tempdir->entries);
+ dirList.append(tempdir);
+
+ parseLine("",0);
+ }
+ return true;
+}
+
+
+// copy a file to the vfs (physical)
+void arc_vfs::vfs_addFiles(KURL::List *fileUrls,KIO::CopyJob::CopyMode mode,QObject* toNotify,QString dir, PreserveMode /*pmode*/ ){
+ if ( addCmd.isEmpty() ) return;
+
+ // get the path inside the archive
+ QString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ path = path+"/";
+ if(dir != "" ) dir = "/"+dir;
+ if(path.left(1) != "/") path = "/"+path;
+
+ // make sure the destination exist
+ for( int i=0; i >= 0 ; i= QString(tmpDir+path+dir).find('/',i+1) ){
+ QDir().mkdir(QString(tmpDir+path+dir).left(i));
+ }
+
+ changed = true; //rescan the archive
+
+ KURL dest;
+ dest.setPath(tmpDir+path+dir);
+
+ KIO::Job* job = new KIO::CopyJob(*fileUrls,dest,mode,false,true);
+ connect(job,SIGNAL(result(KIO::Job*)),this,SLOT(vfs_refresh(KIO::Job*)) );
+ if(mode == KIO::CopyJob::Move) // notify the other panel
+ connect(job,SIGNAL(result(KIO::Job*)),toNotify,SLOT(vfs_refresh(KIO::Job*)) );
+}
+
+
+// remove a file from the vfs (physical)
+void arc_vfs::vfs_delFiles(QStringList *fileNames){
+ if ( delCmd.isEmpty() ) return;
+ // if we move to trash - just extract files and move them to trash -
+ // the repack() will delete them for us
+ krConfig->setGroup("General");
+ if( krConfig->readBoolEntry("Move To Trash",_MoveToTrash) ) {
+ KURL::List* filesUrls = vfs_getFiles(fileNames); // extract
+ changed = true;
+
+ KIO::Job *job = new KIO::CopyJob(*filesUrls,KGlobalSettings::trashPath(),KIO::CopyJob::Move,false,true );
+ connect(job,SIGNAL(result(KIO::Job*)),this,SLOT(vfs_refresh(KIO::Job*)));
+ }
+ // else we have to delete the files from both the archive and the temp dir
+ else {
+ // change dir to the temp dir
+ QString save = getcwd(0,0);
+ chdir(tmpDir.local8Bit());
+
+ QStringList files;
+ KIO::filesize_t totalSizeVal = 0;
+ unsigned long totalFilesVal = 0;
+
+ // names -> urls
+ for(QStringList::Iterator name = fileNames->begin(); name != fileNames->end(); ++name )
+ processName(*name,&files,&totalSizeVal,&totalFilesVal);
+
+
+ KShellProcess proc1 , proc2;
+ krApp->startWaiting(i18n("Deleting Files..."),files.count()+ignoreLines);
+ connect(&proc1,SIGNAL(receivedStdout(KProcess*,char*,int)),
+ krApp, SLOT(incProgress(KProcess*,char*,int)) );
+
+ proc1 << delCmd << "\""+arcFile+"\"";
+ proc2 << "rm -rf";
+ for(unsigned int i =0; i < files.count(); ){
+ proc1 << (prefix+*files.at(i));
+ proc2 << tmpDir+"/"+(*files.at(i));
+ extFiles.remove(*files.at(i++));
+ if ( i%MAX_FILES==0 || i==files.count() ){
+ proc1.start(KProcess::NotifyOnExit,KProcess::AllOutput);
+ proc2.start();
+ while( proc1.isRunning() || proc2.isRunning() ) qApp->processEvents(); // busy wait - need to find something better...
+ proc1.clearArguments() ; proc2.clearArguments();
+ proc1 << delCmd << "\""+arcFile+"\"";
+ proc2 << "rm -rf";
+ }
+ }
+ krApp->stopWait();
+
+ changed = true;
+ chdir (save.local8Bit());
+ vfs_refresh(vfs_origin);
+ }
+}
+
+// return a path to the file
+QString arc_vfs::vfs_getFile(QString name){
+ // get the current file path
+ QString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ if(path.left(1)=="/") path.remove(0,1);
+ if(path != "") path = path+"/";
+
+ QStringList temp(name);
+ vfs_getFiles(&temp);
+
+ return tmpDir+"/"+path+name;
+}
+
+KURL::List* arc_vfs::vfs_getFiles(QStringList* names){
+ KURL url;
+ KURL::List* urls = new KURL::List();
+
+ // get the current file path
+ QString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ if(path.left(1)=="/") path.remove(0,1);
+ if(path != "") path = path+"/";
+
+ // change dir to the temp dir
+ QString save = getcwd(0,0);
+ chdir(tmpDir.local8Bit());
+ // names -> urls
+ QStringList files;
+ KIO::filesize_t totalSize = 0;
+ unsigned long totalFiles = 0;
+ for(QStringList::Iterator name = names->begin(); name != names->end(); ++name ){
+ processName(*name,&files,&totalSize,&totalFiles);
+ url.setPath(tmpDir+"/"+path+(*name));
+ urls->append(url);
+ }
+ // check the urls for unpacked files and directories
+ for(QStringList::Iterator file = files.begin(); file != files.end(); ++file ){
+ if ( (*file).right(1)=="/" ){
+ QDir(tmpDir).mkdir(*file);
+ if( vfs_type == "-rar" ) file = files.remove(file--);
+ }
+ // don't unpack the same file twice
+ else if( extFiles.contains(*file) ){
+ file = files.remove(file--);
+ }
+ }
+ // unpack ( if needed )
+ if ( files.count() > 0 ){
+ krApp->startWaiting(i18n("Unpacking Files"),files.count()+ignoreLines);
+ KShellProcess proc;
+ connect(&proc,SIGNAL(receivedStdout(KProcess*,char*,int)),
+ krApp, SLOT(incProgress(KProcess*,char*,int)) );
+
+ proc << cmd << getCmd << "\""+arcFile+"\"";
+ if( vfs_type == "gzip" || vfs_type == "zip2" ) proc << ">";
+ for(unsigned int i=0 ; i < files.count() ; ){
+ proc << (prefix+*files.at(i++));
+ if ( i%MAX_FILES==0 || i==files.count() ){
+ proc.start(KProcess::NotifyOnExit,KProcess::AllOutput);
+ while( proc.isRunning() ) qApp->processEvents();
+ proc.clearArguments();
+ proc << cmd << getCmd << "\""+arcFile+"\"";
+ }
+ }
+ getExtFiles(); // this will update the extFiles list.
+ krApp->stopWait();
+ }
+ // restore dir
+ chdir(save.local8Bit());
+
+ return urls;
+}
+
+// make dir
+void arc_vfs::vfs_mkdir(QString name){
+ QString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ if(path.left(1)=="/") path.remove(0,1);
+ if(path != "") path = path+"/";
+
+ QDir(tmpDir).mkdir(path+name);
+ changed = true; //rescan the archive
+ vfs_refresh(vfs_origin);
+}
+
+// rename file
+void arc_vfs::vfs_rename(QString fileName,QString newName){
+ KURL::List temp;
+ temp.append(vfs_getFile(fileName));
+ QString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ if(path.left(1)=="/") path.remove(0,1);
+ if(path != "") path = path+"/";
+
+ QDir(tmpDir).mkdir(path);
+ changed = true; //rescan the archive
+
+ KURL dest;
+ dest.setPath(tmpDir+path+"/"+newName);
+
+ KIO::Job* job = new KIO::CopyJob(temp,dest,KIO::CopyJob::Move,false,false);
+ connect(job,SIGNAL(result(KIO::Job*)),this,SLOT(vfs_refresh(KIO::Job*)) );
+}
+
+bool arc_vfs::vfs_refresh(QString origin){
+ if ( error ) return false;
+
+ if ( changed || origin == vfs_origin ){
+ repack(); // repack dirs only if needed
+ if ( !getDirs() ){
+ if (!quietMode) emit startUpdate();
+ return true;
+ }
+ changed = false;
+ }
+
+ vfs_origin = origin;
+ // get the directory...
+ QString path = origin.right((origin.length()-origin.findRev('\\'))-1);
+ if(path.left(1) =="/") path.remove(0,1);
+
+ vfs_filesP = findDir(path);
+
+ if (!quietMode) emit startUpdate();
+ return true;
+}
+
+// service functions
+QString arc_vfs::nextWord(QString &s,char d) {
+ s=s.stripWhiteSpace();
+ int j=s.find(d,0);
+ QString temp=s.left(j); // find the leftmost word.
+ s.remove(0,j);
+ return temp;
+}
+
+void arc_vfs::getFilesToPack(QStringList* filesToPack,QString dir_name){
+ bool newDir = false;
+ vfileDict *vfs_filesP_backup = vfs_filesP; // save vfs_filesP
+
+ // init all the diffrent lists (and list pointers);
+ vfs_filesP=findDir(dir_name);
+ if ( vfs_filesP == 0) newDir = true;
+ if(dir_name != "") dir_name = dir_name+"/";
+
+ register DIR* dir = opendir(tmpDir.local8Bit()+"/"+dir_name.local8Bit());
+ if(!dir) return ;
+
+ register struct dirent* dirEnt;
+ QString name;
+ KDE_struct_stat stat_p;
+ while( (dirEnt=readdir(dir)) != NULL ){
+ name = dirEnt->d_name;
+ if ( name == ".." || name == "." ) continue;
+ if( KDE_lstat(tmpDir.local8Bit()+"/"+dir_name.local8Bit()+name.local8Bit(),&stat_p) ) continue;
+ extFile temp(dir_name+name,stat_p.st_mtime,stat_p.st_size);
+ // add to the list file that are diffrent than the ones packed
+ if( S_ISDIR(stat_p.st_mode) ){ // recurse on all sub dirs
+ if( !findDir(dir_name+name) ){
+ // add to the list only new && empty dirs
+ if( newDir && QDir(dir_name+name).entryList(QDir::All | QDir::AccessMask).count() <= 2 )
+ filesToPack->append( dir_name+name);
+ }
+ getFilesToPack(filesToPack,dir_name+name);
+ continue;
+ }
+
+ // if the file don't exist add it to the archive and to the extFiles
+ if( newDir || !extFiles.contains( dir_name+name ) ){
+ filesToPack->append( dir_name+name );
+ extFiles.append( temp );
+ } // else if the file exist but was modified - repack it;
+ else if( !extFiles.contains( temp ) ){
+ filesToPack->append( dir_name+name );
+ extFiles.remove( dir_name+name );
+ extFiles.append( temp );
+ }
+ }
+ vfs_filesP = vfs_filesP_backup; // restore vfs_filesP
+}
+
+void arc_vfs::getFilesToDelete(QStringList* filesToDelete,QString){
+ // sync the extFiles - and find out which files were deleted
+ QString file;
+ for(unsigned int i=0 ; i<extFiles.count(); ){
+ file = tmpDir+"/"+(*extFiles.at(i)).url;
+ if( !KRpermHandler::fileExist(file) ){
+ filesToDelete->append( (*extFiles.at(i)).url );
+ extFiles.remove(extFiles.at(i));
+ }
+ else ++i;
+ }
+}
+
+void arc_vfs::getExtFiles(QString dir_name){
+ register DIR* dir = opendir(tmpDir.local8Bit()+"/"+dir_name.local8Bit());
+ if(!dir){
+ kdWarning() << "faild to opendir(): " << tmpDir.local8Bit()+"/"+dir_name.local8Bit() << endl;
+ return ;
+ }
+
+ if( dir_name != "") dir_name = dir_name+"/";
+
+ register struct dirent* dirEnt;
+ QString name;
+ KDE_struct_stat stat_p;
+ while( (dirEnt=readdir(dir)) != NULL ){
+ name = dirEnt->d_name;
+ if ( name == ".." || name == "." ) continue;
+ if( KDE_lstat(tmpDir.local8Bit()+"/"+dir_name.local8Bit()+name.local8Bit(),&stat_p) ) continue;
+ extFile temp(dir_name+name,stat_p.st_mtime,stat_p.st_size);
+ // recurse on all sub dirs
+ if( S_ISDIR(stat_p.st_mode) ){
+ getExtFiles(dir_name+name);
+ }
+ // if the file is not in extFiles - it is newly extracted.
+ // note: getFilesToPack() updates time + size !
+ else if( !extFiles.contains( dir_name+name ) ){
+ extFiles.append( temp );
+ }
+ }
+}
+
+void arc_vfs::repack(){
+ QString save = getcwd(0,0);
+ chdir(tmpDir.local8Bit());
+
+ // delete from the archive files that were unpacked and deleted
+ if( vfs_isWritable() ){
+ QStringList filesToDelete;
+ getFilesToDelete(&filesToDelete);
+ if( !filesToDelete.isEmpty() ){
+ KShellProcess delProc;
+ krApp->startWaiting(i18n("Deleting Files..."),filesToDelete.count()+ignoreLines);
+ connect(&delProc,SIGNAL(receivedStdout(KProcess*,char*,int)),
+ krApp, SLOT(incProgress(KProcess*,char*,int)) );
+
+ delProc << delCmd << "\""+arcFile+"\"";
+ for( unsigned int i=0 ; i < filesToDelete.count() ;){
+ delProc << (*filesToDelete.at(i++));
+ if( i%MAX_FILES==0 || i==filesToDelete.count() ){
+ delProc.start(KProcess::NotifyOnExit,KProcess::AllOutput);
+ while( delProc.isRunning() ) qApp->processEvents();
+ delProc.clearArguments();
+ delProc << delCmd << "\""+arcFile+"\"";
+ }
+ }
+ krApp->stopWait();
+ }
+ }
+
+ // finaly repack tmpDir
+ if( vfs_isWritable() || vfs_type=="gzip" || vfs_type=="zip2" ){
+ QStringList filesToPack;
+ getFilesToPack(&filesToPack);
+ if( !filesToPack.isEmpty() ){
+ KShellProcess addProc;
+ krApp->startWaiting(i18n("Repacking..."),filesToPack.count()+ignoreLines);
+ connect(&addProc,SIGNAL(receivedStdout(KProcess*,char*,int)),
+ krApp, SLOT(incProgress(KProcess*,char*,int)) );
+
+ if( vfs_type=="gzip" || vfs_type=="zip2" ){
+ addProc << addCmd << *filesToPack.at(0)<< ">" << "\""+arcFile+"\"";
+ addProc.start(KProcess::NotifyOnExit);
+ while( addProc.isRunning() ) qApp->processEvents();
+ }
+ else {
+ addProc << addCmd << "\""+arcFile+"\"";
+ for( unsigned int i=0 ; i<filesToPack.count(); ){
+ addProc << "\""+prefix+(*filesToPack.at(i++))+"\"";
+ if( i%MAX_FILES==0 || i==filesToPack.count() ){
+ addProc.start(KProcess::NotifyOnExit,KProcess::AllOutput);
+ while( addProc.isRunning() ) qApp->processEvents(); // busy wait - need to find something better...
+ addProc.clearArguments();
+ addProc << addCmd << "\""+arcFile+"\"";
+ }
+ }
+ }
+ krApp->stopWait();
+ }
+ }
+ chdir(save.local8Bit());
+}
+
+vfileDict* arc_vfs::findDir(QString name){
+ for(arc_dir* temp = dirList.first();temp != 0 ; temp = dirList.next()){
+ if(temp->name == name) return &(temp->entries);
+ }
+ return 0;
+}
+
+arc_vfs::arc_dir* arc_vfs::findArcDir(QString name){
+for(arc_dir* temp = dirList.first();temp != 0 ; temp = dirList.next()){
+ if(temp->name == name) return temp;
+ }
+ return 0;
+}
+
+QString arc_vfs::changeDir(QString name){
+ if(name.left(2) == "./") {
+ prefix = "./";
+ name.remove(0,2);
+ }
+
+ if(!name.contains('/')){
+ vfs_filesP = findDir("");
+ return name;
+ }
+ // seperate the path from the name
+ QString path = name.left(name.findRev('/'));
+ name = name.mid(name.findRev('/')+1);
+ // see if the path exists
+ if ((vfs_filesP=findDir(path)) == 0){
+ //create a new dir entry
+ QString Pname = path.mid(path.findRev('/')+1);
+ if(Pname.isEmpty()) return name;
+ QString tempName = arcFile;
+ QFileInfo qfi(tempName.replace(QRegExp("\\"),""));
+ vfile* vf=new vfile(Pname,0,"drwxr-xr-x",qfi.lastModified().toTime_t(),false,
+ qfi.owner(),qfi.group(),"inode/directory","",0 );
+ // add dirs if needed
+ changeDir(path);
+
+ vfile* vf2 = vfs_search(Pname);
+ if(vf2 != 0) vfs_removeFromList(vf2);
+ vfs_addToList(vf);
+
+ // add a new arc_dir
+ dirList.append(new arc_dir(path));
+ vfs_filesP = findDir(path);
+ }
+ return name;
+}
+
+// calculate space
+void arc_vfs::vfs_calcSpace(QString name ,KIO::filesize_t *totalSize,unsigned long *totalFiles,unsigned long *totalDirs,bool* stop){
+ if ( *stop ) return;
+ vfile* vf = vfs_search(name);
+
+ // get the path inside the archive
+ QString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ path = path+"/";
+ if(path.left(1) == "/") path.remove(0,1);
+
+ if( !vf->vfile_isDir() ){ // single files are simple :)
+ ++(*totalFiles);
+ (*totalSize) += vf->vfile_getSize();
+ }
+ else { // handle directories : (
+ ++(*totalDirs);
+
+ QString origin_backup = vfs_origin; // backup the vfs origin
+ vfs_origin = vfs_origin+"/"+name;
+ vfileDict* vfs_filesP_backup = vfs_filesP; // backup the vfs_filesP
+ vfs_filesP = findDir(path+name);
+
+ // process all the files in the directory.
+ for( vf = vfs_getFirstFile(); vf != 0; vf = vfs_getNextFile() ){
+ if (*stop) return;
+ vfs_calcSpace(vf->vfile_getName(),totalSize,totalFiles,totalDirs,stop);
+ }
+
+ vfs_origin = origin_backup; // restore origin
+ vfs_filesP = vfs_filesP_backup; // restore vfs_filesP
+ }
+}
+
+void arc_vfs::processName(const QString& name, QStringList *urls,KIO::filesize_t *totalSize,unsigned long *totalFiles ){
+ vfile* vf = vfs_search(name);
+ if ( vf == 0 ) return;
+
+ // get the path inside the archive
+ QString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ path = path+"/";
+ if(path.left(1) == "/") path.remove(0,1);
+
+ if( !vf->vfile_isDir() || vf->vfile_isSymLink() ){ // single files are simple :)
+ ++(*totalFiles);
+ (*totalSize) += vf->vfile_getSize();
+ urls->append(path+name);
+ } else { // handle directories : (
+ urls->append(path+name+"/");
+ QString origin_backup = vfs_origin; // backup the vfs origin
+ vfs_origin = vfs_origin+"/"+name;
+ vfileDict* vfs_filesP_backup = vfs_filesP; // backup the vfs_filesP
+ vfs_filesP = findDir(path+name);
+
+ // process all the files in the directory.
+ for( vf = vfs_getFirstFile(); vf != 0; vf = vfs_getNextFile() )
+ processName(vf->vfile_getName(),urls,totalSize,totalFiles);
+
+ vfs_origin = origin_backup; // restore origin
+ vfs_filesP = vfs_filesP_backup; // restore vfs_filesP
+ }
+}
+
+void arc_vfs::parseLine(QString line, QFile* temp){
+ QString name;
+ KIO::filesize_t size = 0;
+ QString perm;
+ QFileInfo qfi(arcFile);
+ time_t mtime = qfi.lastModified().toTime_t();
+ bool link = false;
+ uid_t owner = getuid();
+ gid_t group = getgid();
+ QString dest = "";
+ mode_t mode = 0;
+
+
+ // parse gziped files
+ if(vfs_type == "gzip"){
+ KDE_struct_stat stat_p;
+ KDE_stat(arcFile.local8Bit(),&stat_p);
+
+ nextWord(line);
+ size = nextWord(line).toLong();
+ nextWord(line);
+ name = nextWord(line,'\n');
+ if(name.contains('/')) name = name.mid(name.findRev('/')+1,name.length());
+ perm = KRpermHandler::mode2QString(stat_p.st_mode) ;
+ owner = KRpermHandler::user2uid(qfi.owner());
+ group = KRpermHandler::group2gid(qfi.group());
+ mode = stat_p.st_mode;
+ }
+
+ // parse bzip2ed files
+ if( vfs_type == "zip2" ){
+ KDE_struct_stat stat_p;
+ KDE_stat(arcFile.local8Bit(),&stat_p);
+
+ name = qfi.fileName();
+ name = name.left(name.findRev('.'));
+ //long size = qfi.size();
+ perm = KRpermHandler::mode2QString(stat_p.st_mode) ;
+ owner = KRpermHandler::user2uid(qfi.owner());
+ group = KRpermHandler::group2gid(qfi.group());
+ mode = stat_p.st_mode;
+ }
+
+ // parse tar files
+ if(vfs_type == "-tar" || vfs_type == "-tbz" || vfs_type == "-tgz" ){
+ perm = nextWord(line);
+ QString temp = nextWord(line);
+ owner = temp.left(temp.findRev('/')).toInt();
+ group = temp.mid(temp.find('/')+1,temp.length()).toInt();
+ size = nextWord(line).toLong();
+ temp = nextWord(line);
+ name = nextWord(line,'\n');
+ if (name.startsWith("/")) // fix full-paths problem in tar (thanks to Heiner!)
+ name.remove(0, 1);
+ if( name.contains(" -> ") ){
+ link = true;
+ dest = name.mid(name.find(" -> ")+4);
+ name = name.left(name.find(" -> "));
+ }
+ }
+
+ // parse zipped files
+ if(vfs_type == "-zip"){
+ perm = nextWord(line);
+ if(perm.length() != 10)
+ perm = (perm.at(0)=='d')? "drwxr-xr-x" : "-rw-r--r--" ;
+ if (nextWord(line).contains("file")) return;
+ nextWord(line);
+ size = nextWord(line).toLong();
+ nextWord(line);nextWord(line);
+ QString temp = nextWord(line);
+ name = nextWord(line,'\n');
+ }
+
+ // parse cpio packages
+ if(vfs_type == "cpio" || vfs_type == "+rpm"){
+ perm = nextWord(line);
+ nextWord(line);nextWord(line);nextWord(line);
+ size = nextWord(line).toLong();
+ nextWord(line);nextWord(line);nextWord(line);
+ QString tempName = arcFile;
+ QFileInfo qfi(tempName.replace(QRegExp("\\"),""));
+ name = nextWord(line,'\n');
+ if ( name.left(1) == "/" ) name.remove(0,1);
+ if( name.contains(" -> ") ){
+ link = true;
+ dest = name.mid(name.find(" -> ")+4);
+ name = name.left(name.find(" -> "));
+ }
+ }
+ // parse rared files
+ if(vfs_type == "-rar"){
+ name = nextWord(line,'\n');
+ temp->readLine(line,10000);
+ size = nextWord(line).toLong();
+ nextWord(line);
+ nextWord(line);
+ perm = nextWord(line);
+ if(perm.length() != 10)
+ perm = (perm.at(1)=='D')? "drwxr-xr-x" : "-rw-r--r--" ;
+ }
+ // parse rpm packages
+ if(vfs_type == "-rpm"){
+ name = nextWord(line);
+ if ( name.left(1) == "/" ) name.remove(0,1);
+ size = nextWord(line).toLong();
+ mtime = nextWord(line).toLong();
+ nextWord(line);
+ perm = KRpermHandler::mode2QString(nextWord(line).toLong());
+ perm = (perm.at(0)=='d')? "drwxr-xr-x" : "-rw-r--r--" ;
+ }
+
+ if ( perm[0]=='d' && name.right(1) != "/" ) name = name+"/";
+ name = changeDir(name);
+ if(name.length() < 1) return;
+
+
+ QString mime = KMimeType::findByURL( "/"+name,0,true,true)->name();
+ vfile* vf=new vfile(name,size,perm,mtime,link,owner,group,mime,dest,mode);
+ vfile* vf2 = vfs_search(name);
+ if(vf2 != 0) vfs_removeFromList(vf2);
+ vfs_addToList(vf);
+}
+
+#include "arc_vfs.moc"
diff --git a/krusader/VFS/arc_vfs.h b/krusader/VFS/arc_vfs.h
new file mode 100644
index 0000000..b4adf9b
--- /dev/null
+++ b/krusader/VFS/arc_vfs.h
@@ -0,0 +1,130 @@
+/***************************************************************************
+ arc_vfs.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef ARC_VFS_H
+#define ARC_VFS_H
+
+#include <sys/types.h>
+#include "vfs.h"
+#include <qvaluestack.h>
+#include <kprocess.h>
+#include <qfile.h>
+#include <qprogressdialog.h>
+
+class arc_vfs : public vfs {
+ Q_OBJECT
+ class arc_dir;
+ class extFile;
+public:
+ arc_vfs(QString origin,QString type,QObject* panel,bool write);
+ ~arc_vfs();
+
+ // copy a file to the vfs (physical)
+ void vfs_addFiles(KURL::List *fileUrls,KIO::CopyJob::CopyMode mode,QObject* toNotify=0,QString dir = "", PreserveMode pmode = PM_DEFAULT );
+ // remove a file from the vfs (physical)
+ void vfs_delFiles(QStringList *fileNames);
+ // return a path to the file
+ QString vfs_getFile(QString name);
+ KURL::List* vfs_getFiles(QStringList* names);
+ // make dir
+ void vfs_mkdir(QString name);
+ // rename file
+ void vfs_rename(QString fileName,QString newName);
+ // calculate space
+ void vfs_calcSpace(QString name ,KIO::filesize_t *totalSize,unsigned long *totalFiles,unsigned long *totalDirs, bool* stop);
+ // return the working dir
+ QString vfs_workingDir();
+
+public slots:
+ // actually reads files and stats
+ bool vfs_refresh(QString origin);
+ void repack();
+
+protected:
+ QString tmpDir; // the temp directory tha archive is using
+ QString arcFile; // the archive file URL
+ bool changed; // true if repack changed the archive
+ QList<arc_dir> dirList;
+ QValueList<extFile> extFiles; // the name, time & size of files unpacked from this archive
+
+ void processName(const QString& name,QStringList *urls,KIO::filesize_t *totalSize,unsigned long *totalFiles );
+ bool getDirs(); // fill the dir list
+ vfileDict* findDir(QString name);
+ arc_dir* findArcDir(QString name);
+ void getFilesToPack (QStringList* filesToPack,QString dir_name = "");
+ void getFilesToDelete(QStringList* filesToDelete,QString dir_name = "");
+ void getExtFiles( QString dir_name="" );
+ QString nextWord( QString &s, char d=' ' );
+ QString changeDir(QString name);
+
+ void parseLine(QString line,QFile* temp);
+
+ QString prefix;
+ QString cmd; // the archiver main command
+ QString listCmd; // the file listing option
+ QString delCmd; // the delete option
+ QString addCmd; // the add files option
+ QString getCmd; // the extract files option
+
+ // the interl progress bar variale
+ int ignoreLines; // no of lines to ignore on stdout
+
+private:
+ class arc_dir{
+ public:
+ arc_dir(QString _name){
+ name = _name;
+ entries.setAutoDelete(true);
+ }
+ QString name; // the name of the dir
+ vfileDict entries; // the file and dir in this dir
+ };
+
+ class extFile{
+ public:
+ extFile(): url(""),time(0),size(0){}
+ extFile(QString u): url(u),time(0),size(0){}
+ extFile(QString u,time_t t,off_t s): url(u),time(t),size(s){}
+ bool operator==(const extFile& ef) const{
+ if( url != ef.url ) return false;
+ if( size*ef.size && size!=ef.size )return false;
+ if( time*ef.time && time!=ef.time )return false;
+ return true;
+ }
+ QString url;
+ time_t time;
+ off_t size;
+ };
+
+
+
+};
+
+#endif
diff --git a/krusader/VFS/ftp_vfs.cpp b/krusader/VFS/ftp_vfs.cpp
new file mode 100644
index 0000000..1cfb394
--- /dev/null
+++ b/krusader/VFS/ftp_vfs.cpp
@@ -0,0 +1,297 @@
+/***************************************************************************
+ ftp_vfs.cpp
+ -------------------
+ copyright : (C) 2000 by Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+
+***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+// Sys includes
+#include <time.h>
+#include <sys/param.h>
+#include <unistd.h>
+#ifdef BSD
+#include <sys/types.h>
+#endif
+// QT includes
+#include <qdir.h>
+#include <qregexp.h>
+#include <qtimer.h>
+#include <qeventloop.h>
+// KDE includes
+#include <kio/jobclasses.h>
+#include <klocale.h>
+#include <kio/job.h>
+#include <kmessagebox.h>
+#include <kprotocolinfo.h>
+#include <kdebug.h>
+// Krusader includes
+#include "ftp_vfs.h"
+#include "krpermhandler.h"
+#include "../Dialogs/krdialogs.h"
+#include "../Dialogs/krprogress.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include "../resources.h"
+
+ftp_vfs::ftp_vfs( QObject* panel ) : vfs( panel ), busy( false ) {
+ // set the writable attribute
+ isWritable = true;
+ vfs_type = FTP;
+}
+
+ftp_vfs::~ftp_vfs() {
+ busy = false;
+}
+
+void ftp_vfs::slotAddFiles( KIO::Job *, const KIO::UDSEntryList& entries ) {
+ int rwx = -1;
+
+ QString prot = vfs_origin.protocol();
+ if( prot == "krarc" || prot == "tar" || prot == "zip" )
+ rwx = PERM_ALL;
+
+ KIO::UDSEntryListConstIterator it = entries.begin();
+ KIO::UDSEntryListConstIterator end = entries.end();
+
+ // as long as u can find files - add them to the vfs
+ for ( ; it != end; ++it ) {
+ KFileItem kfi( *it, vfs_origin, true, true );
+ vfile *temp;
+
+ // get file statistics
+ QString name = kfi.text();
+ // ignore un-needed entries
+ if ( name.isEmpty() || name == "." || name == ".." ) continue;
+
+ KIO::filesize_t size = kfi.size();
+ time_t mtime = kfi.time( KIO::UDS_MODIFICATION_TIME );
+ bool symLink = kfi.isLink();
+ mode_t mode = kfi.mode() | kfi.permissions();
+ QString perm = KRpermHandler::mode2QString( mode );
+ // set the mimetype
+ QString mime = kfi.mimetype();
+ QString symDest = "";
+ if ( symLink ) {
+ symDest = kfi.linkDest();
+ if ( kfi.isDir() ) perm[ 0 ] = 'd';
+ }
+
+ // create a new virtual file object
+ if ( kfi.user().isEmpty() )
+ temp = new vfile( name, size, perm, mtime, symLink, getuid(), getgid(), mime, symDest, mode, rwx );
+ else {
+ QString currentUser = vfs_origin.user();
+ if ( currentUser.contains( "@" ) ) /* remove the FTP proxy tags from the username */
+ currentUser.truncate( currentUser.find( '@' ) );
+ if ( currentUser.isEmpty() ) {
+ if( vfs_origin.host().isEmpty() )
+ currentUser = KRpermHandler::uid2user( getuid() );
+ else {
+ currentUser = ""; // empty, but not QString::null
+ }
+ }
+#if KDE_IS_VERSION(3,5,0)
+ temp = new vfile( name, size, perm, mtime, symLink,
+ kfi.user(), kfi.group(), currentUser,
+ mime, symDest, mode, rwx, kfi.ACL().asString(),
+ kfi.defaultACL().asString() );
+#else
+ temp = new vfile( name, size, perm, mtime, symLink, kfi.user(), kfi.group(), currentUser, mime, symDest, mode, rwx );
+#endif
+ }
+
+#if KDE_IS_VERSION(3,4,0)
+ if( !kfi.localPath().isEmpty() ){
+ temp->vfile_setUrl( kfi.localPath() );
+ } else {
+ temp->vfile_setUrl( kfi.url() );
+ }
+#else
+ temp->vfile_setUrl( kfi.url() );
+#endif
+ temp->vfile_setIcon( kfi.iconName() );
+ foundVfile( temp );
+ }
+}
+
+void ftp_vfs::slotPermanentRedirection( KIO::Job*, const KURL&, const KURL& newUrl ) {
+ vfs_origin = newUrl;
+ vfs_origin.adjustPath(-1);
+}
+
+void ftp_vfs::slotRedirection( KIO::Job *, const KURL &url ) {
+ // update the origin
+ vfs_origin = url;
+ vfs_origin.adjustPath(-1);
+}
+
+void ftp_vfs::slotListResult( KIO::Job *job ) {
+ if ( job && job->error() ) {
+ // we failed to refresh
+ listError = true;
+ // display error message
+ if ( !quietMode ) job->showErrorDialog( krApp );
+ }
+ busy = false;
+}
+
+bool ftp_vfs::populateVfsList( const KURL& origin, bool showHidden ) {
+ QString errorMsg = QString::null;
+ if ( !origin.isValid() )
+ errorMsg = i18n( "Malformed URL:\n%1" ).arg( origin.url() );
+ if ( !KProtocolInfo::supportsListing( origin ) ) {
+ if( origin.protocol() == "ftp" && KProtocolInfo::supportsReading( origin ) )
+ errorMsg = i18n( "Krusader doesn't support FTP access via HTTP.\nIf it is not the case, please check and change the Proxy settings in kcontrol." );
+ else
+ errorMsg = i18n( "Protocol not supported by Krusader:\n%1" ).arg( origin.url() );
+ }
+
+ if ( !errorMsg.isEmpty() ) {
+ if ( !quietMode ) KMessageBox::sorry( krApp, errorMsg );
+ return false;
+ }
+
+ busy = true;
+
+ vfs_origin = origin;
+ vfs_origin.adjustPath(-1);
+
+ //QTimer::singleShot( 0,this,SLOT(startLister()) );
+ listError = false;
+ // Open the directory marked by origin
+ krConfig->setGroup( "Look&Feel" );
+ //vfs_origin.adjustPath(+1);
+ KIO::Job *job = KIO::listDir( vfs_origin, false, showHidden );
+ connect( job, SIGNAL( entries( KIO::Job*, const KIO::UDSEntryList& ) ),
+ this, SLOT( slotAddFiles( KIO::Job*, const KIO::UDSEntryList& ) ) );
+ connect( job, SIGNAL( redirection( KIO::Job*, const KURL& ) ),
+ this, SLOT( slotRedirection( KIO::Job*, const KURL& ) ) );
+ connect( job, SIGNAL( permanentRedirection( KIO::Job*, const KURL&, const KURL& ) ),
+ this, SLOT( slotPermanentRedirection( KIO::Job*, const KURL&, const KURL& ) ) );
+
+ connect( job, SIGNAL( result( KIO::Job* ) ),
+ this, SLOT( slotListResult( KIO::Job* ) ) );
+
+ job->setWindow( krApp );
+
+ if ( !quietMode ) {
+ emit startJob( job );
+ //new KrProgress(job); ==> disabled because of in-panel refresh
+ }
+
+ while ( busy && vfs_processEvents());
+
+ if ( listError ) return false;
+
+ return true;
+}
+
+
+// copy a file to the vfs (physical)
+void ftp_vfs::vfs_addFiles( KURL::List *fileUrls, KIO::CopyJob::CopyMode mode, QObject* toNotify, QString dir, PreserveMode /*pmode*/ ) {
+ KURL destUrl = vfs_origin;
+
+ if ( dir != "" ) {
+ destUrl.addPath( dir );
+ destUrl.cleanPath(); // removes the '..', '.' and extra slashes from the URL.
+
+ if ( destUrl.protocol() == "tar" || destUrl.protocol() == "zip" || destUrl.protocol() == "krarc" ) {
+ if ( QDir( destUrl.path( -1 ) ).exists() )
+ destUrl.setProtocol( "file" ); // if we get out from the archive change the protocol
+ }
+ }
+
+ KIO::Job* job = new KIO::CopyJob( *fileUrls, destUrl, mode, false, true );
+ connect( job, SIGNAL( result( KIO::Job* ) ), this, SLOT( vfs_refresh( KIO::Job* ) ) );
+ if ( mode == KIO::CopyJob::Move ) // notify the other panel
+ connect( job, SIGNAL( result( KIO::Job* ) ), toNotify, SLOT( vfs_refresh( KIO::Job* ) ) );
+}
+
+// remove a file from the vfs (physical)
+void ftp_vfs::vfs_delFiles( QStringList *fileNames ) {
+ KURL::List filesUrls;
+ KURL url;
+
+ // names -> urls
+ for ( uint i = 0 ; i < fileNames->count(); ++i ) {
+ QString filename = ( *fileNames ) [ i ];
+ url = vfs_origin;
+ url.addPath( filename );
+ filesUrls.append( url );
+ }
+ KIO::Job *job = new KIO::DeleteJob( filesUrls, false, true );
+ connect( job, SIGNAL( result( KIO::Job* ) ), this, SLOT( vfs_refresh( KIO::Job* ) ) );
+}
+
+
+KURL::List* ftp_vfs::vfs_getFiles( QStringList* names ) {
+ KURL url;
+ KURL::List* urls = new KURL::List();
+ for ( QStringList::Iterator name = names->begin(); name != names->end(); ++name ) {
+ url = vfs_getFile( *name );
+ urls->append( url );
+ }
+ return urls;
+}
+
+
+// return a path to the file
+KURL ftp_vfs::vfs_getFile( const QString& name ) {
+ vfile * vf = vfs_search( name );
+ if ( !vf ) return KURL(); // empty
+
+ KURL url = vf->vfile_getUrl();
+ if ( vf->vfile_isDir() ) url.adjustPath( + 1 );
+ return url;
+}
+
+void ftp_vfs::vfs_mkdir( const QString& name ) {
+ KURL url = vfs_origin;
+ url.addPath( name );
+
+ KIO::SimpleJob* job = KIO::mkdir( url );
+ connect( job, SIGNAL( result( KIO::Job* ) ), this, SLOT( vfs_refresh( KIO::Job* ) ) );
+}
+
+void ftp_vfs::vfs_rename( const QString& fileName, const QString& newName ) {
+ KURL::List fileUrls;
+ KURL oldUrl = vfs_origin;
+ oldUrl.addPath( fileName ) ;
+
+ fileUrls.append( oldUrl );
+
+ KURL newUrl = vfs_origin;
+ newUrl.addPath( newName );
+
+ KIO::Job *job = new KIO::CopyJob( fileUrls, newUrl, KIO::CopyJob::Move, true, true );
+ connect( job, SIGNAL( result( KIO::Job* ) ), this, SLOT( vfs_refresh( KIO::Job* ) ) );
+}
+
+QString ftp_vfs::vfs_workingDir() {
+ return vfs_origin.url( -1 );
+}
+
+#include "ftp_vfs.moc"
diff --git a/krusader/VFS/ftp_vfs.h b/krusader/VFS/ftp_vfs.h
new file mode 100644
index 0000000..14387a8
--- /dev/null
+++ b/krusader/VFS/ftp_vfs.h
@@ -0,0 +1,79 @@
+/***************************************************************************
+ ftp_vfs.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ A vfs class that handels "ftp/samba" directory enteris
+ inherits: vfs
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef FTP_VFS
+#define FTP_VFS
+
+// KDE includes
+#include <kdirlister.h>
+// Krusader includes
+#include "vfs.h"
+
+class ftp_vfs : public vfs{
+ Q_OBJECT
+public:
+ // the constructor simply uses the inherited constructor
+ ftp_vfs(QObject* panel);
+ ~ftp_vfs();
+
+ /// Copy a file to the vfs (physical).
+ virtual void vfs_addFiles(KURL::List *fileUrls,KIO::CopyJob::CopyMode mode,QObject* toNotify,QString dir = "", PreserveMode pmode = PM_DEFAULT );
+ /// Remove a file from the vfs (physical)
+ virtual void vfs_delFiles(QStringList *fileNames);
+ /// Return a list of URLs for multiple files
+ virtual KURL::List* vfs_getFiles(QStringList* names);
+ /// Return a URL to a single file
+ virtual KURL vfs_getFile(const QString& name);
+ /// Create a new directory
+ virtual void vfs_mkdir(const QString& name);
+ /// Rename file
+ virtual void vfs_rename(const QString& fileName,const QString& newName);
+ /// Return the VFS working dir
+ QString vfs_workingDir();
+
+public slots:
+ /// Handles new files from the dir lister
+ void slotAddFiles(KIO::Job * job, const KIO::UDSEntryList& entries);
+ /// Redirection signal handlers
+ void slotRedirection(KIO::Job *, const KURL &url);
+ void slotPermanentRedirection(KIO::Job*,const KURL&,const KURL& newUrl);
+ /// Called when the dir listing job is finished (for better or worst)
+ void slotListResult(KIO::Job *job);
+ /// Active the dir listing job
+ bool populateVfsList(const KURL& origin, bool showHidden);
+
+protected:
+ KURL origin_backup; //< used to backup the old URL when refreshing to a new one,
+ bool busy;
+ bool listError;
+};
+
+#endif
diff --git a/krusader/VFS/krarchandler.cpp b/krusader/VFS/krarchandler.cpp
new file mode 100644
index 0000000..2d4f0b6
--- /dev/null
+++ b/krusader/VFS/krarchandler.cpp
@@ -0,0 +1,756 @@
+/***************************************************************************
+ krarchandler.cpp
+ -------------------
+ copyright : (C) 2001 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+ Description
+***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+// QT includes
+#include <qtextstream.h>
+// KDE includes
+#include <kprocess.h>
+#include <ktempfile.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kio/passdlg.h>
+#include <qfile.h>
+#include <kstandarddirs.h>
+#include <ktar.h>
+#include <kio/global.h>
+// Krusader includes
+#include "krarchandler.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include "../krservices.h"
+#include "../Dialogs/krpleasewait.h"
+
+static QStringList arcProtocols = QStringList::split(";", "tar;bzip;bzip2;gzip;krarc;zip");
+
+KWallet::Wallet * KRarcHandler::wallet = 0;
+
+QStringList KRarcHandler::supportedPackers() {
+ QStringList packers;
+
+ // we will simply try to find the packers here..
+ if ( KrServices::cmdExist( "tar" ) ) packers.append( "tar" );
+ if ( KrServices::cmdExist( "gzip" ) ) packers.append( "gzip" );
+ if ( KrServices::cmdExist( "bzip2" ) ) packers.append( "bzip2" );
+ if ( KrServices::cmdExist( "unzip" ) ) packers.append( "unzip" );
+ if ( KrServices::cmdExist( "zip" ) ) packers.append( "zip" );
+ if ( KrServices::cmdExist( "lha" ) ) packers.append( "lha" );
+ if ( KrServices::cmdExist( "cpio" ) ) packers.append( "cpio" );
+ if ( KrServices::cmdExist( "unrar" ) ) packers.append( "unrar" );
+ if ( KrServices::cmdExist( "rar" ) ) packers.append( "rar" );
+ if ( KrServices::cmdExist( "arj" ) ) packers.append( "arj" );
+ if ( KrServices::cmdExist( "unarj" ) ) packers.append( "unarj" );
+ if ( KrServices::cmdExist( "unace" ) ) packers.append( "unace" );
+ if ( KrServices::cmdExist( "dpkg" ) ) packers.append( "dpkg" );
+ if ( KrServices::cmdExist( "7z" ) || KrServices::cmdExist( "7za" ) ) packers.append( "7z" );
+ if ( KrServices::cmdExist( "rpm" ) && KrServices::cmdExist( "rpm2cpio" ) ) packers.append( "rpm" );
+ // kdDebug() << "Supported Packers:" << endl;
+ //QStringList::Iterator it;
+ //for( it = packers.begin(); it != packers.end(); ++it )
+ // kdDebug() << *it << endl;
+
+ return packers;
+ }
+
+bool KRarcHandler::arcSupported( QString type ) {
+ // lst will contain the supported unpacker list...
+ krConfig->setGroup( "Archives" );
+ QStringList lst = krConfig->readListEntry( "Supported Packers" );
+
+ if ( type == "-zip" && lst.contains( "unzip" ) )
+ return true;
+ else if ( type == "-tar" && lst.contains( "tar" ) )
+ return true;
+ else if ( type == "-tbz" && lst.contains( "tar" ) )
+ return true;
+ else if ( type == "-tgz" && lst.contains( "tar" ) )
+ return true;
+ else if ( type == "tarz" && lst.contains( "tar" ) )
+ return true;
+ else if ( type == "gzip" && lst.contains( "gzip" ) )
+ return true;
+ else if ( type == "zip2" && lst.contains( "bzip2" ) )
+ return true;
+ else if ( type == "-lha" && lst.contains( "lha" ) )
+ return true;
+ else if ( type == "-ace" && lst.contains( "unace" ) )
+ return true;
+ else if ( type == "-rpm" && lst.contains( "cpio" ) )
+ return true;
+ else if ( type == "cpio" && lst.contains( "cpio" ) )
+ return true;
+ else if ( type == "-rar" && ( lst.contains( "unrar" ) || lst.contains( "rar" ) ) )
+ return true;
+ else if ( type == "-arj" && ( lst.contains( "unarj" ) || lst.contains( "arj" ) ) )
+ return true;
+ else if ( type == "-deb" && ( lst.contains( "dpkg" ) && lst.contains( "tar" ) ) )
+ return true;
+ else if ( type == "-7z" && lst.contains( "7z" ) )
+ return true;
+ // not supported : (
+ return false;
+ }
+
+bool KRarcHandler::arcHandled( QString type ) {
+ // first check if supported
+ if ( !arcSupported( type ) ) return false;
+
+ krConfig->setGroup( "Archives" );
+ if ( ( type == "-tgz" && krConfig->readBoolEntry( "Do GZip" , _DoGZip ) ) ||
+ ( type == "tarz" && krConfig->readBoolEntry( "Do GZip" , _DoGZip ) ) ||
+ ( type == "-tar" && krConfig->readBoolEntry( "Do Tar" , _DoTar ) ) ||
+ ( type == "-tbz" && krConfig->readBoolEntry( "Do BZip2", _DoBZip2 ) ) ||
+ ( type == "gzip" && krConfig->readBoolEntry( "Do GZip" , _DoGZip ) ) ||
+ ( type == "zip2" && krConfig->readBoolEntry( "Do BZip2", _DoBZip2 ) ) ||
+ ( type == "-zip" && krConfig->readBoolEntry( "Do UnZip", _DoUnZip ) ) ||
+ ( type == "-lha" && krConfig->readBoolEntry( "Do Lha", _DoUnZip ) ) ||
+ ( type == "-rar" && krConfig->readBoolEntry( "Do UnRar", _DoUnRar ) ) ||
+ ( type == "-arj" && krConfig->readBoolEntry( "Do UnArj", _DoUnarj ) ) ||
+ ( type == "-ace" && krConfig->readBoolEntry( "Do UnAce", _DoUnAce ) ) ||
+ ( type == "cpio" && krConfig->readBoolEntry( "Do RPM" , _DoRPM ) ) ||
+ ( type == "-rpm" && krConfig->readBoolEntry( "Do RPM" , _DoRPM ) ) ||
+ ( type == "-deb" && krConfig->readBoolEntry( "Do DEB" , _DoDEB ) ) ||
+ ( type == "-7z" && krConfig->readBoolEntry( "Do 7z" , _Do7z ) ) )
+ return true;
+ else
+ return false;
+ }
+
+
+long KRarcHandler::arcFileCount( QString archive, QString type, QString password ) {
+ int divideWith = 1;
+
+ // first check if supported
+ if ( !arcSupported( type ) ) return 0;
+
+ // bzip an gzip archive contains only one file
+ if ( type == "zip2" || type == "gzip" ) return 1L;
+
+ // set the right lister to do the job
+ QString lister;
+
+ if ( type == "-zip" ) lister = KrServices::fullPathName( "unzip" ) + " -ZTs";
+ else if ( type == "-tar" ) lister = KrServices::fullPathName( "tar" ) + " -tvf";
+ else if ( type == "-tgz" ) lister = KrServices::fullPathName( "tar" ) + " -tvzf";
+ else if ( type == "tarz" ) lister = KrServices::fullPathName( "tar" ) + " -tvzf";
+ else if ( type == "-tbz" ) lister = KrServices::fullPathName( "tar" ) + " -tjvf";
+ else if ( type == "-lha" ) lister = KrServices::fullPathName( "lha" ) + " l";
+ else if ( type == "-rar" ) lister = KrServices::fullPathName( KrServices::cmdExist( "rar" ) ? "rar" : "unrar" ) + " l -v";
+ else if ( type == "-ace" ) lister = KrServices::fullPathName( "unace" ) + " l";
+ else if ( type == "-arj" ) { if( KrServices::cmdExist( "arj" ) )
+ lister = KrServices::fullPathName( "arj" ) + " v -y -v",
+ divideWith = 4;
+ else
+ lister = KrServices::fullPathName( "unarj" ) + " l";
+ }
+ else if ( type == "-rpm" ) lister = KrServices::fullPathName( "rpm" ) + " --dump -lpq";
+ else if ( type == "-deb" ) lister = KrServices::fullPathName( "dpkg" ) + " -c";
+ else if ( type == "-7z" ) lister = KrServices::fullPathName( "7z" ) + " -y l";
+ else return 0L;
+
+ if ( !password.isNull() ) {
+ if ( type == "-arj" )
+ lister += " -g'" + password + "'";
+ if ( type == "-ace" || type == "-rar" || type == "-7z" )
+ lister += " -p'" + password + "'";
+ }
+
+ // tell the user to wait
+ krApp->startWaiting( i18n( "Counting files in archive" ), 0, true );
+
+ // count the number of files in the archive
+ long count = 1;
+ KTempFile tmpFile( /*"tmp"*/ QString::null, "krusader-unpack" ); // commented out as it created files in the current dir!
+ KrShellProcess list;
+ list << lister << KrServices::quote( archive ) << ">" << tmpFile.name() ;
+ if( type == "-ace" && QFile( "/dev/ptmx" ).exists() ) // Don't remove, unace crashes if missing!!!
+ list<< "<" << "/dev/ptmx";
+ list.start( KProcess::NotifyOnExit, KProcess::AllOutput );
+ while ( list.isRunning() ) {
+ usleep( 1000 );
+ qApp->processEvents();
+ if( krApp->wasWaitingCancelled() )
+ list.kill();
+ }
+ ; // busy wait - need to find something better...
+
+ krApp->stopWait();
+
+ if( !list.normalExit() || !checkStatus( type, list.exitStatus() ) ) {
+ KMessageBox::detailedError (krApp, i18n( "Failed to list the content of the archive (%1)!" ).arg( archive ),
+ list.getErrorMsg(), i18n("Error" ) );
+ return 0;
+ }
+
+ QTextStream *stream = tmpFile.textStream();
+ while ( stream && stream->readLine() != QString::null ) ++count;
+ tmpFile.unlink();
+
+ //make sure you call stopWait after this function return...
+ //krApp->stopWait();
+
+ return count / divideWith;
+ }
+
+bool KRarcHandler::unpack( QString archive, QString type, QString password, QString dest ) {
+ krConfig->setGroup( "Archives" );
+ if ( krConfig->readBoolEntry( "Test Before Unpack", _TestBeforeUnpack ) ) {
+ // test first - or be sorry later...
+ if ( type != "-rpm" && type != "-deb" && !test( archive, type, password, 0 ) ) {
+ KMessageBox::error( krApp, i18n( "Failed to unpack" ) + " \"" + archive + "\" !" );
+ return false;
+ }
+ }
+
+ // count the files in the archive
+ long count = arcFileCount( archive, type, password );
+ if ( count == 0 ) return false; // not supported
+ if ( count == 1 ) count = 0 ;
+
+ // choose the right packer for the job
+ QString packer, cpioName = QString::null;
+
+ // set the right packer to do the job
+ if ( type == "-zip" ) packer = KrServices::fullPathName( "unzip" ) + " -o" ;
+ else if ( type == "-tar" ) packer = KrServices::fullPathName( "tar" ) + " -xvf";
+ else if ( type == "-tgz" ) packer = KrServices::fullPathName( "tar" ) + " -xvzf";
+ else if ( type == "tarz" ) packer = KrServices::fullPathName( "tar" ) + " -xvzf";
+ else if ( type == "-tbz" ) packer = KrServices::fullPathName( "tar" ) + " -xjvf";
+ else if ( type == "gzip" ) packer = KrServices::fullPathName( "gzip" ) + " -cd";
+ else if ( type == "zip2" ) packer = KrServices::fullPathName( "bzip2" ) + " -cdk";
+ else if ( type == "-lha" ) packer = KrServices::fullPathName( "lha" ) + " xf";
+ else if ( type == "-rar" ) packer = KrServices::fullPathName( KrServices::cmdExist( "rar" ) ? "rar" : "unrar" ) + " -y x";
+ else if ( type == "-ace" ) packer = KrServices::fullPathName( "unace" ) + " x";
+ else if ( type == "-arj" ) packer = KrServices::cmdExist( "arj" ) ?
+ KrServices::fullPathName( "arj" ) + " -y -v x" :
+ KrServices::fullPathName( "unarj" ) + " x";
+ else if ( type == "-7z" ) packer = KrServices::fullPathName( "7z" ) + " -y x";
+ else if ( type == "-rpm" ) {
+ QString tempDir = locateLocal("tmp",QString::null);
+
+ cpioName = tempDir+"/contents.cpio";
+
+ KrShellProcess cpio;
+ cpio << KrServices::fullPathName( "rpm2cpio" ) << " " + KrServices::quote( archive ) << " > " << cpioName;
+ cpio.start(KProcess::Block, KProcess::AllOutput );
+ if( !cpio.normalExit() || !checkStatus( "cpio", cpio.exitStatus() ) ) {
+ KMessageBox::detailedError (krApp, i18n( "Failed to convert rpm (%1) to cpio!" ).arg( archive ),
+ cpio.getErrorMsg(), i18n("Error" ) );
+ return 0;
+ }
+
+ archive = cpioName;
+ packer = KrServices::fullPathName( "cpio" ) + " --force-local --no-absolute-filenames -iuvdF";
+ }
+ else if ( type == "-deb" ) {
+ QString tempDir = locateLocal("tmp",QString::null);
+
+ cpioName = tempDir+"/contents.tar";
+
+ KrShellProcess dpkg;
+ dpkg << KrServices::fullPathName( "dpkg" ) << " --fsys-tarfile " + KrServices::quote( archive ) << " > " << cpioName;
+ dpkg.start(KProcess::Block, KProcess::AllOutput );
+ if( !dpkg.normalExit() || !checkStatus( "-deb", dpkg.exitStatus() ) ) {
+ KMessageBox::detailedError (krApp, i18n( "Failed to convert deb (%1) to tar!" ).arg( archive ),
+ dpkg.getErrorMsg(), i18n("Error" ) );
+ return 0;
+ }
+
+ archive = cpioName;
+ packer = KrServices::fullPathName( "tar" ) + " xvf ";
+ }
+ else return false;
+
+ if ( !password.isNull() ) {
+ if ( type == "-zip" )
+ packer += " -P '" + password + "'";
+ if ( type == "-arj" )
+ packer += " -g'" + password + "'";
+ if ( type == "-ace" || type == "-rar" || type == "-7z" )
+ packer += " -p'" + password + "'";
+ }
+
+ // unpack the files
+ KrShellProcess proc;
+ proc << packer << " " + KrServices::quote( archive );
+ if( type == "zip2" || type=="gzip" ){
+ QString arcname = archive.mid(archive.findRev("/")+1);
+ if( arcname.contains(".") ) arcname = arcname.left(arcname.findRev("."));
+ proc << ">" << KrServices::quote( dest+"/"+arcname );
+ }
+ if( type == "-ace" && QFile( "/dev/ptmx" ).exists() ) // Don't remove, unace crashes if missing!!!
+ proc << "<" << "/dev/ptmx";
+
+ QString save = getcwd( 0, 0 );
+ chdir( dest.local8Bit() );
+
+ // tell the user to wait
+ krApp->startWaiting( i18n( "Unpacking File(s)" ), count, true );
+ if ( count != 0 ) {
+ connect( &proc, SIGNAL( receivedStdout( KProcess*, char*, int ) ),
+ krApp, SLOT( incProgress( KProcess*, char*, int ) ) );
+ if( type == "-rpm" )
+ connect( &proc, SIGNAL( receivedStderr( KProcess*, char*, int ) ),
+ krApp, SLOT( incProgress( KProcess*, char*, int ) ) );
+ }
+
+ // start the unpacking process
+ proc.start( KProcess::NotifyOnExit, KProcess::AllOutput );
+ while ( proc.isRunning() ) {
+ usleep( 1000 );
+ qApp->processEvents();
+ if( krApp->wasWaitingCancelled() )
+ proc.kill();
+ }
+ ; // busy wait - need to find something better...
+ krApp->stopWait();
+ chdir( save.local8Bit() );
+
+ if( !cpioName.isEmpty() )
+ QFile( cpioName ).remove(); /* remove the cpio file */
+
+ // check the return value
+ if ( !proc.normalExit() || !checkStatus( type, proc.exitStatus() ) ) {
+ KMessageBox::detailedError (krApp, i18n( "Failed to unpack %1!" ).arg( archive ),
+ krApp->wasWaitingCancelled() ? i18n( "User cancelled." ) :
+ proc.getErrorMsg(), i18n("Error" ) );
+ return false;
+ }
+ return true; // SUCCESS
+ }
+
+bool KRarcHandler::test( QString archive, QString type, QString password, long count ) {
+ // choose the right packer for the job
+ QString packer;
+
+ // set the right packer to do the job
+ if ( type == "-zip" ) packer = KrServices::fullPathName( "unzip" ) + " -t";
+ else if ( type == "-tar" ) packer = KrServices::fullPathName( "tar" ) + " -tvf";
+ else if ( type == "-tgz" ) packer = KrServices::fullPathName( "tar" ) + " -tvzf";
+ else if ( type == "tarz" ) packer = KrServices::fullPathName( "tar" ) + " -tvzf";
+ else if ( type == "-tbz" ) packer = KrServices::fullPathName( "tar" ) + " -tjvf";
+ else if ( type == "gzip" ) packer = KrServices::fullPathName( "gzip" ) + " -tv";
+ else if ( type == "zip2" ) packer = KrServices::fullPathName( "bzip2" ) + " -tv";
+ else if ( type == "-rar" ) packer = KrServices::fullPathName( KrServices::cmdExist( "rar" ) ? "rar" : "unrar" ) + " t";
+ else if ( type == "-ace" ) packer = KrServices::fullPathName( "unace" ) + " t";
+ else if ( type == "-lha" ) packer = KrServices::fullPathName( "lha" ) + " t";
+ else if ( type == "-arj" ) packer = KrServices::fullPathName( KrServices::cmdExist( "arj" ) ? "arj" : "unarj" ) + " t";
+ else if ( type == "cpio" ) packer = KrServices::fullPathName( "cpio" ) + " --only-verify-crc -tvF" ;
+ else if ( type == "-7z" ) packer = KrServices::fullPathName( "7z" ) + " -y t";
+ else return false;
+
+ if ( !password.isNull() ) {
+ if ( type == "-zip" )
+ packer += " -P '" + password + "'";
+ if ( type == "-arj" )
+ packer += " -g'" + password + "'";
+ if ( type == "-ace" || type == "-rar" || type == "-7z" )
+ packer += " -p'" + password + "'";
+ }
+
+ // unpack the files
+ KrShellProcess proc;
+ proc << packer << KrServices::quote( archive );
+
+ if( type == "-ace" && QFile( "/dev/ptmx" ).exists() ) // Don't remove, unace crashes if missing!!!
+ proc << "<" << "/dev/ptmx";
+
+ // tell the user to wait
+ krApp->startWaiting( i18n( "Testing Archive" ), count, true );
+ if ( count != 0 ) connect( &proc, SIGNAL( receivedStdout( KProcess*, char*, int ) ),
+ krApp, SLOT( incProgress( KProcess*, char*, int ) ) );
+
+ // start the unpacking process
+ proc.start( KProcess::NotifyOnExit, KProcess::AllOutput );
+ while ( proc.isRunning() ) {
+ usleep( 1000 );
+ qApp->processEvents();
+ if( krApp->wasWaitingCancelled() )
+ proc.kill();
+ }
+ ; // busy wait - need to find something better...
+ krApp->stopWait();
+
+ // check the return value
+ if ( !proc.normalExit() || !checkStatus( type, proc.exitStatus() ) )
+ return false;
+
+ return true; // SUCCESS
+ }
+
+bool KRarcHandler::pack( QStringList fileNames, QString type, QString dest, long count, QMap<QString,QString> extraProps ) {
+ // set the right packer to do the job
+ QString packer;
+
+ if ( type == "zip" ) { packer = KrServices::fullPathName( "zip" ) + " -ry"; type = "-zip"; }
+ else if ( type == "tar" ) { packer = KrServices::fullPathName( "tar" ) + " -cvf"; type = "-tar"; }
+ else if ( type == "tar.gz" ) { packer = KrServices::fullPathName( "tar" ) + " -cvzf"; type = "-tgz"; }
+ else if ( type == "tar.bz2" ) { packer = KrServices::fullPathName( "tar" ) + " -cvjf"; type = "-tbz"; }
+ else if ( type == "rar" ) { packer = KrServices::fullPathName( "rar" ) + " -r a"; type = "-rar"; }
+ else if ( type == "lha" ) { packer = KrServices::fullPathName( "lha" ) + " a"; type = "-lha"; }
+ else if ( type == "arj" ) { packer = KrServices::fullPathName( "arj" ) + " -r -y a"; type = "-arj"; }
+ else if ( type == "7z" ) { packer = KrServices::fullPathName( "7z" ) + " -y a"; type = "-7z"; }
+ else return false;
+
+ QString password = QString::null;
+
+ if( extraProps.count( "Password" ) > 0 ) {
+ password = extraProps[ "Password" ];
+
+ if ( !password.isNull() ) {
+ if ( type == "-zip" )
+ packer += " -P '" + password + "'";
+ else if ( type == "-arj" )
+ packer += " -g'" + password + "'";
+ else if ( type == "-ace" || type == "-7z" )
+ packer += " -p'" + password + "'";
+ else if ( type == "-rar" ) {
+ if( extraProps.count( "EncryptHeaders" ) > 0 )
+ packer += " -hp'" + password + "'";
+ else
+ packer += " -p'" + password + "'";
+ }
+ else
+ password = QString::null;
+ }
+ }
+
+ if( extraProps.count( "VolumeSize" ) > 0 ) {
+ QString sizeStr = extraProps[ "VolumeSize" ];
+ KIO::filesize_t size = sizeStr.toLongLong();
+
+ if( size >= 10000 ) {
+ if( type == "-arj" || type == "-rar" )
+ packer += QString( " -v%1b" ).arg( sizeStr );
+ }
+ }
+
+ if( extraProps.count( "CompressionLevel" ) > 0 ) {
+ int level = extraProps[ "CompressionLevel" ].toInt() - 1;
+ if ( level < 0 )
+ level = 0;
+ if ( level > 8 )
+ level = 8;
+
+ if( type == "-rar" ) {
+ static const int rarLevels[] = { 0, 1, 2, 2, 3, 3, 4, 4, 5 };
+ packer += QString( " -m%1" ).arg( rarLevels[ level ] );
+ }
+ else if( type == "-arj" ) {
+ static const int arjLevels[] = { 0, 4, 4, 3, 3, 2, 2, 1, 1 };
+ packer += QString( " -m%1" ).arg( arjLevels[ level ] );
+ }
+ else if( type == "-zip" ) {
+ static const int zipLevels[] = { 0, 1, 2, 4, 5, 6, 7, 8, 9 };
+ packer += QString( " -%1" ).arg( zipLevels[ level ] );
+ }
+ else if( type == "-7z" ) {
+ static const int sevenZipLevels[] = { 0, 1, 2, 4, 5, 6, 7, 8, 9 };
+ packer += QString( " -mx%1" ).arg( sevenZipLevels[ level ] );
+ }
+ }
+
+ if( extraProps.count( "CommandLineSwitches" ) > 0 )
+ packer += QString( " %1" ).arg( extraProps[ "CommandLineSwitches" ] );
+
+ // prepare to pack
+ KrShellProcess proc;
+ proc << packer << KrServices::quote( dest );
+
+ for ( QStringList::Iterator file = fileNames.begin(); file != fileNames.end(); ++file ) {
+ proc << KrServices::quote( *file );
+ }
+
+ // tell the user to wait
+ krApp->startWaiting( i18n( "Packing File(s)" ), count, true );
+ if ( count != 0 )
+ connect( &proc, SIGNAL( receivedStdout( KProcess*, char*, int ) ),
+ krApp, SLOT( incProgress( KProcess*, char*, int ) ) );
+
+ // start the packing process
+ proc.start( KProcess::NotifyOnExit, KProcess::AllOutput );
+ while ( proc.isRunning() ) {
+ usleep( 1000 );
+ qApp->processEvents();
+ if( krApp->wasWaitingCancelled() )
+ proc.kill();
+ }
+ ; // busy wait - need to find something better...
+ krApp->stopWait();
+
+ // check the return value
+ if ( !proc.normalExit() || !checkStatus( type, proc.exitStatus() ) ) {
+ KMessageBox::detailedError (krApp, i18n( "Failed to pack %1!" ).arg( dest ),
+ krApp->wasWaitingCancelled() ? i18n( "User cancelled." ) : proc.getErrorMsg(),
+ i18n("Error" ) );
+ return false;
+ }
+
+ krConfig->setGroup( "Archives" );
+ if ( krConfig->readBoolEntry( "Test Archives", _TestArchives ) &&
+ !test( dest, type, password, count ) ) {
+ KMessageBox::error( krApp, i18n( "Failed to pack: " ) + dest, i18n( "Error" ) );
+ return false;
+ }
+ return true; // SUCCESS
+ }
+
+QString KRarcHandler::getPassword( QString path ) {
+ QString password;
+
+ QString key = "krarc-" + path;
+
+ if( !KWallet::Wallet::keyDoesNotExist(KWallet::Wallet::NetworkWallet(), KWallet::Wallet::PasswordFolder(), key ) ) {
+ if( !KWallet::Wallet::isOpen( KWallet::Wallet::NetworkWallet() ) && wallet != 0 ) {
+ delete wallet;
+ wallet = 0;
+ }
+ if( wallet == 0 )
+ wallet = KWallet::Wallet::openWallet( KWallet::Wallet::NetworkWallet() );
+ if ( wallet && wallet->hasFolder( KWallet::Wallet::PasswordFolder() ) ) {
+ wallet->setFolder( KWallet::Wallet::PasswordFolder() );
+ QMap<QString,QString> map;
+ if ( wallet->readMap( key, map ) == 0 ) {
+ QMap<QString, QString>::ConstIterator it = map.find( "password" );
+ if ( it != map.end() )
+ password = it.data();
+ }
+ }
+ }
+
+ bool keep = true;
+ QString user = "archive";
+ KIO::PasswordDialog passDlg( i18n("This archive is encrypted, please supply the password:"),
+ user, true );
+ passDlg.setPassword( password );
+ if (passDlg.exec() == KIO::PasswordDialog::Accepted) {
+ password = passDlg.password();
+ if ( keep ) {
+ if( !KWallet::Wallet::isOpen( KWallet::Wallet::NetworkWallet() ) && wallet != 0 ) {
+ delete wallet;
+ wallet = 0;
+ }
+ if ( !wallet )
+ wallet = KWallet::Wallet::openWallet( KWallet::Wallet::NetworkWallet() );
+ if ( wallet ) {
+ bool ok = true;
+ if ( !wallet->hasFolder( KWallet::Wallet::PasswordFolder() ) )
+ ok = wallet->createFolder( KWallet::Wallet::PasswordFolder() );
+ if ( ok ) {
+ wallet->setFolder( KWallet::Wallet::PasswordFolder() );
+ QMap<QString,QString> map;
+ map.insert( "login", "archive" );
+ map.insert( "password", password );
+ wallet->writeMap( key, map );
+ }
+ }
+ }
+ return password;
+ }
+
+ return "";
+}
+
+bool KRarcHandler::isArchive(const KURL& url) {
+ QString protocol = url.protocol();
+ if (arcProtocols.find(protocol) != arcProtocols.end())
+ return true;
+ else return false;
+}
+
+QString KRarcHandler::getType( bool &encrypted, QString fileName, QString mime, bool checkEncrypted ) {
+ QString result = detectArchive( encrypted, fileName, checkEncrypted );
+ if( result.isNull() )
+ result = mime;
+ else
+ result = "-" + result;
+
+ if( result.endsWith( "-7z" ) )
+ result = "-7z";
+
+ return result.right( 4 );
+}
+
+
+bool KRarcHandler::checkStatus( QString type, int exitCode ) {
+ if( type == "-zip" || type == "-rar" || type == "-7z" )
+ return exitCode == 0 || exitCode == 1;
+ else if( type == "-ace" || type == "zip2" || type == "-lha" || type == "-rpm" || type == "cpio" ||
+ type == "-tar" || type == "tarz" || type == "-tbz" || type == "-tgz" || type == "-arj" ||
+ type == "-deb" )
+ return exitCode == 0;
+ else if( type == "gzip" )
+ return exitCode == 0 || exitCode == 2;
+ else
+ return exitCode == 0;
+}
+
+struct AutoDetectParams {
+ QString type;
+ int location;
+ QString detectionString;
+};
+
+QString KRarcHandler::detectArchive( bool &encrypted, QString fileName, bool checkEncrypted ) {
+ static AutoDetectParams autoDetectParams[] = {{"zip", 0, "PK\x03\x04"},
+ {"rar", 0, "Rar!\x1a" },
+ {"arj", 0, "\x60\xea" },
+ {"rpm", 0, "\xed\xab\xee\xdb"},
+ {"ace", 7, "**ACE**" },
+ {"bzip2",0, "\x42\x5a\x68\x39\x31" },
+ {"gzip", 0, "\x1f\x8b"},
+ {"deb", 0, "!<arch>\ndebian-binary " },
+ {"7z", 0, "7z\xbc\xaf\x27\x1c" } };
+ static int autoDetectElems = sizeof( autoDetectParams ) / sizeof( AutoDetectParams );
+
+ encrypted = false;
+
+ QFile arcFile( fileName );
+ if ( arcFile.open( IO_ReadOnly ) ) {
+ char buffer[ 1024 ];
+ long sizeMax = arcFile.readBlock( buffer, sizeof( buffer ) );
+ arcFile.close();
+
+ for( int i=0; i < autoDetectElems; i++ ) {
+ QString detectionString = autoDetectParams[ i ].detectionString;
+ int location = autoDetectParams[ i ].location;
+
+ int endPtr = detectionString.length() + location;
+ if( endPtr > sizeMax )
+ continue;
+
+ unsigned int j=0;
+ for(; j != detectionString.length(); j++ ) {
+ if( detectionString[ j ] == '?' )
+ continue;
+ if( buffer[ location + j ] != detectionString[ j ] )
+ break;
+ }
+
+ if( j == detectionString.length() ) {
+ QString type = autoDetectParams[ i ].type;
+ if( type == "bzip2" || type == "gzip" ) {
+ KTar tapeArchive( fileName );
+ if( tapeArchive.open( IO_ReadOnly ) ) {
+ tapeArchive.close();
+ if( type == "bzip2" )
+ type = "tbz";
+ else
+ type = "tgz";
+ }
+ }
+ else if( type == "zip" )
+ encrypted = (buffer[6] & 1);
+ else if( type == "arj" ) {
+ if( sizeMax > 4 ) {
+ long headerSize = ((unsigned char *)buffer)[ 2 ] + 256*((unsigned char *)buffer)[ 3 ];
+ long fileHeader = headerSize + 10;
+ if( fileHeader + 9 < sizeMax && buffer[ fileHeader ] == (char)0x60 && buffer[ fileHeader + 1 ] == (char)0xea )
+ encrypted = (buffer[ fileHeader + 8 ] & 1 );
+ }
+ }
+ else if( type == "rar" ) {
+ if( sizeMax > 13 && buffer[ 9 ] == (char)0x73 ) {
+ if( buffer[ 10 ] & 0x80 ) { // the header is encrypted?
+ encrypted = true;
+ } else {
+ long offset = 7;
+ long mainHeaderSize = ((unsigned char *)buffer)[ offset+5 ] + 256*((unsigned char *)buffer)[ offset+6 ];
+ offset += mainHeaderSize;
+ while( offset + 10 < sizeMax ) {
+ long headerSize = ((unsigned char *)buffer)[ offset+5 ] + 256*((unsigned char *)buffer)[ offset+6 ];
+ bool isDir = (buffer[ offset+7 ] == '\0' ) && (buffer[ offset+8 ] == '\0' ) &&
+ (buffer[ offset+9 ] == '\0' ) && (buffer[ offset+10 ] == '\0' );
+
+ if( buffer[ offset + 2 ] != (char)0x74 )
+ break;
+ if( !isDir ) {
+ encrypted = ( buffer[ offset + 3 ] & 4 ) != 0;
+ break;
+ }
+ offset += headerSize;
+ }
+ }
+ }
+ }
+ else if( type == "ace" ) {
+ long offset = 0;
+ long mainHeaderSize = ((unsigned char *)buffer)[ offset+2 ] + 256*((unsigned char *)buffer)[ offset+3 ] + 4;
+ offset += mainHeaderSize;
+ while( offset + 10 < sizeMax ) {
+ long headerSize = ((unsigned char *)buffer)[ offset+2 ] + 256*((unsigned char *)buffer)[ offset+3 ] + 4;
+ bool isDir = (buffer[ offset+11 ] == '\0' ) && (buffer[ offset+12 ] == '\0' ) &&
+ (buffer[ offset+13 ] == '\0' ) && (buffer[ offset+14 ] == '\0' );
+
+ if( buffer[ offset + 4 ] != (char)0x01 )
+ break;
+ if( !isDir ) {
+ encrypted = ( buffer[ offset + 6 ] & 64 ) != 0;
+ break;
+ }
+ offset += headerSize;
+ }
+ }
+ else if( type == "7z" ) {
+ if( checkEncrypted ) { // encryption check is expensive
+ // check only if it's necessary
+ Kr7zEncryptionChecker proc;
+ proc << KrServices::fullPathName( "7z" ) << " -y t";
+ proc << KrServices::quote( fileName );
+ proc.start(KProcess::Block,KProcess::AllOutput);
+ encrypted = proc.isEncrypted();
+ }
+ }
+ return type;
+ }
+ }
+
+ if( sizeMax >= 512 ) {
+ /* checking if it's a tar file */
+ unsigned checksum = 32*8;
+ char chksum[ 9 ];
+ for( int i=0; i != 512; i++ )
+ checksum += ((unsigned char *)buffer)[ i ];
+ for( int i=148; i != 156; i++ )
+ checksum -= ((unsigned char *)buffer)[ i ];
+ sprintf( chksum, "0%o", checksum );
+ if( !memcmp( buffer + 148, chksum, strlen( chksum ) ) ) {
+ int k = strlen( chksum );
+ for(; k < 8; k++ )
+ if( buffer[148+k] != 0 && buffer[148+k] != 32 )
+ break;
+ if( k==8 )
+ return "tar";
+ }
+ }
+ }
+ return QString::null;
+}
+
+#include "krarchandler.moc"
+
diff --git a/krusader/VFS/krarchandler.h b/krusader/VFS/krarchandler.h
new file mode 100644
index 0000000..3d3606d
--- /dev/null
+++ b/krusader/VFS/krarchandler.h
@@ -0,0 +1,148 @@
+/***************************************************************************
+ krarchandler.h
+ -------------------
+ copyright : (C) 2001 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description: this class will supply static archive handling functions.
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef KRARCHANDLER_H
+#define KRARCHANDLER_H
+
+#include <qstringlist.h>
+#include <qobject.h>
+#include <kprocess.h>
+#include <kurl.h>
+#include <kwallet.h>
+
+class KRarcHandler: public QObject {
+ Q_OBJECT
+public:
+ // return the number of files in the archive
+ static long arcFileCount(QString archive, QString type, QString password);
+ // unpack an archive to destination directory
+ static bool unpack(QString archive, QString type, QString password, QString dest );
+ // pack an archive to destination directory
+ static bool pack(QStringList fileNames, QString type, QString dest, long count, QMap<QString,QString> extraProps );
+ // test an archive
+ static bool test(QString archive, QString type, QString password, long count = 0L );
+ // true - if the right unpacker exist in the system
+ static bool arcSupported(QString type);
+ // true - if supported and the user want us to handle this kind of archive
+ static bool arcHandled(QString type);
+ // return the a list of supported packers
+ static QStringList supportedPackers();
+ // true - if the url is an archive (ie: tar:/home/test/file.tar.bz2)
+ static bool isArchive(const KURL& url);
+ // used to determine the type of the archive
+ static QString getType( bool &encrypted, QString fileName, QString mime, bool checkEncrypted = true );
+ // queries the password from the user
+ static QString getPassword( QString path );
+ // detects the archive type
+ static QString detectArchive( bool &encrypted, QString fileName, bool checkEncrypted = true );
+private:
+ // checks if the returned status is correct
+ static bool checkStatus( QString type, int exitCode );
+
+ static KWallet::Wallet * wallet;
+};
+
+class KrShellProcess : public KShellProcess {
+ Q_OBJECT
+public:
+ KrShellProcess() : KShellProcess(), errorMsg( QString::null ), outputMsg( QString::null ) {
+ connect(this,SIGNAL(receivedStderr(KProcess*,char*,int)),
+ this,SLOT(receivedErrorMsg(KProcess*,char*,int)) );
+ connect(this,SIGNAL(receivedStdout(KProcess*,char*,int)),
+ this,SLOT(receivedOutputMsg(KProcess*,char*,int)) );
+ }
+
+ QString getErrorMsg() {
+ if( errorMsg.stripWhiteSpace().isEmpty() )
+ return outputMsg.right( 500 );
+ else
+ return errorMsg.right( 500 );
+ }
+
+public slots:
+ void receivedErrorMsg(KProcess*, char *buf, int len) {
+ errorMsg += QString::fromLocal8Bit( buf, len );
+ if( errorMsg.length() > 500 )
+ errorMsg = errorMsg.right( 500 );
+ receivedOutputMsg( 0, buf, len );
+ }
+
+ void receivedOutputMsg(KProcess*, char *buf, int len) {
+ outputMsg += QString::fromLocal8Bit( buf, len );
+ if( outputMsg.length() > 500 )
+ outputMsg = outputMsg.right( 500 );
+ }
+
+private:
+ QString errorMsg;
+ QString outputMsg;
+};
+
+class Kr7zEncryptionChecker : public KrShellProcess {
+ Q_OBJECT
+
+public:
+ Kr7zEncryptionChecker() : KrShellProcess(), encrypted( false ), lastData() {
+ connect(this,SIGNAL(receivedStdout(KProcess*,char*,int)),
+ this,SLOT(processStdout(KProcess*,char*,int)) );
+ }
+
+public slots:
+ void processStdout( KProcess *proc,char *buf,int len ) {
+ QByteArray d(len);
+ d.setRawData(buf,len);
+ QString data = QString( d );
+ d.resetRawData(buf,len);
+
+ QString checkable = lastData + data;
+
+ QStringList lines = QStringList::split( '\n', checkable );
+ lastData = lines[ lines.count() - 1 ];
+ for( unsigned i=0; i != lines.count(); i++ ) {
+ QString line = lines[ i ].stripWhiteSpace().lower();
+ int ndx = line.find( "testing" );
+ if( ndx >=0 )
+ line.truncate( ndx );
+ if( line.isEmpty() )
+ continue;
+
+ if( line.contains( "password" ) && line.contains( "enter" ) ) {
+ encrypted = true;
+ proc->kill();
+ }
+ }
+ }
+
+ bool isEncrypted() { return encrypted; }
+private:
+ bool encrypted;
+ QString lastData;
+};
+
+#endif
diff --git a/krusader/VFS/krdirwatch.cpp b/krusader/VFS/krdirwatch.cpp
new file mode 100644
index 0000000..96ec185
--- /dev/null
+++ b/krusader/VFS/krdirwatch.cpp
@@ -0,0 +1,124 @@
+/***************************************************************************
+ krdirwatch.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u rc e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#include "krdirwatch.h"
+#include <unistd.h>
+#include <sys/types.h>
+#include <kdebug.h>
+#include "krpermhandler.h"
+#include "qstringlist.h"
+#include <qdir.h>
+
+KRdirWatch::KRdirWatch(int msec,bool dirOnly):
+ delay(msec),t(this), changed(false) {
+ if(dirOnly) dir.setFilter( QDir::Dirs | QDir::Hidden | QDir::NoSymLinks );
+ watched.setAutoDelete(true);
+ connect(&t,SIGNAL(timeout()),this, SLOT(checkDirs()));
+ startScan();
+}
+
+KRdirWatch::~KRdirWatch(){
+ clearList();
+ stopScan();
+}
+
+void KRdirWatch::removeDir(QString path){
+ t.stop();
+ for ( it = watched.first(); it != 0; )
+ if (it->path == path) watched.remove();
+ else it = watched.next();
+ if (!stopped) startScan();
+}
+
+void KRdirWatch::addDir(QString path, bool checkPermissions){
+ t.stop();
+
+ krDirEntry* temp = new krDirEntry;
+ if (!dir.cd(path)){ // if it's not a dir or don't exist - don't add it
+ //kdDebug() << "KRDirWatch: can't watch " + path +", (don't exist)" << endl;
+ return;
+ }
+ if( checkPermissions ) {
+ // if we can't read it - don't bother
+ if (getgid() != 0 && !KRpermHandler::fileReadable(path) ){
+ //kdDebug() << "KRDirWatch: can't watch " + path +", (not readable)" << endl;
+ return;
+ }
+ if (!KRpermHandler::fileWriteable(path) ){ // read-only directorys can't be changed
+ //kdDebug() << "KRDirWatch: not watching " + path +", (read-only directory)" << endl;
+ return;
+ }
+ }
+ qfi.setFile(path);
+
+ temp->path = dir.path();
+ temp->count = dir.entryList(QDir::All | QDir::AccessMask).count();
+ temp->lastModified = qfi.lastModified();
+
+ watched.append(temp);
+ if (!stopped) startScan();
+}
+
+// here we do the actual checking
+void KRdirWatch::checkDirs(){
+ t.stop();
+
+ QString path;
+ unsigned long count;
+ QDateTime dt;
+
+ for ( it = watched.first(); it != 0; it = watched.next() ){
+ path = it->path;
+ qfi.setFile(path);
+ if (!dir.cd(path)){
+ clearList();
+ emit dirty();
+ return;
+ }
+ dt = qfi.lastModified();
+ count = dir.entryList(QDir::All | QDir::AccessMask).count();
+ // check for changes
+ if(it->lastModified!=dt || it->count!=count){
+ changed = true;
+ it->lastModified=dt;
+ it->count=count;
+ startScan();
+ return;
+ }
+ if(changed){
+ changed = false;
+ clearList();
+ emit dirty();
+ return;
+ }
+ }
+ if (!stopped) startScan();
+}
+
+#include "krdirwatch.moc"
diff --git a/krusader/VFS/krdirwatch.h b/krusader/VFS/krdirwatch.h
new file mode 100644
index 0000000..e897eeb
--- /dev/null
+++ b/krusader/VFS/krdirwatch.h
@@ -0,0 +1,79 @@
+/***************************************************************************
+ krdirwatch.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KRDIRWATCH_H
+#define KRDIRWATCH_H
+
+#include <qobject.h>
+#include <qstring.h>
+#include <qptrlist.h>
+#include <qtimer.h>
+#include <qdatetime.h>
+#include <qdir.h>
+
+
+typedef struct krDirEntry_s{
+ QString path;
+ unsigned long count; // number of files
+ QDateTime lastModified;
+} krDirEntry ;
+
+class KRdirWatch : public QObject {
+ Q_OBJECT
+public:
+ KRdirWatch(int msec = 250 , bool dirOnly = false );
+ ~KRdirWatch();
+ void addDir(QString path,bool checkPermissions = true );
+ void removeDir(QString path);
+
+ inline void clearList(){watched.clear();}
+ inline void startScan(){t.start(delay);stopped=false;}
+ inline void stopScan() {t.stop(); stopped=true;}
+
+public slots:
+ void checkDirs(); // here we do the actual checking
+
+signals:
+ void dirty();
+
+protected:
+ int delay; // time in msec between updates
+ QList<krDirEntry> watched;
+ QTimer t;
+ QDir dir;
+ QFileInfo qfi;
+ krDirEntry* it;
+ bool changed; // true if something happend to the watched dirs
+ bool stopped; // true if the watcher is stopped
+};
+
+#endif
diff --git a/krusader/VFS/krpermhandler.cpp b/krusader/VFS/krpermhandler.cpp
new file mode 100644
index 0000000..fd8e52c
--- /dev/null
+++ b/krusader/VFS/krpermhandler.cpp
@@ -0,0 +1,355 @@
+/***************************************************************************
+ krpermhandler.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+ Description
+***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+
+// System includes
+#include <unistd.h>
+#include <math.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <time.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <klargefile.h>
+// Qt includes
+#include <qdatetime.h>
+#include <qdir.h>
+// krusader includes
+#include <kdeversion.h>
+#include "krpermhandler.h"
+#include "../resources.h"
+
+QDict<uid_t> *KRpermHandler::passwdCache = 0L;
+QDict<gid_t> *KRpermHandler::groupCache = 0L;
+QIntDict<char> *KRpermHandler::currentGroups = 0L;
+QIntDict<QString> *KRpermHandler::uidCache = 0L;
+QIntDict<QString> *KRpermHandler::gidCache = 0L;
+
+char KRpermHandler::writeable( QString perm, gid_t gid, uid_t uid, int rwx ) {
+ if( rwx != -1 )
+ return ( rwx & W_OK ) ? ALLOWED_PERM : NO_PERM;
+ // root override
+ if ( getuid() == 0 )
+ return ALLOWED_PERM;
+ // first check other permissions.
+ if ( perm[ 8 ] != '-' ) return ALLOWED_PERM;
+ // now check group permission
+ if ( ( perm[ 5 ] != '-' ) && ( currentGroups->find( gid ) ) )
+ return ALLOWED_PERM;
+ // the last chance - user permissions
+ if ( ( perm[ 2 ] != '-' ) && ( uid == getuid() ) )
+ return ALLOWED_PERM;
+ // sorry !
+ return NO_PERM;
+}
+
+char KRpermHandler::readable( QString perm, gid_t gid, uid_t uid, int rwx ) {
+ if( rwx != -1 )
+ return ( rwx & R_OK ) ? ALLOWED_PERM : NO_PERM;
+ // root override
+ if ( getuid() == 0 )
+ return ALLOWED_PERM;
+ // first check other permissions.
+ if ( perm[ 7 ] != '-' ) return ALLOWED_PERM;
+ // now check group permission
+ if ( ( perm[ 4 ] != '-' ) && ( currentGroups->find( gid ) ) )
+ return ALLOWED_PERM;
+ // the last chance - user permissions
+ if ( ( perm[ 1 ] != '-' ) && ( uid == getuid() ) )
+ return ALLOWED_PERM;
+ // sorry !
+ return NO_PERM;
+}
+
+char KRpermHandler::executable( QString perm, gid_t gid, uid_t uid, int rwx ) {
+ if( rwx != -1 )
+ return ( rwx & X_OK ) ? ALLOWED_PERM : NO_PERM;
+ // first check other permissions.
+ if ( perm[ 9 ] != '-' ) return ALLOWED_PERM;
+ // now check group permission
+ if ( ( perm[ 6 ] != '-' ) && ( currentGroups->find( gid ) ) )
+ return ALLOWED_PERM;
+ // the last chance - user permissions
+ if ( ( perm[ 3 ] != '-' ) && ( uid == getuid() ) )
+ return ALLOWED_PERM;
+ // sorry !
+ return NO_PERM;
+}
+
+bool KRpermHandler::fileWriteable( QString localFile ) {
+ KDE_struct_stat stat_p;
+ if ( KDE_stat( localFile.local8Bit(), &stat_p ) == -1 ) return false;
+ mode_t m = stat_p.st_mode;
+ QString perm = mode2QString( m );
+ return writeable( perm, stat_p.st_gid, stat_p.st_uid );
+}
+
+bool KRpermHandler::fileReadable( QString localFile ) {
+ KDE_struct_stat stat_p;
+ if ( KDE_stat( localFile.local8Bit(), &stat_p ) == -1 ) return false;
+ mode_t m = stat_p.st_mode;
+ QString perm = mode2QString( m );
+ return readable( perm, stat_p.st_gid, stat_p.st_uid );
+}
+
+bool KRpermHandler::fileExecutable( QString localFile ) {
+ KDE_struct_stat stat_p;
+ if ( KDE_stat( localFile.local8Bit(), &stat_p ) == -1 ) return false;
+ mode_t m = stat_p.st_mode;
+ QString perm = mode2QString( m );
+ return executable( perm, stat_p.st_gid, stat_p.st_uid );
+}
+
+QString KRpermHandler::mode2QString( mode_t m ) {
+ char perm[ 11 ];
+ for( int i=0; i != 10; i++ )
+ perm[ i ] = '-';
+ perm[ 10 ] = 0;
+
+ if ( S_ISLNK( m ) ) perm[ 0 ] = 'l'; // check for symLink
+ if ( S_ISDIR( m ) ) perm[ 0 ] = 'd'; // check for directory
+
+ //ReadUser = 0400, WriteUser = 0200, ExeUser = 0100, Suid = 04000
+ if ( m & 0400 ) perm[ 1 ] = 'r';
+ if ( m & 0200 ) perm[ 2 ] = 'w';
+ if ( m & 0100 ) perm[ 3 ] = 'x';
+ if ( m & 04000 ) perm[ 3 ] = 's';
+ //ReadGroup = 0040, WriteGroup = 0020, ExeGroup = 0010, Gid = 02000
+ if ( m & 0040 ) perm[ 4 ] = 'r';
+ if ( m & 0020 ) perm[ 5 ] = 'w';
+ if ( m & 0010 ) perm[ 6 ] = 'x';
+ if ( m & 02000 ) perm[ 6 ] = 's';
+ //ReadOther = 0004, WriteOther = 0002, ExeOther = 0001, Sticky = 01000
+ if ( m & 0004 ) perm[ 7 ] = 'r';
+ if ( m & 0002 ) perm[ 8 ] = 'w';
+ if ( m & 0001 ) perm[ 9 ] = 'x';
+ if ( m & 01000 ) perm[ 9 ] = 't';
+
+ return QString( perm );
+}
+
+void KRpermHandler::init() {
+ // set the umask to 022
+ //umask( 022 );
+
+ // 50 groups should be enough
+ gid_t groupList[ 50 ];
+ int groupNo = getgroups( 50, groupList );
+
+ // init the groups and user caches
+ passwdCache = new QDict<uid_t>( 317 );
+ groupCache = new QDict<gid_t>( 317 );
+ currentGroups = new QIntDict<char>( 317 );
+ uidCache = new QIntDict<QString>( 317 );
+ gidCache = new QIntDict<QString>( 317 );
+
+
+ passwdCache->setAutoDelete( true );
+ groupCache->setAutoDelete( true );
+ currentGroups->setAutoDelete( true );
+ uidCache->setAutoDelete( true );
+ gidCache->setAutoDelete( true );
+
+ // fill the UID cache
+ struct passwd *pass;
+ uid_t* uid_temp;
+ while ( ( pass = getpwent() ) != 0L ) {
+ uid_temp = new uid_t( pass->pw_uid );
+ passwdCache->insert( pass->pw_name, uid_temp );
+ uidCache->insert( pass->pw_uid, new QString( pass->pw_name ) );
+ }
+ delete pass;
+ endpwent();
+
+ // fill the GID cache
+ struct group *gr;
+ gid_t* gid_temp;
+ while ( ( gr = getgrent() ) != 0L ) {
+ gid_temp = new gid_t( gr->gr_gid );
+ groupCache->insert( gr->gr_name, gid_temp );
+ gidCache->insert( gr->gr_gid, new QString( gr->gr_name ) );
+ }
+ delete gr;
+ endgrent();
+
+ // fill the groups for the current user
+ char * t = new char( 1 );
+ for ( int i = 0; i < groupNo; ++i ) {
+ currentGroups->insert( groupList[ i ], t );
+ }
+ // just to be sure add the effective gid...
+ currentGroups->insert( getegid(), t );
+}
+
+char KRpermHandler::ftpWriteable ( QString fileOwner, QString userName, QString perm ) {
+ // first check other permissions.
+ if ( perm[ 8 ] != '-' ) return ALLOWED_PERM;
+ // can't check group permission !
+ // so check the user permissions
+ if ( ( perm[ 2 ] != '-' ) && ( fileOwner == userName ) )
+ return ALLOWED_PERM;
+ if ( ( perm[ 2 ] != '-' ) && ( userName.isEmpty() ) )
+ return UNKNOWN_PERM;
+ if ( perm[ 5 ] != '-' ) return UNKNOWN_PERM;
+ return NO_PERM;
+}
+
+char KRpermHandler::ftpReadable ( QString fileOwner, QString userName, QString perm ) {
+ // first check other permissions.
+ if ( perm[ 7 ] != '-' ) return ALLOWED_PERM;
+ // can't check group permission !
+ // so check the user permissions
+ if ( ( perm[ 1 ] != '-' ) && ( fileOwner == userName ) )
+ return ALLOWED_PERM;
+ if ( ( perm[ 1 ] != '-' ) && ( userName.isEmpty() ) )
+ return UNKNOWN_PERM;
+ if ( perm[ 4 ] != '-' ) return UNKNOWN_PERM;
+ return NO_PERM;
+}
+
+char KRpermHandler::ftpExecutable( QString fileOwner, QString userName, QString perm ) {
+ // first check other permissions.
+ if ( perm[ 9 ] != '-' ) return ALLOWED_PERM;
+ // can't check group permission !
+ // so check the user permissions
+ if ( ( perm[ 3 ] != '-' ) && ( fileOwner == userName ) )
+ return ALLOWED_PERM;
+ if ( ( perm[ 3 ] != '-' ) && ( userName.isEmpty() ) )
+ return UNKNOWN_PERM;
+ if ( perm[ 6 ] != '-' ) return UNKNOWN_PERM;
+ return NO_PERM;
+}
+
+bool KRpermHandler::dirExist( QString path ) {
+ DIR * dir = opendir( path.local8Bit() );
+ if ( !dir ) return false;
+ closedir( dir ); // bug fix Karai Csaba (ckarai)
+ return true;
+}
+
+bool KRpermHandler::fileExist( QString fullPath ) {
+ if ( fullPath.right( 1 ) == "/" ) fullPath = fullPath.left( fullPath.length() - 1 ) ;
+ if ( fullPath.left( 1 ) != "/" ) return fileExist( "/", fullPath );
+ return fileExist( fullPath.left( fullPath.findRev( "/" ) ) ,
+ fullPath.mid( fullPath.findRev( "/" ) + 1 ) );
+}
+
+bool KRpermHandler::fileExist( QString path, QString name ) {
+ if ( QDir( path ).exists( name ) ) return true;
+ DIR* dir = opendir( path.local8Bit() );
+ if ( !dir ) return false;
+ struct dirent* dirEnt;
+ while ( ( dirEnt = readdir( dir ) ) ) {
+ if ( dirEnt->d_name == name ) {
+ closedir( dir );
+ return true;
+ }
+ }
+ closedir( dir );
+ return false;
+}
+
+QString KRpermHandler::parseSize( KIO::filesize_t val ) {
+#if (KDE_VERSION_MAJOR >= 3) && (KDE_VERSION_MINOR >= 5)
+ return KGlobal::locale()->formatNumber(QString::number(val), false, 0);
+#else
+ return KGlobal::locale()->formatNumber(val);
+#endif
+
+#if 0
+ QString temp;
+ temp.sprintf( "%llu", val );
+ if ( temp.length() <= 3 ) return temp;
+ unsigned int i = temp.length() % 3;
+ if ( i == 0 ) i = 3;
+ QString size = temp.left( i ) + ",";
+ while ( i + 3 < temp.length() ) {
+ size = size + temp.mid( i, 3 ) + ",";
+ i += 3;
+ }
+ size = size + temp.right( 3 );
+
+ return size;
+#endif
+}
+
+QString KRpermHandler::date2qstring( QString date ) {
+ QString temp;
+ int year;
+
+ year = date[ 6 ].digitValue() * 10 + date[ 7 ].digitValue();
+ year > 80 ? year += 1900 : year += 2000;
+
+ temp.sprintf( "%d", year );
+ temp = temp + date[ 3 ] + date[ 4 ] + date[ 0 ] + date[ 1 ] + date[ 9 ] + date[ 10 ] + date[ 12 ] + date[ 13 ];
+
+ return temp;
+}
+
+time_t KRpermHandler::QString2time( QString date ) {
+ struct tm t;
+ t.tm_sec = 0;
+ t.tm_min = ( QString( date[ 12 ] ) + QString( date[ 13 ] ) ).toInt();
+ t.tm_hour = ( QString( date[ 9 ] ) + QString( date[ 10 ] ) ).toInt();
+ t.tm_mday = ( QString( date[ 0 ] ) + QString( date[ 1 ] ) ).toInt();
+ t.tm_mon = ( QString( date[ 3 ] ) + QString( date[ 4 ] ) ).toInt() - 1;
+ t.tm_year = ( QString( date[ 6 ] ) + QString( date[ 7 ] ) ).toInt();
+ if ( t.tm_year < 70 ) t.tm_year += 100;
+ t.tm_isdst = -1; // daylight saving time information isn't availble
+
+ return mktime( &t );
+}
+
+gid_t KRpermHandler::group2gid( QString group ) {
+ gid_t * gid = groupCache->find( group );
+ if ( gid ) return * gid;
+ return getgid();
+}
+uid_t KRpermHandler::user2uid ( QString user ) {
+ uid_t * uid = passwdCache->find( user );
+ if ( uid ) return * uid;
+ return getuid();
+}
+
+QString KRpermHandler::gid2group( gid_t groupId ) {
+ QString * group = gidCache->find( groupId );
+ if ( group ) return * group;
+ return QString( "???" );
+}
+
+QString KRpermHandler::uid2user ( uid_t userId ) {
+ QString * user = uidCache->find( userId );
+ if ( user ) return * user;
+ return QString( "???" );
+}
+
diff --git a/krusader/VFS/krpermhandler.h b/krusader/VFS/krpermhandler.h
new file mode 100644
index 0000000..8529ca6
--- /dev/null
+++ b/krusader/VFS/krpermhandler.h
@@ -0,0 +1,89 @@
+/***************************************************************************
+ krpermhandler.h
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KRPERMHANDLER_H
+#define KRPERMHANDLER_H
+
+#include <qstring.h>
+#include <qfileinfo.h>
+#include <sys/types.h>
+#include <qdict.h>
+#include <qintdict.h>
+#include <kio/global.h>
+
+#define NO_PERM 0
+#define UNKNOWN_PERM 1
+#define ALLOWED_PERM 2
+
+class KRpermHandler {
+public:
+ KRpermHandler(){}
+ ~KRpermHandler(){}
+
+ static void init();
+
+ static gid_t group2gid(QString group);
+ static uid_t user2uid (QString user);
+
+ static QString gid2group(gid_t groupId);
+ static QString uid2user (uid_t userId);
+
+ static char writeable (QString perm, gid_t gid, uid_t uid, int rwx=-1);
+ static char readable (QString perm, gid_t gid, uid_t uid, int rwx=-1);
+ static char executable(QString perm, gid_t gid, uid_t uid, int rwx=-1);
+
+ static bool fileWriteable (QString localFile);
+ static bool fileReadable (QString localFile);
+ static bool fileExecutable(QString localFile);
+
+ static char ftpWriteable ( QString fileOwner, QString userName, QString perm );
+ static char ftpReadable ( QString fileOwner, QString userName, QString perm );
+ static char ftpExecutable( QString fileOwner, QString userName, QString perm );
+
+ static bool dirExist (QString path);
+ static bool fileExist(QString fullPath);
+ static bool fileExist(QString Path, QString name);
+
+ static QString mode2QString(mode_t m);
+ static QString parseSize(KIO::filesize_t val);
+ static QString date2qstring(QString date);
+ static time_t QString2time(QString date);
+
+private:
+ // cache for passwd and group entries
+ static QDict<uid_t> *passwdCache;
+ static QDict<gid_t> *groupCache;
+ static QIntDict<char> *currentGroups;
+ static QIntDict<QString> *uidCache;
+ static QIntDict<QString> *gidCache;
+};
+
+#endif
diff --git a/krusader/VFS/krquery.cpp b/krusader/VFS/krquery.cpp
new file mode 100644
index 0000000..a3a0443
--- /dev/null
+++ b/krusader/VFS/krquery.cpp
@@ -0,0 +1,653 @@
+/***************************************************************************
+ krquery.cpp
+ -------------------
+ copyright : (C) 2001 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+
+#include "krquery.h"
+#include "../krusader.h"
+#include "../resources.h"
+#include "vfs.h"
+#include "krarchandler.h"
+#include "krpermhandler.h"
+
+#include <qtextstream.h>
+#include <qtextcodec.h>
+#include <qregexp.h>
+#include <klargefile.h>
+#include <klocale.h>
+#include <kmimetype.h>
+#include <qfile.h>
+#include <kurlcompletion.h>
+#include <kio/job.h>
+#include <kfileitem.h>
+
+#define STATUS_SEND_DELAY 250
+#define MAX_LINE_LEN 500
+
+// set the defaults
+KRQuery::KRQuery(): QObject(), matchesCaseSensitive(true), bNull( true ),
+ contain(QString::null),containCaseSensetive(true),
+ containWholeWord(false),containOnRemote(false),
+ minSize(0),maxSize(0),newerThen(0),olderThen(0),
+ owner(QString::null),group(QString::null),perm(QString::null),
+ type(QString::null),inArchive(false),recurse(true),
+ followLinksP(true), receivedBuffer( 0 ), processEventsConnected(0) {}
+
+// set the defaults
+KRQuery::KRQuery( const QString &name, bool matchCase ) : QObject(),
+ bNull( true ),contain(QString::null),containCaseSensetive(true),
+ containWholeWord(false), containOnRemote(false),
+ minSize(0),maxSize(0),newerThen(0),olderThen(0),
+ owner(QString::null),group(QString::null),perm(QString::null),
+ type(QString::null),inArchive(false),recurse(true),
+ followLinksP(true), receivedBuffer( 0 ), processEventsConnected(0) {
+ setNameFilter( name, matchCase );
+}
+
+KRQuery::KRQuery( const KRQuery & that ) : QObject(), receivedBuffer( 0 ), processEventsConnected(0) {
+ *this = that;
+}
+
+KRQuery::~KRQuery() {
+ if( receivedBuffer )
+ delete []receivedBuffer;
+ receivedBuffer = 0;
+}
+
+KRQuery& KRQuery::operator=(const KRQuery &old) {
+ matches = old.matches;
+ excludes = old.excludes;
+ includedDirs = old.includedDirs;
+ excludedDirs = old.excludedDirs;
+ matchesCaseSensitive = old.matchesCaseSensitive;
+ bNull = old.bNull;
+ contain = old.contain;
+ containCaseSensetive = old.containCaseSensetive;
+ containWholeWord = old.containWholeWord;
+ containOnRemote = old.containOnRemote;
+ minSize = old.minSize;
+ maxSize = old.maxSize;
+ newerThen = old.newerThen;
+ olderThen = old.olderThen;
+ owner = old.owner;
+ group = old.group;
+ perm = old.perm;
+ type = old.type;
+ customType = old.customType;
+ inArchive = old.inArchive;
+ recurse = old.recurse;
+ followLinksP = old.followLinksP;
+ whereToSearch = old.whereToSearch;
+ whereNotToSearch = old.whereNotToSearch;
+ origFilter = old.origFilter;
+
+ return *this;
+}
+
+void KRQuery::connectNotify ( const char * signal ) {
+ QString signalString = QString( signal ).replace( " ", "" );
+ QString processString = QString( SIGNAL( processEvents( bool & ) ) ).replace( " ", "" );
+ if( signalString == processString )
+ processEventsConnected++;
+}
+
+void KRQuery::disconnectNotify ( const char * signal ) {
+ QString signalString = QString( signal ).replace( " ", "" );
+ QString processString = QString( SIGNAL( processEvents( bool & ) ) ).replace( " ", "" );
+ if( signalString == processString )
+ processEventsConnected--;
+}
+
+bool KRQuery::checkPerm( QString filePerm ) const
+{
+ for ( int i = 0; i < 9; ++i )
+ if ( perm[ i ] != '?' && perm[ i ] != filePerm[ i + 1 ] ) return false;
+ return true;
+}
+
+bool KRQuery::checkType( QString mime ) const
+{
+ if ( type == mime ) return true;
+ if ( type == i18n( "Archives" ) ) return KRarcHandler::arcSupported( mime.right( 4 ) );
+ if ( type == i18n( "Directories" ) ) return mime.contains( "directory" );
+ if ( type == i18n( "Image Files" ) ) return mime.contains( "image/" );
+ if ( type == i18n( "Text Files" ) ) return mime.contains( "text/" );
+ if ( type == i18n( "Video Files" ) ) return mime.contains( "video/" );
+ if ( type == i18n( "Audio Files" ) ) return mime.contains( "audio/" );
+ if ( type == i18n( "Custom" ) ) return customType.contains( mime );
+ return false;
+}
+
+bool KRQuery::match( const QString & name ) const {
+ return matchCommon( name, matches, excludes );
+}
+
+bool KRQuery::matchDirName( const QString & name ) const {
+ return matchCommon( name, includedDirs, excludedDirs );
+}
+
+bool KRQuery::matchCommon( const QString &nameIn, const QStringList &matchList, const QStringList &excludeList ) const
+{
+ if( excludeList.count() == 0 && matchList.count() == 0 ) /* true if there's no match condition */
+ return true;
+
+ QString name( nameIn );
+ int ndx = nameIn.findRev( '/' ); // virtual filenames may contain '/'
+ if( ndx != -1 ) // but the end of the filename is OK
+ name = nameIn.mid( ndx + 1 );
+
+ unsigned int len;
+ for ( unsigned int i = 0; i < excludeList.count(); ++i )
+ {
+ QRegExp( *excludeList.at( i ), matchesCaseSensitive, true ).match( name, 0, ( int* ) & len );
+ if ( len == name.length() ) return false;
+ }
+
+ if( matchList.count() == 0 )
+ return true;
+
+ for ( unsigned int i = 0; i < matchList.count(); ++i )
+ {
+ QRegExp( *matchList.at( i ), matchesCaseSensitive, true ).match( name, 0, ( int* ) & len );
+ if ( len == name.length() ) return true;
+ }
+ return false;
+}
+
+bool KRQuery::match( vfile *vf ) const
+{
+ if( vf->vfile_isDir() && !matchDirName( vf->vfile_getName() ) ) return false;
+ // see if the name matches
+ if ( !match( vf->vfile_getName() ) ) return false;
+ // checking the mime
+ if( !type.isEmpty() && !checkType( vf->vfile_getMime( true ) ) ) return false;
+ // check that the size fit
+ KIO::filesize_t size = vf->vfile_getSize();
+ if ( minSize && size < minSize ) return false;
+ if ( maxSize && size > maxSize ) return false;
+ // check the time frame
+ time_t mtime = vf->vfile_getTime_t();
+ if ( olderThen && mtime > olderThen ) return false;
+ if ( newerThen && mtime < newerThen ) return false;
+ // check owner name
+ if ( !owner.isEmpty() && vf->vfile_getOwner() != owner ) return false;
+ // check group name
+ if ( !group.isEmpty() && vf->vfile_getGroup() != group ) return false;
+ //check permission
+ if ( !perm.isEmpty() && !checkPerm( vf->vfile_getPerm() ) ) return false;
+
+ if ( !contain.isEmpty() )
+ {
+ if( (totalBytes = vf->vfile_getSize()) == 0 )
+ totalBytes++; // sanity
+ receivedBytes = 0;
+ if( receivedBuffer ) {
+ delete []receivedBuffer;
+ receivedBuffer = 0;
+ }
+ fileName = vf->vfile_getName();
+ timer.start();
+
+ if( vf->vfile_getUrl().isLocalFile() )
+ {
+ if( !containsContent( vf->vfile_getUrl().path() ) ) return false;
+ }
+ else
+ {
+ if( containOnRemote ) {
+ if( processEventsConnected == 0 ) return false;
+ if( !containsContent( vf->vfile_getUrl() ) ) return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool KRQuery::match( KFileItem *kfi ) const {
+ mode_t mode = kfi->mode() | kfi->permissions();
+ QString perm = KRpermHandler::mode2QString( mode );
+ if ( kfi->isDir() )
+ perm[ 0 ] = 'd';
+
+ vfile temp( kfi->text(), kfi->size(), perm, kfi->time( KIO::UDS_MODIFICATION_TIME ),
+ kfi->isLink(), kfi->user(), kfi->group(), kfi->user(),
+ kfi->mimetype(), kfi->linkDest(), mode );
+
+ return match( &temp );
+}
+
+// takes the string and adds BOLD to it, so that when it is displayed,
+// the grepped text will be bold
+void fixFoundTextForDisplay(QString& haystack, int start, int length) {
+ QString before = haystack.left( start );
+ QString text = haystack.mid( start, length );
+ QString after = haystack.mid( start + length );
+
+ before.replace( '&', "&amp;" );
+ before.replace( '<', "&lt;" );
+ before.replace( '>', "&gt;" );
+
+ text.replace( '&', "&amp;" );
+ text.replace( '<', "&lt;" );
+ text.replace( '>', "&gt;" );
+
+ after.replace( '&', "&amp;" );
+ after.replace( '<', "&lt;" );
+ after.replace( '>', "&gt;" );
+
+ haystack = ("<qt>"+before+"<b>"+text+"</b>"+after+"</qt>" );
+}
+
+bool KRQuery::checkBuffer( const char *buf, int len ) const {
+ if( len == 0 ) { // last block?
+ if( receivedBuffer ) {
+ bool result = checkLines( receivedBuffer, receivedBufferLen );
+ delete []receivedBuffer;
+ receivedBuffer = 0;
+ return result;
+ }
+ return false;
+ }
+
+ int after = len;
+ while( buf[ after-1 ] != '\n' && buf[ after-1 ] != 0 ) {
+ after--;
+ if( after <= 0 || after <= len - MAX_LINE_LEN ) {
+ after = len; // if there's no <ENTER> in MAX_LINE_LEN, we break the line
+ break; // breaking the line causes problems at Unicode characters
+ }
+ }
+
+ if( receivedBuffer ) {
+ int previous = 0;
+ while( previous < after && previous < MAX_LINE_LEN && buf[previous] != '\n' && buf[previous] != 0 )
+ previous++;
+
+ char * str = new char[ receivedBufferLen + previous ];
+ memcpy( str, receivedBuffer, receivedBufferLen );
+ delete []receivedBuffer;
+ receivedBuffer = 0;
+ memcpy( str + receivedBufferLen, buf, previous );
+
+ if( checkLines( str, receivedBufferLen+previous ) ) {
+ delete []str;
+ return true;
+ }
+ delete []str;
+
+ if( after > previous && checkLines( buf+previous, after-previous ) )
+ return true;
+
+ } else if( checkLines( buf, after ) )
+ return true;
+
+ if( after < len ) {
+ receivedBufferLen = len-after;
+ receivedBuffer = new char [ receivedBufferLen ];
+ memcpy( receivedBuffer, buf+after, receivedBufferLen );
+ }
+ return false;
+}
+
+bool KRQuery::checkLines( const char * buf, int len ) const
+{
+ QStringList list;
+
+ int start = 0;
+ int k = 0;
+ while( k < len )
+ {
+ if( buf[ k ] == 0 || buf[ k ] == '\n' )
+ {
+ if( k != start )
+ {
+ QString line = QTextCodec::codecForLocale()->toUnicode( buf + start, k - start );
+ if( !line.isEmpty() )
+ list << line;
+ }
+ start = k + 1;
+ }
+ k++;
+ }
+ if( start != k )
+ {
+ QString line = QTextCodec::codecForLocale()->toUnicode( buf + start, k - start );
+ if( !line.isEmpty() )
+ list << line;
+ }
+
+ for( unsigned int i=0; i != list.count(); i++ ) {
+ QString line = list[ i ];
+
+ int ndx = 0;
+ if ( line.isNull() ) return false;
+ if ( containWholeWord )
+ {
+ while ( ( ndx = line.find( contain, ndx, containCaseSensetive ) ) != -1 )
+ {
+ QChar before = line.at( ndx - 1 );
+ QChar after = line.at( ndx + contain.length() );
+
+ if ( !before.isLetterOrNumber() && !after.isLetterOrNumber() &&
+ after != '_' && before != '_' ) {
+ lastSuccessfulGrep = line;
+ fixFoundTextForDisplay(lastSuccessfulGrep, ndx, contain.length());
+ return true;
+ }
+ ndx++;
+ }
+ }
+ else if ( (ndx = line.find( contain, 0, containCaseSensetive )) != -1 ) {
+ lastSuccessfulGrep = line;
+ fixFoundTextForDisplay(lastSuccessfulGrep, ndx, contain.length());
+ return true;
+ }
+ }
+ return false;
+}
+
+bool KRQuery::containsContent( QString file ) const
+{
+ QFile qf( file );
+ if( !qf.open( IO_ReadOnly ) )
+ return false;
+
+ char buffer[ 1440 ]; // 2k buffer
+
+ while ( !qf.atEnd() )
+ {
+ int bytes = qf.readBlock( buffer, sizeof( buffer ) );
+ if( bytes <= 0 )
+ break;
+
+ receivedBytes += bytes;
+
+ if( checkBuffer( buffer, bytes ) )
+ return true;
+
+ if( checkTimer() ) {
+ bool stopped = false;
+ emit ((KRQuery *)this)->processEvents( stopped );
+ if( stopped )
+ return false;
+ }
+ }
+ if( checkBuffer( buffer, 0 ) )
+ return true;
+
+ lastSuccessfulGrep = QString::null; // nothing was found
+ return false;
+}
+
+bool KRQuery::containsContent( KURL url ) const
+{
+ KIO::TransferJob *contentReader = KIO::get( url, false, false );
+ connect(contentReader, SIGNAL(data(KIO::Job *, const QByteArray &)),
+ this, SLOT(containsContentData(KIO::Job *, const QByteArray &)));
+ connect(contentReader, SIGNAL( result( KIO::Job* ) ),
+ this, SLOT(containsContentFinished( KIO::Job* ) ) );
+
+ busy = true;
+ containsContentResult = false;
+ bool stopped = false;
+
+ while( busy && !stopped ) {
+ checkTimer();
+ emit ((KRQuery *)this)->processEvents( stopped );
+ }
+
+ if( busy ) {
+ contentReader->kill();
+ busy = false;
+ }
+
+ return containsContentResult;
+}
+
+void KRQuery::containsContentData(KIO::Job *job, const QByteArray &array) {
+ receivedBytes += array.size();
+ if( checkBuffer( array.data(), array.size() ) ) {
+ containsContentResult = true;
+ containsContentFinished( job );
+ job->kill();
+ return;
+ }
+ checkTimer();
+}
+
+void KRQuery::containsContentFinished( KIO::Job * ) {
+ busy = false;
+}
+
+bool KRQuery::checkTimer() const {
+ if( timer.elapsed() >= STATUS_SEND_DELAY ) {
+ int pcnt = (int)(100.*(double)receivedBytes/(double)totalBytes + .5);
+ QString message = i18n( "Searching content of '%1' (%2%)" )
+ .arg( fileName ).arg( pcnt );
+ timer.start();
+ emit ((KRQuery *)this)->status( message );
+ return true;
+ }
+ return false;
+}
+
+QStringList KRQuery::split( QString str )
+{
+ QStringList list;
+ unsigned splitNdx = 0;
+ unsigned startNdx = 0;
+ bool quotation = false;
+
+ while( splitNdx < str.length() )
+ {
+ if( str[ splitNdx ] == '"' )
+ quotation = !quotation;
+
+ if( !quotation && str[ splitNdx ] == ' ')
+ {
+ QString section = str.mid( startNdx, splitNdx - startNdx );
+ startNdx = splitNdx+1;
+ if( section.startsWith( "\"" ) && section.endsWith( "\"" ) && section.length() >=2 )
+ section = section.mid( 1, section.length()-2 );
+ if( !section.isEmpty() )
+ list.append( section );
+ }
+ splitNdx++;
+ }
+
+ if( startNdx < splitNdx )
+ {
+ QString section = str.mid( startNdx, splitNdx - startNdx );
+ if( section.startsWith( "\"" ) && section.endsWith( "\"" ) && section.length() >=2 )
+ section = section.mid( 1, section.length()-2 );
+ if( !section.isEmpty() )
+ list.append( section );
+ }
+
+ return list;
+}
+
+void KRQuery::setNameFilter( const QString &text, bool cs )
+{
+ bNull = false;
+ matchesCaseSensitive = cs;
+ origFilter = text;
+
+ QString matchText = text;
+ QString excludeText;
+
+ unsigned excludeNdx = 0;
+ bool quotationMark = 0;
+ while( excludeNdx < matchText.length() )
+ {
+ if( matchText[ excludeNdx ] == '"' )
+ quotationMark = !quotationMark;
+ if( !quotationMark )
+ {
+ if( matchText[ excludeNdx ] == '|' )
+ break;
+ }
+ excludeNdx++;
+ }
+
+ if( excludeNdx < matchText.length() )
+ {
+ excludeText = matchText.mid( excludeNdx + 1 ).stripWhiteSpace();
+ matchText.truncate( excludeNdx );
+ matchText = matchText.stripWhiteSpace();
+ if( matchText.isEmpty() )
+ matchText = "*";
+ }
+
+ unsigned i;
+
+ matches = split( matchText );
+ includedDirs.clear();
+
+ for( i=0; i < matches.count(); ) {
+ if( matches[ i ].endsWith( "/" ) ) {
+ includedDirs.push_back( matches[ i ].left( matches[ i ].length() - 1 ) );
+ matches.remove( matches.at( i ) );
+ continue;
+ }
+
+ if( !matches[ i ].contains( "*" ) && !matches[ i ].contains( "?" ) )
+ matches[ i ] = "*" + matches[ i ] + "*";
+
+ i++;
+ }
+
+ excludes = split( excludeText );
+ excludedDirs.clear();
+
+ for( i=0; i < excludes.count(); ) {
+ if( excludes[ i ].endsWith( "/" ) ) {
+ excludedDirs.push_back( excludes[ i ].left( excludes[ i ].length() - 1 ) );
+ excludes.remove( excludes.at( i ) );
+ continue;
+ }
+
+ if( !excludes[ i ].contains( "*" ) && !excludes[ i ].contains( "?" ) )
+ excludes[ i ] = "*" + excludes[ i ] + "*";
+
+ i++;
+ }
+}
+
+void KRQuery::setContent( const QString &content, bool cs, bool wholeWord, bool remoteSearch )
+{
+ bNull = false;
+ contain = content;
+ containCaseSensetive = cs;
+ containWholeWord = wholeWord;
+ containOnRemote = remoteSearch;
+}
+
+void KRQuery::setMinimumFileSize( KIO::filesize_t minimumSize )
+{
+ bNull = false;
+ minSize = minimumSize;
+}
+
+void KRQuery::setMaximumFileSize( KIO::filesize_t maximumSize )
+{
+ bNull = false;
+ maxSize = maximumSize;
+}
+
+void KRQuery::setNewerThan( time_t time )
+{
+ bNull = false;
+ newerThen = time;
+}
+
+void KRQuery::setOlderThan( time_t time )
+{
+ bNull = false;
+ olderThen = time;
+}
+
+void KRQuery::setOwner( const QString &ownerIn )
+{
+ bNull = false;
+ owner = ownerIn;
+}
+
+void KRQuery::setGroup( const QString &groupIn )
+{
+ bNull = false;
+ group = groupIn;
+}
+
+void KRQuery::setPermissions( const QString &permIn )
+{
+ bNull = false;
+ perm = permIn;
+}
+
+void KRQuery::setMimeType( const QString &typeIn, QStringList customList )
+{
+ bNull = false;
+ type = typeIn;
+ customType = customList;
+}
+
+bool KRQuery::isExcluded( const KURL &url )
+{
+ for ( unsigned int i = 0; i < whereNotToSearch.count(); ++i )
+ if( whereNotToSearch [ i ].isParentOf( url ) || url.equals( whereNotToSearch [ i ], true ) )
+ return true;
+
+ if( !matchDirName( url.fileName() ) )
+ return true;
+
+ return false;
+}
+
+void KRQuery::setSearchInDirs( const KURL::List &urls ) {
+ whereToSearch.clear();
+ for( unsigned int i = 0; i < urls.count(); ++i ) {
+ QString url = urls[ i ].url();
+ KURL completed = vfs::fromPathOrURL( KURLCompletion::replacedPath( url, true, true ) );
+ whereToSearch.append( completed );
+ }
+}
+
+void KRQuery::setDontSearchInDirs( const KURL::List &urls ) {
+ whereNotToSearch.clear();
+ for( unsigned int i = 0; i < urls.count(); ++i ) {
+ QString url = urls[ i ].url();
+ KURL completed = vfs::fromPathOrURL( KURLCompletion::replacedPath( url, true, true ) );
+ whereNotToSearch.append( completed );
+ }
+}
+
+#include "krquery.moc"
diff --git a/krusader/VFS/krquery.h b/krusader/VFS/krquery.h
new file mode 100644
index 0000000..5849d79
--- /dev/null
+++ b/krusader/VFS/krquery.h
@@ -0,0 +1,208 @@
+/***************************************************************************
+ krquery.h
+ -------------------
+ copyright : (C) 2001 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef KRQUERY_H
+#define KRQUERY_H
+
+#include <qstringlist.h>
+#include <qdatetime.h>
+#include <time.h>
+#include <kurl.h>
+#include <kio/jobclasses.h>
+#include "vfile.h"
+
+class KFileItem;
+
+class KRQuery : public QObject {
+ Q_OBJECT
+
+public:
+ // null query
+ KRQuery();
+ // query only with name filter
+ KRQuery( const QString &name, bool matchCase = true );
+ // copy constructor
+ KRQuery( const KRQuery & );
+ // let operator
+ KRQuery& operator=(const KRQuery &);
+ // destructor
+ virtual ~KRQuery();
+
+ // matching a file with the query
+ bool match( vfile *file ) const;// checks if the given vfile object matches the conditions
+ // matching a KIO file with the query
+ bool match( KFileItem *file ) const;// checks if the given vfile object matches the conditions
+ // matching a name with the query
+ bool match( const QString &name ) const;// matching the filename only
+ // matching the name of the directory
+ bool matchDirName( const QString &name ) const;
+
+ // sets the text for name filtering
+ void setNameFilter( const QString &text, bool cs=true );
+ // returns the current filter mask
+ const QString& nameFilter() const { return origFilter; }
+ // returns whether the filter is case sensitive
+ bool isCaseSensitive() { return matchesCaseSensitive; }
+
+ // returns if the filter is null (was cancelled)
+ bool isNull() {return bNull;};
+
+ // sets the content part of the query
+ void setContent( const QString &content, bool cs=true, bool wholeWord=false, bool remoteSearch=false );
+
+ // sets the minimum file size limit
+ void setMinimumFileSize( KIO::filesize_t );
+ // sets the maximum file size limit
+ void setMaximumFileSize( KIO::filesize_t );
+
+ // sets the time the file newer than
+ void setNewerThan( time_t time );
+ // sets the time the file older than
+ void setOlderThan( time_t time );
+
+ // sets the owner
+ void setOwner( const QString &ownerIn );
+ // sets the group
+ void setGroup( const QString &groupIn );
+ // sets the permissions
+ void setPermissions( const QString &permIn );
+
+ // sets the mimetype for the query
+ // type, must be one of the following:
+ // 1. a valid mime type name
+ // 2. one of: i18n("Archives"), i18n("Directories"), i18n("Image Files")
+ // i18n("Text Files"), i18n("Video Files"), i18n("Audio Files")
+ // 3. i18n("Custom") in which case you must supply a list of valid mime-types
+ // in the member QStringList customType
+ void setMimeType( const QString &typeIn, QStringList customList = QStringList() );
+ // true if setMimeType was called
+ bool hasMimeType() { return type.isEmpty(); }
+
+ // sets the search in archive flag
+ void setSearchInArchives( bool flag ) { inArchive = flag; }
+ // gets the search in archive flag
+ bool searchInArchives() { return inArchive; }
+ // sets the recursive flag
+ void setRecursive( bool flag ) { recurse = flag; }
+ // gets the recursive flag
+ bool isRecursive() { return recurse; }
+ // sets whether to follow symbolic links
+ void setFollowLinks( bool flag ) { followLinksP = flag; }
+ // gets whether to follow symbolic links
+ bool followLinks() { return followLinksP; }
+
+ // sets the folders where the searcher will search
+ void setSearchInDirs( const KURL::List &urls );
+ // gets the folders where the searcher searches
+ const KURL::List & searchInDirs() { return whereToSearch; }
+ // sets the folders where search is not permitted
+ void setDontSearchInDirs( const KURL::List &urls );
+ // gets the folders where search is not permitted
+ const KURL::List & dontSearchInDirs() { return whereNotToSearch; }
+ // checks if a URL is excluded
+ bool isExcluded( const KURL &url );
+ // gives whether we search for content
+ bool isContentSearched() const { return !contain.isEmpty(); }
+
+ const QString& foundText() const { return lastSuccessfulGrep; }
+
+protected:
+ // important to know whether the event processor is connected
+ virtual void connectNotify ( const char * signal );
+ // important to know whether the event processor is connected
+ virtual void disconnectNotify ( const char * signal );
+
+protected:
+ QStringList matches; // what to search
+ QStringList excludes; // what to exclude
+ QStringList includedDirs; // what dirs to include
+ QStringList excludedDirs; // what dirs to exclude
+ bool matchesCaseSensitive;
+
+ bool bNull; // flag if the query is null
+
+ QString contain; // file must contain this string
+ bool containCaseSensetive;
+ bool containWholeWord;
+ bool containOnRemote;
+
+ KIO::filesize_t minSize;
+ KIO::filesize_t maxSize;
+
+ time_t newerThen;
+ time_t olderThen;
+
+ QString owner;
+ QString group;
+ QString perm;
+
+ QString type;
+ QStringList customType;
+
+ bool inArchive; // if true- search in archive.
+ bool recurse; // if true recurse ob sub-dirs...
+ bool followLinksP;
+
+ KURL::List whereToSearch; // directorys to search
+ KURL::List whereNotToSearch; // directorys NOT to search
+
+signals:
+ void status( const QString &name );
+ void processEvents( bool & stopped );
+
+private:
+ bool matchCommon( const QString &, const QStringList &, const QStringList & ) const;
+ bool checkPerm(QString perm) const;
+ bool checkType(QString mime) const;
+ bool containsContent( QString file ) const;
+ bool containsContent( KURL url ) const;
+ bool checkBuffer( const char *buffer, int len ) const;
+ bool checkLines( const char *buffer, int len ) const;
+ bool checkTimer() const;
+ QStringList split( QString );
+
+private slots:
+ void containsContentData(KIO::Job *, const QByteArray &);
+ void containsContentFinished(KIO::Job*);
+
+private:
+ QString origFilter;
+ mutable bool busy;
+ mutable bool containsContentResult;
+ mutable char * receivedBuffer;
+ mutable int receivedBufferLen;
+ mutable QString lastSuccessfulGrep;
+ mutable QString fileName;
+ mutable KIO::filesize_t receivedBytes;
+ mutable KIO::filesize_t totalBytes;
+ mutable int processEventsConnected;
+ mutable QTime timer;
+};
+
+#endif
diff --git a/krusader/VFS/krvfshandler.cpp b/krusader/VFS/krvfshandler.cpp
new file mode 100644
index 0000000..6a116fa
--- /dev/null
+++ b/krusader/VFS/krvfshandler.cpp
@@ -0,0 +1,71 @@
+/***************************************************************************
+ krvfshandler.cpp - description
+ -------------------
+ begin : Fri Dec 5 2003
+ copyright : (C) 2003 by Shie Erlich & Rafi Yanai
+ email :
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "krvfshandler.h"
+#include "normal_vfs.h"
+#include "temp_vfs.h"
+#include "ftp_vfs.h"
+#include "virt_vfs.h"
+
+#include <qdir.h>
+
+#include <kdebug.h>
+
+
+KrVfsHandler::KrVfsHandler(){
+}
+KrVfsHandler::~KrVfsHandler(){
+}
+
+vfs::VFS_TYPE KrVfsHandler::getVfsType(const KURL& url){
+ QString protocol = url.protocol();
+
+ if( ( protocol == "krarc" || protocol == "tar" || protocol == "zip" ) &&
+ QDir(url.path(-1)).exists() )
+ return vfs::NORMAL;
+
+ if( url.isLocalFile() ){
+ return vfs::NORMAL;
+ }
+ else{
+ if(url.protocol() == "virt") return vfs::VIRT;
+ else return vfs::FTP;
+ }
+ return vfs::ERROR;
+}
+
+vfs* KrVfsHandler::getVfs(const KURL& url,QObject* parent,vfs* oldVfs){
+ vfs::VFS_TYPE newType,oldType = vfs::ERROR;
+
+ if(oldVfs) oldType = oldVfs->vfs_getType();
+ newType = getVfsType(url);
+
+
+ vfs* newVfs = oldVfs;
+
+ if( oldType != newType ){
+ switch( newType ){
+ case (vfs::NORMAL) : newVfs = new normal_vfs(parent); break;
+ case (vfs::FTP ) : newVfs = new ftp_vfs(parent) ; break;
+ case (vfs::TEMP ) : newVfs = 0/*new temp_vfs(parent)*/ ; break;
+ case (vfs::VIRT ) : newVfs = new virt_vfs(parent) ; break;
+ case (vfs::ERROR ) : newVfs = 0 ; break;
+ }
+ }
+
+ return newVfs;
+}
diff --git a/krusader/VFS/krvfshandler.h b/krusader/VFS/krvfshandler.h
new file mode 100644
index 0000000..698a504
--- /dev/null
+++ b/krusader/VFS/krvfshandler.h
@@ -0,0 +1,40 @@
+/***************************************************************************
+ krvfshandler.h - description
+ -------------------
+ begin : Fri Dec 5 2003
+ copyright : (C) 2003 by Shie Erlich & Rafi Yanai
+ email :
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KRVFSHANDLER_H
+#define KRVFSHANDLER_H
+
+#include <qobject.h>
+
+#include <kurl.h>
+
+#include "vfs.h"
+
+/**
+ *@author Shie Erlich & Rafi Yanai
+ */
+
+class KrVfsHandler : public QObject {
+public:
+ KrVfsHandler();
+ ~KrVfsHandler();
+
+ static vfs::VFS_TYPE getVfsType(const KURL& url);
+ static vfs* getVfs(const KURL& url,QObject* parent=0,vfs* oldVfs=0);
+};
+
+#endif
diff --git a/krusader/VFS/normal_vfs.cpp b/krusader/VFS/normal_vfs.cpp
new file mode 100644
index 0000000..adbfb34
--- /dev/null
+++ b/krusader/VFS/normal_vfs.cpp
@@ -0,0 +1,437 @@
+/***************************************************************************
+ normal_vfs.cpp
+ -------------------
+ copyright : (C) 2000 by Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#include <strings.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <dirent.h>
+// QT includes
+#include <qdir.h>
+#include <qtimer.h>
+// KDE includes
+#include <kmessagebox.h>
+#include <kmimetype.h>
+#include <kio/jobclasses.h>
+#include <klocale.h>
+#include <kglobalsettings.h>
+#include <kdebug.h>
+#include <klargefile.h>
+#include <kfileitem.h>
+// Krusader includes
+#include "normal_vfs.h"
+#include "../Dialogs/krdialogs.h"
+#include "../MountMan/kmountman.h"
+#include "krpermhandler.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include "../resources.h"
+#include "../krslots.h"
+
+// header files for ACL
+#if KDE_IS_VERSION(3,5,0)
+#ifdef HAVE_POSIX_ACL
+#include <sys/acl.h>
+#ifdef HAVE_NON_POSIX_ACL_EXTENSIONS
+#include <acl/libacl.h>
+#endif
+#endif
+#endif
+
+normal_vfs::normal_vfs(QObject* panel):vfs(panel), watcher(0) {
+ vfs_type=NORMAL;
+}
+
+bool normal_vfs::populateVfsList(const KURL& origin, bool showHidden){
+ QString path = origin.path(-1);
+
+ // set the writable attribute to true, if that's not the case - the KIO job
+ // will give the warnings and errors
+ isWritable = true;
+
+ if( watcher ) delete watcher; //stop watching the old dir
+ watcher = 0;
+
+ // set the origin...
+ vfs_origin = origin;
+ vfs_origin.adjustPath(-1);
+ vfs_origin.setProtocol("file"); // do not remove !
+ vfs_origin.cleanPath(-1);
+
+ // check that the new origin exists
+ if ( !QDir(path).exists() )
+ {
+ if( !quietMode ) KMessageBox::error(krApp, i18n("Directory %1 does not exist!").arg( path ), i18n("Error"));
+ return false;
+ }
+
+ krConfig->setGroup("Advanced");
+ if (krConfig->readBoolEntry("AutoMount",_AutoMount)) krMtMan.autoMount(path);
+
+ DIR* dir = opendir(path.local8Bit());
+ if(!dir)
+ {
+ if( !quietMode ) KMessageBox::error(krApp, i18n("Can't open the %1 directory!").arg( path ), i18n("Error"));
+ return false;
+ }
+
+ // change directory to the new directory
+ QString save = getcwd( 0, 0 );
+ if (chdir(path.local8Bit()) != 0) {
+ if( !quietMode ) KMessageBox::error(krApp, i18n("Access denied to")+path, i18n("Error"));
+ closedir(dir);
+ return false;
+ }
+
+ struct dirent* dirEnt;
+ QString name;
+
+ while( (dirEnt=readdir(dir)) != NULL ){
+ name = QString::fromLocal8Bit(dirEnt->d_name);
+
+ // show hidden files ?
+ if ( !showHidden && name.left(1) == "." ) continue ;
+ // we dont need the ".",".." enteries
+ if (name=="." || name == "..") continue;
+
+ vfile* temp = vfileFromName(name);
+ foundVfile(temp);
+ }
+ // clean up
+ closedir(dir);
+ chdir( save.local8Bit() );
+
+ if( panelConnected )
+ {
+ watcher = new KDirWatch();
+ // connect the watcher
+ connect(watcher,SIGNAL(dirty(const QString&)),this,SLOT(vfs_slotDirty(const QString&)));
+ connect(watcher,SIGNAL(created(const QString&)),this, SLOT(vfs_slotCreated(const QString&)));
+ connect(watcher,SIGNAL(deleted(const QString&)),this, SLOT(vfs_slotDeleted(const QString&)));
+ watcher->addDir(vfs_getOrigin().path(-1),true); //start watching the new dir
+ watcher->startScan(true);
+ }
+
+ return true;
+}
+
+// copy a file to the vfs (physical)
+void normal_vfs::vfs_addFiles(KURL::List *fileUrls,KIO::CopyJob::CopyMode mode,QObject* toNotify,QString dir, PreserveMode pmode ){
+ //if( watcher ) watcher->stopScan(); // we will refresh manually this time...
+ if( watcher ) {
+ delete watcher; // stopScan is buggy, leaves reference on the directory, that's why we delete the watcher
+ watcher = 0;
+ }
+
+ KURL dest;
+ dest.setPath(vfs_workingDir()+"/"+dir);
+
+ KIO::Job* job = PreservingCopyJob::createCopyJob( pmode, *fileUrls,dest,mode,false,true );
+ connect(job,SIGNAL(result(KIO::Job*)),this,SLOT(vfs_refresh()) );
+ if(mode == KIO::CopyJob::Move) // notify the other panel
+ connect(job,SIGNAL(result(KIO::Job*)),toNotify,SLOT(vfs_refresh(KIO::Job*)) );
+ else
+ job->setAutoErrorHandlingEnabled( true );
+}
+
+// remove a file from the vfs (physical)
+void normal_vfs::vfs_delFiles(QStringList *fileNames){
+ KURL::List filesUrls;
+ KURL url;
+ QDir local( vfs_workingDir() );
+ vfile* vf;
+
+// if( watcher ) watcher->stopScan(); // we will refresh manually this time...
+ if( watcher ) {
+ delete watcher; // stopScan is buggy, leaves reference on the directory, that's why we delete the watcher
+ watcher = 0;
+ }
+
+ // names -> urls
+ for(uint i=0 ; i<fileNames->count(); ++i){
+ QString filename = (*fileNames)[i];
+ vf = vfs_search(filename);
+ url.setPath( vfs_workingDir()+"/"+filename);
+ filesUrls.append(url);
+ }
+ KIO::Job *job;
+
+ // delete of move to trash ?
+ krConfig->setGroup("General");
+ if( krConfig->readBoolEntry("Move To Trash",_MoveToTrash) ){
+#if KDE_IS_VERSION(3,4,0)
+ job = KIO::trash(filesUrls, true );
+#else
+ job = new KIO::CopyJob(filesUrls,KGlobalSettings::trashPath(),KIO::CopyJob::Move,false,true );
+#endif
+ connect(job,SIGNAL(result(KIO::Job*)),SLOTS,SLOT(changeTrashIcon()));
+ }
+ else
+ job = new KIO::DeleteJob(filesUrls, false, true);
+
+ connect(job,SIGNAL(result(KIO::Job*)),this,SLOT(vfs_refresh(KIO::Job*)));
+}
+
+// return a path to the file
+KURL normal_vfs::vfs_getFile(const QString& name){
+ QString url;
+ if ( vfs_workingDir() == "/" ) url = "/"+name;
+ else url = vfs_workingDir()+"/"+name;
+
+ return vfs::fromPathOrURL(url);
+}
+
+KURL::List* normal_vfs::vfs_getFiles(QStringList* names){
+ KURL::List* urls = new KURL::List();
+ for(QStringList::Iterator name = names->begin(); name != names->end(); ++name){
+ urls->append( vfs_getFile(*name) );
+ }
+ return urls;
+}
+
+void normal_vfs::vfs_mkdir(const QString& name){
+ if (!QDir(vfs_workingDir()).mkdir(name))
+ if (!quietMode) KMessageBox::sorry(krApp,i18n("Can't create a directory. Check your permissions."));
+ vfs::vfs_refresh();
+}
+
+void normal_vfs::vfs_rename(const QString& fileName,const QString& newName){
+ KURL::List fileUrls;
+ KURL url , dest;
+
+ //if( watcher ) watcher->stopScan(); // we will refresh manually this time...
+ if( watcher ) {
+ delete watcher; // stopScan is buggy, leaves reference on the directory, that's why we delete the watcher
+ watcher = 0;
+ }
+
+ url.setPath( vfs_workingDir()+"/"+fileName );
+ fileUrls.append(url);
+ dest.setPath(vfs_workingDir()+"/"+newName);
+
+ KIO::Job *job = new KIO::CopyJob(fileUrls,dest,KIO::CopyJob::Move,true,false );
+ connect(job,SIGNAL(result(KIO::Job*)),this,SLOT(vfs_refresh(KIO::Job*)));
+}
+
+vfile* normal_vfs::vfileFromName(const QString& name){
+ QString path = vfs_workingDir()+"/"+name;
+ QCString fileName = path.local8Bit();
+
+ KDE_struct_stat stat_p;
+ KDE_lstat(fileName.data(),&stat_p);
+ KIO::filesize_t size = stat_p.st_size;
+ QString perm = KRpermHandler::mode2QString(stat_p.st_mode);
+ bool symLink= S_ISLNK(stat_p.st_mode);
+ if( S_ISDIR(stat_p.st_mode) ) perm[0] = 'd';
+
+ KURL mimeUrl = fromPathOrURL(path);
+ QString mime=QString::null;
+
+ char symDest[256];
+ bzero(symDest,256);
+ if( S_ISLNK(stat_p.st_mode) ){ // who the link is pointing to ?
+ int endOfName=0;
+ endOfName=readlink(fileName.data(),symDest,256);
+ if ( endOfName != -1 ){
+ if ( QDir(QString::fromLocal8Bit( symDest ) ).exists() ) perm[0] = 'd';
+ if ( !QDir(vfs_workingDir()).exists( QString::fromLocal8Bit ( symDest ) ) ) mime = "Broken Link !";
+ }
+ else krOut << "Failed to read link: "<< path<<endl;
+ }
+
+ int rwx = 0;
+ if( ::access( fileName.data(), R_OK ) == 0 )
+ rwx |= R_OK;
+ if( ::access( fileName.data(), W_OK ) == 0 )
+ rwx |= W_OK;
+ if( ::access( fileName.data(), X_OK ) == 0 )
+ rwx |= X_OK;
+
+ // create a new virtual file object
+ vfile* temp=new vfile(name,size,perm,stat_p.st_mtime,symLink,stat_p.st_uid,
+ stat_p.st_gid,mime,QString::fromLocal8Bit( symDest ),stat_p.st_mode, rwx);
+ temp->vfile_setUrl( mimeUrl );
+ return temp;
+}
+
+void normal_vfs::getACL( vfile *file, QString &acl, QString &defAcl )
+{
+ acl = defAcl = QString::null;
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+ QCString fileName = file->vfile_getUrl().path( -1 ).local8Bit();
+#if HAVE_NON_POSIX_ACL_EXTENSIONS
+ if ( acl_extended_file( fileName.data() ) )
+ {
+#endif
+ acl = getACL( fileName.data(), ACL_TYPE_ACCESS );
+ if( file->vfile_isDir() )
+ defAcl = getACL( fileName.data(), ACL_TYPE_DEFAULT );
+#if HAVE_NON_POSIX_ACL_EXTENSIONS
+ }
+#endif
+#endif
+}
+
+QString normal_vfs::getACL( const QString & path, int type )
+{
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+ acl_t acl = 0;
+ // do we have an acl for the file, and/or a default acl for the dir, if it is one?
+ if ( ( acl = acl_get_file( path.data(), type ) ) != 0 )
+ {
+ bool aclExtended = false;
+
+#if HAVE_NON_POSIX_ACL_EXTENSIONS
+ aclExtended = acl_equiv_mode( acl, 0 );
+#else
+ acl_entry_t entry;
+ int ret = acl_get_entry( acl, ACL_FIRST_ENTRY, &entry );
+ while ( ret == 1 ) {
+ acl_tag_t currentTag;
+ acl_get_tag_type( entry, &currentTag );
+ if ( currentTag != ACL_USER_OBJ &&
+ currentTag != ACL_GROUP_OBJ &&
+ currentTag != ACL_OTHER )
+ {
+ aclExtended = true;
+ break;
+ }
+ ret = acl_get_entry( acl, ACL_NEXT_ENTRY, &entry );
+ }
+#endif
+
+ if ( !aclExtended )
+ {
+ acl_free( acl );
+ acl = 0;
+ }
+ }
+
+ if( acl == 0 )
+ return QString::null;
+
+ char *aclString = acl_to_text( acl, 0 );
+ QString ret = QString::fromLatin1( aclString );
+ acl_free( (void*)aclString );
+ acl_free( acl );
+
+ return ret;
+#else
+ return QString::null;
+#endif
+}
+
+void normal_vfs::vfs_slotRefresh()
+{
+ krConfig->setGroup("Advanced");
+ int maxRefreshFrequency = krConfig->readNumEntry("Max Refresh Frequency", 1000);
+ vfs_refresh();
+ disconnect( &refreshTimer, SIGNAL( timeout() ), this, SLOT( vfs_slotRefresh() ) );
+ refreshTimer.start( maxRefreshFrequency, true );
+}
+
+bool normal_vfs::burstRefresh(const QString& path ){
+ if( path == vfs_getOrigin().path(-1) ) {
+ if( !refreshTimer.isActive() ) {
+ // the directory itself is dirty - full refresh is needed
+ QTimer::singleShot(0, this, SLOT( vfs_slotRefresh() ) ); // safety: dirty signal comes from KDirWatch!
+ return true;
+ }
+ disconnect( &refreshTimer, SIGNAL( timeout() ), this, SLOT( vfs_slotRefresh() ) );
+ connect( &refreshTimer, SIGNAL( timeout() ), this, SLOT( vfs_slotRefresh() ) );
+ postponedRefreshURL = fromPathOrURL(path);
+ return true;
+ }
+ return false;
+}
+
+void normal_vfs::vfs_slotDirty(const QString& path){
+ if( disableRefresh ){
+ postponedRefreshURL = fromPathOrURL(path);
+ return;
+ }
+
+ if( burstRefresh( path ) )
+ return;
+
+ KURL url = fromPathOrURL(path);
+ QString name = url.fileName();
+
+ // do we have it already ?
+ if( !vfs_search(name ) ) return vfs_slotCreated(path);
+
+ // we have an updated file..
+ removeFromList(name);
+ vfile* vf = vfileFromName(name);
+ addToList(vf);
+ emit updatedVfile(vf);
+}
+
+void normal_vfs::vfs_slotCreated(const QString& path){
+ if( disableRefresh ){
+ postponedRefreshURL = fromPathOrURL(path);
+ return;
+ }
+
+ if( burstRefresh( path ) )
+ return;
+
+
+ KURL url = fromPathOrURL(path);
+ QString name = url.fileName();
+ // if it's in the CVS - it's an update not new file
+ if( vfs_search(name) )
+ return vfs_slotDirty(path);
+
+ vfile* vf = vfileFromName(name);
+ addToList(vf);
+ emit addedVfile(vf);
+}
+
+void normal_vfs::vfs_slotDeleted(const QString& path){
+ if( disableRefresh ){
+ postponedRefreshURL = fromPathOrURL(path);
+ return;
+ }
+
+ if( burstRefresh( path ) )
+ return;
+
+
+ KURL url = fromPathOrURL(path);
+ QString name = url.fileName();
+
+ // if it's not in the CVS - do nothing
+ if( vfs_search(name) ){
+ emit deletedVfile(name);
+ removeFromList(name);
+ }
+}
+
+#include "normal_vfs.moc"
diff --git a/krusader/VFS/normal_vfs.h b/krusader/VFS/normal_vfs.h
new file mode 100644
index 0000000..9c7d067
--- /dev/null
+++ b/krusader/VFS/normal_vfs.h
@@ -0,0 +1,92 @@
+/***************************************************************************
+ normal_vfs.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef NORMAL_VFS
+#define NORMAL_VFS
+
+// QT includes
+#include <qstring.h>
+// KDE includes
+#include <kfileitem.h>
+#include <kdirwatch.h>
+#include <kurl.h>
+// Krusader includes
+#include "vfs.h"
+
+/**
+ * The normal_vfs class is Kruasder implemention for local directories.
+ * As this is the most common case, we try to make it as fast and efficent as possible.
+ */
+class normal_vfs : public vfs{
+ Q_OBJECT
+public:
+ // the constructor simply uses the inherited constructor
+ normal_vfs(QObject* panel);
+ ~normal_vfs(){if( watcher ) delete watcher;}
+
+ /// Copy a file to the vfs (physical).
+ virtual void vfs_addFiles(KURL::List *fileUrls,KIO::CopyJob::CopyMode mode,QObject* toNotify,QString dir = "", PreserveMode pmode = PM_DEFAULT );
+ /// Remove a file from the vfs (physical)
+ virtual void vfs_delFiles(QStringList *fileNames);
+ /// Return a list of URLs for multiple files
+ virtual KURL::List* vfs_getFiles(QStringList* names);
+ /// Return a URL to a single file
+ virtual KURL vfs_getFile(const QString& name);
+ /// Create a new directory
+ virtual void vfs_mkdir(const QString& name);
+ /// Rename file
+ virtual void vfs_rename(const QString& fileName,const QString& newName);
+
+ /// return the VFS working dir
+ virtual QString vfs_workingDir() { return vfs_origin.path(-1); }
+
+ /// Get ACL permissions
+ static void getACL( vfile *file, QString &acl, QString &defAcl );
+
+public slots:
+ void vfs_slotRefresh();
+ void vfs_slotDirty(const QString& path);
+ void vfs_slotCreated(const QString& path);
+ void vfs_slotDeleted(const QString& path);
+
+protected:
+ /// Re-reads files and stats and fills the vfile list
+ virtual bool populateVfsList(const KURL& origin, bool showHidden);
+
+ QTimer refreshTimer; //< Timer to exclude sudden refreshes
+ KDirWatch *watcher; //< The internal dir watcher - use to detect changes in directories
+ vfile* vfileFromName(const QString& name);
+
+private:
+ bool burstRefresh( const QString &path );
+ static QString getACL( const QString & path, int type );
+};
+
+#endif
diff --git a/krusader/VFS/preservingcopyjob.cpp b/krusader/VFS/preservingcopyjob.cpp
new file mode 100644
index 0000000..bd6d6cf
--- /dev/null
+++ b/krusader/VFS/preservingcopyjob.cpp
@@ -0,0 +1,319 @@
+/***************************************************************************
+ preservingcopyjob.cpp - description
+ -------------------
+ copyright : (C) 2005 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "preservingcopyjob.h"
+#include "../defaults.h"
+#include "../krusader.h"
+#include <utime.h>
+#include <klargefile.h>
+#include <kio/job.h>
+#include <kio/jobclasses.h>
+#include <kfileitem.h>
+#include <qfile.h>
+#include <pwd.h>
+#include <grp.h>
+
+
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+#include <sys/acl.h>
+#ifdef HAVE_NON_POSIX_ACL_EXTENSIONS
+#include <acl/libacl.h>
+#endif
+#endif
+
+Attributes::Attributes()
+{
+ time = (time_t)-1;
+ uid = (uid_t)-1;
+ gid = (gid_t)-1;
+ mode = (mode_t)-1;
+ acl = QString::null;
+}
+
+Attributes::Attributes( time_t tIn, uid_t uIn, gid_t gIn, mode_t modeIn, const QString & aclIn )
+{
+ time = tIn, uid = uIn, gid = gIn, mode = modeIn, acl = aclIn;
+}
+
+Attributes::Attributes( time_t tIn, QString user, QString group, mode_t modeIn, const QString & aclIn )
+{
+ time = tIn;
+ uid = (uid_t)-1;
+ struct passwd* pw = getpwnam(QFile::encodeName( user ));
+ if ( pw != 0L )
+ uid = pw->pw_uid;
+ gid = (gid_t)-1;
+ struct group* g = getgrnam(QFile::encodeName( group ));
+ if ( g != 0L )
+ gid = g->gr_gid;
+ mode = modeIn;
+ acl = aclIn;
+}
+
+PreservingCopyJob::PreservingCopyJob( const KURL::List& src, const KURL& dest, CopyMode mode,
+ bool asMethod, bool showProgressInfo ) : KIO::CopyJob( src, dest, mode, asMethod, showProgressInfo )
+{
+ if( dest.isLocalFile() )
+ {
+ connect( this, SIGNAL( aboutToCreate (KIO::Job *, const QValueList< KIO::CopyInfo > &) ),
+ this, SLOT( slotAboutToCreate (KIO::Job *, const QValueList< KIO::CopyInfo > &) ) );
+ connect( this, SIGNAL( copyingDone( KIO::Job *, const KURL &, const KURL &, bool, bool) ),
+ this, SLOT( slotCopyingDone( KIO::Job *, const KURL &, const KURL &, bool, bool) ) );
+ connect( this, SIGNAL( result( KIO::Job * ) ),
+ this, SLOT( slotFinished() ) );
+ }
+}
+
+void PreservingCopyJob::slotAboutToCreate( KIO::Job */*job*/, const QValueList< KIO::CopyInfo > &files )
+{
+ for ( QValueList< KIO::CopyInfo >::ConstIterator it = files.begin(); it != files.end(); ++it ) {
+
+ if( (*it).uSource.isLocalFile() ) {
+ KDE_struct_stat stat_p;
+ KDE_lstat( (*it).uSource.path(-1).local8Bit(),&stat_p); /* getting the date information */
+
+ QString aclStr;
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+ acl_t acl = acl_get_file( (*it).uSource.path(-1).local8Bit(), ACL_TYPE_ACCESS );
+
+ bool aclExtended = false;
+ if( acl )
+ {
+#if HAVE_NON_POSIX_ACL_EXTENSIONS
+ aclExtended = acl_equiv_mode( acl, 0 );
+#else
+ acl_entry_t entry;
+ int ret = acl_get_entry( acl, ACL_FIRST_ENTRY, &entry );
+ while ( ret == 1 ) {
+ acl_tag_t currentTag;
+ acl_get_tag_type( entry, &currentTag );
+ if ( currentTag != ACL_USER_OBJ &&
+ currentTag != ACL_GROUP_OBJ &&
+ currentTag != ACL_OTHER )
+ {
+ aclExtended = true;
+ break;
+ }
+ ret = acl_get_entry( acl, ACL_NEXT_ENTRY, &entry );
+ }
+#endif
+ }
+
+
+ if ( acl && !aclExtended ) {
+ acl_free( acl );
+ acl = NULL;
+ }
+ if( acl )
+ {
+ char *aclString = acl_to_text( acl, 0 );
+ aclStr = QString::fromLatin1( aclString );
+ acl_free( (void*)aclString );
+ acl_free( acl );
+ }
+#endif
+ fileAttributes[ (*it).uSource ] = Attributes( stat_p.st_mtime, stat_p.st_uid, stat_p.st_gid, stat_p.st_mode & 07777, aclStr );
+ }
+ else {
+ time_t mtime = (*it).mtime;
+
+ if( mtime != 0 && mtime != ((time_t) -1 ) ) /* is it correct? */
+ fileAttributes[ (*it).uSource ].time = mtime;
+
+ int permissions = (*it).permissions;
+ fileAttributes[ (*it).uSource ].mode = permissions;
+ }
+ }
+}
+
+void PreservingCopyJob::slotResult( Job *job ) {
+ if( !job->error() ) {
+ if( job->inherits( "KIO::StatJob" ) ) { /* Unfortunately KIO forgets to set times when the file is in the */
+ KURL url = ((KIO::SimpleJob *)job)->url(); /* base directory. That's why we capture every StatJob and set the */
+ /* time manually. */
+ KIO::UDSEntry entry = static_cast<KIO::StatJob*>(job)->statResult();
+ KFileItem kfi(entry, url );
+
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+ fileAttributes[ url ] = Attributes( kfi.time( KIO::UDS_MODIFICATION_TIME ), kfi.user(), kfi.group(), kfi.mode(), kfi.ACL().asString() );
+#else
+ fileAttributes[ url ] = Attributes( kfi.time( KIO::UDS_MODIFICATION_TIME ), kfi.user(), kfi.group(), kfi.mode(), QString::null );
+#endif
+ }
+ }
+
+ CopyJob::slotResult( job );
+
+ for( unsigned j=0; j != subjobs.count(); j++ ) {
+ if( subjobs.at( j )->inherits( "KIO::ListJob" ) ) {
+ disconnect( subjobs.at( j ), SIGNAL( entries (KIO::Job *, const KIO::UDSEntryList &) ),
+ this, SLOT( slotListEntries (KIO::Job *, const KIO::UDSEntryList &) ) );
+ connect( subjobs.at( j ), SIGNAL( entries (KIO::Job *, const KIO::UDSEntryList &) ),
+ this, SLOT( slotListEntries (KIO::Job *, const KIO::UDSEntryList &) ) );
+ }
+ }
+}
+
+void PreservingCopyJob::slotListEntries(KIO::Job *job, const KIO::UDSEntryList &list) {
+ KIO::UDSEntryListConstIterator it = list.begin();
+ KIO::UDSEntryListConstIterator end = list.end();
+ for (; it != end; ++it) {
+ KURL url = ((KIO::SimpleJob *)job)->url();
+ QString relName, user, group;
+ time_t mtime = (time_t)-1;
+ mode_t mode = 0755;
+ QString acl;
+
+ KIO::UDSEntry::ConstIterator it2 = (*it).begin();
+ for( ; it2 != (*it).end(); it2++ ) {
+ switch ((*it2).m_uds) {
+ case KIO::UDS_NAME:
+ if( relName.isEmpty() )
+ relName = (*it2).m_str;
+ break;
+ case KIO::UDS_URL:
+ relName = KURL((*it2).m_str).fileName();
+ break;
+ case KIO::UDS_MODIFICATION_TIME:
+ mtime = (time_t)((*it2).m_long);
+ break;
+ case KIO::UDS_USER:
+ user = (*it2).m_str;
+ break;
+ case KIO::UDS_GROUP:
+ group = (*it2).m_str;
+ break;
+ case KIO::UDS_ACCESS:
+ mode = (*it2).m_long;
+ break;
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+ case KIO::UDS_ACL_STRING:
+ acl = (*it2).m_str;
+ break;
+#endif
+ }
+ }
+ url.addPath( relName );
+
+ fileAttributes[ url ] = Attributes( mtime, user, group, mode, acl );
+ }
+}
+
+void PreservingCopyJob::slotCopyingDone( KIO::Job *, const KURL &from, const KURL &to, bool postpone, bool)
+{
+ if( postpone ) { // the directories are stamped at the last step, so if it's a directory, we postpone
+ unsigned i=0;
+ QString path = to.path( -1 );
+
+ for( ; i != directoriesToStamp.count(); i++ ) // sort the URL-s to avoid parent time stamp modification
+ if( path >= directoriesToStamp[ i ].path( -1 ) )
+ break;
+
+ directoriesToStamp.insert( directoriesToStamp.at( i ), to );
+ originalDirectories.insert( originalDirectories.at( i ), from );
+ }
+ else if( fileAttributes.count( from ) ) {
+ Attributes attrs = fileAttributes[ from ];
+ fileAttributes.remove( from );
+
+ time_t mtime = attrs.time;
+
+ if( to.isLocalFile() )
+ {
+ if( mtime != 0 && mtime != ((time_t) -1 ) )
+ {
+ struct utimbuf timestamp;
+
+ timestamp.actime = time( 0 );
+ timestamp.modtime = mtime;
+
+ utime( (const char *)( to.path( -1 ).local8Bit() ), &timestamp );
+ }
+
+ if( attrs.uid != (uid_t)-1 )
+ chown( (const char *)( to.path( -1 ).local8Bit() ), attrs.uid, (gid_t)-1 );
+ if( attrs.gid != (gid_t)-1 )
+ chown( (const char *)( to.path( -1 ).local8Bit() ), (uid_t)-1, attrs.gid );
+
+ if( attrs.mode != (mode_t) -1 )
+ chmod( (const char *)( to.path( -1 ).local8Bit() ), attrs.mode );
+
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+ if( !attrs.acl.isNull() )
+ {
+ acl_t acl = acl_from_text( attrs.acl.latin1() );
+ if( acl && !acl_valid( acl ) )
+ acl_set_file( to.path( -1 ).local8Bit(), ACL_TYPE_ACCESS, acl );
+ if( acl )
+ acl_free( acl );
+ }
+#endif
+ }
+ }
+}
+
+void PreservingCopyJob::slotFinished() {
+ for( unsigned i=0; i != directoriesToStamp.count(); i++ ) {
+ KURL from = originalDirectories[ i ];
+ KURL to = directoriesToStamp[ i ];
+
+ slotCopyingDone( 0, from, to, false, false );
+ }
+}
+
+KIO::CopyJob * PreservingCopyJob::createCopyJob( PreserveMode pmode, const KURL::List& src, const KURL& dest, CopyMode mode, bool asMethod, bool showProgressInfo )
+{
+ if( ! dest.isLocalFile() )
+ pmode = PM_NONE;
+ if( mode == KIO::CopyJob::Link )
+ pmode = PM_NONE;
+
+ switch( pmode )
+ {
+ case PM_PRESERVE_ATTR:
+ return new PreservingCopyJob( src, dest, mode, asMethod, showProgressInfo );
+ case PM_DEFAULT:
+ {
+ QString group = krConfig->group();
+ krConfig->setGroup( "Advanced" );
+ bool preserve = krConfig->readBoolEntry( "PreserveAttributes", _PreserveAttributes );
+ krConfig->setGroup( group );
+ if( preserve )
+ return new PreservingCopyJob( src, dest, mode, asMethod, showProgressInfo );
+ else
+ return new KIO::CopyJob( src, dest, mode, asMethod, showProgressInfo );
+ }
+ case PM_NONE:
+ default:
+ return new KIO::CopyJob( src, dest, mode, asMethod, showProgressInfo );
+ }
+}
+
+#include "preservingcopyjob.moc"
diff --git a/krusader/VFS/preservingcopyjob.h b/krusader/VFS/preservingcopyjob.h
new file mode 100644
index 0000000..0e48959
--- /dev/null
+++ b/krusader/VFS/preservingcopyjob.h
@@ -0,0 +1,84 @@
+/***************************************************************************
+ preservingcopyjob.h - description
+ -------------------
+ copyright : (C) 2005 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __PRESERVING_COPY_JOB_H__
+#define __PRESERVING_COPY_JOB_H__
+
+#include "config.h"
+#include <time.h>
+#include <kio/jobclasses.h>
+#include <qmap.h>
+#include <qvaluelist.h>
+
+typedef enum {
+ PM_NONE = 0,
+ PM_PRESERVE_ATTR = 1,
+ PM_DEFAULT = 2
+} PreserveMode;
+
+
+class Attributes {
+public:
+ Attributes();
+ Attributes( time_t tIn, uid_t uIn, gid_t gIn, mode_t modeIn, const QString & aclIn );
+ Attributes( time_t tIn, QString user, QString group, mode_t modeIn, const QString & aclIn );
+
+ time_t time;
+ uid_t uid;
+ gid_t gid;
+ mode_t mode;
+ QString acl;
+};
+
+class PreservingCopyJob : public KIO::CopyJob
+{
+ Q_OBJECT
+
+public:
+
+ PreservingCopyJob( const KURL::List& src, const KURL& dest, CopyMode mode, bool asMethod, bool showProgressInfo );
+
+ static KIO::CopyJob *createCopyJob( PreserveMode pmode, const KURL::List& src, const KURL& dest, CopyMode mode, bool asMethod, bool showProgressInfo );
+
+public slots:
+ void slotAboutToCreate (KIO::Job *, const QValueList< KIO::CopyInfo > &);
+ void slotCopyingDone( KIO::Job *, const KURL &, const KURL &, bool, bool);
+ void slotFinished();
+ virtual void slotResult( Job *job );
+ void slotListEntries(KIO::Job *job, const KIO::UDSEntryList &list);
+
+private:
+ QMap<KURL, Attributes> fileAttributes;
+ QMap<KIO::Job *, KURL> pendingJobs;
+ QValueList<KURL> directoriesToStamp;
+ QValueList<KURL> originalDirectories;
+};
+
+#endif /* __PRESERVING_COPY_JOB_H__ */
diff --git a/krusader/VFS/temp_vfs.cpp b/krusader/VFS/temp_vfs.cpp
new file mode 100644
index 0000000..12a5dad
--- /dev/null
+++ b/krusader/VFS/temp_vfs.cpp
@@ -0,0 +1,127 @@
+/***************************************************************************
+ temp_vfs.cpp
+ -------------------
+ copyright : (C) 2001 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+// Qt includes
+#include <qdir.h>
+// KDE includes
+#include <kmessagebox.h>
+#include <kprocess.h>
+// Krusader includes
+#include "temp_vfs.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include "../VFS/krarchandler.h"
+#include "../resources.h"
+#include "../krservices.h"
+
+temp_vfs::temp_vfs( QString origin, QString type, QWidget* panel, bool ):
+ normal_vfs(panel){
+ vfs_type=TEMP;
+ // first we need to create a temp diretory
+ tmpDir = krApp->getTempDir();
+ // then we must get the files from the origin to the tmp dir
+ if( type == "-arj" || type == "-ace" ) handleAceArj(origin,type);
+ else if( type == "-rpm" ) handleRpm(origin);
+ else if( type == "-iso" ) handleIso(origin);
+ else{
+ if (!quietMode) KMessageBox::error(krApp,"Unknown temp_vfs type.");
+ return;
+ }
+}
+
+temp_vfs::~temp_vfs(){
+ if( vfs_type == "-iso" ){
+ // unmount the ISO image
+ KShellProcess umount;
+ umount << "umount -f" << tmpDir;
+ umount.start(KProcess::Block);
+ }
+ // delete the temp dir
+ KShellProcess proc;
+ proc << "rm -rf" << tmpDir;
+ proc.start(KProcess::DontCare);
+}
+
+// return the working dir
+QString temp_vfs::vfs_workingDir(){
+ // get the path inside the archive
+ QString path = vfs_origin.path(-1);
+ path = path.mid(path.findRev('\\')+1);
+ if(path.left(1) != "/") path = "/"+path;
+ QDir().mkdir(tmpDir+path);
+ return tmpDir+path;
+}
+
+bool temp_vfs::vfs_refresh(const KURL& origin){
+ KURL backup = vfs_origin;
+ vfs_origin = origin;
+ vfs_origin.adjustPath(-1);
+ // get the directory...
+ QString path = origin.path(-1).mid(origin.path(-1).findRev('\\')+1);
+ if(path.left(1) =="/") path.remove(0,1);
+ if ( !normal_vfs::vfs_refresh(tmpDir+"/"+path) ){
+ vfs_origin = backup;
+ vfs_origin.adjustPath(-1);
+ return false;
+ }
+ return true;
+}
+
+void temp_vfs::handleAceArj(QString origin, QString type){
+ // for ace and arj we just unpack to the tmpDir
+ if( !KRarcHandler::arcHandled(type) ){
+ if (!quietMode) KMessageBox::error(krApp,"This archive type is NOT supported");
+ return;
+ }
+ else if( !KRarcHandler::unpack(origin,type, QString::null, tmpDir) ){
+ return;
+ }
+}
+
+void temp_vfs::handleRpm(QString origin){
+ // then extract the cpio archive from the rpm
+ KShellProcess rpm;
+ rpm << "rpm2cpio"<<"\""+origin+"\""+" > "+tmpDir+"/contents.cpio";
+ rpm.start(KProcess::Block);
+ // and write a nice header
+ rpm.clearArguments();
+ rpm << "rpm -qip"<<"\""+origin+"\""+" > "+tmpDir+"/header.txt";
+ rpm.start(KProcess::Block);
+ // and a file list
+ rpm.clearArguments();
+ rpm << "rpm -lpq"<<"\""+origin+"\""+" > "+tmpDir+"/filelist.txt";
+ rpm.start(KProcess::Block);
+}
+
+void temp_vfs::handleIso(QString origin){
+ // mount the ISO image
+ KShellProcess mount;
+ mount << KrServices::fullPathName( "mount" ) << "-o loop" << origin << tmpDir;
+ mount.start(KProcess::Block);
+}
diff --git a/krusader/VFS/temp_vfs.h b/krusader/VFS/temp_vfs.h
new file mode 100644
index 0000000..f55eb23
--- /dev/null
+++ b/krusader/VFS/temp_vfs.h
@@ -0,0 +1,57 @@
+/***************************************************************************
+ temp_vfs.h
+ -------------------
+ copyright : (C) 2001 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+
+#ifndef TEMP_VFS_H
+#define TEMP_VFS_H
+
+#include "normal_vfs.h"
+
+class temp_vfs : public normal_vfs {
+public:
+ temp_vfs( QString origin, QString type, QWidget* panel, bool writeable);
+ ~temp_vfs();
+ QString vfs_workingDir();
+ bool vfs_isWritable() { return false; } // temp vfs is not writable !
+
+public slots:
+ // actually reads files and stats
+ bool vfs_refresh(const KURL& origin);
+
+protected:
+ void handleAceArj(QString origin, QString type);
+ void handleRpm(QString origin);
+ void handleIso(QString origin);
+ QString tmpDir;
+
+};
+
+#endif
diff --git a/krusader/VFS/vfile.cpp b/krusader/VFS/vfile.cpp
new file mode 100644
index 0000000..a3e8c6b
--- /dev/null
+++ b/krusader/VFS/vfile.cpp
@@ -0,0 +1,311 @@
+/***************************************************************************
+ vfile.cpp
+ -------------------
+ copyright : (C) 2000 by Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+// System includes
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+// Qt includes
+#include <qdatetime.h>
+// KDE includes
+#include <kmimetype.h>
+#include <kdeversion.h>
+// Krusader includes
+#include "vfile.h"
+#include "krpermhandler.h"
+#include "normal_vfs.h"
+
+#include <kdebug.h>
+
+vfile::vfile(const QString& name, // useful construtor
+ const KIO::filesize_t size,
+ const QString& perm,
+ const time_t mtime,
+ const bool symLink,
+ const uid_t owner,
+ const gid_t group,
+ const QString& mime,
+ const QString& symDest,
+ const mode_t mode,
+ const int rwx)
+{
+ vfile_name=name;
+ vfile_size=size;
+ vfile_owner=QString::null;
+ vfile_ownerId=owner;
+ vfile_group=QString::null;
+ vfile_groupId=group;
+ vfile_userName=QString::null;
+ vfile_perm=perm;
+ vfile_time_t=mtime;
+ vfile_symLink=symLink;
+ vfile_mimeType=mime;
+ vfile_symDest=symDest;
+ vfile_mode=mode;
+ vfile_isdir = ( perm[ 0 ] == 'd' );
+ if (vfile_isDir() && !vfile_symLink )
+ vfile_size = 0;
+ vfile_rwx = rwx;
+ vfile_acl_loaded = false;
+}
+
+vfile::vfile(const QString& name, // useful construtor
+ const KIO::filesize_t size,
+ const QString& perm,
+ const time_t mtime,
+ const bool symLink,
+ const QString& owner,
+ const QString& group,
+ const QString& userName,
+ const QString& mime,
+ const QString& symDest,
+ const mode_t mode,
+ const int rwx,
+ const QString& aclString,
+ const QString& aclDfltString ){
+ vfile_name=name;
+ vfile_size=size;
+ vfile_owner=owner;
+ vfile_group=group;
+ vfile_userName=userName;
+ vfile_ownerId=KRpermHandler::user2uid(owner) ;
+ vfile_groupId=KRpermHandler::group2gid(group);
+ vfile_perm=perm;
+ vfile_time_t=mtime;
+ vfile_symLink=symLink;
+ vfile_mimeType=mime;
+ vfile_symDest=symDest;
+ vfile_mode=mode;
+ vfile_isdir = ( perm[ 0 ] == 'd' );
+ if ( vfile_isDir() && !vfile_symLink )
+ vfile_size = 0;
+ vfile_acl = aclString;
+ vfile_def_acl = aclDfltString;
+ vfile_has_acl = !aclString.isNull() || !aclDfltString.isNull();
+ vfile_acl_loaded = true;
+ vfile_rwx = rwx;
+}
+
+char vfile::vfile_isReadable() const {
+ if( vfile_rwx == PERM_ALL )
+ return ALLOWED_PERM;
+ else if( vfile_userName.isNull() )
+ return KRpermHandler::readable(vfile_perm,vfile_groupId,vfile_ownerId,vfile_rwx);
+ else
+ return KRpermHandler::ftpReadable(vfile_owner, vfile_userName, vfile_perm);
+}
+
+char vfile::vfile_isWriteable() const {
+ if( vfile_rwx == PERM_ALL )
+ return ALLOWED_PERM;
+ else if( vfile_userName.isNull() )
+ return KRpermHandler::writeable(vfile_perm,vfile_groupId,vfile_ownerId,vfile_rwx);
+ else
+ return KRpermHandler::ftpWriteable(vfile_owner, vfile_userName, vfile_perm);
+}
+
+char vfile::vfile_isExecutable() const {
+ if( vfile_rwx == PERM_ALL )
+ {
+ if(( vfile_mode & 0111 ) || vfile_isdir )
+ return ALLOWED_PERM;
+ else
+ return NO_PERM;
+ }
+ else if( vfile_userName.isNull() )
+ return KRpermHandler::executable(vfile_perm,vfile_groupId,vfile_ownerId,vfile_rwx);
+ else
+ return KRpermHandler::ftpExecutable(vfile_owner, vfile_userName, vfile_perm);
+}
+
+const QString& vfile::vfile_getMime(bool fast){
+ if( vfile_mimeType == QString::null ){ // mimetype == "" is OK so don't check mimetype.empty() !
+ vfile_mimeType = KMimeType::findByURL( vfile_getUrl(),vfile_getMode(),vfile_getUrl().isLocalFile(),fast)->name();
+ if( vfile_mimeType.contains("directory") ) vfile_perm[0] = 'd', vfile_isdir = true;
+ }
+ return vfile_mimeType;
+}
+
+const QString& vfile::vfile_getOwner(){
+ if( vfile_owner.isEmpty() )
+ vfile_owner=KRpermHandler::uid2user(vfile_getUid());
+ return vfile_owner;
+}
+
+const QString& vfile::vfile_getGroup(){
+ if( vfile_group.isEmpty() )
+ vfile_group=KRpermHandler::gid2group(vfile_getGid());
+ return vfile_group;
+}
+
+const QString& vfile::vfile_getACL(){
+ if( !vfile_acl_loaded )
+ vfile_loadACL();
+ return vfile_acl;
+}
+
+const QString& vfile::vfile_getDefaultACL(){
+ if( !vfile_acl_loaded )
+ vfile_loadACL();
+ return vfile_def_acl;
+}
+
+void vfile::vfile_loadACL()
+{
+ if( vfile_url.isLocalFile() )
+ {
+ normal_vfs::getACL( this, vfile_acl, vfile_def_acl );
+ vfile_has_acl = !vfile_acl.isNull() || !vfile_def_acl.isNull();
+ }
+ vfile_acl_loaded = true;
+}
+
+const KIO::UDSEntry vfile::vfile_getEntry() {
+ KIO::UDSEntry entry;
+ KIO::UDSAtom atom;
+
+ atom.m_uds = KIO::UDS_NAME;
+ atom.m_str = vfile_getName();
+ entry.append(atom);
+
+ atom.m_uds = KIO::UDS_SIZE;
+ atom.m_long = vfile_getSize();
+ entry.append(atom);
+
+ atom.m_uds = KIO::UDS_MODIFICATION_TIME;
+ atom.m_long = vfile_getTime_t();
+ entry.append(atom);
+
+ atom.m_uds = KIO::UDS_USER;
+ atom.m_str = vfile_getOwner();
+ entry.append(atom);
+
+ atom.m_uds = KIO::UDS_GROUP;
+ atom.m_str = vfile_getGroup();
+ entry.append(atom);
+
+ atom.m_uds = KIO::UDS_MIME_TYPE;
+ atom.m_str = vfile_getMime();
+ entry.append(atom);
+
+ atom.m_uds = KIO::UDS_FILE_TYPE;
+ atom.m_long = vfile_getMode() & S_IFMT;
+ entry.append(atom);
+
+ atom.m_uds = KIO::UDS_ACCESS;
+ atom.m_long = vfile_getMode() & 07777; // keep permissions only
+ entry.append( atom );
+
+ atom.m_uds = KIO::UDS_MIME_TYPE;
+ atom.m_str = vfile_getMime();
+ entry.append(atom);
+
+ if( vfile_isSymLink() ){
+ atom.m_uds = KIO::UDS_LINK_DEST;
+ atom.m_str = vfile_getSymDest();
+ entry.append(atom);
+ }
+
+#if KDE_IS_VERSION(3,5,0)
+ if( !vfile_acl_loaded )
+ vfile_loadACL();
+ if( vfile_has_acl ) {
+ atom.m_uds = KIO::UDS_EXTENDED_ACL;
+ atom.m_long = 1;
+ entry.append( atom );
+
+ if( !vfile_acl.isNull() )
+ {
+ atom.m_uds = KIO::UDS_ACL_STRING;
+ atom.m_str = vfile_acl;
+ entry.append(atom);
+ }
+
+ if( !vfile_def_acl.isNull() )
+ {
+ atom.m_uds = KIO::UDS_DEFAULT_ACL_STRING;
+ atom.m_str = vfile_acl;
+ entry.append(atom);
+ }
+ }
+#endif
+
+ return entry;
+}
+
+bool vfile::operator==(const vfile& vf) const{
+ bool equal;
+
+ if( !vfile_acl_loaded )
+ const_cast<vfile *>( this )->vfile_loadACL();
+ if( !vf.vfile_acl_loaded )
+ const_cast<vfile *>( &vf )->vfile_loadACL();
+
+ equal = (vfile_name == vf.vfile_getName() ) &&
+ (vfile_size == vf.vfile_getSize() ) &&
+ (vfile_perm == vf.vfile_getPerm() ) &&
+ (vfile_time_t == vf.vfile_getTime_t() ) &&
+ (vfile_ownerId == vf.vfile_getUid() ) &&
+ (vfile_groupId == vf.vfile_getGid() ) &&
+ (vfile_has_acl == vf.vfile_has_acl ) &&
+ (!vfile_has_acl ||
+ (vfile_acl == vf.vfile_acl ) &&
+ (vfile_def_acl == vf.vfile_def_acl ) );;
+
+ return equal;
+}
+
+vfile& vfile::operator= (const vfile& vf){
+ vfile_name = vf.vfile_name ;
+ vfile_size = vf.vfile_size ;
+ vfile_mode = vf.vfile_mode ;
+ vfile_ownerId = vf.vfile_ownerId ;
+ vfile_groupId = vf.vfile_groupId ;
+ vfile_owner = vf.vfile_owner ;
+ vfile_group = vf.vfile_group ;
+ vfile_userName = vf.vfile_userName ;
+ vfile_perm = vf.vfile_perm ;
+ vfile_time_t = vf.vfile_time_t ;
+ vfile_symLink = vf.vfile_symLink ;
+ vfile_mimeType = vf.vfile_mimeType ;
+ vfile_symDest = vf.vfile_symDest ;
+ vfile_url = vf.vfile_url ;
+ vfile_isdir = vf.vfile_isdir ;
+ vfile_has_acl = vf.vfile_has_acl ;
+ vfile_acl = vf.vfile_acl ;
+ vfile_def_acl = vf.vfile_def_acl ;
+ vfile_rwx = vf.vfile_rwx ;
+ vfile_acl_loaded = vf.vfile_acl_loaded;
+
+ return (*this);
+}
+
+#include "vfile.moc"
diff --git a/krusader/VFS/vfile.h b/krusader/VFS/vfile.h
new file mode 100644
index 0000000..61aa9bc
--- /dev/null
+++ b/krusader/VFS/vfile.h
@@ -0,0 +1,166 @@
+/***************************************************************************
+ vfile.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef VFILE_H
+#define VFILE_H
+
+// QT includes
+#include <qstring.h>
+#include <qobject.h>
+// System includes
+#include <sys/types.h>
+// KDE includes
+#include <kio/global.h>
+#include <kmimetype.h>
+
+#define PERM_ALL -2
+
+/**
+ * The Virtual File class handles all the details of maintaining a single
+ * file component within the virtual file system (vfs). a vfile object
+ * contains the nessecery details about a file and member functions which
+ * allow the object to give out the needed details about the file.
+ */
+class vfile : public QObject{
+ Q_OBJECT
+
+public:
+ vfile(){}
+
+ /**
+ * Use this constructor when you know the following files properties: \n
+ * file name, file size, file permissions,is the file a link,owner uid & group uid.
+ */
+ vfile(const QString& name,
+ const KIO::filesize_t size,
+ const QString& perm,
+ const time_t mtime,
+ const bool symLink,
+ const uid_t owner,
+ const gid_t group,
+ const QString& mime,
+ const QString& symDest,
+ const mode_t mode,
+ const int rwx = -1 );
+
+ vfile(const QString& name,
+ const KIO::filesize_t size,
+ const QString& perm,
+ const time_t mtime,
+ const bool symLink,
+ const QString& owner,
+ const QString& group,
+ const QString& userName,
+ const QString& mime,
+ const QString& symDest,
+ const mode_t mode,
+ const int rwx = -1,
+ const QString& aclString = QString::null,
+ const QString& aclDfltString = QString::null );
+
+ bool operator==(const vfile& vf) const;
+ vfile& operator= (const vfile& vf);
+ inline bool operator!=(const vfile& vf){ return !((*this)==vf); }
+
+ // following functions give-out file details
+ inline const QString& vfile_getName() const { return vfile_name; }
+ inline KIO::filesize_t vfile_getSize() const { return vfile_size; }
+ inline const QString& vfile_getPerm() const { return vfile_perm; }
+ inline bool vfile_isDir() const { return vfile_isdir; }
+ inline bool vfile_isSymLink() const { return vfile_symLink; }
+ inline const QString& vfile_getSymDest() const { return vfile_symDest; }
+ inline mode_t vfile_getMode() const { return vfile_mode; }
+ inline uid_t vfile_getUid() const { return vfile_ownerId; }
+ inline gid_t vfile_getGid() const { return vfile_groupId; }
+ inline time_t vfile_getTime_t() const { return vfile_time_t; }
+ inline const KURL& vfile_getUrl() const { return vfile_url; }
+
+ const QString& vfile_getMime(bool fast=false);
+ const QString& vfile_getOwner();
+ const QString& vfile_getGroup();
+ const QString& vfile_getACL();
+ const QString& vfile_getDefaultACL();
+ const KIO::UDSEntry vfile_getEntry(); //< return the UDSEntry from the vfile
+ char vfile_isReadable() const;
+ char vfile_isWriteable() const;
+ char vfile_isExecutable() const;
+ /**
+ * Set the file size.
+ * used ONLY when calculating a directory's space, needs to change the
+ * displayed size of the viewitem and thus the vfile. For INTERNAL USE !
+ */
+ inline void vfile_setSize(KIO::filesize_t size) {vfile_size = size;}
+ inline void vfile_setUrl(const KURL& url) {vfile_url = url; }
+
+ inline void vfile_setIcon(const QString& icn) {vfile_icon = icn; }
+ inline QString vfile_getIcon();
+
+ virtual ~vfile(){}
+
+private:
+ void vfile_loadACL();
+
+protected:
+ // the file information list
+ QString vfile_name; //< file name
+ KIO::filesize_t vfile_size; //< file size
+ mode_t vfile_mode; //< file mode
+ uid_t vfile_ownerId; //< file owner id
+ gid_t vfile_groupId; //< file group id
+ QString vfile_owner; //< file owner name
+ QString vfile_group; //< file group name
+ QString vfile_userName; //< the current username
+ QString vfile_perm; //< file permissions string
+ time_t vfile_time_t; //< file modification in time_t format
+ bool vfile_symLink; //< true if the file is a symlink
+ QString vfile_mimeType; //< file mimetype
+ QString vfile_symDest; //< if it's a sym link - its detination
+ KURL vfile_url; //< file URL - empty by default
+ QString vfile_icon; //< the name of the icon file
+ bool vfile_isdir; //< flag, if it's a directory
+ int vfile_rwx; //< flag, showing read, write, execute properties
+ bool vfile_acl_loaded;//<flag, indicates that ACL permissions already loaded
+ bool vfile_has_acl; //< flag, indicates ACL permissions
+ QString vfile_acl; //< ACL permission string
+ QString vfile_def_acl; //< ACL default string
+};
+
+
+QString vfile::vfile_getIcon(){
+ if( vfile_icon.isEmpty() ){
+ QString mime = this->vfile_getMime();
+ if ( mime == "Broken Link !" )
+ vfile_icon = "file_broken";
+ else {
+ vfile_icon = KMimeType::mimeType( mime ) ->icon( QString::null, true );
+ }
+ }
+ return vfile_icon;
+}
+
+#endif
diff --git a/krusader/VFS/vfs.cpp b/krusader/VFS/vfs.cpp
new file mode 100644
index 0000000..54efe7e
--- /dev/null
+++ b/krusader/VFS/vfs.cpp
@@ -0,0 +1,393 @@
+/***************************************************************************
+ vfs.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ------------------------------------------------------------------------
+ the vfs class is an extendable class which by itself does (almost)
+ nothing. other VFSs like the normal_vfs inherits from this class and
+ make it possible to use a consistent API for all types of VFSs.
+
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <unistd.h>
+#include <time.h>
+#include <qeventloop.h>
+#include <kapplication.h>
+#include <klargefile.h>
+#include <qdir.h>
+#include "vfs.h"
+#include "../krusader.h"
+#include "../defaults.h"
+
+vfs::vfs(QObject* panel, bool quiet): vfs_busy(false), quietMode(quiet),disableRefresh(false),postponedRefreshURL(),
+ invalidated(true),panelConnected(false),vfs_tempFilesP(0),vfileIterator(0),deletePossible( true ),
+ deleteRequested( false ) {
+
+
+ setVfsFilesP( new vfileDict() );
+ if ( panel ){
+ panelConnected = true;
+ connect(this,SIGNAL(startUpdate()),panel,SLOT(slotStartUpdate()));
+ connect(this,SIGNAL(incrementalRefreshFinished( const KURL& )),panel,SLOT(slotGetStats( const KURL& )));
+ }
+ else quietMode = true;
+}
+
+vfs::~vfs() {
+ if( !deletePossible )
+ fprintf( stderr, "INTERNAL ERROR: trying to delete vfs while it is used! This may cause crash. Hoping the best...\n" );
+ clear(); // please don't remove this line. This informs the view about deleting the references
+ delete vfs_filesP;
+}
+
+KIO::filesize_t vfs::vfs_totalSize(){
+ KIO::filesize_t temp=0;
+ class vfile* vf=vfs_getFirstFile();
+
+ while (vf!=0){
+ if ( (vf->vfile_getName() != ".") && ( vf->vfile_getName() != "..")
+ && !(vf->vfile_isDir()) )
+ temp+=vf->vfile_getSize();
+ vf=vfs_getNextFile();
+ }
+ return temp;
+}
+
+bool vfs::vfs_refresh(KIO::Job* job){
+ if(job && job->error()){
+ job->showErrorDialog(krApp);
+ }
+ return vfs_refresh(vfs_origin);
+}
+
+KURL vfs::fromPathOrURL( const QString &originIn )
+{
+ QString password, loginName, origin = originIn;
+ bool bugfix = false;
+
+ if ( originIn.contains( ":/" ) && !originIn.startsWith( "/" ) )
+ {
+ // breakdown the url;
+ /* FIXME: untill KDE fixes the bug we have to check for
+ passwords and users with @ in them... */
+ bugfix = origin.find("@") != origin.findRev("@");
+ if(bugfix){
+ if(origin.find(":") != origin.findRev(":", origin.findRev("@") )){
+ int passStart = origin.find( ":",origin.find(":")+1 )+1;
+ int passLen = origin.findRev("@")-passStart;
+ password = origin.mid(passStart,passLen);
+ origin = origin.remove(passStart-1,passLen+1);
+ }
+ if(origin.find("@") != origin.findRev("@")){
+ int usrStart = origin.find( "/" )+1;
+ if(origin.at(usrStart) == '/') ++usrStart;
+ int usrLen = origin.findRev("@")-usrStart;
+ loginName = origin.mid(usrStart,usrLen);
+ origin = origin.remove(usrStart,usrLen+1);
+ }
+ }
+ }
+ KURL url = KURL::fromPathOrURL( origin );
+ if(loginName.isEmpty()) loginName = url.user();
+ if(password.isEmpty()) password = url.pass();
+ if(bugfix){
+ url.setPass(password);
+ url.setUser(loginName);
+ }
+
+ return url;
+}
+
+QString vfs::pathOrURL( const KURL &originIn, int trailingSlash )
+{
+ if( originIn.isLocalFile() )
+ return originIn.path( trailingSlash );
+ return originIn.prettyURL( trailingSlash );
+}
+
+void vfs::setVfsFilesP(vfileDict* dict){
+ vfs_filesP=dict;
+ vfs_tempFilesP = new vfileDict();
+ vfs_tempFilesP->setAutoDelete( true );
+ dict->setAutoDelete(true);
+ if( vfileIterator ) delete vfileIterator;
+ vfileIterator = new QDictIterator<vfile>(*dict);
+}
+
+bool vfs::vfs_refresh(){
+ if( vfs_busy )
+ return false;
+
+ if( invalidated ) // invalidated fs requires total refresh
+ return vfs_refresh( vfs_getOrigin() );
+
+ if( disableRefresh )
+ {
+ postponedRefreshURL = vfs_getOrigin();
+ return false;
+ }
+
+ vfs_busy = true;
+ // and populate it
+ krConfig->setGroup("Advanced");
+ int maxIncrementalRefreshFileNr = krConfig->readNumEntry("Max Incremental Refresh File Nr", 50);
+ krConfig->setGroup("Look&Feel");
+ bool showHidden = krConfig->readBoolEntry("Show Hidden",_ShowHidden);
+ bool res = populateVfsList(vfs_getOrigin(),showHidden);
+
+ QString name;
+ if( res ){
+ // check if the maximum incremental refresh number is achieved
+ int diff = vfs_filesP->count() - vfs_tempFilesP->count();
+ if( diff < 0 )
+ diff = -diff;
+ if( diff >= maxIncrementalRefreshFileNr )
+ {
+ // total filesystem refresh is cheaper than incremental refresh for many files
+ clear();
+ delete vfs_filesP;
+ setVfsFilesP( vfs_tempFilesP );
+ vfs_busy = false;
+
+ emit startUpdate();
+ return true;
+ }
+
+ // compare the two list emiting signals when needed;;
+ for( vfile* vf = vfs_getFirstFile(); vf ; ){
+ name = vf->vfile_getName();
+ vfile* newVf = (*vfs_tempFilesP)[name];
+ if( !newVf ){
+ // the file was deleted..
+ emit deletedVfile(name);
+ vfs_filesP->remove(name);
+ // the remove() advance our iterator !
+ vf = vfileIterator->current();
+ } else {
+ if( *vf != *newVf ){
+ // the file was changed..
+ *vf = *newVf;
+ emit updatedVfile(vf);
+ }
+ vf=vfs_getNextFile();
+ }
+ vfs_tempFilesP->remove(name);
+ }
+ // everything thats left is a new file
+ QDictIterator<vfile> it(*vfs_tempFilesP);
+ for(vfile* vf=it.toFirst(); vf; vf=(++it)){
+ // sanity checking
+ if( !vf || (*vfs_filesP)[vf->vfile_getName()] ) continue;
+
+ vfile* newVf = new vfile();
+ *newVf = *vf;
+ vfs_filesP->insert(newVf->vfile_getName(),newVf);
+ emit addedVfile(newVf);
+ }
+ }
+
+ // delete the temporary vfiles
+ vfs_tempFilesP->clear();
+ vfs_busy = false;
+
+ emit incrementalRefreshFinished( vfs_origin );
+
+ return res;
+}
+
+bool vfs::vfs_refresh(const KURL& origin){
+ if( vfs_busy )
+ return false;
+
+ if( disableRefresh )
+ {
+ postponedRefreshURL = origin;
+ return true;
+ }
+
+ if( !invalidated && origin.equals(vfs_getOrigin(),true) ) return vfs_refresh();
+
+ vfs_busy = true;
+
+ krConfig->setGroup("Look&Feel");
+ bool showHidden = krConfig->readBoolEntry("Show Hidden",_ShowHidden);
+
+ vfs_tempFilesP->clear();
+ // and re-populate it
+ if (!populateVfsList(origin,showHidden) )
+ {
+ vfs_busy = false;
+ return false;
+ }
+
+ clear();
+ delete vfs_filesP;
+ setVfsFilesP( vfs_tempFilesP );
+ vfs_busy = false;
+
+ emit startUpdate();
+
+ invalidated = false;
+ return true;
+}
+
+void vfs::vfs_enableRefresh(bool enable){
+ if (vfs_type != NORMAL) return;
+ if (disableRefresh == !enable) return; // if gets called twice by mistake
+ disableRefresh = quietMode = !enable;
+ if( enable && !postponedRefreshURL.isEmpty() ) vfs_refresh( postponedRefreshURL );
+ postponedRefreshURL = KURL();
+}
+
+void vfs::clear()
+{
+ emit cleared();
+ vfs_filesP->clear();
+}
+
+bool vfs::vfs_processEvents() {
+ if( deleteRequested )
+ return false;
+ deletePossible = false;
+ qApp->eventLoop() ->processEvents( QEventLoop::AllEvents | QEventLoop::WaitForMore );
+ deletePossible = true;
+ if( deleteRequested ) {
+ emit deleteAllowed();
+ return false;
+ }
+ return true;
+}
+
+void vfs::vfs_requestDelete() {
+ if( deletePossible )
+ emit deleteAllowed();
+ deleteRequested = true;
+}
+
+/// to be implemented
+#if KDE_IS_VERSION(3,3,0)
+#include <kdirsize.h>
+void vfs::slotKdsResult( KIO::Job* job){
+ if( job && !job->error() ){
+ KDirSize* kds = static_cast<KDirSize*>(job);
+ *kds_totalSize += kds->totalSize();
+ *kds_totalFiles += kds->totalFiles();
+ *kds_totalDirs += kds->totalSubdirs();
+ }
+ *kds_busy = true;
+}
+
+void vfs::vfs_calcSpace( QString name , KIO::filesize_t* totalSize, unsigned long* totalFiles, unsigned long* totalDirs, bool* stop ) {
+ calculateURLSize( vfs_getFile( name ), totalSize, totalFiles, totalDirs, stop );
+}
+
+void vfs::calculateURLSize( KURL url, KIO::filesize_t* totalSize, unsigned long* totalFiles, unsigned long* totalDirs, bool* stop ) {
+ if ( stop && *stop ) return ;
+ kds_busy = stop;
+ kds_totalSize = totalSize ;
+ kds_totalFiles = totalFiles;
+ kds_totalDirs = totalDirs;
+
+ if( url.isLocalFile() ) {
+ vfs_calcSpaceLocal( url.path(-1), totalSize, totalFiles, totalDirs, stop );
+ return;
+ } else {
+ stat_busy = true;
+ KIO::StatJob* statJob = KIO::stat( url, false );
+ connect( statJob, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotStatResultArrived( KIO::Job* ) ) );
+ while ( !(*stop) && stat_busy ) {usleep(1000);}
+ if( entry.isEmpty() ) return; // statJob failed
+ KFileItem kfi(entry, url, true );
+ if( kfi.isFile() || kfi.isLink() ) {
+ *totalFiles++;
+ *totalSize += kfi.size();
+ return;
+ }
+ }
+
+ KDirSize* kds = KDirSize::dirSizeJob( url );
+ connect( kds, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotKdsResult( KIO::Job* ) ) );
+ while ( !(*stop) ){
+ // we are in a sepetate thread - so sleeping is OK
+ usleep(1000);
+ }
+}
+
+void vfs::vfs_calcSpaceLocal(QString name ,KIO::filesize_t *totalSize,unsigned long *totalFiles,unsigned long *totalDirs, bool* stop){
+ if ( *stop ) return;
+ if (!name.contains("/")) name = vfs_workingDir()+"/"+name;
+ if (name == "/proc") return;
+
+ KDE_struct_stat stat_p; // KDE lstat is necessary as QFileInfo and KFileItem
+ KDE_lstat(name.local8Bit(),&stat_p); // reports wrong size for a symbolic link
+
+ if( S_ISLNK(stat_p.st_mode) || !S_ISDIR(stat_p.st_mode) ) { // single files are easy : )
+ ++(*totalFiles);
+ (*totalSize) += stat_p.st_size;
+ }
+ else{ // handle directories
+ // avoid a nasty crash on un-readable dirs
+ bool readable = ::access( name.local8Bit(), R_OK | X_OK ) == 0;
+ if( !readable )
+ return;
+
+ QDir dir(name);
+ if ( !dir.exists() ) return;
+
+ ++(*totalDirs);
+ dir.setFilter(QDir::All | QDir::System | QDir::Hidden);
+ dir.setSorting(QDir::Name | QDir::DirsFirst);
+
+ // recurse on all the files in the directory
+ QFileInfoList* fileList = const_cast<QFileInfoList*>(dir.entryInfoList());
+ for (QFileInfo* qfiP = fileList->first(); qfiP != 0; qfiP = fileList->next()){
+ if ( *stop ) return;
+ if (qfiP->fileName() != "." && qfiP->fileName() != "..")
+ vfs_calcSpaceLocal(name+"/"+qfiP->fileName(),totalSize,totalFiles,totalDirs,stop);
+ }
+ }
+}
+
+
+void vfs::slotStatResultArrived( KIO::Job* job ) {
+ if( !job || job->error() ) entry = KIO::UDSEntry();
+ else entry = static_cast<KIO::StatJob*>(job)->statResult();
+ stat_busy = false;
+}
+
+#else
+void vfs::slotKdsResult(KIO::Job *job){/* empty */}
+void vfs::vfs_calcSpace( QString /*name*/ , KIO::filesize_t* /*totalSize*/, unsigned long* /*totalFiles*/, unsigned long* /*totalDirs*/, bool* /*stop*/ ) {/* empty*/}
+#endif
+
+QValueList<vfile*> vfs::vfs_search(const KRQuery& filter) {
+ QValueList<vfile*> result;
+ for ( vfile *vf = vfs_getFirstFile(); vf != 0 ; vf = vfs_getNextFile() )
+ if (filter.match(vf))
+ result.append(vf);
+ return result;
+}
+
+#include "vfs.moc"
diff --git a/krusader/VFS/vfs.h b/krusader/VFS/vfs.h
new file mode 100644
index 0000000..a20645d
--- /dev/null
+++ b/krusader/VFS/vfs.h
@@ -0,0 +1,186 @@
+/***************************************************************************
+ vfs.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef VFS_H
+#define VFS_H
+
+// QT includes
+#include <qstring.h>
+#include <qvaluelist.h>
+#include <qobject.h>
+#include <qdict.h>
+// KDE includes
+#include <kurl.h>
+#include <kio/jobclasses.h>
+// Krusader includes
+#include "vfile.h"
+#include "preservingcopyjob.h"
+#include "krquery.h"
+
+/**
+ * The vfs class is an extendable class which by itself does (almost)
+ * nothing. other VFSs like the normal_vfs inherits from this class and
+ * make it possible to use a consistent API for all types of VFSs.
+ */
+class vfs: public QObject{
+ Q_OBJECT
+public:
+ typedef QDict<vfile> vfileDict;
+ enum VFS_TYPE{ERROR=0,NORMAL,FTP,TEMP,VIRT};
+
+ /**
+ * Creates a vfs.
+ * @param panel the panel father. the VFS will connect it's signals to this object.
+ * @param quiet if true, the VFS will not display error messages
+ */
+ vfs(QObject* panel, bool quiet=false);
+ virtual ~vfs();
+
+ /// Copy a file to the vfs (physical).
+ virtual void vfs_addFiles(KURL::List *fileUrls,KIO::CopyJob::CopyMode mode,QObject* toNotify,QString dir = "", PreserveMode pmode = PM_DEFAULT)=0;
+ /// Remove a file from the vfs (physical)
+ virtual void vfs_delFiles(QStringList *fileNames)=0;
+ /// Return a list of URLs for multiple files
+ virtual KURL::List* vfs_getFiles(QStringList* names)=0;
+ /// Return a URL to a single file
+ virtual KURL vfs_getFile(const QString& name)=0;
+ /// Create a new directory
+ virtual void vfs_mkdir(const QString& name)=0;
+ /// Rename file
+ virtual void vfs_rename(const QString& fileName,const QString& newName)=0;
+ /// Calculate the amount of space occupied by a file or directory (recursive).
+ virtual void vfs_calcSpace(QString name ,KIO::filesize_t *totalSize,unsigned long *totalFiles,unsigned long *totalDirs, bool * stop);
+ /// Calculate the amount of space occupied by a local file or directory (recursive).
+ virtual void vfs_calcSpaceLocal(QString name ,KIO::filesize_t *totalSize,unsigned long *totalFiles,unsigned long *totalDirs, bool * stop);
+
+ /// Return the VFS working dir
+ virtual QString vfs_workingDir()=0;
+ /// Return true if the VFS url is writable
+ virtual bool vfs_isWritable() { return isWritable; }
+ /// Return vfile* or 0 if not found
+ inline vfile* vfs_search(const QString& name){ return (*vfs_filesP)[name]; }
+ /// Return an empty vfile* list if not found
+ QValueList<vfile*> vfs_search(const KRQuery& filter);
+ /// The total size of all the files in the VFS,
+ KIO::filesize_t vfs_totalSize();
+ /// The number of files in the VFS
+ inline unsigned long vfs_noOfFiles() { return vfs_filesP->count(); }
+ /// Returns the VFS url.
+ inline KURL vfs_getOrigin() { return vfs_origin; }
+ /// Return the VFS type.
+ inline VFS_TYPE vfs_getType() { return vfs_type; }
+ /// Returns true if vfs is busy
+ inline bool vfs_isBusy() { return vfs_busy; }
+ /// Return the first file in the VFS and set the internal iterator to the beginning of the list.
+ inline vfile* vfs_getFirstFile(){ return (vfileIterator ? vfileIterator->toFirst() : 0); }
+ /// Return the the next file in the list and advance the iterator.
+ inline vfile* vfs_getNextFile() { return (vfileIterator ? ++(*vfileIterator) : 0); }
+ /// returns true if the vfs can be deleted without crash
+ virtual bool vfs_canDelete() { return deletePossible; }
+ /// process the application events
+ virtual bool vfs_processEvents();
+ /// process the application events
+ virtual void vfs_requestDelete();
+ /// process the application events
+ virtual bool vfs_isDeleting() { return deleteRequested; }
+ // KDE FTP proxy bug correction
+ static KURL fromPathOrURL( const QString &originIn );
+ static QString pathOrURL( const KURL &originIn, int trailingSlash = 0 );
+
+
+public slots:
+ /// Re-reads files and stats and fills the vfile list
+ bool vfs_refresh(const KURL& origin);
+ /// Used to refresh the VFS when a job finishs. it calls the refresh() slot
+ /// or display a error message if the job fails
+ bool vfs_refresh(KIO::Job* job);
+ bool vfs_refresh();
+ void vfs_setQuiet(bool beQuiet){ quietMode=beQuiet; }
+ void vfs_enableRefresh(bool enable);
+ void vfs_invalidate() { invalidated = true; }
+
+signals:
+ void startUpdate(); //< emitted when the VFS starts to refresh its list of vfiles.
+ void startJob(KIO::Job* job);
+ void incrementalRefreshFinished( const KURL& ); //< emitted when the incremental refresh was finished
+ void addedVfile(vfile* vf);
+ void deletedVfile(const QString& name);
+ void updatedVfile(vfile* vf);
+ void cleared();
+ void deleteAllowed();
+
+protected:
+ /// Feel the vfs dictionary with vfiles, must be implemented for each vfs
+ virtual bool populateVfsList(const KURL& origin, bool showHidden) = 0;
+ /// Called by populateVfsList for each file
+ void foundVfile( vfile *vf ) { vfs_tempFilesP->insert(vf->vfile_getName(),vf); }
+ /// Set the vfile list pointer
+ void setVfsFilesP(vfileDict* dict);
+ /// clear and delete all current vfiles
+ inline void clear();
+ /// Add a new vfile to the list.
+ inline void addToList(vfile *data){ vfs_filesP->insert(data->vfile_getName(),data); }
+ /// Deletes a vfile from the list.
+ inline void removeFromList(QString name){ vfs_filesP->remove(name); }
+
+ /// Deletes a vfile from the list.
+ void calculateURLSize(KURL url,KIO::filesize_t *totalSize,unsigned long *totalFiles,unsigned long *totalDirs, bool * stop);
+
+ VFS_TYPE vfs_type; //< the vfs type.
+ KURL vfs_origin; //< the path or file the VFS originates from.
+ bool vfs_busy; //< true if vfs is busy with refreshing
+ bool quietMode; //< if true the vfs won't display error messages or emit signals
+ bool disableRefresh; //< true if refresh is disabled
+ bool isWritable; //< true if it's writable
+ KURL postponedRefreshURL; //< true if vfs_refresh() was called when refresh is disabled.
+ bool invalidated; //< the content of the cache is invalidated
+ bool panelConnected; //< indicates that there's a panel connected. Important for disabling the dir watcher
+
+protected slots:
+ /// The slot for the KDirSize job
+ void slotKdsResult(KIO::Job *job);
+ void slotStatResultArrived(KIO::Job *job);
+
+private:
+ vfileDict* vfs_filesP; //< Point to a lists of virtual files (vfile).
+ vfileDict* vfs_tempFilesP;//< Temporary files are stored here
+ QDictIterator<vfile>* vfileIterator; //< Point to a dictionary of virtual files (vfile).
+
+ // used in the calcSpace function
+ bool* kds_busy;
+ bool stat_busy;
+ bool deletePossible;
+ bool deleteRequested;
+ KIO::UDSEntry entry;
+ KIO::filesize_t* kds_totalSize;
+ unsigned long* kds_totalFiles;
+ unsigned long* kds_totalDirs;
+};
+
+#endif
diff --git a/krusader/VFS/virt_vfs.cpp b/krusader/VFS/virt_vfs.cpp
new file mode 100644
index 0000000..360e0f7
--- /dev/null
+++ b/krusader/VFS/virt_vfs.cpp
@@ -0,0 +1,341 @@
+/***************************************************************************
+ virt_vfs.cpp - description
+ -------------------
+ begin : Fri Dec 5 2003
+ copyright : (C) 2003 by Shie Erlich & Rafi Yanai
+ email :
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <unistd.h>
+#include <time.h>
+
+#include <kfileitem.h>
+#include <kglobalsettings.h>
+#include <kurl.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kdirsize.h>
+#include <kstandarddirs.h>
+
+#include "krpermhandler.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include "virt_vfs.h"
+
+#define VIRT_VFS_DB "virt_vfs.db"
+
+QDict<KURL::List> virt_vfs::virtVfsDict;
+KConfig* virt_vfs::virt_vfs_db=0;
+
+virt_vfs::virt_vfs( QObject* panel, bool quiet ) : vfs( panel, quiet ) {
+ // set the writable attribute
+ isWritable = true;
+
+ virtVfsDict.setAutoDelete( true );
+ if ( virtVfsDict.isEmpty() ) {
+ restore();
+ }
+
+ vfs_type = VIRT;
+}
+
+virt_vfs::~virt_vfs() {}
+
+bool virt_vfs::populateVfsList( const KURL& origin, bool /*showHidden*/ ) {
+ vfs_origin = origin;
+ vfs_origin.adjustPath(-1);
+ path = origin.path( -1 ).mid( 1 );
+ if ( path.isEmpty() ) path = "/";
+
+ KURL::List* urlList = virtVfsDict[ path ];
+ if ( !urlList ) {
+ urlList = new KURL::List();
+ virtVfsDict.insert( path, urlList );
+ virtVfsDict[ "/" ] ->append( KURL::fromPathOrURL( "virt:/" + path ) );
+ }
+
+ if ( urlList->isEmpty() ) return true;
+ KURL::List::iterator it;
+ for ( it = urlList->begin() ; it != urlList->end() ; /*++it*/ ) {
+ KURL url = *it;
+ // translate url->vfile and remove urls that no longer exist from the list
+ vfile* vf = stat(url);
+ if ( !vf ) {
+ it = urlList->remove( it );
+ // the iterator is advanced automaticly
+ continue;
+ }
+ foundVfile( vf );
+ ++it;
+ }
+ save();
+ return true;
+}
+
+void virt_vfs::vfs_addFiles( KURL::List *fileUrls, KIO::CopyJob::CopyMode /*mode*/, QObject* /*toNotify*/, QString /*dir*/, PreserveMode /*pmode*/ ) {
+ if ( path == "/" ) {
+ if ( !quietMode )
+ KMessageBox::error( krApp, i18n( "You can't copy files directly to the 'virt:/' directory.\nYou can create a sub directory and copy your files into it." ), i18n( "Error" ) );
+ return ;
+ }
+
+ KURL::List* urlList = virtVfsDict[ path ];
+ for( unsigned i=0; i != fileUrls->count(); i++ ) {
+ if( !urlList->contains( (*fileUrls)[ i ] ) )
+ urlList->push_back( (*fileUrls)[ i ] );
+ }
+
+ vfs_refresh();
+}
+
+void virt_vfs::vfs_delFiles( QStringList *fileNames ) {
+ if ( path == "/" ) {
+ for ( uint i = 0 ; i < fileNames->count(); ++i ) {
+ QString filename = ( *fileNames ) [ i ];
+ virtVfsDict[ "/" ] ->remove( QString("virt:/")+filename );
+ virtVfsDict.remove( filename );
+ }
+ vfs_refresh();
+ return ;
+ }
+
+ KURL::List filesUrls;
+ KURL url;
+
+ // names -> urls
+ for ( uint i = 0 ; i < fileNames->count(); ++i ) {
+ QString filename = ( *fileNames ) [ i ];
+ filesUrls.append( vfs_getFile( filename ) );
+ }
+ KIO::Job *job;
+
+ // delete of move to trash ?
+ krConfig->setGroup( "General" );
+ if ( krConfig->readBoolEntry( "Move To Trash", _MoveToTrash ) ) {
+#if KDE_IS_VERSION(3,4,0)
+ job = KIO::trash( filesUrls, true );
+#else
+ job = new KIO::CopyJob( filesUrls, KGlobalSettings::trashPath(), KIO::CopyJob::Move, false, true );
+#endif
+ connect( job, SIGNAL( result( KIO::Job* ) ), krApp, SLOT( changeTrashIcon() ) );
+ } else
+ job = new KIO::DeleteJob( filesUrls, false, true );
+
+ // refresh will remove the deleted files...
+ connect( job, SIGNAL( result( KIO::Job* ) ), this, SLOT( vfs_refresh( KIO::Job* ) ) );
+}
+
+void virt_vfs::vfs_removeFiles( QStringList *fileNames ) {
+ if ( path == "/" )
+ return;
+
+ // removing the URLs from the collection
+ for ( uint i = 0 ; i < fileNames->count(); ++i ) {
+ KURL::List* urlList = virtVfsDict[ path ];
+ if( urlList )
+ urlList->remove( vfs_getFile( ( *fileNames ) [ i ] ) );
+ }
+
+ vfs_refresh();
+}
+
+KURL::List* virt_vfs::vfs_getFiles( QStringList* names ) {
+ KURL url;
+ KURL::List* urls = new KURL::List();
+ for ( QStringList::Iterator name = names->begin(); name != names->end(); ++name ) {
+ url = vfs_getFile( *name );
+ urls->append( url );
+ }
+ return urls;
+}
+
+KURL virt_vfs::vfs_getFile( const QString& name ) {
+ vfile * vf = vfs_search( name );
+ if ( !vf ) return KURL(); // empty
+
+ KURL url = vf->vfile_getUrl();
+ if ( vf->vfile_isDir() ) url.adjustPath( + 1 );
+ return url;
+}
+
+void virt_vfs::vfs_mkdir( const QString& name ) {
+ if ( path != "/" ) {
+ if ( !quietMode )
+ KMessageBox::error( krApp, i18n( "Creating new directories is allowed only in the 'virt:/' directory." ), i18n( "Error" ) );
+ return ;
+ }
+ KURL::List* temp = new KURL::List();
+ virtVfsDict.insert( name, temp );
+ virtVfsDict[ "/" ] ->append( QString( "virt:/" )+name );
+
+ vfs_refresh();
+}
+
+void virt_vfs::vfs_rename( const QString& fileName, const QString& newName ) {
+ KURL::List fileUrls;
+ KURL url , dest;
+
+ vfile* vf = vfs_search( fileName );
+ if ( !vf ) return ; // not found
+
+ if ( path == "/" ) {
+ virtVfsDict[ "/" ] ->append( QString( "virt:/" ) + newName );
+ virtVfsDict[ "/" ] ->remove( QString( "virt:/" ) + fileName );
+ virtVfsDict.insert( newName, virtVfsDict.take( fileName ) );
+ vfs_refresh();
+ return ;
+ }
+
+ url = vf->vfile_getUrl();
+ fileUrls.append( url );
+
+ dest = fromPathOrURL( newName );
+ // add the new url to the list
+ // the the list is refreshed only existing files remain -
+ // so we don't have to worry if the job was successful
+ virtVfsDict[ path ] ->append( dest );
+
+ KIO::Job *job = new KIO::CopyJob( fileUrls, dest, KIO::CopyJob::Move, true, false );
+ connect( job, SIGNAL( result( KIO::Job* ) ), this, SLOT( vfs_refresh( KIO::Job* ) ) );
+}
+
+void virt_vfs::slotStatResult( KIO::Job* job ) {
+ if( !job || job->error() ) entry = KIO::UDSEntry();
+ else entry = static_cast<KIO::StatJob*>(job)->statResult();
+ busy = false;
+}
+
+vfile* virt_vfs::stat( const KURL& url ) {
+ if( url.protocol() == "virt" ){
+ QString path = url.path().mid(1);
+ if( path.isEmpty() ) path = "/";
+ vfile * temp = new vfile( path, 0, "drwxr-xr-x", time( 0 ), false, getuid(), getgid(), "inode/directory", "", 0 );
+ temp->vfile_setUrl( url );
+ return temp;
+ }
+ KFileItem* kfi;
+ if ( url.isLocalFile() ) {
+ kfi = new KFileItem( KFileItem::Unknown, KFileItem::Unknown, url, true );
+ }
+ else {
+ busy = true;
+ KIO::StatJob* statJob = KIO::stat( url, false );
+ connect( statJob, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotStatResult( KIO::Job* ) ) );
+ while ( busy && vfs_processEvents() );
+ if( entry.isEmpty() ) return 0; // statJob failed
+
+ kfi = new KFileItem(entry, url, true );
+ }
+
+ if ( !kfi->time( KIO::UDS_MODIFICATION_TIME ) ){
+ delete kfi;
+ return 0; // file not found
+ }
+
+ vfile *temp;
+
+ // get file statistics
+ QString name;
+ if( url.isLocalFile() )
+ name = url.path();
+ else
+ name = url.prettyURL();
+
+ KIO::filesize_t size = kfi->size();
+ time_t mtime = kfi->time( KIO::UDS_MODIFICATION_TIME );
+ bool symLink = kfi->isLink();
+ mode_t mode = kfi->mode() | kfi->permissions();
+ QString perm = KRpermHandler::mode2QString( mode );
+// set the mimetype
+ QString mime = QString::null;
+ QString symDest = "";
+ if ( symLink ) {
+ symDest = kfi->linkDest();
+ if ( kfi->isDir() ) perm[ 0 ] = 'd';
+ }
+
+ // create a new virtual file object
+ if ( kfi->user().isEmpty() )
+ temp = new vfile( name, size, perm, mtime, symLink, getuid(), getgid(), mime, symDest, mode );
+ else {
+ QString currentUser = url.user();
+ if ( currentUser.contains( "@" ) ) /* remove the FTP proxy tags from the username */
+ currentUser.truncate( currentUser.find( '@' ) );
+ if ( currentUser.isEmpty() )
+ currentUser = KRpermHandler::uid2user( getuid() );
+ temp = new vfile( name, size, perm, mtime, symLink, kfi->user(), kfi->group(), currentUser, mime, symDest, mode );
+ }
+
+ temp->vfile_setUrl( kfi->url() );
+ delete kfi;
+ return temp;
+}
+
+KConfig* virt_vfs::getVirtDB(){
+ if( !virt_vfs_db ){
+ virt_vfs_db = new KConfig(VIRT_VFS_DB,false,"data");
+ }
+ return virt_vfs_db;
+}
+
+bool virt_vfs::save(){
+ KConfig* db = getVirtDB();
+
+ db->setGroup("virt_db");
+ QDictIterator<KURL::List> it( virtVfsDict ); // See QDictIterator
+ for( ; it.current(); ++it ){
+ KURL::List::iterator url;
+ QStringList entry;
+ for ( url = it.current()->begin() ; url != it.current()->end() ; ++url ) {
+ entry.append( (*url).prettyURL() );
+ }
+ db->writeEntry(it.currentKey(),entry);
+ }
+
+ db->sync();
+
+ return true;
+}
+
+bool virt_vfs::restore(){
+ KConfig* db = getVirtDB();
+ db->setGroup("virt_db");
+
+ QMap<QString, QString> map = db->entryMap("virt_db");
+ QMap<QString, QString>::Iterator it;
+ KURL::List* urlList;
+ for ( it = map.begin(); it != map.end(); ++it ) {
+ urlList = new KURL::List( db->readListEntry(it.key()) );
+ virtVfsDict.insert( it.key(),urlList );
+ }
+
+ if( !virtVfsDict["/" ]){
+ urlList = new KURL::List();
+ virtVfsDict.insert( "/", urlList );
+ }
+
+ return true;
+}
+
+void virt_vfs::vfs_calcSpace( QString name , KIO::filesize_t* totalSize, unsigned long* totalFiles, unsigned long* totalDirs, bool* stop ) {
+ if ( stop && *stop ) return ;
+ if( path == "/" ) {
+ KURL::List* urlList = virtVfsDict[ name ];
+ if ( urlList )
+ for( unsigned i=0; (i != urlList->size()) && !(*stop); i++ )
+ calculateURLSize( (*urlList)[ i ], totalSize, totalFiles, totalDirs, stop );
+ return;
+ }
+ return vfs::vfs_calcSpace( name, totalSize, totalFiles, totalDirs, stop );
+}
+
+#include "virt_vfs.moc"
diff --git a/krusader/VFS/virt_vfs.h b/krusader/VFS/virt_vfs.h
new file mode 100644
index 0000000..2cf880f
--- /dev/null
+++ b/krusader/VFS/virt_vfs.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+ virt_vfs.h - description
+ -------------------
+ begin : Fri Dec 5 2003
+ copyright : (C) 2003 by Shie Erlich & Rafi Yanai
+ email :
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef VIRT_VFS_H
+#define VIRT_VFS_H
+
+#include <kconfig.h>
+
+#include "vfs.h"
+
+/**
+ *@author Shie Erlich & Rafi Yanai
+ */
+
+class virt_vfs : public vfs {
+Q_OBJECT
+public:
+ virt_vfs(QObject* panel, bool quiet=false);
+ ~virt_vfs();
+
+ /// Copy a file to the vfs (physical).
+ void vfs_addFiles(KURL::List *fileUrls,KIO::CopyJob::CopyMode mode,QObject* toNotify,QString dir = "", PreserveMode pmode = PM_DEFAULT );
+ /// Remove a file from the vfs (physical)
+ void vfs_delFiles(QStringList *fileNames);
+ /// Remove a file from the collection (only its link, not the file)
+ void vfs_removeFiles(QStringList *fileNames);
+ /// Return a list of URLs for multiple files
+ KURL::List* vfs_getFiles(QStringList* names);
+ /// Return a URL to a single file
+ KURL vfs_getFile(const QString& name);
+ /// Create a new directory
+ void vfs_mkdir(const QString& name);
+ /// Rename file
+ void vfs_rename(const QString& fileName,const QString& newName);
+ /// Calculate the amount of space occupied by a file or directory (recursive).
+ virtual void vfs_calcSpace(QString name ,KIO::filesize_t *totalSize,unsigned long *totalFiles,unsigned long *totalDirs, bool * stop);
+
+ /// Return the VFS working dir
+ QString vfs_workingDir(){ return QString::null; }
+
+protected slots:
+ void slotStatResult(KIO::Job *job);
+
+protected:
+ /// Save the dictionary to file
+ bool save();
+ /// Restore the dictionary from file
+ bool restore();
+ /// return the URLs DB
+ KConfig* getVirtDB();
+
+ bool populateVfsList(const KURL& origin, bool showHidden);
+ vfile* stat(const KURL& url);
+
+ static QDict<KURL::List> virtVfsDict;
+ static KConfig* virt_vfs_db;
+ bool busy;
+ QString path;
+ KIO::UDSEntry entry;
+};
+
+#endif
diff --git a/krusader/VFS/virtualcopyjob.cpp b/krusader/VFS/virtualcopyjob.cpp
new file mode 100644
index 0000000..7b11c77
--- /dev/null
+++ b/krusader/VFS/virtualcopyjob.cpp
@@ -0,0 +1,316 @@
+/***************************************************************************
+ virtualcopyjob.cpp - description
+ -------------------
+ copyright : (C) 2006 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "virtualcopyjob.h"
+#include "vfs.h"
+#include "vfile.h"
+#include "../krusader.h"
+#include <kio/observer.h>
+#include <kio/global.h>
+#include <kio/jobclasses.h>
+#include <kdirsize.h>
+
+#define REPORT_TIMEOUT 200
+
+VirtualCopyJob::VirtualCopyJob( const QStringList *names, vfs * vfs, const KURL& dest, const KURL& baseURL,
+ PreserveMode pmode, KIO::CopyJob::CopyMode mode, bool asMethod, bool showProgressInfo ) :
+ KIO::Job( showProgressInfo ), m_totalSize( 0 ), m_totalFiles( 0 ), m_totalSubdirs( 0 ),
+ m_processedSize( 0 ), m_processedFiles( 0 ), m_processedSubdirs( 0 ), m_tempSize( 0 ), m_tempFiles( 0 ),
+ m_tempSubdirs( 0 ), m_dirsToGetSize(), m_filesToCopy(), m_size(), m_filenum(), m_subdirs(), m_baseURL( baseURL ),
+ m_dest( dest ), m_pmode( pmode ), m_mode( mode ), m_asMethod( asMethod ), m_showProgressInfo( showProgressInfo ),
+ m_state( ST_STARTING ), m_reportTimer(), m_current(), m_currentDir(), m_dirStack() {
+
+ m_filesToCopy.setAutoDelete( true );
+ m_dest.adjustPath( 1 );
+
+ vfile * file = vfs->vfs_getFirstFile();
+ while( file ) {
+ if( names->contains( file->vfile_getName() ) ) {
+ QString relativeDir = KURL::relativeURL( baseURL, file->vfile_getUrl().upURL() );
+
+ KURL::List *list = m_filesToCopy.find( relativeDir );
+ if( list == 0 ) {
+ list = new KURL::List();
+ m_filesToCopy.insert( relativeDir, list );
+ // initialize the dir content
+ m_size[ relativeDir ] = 0;
+ m_filenum[ relativeDir ] = 0;
+ m_subdirs[ relativeDir ] = 0;
+ }
+
+ if( !list->contains( file->vfile_getUrl() ) ) {
+ if( file->vfile_isDir() ) {
+ m_dirsToGetSize.append( file->vfile_getUrl() );
+ m_totalSubdirs++;
+ m_subdirs[ relativeDir ]++;
+ } else {
+ m_totalFiles++;
+ m_filenum[ relativeDir ]++;
+ m_totalSize += file->vfile_getSize();
+ m_size[ relativeDir ] += file->vfile_getSize();
+ }
+ list->append( file->vfile_getUrl() );
+ }
+ }
+ file = vfs->vfs_getNextFile();
+ }
+
+ if ( showProgressInfo ) {
+ connect( this, SIGNAL( totalFiles( KIO::Job*, unsigned long ) ),
+ Observer::self(), SLOT( slotTotalFiles( KIO::Job*, unsigned long ) ) );
+ connect( this, SIGNAL( totalDirs( KIO::Job*, unsigned long ) ),
+ Observer::self(), SLOT( slotTotalDirs( KIO::Job*, unsigned long ) ) );
+ connect( this, SIGNAL( processedFiles( KIO::Job*, unsigned long ) ),
+ Observer::self(), SLOT( slotProcessedFiles( KIO::Job*, unsigned long ) ) );
+ connect( this, SIGNAL( processedDirs( KIO::Job*, unsigned long ) ),
+ Observer::self(), SLOT( slotProcessedDirs( KIO::Job*, unsigned long ) ) );
+ connect( this, SIGNAL( percent( KIO::Job*, unsigned long ) ),
+ Observer::self(), SLOT( slotPercent( KIO::Job*, unsigned long ) ) );
+ }
+
+ QTimer::singleShot( 0, this, SLOT( slotStart() ) );
+}
+
+void VirtualCopyJob::slotStart() {
+ if( m_showProgressInfo ) {
+ if( m_mode == KIO::CopyJob::Move )
+ Observer::self()->slotMoving( this, m_baseURL, m_dest );
+ else
+ Observer::self()->slotCopying( this, m_baseURL, m_dest );
+ }
+
+ connect(&m_reportTimer,SIGNAL(timeout()),this,SLOT(slotReport()));
+ m_reportTimer.start(REPORT_TIMEOUT,false);
+
+ statNextDir();
+}
+
+void VirtualCopyJob::slotReport() {
+ switch( m_state ) {
+ case ST_CREATING_DIRECTORY:
+ if( m_showProgressInfo ) {
+ Observer::self()->slotCreatingDir( this, m_current );
+ Observer::self()->slotProcessedDirs( this, m_processedSubdirs );
+ emit processedDirs( this, m_processedSubdirs );
+ }
+ break;
+ case ST_CALCULATING_TOTAL_SIZE:
+ emit totalSize( this, m_totalSize );
+ emit totalDirs( this, m_totalSubdirs );
+ emit totalFiles( this, m_totalFiles );
+ break;
+ case ST_COPYING:
+ {
+ emit processedDirs( this, m_processedSubdirs + m_tempSubdirs );
+ emit processedFiles( this, m_processedFiles + m_tempFiles );
+ setProcessedSize( m_processedSize + m_tempSize );
+ emit processedSize( this, m_processedSize + m_tempSize );
+ double percDbl = ((double)( m_processedSize + m_tempSize )/(double)m_totalSize) * 100. + 0.5;
+ unsigned long perc = (long)percDbl;
+ if( perc > 100 )
+ perc = 100;
+ emit percent( this, perc );
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void VirtualCopyJob::statNextDir() {
+ m_state = ST_CALCULATING_TOTAL_SIZE;
+
+ if( m_dirsToGetSize.count() == 0 ) {
+ slotReport(); // report the total size values
+ createNextDir();
+ return;
+ }
+ KURL dirToCheck = m_dirsToGetSize.first();
+ m_dirsToGetSize.pop_front();
+
+ m_currentDir = KURL::relativeURL( m_baseURL, dirToCheck.upURL() );
+
+ KDirSize* kds = KDirSize::dirSizeJob( dirToCheck );
+ connect( kds, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotKdsResult( KIO::Job* ) ) );
+}
+
+void VirtualCopyJob::slotKdsResult( KIO::Job * job ) {
+ KDirSize* kds = static_cast<KDirSize*>(job);
+ m_totalSize += kds->totalSize();
+ m_totalFiles += kds->totalFiles();
+ m_totalSubdirs += kds->totalSubdirs();
+
+ m_size[ m_currentDir ] += kds->totalSize();
+ m_filenum[ m_currentDir ] += kds->totalFiles();
+ m_subdirs[ m_currentDir ] += kds->totalSubdirs();
+ statNextDir();
+}
+
+void VirtualCopyJob::createNextDir() {
+ m_state = ST_CREATING_DIRECTORY;
+
+ if( m_filesToCopy.count() == 0 ) {
+ emitResult();
+ return;
+ }
+
+ QDictIterator<KURL::List> diter( m_filesToCopy );
+
+ m_currentDir = diter.currentKey();
+ m_current = m_dest;
+ if( m_currentDir != "./" && !m_currentDir.isEmpty() )
+ m_current.addPath( m_currentDir );
+
+ KIO::Job *job = KIO::stat( m_current );
+ connect( job, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotStatResult( KIO::Job* ) ) );
+}
+
+void VirtualCopyJob::slotStatResult( KIO::Job *job ) {
+ KURL url = (static_cast<KIO::SimpleJob*>(job) )->url();
+
+ if ( job && job->error() ) {
+ if( job->error() == KIO::ERR_DOES_NOT_EXIST && !url.equals( url.upURL(),true ) ) {
+ m_dirStack.push_back( url.fileName() );
+ KIO::Job *job = KIO::stat( url.upURL() );
+ connect( job, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotStatResult( KIO::Job* ) ) );
+ return;
+ }
+ job->showErrorDialog( krApp );
+ directoryFinished( m_currentDir );
+ createNextDir();
+ return;
+ }
+
+ if( m_dirStack.count() ) {
+ url.adjustPath( 1 );
+ url.addPath( m_dirStack.last() );
+ m_dirStack.pop_back();
+
+ KIO::Job *mkdir_job = KIO::mkdir( url );
+ connect( mkdir_job, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotMkdirResult( KIO::Job* ) ) );
+ }
+ else
+ copyCurrentDir();
+}
+
+void VirtualCopyJob::slotMkdirResult( KIO::Job *job ) {
+ KURL url = (static_cast<KIO::SimpleJob*>(job) )->url();
+
+ if ( job && job->error() ) {
+ job->showErrorDialog( krApp );
+ directoryFinished( m_currentDir );
+ createNextDir();
+ return;
+ }
+
+ if( m_dirStack.count() ) {
+ url.adjustPath( 1 );
+ url.addPath( m_dirStack.last() );
+ m_dirStack.pop_back();
+
+ KIO::Job *mkdir_job = KIO::mkdir( url );
+ connect( mkdir_job, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotMkdirResult( KIO::Job* ) ) );
+ }
+ else
+ copyCurrentDir();
+}
+
+void VirtualCopyJob::copyCurrentDir() {
+ m_state = ST_COPYING;
+
+ KIO::CopyJob * copy_job = PreservingCopyJob::createCopyJob( m_pmode, *m_filesToCopy[ m_currentDir ], m_current,
+ m_mode, m_asMethod, false );
+
+ connect( copy_job, SIGNAL( copying(KIO::Job *, const KURL &, const KURL &) ),
+ this, SLOT( slotCopying(KIO::Job *, const KURL &, const KURL &) ) );
+ connect( copy_job, SIGNAL( moving(KIO::Job *, const KURL &, const KURL &) ),
+ this, SLOT( slotMoving(KIO::Job *, const KURL &, const KURL &) ) );
+ connect( copy_job, SIGNAL( creatingDir(KIO::Job *, const KURL &) ),
+ this, SLOT( slotCreatingDir(KIO::Job *, const KURL &) ) );
+ connect( copy_job, SIGNAL( processedFiles (KIO::Job *, unsigned long) ),
+ this, SLOT( slotProcessedFiles (KIO::Job *, unsigned long) ) );
+ connect( copy_job, SIGNAL( processedDirs (KIO::Job *, unsigned long) ),
+ this, SLOT( slotProcessedDirs (KIO::Job *, unsigned long) ) );
+ connect( copy_job, SIGNAL( processedSize (KIO::Job *, KIO::filesize_t) ),
+ this, SLOT( slotProcessedSize (KIO::Job *, KIO::filesize_t) ) );
+ connect( copy_job, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotCopyResult( KIO::Job* ) ) );
+}
+
+void VirtualCopyJob::slotCopyResult( KIO::Job *job ) {
+ if ( job && job->error() ) {
+ job->showErrorDialog( krApp );
+ }
+
+ directoryFinished( m_currentDir );
+ createNextDir();
+}
+
+void VirtualCopyJob::directoryFinished( const QString &name ) {
+ m_filesToCopy.remove( name );
+
+ m_processedSize += m_size[ name ];
+ m_processedFiles += m_filenum[ name ];
+ m_processedSubdirs += m_subdirs[ name ];
+
+ m_tempSize = m_tempFiles = m_tempSubdirs = 0;
+
+ m_size.remove( name );
+ m_filenum.remove( name );
+ m_subdirs.remove( name );
+}
+
+void VirtualCopyJob::slotCopying(KIO::Job *, const KURL &from, const KURL &to) {
+ if( m_showProgressInfo )
+ Observer::self()->slotCopying( this, from, to );
+}
+
+void VirtualCopyJob::slotMoving(KIO::Job *, const KURL &from, const KURL &to) {
+ if( m_showProgressInfo )
+ Observer::self()->slotMoving( this, from, to );
+}
+
+void VirtualCopyJob::slotCreatingDir(KIO::Job *, const KURL &to) {
+ if( m_showProgressInfo )
+ Observer::self()->slotCreatingDir( this, to );
+}
+
+void VirtualCopyJob::slotProcessedFiles (KIO::Job *, unsigned long filenum) {
+ m_tempFiles = filenum;
+}
+
+void VirtualCopyJob::slotProcessedDirs (KIO::Job *, unsigned long subdirs) {
+ m_tempSubdirs = subdirs;
+}
+
+void VirtualCopyJob::slotProcessedSize (KIO::Job *, KIO::filesize_t size) {
+ m_tempSize = size;
+}
+
+#include "virtualcopyjob.moc"
diff --git a/krusader/VFS/virtualcopyjob.h b/krusader/VFS/virtualcopyjob.h
new file mode 100644
index 0000000..6505a97
--- /dev/null
+++ b/krusader/VFS/virtualcopyjob.h
@@ -0,0 +1,125 @@
+/***************************************************************************
+ virtualcopyjob.h - description
+ -------------------
+ copyright : (C) 2006 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __VIRTUAL_COPY_JOB_H__
+#define __VIRTUAL_COPY_JOB_H__
+
+#include <kio/job.h>
+#include "preservingcopyjob.h"
+#include <qvaluelist.h>
+#include <qtimer.h>
+#include <qdict.h>
+#include <qmap.h>
+
+class vfs;
+
+typedef enum {
+ ST_STARTING = 0,
+ ST_CALCULATING_TOTAL_SIZE = 1,
+ ST_CREATING_DIRECTORY = 2,
+ ST_COPYING = 3
+} State;
+
+class VirtualCopyJob : public KIO::Job
+{
+ Q_OBJECT
+
+public:
+ VirtualCopyJob( const QStringList *names, vfs * vfs, const KURL& dest, const KURL& baseURL,
+ PreserveMode pmode, KIO::CopyJob::CopyMode mode, bool asMethod, bool showProgressInfo );
+
+protected:
+ void statNextDir();
+ void createNextDir();
+ void copyCurrentDir();
+ void directoryFinished( const QString & );
+
+protected slots:
+ void slotStart();
+ void slotReport();
+
+ void slotKdsResult( KIO::Job * );
+ void slotStatResult( KIO::Job * );
+ void slotMkdirResult( KIO::Job * );
+ void slotCopyResult( KIO::Job * );
+
+ void slotCopying(KIO::Job *, const KURL &, const KURL &);
+ void slotMoving(KIO::Job *, const KURL &, const KURL &);
+ void slotCreatingDir(KIO::Job *, const KURL &);
+
+ void slotProcessedFiles (KIO::Job *, unsigned long);
+ void slotProcessedDirs (KIO::Job *, unsigned long);
+ void slotProcessedSize (KIO::Job *, KIO::filesize_t);
+
+signals:
+ void totalFiles( KIO::Job *job, unsigned long files );
+ void totalDirs( KIO::Job *job, unsigned long dirs );
+ void processedFiles( KIO::Job *job, unsigned long files );
+ void processedDirs( KIO::Job *job, unsigned long dirs );
+
+private:
+ KIO::filesize_t m_totalSize;
+ unsigned long m_totalFiles;
+ unsigned long m_totalSubdirs;
+
+ KIO::filesize_t m_processedSize;
+ unsigned long m_processedFiles;
+ unsigned long m_processedSubdirs;
+
+ KIO::filesize_t m_tempSize;
+ unsigned long m_tempFiles;
+ unsigned long m_tempSubdirs;
+
+ QValueList<KURL> m_dirsToGetSize;
+
+ QDict<KURL::List> m_filesToCopy;
+
+ QMap<QString,int> m_size;
+ QMap<QString,int> m_filenum;
+ QMap<QString,int> m_subdirs;
+
+ KURL m_baseURL;
+ KURL m_dest;
+ PreserveMode m_pmode;
+ KIO::CopyJob::CopyMode m_mode;
+ bool m_asMethod;
+ bool m_showProgressInfo;
+
+ State m_state;
+
+ QTimer m_reportTimer;
+
+ KURL m_current;
+ QString m_currentDir;
+
+ QStringList m_dirStack;
+};
+
+#endif /* __VIRTUAL_COPY_JOB_H__ */
diff --git a/krusader/alpa-yellow.color b/krusader/alpa-yellow.color
new file mode 100644
index 0000000..a7a9a45
--- /dev/null
+++ b/krusader/alpa-yellow.color
Binary files differ
diff --git a/krusader/bash.color b/krusader/bash.color
new file mode 100644
index 0000000..664b975
--- /dev/null
+++ b/krusader/bash.color
Binary files differ
diff --git a/krusader/calc.js b/krusader/calc.js
new file mode 100644
index 0000000..de43427
--- /dev/null
+++ b/krusader/calc.js
@@ -0,0 +1,64 @@
+
+function Calculator(ui)
+{
+ // Setup entry functions
+ var display = ui.child('display');
+ this.display = display;
+
+ this.one = function() { display.intValue = display.intValue*10+1; }
+ this.two = function() { display.intValue = display.intValue*10+2; }
+ this.three = function() { display.intValue = display.intValue*10+3; }
+ this.four = function() { display.intValue = display.intValue*10+4; }
+ this.five = function() { display.intValue = display.intValue*10+5; }
+ this.six = function() { display.intValue = display.intValue*10+6; }
+ this.seven = function() { display.intValue = display.intValue*10+7; }
+ this.eight = function() { display.intValue = display.intValue*10+8; }
+ this.nine = function() { display.intValue = display.intValue*10+9; }
+ this.zero = function() { display.intValue = display.intValue*10+0; }
+
+ ui.connect( ui.child('one'), 'clicked()', this, 'one' );
+ ui.connect( ui.child('two'), 'clicked()', this, 'two' );
+ ui.connect( ui.child('three'), 'clicked()', this, 'three' );
+ ui.connect( ui.child('four'), 'clicked()', this, 'four' );
+ ui.connect( ui.child('five'), 'clicked()', this, 'five' );
+ ui.connect( ui.child('six'), 'clicked()', this, 'six' );
+ ui.connect( ui.child('seven'), 'clicked()', this, 'seven' );
+ ui.connect( ui.child('eight'), 'clicked()', this, 'eight' );
+ ui.connect( ui.child('nine'), 'clicked()', this, 'nine' );
+ ui.connect( ui.child('zero'), 'clicked()', this, 'zero' );
+
+ this.val = 0;
+ this.lastop = function() {}
+
+ this.plus = function()
+ {
+ this.val = display.intValue+this.val;
+ display.intValue = 0;
+ this.lastop=this.plus
+ }
+
+ this.minus = function()
+ {
+ this.val = display.intValue-this.val;
+ display.intValue = 0;
+ this.lastop=this.minus;
+ }
+
+
+ ui.connect( ui.child('plus'), 'clicked()', this, 'plus' );
+ ui.connect( ui.child('minus'), 'clicked()', this, 'minus' );
+
+ this.equals = function() { this.lastop(); display.intValue = this.val; }
+ this.clear = function() { this.lastop=function(){}; display.intValue = 0; this.val = 0; }
+
+ ui.connect( ui.child('equals'), 'clicked()', this, 'equals' );
+ ui.connect( ui.child('clear'), 'clicked()', this, 'clear' );
+
+ this.setCap = function() { Krusader.setCaption( display.intValue ); }
+ ui.connect( ui.child('setCap'), 'clicked()', this, 'setCap' );
+}
+
+var ui = Factory.loadui( scriptDir + 'calc.ui' );
+var calc = new Calculator(ui);
+
+ui.show();
diff --git a/krusader/calc.ui b/krusader/calc.ui
new file mode 100644
index 0000000..fd442e6
--- /dev/null
+++ b/krusader/calc.ui
@@ -0,0 +1,267 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>calc</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>calc</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>244</width>
+ <height>193</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>JS Calculator</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLCDNumber" row="0" column="0">
+ <property name="name">
+ <cstring>display</cstring>
+ </property>
+ <property name="numDigits">
+ <number>18</number>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton" row="1" column="3">
+ <property name="name">
+ <cstring>plus</cstring>
+ </property>
+ <property name="text">
+ <string>+</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="0" column="4">
+ <property name="name">
+ <cstring>all_clear</cstring>
+ </property>
+ <property name="text">
+ <string>AC</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="2" column="3">
+ <property name="name">
+ <cstring>minus</cstring>
+ </property>
+ <property name="text">
+ <string>-</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="3" column="2" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>equals</cstring>
+ </property>
+ <property name="text">
+ <string>=</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="4">
+ <property name="name">
+ <cstring>clear</cstring>
+ </property>
+ <property name="text">
+ <string>CL</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="3" column="1">
+ <property name="name">
+ <cstring>zero</cstring>
+ </property>
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="0">
+ <property name="name">
+ <cstring>four</cstring>
+ </property>
+ <property name="text">
+ <string>4</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="0" column="1">
+ <property name="name">
+ <cstring>two</cstring>
+ </property>
+ <property name="text">
+ <string>2</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="1">
+ <property name="name">
+ <cstring>five</cstring>
+ </property>
+ <property name="text">
+ <string>5</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="0" column="2">
+ <property name="name">
+ <cstring>three</cstring>
+ </property>
+ <property name="text">
+ <string>3</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="2" column="0">
+ <property name="name">
+ <cstring>seven</cstring>
+ </property>
+ <property name="text">
+ <string>7</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="2">
+ <property name="name">
+ <cstring>six</cstring>
+ </property>
+ <property name="text">
+ <string>6</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="2" column="1">
+ <property name="name">
+ <cstring>eight</cstring>
+ </property>
+ <property name="text">
+ <string>8</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="2" column="2">
+ <property name="name">
+ <cstring>nine</cstring>
+ </property>
+ <property name="text">
+ <string>9</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="0" column="0">
+ <property name="name">
+ <cstring>one</cstring>
+ </property>
+ <property name="text">
+ <string>1</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QPushButton" row="2" column="0">
+ <property name="name">
+ <cstring>setCap</cstring>
+ </property>
+ <property name="text">
+ <string>Set as caption</string>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>plus</sender>
+ <signal>clicked()</signal>
+ <receiver>calc</receiver>
+ <slot>plus()</slot>
+ </connection>
+ <connection>
+ <sender>minus</sender>
+ <signal>clicked()</signal>
+ <receiver>calc</receiver>
+ <slot>minus()</slot>
+ </connection>
+ <connection>
+ <sender>equals</sender>
+ <signal>clicked()</signal>
+ <receiver>calc</receiver>
+ <slot>equals()</slot>
+ </connection>
+ <connection>
+ <sender>zero</sender>
+ <signal>clicked()</signal>
+ <receiver>calc</receiver>
+ <slot>zero()</slot>
+ </connection>
+ <connection>
+ <sender>four</sender>
+ <signal>clicked()</signal>
+ <receiver>calc</receiver>
+ <slot>four()</slot>
+ </connection>
+ <connection>
+ <sender>two</sender>
+ <signal>clicked()</signal>
+ <receiver>calc</receiver>
+ <slot>two()</slot>
+ </connection>
+ <connection>
+ <sender>five</sender>
+ <signal>clicked()</signal>
+ <receiver>calc</receiver>
+ <slot>five()</slot>
+ </connection>
+ <connection>
+ <sender>three</sender>
+ <signal>clicked()</signal>
+ <receiver>calc</receiver>
+ <slot>three()</slot>
+ </connection>
+ <connection>
+ <sender>seven</sender>
+ <signal>clicked()</signal>
+ <receiver>calc</receiver>
+ <slot>seven()</slot>
+ </connection>
+ <connection>
+ <sender>six</sender>
+ <signal>clicked()</signal>
+ <receiver>calc</receiver>
+ <slot>six()</slot>
+ </connection>
+ <connection>
+ <sender>eight</sender>
+ <signal>clicked()</signal>
+ <receiver>calc</receiver>
+ <slot>eight()</slot>
+ </connection>
+ <connection>
+ <sender>nine</sender>
+ <signal>clicked()</signal>
+ <receiver>calc</receiver>
+ <slot>nine()</slot>
+ </connection>
+ <connection>
+ <sender>one</sender>
+ <signal>clicked()</signal>
+ <receiver>calc</receiver>
+ <slot>one()</slot>
+ </connection>
+</connections>
+<slots>
+ <slot>one()</slot>
+ <slot>two()</slot>
+ <slot>three()</slot>
+ <slot>four()</slot>
+ <slot>five()</slot>
+ <slot>six()</slot>
+ <slot>seven()</slot>
+ <slot>eight()</slot>
+ <slot>nine()</slot>
+ <slot>zero()</slot>
+ <slot>plus()</slot>
+ <slot>minus()</slot>
+ <slot>equals()</slot>
+ <slot>setCap()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/krusader/cr16-app-krusader_blue.png b/krusader/cr16-app-krusader_blue.png
new file mode 100644
index 0000000..fce437d
--- /dev/null
+++ b/krusader/cr16-app-krusader_blue.png
Binary files differ
diff --git a/krusader/cr16-app-krusader_red.png b/krusader/cr16-app-krusader_red.png
new file mode 100644
index 0000000..4a85c77
--- /dev/null
+++ b/krusader/cr16-app-krusader_red.png
Binary files differ
diff --git a/krusader/cr16-app-krusader_root.png b/krusader/cr16-app-krusader_root.png
new file mode 100644
index 0000000..de3dc9e
--- /dev/null
+++ b/krusader/cr16-app-krusader_root.png
Binary files differ
diff --git a/krusader/cr16-app-krusader_user.png b/krusader/cr16-app-krusader_user.png
new file mode 100644
index 0000000..622da20
--- /dev/null
+++ b/krusader/cr16-app-krusader_user.png
Binary files differ
diff --git a/krusader/cr22-app-krusader_blue.png b/krusader/cr22-app-krusader_blue.png
new file mode 100644
index 0000000..ea20b70
--- /dev/null
+++ b/krusader/cr22-app-krusader_blue.png
Binary files differ
diff --git a/krusader/cr22-app-krusader_red.png b/krusader/cr22-app-krusader_red.png
new file mode 100644
index 0000000..a35cd17
--- /dev/null
+++ b/krusader/cr22-app-krusader_red.png
Binary files differ
diff --git a/krusader/cr22-app-krusader_root.png b/krusader/cr22-app-krusader_root.png
new file mode 100644
index 0000000..f278795
--- /dev/null
+++ b/krusader/cr22-app-krusader_root.png
Binary files differ
diff --git a/krusader/cr22-app-krusader_shield.png b/krusader/cr22-app-krusader_shield.png
new file mode 100644
index 0000000..84fe966
--- /dev/null
+++ b/krusader/cr22-app-krusader_shield.png
Binary files differ
diff --git a/krusader/cr22-app-krusader_user.png b/krusader/cr22-app-krusader_user.png
new file mode 100644
index 0000000..b818071
--- /dev/null
+++ b/krusader/cr22-app-krusader_user.png
Binary files differ
diff --git a/krusader/cr32-app-krusader_blue.png b/krusader/cr32-app-krusader_blue.png
new file mode 100644
index 0000000..e6ef8a9
--- /dev/null
+++ b/krusader/cr32-app-krusader_blue.png
Binary files differ
diff --git a/krusader/cr32-app-krusader_red.png b/krusader/cr32-app-krusader_red.png
new file mode 100644
index 0000000..acebcce
--- /dev/null
+++ b/krusader/cr32-app-krusader_red.png
Binary files differ
diff --git a/krusader/cr32-app-krusader_root.png b/krusader/cr32-app-krusader_root.png
new file mode 100644
index 0000000..6be1af7
--- /dev/null
+++ b/krusader/cr32-app-krusader_root.png
Binary files differ
diff --git a/krusader/cr32-app-krusader_shield.png b/krusader/cr32-app-krusader_shield.png
new file mode 100644
index 0000000..005c9be
--- /dev/null
+++ b/krusader/cr32-app-krusader_shield.png
Binary files differ
diff --git a/krusader/cr32-app-krusader_user.png b/krusader/cr32-app-krusader_user.png
new file mode 100644
index 0000000..4b2fd3b
--- /dev/null
+++ b/krusader/cr32-app-krusader_user.png
Binary files differ
diff --git a/krusader/cr48-app-krusader_blue.png b/krusader/cr48-app-krusader_blue.png
new file mode 100644
index 0000000..20af4dd
--- /dev/null
+++ b/krusader/cr48-app-krusader_blue.png
Binary files differ
diff --git a/krusader/cr48-app-krusader_red.png b/krusader/cr48-app-krusader_red.png
new file mode 100644
index 0000000..761c07f
--- /dev/null
+++ b/krusader/cr48-app-krusader_red.png
Binary files differ
diff --git a/krusader/cr48-app-krusader_root.png b/krusader/cr48-app-krusader_root.png
new file mode 100644
index 0000000..f2bf59c
--- /dev/null
+++ b/krusader/cr48-app-krusader_root.png
Binary files differ
diff --git a/krusader/cr48-app-krusader_shield.png b/krusader/cr48-app-krusader_shield.png
new file mode 100644
index 0000000..c086abb
--- /dev/null
+++ b/krusader/cr48-app-krusader_shield.png
Binary files differ
diff --git a/krusader/cr48-app-krusader_user.png b/krusader/cr48-app-krusader_user.png
new file mode 100644
index 0000000..ace741b
--- /dev/null
+++ b/krusader/cr48-app-krusader_user.png
Binary files differ
diff --git a/krusader/cr64-app-krusader_blue.png b/krusader/cr64-app-krusader_blue.png
new file mode 100644
index 0000000..07b7ed8
--- /dev/null
+++ b/krusader/cr64-app-krusader_blue.png
Binary files differ
diff --git a/krusader/cr64-app-krusader_red.png b/krusader/cr64-app-krusader_red.png
new file mode 100644
index 0000000..0234239
--- /dev/null
+++ b/krusader/cr64-app-krusader_red.png
Binary files differ
diff --git a/krusader/cr64-app-krusader_root.png b/krusader/cr64-app-krusader_root.png
new file mode 100644
index 0000000..29f0c3d
--- /dev/null
+++ b/krusader/cr64-app-krusader_root.png
Binary files differ
diff --git a/krusader/cr64-app-krusader_shield.png b/krusader/cr64-app-krusader_shield.png
new file mode 100644
index 0000000..d93d269
--- /dev/null
+++ b/krusader/cr64-app-krusader_shield.png
Binary files differ
diff --git a/krusader/cr64-app-krusader_user.png b/krusader/cr64-app-krusader_user.png
new file mode 100644
index 0000000..aa018ea
--- /dev/null
+++ b/krusader/cr64-app-krusader_user.png
Binary files differ
diff --git a/krusader/defaults.h b/krusader/defaults.h
new file mode 100644
index 0000000..5d99fe4
--- /dev/null
+++ b/krusader/defaults.h
@@ -0,0 +1,306 @@
+/***************************************************************************
+ defaults.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+ Description
+***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+#include <kglobalsettings.h>
+
+/////////////////////// [Startup]
+// UI Save Settings
+#define _UiSave false
+// Show Cmd Line
+#define _ShowCmdline true
+// Show status bar
+#define _ShowStatusBar true
+// Show tool bar
+#define _ShowToolBar true
+// Show FN Keys
+#define _ShowFNkeys true
+// Show Terminal Emulator
+#define _ShowTerminalEmulator false
+// Remember Position
+#define _RememberPos true
+// Start to tray
+#define _StartToTray false
+// Left Tab Bar
+// Right Tab Bar
+// Left Panel Popup
+#define _LeftPanelPopup 0
+// Right Panel Popup
+#define _RightPanelPopup 0
+
+
+////////////////////////[Look&Feel]
+// Filelist Font ///////
+#define _FilelistFont new QFont(KGlobalSettings::generalFont())
+// Warn On Exit ////////
+#define _WarnOnExit false
+// Minimize To Tray ////
+#define _MinimizeToTray false
+// Mark Dirs ///////////
+#define _MarkDirs false
+// Show Hidden /////////
+#define _ShowHidden true
+// Sort By Extention ///
+#define _SortByExt false
+// Case Sensative Sort /
+#define _CaseSensativeSort false
+// Html Min Font Size //
+#define _HtmlMinFontSize 12
+// Filelist Icon Size //
+#define _FilelistIconSize QString("22")
+// Mouse Selection /////
+#define _MouseSelection 0 // 0 - normal (shift+click, ctrl+click), 1 - left click, 2 - right click
+// Use fullpath tab names /////
+#define _FullPathTabNames false
+
+// Panel Toolbar Checkboxes
+// Panel Toolbar Visible checkbox turned off
+#define _PanelToolBar true
+// cd / is turned on
+#define _cdRoot true
+// cd ~ is turned on
+#define _cdHome false
+// cd .. is turned on
+#define _cdUp true
+// cd other panel is turned on
+#define _cdOther false
+// Open directory is turned on
+#define _Open false
+// syncBrowseButton is turned on
+#define _syncBrowseButton false
+// Clear Location Bar Visible
+#define _ClearLocation true
+// Use the default colors of KDE
+#define _KDEDefaultColors true
+// Enable Alternate Background colors
+#define _AlternateBackground true
+// Show current item even if not focussed
+#define _ShowCurrentItemAlways false
+// Dim the colors of the inactive panel
+#define _DimInactiveColors false
+// Human Readable Size
+#define _HumanReadableSize true
+// With Icons
+#define _WithIcons true
+// Single Click Selects
+#define _SingleClickSelects false
+// Numeric Permissions
+#define _NumericPermissions false
+// Number of Columns in the Brief View
+#define _NumberOfBriefColumns 3
+// Create brief mode panels
+#define _DefaultPanelType "Detailed"
+// Show splashscreen
+#define _ShowSplashScreen true
+// Single instance mode
+#define _SingleInstanceMode false
+
+/////////////////////// [General]
+// Mimetype Magic /////
+#define _MimetypeMagic true
+// Move To Trash //////
+#define _MoveToTrash false
+// Terminal ///////////
+#define _Terminal "konsole"
+// Send CDs ///////////
+#define _SendCDs true
+// Editor /////////////
+#define _Editor "internal editor"
+// Temp Directory /////
+#define _TempDirectory "/tmp/krusader.tmp"
+// Classic Quicksearch
+#define _NewStyleQuicksearch true
+// Case Sensitive quick search, if _NewStyleQuicksearch is true
+#define _CaseSensitiveQuicksearch false
+// View In Separate Window
+#define _ViewInSeparateWindow false
+
+/////////////////////// [Advanced]
+// Permission Check ///
+//#define _PermCheck true
+// AutoMount //////////
+#define _AutoMount false
+// Preserving date //////////
+#define _PreserveAttributes false
+// Nonmount Points ////
+#define _NonMountPoints "/, "
+// Confirm Unempty Dir // (for delete)
+#define _ConfirmUnemptyDir true
+// Confirm Delete ///// (for deleting files)
+#define _ConfirmDelete true
+// Confirm Copy /////// (for copying files)
+#define _ConfirmCopy true
+// Confirm Move /////// (for moving files)
+#define _ConfirmMove true
+// Icon Cache Size ////
+#define _IconCacheSize 2048
+
+/////////////////////// [Archives]
+// Do Tar /////////////
+#define _DoTar true
+// Do GZip ////////////
+#define _DoGZip true
+// Do Zip /////////////
+#define _DoZip true
+// Do UnZip ///////////
+#define _DoUnZip true
+// Do BZip2 ///////////
+#define _DoBZip2 true
+// Do Rar /////////////
+#define _DoRar true
+// Do UnRar ///////////
+#define _DoUnRar true
+// Do UnAce ///////////
+#define _DoUnAce true
+// Do Arj /////////////
+#define _DoArj true
+// Do UnArj ///////////
+#define _DoUnarj true
+// Do RPM /////////////
+#define _DoRPM true
+// Do DEB ///////////// ====> new
+#define _DoDEB true
+// Do Lha /////////////
+#define _DoLha true
+// Do 7z ///////////// ====> new
+#define _Do7z true
+// Allow Move Into Archive //
+#define _MoveIntoArchive false
+// Test Archives //////
+#define _TestArchives false
+// Test Before Unpack ////
+#define _TestBeforeUnpack true
+// Supported Packers // ====> a QStringList of SYSTEM supported archives ( also new )
+
+/////////////////////// [UserActions]
+// Terminal for UserActions ///////////
+#define _UserActions_Terminal "konsole --noclose -e"
+// Normal font for output collection ///////
+#define _UserActions_NormalFont new QFont(KGlobalSettings::generalFont())
+// Font for output collection with fixed width ///////
+#define _UserActions_FixedFont new QFont(KGlobalSettings::fixedFont())
+// Use for output collection fixed width font as default ///////
+#define _UserActions_UseFixedFont false
+
+/////////////////////// [Private]
+// Start Position /////
+#define _StartPosition new QPoint(QApplication::desktop()->width()/2 - mainView->sizeHint().width()/2,QApplication::desktop()->height()/2 - 250)
+// Start Size /////////
+#define _StartSize new QSize(mainView->sizeHint().width(),500)
+// Panel Size /////////
+#define _PanelSize 0
+// Terminal Size //////
+#define _TerminalSize 0
+// Left Name Size - size of the left panel's name column
+// Left Size Size - size of the left panel's size column
+// Left Date Size - size of the left panel's date column
+// Right Name Size - size of the right panel's name column
+// Right Size Size - size of the left panel's size column
+// Right Date Size - size of the left panel's date column
+// Splitter Sizes - sizes of the splitter
+
+/////////////////////// [RemoteMan]
+// Connections ////////
+// the basic connections are defined internally
+
+/////////////////////// [Search]
+// Saved Searches /////
+// holds an index of saved searches
+// Confirm Feed to Listbox ///// (costum-name on feed ti listbox)
+#define _ConfirmFeedToListbox true
+
+
+/////////// here are additional variables used internally by Krusader ////////////
+// BookmarkArchives - The infobox about not allowing bookmarks inside archives
+// BackArchiveWarning - The infobox about not allowing to back up into archives
+// SupermountWarning - Warning about mounting/unmounting supermount filesystems
+// lastHomeRight - Save the last place the right list panel was showing
+// lastHomeLeft - Save the last place the left list panel was showing
+// lastUsedPacker - used by packGUI to remember the last used packer
+
+/////////////////////// [Popular Urls]
+// PopularUrls - a string list containing the top urls
+// PopularUrlsRank - an int list contains the urls' ranking
+
+/////////////////////// [Synchronize directories]
+// Don't overwrite automatically /////////////
+#define _ConfirmOverWrites false
+// Recursive search in the subdirectories /////////////
+#define _RecurseSubdirs true
+// The searcher follows symlinks /////////////
+#define _FollowSymlinks false
+// Files with similar size are compared by content /////////////
+#define _CompareByContent false
+// The date information is ignored at synchronization /////////////
+#define _IgnoreDate false
+// Asymmetric Client-File Server compare mode /////////////
+#define _Asymmetric false
+// Case insensitive compare in synchronizer /////////////
+#define _IgnoreCase false
+// Scrolls the results of the synchronization /////////////
+#define _ScrollResults false
+// The right arrow button is turned on /////////////
+#define _BtnLeftToRight true
+// The equals button is turned on /////////////
+#define _BtnEquals true
+// The not equals button is turned on /////////////
+#define _BtnDifferents true
+// The left arrow button is turned on /////////////
+#define _BtnRightToLeft true
+// The trash button is turned on /////////////
+#define _BtnDeletable true
+// The duplicates button is turned on /////////////
+#define _BtnDuplicates true
+// The singles button is turned on /////////////
+#define _BtnSingles true
+
+/////////////////////// [Custom Selection Mode]
+// QT Selection
+#define _QtSelection false
+// Left Selects
+#define _LeftSelects true
+// Left Preserves
+#define _LeftPreserves false
+// ShiftCtrl Left Selects
+#define _ShiftCtrlLeft false
+// Right Selects
+#define _RightSelects true
+// Right Preserves
+#define _RightPreserves false
+// ShiftCtrl Right Selects
+#define _ShiftCtrlRight false
+// Space Moves Down
+#define _SpaceMovesDown true
+// Space Calc Space
+#define _SpaceCalcSpace true
+// Insert Moves Down
+#define _InsertMovesDown true
+// Immediate Context Menu
+#define _ImmediateContextMenu true
diff --git a/krusader/dos_navigator.color b/krusader/dos_navigator.color
new file mode 100644
index 0000000..423fbe3
--- /dev/null
+++ b/krusader/dos_navigator.color
Binary files differ
diff --git a/krusader/kicons.cpp b/krusader/kicons.cpp
new file mode 100644
index 0000000..103cf53
--- /dev/null
+++ b/krusader/kicons.cpp
@@ -0,0 +1,377 @@
+/***************************************************************************
+ kicons.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ this file is the Krusader's icon library.
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "kicons.h"
+#include "krusader.h"
+#include "defaults.h"
+#include <qstring.h>
+
+QPixmap FL_LOADICON(QString name) {
+ krConfig->setGroup("Look&Feel");
+ int size = (krConfig->readEntry("Filelist Icon Size",_FilelistIconSize)).toInt();
+ if (size!=22)
+ return krLoader->loadIcon(name,KIcon::Desktop,size);
+ // else implied
+ return QIconSet(krLoader->loadIcon(name,KIcon::Desktop,32)).pixmap(QIconSet::Small,true);
+}
+
+const char * no_xpm[] = {
+"14 14 5 1",
+" c None",
+". c #F70713",
+"+ c #800309",
+"@ c #7F0309",
+"# c #EC0612",
+" ",
+" .. .. ",
+" ... ... ",
+" ... ... ",
+" ... ... ",
+" ..... ",
+" ... ",
+" ..... ",
+" ....#.. ",
+" ... ... ",
+" ... ... ",
+" ... ... ",
+" .. .. ",
+" "};
+
+const char * yes_xpm[] = {
+"14 14 4 1",
+" c None",
+". c #07F907",
+"+ c #06F806",
+"@ c #06F706",
+" ",
+" .",
+" ...",
+" ....",
+" ... ",
+" ... ",
+" .. ",
+".. .. ",
+".... ... ",
+" .. ... ",
+" .... ",
+" ...+ ",
+" .. ",
+" @. "};
+
+const char * link_xpm[] = {
+"32 32 28 1",
+" c None",
+". c #000000",
+"+ c #FEFEFE",
+"@ c #FFFFFF",
+"# c #D7D7D7",
+"$ c #F6F6F6",
+"% c #646464",
+"& c #373737",
+"* c #2B2B2B",
+"= c #BEBEBE",
+"- c #393939",
+"; c #363636",
+"> c #F0F0F0",
+", c #AFAFAF",
+"' c #2A2A2A",
+") c #606060",
+"! c #474747",
+"~ c #868686",
+"{ c #262626",
+"] c #1E1E1E",
+"^ c #DEDEDE",
+"/ c #666666",
+"( c #222222",
+"_ c #1C1C1C",
+": c #DCDCDC",
+"< c #4F4F4F",
+"[ c #1A1A1A",
+"} c #525252",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+".......... ",
+".+@##$++@. ",
+".@%&*#+++. ",
+".@=@-;@@+. ",
+".@>@,')!+. ",
+".@@~!*{]@. ",
+".@@^/'(_@. ",
+".@@@:<][@. ",
+".++++:}[+. ",
+".@@@@@@#@. ",
+".......... "};
+
+const char * black_xpm[] = {
+"32 32 2 1",
+" c None",
+". c #000000",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+".......... ",
+".......... ",
+".......... ",
+".......... ",
+".......... ",
+".......... ",
+".......... ",
+".......... ",
+".......... ",
+".......... ",
+".......... "};
+
+const char * yellow_xpm[] = {
+"32 32 3 1",
+" c None",
+". c #000000",
+"+ c #FFEE00",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+".......... ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".......... "};
+
+const char * red_xpm[] = {
+"32 32 3 1",
+" c None",
+". c #000000",
+"+ c #FF0000",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+".......... ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".......... "};
+
+const char * white_xpm[] = {
+"32 32 3 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+".......... ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".......... "};
+
+const char * green_xpm[] = {
+"32 32 3 1",
+" c None",
+". c #000000",
+"+ c #15FF00",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+".......... ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".......... "};
+
+const char * blue_xpm[] = {
+"32 32 3 1",
+" c None",
+". c #000000",
+"+ c #1100FF",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+".......... ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".++++++++. ",
+".......... "};
+
diff --git a/krusader/kicons.h b/krusader/kicons.h
new file mode 100644
index 0000000..ae200db
--- /dev/null
+++ b/krusader/kicons.h
@@ -0,0 +1,29 @@
+#ifndef KICONS_H
+#define KICONS_H
+
+#include <qiconset.h>
+#include <qpixmap.h>
+#include <kiconloader.h>
+#include <kicontheme.h>
+
+// can be used everywhere - EXCEPT in KFileList related calls, loads the icon according to
+// KIcon::Desktop settings and resizes it to a smaller size. If this is used to toolbuttons,
+// the the icon is resized again to fit into the toolbutton or menu.
+// IMPORTANT: this SHOULD NOT BE USED for actions. If creating an action, just state the file-name
+// of the icon to allow automatic resizing when needed.
+#define LOADICON(X) QIconSet(krLoader->loadIcon(X,KIcon::Desktop)).pixmap(QIconSet::Small,true)
+
+// used only for calls within the kfilelist framework, handles icon sizes
+QPixmap FL_LOADICON(QString name);
+
+extern const char * no_xpm[];
+extern const char * yes_xpm[];
+extern const char * link_xpm[];
+extern const char * black_xpm[];
+extern const char * yellow_xpm[];
+extern const char * green_xpm[];
+extern const char * red_xpm[];
+extern const char * white_xpm[];
+extern const char * blue_xpm[];
+
+#endif
diff --git a/krusader/krservices.cpp b/krusader/krservices.cpp
new file mode 100644
index 0000000..bf0ef35
--- /dev/null
+++ b/krusader/krservices.cpp
@@ -0,0 +1,216 @@
+/***************************************************************************
+ krservices.cpp - description
+ -------------------
+ begin : Thu Aug 8 2002
+ copyright : (C) 2002 by Shie Erlich & Rafi Yanai
+ email :
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <stdlib.h>
+#include <unistd.h>
+// QT includes
+#include <qdir.h>
+// KDE includes
+#include <kdebug.h>
+// Krusader includes
+#include "krservices.h"
+#include "krusader.h"
+
+QMap<QString,QString>* KrServices::slaveMap=0;
+
+bool KrServices::cmdExist(QString cmdName)
+{
+ QString lastGroup = krConfig->group();
+
+ krConfig->setGroup( "Dependencies" );
+ if( QFile( krConfig->readEntry( cmdName, QString::null )).exists() )
+ {
+ krConfig->setGroup( lastGroup );
+ return true;
+ }
+
+ krConfig->setGroup( lastGroup );
+ return !detectFullPathName( cmdName ).isEmpty();
+}
+
+QString KrServices::detectFullPathName(QString name)
+{
+ QStringList path = QStringList::split(":",getenv("PATH"));
+
+ for ( QStringList::Iterator it = path.begin(); it != path.end(); ++it )
+ {
+ if( QDir(*it).exists( name ) )
+ {
+ QString dir = *it;
+ if( !dir.endsWith( "/" ) )
+ dir+="/";
+
+ return dir+name;
+ }
+ }
+
+ return "";
+}
+
+QString KrServices::fullPathName( QString name, QString confName )
+{
+ QString lastGroup = krConfig->group();
+ QString supposedName;
+
+ if( confName.isNull() )
+ confName = name;
+
+ krConfig->setGroup( "Dependencies" );
+ if( QFile( supposedName = krConfig->readEntry( confName, "" )).exists() )
+ {
+ krConfig->setGroup( lastGroup );
+ return supposedName;
+ }
+
+ if( ( supposedName = detectFullPathName( name ) ).isEmpty() )
+ {
+ krConfig->setGroup( lastGroup );
+ return "";
+ }
+
+ krConfig->writeEntry( confName, supposedName );
+ krConfig->setGroup( lastGroup );
+ return supposedName;
+}
+
+// TODO: Document me!
+QStringList KrServices::separateArgs( QString args )
+{
+ QStringList argList;
+ int pointer = 0, tokenStart, len = args.length();
+ bool quoted = false;
+ QChar quoteCh;
+
+ do{
+ while( pointer < len && args[ pointer ].isSpace() )
+ pointer++;
+
+ if( pointer >= len )
+ break;
+
+ tokenStart = pointer;
+
+ QString result="";
+
+ for(; pointer < len && ( quoted || !args[ pointer ].isSpace()) ; pointer++)
+ {
+ if( !quoted && ( args[pointer] == '"' || args[pointer] == '\'' ) ) {
+ quoted = true, quoteCh = args[pointer];
+ continue;
+ }
+ else if( quoted && args[pointer] == quoteCh ) {
+ quoted = false;
+ continue;
+ }
+ else if( !quoted && args[pointer] == '\\' )
+ {
+ pointer++;
+ if(pointer>=len) break;
+ }
+
+ result += args[pointer];
+ }
+
+ argList.append( result );
+
+ }while( pointer < len );
+
+ return argList;
+}
+
+QString KrServices::registerdProtocol(QString mimetype){
+ if( slaveMap == 0 ){
+ slaveMap = new QMap<QString,QString>();
+
+ krConfig->setGroup( "Protocols" );
+ QStringList protList = krConfig->readListEntry( "Handled Protocols" );
+ for( QStringList::Iterator it = protList.begin(); it != protList.end(); it++ ){
+ QStringList mimes = krConfig->readListEntry( QString( "Mimes For %1" ).arg( *it ) );
+ for( QStringList::Iterator it2 = mimes.begin(); it2 != mimes.end(); it2++ )
+ (*slaveMap)[*it2] = *it;
+ }
+
+
+ }
+ return (*slaveMap)[mimetype];
+}
+
+void KrServices::clearProtocolCache()
+{
+ if( slaveMap )
+ delete slaveMap;
+ slaveMap = 0;
+}
+
+bool KrServices::fileToStringList(QTextStream *stream, QStringList& target, bool keepEmptyLines) {
+ if (!stream) return false;
+ QString line;
+ while ( !stream->atEnd() ) {
+ line = stream->readLine().stripWhiteSpace();
+ if (keepEmptyLines || !line.isEmpty()) target.append(line);
+ }
+ return true;
+}
+
+QString KrServices::quote( QString name ) {
+ if( !name.contains( '\'' ) )
+ return "'" + name + "'";
+ if( !name.contains( '"' ) && !name.contains( '$' ) )
+ return "\"" + name + "\"";
+ return escape( name );
+}
+
+QStringList KrServices::quote( const QStringList& names ) {
+ QStringList result;
+ for (unsigned i=0; i<names.size(); ++i)
+ result.append(quote(names[i]));
+ return result;
+}
+
+QString KrServices::escape( QString name ) {
+ const QString evilstuff = "\\\"'`()[]{}!?;$&<>| \t\r\n"; // stuff that should get escaped
+
+ for ( unsigned int i = 0; i < evilstuff.length(); ++i )
+ name.replace( evilstuff[ i ], ('\\' + evilstuff[ i ]) );
+
+ return name;
+}
+
+
+// ------- KEasyProcess
+KEasyProcess::KEasyProcess(QObject *parent, const char *name): KProcess(parent, name) {
+ init();
+}
+
+KEasyProcess::KEasyProcess(): KProcess() {
+ init();
+}
+
+void KEasyProcess::init() {
+ connect(this, SIGNAL(receivedStdout(KProcess *, char *, int)),
+ this, SLOT(receivedStdout(KProcess *, char *, int)));
+ connect(this, SIGNAL(receivedStderr(KProcess *, char *, int)),
+ this, SLOT(receivedStderr(KProcess *, char *, int)));
+}
+
+void KEasyProcess::receivedStdout (KProcess * /* proc */, char *buffer, int buflen) {
+ _stdout+=QString::fromLocal8Bit(buffer, buflen);
+}
+
+void KEasyProcess::receivedStderr (KProcess * /* proc */, char *buffer, int buflen) {
+ _stderr+=QString::fromLocal8Bit(buffer, buflen);
+}
diff --git a/krusader/krservices.h b/krusader/krservices.h
new file mode 100644
index 0000000..d001cf2
--- /dev/null
+++ b/krusader/krservices.h
@@ -0,0 +1,78 @@
+/***************************************************************************
+ krservices.h - description
+ -------------------
+ begin : Thu Aug 8 2002
+ copyright : (C) 2002 by Shie Erlich & Rafi Yanai
+ email :
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KRSERVICES_H
+#define KRSERVICES_H
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qmap.h>
+#include <kprocess.h>
+
+/**
+ *@author Shie Erlich & Rafi Yanai
+ */
+
+class KrServices {
+public:
+ KrServices(){}
+ ~KrServices(){}
+
+ static bool cmdExist(QString cmdName);
+ static QString detectFullPathName( QString name );
+ static QString fullPathName( QString name, QString confName = QString::null );
+ static QStringList separateArgs( QString args );
+ static QString registerdProtocol(QString mimetype);
+ static void clearProtocolCache();
+ static bool fileToStringList(QTextStream *stream, QStringList& target, bool keepEmptyLines=false);
+ static QString quote( QString name );
+ static QStringList quote( const QStringList& names );
+
+protected:
+ static QString escape( QString name );
+
+private:
+ static QMap<QString,QString>* slaveMap;
+
+};
+
+
+// TODO: make KrServices a namespace and move it there
+
+// wraps over kprocess, but buffers stdout and stderr and allows easy access to them later
+// note, that you still have to enable stdout,stderr in KEasyProcess::start() for buffering
+// to happen (ie: start(KEasyProcess::Block, KEasyProcess::AllOutput);)
+class KEasyProcess: public KProcess {
+ Q_OBJECT
+public:
+ KEasyProcess(QObject *parent, const char *name=0);
+ KEasyProcess();
+ virtual ~KEasyProcess() {}
+
+ const QString& getStdout() const { return _stdout; }
+ const QString& getStderr() const { return _stderr; }
+
+protected slots:
+ void receivedStdout (KProcess *proc, char *buffer, int buflen);
+ void receivedStderr (KProcess *proc, char *buffer, int buflen);
+ void init();
+
+private:
+ QString _stdout, _stderr;
+};
+
+#endif
diff --git a/krusader/krslots.cpp b/krusader/krslots.cpp
new file mode 100644
index 0000000..17c8b4b
--- /dev/null
+++ b/krusader/krslots.cpp
@@ -0,0 +1,944 @@
+/***************************************************************************
+ krslots.cpp
+ -------------------
+ copyright : (C) 2001 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <qdir.h>
+#include <qpoint.h>
+#include <qstringlist.h>
+#include <qprogressdialog.h>
+#include <qlistview.h>
+#include <qpixmapcache.h>
+// KDE includes
+#include <klocale.h>
+#include <kprocess.h>
+#include <kmessagebox.h>
+#include <klineeditdlg.h>
+#include <kdirnotify_stub.h>
+#include <kio/netaccess.h>
+#include <kedittoolbar.h>
+#include <kdeversion.h>
+#include <kcmdlineargs.h>
+#include <KViewer/krviewer.h>
+
+#ifdef __KJSEMBED__
+#include "KrJS/krjs.h"
+#include <kjsembed/jsconsolewidget.h>
+#endif
+
+// Krusader includes
+#include "krslots.h"
+#include "krusader.h"
+#include "krusaderview.h"
+#include "Panel/listpanel.h"
+#include "Panel/krselectionmode.h"
+#include "Panel/krdetailedview.h"
+#include "Panel/krdetailedviewitem.h"
+#include "Panel/krbriefview.h"
+#include "Panel/krbriefviewitem.h"
+#include "Dialogs/krdialogs.h"
+#include "Dialogs/krspwidgets.h"
+#include "Dialogs/krkeydialog.h"
+#include "GUI/krusaderstatus.h"
+#include "RemoteMan/remoteman.h"
+#include "Panel/panelfunc.h"
+#include "Konfigurator/konfigurator.h"
+#include "MountMan/kmountman.h"
+#include "defaults.h"
+#include "resources.h"
+#include "GUI/kfnkeys.h"
+#include "GUI/kcmdline.h"
+#include "GUI/syncbrowsebutton.h"
+#include "VFS/krquery.h"
+#include "Search/krsearchmod.h"
+#include "Search/krsearchdialog.h"
+#include "Locate/locate.h"
+#include "VFS/vfs.h"
+#include "panelmanager.h"
+#include "Splitter/splittergui.h"
+#include "Splitter/splitter.h"
+#include "Splitter/combiner.h"
+#include "ActionMan/actionman.h"
+#include "UserMenu/usermenu.h"
+#include "Panel/panelpopup.h"
+#include "Synchronizer/synchronizergui.h"
+#include "DiskUsage/diskusagegui.h"
+#include "krservices.h"
+#include "Panel/krviewitem.h"
+
+#define REFRESH_BOTH_PANELS { ListPanel *p=ACTIVE_PANEL; \
+ MAIN_VIEW->left->func->refresh(); \
+ MAIN_VIEW->right->func->refresh();\
+ p->slotFocusOnMe(); }
+#define ACTIVE_PANEL_MANAGER (ACTIVE_PANEL == krApp->mainView->left ? krApp->mainView->leftMng : \
+ krApp->mainView->rightMng)
+
+void KRslots::sendFileByEmail(QString filename) {
+ QString mailProg;
+ QStringList lst = Krusader::supportedTools();
+ if (lst.contains("MAIL")) mailProg=lst[lst.findIndex("MAIL") + 1];
+ else {
+ KMessageBox::error(0,i18n("Krusader can't find a supported mail client. Please install one to your path. Hint: Krusader supports Kmail."));
+ return;
+ }
+
+ KShellProcess proc;
+
+ if ( vfs::fromPathOrURL( mailProg ).fileName() == "kmail") {
+ proc << "kmail" << "--subject \""+i18n("Sending file: ")+
+ filename.mid(filename.findRev('/')+1)+"\"" << QString::null +
+ "--attach "+"\"" + filename + "\"";
+ }
+
+ if (!proc.start(KProcess::DontCare))
+ KMessageBox::error(0,i18n("Error executing ")+mailProg+" !");
+ else proc.detach();
+}
+
+void KRslots::compareContent() {
+ QStringList lstLeft, lstRight;
+ QStringList* lstActive;
+ KURL name1, name2;
+
+ MAIN_VIEW->left->getSelectedNames( &lstLeft );
+ MAIN_VIEW->right->getSelectedNames( &lstRight );
+ lstActive = ( ACTIVE_PANEL->isLeft() ? &lstLeft : &lstRight );
+
+ if ( lstLeft.count() == 1 && lstRight.count() == 1 ) {
+ // first, see if we've got exactly 1 selected file in each panel:
+ name1 = MAIN_VIEW->left->func->files()->vfs_getFile( lstLeft[0] );
+ name2 = MAIN_VIEW->right->func->files()->vfs_getFile( lstRight[0] );
+ }
+ else if ( lstActive->count() == 2 ) {
+ // next try: are in the current panel exacty 2 files selected?
+ name1 = ACTIVE_PANEL->func->files()->vfs_getFile( (*lstActive)[0] );
+ name2 = ACTIVE_PANEL->func->files()->vfs_getFile( (*lstActive)[1] );
+ }
+ else if ( ACTIVE_PANEL->otherPanel->func->files()->vfs_search( ACTIVE_PANEL->view->getCurrentItem() ) ) {
+ // next try: is in the other panel a file with the same name?
+ name1 = ACTIVE_PANEL->func->files()->vfs_getFile( ACTIVE_PANEL->view->getCurrentItem() );
+ name2 = ACTIVE_PANEL->otherPanel->func->files()->vfs_getFile( ACTIVE_PANEL->view->getCurrentItem() );
+ }
+ else {
+ // if we got here, then we can't be sure what file to diff
+ KMessageBox::detailedError(0, i18n("Don't know which files to compare."), "<qt>" + i18n("To compare two files by content, you can either:<ul><li>Select one file in the left panel, and one in the right panel.</li><li>Select exactly two files in the active panel.</li><li>Make sure there is a file in the other panel, with the same name as the current file in the active panel.</li></ul>") + "</qt>" );
+
+ return;
+ }
+
+ // else implied: all ok, let's call kdiff
+ // but if one of the files isn't local, download them first
+ compareContent( name1, name2 );
+}
+
+class KrProcess: public KProcess
+{
+ QString tmp1, tmp2;
+
+public:
+ KrProcess( QString in1, QString in2 )
+ {
+ tmp1 = in1;
+ tmp2 = in2;
+ }
+
+ virtual void processHasExited (int )
+ {
+ if( !tmp1.isEmpty() )
+ KIO::NetAccess::removeTempFile( tmp1 );
+ if( !tmp2.isEmpty() )
+ KIO::NetAccess::removeTempFile( tmp2 );
+ delete this;
+ }
+};
+
+void KRslots::compareContent( KURL url1, KURL url2 )
+{
+ QString diffProg;
+ QStringList lst = Krusader::supportedTools();
+ if (lst.contains("DIFF")) diffProg=lst[lst.findIndex("DIFF") + 1];
+ else {
+ KMessageBox::error(0,i18n("Krusader can't find any of the supported diff-frontends. Please install one to your path. Hint: Krusader supports Kompare, Kdiff3 and Xxdiff."));
+ return;
+ }
+
+ QString tmp1 = QString::null, tmp2 = QString::null;
+
+ if (!url1.isLocalFile()) {
+ if( !KIO::NetAccess::download( url1, tmp1, 0 ) ){
+ KMessageBox::sorry(krApp,i18n("Krusader is unable to download: ")+url1.fileName());
+ return;
+ }
+ } else tmp1 = url1.path();
+ if (!url2.isLocalFile()) {
+ if( !KIO::NetAccess::download( url2, tmp2, 0 ) ){
+ KMessageBox::sorry(krApp,i18n("Krusader is unable to download: ")+url2.fileName());
+ if( tmp1 != url1.path() )
+ KIO::NetAccess::removeTempFile( tmp1 );
+ return;
+ }
+ } else tmp2 = url2.path();
+
+ KrProcess *p = new KrProcess( tmp1 != url1.path() ? tmp1 : QString::null,
+ tmp2 != url2.path() ? tmp2 : QString::null );
+ *p << diffProg << tmp1 << tmp2;
+ if (!p->start(KProcess::DontCare))
+ KMessageBox::error(0,i18n("Error executing ")+diffProg+" !");
+}
+
+void KRslots::rightclickMenu() {
+ if( dynamic_cast<KrDetailedView*>(ACTIVE_PANEL->view) != 0 )
+ {
+ QListViewItem * currentItem = dynamic_cast<QListViewItem*>(ACTIVE_PANEL->view->getCurrentKrViewItem());
+ if( currentItem )
+ {
+ ACTIVE_PANEL->popRightClickMenu(
+ ACTIVE_PANEL->mapToGlobal(
+ dynamic_cast<KListView*>(ACTIVE_PANEL->view)->itemRect( currentItem ).topLeft()
+ )
+ );
+ }
+ }
+ else if( dynamic_cast<KrBriefView*>(ACTIVE_PANEL->view) != 0 )
+ {
+ QIconViewItem * currentItem = dynamic_cast<QIconViewItem*>(ACTIVE_PANEL->view->getCurrentKrViewItem());
+ if( currentItem )
+ {
+ ACTIVE_PANEL->popRightClickMenu(
+ ACTIVE_PANEL->mapToGlobal(
+ currentItem->rect().topLeft()
+ )
+ );
+ }
+ }
+}
+
+void KRslots::addBookmark(){
+ // TODO: this no longer works!
+}
+
+// GUI toggle slots
+void KRslots::toggleFnkeys(){
+ if( MAIN_VIEW->fnKeys->isVisible() ) MAIN_VIEW->fnKeys->hide();
+ else MAIN_VIEW->fnKeys->show();
+}
+
+void KRslots::toggleCmdline(){
+ if( MAIN_VIEW->cmdLine->isVisible() ) MAIN_VIEW->cmdLine->hide();
+ else MAIN_VIEW->cmdLine->show();
+}
+
+void KRslots::toggleToolbar() {
+ if (krApp->toolBar()->isVisible())
+ krApp->toolBar()->hide();
+ else krApp->toolBar()->show();
+}
+
+void KRslots::toggleActionsToolbar() {
+ if (krApp->toolBar("actionsToolBar")->isVisible())
+ krApp->toolBar("actionsToolBar")->hide();
+ else krApp->toolBar("actionsToolBar")->show();
+}
+
+
+void KRslots::toggleStatusbar() {
+ if (krApp->statusBar()->isVisible())
+ krApp->statusBar()->hide();
+ else krApp->statusBar()->show();
+}
+
+void KRslots::toggleTerminal() {
+ if( MAIN_VIEW->terminal_dock->isVisible() ) MAIN_VIEW->slotTerminalEmulator(false);
+ else MAIN_VIEW->slotTerminalEmulator(true);
+}
+
+void KRslots::insertFileName(bool full_path)
+{
+ QString filename = ACTIVE_PANEL->view->getCurrentItem();
+ if( filename == QString::null )
+ return;
+
+ if( full_path ){
+ QString path=vfs::pathOrURL( ACTIVE_FUNC->files()->vfs_getOrigin(), 1 );
+ filename = path+filename;
+ }
+
+ filename = KrServices::quote( filename );
+
+ if(MAIN_VIEW->cmdLine->isVisible() || !MAIN_VIEW->konsole_part || !MAIN_VIEW->konsole_part->widget() ||
+ !MAIN_VIEW->konsole_part->widget()->isVisible() ){
+ QString current = MAIN_VIEW->cmdLine->text();
+ if( current.length() != 0 && !current.endsWith( " " ) )
+ current += " ";
+ MAIN_VIEW->cmdLine->setText( current + filename );
+ MAIN_VIEW->cmdLine->setFocus();
+ }
+ else if(MAIN_VIEW->konsole_part){
+ filename = QString( " " ) + filename + QString( " " );
+ QKeyEvent keyEvent( QEvent::KeyPress, 0, -1, 0, filename);
+ QApplication::sendEvent( MAIN_VIEW->konsole_part->widget(), &keyEvent );
+ MAIN_VIEW->konsole_part->widget()->setFocus();
+ }
+}
+
+// directory list functions
+void KRslots::allFilter() { ACTIVE_PANEL->setFilter(KrViewProperties::All); }
+void KRslots::execFilter() { ACTIVE_PANEL->setFilter(KrViewProperties::All); }
+void KRslots::customFilter() { ACTIVE_PANEL->setFilter(KrViewProperties::Custom); }
+void KRslots::markAll() { ACTIVE_PANEL->select(true,true); }
+void KRslots::unmarkAll() { ACTIVE_PANEL->select(false,true); }
+void KRslots::markGroup() { ACTIVE_PANEL->select(true,false); }
+void KRslots::markGroup(const QString& mask, bool select) { ACTIVE_PANEL->select( KRQuery( mask ), select); }
+void KRslots::unmarkGroup() { ACTIVE_PANEL->select(false,false); }
+void KRslots::invert() { ACTIVE_PANEL->invertSelection(); }
+
+void KRslots::root() { ACTIVE_FUNC->openUrl(vfs::fromPathOrURL("/"));}
+void KRslots::refresh(const KURL& u){ ACTIVE_FUNC->openUrl(u); }
+void KRslots::home() { ACTIVE_FUNC->openUrl(QDir::homeDirPath()); }
+void KRslots::refresh() { ACTIVE_FUNC->refresh(); }
+void KRslots::properties() { ACTIVE_FUNC->properties(); }
+void KRslots::dirUp() { ACTIVE_FUNC->dirUp(); }
+void KRslots::back() { ACTIVE_FUNC->goBack(); }
+void KRslots::slotPack() { ACTIVE_FUNC->pack(); }
+void KRslots::slotUnpack() { ACTIVE_FUNC->unpack(); }
+void KRslots::testArchive() { ACTIVE_FUNC->testArchive(); }
+void KRslots::calcSpace() { ACTIVE_FUNC->calcSpace(); }
+void KRslots::FTPDisconnect() { ACTIVE_FUNC->FTPDisconnect(); }
+void KRslots::newFTPconnection(){ ACTIVE_FUNC->newFTPconnection(); }
+void KRslots::cut() { ACTIVE_FUNC->copyToClipboard( true ); }
+void KRslots::copy() { ACTIVE_FUNC->copyToClipboard( false ); }
+void KRslots::paste() { ACTIVE_FUNC->pasteFromClipboard(); }
+void KRslots::createChecksum() { ACTIVE_FUNC->createChecksum(); }
+void KRslots::matchChecksum() { ACTIVE_FUNC->matchChecksum(); }
+
+// run external modules / programs
+void KRslots::runKonfigurator(bool firstTime) {
+
+ krConfig->setGroup( "Look&Feel" );
+ int size = (krConfig->readEntry("Filelist Icon Size",_FilelistIconSize)).toInt();
+
+ Konfigurator *konfigurator = new Konfigurator(firstTime);
+
+ if( konfigurator->isGUIRestartNeeded() )
+ {
+ krConfig->setGroup( "Look&Feel" );
+ if((krConfig->readEntry("Filelist Icon Size",_FilelistIconSize)).toInt() != size )
+ QPixmapCache::clear();
+
+ KrDetailedViewItem::itemHeightChanged(); // needed when icon size / font size changes
+ KrBriefViewItem::itemHeightChanged();
+
+ MAIN_VIEW->leftMng->slotRecreatePanels();
+ MAIN_VIEW->rightMng->slotRecreatePanels();
+ MAIN_VIEW->fnKeys->updateShortcuts();
+ KrSelectionMode::resetSelectionHandler();
+ }
+
+ krApp->configChanged();
+ delete konfigurator;
+}
+
+void KRslots::setDetailedView() {
+ if( ACTIVE_PANEL && ACTIVE_PANEL->getType() != "Detailed" )
+ ACTIVE_PANEL->changeType( "Detailed" );
+}
+
+void KRslots::setBriefView() {
+ if( ACTIVE_PANEL && ACTIVE_PANEL->getType() != "Brief" )
+ ACTIVE_PANEL->changeType( "Brief" );
+}
+
+void KRslots::toggleHidden(){
+ krConfig->setGroup("Look&Feel");
+ bool show = !krConfig->readBoolEntry("Show Hidden",_ShowHidden);
+ krApp->actToggleHidden->setChecked(show);
+ krConfig->writeEntry("Show Hidden",show);
+
+ MAIN_VIEW->leftMng->refreshAllTabs( true );
+ MAIN_VIEW->rightMng->refreshAllTabs( true );
+}
+
+void KRslots::swapPanels(){
+ KURL leftURL = MAIN_VIEW->left->func->files()->vfs_getOrigin();
+ KURL rightURL = MAIN_VIEW->right->func->files()->vfs_getOrigin();
+
+ MAIN_VIEW->left->func->openUrl( rightURL );
+ MAIN_VIEW->right->func->openUrl( leftURL );
+}
+
+void KRslots::toggleSwapSides(){
+ QValueList<int> lst = MAIN_VIEW->horiz_splitter->sizes();
+
+ MAIN_VIEW->horiz_splitter->moveToLast( MAIN_VIEW->leftMng );
+
+ int old = lst[ 0 ];
+ lst[ 0 ] = lst [ 1 ];
+ lst[ 1 ] = old;
+
+ MAIN_VIEW->horiz_splitter->setSizes( lst );
+
+ ListPanel *tmpPanel; // temporary variables for swapping
+ PanelManager *tmpMng;
+
+ tmpMng = MAIN_VIEW->leftMng;
+ MAIN_VIEW->leftMng = MAIN_VIEW->rightMng;
+ MAIN_VIEW->rightMng = tmpMng;
+
+ tmpPanel = MAIN_VIEW->left;
+ MAIN_VIEW->left = MAIN_VIEW->right;
+ MAIN_VIEW->right = tmpPanel;
+
+ MAIN_VIEW->leftMng->swapPanels();
+ MAIN_VIEW->rightMng->swapPanels();
+
+ MAIN_VIEW->left->updateGeometry();
+ MAIN_VIEW->right->updateGeometry();
+}
+
+void KRslots::search() {
+ if ( KrSearchDialog::SearchDialog != 0 ) {
+ krConfig->setGroup( "Search" );
+ if( krConfig->readBoolEntry( "Window Maximized", false ) )
+ KrSearchDialog::SearchDialog->showMaximized();
+ else
+ KrSearchDialog::SearchDialog->showNormal();
+
+ KrSearchDialog::SearchDialog->raise();
+ KrSearchDialog::SearchDialog->setActiveWindow();
+ } else
+ KrSearchDialog::SearchDialog = new KrSearchDialog();
+}
+
+void KRslots::locate()
+{
+ if( !KrServices::cmdExist( "locate" ) )
+ {
+ KMessageBox::error(krApp, i18n( "Can't find the 'locate' command. Please install the "
+ "findutils-locate package of GNU, or set its dependencies in "
+ "Konfigurator" ));
+ return;
+ }
+
+ if ( LocateDlg::LocateDialog != 0 ) {
+ LocateDlg::LocateDialog->showNormal();
+ LocateDlg::LocateDialog->raise();
+ LocateDlg::LocateDialog->setActiveWindow();
+ LocateDlg::LocateDialog->reset();
+ } else
+ LocateDlg::LocateDialog = new LocateDlg();
+}
+
+void KRslots::runRemoteMan() {
+ // display outage information
+ KMessageBox::information(krApp, i18n( "Important: RemoteMan has been replaced by our new bookmark manager. "
+ "The new manager handles local files and remote URLs the same way. "
+ "RemoteMan is being left around to allow an easier transition and "
+ "give you a chance to move your bookmarks. IT WILL BE REMOVED SOON!"
+ "\n"
+ "Try the new bookmark-manager: open a new remote connection, once "
+ "done, press the bookmark button, select 'Add bookmark' and that's it!"));
+
+ QString host=remoteMan::getHost();
+ if (host==QString::null) return;
+ // otherwise, attempt a connection
+ ACTIVE_FUNC->openUrl(vfs::fromPathOrURL(host));
+}
+
+void KRslots::runMountMan() {
+ // left as a precaution, although we use kde's services now
+ if( !KrServices::cmdExist( "df" ) || !KrServices::cmdExist( "mount" ) )
+ {
+ KMessageBox::error(0,
+ i18n("Can't start 'mount'! Check the 'Dependencies' page in konfigurator."));
+ return;
+ }
+
+ krApp->mountMan->mainWindow();
+}
+
+void KRslots::homeTerminal(){
+ QString save = getcwd(0,0);
+ chdir (QDir::homeDirPath().local8Bit());
+
+ KProcess proc;
+ krConfig->setGroup("General");
+ QString term = krConfig->readEntry("Terminal",_Terminal);
+ proc << KrServices::separateArgs( term );
+
+ if( term.contains( "konsole" ) ) /* KDE 3.2 bug (konsole is killed by pressing Ctrl+C) */
+ { /* Please remove the patch if the bug is corrected */
+ proc << "&";
+ proc.setUseShell( true );
+ }
+
+ if(!proc.start(KProcess::DontCare))
+ KMessageBox::sorry(krApp,i18n("Can't open ")+"\""+term+"\"");
+
+ chdir(save.local8Bit());
+}
+
+void KRslots::sysInfo(){
+ KProcess proc;
+ proc << "kcmshell" << "System/ksysctrl";
+ if (!proc.start(KProcess::DontCare)){
+ KMessageBox::sorry(krApp,i18n("Can't find \"KsysCtrl\". Please install KDE admin package"));
+ }
+}
+
+void KRslots::multiRename(){
+ QStringList lst = Krusader::supportedTools();
+ int i = lst.findIndex("RENAME");
+ if (i == -1){
+ KMessageBox::sorry(krApp,i18n("Can't find a batch rename tool.\nYou can get Krename at http://www.krename.net"));
+ return;
+ }
+ QString pathToRename = lst[i+1];
+
+ QStringList names;
+ ((ListPanel*)ACTIVE_PANEL)->getSelectedNames(&names);
+ KURL::List* urls = ACTIVE_FUNC->files()->vfs_getFiles(&names);
+
+ if( urls->isEmpty() ){
+ delete urls;
+ return;
+ }
+
+ KShellProcess proc;
+ proc << pathToRename;
+
+ for( KURL::List::iterator u=urls->begin(); u != urls->end(); ++u){
+ if( QFileInfo((*u).path()).isDir() ) proc << "-r";
+ proc << "\"" + (*u).path() + "\""; // patch thanks to Tobias Vogele
+ }
+
+ proc.start(KProcess::DontCare);
+ delete urls;
+}
+
+void KRslots::rootKrusader()
+{
+ if( !KrServices::cmdExist( "krusader" ) || !KrServices::cmdExist( "kdesu" ) )
+ {
+ KMessageBox::sorry( krApp, i18n( "Can't start root mode krusader, because krusader or kdesu is missing from the path. Please configure the dependencies in Konfigurator!" ) );
+ return;
+ }
+
+ KShellProcess proc;
+ proc << KrServices::fullPathName( "kdesu" ) << QString("'") + KrServices::fullPathName( "krusader" ) +
+ " --left=\"" +MAIN_VIEW->left->func->files()->vfs_getOrigin().url() +
+ "\" --right=\""+MAIN_VIEW->right->func->files()->vfs_getOrigin().url() + "\"'";
+
+ proc.start(KProcess::DontCare);
+}
+
+// settings slots
+void KRslots::configToolbar(){
+ KEditToolbar dlg(krApp->factory());
+ if (dlg.exec()) krApp->updateGUI();
+}
+
+void KRslots::configKeys(){
+ KrKeyDialog( MAIN_VIEW );
+}
+
+// misc
+void KRslots::changeTrashIcon(){
+ // update trash bin icon - this is "stolen" konqi code
+ // Copyright (C) 2000 David Faure <faure@kde.org>
+ KURL trash;
+ trash.setPath(KGlobalSettings::trashPath());
+ KURL::List lst;
+ lst.append(trash);
+ KDirNotify_stub allDirNotify("*","KDirNotify*");
+ allDirNotify.FilesChanged( lst );
+ // end of konqi code
+}
+
+// F2
+void KRslots::terminal() { ACTIVE_FUNC->terminal(); }
+// F3
+void KRslots::view() { ACTIVE_FUNC->view(); }
+// F4
+void KRslots::edit() { ACTIVE_FUNC->editFile(); }
+// F5
+void KRslots::copyFiles() { ACTIVE_FUNC->copyFiles(); }
+// F6
+void KRslots::moveFiles() { ACTIVE_FUNC->moveFiles(); }
+// F7
+void KRslots::mkdir() { ACTIVE_FUNC->mkdir(); }
+// F8
+void KRslots::deleteFiles(bool reallyDelete) { ACTIVE_FUNC->deleteFiles(reallyDelete);}
+// F9
+void KRslots::rename() { ACTIVE_FUNC->rename(); }
+
+// Shift F3
+void KRslots::viewDlg(){
+ // ask the user for a url to view
+ KURL dest = KChooseDir::getDir(i18n("Enter a URL to view:"), ACTIVE_PANEL->virtualPath(), ACTIVE_PANEL->virtualPath());
+ if ( dest.isEmpty() ) return ; // the user canceled
+
+ KrViewer::view( dest ); // view the file
+// }
+ // nothing more to it!
+}
+
+// Shift F4
+void KRslots::editDlg(){
+ // ask the user for the filename to edit
+ KURL dest = KChooseDir::getDir(i18n("Enter the filename to edit:"), ACTIVE_PANEL->virtualPath(), ACTIVE_PANEL->virtualPath());
+ if ( dest.isEmpty() ) return ; // the user canceled
+
+ KrViewer::edit( dest );
+
+ if( dest.upURL().equals( ACTIVE_PANEL->virtualPath(), true ) )
+ refresh();
+}
+
+void KRslots::duplicateTab() {
+ ACTIVE_PANEL_MANAGER->slotNewTab(ACTIVE_PANEL->virtualPath());
+}
+
+// ugly: do this right before release!
+void KRslots::newTab(const KURL& url) {
+ if (url.isValid())
+ ACTIVE_PANEL_MANAGER->slotNewTab(url);
+ else ACTIVE_PANEL_MANAGER->slotNewTab();
+}
+
+void KRslots::nextTab() {
+ ACTIVE_PANEL_MANAGER->slotNextTab();
+}
+
+void KRslots::previousTab() {
+ ACTIVE_PANEL_MANAGER->slotPreviousTab();
+}
+
+void KRslots::newTab(KrViewItem *it) {
+ if (!it) return;
+ if( it->name() == ".." ) {
+ KURL url = ACTIVE_PANEL->virtualPath();
+ ACTIVE_PANEL_MANAGER->slotNewTab( url.upURL() );
+ }
+ else if (ITEM2VFILE(ACTIVE_PANEL, it)->vfile_isDir()) {
+ KURL url = ACTIVE_PANEL->virtualPath();
+ url.addPath( it->name() );
+ ACTIVE_PANEL_MANAGER->slotNewTab( url );
+ }
+}
+
+void KRslots::closeTab() {
+ ACTIVE_PANEL_MANAGER->slotCloseTab();
+}
+
+void KRslots::slotSplit()
+{
+ QStringList list;
+ QString name;
+
+ ((ListPanel*)ACTIVE_PANEL)->getSelectedNames(&list);
+
+ // first, see if we've got exactly 1 selected file, if not, try the current one
+ if (list.count() == 1) name = list[0];
+
+ if ( name.isEmpty() ) {
+ // if we got here, then one of the panel can't be sure what file to diff
+ KMessageBox::error(0,i18n("Don't know which file to split."));
+ return;
+ }
+
+ KURL fileURL = ACTIVE_FUNC->files()->vfs_getFile(name);
+ if( fileURL.isEmpty() )
+ return;
+
+ if ( ACTIVE_FUNC->files()->vfs_search( name )->vfile_isDir() ) {
+ KMessageBox::sorry( krApp, i18n( "You can't split a directory!" ) );
+ return ;
+ }
+
+ KURL destDir = ACTIVE_PANEL->otherPanel->func->files()->vfs_getOrigin();
+
+ SplitterGUI splitterGUI( MAIN_VIEW, fileURL, destDir );
+
+ if( splitterGUI.result() == QDialog::Accepted )
+ {
+ bool splitToOtherPanel = ( splitterGUI.getDestinationDir().equals( ACTIVE_PANEL->otherPanel->virtualPath(), true ) );
+
+ Splitter split( MAIN_VIEW, fileURL, splitterGUI.getDestinationDir() );
+ split.split( splitterGUI.getSplitSize() );
+
+ if ( splitToOtherPanel )
+ ACTIVE_PANEL->otherPanel->func->refresh();
+ }
+}
+
+void KRslots::slotCombine(){
+ QStringList list;
+ KURL baseURL;
+ bool unixStyle = false;
+ bool windowsStyle = false;
+ QString commonName = QString::null;
+ unsigned int commonLength = 0;
+
+ ((ListPanel*)ACTIVE_PANEL)->getSelectedNames(&list);
+ if ( list.isEmpty() )
+ {
+ KMessageBox::error(0,i18n("Don't know which files to combine."));
+ return;
+ }
+
+ /* checking splitter names */
+ for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it )
+ {
+ KURL url = ACTIVE_FUNC->files()->vfs_getFile(*it);
+ if( url.isEmpty() )
+ return;
+
+ if ( ACTIVE_FUNC->files()->vfs_search( *it )->vfile_isDir() ) {
+ KMessageBox::sorry( krApp, i18n( "You can't combine a directory!" ) );
+ return ;
+ }
+
+ if( !unixStyle )
+ {
+ QString name = url.fileName();
+ int extPos = name.findRev( '.' );
+ QString ext = name.mid( extPos + 1 );
+ name.truncate( extPos );
+ url.setFileName( name );
+
+ bool isExtInt;
+ ext.toInt( &isExtInt, 10 );
+
+ if( extPos < 1 || ext.isEmpty() || ( ext != "crc" && !isExtInt ) )
+ {
+ if( windowsStyle )
+ {
+ KMessageBox::error(0,i18n("Not a split file %1!").arg( vfs::pathOrURL( url ) ));
+ return;
+ }
+ unixStyle = true;
+ }
+ else
+ {
+
+ if( ext != "crc" )
+ windowsStyle = true;
+
+ if( baseURL.isEmpty() )
+ baseURL = url;
+ else if( baseURL != url )
+ {
+ KMessageBox::error(0,i18n("Select only one split file!"));
+ return;
+ }
+ }
+ }
+
+ if( unixStyle )
+ {
+ bool error = true;
+
+ do
+ {
+ QString shortName = *it;
+ QChar lastChar = shortName.at( shortName.length()-1 );
+
+ if( lastChar.isLetter() )
+ {
+ char fillLetter = ( lastChar.upper() == lastChar ) ? 'A' : 'a';
+
+ if( commonName.isNull() )
+ {
+ commonLength = shortName.length();
+ commonName = shortName;
+
+ while ( commonName.length() )
+ {
+ QString shorter = commonName.left( commonName.length() - 1 );
+ QString testFile = shorter.leftJustify( commonLength, fillLetter );
+
+ if( ACTIVE_FUNC->files()->vfs_search( testFile ) == 0 )
+ break;
+ else
+ {
+ commonName = shorter;
+ baseURL = ACTIVE_FUNC->files()->vfs_getOrigin();
+ baseURL.addPath( testFile );
+ }
+ }
+
+ error = ( commonName == shortName );
+ }
+ else if( commonLength == shortName.length() && shortName.startsWith( commonName ) )
+ error = false;
+ }
+ }while ( false );
+
+ if( error )
+ {
+ KMessageBox::error(0,i18n("Not a splitted file %1!").arg( vfs::pathOrURL( url ) ));
+ return;
+ }
+ }
+ }
+
+ // ask the user for the copy dest
+ KURL dest = KChooseDir::getDir(i18n("Combining %1.* to directory:" ).arg( vfs::pathOrURL( baseURL ) ),
+ ACTIVE_PANEL->otherPanel->virtualPath(), ACTIVE_PANEL->virtualPath());
+ if ( dest.isEmpty() ) return ; // the user canceled
+
+ bool combineToOtherPanel = ( dest.equals( ACTIVE_PANEL->otherPanel->virtualPath(), true ) );
+
+ Combiner combine( MAIN_VIEW, baseURL, dest, unixStyle );
+ combine.combine();
+
+ if ( combineToOtherPanel )
+ ACTIVE_PANEL->otherPanel->func->refresh();
+}
+
+void KRslots::userMenu() {
+ //UserMenu um;
+ //um.exec();
+ krApp->userMenu->exec();
+}
+
+void KRslots::manageUseractions() {
+ ActionMan actionMan( MAIN_VIEW );
+}
+
+void KRslots::slotSynchronizeDirs( QStringList selected ) {
+ new SynchronizerGUI( 0, MAIN_VIEW->left->func->files()->vfs_getOrigin(),
+ MAIN_VIEW->right->func->files()->vfs_getOrigin(), selected );
+}
+
+void KRslots::slotSyncBrowse() {
+ ACTIVE_PANEL->syncBrowseButton->toggle();
+}
+
+void KRslots::updatePopupPanel(KrViewItem *item) {
+ // which panel to display on?
+ ListPanel *lp = 0;
+ if (ACTIVE_PANEL->popup->isHidden() &&
+ ACTIVE_PANEL->otherPanel->popup->isHidden()) return;
+ if (ACTIVE_PANEL->popup->isShown())
+ lp = ACTIVE_PANEL;
+ else if (ACTIVE_PANEL->otherPanel->popup->isShown())
+ lp = ACTIVE_PANEL->otherPanel;
+
+ KURL url;
+ if (item->name()!="..") // updir
+ url = ACTIVE_FUNC->files()->vfs_getFile(item->name());
+ lp->popup->update(url);
+}
+
+void KRslots::compareDirs()
+{
+ ACTIVE_PANEL->compareDirs();
+ ACTIVE_PANEL->otherPanel->compareDirs();
+}
+
+void KRslots::compareSetup()
+{
+ for( int i=0; Krusader::compareArray[i] != 0; i++ )
+ if( (*Krusader::compareArray[i])->isChecked() )
+ {
+ krConfig->setGroup( "Private" );
+ krConfig->writeEntry( "Compare Mode", i );
+ break;
+ }
+}
+
+/** called by actions actExec* to choose the built-in command line mode */
+void KRslots::execTypeSetup()
+{
+ for( int i=0; Krusader::execTypeArray[i] != 0; i++ )
+ if( (*Krusader::execTypeArray[i])->isChecked() )
+ {
+ if( *Krusader::execTypeArray[i] == Krusader::actExecTerminalEmbedded ){
+ // if commands are to be executed in the TE, it must be loaded
+ MAIN_VIEW->createTE();
+ }
+ KConfigGroup grp(krConfig, "Private" );
+ grp.writeEntry( "Command Execution Mode", i );
+ break;
+ }
+}
+
+void KRslots::togglePopupPanel() {
+ ACTIVE_PANEL->togglePanelPopup();
+}
+
+void KRslots::slotDiskUsage()
+{
+ DiskUsageGUI du( ACTIVE_FUNC->files()->vfs_getOrigin(), MAIN_VIEW, "DiskUsage" );
+}
+
+// when window becomes focused, enable the refresh in the visible panels
+void KRslots::windowActive() {
+ if( MAIN_VIEW != 0 ) { /* CRASH FIX: it's possible that the method is called after destroying the main view */
+ MAIN_VIEW->left->panelActive();
+ MAIN_VIEW->right->panelActive();
+ }
+}
+
+// when another application becomes focused, do a windows-commander style refresh: don't
+// refresh at all until krusader becomes focused again
+void KRslots::windowInactive() {
+ if( MAIN_VIEW != 0 ) { /* CRASH FIX: it's possible that the method is called after destroying the main view */
+ MAIN_VIEW->left->panelInactive();
+ MAIN_VIEW->right->panelInactive();
+ }
+}
+
+void KRslots::slotLocationBar() {
+ ACTIVE_PANEL->origin->lineEdit()->selectAll();
+ ACTIVE_PANEL->origin->setFocus();
+}
+
+void KRslots::slotJumpBack() {
+ ACTIVE_PANEL->jumpBack();
+}
+
+void KRslots::slotSetJumpBack() {
+ ACTIVE_PANEL->setJumpBack( ACTIVE_PANEL->virtualPath() );
+}
+
+//shows the JavaScript-Console
+void KRslots::jsConsole() {
+#ifdef __KJSEMBED__
+ if ( ! krJS )
+ krJS = new KrJS();
+ krJS->view()->show();
+#endif
+}
+
+void KRslots::bookmarkCurrent() {
+ krBookMan->bookmarkCurrent(ACTIVE_PANEL->virtualPath());
+}
+
+#include "krslots.moc"
diff --git a/krusader/krslots.h b/krusader/krslots.h
new file mode 100644
index 0000000..293279c
--- /dev/null
+++ b/krusader/krslots.h
@@ -0,0 +1,187 @@
+/***************************************************************************
+ krslots.h
+ -------------------
+ copyright : (C) 2001 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+ Description
+***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+
+
+#ifndef KRSLOTS_H
+#define KRSLOTS_H
+
+#include <qobject.h>
+// the 2 following #includes should go away with the ugly stubs on the bottom
+#include "krusader.h"
+#include "krusaderview.h"
+#include "Panel/listpanel.h"
+#include "Panel/panelfunc.h"
+#include "BookMan/krbookmarkbutton.h"
+#include "GUI/kcmdline.h"
+#include "GUI/dirhistorybutton.h"
+#include "GUI/mediabutton.h"
+
+class ListPanel;
+class KURL;
+
+class KRslots : public QObject {
+ Q_OBJECT
+
+ public:
+ enum compareMode { full } ;
+
+ KRslots(QObject *parent): QObject(parent, "KRslots") {}
+ ~KRslots() {}
+
+ public slots:
+ void createChecksum();
+ void matchChecksum();
+ void sendFileByEmail( QString filename );
+ void compareContent();
+ void compareContent( KURL, KURL );
+ void rightclickMenu();
+ void insertFileName(bool full_path);
+ void rootKrusader();
+ void swapPanels();
+ void setBriefView();
+ void setDetailedView();
+ void toggleHidden();
+ void toggleSwapSides();
+ void togglePopupPanel();
+ void configToolbar();
+ void configKeys();
+ void toggleToolbar();
+ void toggleActionsToolbar();
+ void toggleStatusbar();
+ void toggleTerminal();
+ void home();
+ void root();
+ void dirUp();
+ void markAll();
+ void unmarkAll();
+ void markGroup();
+ void markGroup(const QString &, bool select);
+ void unmarkGroup();
+ void invert();
+ void compareDirs();
+ void compareSetup();
+ /** called by actExec* actions to choose the built-in command line mode */
+ void execTypeSetup();
+ void refresh();
+ void refresh( const KURL& u );
+ void properties();
+ void back();
+ void slotPack();
+ void slotUnpack();
+ void cut();
+ void copy();
+ void paste();
+ void testArchive();
+ void calcSpace();
+ void FTPDisconnect();
+ void allFilter();
+ void execFilter();
+ void customFilter();
+ void newFTPconnection();
+ void runKonfigurator( bool firstTime = false );
+ void startKonfigurator() { runKonfigurator( false ); }
+ void search(); // call the search module
+ void locate();
+ void homeTerminal();
+ void sysInfo();
+ void addBookmark();
+ void runMountMan();
+ void runRemoteMan();
+ void toggleFnkeys();
+ void toggleCmdline();
+ void changeTrashIcon();
+ void multiRename();
+ void openRightBookmarks() { RIGHT_PANEL->slotFocusOnMe(); RIGHT_PANEL->bookmarksButton->openPopup(); }
+ void openLeftBookmarks() { LEFT_PANEL->slotFocusOnMe(); LEFT_PANEL->bookmarksButton->openPopup(); }
+ void openBookmarks() { ACTIVE_PANEL->bookmarksButton->openPopup(); }
+ void bookmarkCurrent();
+ void openHistory() { ACTIVE_PANEL->historyButton->openPopup(); }
+ void openLeftHistory() { LEFT_PANEL->historyButton->openPopup(); }
+ void openRightHistory() { RIGHT_PANEL->historyButton->openPopup(); }
+ void openMedia() { ACTIVE_PANEL->mediaButton->openPopup(); }
+ void openLeftMedia() { LEFT_PANEL->mediaButton->openPopup(); }
+ void openRightMedia() { RIGHT_PANEL->mediaButton->openPopup(); }
+ void syncPanels() {
+ ListPanel *t = ACTIVE_PANEL;
+ OTHER_FUNC->openUrl(ACTIVE_PANEL->virtualPath());
+ t->slotFocusOnMe();
+ }
+ void cmdlinePopup() { MAIN_VIEW->cmdLine->popup(); }
+ void duplicateTab();
+ void newTab(const KURL& url = KURL());
+ void newTab(KrViewItem *item);
+ void closeTab();
+ void nextTab();
+ void previousTab();
+ void slotSplit();
+ void slotCombine();
+ void userMenu();
+ void manageUseractions();
+ void slotSynchronizeDirs( QStringList selected = QStringList() );
+ void slotSyncBrowse();
+ void slotDiskUsage();
+ void slotLocationBar();
+ void slotJumpBack();
+ void slotSetJumpBack();
+ void newSymlink() { ACTIVE_PANEL->func->krlink(true); }
+ void updatePopupPanel(KrViewItem *);
+ void windowActive(); // called when krusader's window becomes focussed
+ void windowInactive(); // called when another application steals the focus
+ // F2
+ void terminal();
+ // F3
+ void view();
+ // Shift F3
+ void viewDlg();
+ // F4
+ void edit();
+ // Shift F4
+ void editDlg();
+ // F5
+ void copyFiles();
+ // F6
+ void moveFiles();
+ // F7
+ void mkdir();
+ // F8
+ void deleteFiles(bool reallyDelete=false);
+ // F9
+ void rename();
+
+ // ugly stubs, remove later ?
+ void slotCurrentChanged( QString p ) { MAIN_VIEW->slotCurrentChanged( p ); }
+ void slotSetActivePanel( ListPanel *p ) { MAIN_VIEW->slotSetActivePanel( p ); }
+
+
+ void jsConsole();
+};
+
+#endif
diff --git a/krusader/krusader.cpp b/krusader/krusader.cpp
new file mode 100644
index 0000000..430beff
--- /dev/null
+++ b/krusader/krusader.cpp
@@ -0,0 +1,1248 @@
+/***************************************************************************
+ krusader.cpp
+ -------------------
+copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+e-mail : krusader@users.sourceforge.net
+web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+Description
+***************************************************************************
+
+A
+
+db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <unistd.h>
+#ifdef BSD
+#include <sys/types.h>
+#endif
+// KDE includes
+#include <kmessagebox.h>
+#include <kaction.h>
+#include <kcursor.h>
+#include <ksystemtray.h>
+#include <kmenubar.h>
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kaccelmanager.h>
+#include <kwin.h>
+
+#if KDE_IS_VERSION(3,2,0)
+#include <kactionclasses.h>
+#endif
+
+#include <kdeversion.h>
+// QT includes
+#include <qpixmap.h>
+#include <qstringlist.h>
+#include <qdir.h>
+#include <qprinter.h>
+#include <qprogressdialog.h>
+#include <qvaluelist.h>
+#include <qwhatsthis.h>
+#include <qwidgetlist.h>
+#include <qdatetime.h>
+#include <dcopclient.h>
+// Krusader includes
+#include "krusader.h"
+#include "kicons.h"
+#include "VFS/krpermhandler.h"
+#include "GUI/krusaderstatus.h"
+#include "RemoteMan/remoteman.h"
+#include "Dialogs/krpleasewait.h"
+#include "krusaderview.h"
+#include "Panel/listpanel.h"
+#include "Panel/panelfunc.h"
+#include "Konfigurator/konfigurator.h"
+#include "Konfigurator/kgprotocols.h"
+#include "MountMan/kmountman.h"
+#include "Panel/panelpopup.h"
+#include "Queue/queue_mgr.h"
+#include "defaults.h"
+#include "resources.h"
+#include "GUI/kfnkeys.h"
+#include "GUI/kcmdline.h"
+#include "krslots.h"
+#include "krservices.h"
+#include "UserAction/useraction.h"
+// This makes gcc-4.1 happy. Warning about possible problem with KrAction's dtor not called
+#include "UserAction/kraction.h"
+#include "UserAction/expander.h"
+#include "UserMenu/usermenu.h"
+#include "panelmanager.h"
+#include "MountMan/kmountman.h"
+#include "BookMan/krbookmarkhandler.h"
+#include "Dialogs/popularurls.h"
+#include "GUI/krremoteencodingmenu.h"
+#include "Dialogs/checksumdlg.h"
+
+#ifdef __KJSEMBED__
+#include "KrJS/krjs.h"
+#endif
+
+// define the static members
+Krusader *Krusader::App = 0;
+KAction *Krusader::actProperties = 0;
+KAction *Krusader::actPack = 0;
+KAction *Krusader::actUnpack = 0;
+KAction *Krusader::actTest = 0;
+KAction *Krusader::actCopy = 0;
+KAction *Krusader::actPaste = 0;
+KAction *Krusader::actCompare = 0;
+KAction *Krusader::actCalculate = 0;
+KAction *Krusader::actCreateChecksum = 0;
+KAction *Krusader::actMatchChecksum = 0;
+KAction *Krusader::actSelect = 0;
+KAction *Krusader::actSelectAll = 0;
+KAction *Krusader::actUnselect = 0;
+KAction *Krusader::actUnselectAll = 0;
+KAction *Krusader::actInvert = 0;
+KAction *Krusader::actCompDirs = 0;
+KAction *Krusader::actSync = 0;
+KAction *Krusader::actDiskUsage = 0;
+KAction *Krusader::actHomeTerminal = 0;
+KAction *Krusader::actFTPConnect = 0;
+KAction *Krusader::actFTPNewConnect = 0;
+KAction *Krusader::actFTPDisconnect = 0;
+KAction *Krusader::actProfiles = 0;
+KAction *Krusader::actMultiRename = 0;
+KAction *Krusader::actAllFilter = 0;
+KAction *Krusader::actExecFilter = 0;
+KAction *Krusader::actCustomFilter = 0;
+KAction *Krusader::actMountMan = 0;
+KAction *Krusader::actNewTool = 0;
+KAction *Krusader::actKonfigurator = 0;
+KAction *Krusader::actToolsSetup = 0;
+KAction *Krusader::actSwapPanels = 0;
+KAction *Krusader::actSwapSides = 0;
+KAction *Krusader::actBack = 0;
+KAction *Krusader::actRoot = 0;
+KAction *Krusader::actFind = 0;
+KAction *Krusader::actLocate = 0;
+KAction *Krusader::actSwitchFullScreenTE = 0;
+//KAction *Krusader::actAddBookmark = 0;
+KAction *Krusader::actSavePosition = 0;
+KAction *Krusader::actSelectColorMask = 0;
+KAction *Krusader::actOpenLeftBm = 0;
+KAction *Krusader::actOpenRightBm = 0;
+KAction *Krusader::actDirUp = 0;
+KAction *Krusader::actCmdlinePopup = 0;
+KAction *Krusader::actNewTab = 0;
+KAction *Krusader::actDupTab = 0;
+KAction *Krusader::actCloseTab = 0;
+KAction *Krusader::actNextTab = 0;
+KAction *Krusader::actPreviousTab = 0;
+KAction *Krusader::actSplit = 0;
+KAction *Krusader::actCombine = 0;
+KAction *Krusader::actUserMenu = 0;
+KAction *Krusader::actManageUseractions = 0;
+KAction *Krusader::actSyncDirs = 0;
+KAction *Krusader::actSyncBrowse = 0;
+KAction *Krusader::actF2 = 0;
+KAction *Krusader::actF3 = 0;
+KAction *Krusader::actF4 = 0;
+KAction *Krusader::actF5 = 0;
+KAction *Krusader::actF6 = 0;
+KAction *Krusader::actF7 = 0;
+KAction *Krusader::actF8 = 0;
+KAction *Krusader::actF9 = 0;
+KAction *Krusader::actF10 = 0;
+KAction *Krusader::actLocationBar = 0;
+KAction *Krusader::actPopularUrls = 0;
+KAction *Krusader::actJumpBack = 0;
+KAction *Krusader::actSetJumpBack = 0;
+KAction *Krusader::actDetailedView = 0;
+KAction *Krusader::actBriefView = 0;
+
+KToggleAction *Krusader::actToggleTerminal = 0;
+KToggleAction *Krusader::actVerticalMode = 0;
+KRadioAction *Krusader::actSelectNewerAndSingle = 0;
+KRadioAction *Krusader::actSelectSingle = 0;
+KRadioAction *Krusader::actSelectNewer = 0;
+KRadioAction *Krusader::actSelectDifferentAndSingle = 0;
+KRadioAction *Krusader::actSelectDifferent = 0;
+KRadioAction **Krusader::compareArray[] = {&actSelectNewerAndSingle, &actSelectNewer, &actSelectSingle,
+ &actSelectDifferentAndSingle, &actSelectDifferent, 0};
+KRadioAction *Krusader::actExecStartAndForget = 0;
+KRadioAction *Krusader::actExecCollectSeparate = 0;
+KRadioAction *Krusader::actExecCollectTogether = 0;
+KRadioAction *Krusader::actExecTerminalExternal = 0;
+KRadioAction *Krusader::actExecTerminalEmbedded = 0;
+KRadioAction **Krusader::execTypeArray[] =
+ {&actExecStartAndForget, &actExecCollectSeparate, &actExecCollectTogether,
+ &actExecTerminalExternal, &actExecTerminalEmbedded, 0};
+
+KPopupMenu *Krusader::userActionMenu = 0;
+UserAction *Krusader::userAction = 0;
+UserMenu *Krusader::userMenu = 0;
+KrBookmarkHandler *Krusader::bookman = 0;
+//QTextOStream *Krusader::_krOut = QTextOStream(::stdout);
+
+#ifdef __KJSEMBED__
+KrJS *Krusader::js = 0;
+KAction *Krusader::actShowJSConsole = 0;
+#endif
+
+// construct the views, statusbar and menu bars and prepare Krusader to start
+Krusader::Krusader() : KParts::MainWindow(0,0,WType_TopLevel|WDestructiveClose|Qt::WStyle_ContextHelp),
+ DCOPObject("Krusader-Interface"), status(NULL), sysTray( 0 ), isStarting( true ), isExiting( false ), directExit( false ) {
+ // parse command line arguments
+ KCmdLineArgs * args = KCmdLineArgs::parsedArgs();
+
+ kapp->ref(); // FIX: krusader exits at closing the viewer when minimized to tray
+
+ // create the "krusader"
+ App = this;
+ slot = new KRslots(this);
+ setXMLFile( "krusaderui.rc" ); // kpart-related xml file
+
+ plzWait = new KRPleaseWaitHandler();
+
+ bool runKonfig = versionControl();
+
+ QString message;
+ switch ( config->getConfigState() ) {
+ case KConfigBase::NoAccess :
+ message = "Krusader's configuration file can't be found. Default values will be used.";
+ break;
+ case KConfigBase::ReadOnly :
+ message = "Krusader's configuration file is in READ ONLY mode (why is that!?) Changed values will not be saved";
+ break;
+ case KConfigBase::ReadWrite :
+ message = "";
+ break;
+ }
+ if ( message != "" ) {
+ KMessageBox::error( krApp, message );
+ }
+
+ // create an icon loader
+ iconLoader = KGlobal::iconLoader();
+
+ // create MountMan
+ mountMan = new KMountMan();
+
+ // create bookman
+ bookman = new KrBookmarkHandler();
+
+ popularUrls = new PopularUrls(this);
+
+ queueManager = new QueueManager();
+
+ // create the main view
+ mainView = new KrusaderView( this );
+
+ // setup all the krusader's actions
+ setupActions();
+
+ // init the permmision handler class
+ KRpermHandler::init();
+
+ // init the protocol handler
+ KgProtocols::init();
+
+ // init the checksum tools
+ initChecksumModule();
+
+ krConfig->setGroup( "Look&Feel" );
+ QString defaultType = krConfig->readEntry( "Default Panel Type", _DefaultPanelType );
+
+ krConfig->setGroup( "Startup" );
+ QStringList leftTabs = krConfig->readPathListEntry( "Left Tab Bar" );
+ QStringList rightTabs = krConfig->readPathListEntry( "Right Tab Bar" );
+ QStringList leftTabTypes = krConfig->readListEntry( "Left Tab Bar Types" );
+ QStringList rightTabTypes = krConfig->readListEntry( "Right Tab Bar Types" );
+ QValueList<int> leftTabProps = krConfig->readIntListEntry( "Left Tab Bar Props" );
+ QValueList<int> rightTabProps = krConfig->readIntListEntry( "Right Tab Bar Props" );
+ int leftActiveTab = krConfig->readNumEntry( "Left Active Tab", 0 );
+ int rightActiveTab = krConfig->readNumEntry( "Right Active Tab", 0 );
+ QString startProfile = krConfig->readEntry("Starter Profile Name", QString::null );
+ bool leftActive = krConfig->readBoolEntry( "Left Side Is Active", false );
+
+ // get command-line arguments
+ if ( args->isSet( "left" ) ) {
+ leftTabs = QStringList::split( ',', args->getOption( "left" ) );
+ leftTabTypes.clear();
+ leftTabProps.clear();
+
+ leftActiveTab = 0;
+
+ // make sure left or right are not relative paths
+ for(unsigned int i = 0; i != leftTabs.count(); i++ )
+ {
+ leftTabs[ i ] = leftTabs[ i ].stripWhiteSpace();
+ if( !leftTabs[ i ].startsWith( "/" ) && leftTabs[ i ].find( ":/" ) < 0 )
+ leftTabs[ i ] = QDir::currentDirPath() + "/" + leftTabs[ i ];
+ }
+ startProfile = QString::null;
+ }
+ if ( args->isSet( "right" ) ) {
+ rightTabs = QStringList::split( ',', args->getOption( "right" ) );
+ rightTabTypes.clear();
+ rightTabProps.clear();
+
+ rightActiveTab = 0;
+
+ // make sure left or right are not relative paths
+ for(unsigned int i = 0; i != rightTabs.count(); i++ )
+ {
+ rightTabs[ i ] = rightTabs[ i ].stripWhiteSpace();
+ if( !rightTabs[ i ].startsWith( "/" ) && rightTabs[ i ].find( ":/" ) < 0 )
+ rightTabs[ i ] = QDir::currentDirPath() + "/" + rightTabs[ i ];
+ }
+ startProfile = QString::null;
+ }
+
+ while( leftTabTypes.count() < leftTabs.count() )
+ leftTabTypes += defaultType;
+ while( rightTabTypes.count() < rightTabs.count() )
+ rightTabTypes += defaultType;
+ while( leftTabProps.count() < leftTabs.count() )
+ leftTabProps += 0;
+ while( rightTabProps.count() < rightTabs.count() )
+ rightTabProps += 0;
+
+ if ( args->isSet( "profile" ) )
+ startProfile = args->getOption( "profile" );
+
+ if( !startProfile.isEmpty() ) {
+ leftTabs.clear();
+ leftTabTypes.clear();
+ leftTabProps.clear();
+ rightTabs.clear();
+ rightTabTypes.clear();
+ rightTabProps.clear();
+ leftActiveTab = rightActiveTab = 0;
+ }
+
+ if( leftTabs.count() == 0 )
+ {
+ leftTabs.push_back( QDir::homeDirPath() );
+ leftTabTypes.push_back( defaultType );
+ leftTabProps.push_back( 0 );
+ }
+ if( rightTabs.count() == 0 )
+ {
+ rightTabs.push_back( QDir::homeDirPath() );
+ rightTabTypes.push_back( defaultType );
+ rightTabProps.push_back( 0 );
+ }
+
+ // starting the panels
+ mainView->start( leftTabs, leftTabTypes, leftTabProps, leftActiveTab, rightTabs,
+ rightTabTypes, rightTabProps, rightActiveTab, leftActive );
+
+ // create the user menu
+ userMenu = new UserMenu( this );
+ userMenu->hide();
+
+ // setup keyboard accelerators
+ setupAccels();
+
+ // create a status bar
+ status = new KrusaderStatus( this );
+ QWhatsThis::add( status, i18n( "Statusbar will show basic information "
+ "about file below mouse pointer." ) );
+
+ // This enables Krusader to show a tray icon
+ sysTray = new KSystemTray( this );
+ // Krusader::privIcon() returns either "krusader_blue" or "krusader_red" if the user got root-privileges
+ sysTray->setPixmap( iconLoader->loadIcon( privIcon(), KIcon::Panel, 22 ) );
+ sysTray->hide();
+
+ connect( sysTray, SIGNAL( quitSelected() ), this, SLOT( setDirectExit() ) );
+
+ setCentralWidget( mainView );
+ config->setGroup( "Startup" );
+ bool startToTray = config->readBoolEntry( "Start To Tray", _StartToTray );
+ config->setGroup( "Look&Feel" );
+ bool minimizeToTray = config->readBoolEntry( "Minimize To Tray", _MinimizeToTray );
+ bool singleInstanceMode = config->readBoolEntry( "Single Instance Mode", _SingleInstanceMode );
+
+ startToTray = startToTray && minimizeToTray;
+
+ if( singleInstanceMode && minimizeToTray )
+ sysTray->show();
+
+
+ // manage our keyboard short-cuts
+ //KAcceleratorManager::manage(this,true);
+
+ setCursor( KCursor::arrowCursor() );
+
+ if ( ! startProfile.isEmpty() )
+ mainView->profiles( startProfile );
+ // let the good times rool :)
+ updateGUI( true );
+
+ if ( runKonfig )
+ slot->runKonfigurator( true );
+
+ if (!runKonfig) {
+ config->setGroup( "Private" );
+ if ( krConfig->readBoolEntry( "Maximized" ) )
+ restoreWindowSize(config);
+ else {
+ move( oldPos = krConfig->readPointEntry( "Start Position", _StartPosition ) );
+ resize( oldSize = krConfig->readSizeEntry( "Start Size", _StartSize ));
+ }
+ }
+
+ if( startToTray ) {
+ sysTray->show();
+ hide();
+ }
+ else
+ show();
+
+
+ isStarting = false;
+}
+
+Krusader::~Krusader() {
+ if( !isExiting ) // save the settings if it was not saved (SIGTERM)
+ saveSettings();
+
+ delete mainView;
+ delete queueManager;
+ mainView = 0;
+ App = 0;
+}
+
+bool Krusader::versionControl() {
+#define FIRST_RUN "First Time"
+ bool retval = false;
+ // create config file
+ config = kapp->config();
+ bool firstRun = config->readBoolEntry(FIRST_RUN, true);
+
+#if 0
+ QString oldVerText = config->readEntry( "Version", "10.0" );
+ oldVerText.truncate( oldVerText.findRev( "." ) ); // remove the third dot
+ float oldVer = oldVerText.toFloat();
+ // older icompatible version
+ if ( oldVer <= 0.9 ) {
+ KMessageBox::information( krApp, i18n( "A configuration of 1.51 or older was detected. Krusader has to reset your configuration to default values.\nNote: Your bookmarks and keybindings will remain intact.\n Krusader will now run Konfigurator." ) );
+ /*if ( !QDir::home().remove( ".kde/share/config/krusaderrc" ) ) {
+ KMessageBox::error( krApp, i18n( "Unable to remove your krusaderrc file! Please remove it manually and rerun Krusader." ) );
+ exit( 1 );
+ }*/
+ retval = true;
+ config->reparseConfiguration();
+ }
+#endif
+
+ // first installation of krusader
+ if ( firstRun ) {
+ KMessageBox::information( krApp, i18n( "<qt><b>Welcome to Krusader!</b><p>As this is your first run, your machine will now be checked for external applications. Then the Konfigurator will be launched where you can customize Krusader to your needs.</p></qt>" ) );
+ retval = true;
+ }
+ config->writeEntry( "Version", VERSION );
+ config->writeEntry( FIRST_RUN, false);
+ config->sync();
+ return retval;
+}
+
+void Krusader::statusBarUpdate( QString& mess ) {
+ // change the message on the statusbar for 2 seconds
+ if (status) // ugly!!!! But as statusBar() creates a status bar if there is no, I have to ask status to prevent
+ // the creation of the KDE default status bar instead of KrusaderStatus.
+ statusBar() ->message( mess, 5000 );
+}
+
+void Krusader::showEvent ( QShowEvent * ) {
+ if( isExiting )
+ return;
+ config->setGroup( "Look&Feel" );
+ bool showTrayIcon = krConfig->readBoolEntry( "Minimize To Tray", _MinimizeToTray );
+ bool singleInstanceMode = krConfig->readBoolEntry( "Single Instance Mode", _SingleInstanceMode );
+
+ if( showTrayIcon && !singleInstanceMode )
+ sysTray->hide();
+ show(); // needed to make sure krusader is removed from
+ // the taskbar when minimizing (system tray issue)
+}
+
+void Krusader::hideEvent ( QHideEvent *e ) {
+ if( isExiting ) {
+ KParts::MainWindow::hideEvent( e );
+ sysTray->hide();
+ return;
+ }
+ QString lastGroup = config->group();
+ config->setGroup( "Look&Feel" );
+ bool showTrayIcon = krConfig->readBoolEntry( "Minimize To Tray", _MinimizeToTray );
+ config->setGroup ( lastGroup );
+
+ bool isModalTopWidget = false;
+
+ QWidget *actWnd = qApp->activeWindow();
+ if ( actWnd )
+ isModalTopWidget = actWnd->isModal();
+
+ if ( showTrayIcon && !isModalTopWidget && KWin::windowInfo( winId() ).isOnCurrentDesktop() ) {
+ sysTray->show();
+ hide(); // needed to make sure krusader is removed from
+ // the taskbar when minimizing (system tray issue)
+ } else KParts::MainWindow::hideEvent( e );
+}
+
+void Krusader::moveEvent ( QMoveEvent *e ) {
+ oldPos = e->oldPos();
+ KParts::MainWindow::moveEvent( e );
+}
+
+void Krusader::resizeEvent ( QResizeEvent *e ) {
+ oldSize = e->oldSize();
+ KParts::MainWindow::resizeEvent( e );
+}
+
+void Krusader::setupAccels() {
+ accels = new KAccel( this );
+ // SHIFT+F3
+ accels->insert( "F3_ViewDlg", i18n( "F3 View Dialog" ), QString::null,
+ SHIFT + Key_F3, SLOTS, SLOT( viewDlg() ) );
+ // Tab
+ accels->insert( "Tab-Switch panel", i18n( "Tab: switch panel" ), QString::null,
+ Key_Tab, mainView, SLOT( panelSwitch() ) );
+
+}
+
+// <patch> Moving from Pixmap actions to generic filenames - thanks to Carsten Pfeiffer
+void Krusader::setupActions() {
+ // first come the TODO actions
+ //actSync = 0;//new KAction(i18n("S&yncronize Dirs"), 0, this, 0, actionCollection(), "sync dirs");
+ //actNewTool = 0;//new KAction(i18n("&Add a new tool"), 0, this, 0, actionCollection(), "add tool");
+ //actToolsSetup = 0;//new KAction(i18n("&Tools Menu Setup"), 0, 0, this, 0, actionCollection(), "tools setup");
+ //KStdAction::print(SLOTS, 0,actionCollection(),"std_print");
+ //KStdAction::showMenubar( SLOTS, SLOT( showMenubar() ), actionCollection(), "std_menubar" );
+
+
+ // second, the KDE standard action
+ //KStdAction::up( SLOTS, SLOT( dirUp() ), actionCollection(), "std_up" )->setShortcut(Key_Backspace);
+ /* Shortcut disabled because of the Terminal Emulator bug. */
+ krConfig->setGroup( "Private" );
+ int compareMode = krConfig->readNumEntry( "Compare Mode", 0 );
+ int cmdExecMode = krConfig->readNumEntry( "Command Execution Mode", 0 );
+
+ KStdAction::home( SLOTS, SLOT( home() ), actionCollection(), "std_home" )->setText( i18n("Home") ); /*->setShortcut(Key_QuoteLeft);*/
+ new KAction( i18n( "&Reload" ), "reload", CTRL + Key_R, SLOTS, SLOT( refresh() ), actionCollection(), "std_redisplay" );
+ actShowToolBar = KStdAction::showToolbar( SLOTS, SLOT( toggleToolbar() ), actionCollection(), "std_toolbar" );
+ new KToggleAction( i18n("Show Actions Toolbar"), 0, SLOTS, SLOT( toggleActionsToolbar() ),
+ actionCollection(), "toggle actions toolbar" );
+ actShowStatusBar = KStdAction::showStatusbar( SLOTS, SLOT( toggleStatusbar() ), actionCollection(), "std_statusbar" );
+ KStdAction::quit( this, SLOT( slotClose() ), actionCollection(), "std_quit" );
+ KStdAction::configureToolbars( SLOTS, SLOT( configToolbar() ), actionCollection(), "std_config_toolbar" );
+ KStdAction::keyBindings( SLOTS, SLOT( configKeys() ), actionCollection(), "std_config_keys" );
+
+ KStdAction::cut( SLOTS, SLOT( cut() ), actionCollection(), "std_cut" )->setText( i18n("Cut to Clipboard") );
+ (actCopy = KStdAction::copy( SLOTS, SLOT( copy() ), actionCollection(), "std_copy" ))->setText( i18n("Copy to Clipboard") );
+ (actPaste = KStdAction::paste( SLOTS, SLOT( paste() ), actionCollection(), "std_paste" ))->setText( i18n("Paste from Clipboard") );
+
+ // the toggle actions
+ actToggleFnkeys = new KToggleAction( i18n( "Show &FN Keys Bar" ), 0, SLOTS,
+ SLOT( toggleFnkeys() ), actionCollection(), "toggle fn bar" );
+ actToggleFnkeys->setChecked( true );
+ actToggleCmdline = new KToggleAction( i18n( "Show &Command Line" ), 0, SLOTS,
+ SLOT( toggleCmdline() ), actionCollection(), "toggle command line" );
+ actToggleCmdline->setChecked( true );
+ actToggleTerminal = new KToggleAction( i18n( "Show Terminal &Emulator" ), ALT + CTRL + Key_T, SLOTS,
+ SLOT( toggleTerminal() ), actionCollection(), "toggle terminal emulator" );
+ actToggleTerminal->setChecked( false );
+
+ actDetailedView = new KAction( i18n( "&Detailed View" ), ALT + SHIFT + Key_D, SLOTS,
+ SLOT( setDetailedView() ), actionCollection(), "detailed_view" );
+
+ actBriefView = new KAction( i18n( "&Brief View" ), ALT + SHIFT + Key_B, SLOTS,
+ SLOT( setBriefView() ), actionCollection(), "brief_view" );
+
+ actToggleHidden = new KToggleAction( i18n( "Show &Hidden Files" ), CTRL + Key_Period, SLOTS,
+ SLOT( toggleHidden() ), actionCollection(), "toggle hidden files" );
+ actSwapPanels = new KAction( i18n( "S&wap Panels" ), CTRL + Key_U, SLOTS,
+ SLOT( swapPanels() ), actionCollection(), "swap panels" );
+ actSwapSides = new KAction( i18n( "Sw&ap Sides" ), CTRL + SHIFT + Key_U, SLOTS,
+ SLOT( toggleSwapSides() ), actionCollection(), "toggle swap sides" );
+ krConfig->setGroup( "Look&Feel" );
+ actToggleHidden->setChecked( krConfig->readBoolEntry( "Show Hidden", _ShowHidden ) );
+
+ // and then the DONE actions
+ actCmdlinePopup = new KAction( i18n( "popup cmdline" ), 0, CTRL + Key_Slash, SLOTS,
+ SLOT( cmdlinePopup() ), actionCollection(), "cmdline popup" );
+ /* Shortcut disabled because of the Terminal Emulator bug. */
+ actDirUp = new KAction( i18n( "Up" ), "up", CTRL+Key_PageUp /*Key_Backspace*/, SLOTS, SLOT( dirUp() ), actionCollection(), "dirUp" );
+ new KAction( i18n( "&New Text File..." ), "filenew", SHIFT + Key_F4, SLOTS, SLOT( editDlg() ), actionCollection(), "edit_new_file" );
+ new KAction( i18n( "Start &Root Mode Krusader" ), "krusader_root", ALT + Key_K, SLOTS, SLOT( rootKrusader() ), actionCollection(), "root krusader" );
+
+ actTest = new KAction( i18n( "T&est Archive" ), "ark", ALT + Key_E,
+ SLOTS, SLOT( testArchive() ), actionCollection(), "test archives" );
+ //actFTPConnect = new KAction( i18n( "&Net Connections" ), "domtreeviewer", 0,
+ // SLOTS, SLOT( runRemoteMan() ), actionCollection(), "ftp connect" );
+ actFTPNewConnect = new KAction( i18n( "New Net &Connection..." ), "connect_creating", CTRL + Key_N,
+ SLOTS, SLOT( newFTPconnection() ), actionCollection(), "ftp new connection" );
+ actProfiles = new KAction( i18n( "Pro&files" ), "kr_profile", ALT + Key_L,
+ MAIN_VIEW, SLOT( profiles() ), actionCollection(), "profile" );
+ actCalculate = new KAction( i18n( "Calculate &Occupied Space" ), "kcalc", 0,
+ SLOTS, SLOT( calcSpace() ), actionCollection(), "calculate" );
+ actCreateChecksum = new KAction( i18n( "Create Checksum..." ), "binary", 0,
+ SLOTS, SLOT( createChecksum() ), actionCollection(), "create checksum" );
+ actMatchChecksum = new KAction( i18n( "Verify Checksum..." ), "match_checksum", 0,
+ SLOTS, SLOT( matchChecksum() ), actionCollection(), "match checksum" );
+ actProperties = new KAction( i18n( "&Properties..." ), 0, ALT+Key_Enter,
+ SLOTS, SLOT( properties() ), actionCollection(), "properties" );
+ actPack = new KAction( i18n( "Pac&k..." ), "kr_arc_pack", ALT + Key_P,
+ SLOTS, SLOT( slotPack() ), actionCollection(), "pack" );
+ actUnpack = new KAction( i18n( "&Unpack..." ), "kr_arc_unpack", ALT + Key_U,
+ SLOTS, SLOT( slotUnpack() ), actionCollection() , "unpack" );
+ actSplit = new KAction( i18n( "Sp&lit File..." ), "kr_split", CTRL + Key_P,
+ SLOTS, SLOT( slotSplit() ), actionCollection(), "split" );
+ actCombine = new KAction( i18n( "Com&bine Files..." ), "kr_combine", CTRL + Key_B,
+ SLOTS, SLOT( slotCombine() ), actionCollection() , "combine" );
+ actSelect = new KAction( i18n( "Select &Group..." ), "kr_select", CTRL + Key_Plus,
+ SLOTS, SLOT( markGroup() ), actionCollection(), "select group" );
+ actSelectAll = new KAction( i18n( "&Select All" ), "kr_selectall", ALT + Key_Plus,
+ SLOTS, SLOT( markAll() ), actionCollection(), "select all" );
+ actUnselect = new KAction( i18n( "&Unselect Group..." ), "kr_unselect", CTRL + Key_Minus,
+ SLOTS, SLOT( unmarkGroup() ), actionCollection(), "unselect group" );
+ actUnselectAll = new KAction( i18n( "U&nselect All" ), "kr_unselectall", ALT + Key_Minus,
+ SLOTS, SLOT( unmarkAll() ), actionCollection(), "unselect all" );
+ actInvert = new KAction( i18n( "&Invert Selection" ), "kr_invert", ALT + Key_Asterisk,
+ SLOTS, SLOT( invert() ), actionCollection(), "invert" );
+ actCompDirs = new KAction( i18n( "&Compare Directories" ), "view_left_right", ALT + Key_C,
+ SLOTS, SLOT( compareDirs() ), actionCollection(), "compare dirs" );
+ actSelectNewerAndSingle = new KRadioAction( i18n( "&Select Newer and Single" ), 0,
+ SLOTS, SLOT( compareSetup() ), actionCollection(), "select_newer_and_single" );
+ actSelectNewer = new KRadioAction( i18n( "Select &Newer" ), 0,
+ SLOTS, SLOT( compareSetup() ), actionCollection(), "select_newer" );
+ actSelectSingle = new KRadioAction( i18n( "Select &Single" ), 0,
+ SLOTS, SLOT( compareSetup() ), actionCollection(), "select_single" );
+ actSelectDifferentAndSingle = new KRadioAction( i18n( "Select Different &and Single" ), 0,
+ SLOTS, SLOT( compareSetup() ), actionCollection(), "select_different_and_single" );
+ actSelectDifferent = new KRadioAction( i18n( "Select &Different" ), 0,
+ SLOTS, SLOT( compareSetup() ), actionCollection(), "select_different" );
+ actSelectNewerAndSingle->setExclusiveGroup( "the_select_group" );
+ actSelectNewer->setExclusiveGroup( "the_select_group" );
+ actSelectSingle->setExclusiveGroup( "the_select_group" );
+ actSelectDifferentAndSingle->setExclusiveGroup( "the_select_group" );
+ actSelectDifferent->setExclusiveGroup( "the_select_group" );
+ if( compareMode < (int)( sizeof( compareArray ) / sizeof( KRadioAction ** ) ) -1 )
+ (*compareArray[ compareMode ])->setChecked( true );
+ actExecStartAndForget = new KRadioAction(
+ i18n( "Start and &Forget" ), 0,
+ SLOTS, SLOT( execTypeSetup() ),
+ actionCollection(), "exec_start_and_forget" );
+ actExecCollectSeparate = new KRadioAction(
+ i18n( "Display &Separated Standard and Error Output" ), 0,
+ SLOTS, SLOT( execTypeSetup() ),
+ actionCollection(), "exec_collect_separate" );
+ actExecCollectTogether = new KRadioAction(
+ i18n( "Display &Mixed Standard and Error Output" ), 0,
+ SLOTS, SLOT( execTypeSetup() ),
+ actionCollection(), "exec_collect_together" );
+ actExecTerminalExternal = new KRadioAction(
+ i18n( "Start in &New Terminal" ), 0,
+ SLOTS, SLOT( execTypeSetup() ),
+ actionCollection(), "exec_terminal_external" );
+ actExecTerminalEmbedded = new KRadioAction(
+ i18n( "Send to &Embedded Terminal Emulator" ), 0,
+ SLOTS, SLOT( execTypeSetup() ),
+ actionCollection(), "exec_terminal_embedded" );
+ actExecStartAndForget->setExclusiveGroup("the_exec_type_group");
+ actExecCollectSeparate->setExclusiveGroup("the_exec_type_group");
+ actExecCollectTogether->setExclusiveGroup("the_exec_type_group");
+ actExecTerminalExternal->setExclusiveGroup("the_exec_type_group");
+ actExecTerminalEmbedded->setExclusiveGroup("the_exec_type_group");
+ if( cmdExecMode < (int)( sizeof( execTypeArray ) / sizeof( KRadioAction ** ) ) -1 )
+ (*execTypeArray[ cmdExecMode ])->setChecked( true );
+
+
+ actHomeTerminal = new KAction( i18n( "Start &Terminal" ), "terminal", 0,
+ SLOTS, SLOT( homeTerminal() ), actionCollection(), "terminal@home" );
+ actFTPDisconnect = new KAction( i18n( "Disconnect &from Net" ), "kr_ftp_disconnect", SHIFT + CTRL + Key_F,
+ SLOTS, SLOT( FTPDisconnect() ), actionCollection(), "ftp disconnect" );
+#if KDE_IS_VERSION(3,2,0) /* new mountman feature is available in kde 3.2 only! */
+ actMountMan = new KToolBarPopupAction( i18n( "&MountMan..." ), "kr_mountman", ALT + Key_Slash,
+ SLOTS, SLOT( runMountMan() ), actionCollection(), "mountman" );
+ connect( ( ( KToolBarPopupAction* ) actMountMan ) ->popupMenu(), SIGNAL( aboutToShow() ),
+ mountMan, SLOT( quickList() ) );
+#else
+ actMountMan = new KAction( i18n( "&MountMan..." ), "kr_mountman", ALT + Key_Slash,
+ SLOTS, SLOT( runMountMan() ), actionCollection(), "mountman" );
+#endif /* KDE 3.2 */
+
+ actFind = new KAction( i18n( "&Search..." ), "filefind", CTRL + Key_S,
+ SLOTS, SLOT( search() ), actionCollection(), "find" );
+ actLocate = new KAction( i18n( "&Locate..." ), "find", SHIFT+CTRL + Key_L,
+ SLOTS, SLOT( locate() ), actionCollection(), "locate" );
+ actSyncDirs = new KAction( i18n( "Synchronize &Directories..." ), "kr_syncdirs", CTRL + Key_Y,
+ SLOTS, SLOT( slotSynchronizeDirs() ), actionCollection(), "sync dirs" );
+ actSyncBrowse = new KAction( i18n( "S&ynchron Directory Changes" ), "kr_syncbrowse_off", ALT + Key_Y,
+ SLOTS, SLOT( slotSyncBrowse() ), actionCollection(), "sync browse" );
+ actDiskUsage = new KAction( i18n( "D&isk Usage..." ), "kr_diskusage", ALT + Key_D,
+ SLOTS, SLOT( slotDiskUsage() ), actionCollection(), "disk usage" );
+ actKonfigurator = new KAction( i18n( "Configure &Krusader..." ), "configure", 0,
+ SLOTS, SLOT( startKonfigurator() ), actionCollection(), "konfigurator" );
+ actBack = new KAction( i18n( "Back" ), "back", 0,
+ SLOTS, SLOT( back() ), actionCollection(), "back" );
+ actRoot = new KAction( i18n( "Root" ), "top", CTRL + Key_Backspace,
+ SLOTS, SLOT( root() ), actionCollection(), "root" );
+ actSavePosition = new KAction( i18n( "Save &Position" ), 0,
+ krApp, SLOT( savePosition() ), actionCollection(), "save position" );
+ actAllFilter = new KAction( i18n( "&All Files" ), SHIFT + Key_F10,
+ SLOTS, SLOT( allFilter() ), actionCollection(), "all files" );
+ //actExecFilter = new KAction( i18n( "&Executables" ), SHIFT + Key_F11,
+ // SLOTS, SLOT( execFilter() ), actionCollection(), "exec files" );
+ actCustomFilter = new KAction( i18n( "&Custom" ), SHIFT + Key_F12,
+ SLOTS, SLOT( customFilter() ), actionCollection(), "custom files" );
+ actCompare = new KAction( i18n( "Compare b&y Content..." ), "kmultiple", 0,
+ SLOTS, SLOT( compareContent() ), actionCollection(), "compare" );
+ actMultiRename = new KAction( i18n( "Multi &Rename..." ), "krename", SHIFT + Key_F9,
+ SLOTS, SLOT( multiRename() ), actionCollection(), "multirename" );
+ new KAction( i18n( "Right-click Menu" ), Key_Menu,
+ SLOTS, SLOT( rightclickMenu() ), actionCollection(), "rightclick menu" );
+ new KAction( i18n( "Right Bookmarks" ), ALT + Key_Right,
+ SLOTS, SLOT( openRightBookmarks() ), actionCollection(), "right bookmarks" );
+ new KAction( i18n( "Left Bookmarks" ), ALT + Key_Left,
+ SLOTS, SLOT( openLeftBookmarks() ), actionCollection(), "left bookmarks" );
+ new KAction( i18n( "Bookmarks" ), CTRL + Key_D,
+ SLOTS, SLOT( openBookmarks() ), actionCollection(), "bookmarks" );
+ new KAction( i18n( "Bookmark Current" ), CTRL + SHIFT + Key_D,
+ SLOTS, SLOT( bookmarkCurrent() ), actionCollection(), "bookmark current" );
+ new KAction( i18n( "History" ), CTRL + Key_H,
+ SLOTS, SLOT( openHistory() ), actionCollection(), "history" );
+ new KAction( i18n( "Sync Panels" ), ALT + Key_O,
+ SLOTS, SLOT( syncPanels() ), actionCollection(), "sync panels");
+ new KAction( i18n( "Left History" ), ALT + CTRL + Key_Left,
+ SLOTS, SLOT( openLeftHistory() ), actionCollection(), "left history" );
+ new KAction( i18n( "Right History" ), ALT + CTRL + Key_Right,
+ SLOTS, SLOT( openRightHistory() ), actionCollection(), "right history" );
+ new KAction( i18n( "Media" ), CTRL + Key_M,
+ SLOTS, SLOT( openMedia() ), actionCollection(), "media" );
+ new KAction( i18n( "Left Media" ), CTRL + SHIFT + Key_Left,
+ SLOTS, SLOT( openLeftMedia() ), actionCollection(), "left media" );
+ new KAction( i18n( "Right Media" ), CTRL + SHIFT + Key_Right,
+ SLOTS, SLOT( openRightMedia() ), actionCollection(), "right media" );
+ new KAction( i18n( "New Symlink..." ), CTRL + ALT + Key_S,
+ SLOTS, SLOT( newSymlink() ), actionCollection(), "new symlink");
+ new KToggleAction( i18n( "Toggle Popup Panel" ), ALT + Key_Down, SLOTS,
+ SLOT( togglePopupPanel() ), actionCollection(), "toggle popup panel" );
+ actVerticalMode = new KToggleAction( i18n( "Vertical Mode" ), "view_top_bottom", ALT + CTRL + Key_R, MAIN_VIEW,
+ SLOT( toggleVerticalMode() ), actionCollection(), "toggle vertical mode" );
+ actNewTab = new KAction( i18n( "New Tab" ), "tab_new", ALT + CTRL + Key_N, SLOTS,
+ SLOT( newTab() ), actionCollection(), "new tab" );
+ actDupTab = new KAction( i18n( "Duplicate Current Tab" ), "tab_duplicate", ALT + CTRL + SHIFT + Key_N, SLOTS,
+ SLOT( duplicateTab() ), actionCollection(), "duplicate tab" );
+ actCloseTab = new KAction( i18n( "Close Current Tab" ), "tab_remove", CTRL + Key_W, SLOTS,
+ SLOT( closeTab() ), actionCollection(), "close tab" );
+ actNextTab = new KAction( i18n( "Next Tab" ), SHIFT + Key_Right, SLOTS,
+ SLOT( nextTab() ), actionCollection(), "next tab" );
+ actPreviousTab = new KAction( i18n( "Previous Tab" ), SHIFT + Key_Left, SLOTS,
+ SLOT( previousTab() ), actionCollection(), "previous tab" );
+/*
+ actUserMenu = new KAction( i18n( "User Menu" ), ALT + Key_QuoteLeft, SLOTS,
+ SLOT( userMenu() ), actionCollection(), "user menu" );
+*/
+ actManageUseractions = new KAction( i18n( "Manage User Actions..." ), 0, SLOTS,
+ SLOT( manageUseractions() ), actionCollection(), "manage useractions" );
+ new KrRemoteEncodingMenu(i18n("Select Remote Charset"), "charset", actionCollection(), "changeremoteencoding");
+
+ // setup the Fn keys
+ actF2 = new KAction( i18n( "Start Terminal Here" ), "terminal", Key_F2,
+ SLOTS, SLOT( terminal() ) , actionCollection(), "F2_Terminal" );
+ actF3 = new KAction( i18n( "View File" ), Key_F3,
+ SLOTS, SLOT( view() ) , actionCollection(), "F3_View" );
+ actF4 = new KAction( i18n( "Edit File" ), Key_F4,
+ SLOTS, SLOT( edit() ) , actionCollection(), "F4_Edit" );
+ actF5 = new KAction( i18n( "Copy..." ), Key_F5,
+ SLOTS, SLOT( copyFiles() ) , actionCollection(), "F5_Copy" );
+ actF6 = new KAction( i18n( "Move..." ), Key_F6,
+ SLOTS, SLOT( moveFiles() ) , actionCollection(), "F6_Move" );
+ actF7 = new KAction( i18n( "New Directory..." ), "folder_new", Key_F7,
+ SLOTS, SLOT( mkdir() ) , actionCollection(), "F7_Mkdir" );
+ actF8 = new KAction( i18n( "Delete" ), "editdelete", Key_F8,
+ SLOTS, SLOT( deleteFiles() ) , actionCollection(), "F8_Delete" );
+ actF9 = new KAction( i18n( "Rename" ), Key_F9,
+ SLOTS, SLOT( rename() ) , actionCollection(), "F9_Rename" );
+ actF10 = new KAction( i18n( "Quit" ), Key_F10,
+ this, SLOT( slotClose() ) , actionCollection(), "F10_Quit" );
+ actPopularUrls = new KAction( i18n("Popular URLs..."), CTRL+Key_Z,
+ popularUrls, SLOT( showDialog() ), actionCollection(), "Popular_Urls");
+ actLocationBar = new KAction( i18n("Go to Location Bar"), CTRL+Key_L,
+ SLOTS, SLOT( slotLocationBar() ), actionCollection(), "location_bar");
+ actJumpBack = new KAction( i18n("Jump Back"), "kr_jumpback", CTRL+Key_J,
+ SLOTS, SLOT( slotJumpBack() ), actionCollection(), "jump_back");
+ actSetJumpBack = new KAction( i18n("Set Jump Back Point"), "kr_setjumpback", CTRL+SHIFT+Key_J,
+ SLOTS, SLOT( slotSetJumpBack() ), actionCollection(), "set_jump_back");
+ actSwitchFullScreenTE = new KAction( i18n( "Toggle Fullwidget Terminal Emulator" ), 0, CTRL + Key_F,
+ MAIN_VIEW, SLOT( switchFullScreenTE() ), actionCollection(), "switch_fullscreen_te" );
+
+ // and at last we can set the tool-tips
+ actSelect->setToolTip( i18n( "Select files using a filter" ) );
+ actSelectAll->setToolTip( i18n("Select all files in the current directory" ) );
+ actUnselectAll->setToolTip( i18n( "Unselect all selected files" ) );
+ actKonfigurator->setToolTip( i18n( "Setup Krusader the way you like it" ) );
+ actBack->setToolTip( i18n( "Back to the place you came from" ) );
+ actRoot->setToolTip( i18n( "ROOT (/)" ) );
+ actFind->setToolTip( i18n( "Search for files" ) );
+
+ // setup all UserActions
+ userAction = new UserAction();
+
+ #ifdef __KJSEMBED__
+ actShowJSConsole = new KAction( i18n( "JavaScript Console..." ), ALT + CTRL + Key_J, SLOTS, SLOT( jsConsole() ), actionCollection(), "JS_Console" );
+ #endif
+}
+
+///////////////////////////////////////////////////////////////////////////
+//////////////////// implementation of slots //////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+void Krusader::savePosition() {
+ config->setGroup( "Private" );
+ config->writeEntry( "Maximized", isMaximized() );
+ if (isMaximized())
+ saveWindowSize(config);
+ else {
+ config->writeEntry( "Start Position", isMaximized() ? oldPos : pos() );
+ config->writeEntry( "Start Size", isMaximized() ? oldSize : size() );
+ }
+ config->writeEntry( "Panel Size", mainView->vert_splitter->sizes() [ 0 ] );
+ config->writeEntry( "Terminal Size", mainView->vert_splitter->sizes() [ 1 ] );
+ QValueList<int> lst = mainView->horiz_splitter->sizes();
+ config->writeEntry( "Splitter Sizes", lst );
+ mainView->left->popup->saveSizes();
+ mainView->right->popup->saveSizes();
+ if( !MAIN_VIEW->getTerminalEmulatorSplitterSizes().isEmpty() )
+ config->writeEntry( "Terminal Emulator Splitter Sizes", MAIN_VIEW->getTerminalEmulatorSplitterSizes() );
+
+ // save view settings ---> fix when we have tabbed-browsing
+ mainView->left->view->saveSettings();
+ mainView->right->view->saveSettings();
+
+ config->setGroup( "Startup" );
+ config->writeEntry( "Vertical Mode", actVerticalMode->isChecked());
+ config->sync();
+}
+
+void Krusader::saveSettings() {
+ toolBar() ->saveSettings( krConfig, "Private" );
+ toolBar("actionsToolBar")->saveSettings( krConfig, "Actions Toolbar" );
+ config->setGroup( "Startup" );
+ config->writeEntry( "Left Active Tab", mainView->leftMng->activeTab() );
+ config->writeEntry( "Right Active Tab", mainView->rightMng->activeTab() );
+ config->writeEntry( "Left Side Is Active", MAIN_VIEW->activePanel->isLeft() );
+ mainView->leftMng->saveSettings( krConfig, "Left Tab Bar" );
+ mainView->rightMng->saveSettings( krConfig, "Right Tab Bar" );
+
+ bool rememberpos = config->readBoolEntry( "Remember Position", _RememberPos );
+ bool uisavesettings = config->readBoolEntry( "UI Save Settings", _UiSave );
+
+ // save the popup panel's page of the CURRENT tab
+ config->writeEntry( "Left Panel Popup", mainView->left->popup->currentPage() );
+ config->writeEntry( "Right Panel Popup", mainView->right->popup->currentPage() );
+
+ // save size and position
+ if ( rememberpos || uisavesettings ) {
+ savePosition();
+ }
+
+ // save the gui
+ if ( uisavesettings ) {
+ config->setGroup( "Startup" );
+ config->writeEntry( "Show status bar", actShowStatusBar->isChecked() );
+ config->writeEntry( "Show tool bar", actShowToolBar->isChecked() );
+ config->writeEntry( "Show FN Keys", actToggleFnkeys->isChecked() );
+ config->writeEntry( "Show Cmd Line", actToggleCmdline->isChecked() );
+ config->writeEntry( "Show Terminal Emulator", actToggleTerminal->isChecked() );
+ config->writeEntry( "Vertical Mode", actVerticalMode->isChecked());
+ config->writeEntry( "Start To Tray", isHidden());
+ }
+
+ // save popular links
+ popularUrls->save();
+
+ config->sync();
+}
+
+void Krusader::refreshView() {
+ delete mainView;
+ mainView = new KrusaderView( this );
+ setCentralWidget( mainView );
+ config->setGroup( "Private" );
+ resize( krConfig->readSizeEntry( "Start Size", _StartSize ) );
+ move( krConfig->readPointEntry( "Start Position", _StartPosition ) );
+ mainView->show();
+ show();
+}
+
+void Krusader::configChanged() {
+ config->setGroup( "Look&Feel" );
+ bool minimizeToTray = config->readBoolEntry( "Minimize To Tray", _MinimizeToTray );
+ bool singleInstanceMode = config->readBoolEntry( "Single Instance Mode", _SingleInstanceMode );
+
+ if( !isHidden() ) {
+ if( singleInstanceMode && minimizeToTray )
+ sysTray->show();
+ else
+ sysTray->hide();
+ } else {
+ if( minimizeToTray )
+ sysTray->show();
+ }
+}
+
+void Krusader::slotClose() {
+ directExit = true;
+ close();
+}
+
+bool Krusader::queryClose() {
+ if( isStarting || isExiting )
+ return false;
+
+ if( kapp->sessionSaving() ) // KDE is logging out, accept the close
+ {
+ saveSettings();
+
+ kapp->dcopClient()->registerAs( KApplication::kApplication()->name(), true );
+
+ kapp->deref(); // FIX: krusader exits at closing the viewer when minimized to tray
+ kapp->deref(); // and close the application
+ return isExiting = true; // this will also kill the pending jobs
+ }
+
+ krConfig->setGroup( "Look&Feel" );
+ if( !directExit && krConfig->readBoolEntry( "Single Instance Mode", _SingleInstanceMode ) &&
+ krConfig->readBoolEntry( "Minimize To Tray", _MinimizeToTray ) ) {
+ hide();
+ return false;
+ }
+
+ // the shutdown process can be cancelled. That's why
+ // the directExit variable is set to normal here.
+ directExit = false;
+
+ bool quit = true;
+
+ if ( krConfig->readBoolEntry( "Warn On Exit", _WarnOnExit ) ) {
+ switch ( KMessageBox::warningYesNo( this,
+ i18n( "Are you sure you want to quit?" ) ) ) {
+ case KMessageBox::Yes :
+ quit = true;
+ break;
+ case KMessageBox::No :
+ quit = false;
+ break;
+ default:
+ quit = false;
+ }
+ }
+ if ( quit ) {
+ /* First try to close the child windows, because it's the safer
+ way to avoid crashes, then close the main window.
+ If closing a child is not successful, then we cannot let the
+ main window close. */
+
+ for(;;) {
+ QWidgetList * list = QApplication::topLevelWidgets();
+ QWidget *activeModal = QApplication::activeModalWidget();
+ QWidget *w = list->first();
+
+ if( activeModal && activeModal != this && activeModal != menuBar() && activeModal != sysTray && list->contains( activeModal ) && !activeModal->isHidden() )
+ w = activeModal;
+ else {
+ while(w && (w==this || w==sysTray || w->isHidden() || w==menuBar()) )
+ w = list->next();
+ }
+ delete list;
+
+ if(!w) break;
+ bool hid = false;
+
+ if( w->inherits( "KDialogBase" ) ) { // KDE is funny and rejects the close event for
+ w->hide(); // playing a fancy animation with the CANCEL button.
+ hid = true; // if we hide the widget, KDialogBase accepts the close event
+ }
+
+ if( !w->close() ) {
+ if( hid )
+ w->show();
+
+ if( w->inherits( "QDialog" ) )
+ fprintf( stderr, "Failed to close: %s\n", w->className() );
+
+ return false;
+ }
+ }
+
+ saveSettings();
+
+ isExiting = true;
+ hide(); // hide
+
+ // Changes the name of the application. Single instance mode requires unique appid.
+ // As Krusader is exiting, we release that unique appid, so new Krusader instances
+ // can be started.
+ kapp->dcopClient()->registerAs( KApplication::kApplication()->name(), true );
+
+ kapp->deref(); // FIX: krusader exits at closing the viewer when minimized to tray
+ kapp->deref(); // and close the application
+ return false; // don't let the main widget close. It stops the pendig copies!
+ } else
+ return false;
+}
+
+// the please wait dialog functions
+void Krusader::startWaiting( QString msg, int count , bool cancel ) {
+ plzWait->startWaiting( msg , count, cancel );
+}
+
+bool Krusader::wasWaitingCancelled() const {
+ return plzWait->wasCancelled();
+}
+
+void Krusader::incProgress( KProcess *, char *buffer, int buflen ) {
+ int howMuch = 0;
+ for ( int i = 0 ; i < buflen; ++i )
+ if ( buffer[ i ] == '\n' )
+ ++howMuch;
+
+ plzWait->incProgress( howMuch );
+}
+
+void Krusader::stopWait() {
+ plzWait->stopWait();
+}
+
+void Krusader::updateGUI( bool enforce ) {
+ // now, check if we need to create a konsole_part
+ config->setGroup( "Startup" );
+
+ // call the XML GUI function to draw the UI
+ createGUI( mainView->konsole_part );
+
+ // this needs to be called AFTER createGUI() !!!
+ userActionMenu = (KPopupMenu*) guiFactory()->container( "useractionmenu", this );
+ if ( userActionMenu )
+ userAction->populateMenu( userActionMenu );
+
+ toolBar() ->applySettings( krConfig, "Private" );
+
+ toolBar("actionsToolBar") ->applySettings( krConfig, "Actions Toolbar" );
+ static_cast<KToggleAction*>(actionCollection()->action("toggle actions toolbar"))->
+ setChecked(toolBar("actionsToolBar")->isVisible());
+
+ if ( enforce ) {
+ // now, hide what need to be hidden
+ if ( !krConfig->readBoolEntry( "Show tool bar", _ShowToolBar ) ) {
+ toolBar() ->hide();
+ actShowToolBar->setChecked( false );
+ } else {
+ toolBar() ->show();
+ actShowToolBar->setChecked( true );
+ }
+ if ( !krConfig->readBoolEntry( "Show status bar", _ShowStatusBar ) ) {
+ statusBar() ->hide();
+ actShowStatusBar->setChecked( false );
+ } else {
+ statusBar() ->show();
+ actShowStatusBar->setChecked( true );
+ }
+ if ( !krConfig->readBoolEntry( "Show Cmd Line", _ShowCmdline ) ) {
+ mainView->cmdLine->hide();
+ actToggleCmdline->setChecked( false );
+ } else {
+ mainView->cmdLine->show();
+ actToggleCmdline->setChecked( true );
+ }
+
+ // update the Fn bar to the shortcuts selected by the user
+ mainView->fnKeys->updateShortcuts();
+ if ( !krConfig->readBoolEntry( "Show FN Keys", _ShowFNkeys ) ) {
+ mainView->fnKeys->hide();
+ actToggleFnkeys->setChecked( false );
+ } else {
+ mainView->fnKeys->show();
+ actToggleFnkeys->setChecked( true );
+ }
+ // set vertical mode
+ if (krConfig->readBoolEntry( "Vertical Mode", false)) {
+ actVerticalMode->setChecked(true);
+ mainView->toggleVerticalMode();
+ }
+ if ( config->readBoolEntry( "Show Terminal Emulator", _ShowTerminalEmulator ) ) {
+ mainView->slotTerminalEmulator( true ); // create konsole_part
+ KConfigGroup grp(krConfig, "Private" );
+ QValueList<int> lst;
+ lst.append( grp.readNumEntry( "Panel Size", _PanelSize ) );
+ lst.append( grp.readNumEntry( "Terminal Size", _TerminalSize ) );
+ mainView->vert_splitter->setSizes( lst );
+ config->setGroup( "Startup" );
+ } else if ( actExecTerminalEmbedded->isChecked() ) {
+ //create (but not show) terminal emulator,
+ //if command-line commands are to be run there
+ mainView->createTE();
+ }
+ }
+ // popular urls
+ popularUrls->load();
+
+}
+
+// return a list in the format of TOOLS,PATH. for example
+// DIFF,kdiff,TERMINAL,konsole,...
+//
+// currently supported tools: DIFF, MAIL, RENAME
+//
+// to use it: QStringList lst = supportedTools();
+// int i = lst.findIndex("DIFF");
+// if (i!=-1) pathToDiff=lst[i+1];
+QStringList Krusader::supportedTools() {
+ QStringList tools;
+
+ // first, a diff program: kdiff
+ if ( KrServices::cmdExist( "kdiff3" ) ) {
+ tools.append( "DIFF" );
+ tools.append( KrServices::fullPathName( "kdiff3", "diff utility" ) );
+ } else if ( KrServices::cmdExist( "kompare" ) ) {
+ tools.append( "DIFF" );
+ tools.append( KrServices::fullPathName( "kompare", "diff utility" ) );
+ } else if ( KrServices::cmdExist( "xxdiff" ) ) {
+ tools.append( "DIFF" );
+ tools.append( KrServices::fullPathName( "xxdiff", "diff utility" ) );
+ }
+ // a mailer: kmail
+ if ( KrServices::cmdExist( "kmail" ) ) {
+ tools.append( "MAIL" );
+ tools.append( KrServices::fullPathName( "kmail" ) );
+ }
+ // rename tool: krename
+ if ( KrServices::cmdExist( "krename" ) ) {
+ tools.append( "RENAME" );
+ tools.append( KrServices::fullPathName( "krename" ) );
+ }
+ // checksum utility
+ if (KrServices::cmdExist("md5deep")) {
+ tools.append("MD5");
+ tools.append(KrServices::fullPathName("md5deep", "checksum utility"));
+ } else if (KrServices::cmdExist("md5sum")) {
+ tools.append("MD5");
+ tools.append(KrServices::fullPathName("md5sum", "checksum utility"));
+ } else if (KrServices::cmdExist("sha1deep")) {
+ tools.append("MD5");
+ tools.append(KrServices::fullPathName("sha1deep", "checksum utility"));
+ } else if (KrServices::cmdExist("sha256deep")) {
+ tools.append("MD5");
+ tools.append(KrServices::fullPathName("sha256deep", "checksum utility"));
+ } else if (KrServices::cmdExist("tigerdeep")) {
+ tools.append("MD5");
+ tools.append(KrServices::fullPathName("tigerdeep", "checksum utility"));
+ } else if (KrServices::cmdExist("whirlpooldeep")) {
+ tools.append("MD5");
+ tools.append(KrServices::fullPathName("whirlpooldeep", "checksum utility"));
+ } else if (KrServices::cmdExist("cfv")) {
+ tools.append("MD5");
+ tools.append(KrServices::fullPathName("cfv", "checksum utility"));
+ }
+
+ return tools;
+}
+
+QString Krusader::getTempDir() {
+ // try to make krusader temp dir
+ krConfig->setGroup( "General" );
+ QString tmpDir = krConfig->readEntry( "Temp Directory", _TempDirectory );
+
+ if ( ! QDir( tmpDir ).exists() ) {
+ for ( int i = 1 ; i != -1 ; i = tmpDir.find( '/', i + 1 ) )
+ QDir().mkdir( tmpDir.left( i ) );
+ QDir().mkdir( tmpDir );
+ chmod( tmpDir.local8Bit(), 0777 );
+ }
+
+ // add a secure sub dir under the user UID
+ QString uid;
+ uid.sprintf( "%d", getuid() );
+ QDir( tmpDir ).mkdir( uid );
+ tmpDir = tmpDir + "/" + uid + "/";
+ chmod( tmpDir.local8Bit(), S_IRUSR | S_IWUSR | S_IXUSR );
+ // add a random sub dir to use
+ while ( QDir().exists( tmpDir ) )
+ tmpDir = tmpDir + kapp->randomString( 8 );
+ QDir().mkdir( tmpDir );
+
+ if ( !QDir( tmpDir ).isReadable() ) {
+ KMessageBox::error( krApp, "Could not create a temporary directory. Handling of Archives will not be possible until this is fixed." );
+ return QString::null;
+ }
+ return tmpDir;
+}
+
+QString Krusader::getTempFile() {
+ // try to make krusader temp dir
+ krConfig->setGroup( "General" );
+ QString tmpDir = krConfig->readEntry( "Temp Directory", _TempDirectory );
+
+ if ( ! QDir( tmpDir ).exists() ) {
+ for ( int i = 1 ; i != -1 ; i = tmpDir.find( '/', i + 1 ) )
+ QDir().mkdir( tmpDir.left( i ) );
+ QDir().mkdir( tmpDir );
+ chmod( tmpDir.local8Bit(), 0777 );
+ }
+
+ // add a secure sub dir under the user UID
+ QString uid;
+ uid.sprintf( "%d", getuid() );
+ QDir( tmpDir ).mkdir( uid );
+ tmpDir = tmpDir + "/" + uid + "/";
+ chmod( tmpDir.local8Bit(), S_IRUSR | S_IWUSR | S_IXUSR );
+
+ while ( QDir().exists( tmpDir ) )
+ tmpDir = tmpDir + kapp->randomString( 8 );
+ return tmpDir;
+}
+
+const char* Krusader::privIcon() {
+ if ( geteuid() )
+ return "krusader_user";
+ else
+ return "krusader_root";
+}
+
+bool Krusader::process(const QCString &fun, const QByteArray &/* data */, QCString &/* replyType */, QByteArray &/* replyData */) {
+ if (fun == "moveToTop()") {
+ moveToTop();
+ return true;
+ } else {
+ fprintf( stderr, "Processing DCOP call failed. Function unknown!\n" );
+ return false;
+ }
+}
+
+void Krusader::moveToTop() {
+ if( isHidden() )
+ show();
+
+ KWin::forceActiveWindow( winId() );
+}
+
+#include "krusader.moc"
diff --git a/krusader/krusader.desktop b/krusader/krusader.desktop
new file mode 100644
index 0000000..5223b79
--- /dev/null
+++ b/krusader/krusader.desktop
@@ -0,0 +1,86 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Krusader
+Exec=krusader -caption "%c" %i %m
+Icon=krusader_user.png
+Terminal=false
+Type=Application
+DocPath=krusader/index.html
+Categories=FileManager;Utility;Qt;KDE;
+Comment=Twin-Panel File Manager
+Comment[hu]=Kétpaneles fájlkezelő
+Comment[de]=Zwei-Fenster Dateimanager
+Comment[cs]=Dvojpanelový správce souborů
+GenericName=File Manager
+GenericName[af]=Lêer Bestuurder
+GenericName[ar]=مدير الملفات
+GenericName[az]=Fayl İdarəcisi
+GenericName[be]=Мэнэджэр файлаў
+GenericName[bg]=Файлов браузър
+GenericName[bn]=ফাইল ম্যানেজার
+GenericName[br]=Merour restroù
+GenericName[bs]=Upravitelj datotekama
+GenericName[ca]=Gestor de fitxers
+GenericName[cs]=Správce souborů
+GenericName[cy]=Rheolydd Ffeiliau
+GenericName[da]=Filhåndtering
+GenericName[de]=Dateimanager
+GenericName[el]=Διαχειριστής αρχείων
+GenericName[eo]=Dosieradministrilo
+GenericName[es]=Administrador de archivos
+GenericName[et]=Failihaldur
+GenericName[eu]=Fitxategi Kudeatzailea
+GenericName[fa]=مدیر پرونده
+GenericName[fi]=Tiedostonhallinta
+GenericName[fo]=Fíluhandfarari
+GenericName[fr]=Gestionnaire de fichiers
+GenericName[ga]=Bainisteoir Chomhad
+GenericName[gl]=Xestor de Ficheiros
+GenericName[he]=מנהל הקבצים
+GenericName[hi]=फ़ाइल प्रबंधक
+GenericName[hr]=Upravitelj datotekama
+GenericName[hsb]=Rjadowar datajow
+GenericName[hu]=Fájlkezelő
+GenericName[id]=Manajer File
+GenericName[is]=Skráastjóri
+GenericName[it]=File manager
+GenericName[ja]=ファイルマネージャ
+GenericName[ko]=파일 관리자
+GenericName[lo]=ເຄື່ອງມືການຈັດການແຟ້ມ
+GenericName[lt]=Bylų Tvarkyklė
+GenericName[lv]=Failu Menedžeris
+GenericName[mk]=Менаџер на датотеки
+GenericName[mn]=Файл удирдагч
+GenericName[ms]=Pengurus Fail
+GenericName[mt]=Manager tal-Fajls
+GenericName[nb]=Filbehandler
+GenericName[nds]=Dateimanager
+GenericName[nl]=Bestandsbeheerder
+GenericName[nn]=Filbehandlar
+GenericName[nso]=Molaodi wa Faele
+GenericName[oc]=Gestionari de fiquièrs
+GenericName[pl]=Menedżer plików
+GenericName[pt]=Gestor de Ficheiros
+GenericName[pt_BR]=Gerenciador de Arquivos
+GenericName[ro]=Managerul de fişiere
+GenericName[ru]=Файловый менеджер
+GenericName[sk]=Správca súborov
+GenericName[sl]=Upravljalnik datotek
+GenericName[sr]=Менаџер фајлова
+GenericName[sr@Latn]=Menadžer fajlova
+GenericName[ss]=Siphatsi selifayela
+GenericName[sv]=Filhanterare
+GenericName[ta]=கோப்பு மேலாளர்
+GenericName[tg]=Мудири файл
+GenericName[th]=เครื่องมือจัดการแฟ้ม
+GenericName[tr]=Dosya Yöneticisi
+GenericName[uk]=Менеджер файлів
+GenericName[uz]=Файл бошқарувчиси
+GenericName[ven]=Mulanguli wa faela
+GenericName[vi]=Trình quản lí file
+GenericName[wa]=Manaedjeu di fitchîs
+GenericName[xh]=Umphathi Wefayile
+GenericName[xx]=xxFile Managerxx
+GenericName[zh_CN]=文件管理器
+GenericName[zh_TW]=檔案管理程式
+GenericName[zu]=imenenja yamafayela
diff --git a/krusader/krusader.h b/krusader/krusader.h
new file mode 100644
index 0000000..f693326
--- /dev/null
+++ b/krusader/krusader.h
@@ -0,0 +1,274 @@
+
+/***************************************************************************
+ krusader.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ The main application ! what's more to say ?
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KRUSADER_H
+#define KRUSADER_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+// KDE includes
+#include <kapplication.h>
+#include <kparts/mainwindow.h>
+#include <kstdaction.h>
+#include <kaction.h>
+#include <kconfig.h>
+#include <kaccel.h>
+#include <qstringlist.h>
+#include <qtextstream.h>
+#include <kdebug.h>
+#include <dcopobject.h>
+
+#ifdef __KJSEMBED__
+class KrJS;
+#endif
+
+class KrusaderStatus;
+class KRPleaseWaitHandler;
+class KrusaderView;
+class KProcess;
+class KRslots;
+class KIconLoader;
+class KSystemTray;
+class UserMenu;
+class UserAction;
+class Expander;
+class KMountMan;
+class KrBookmarkHandler;
+class PopularUrls;
+class QueueManager;
+
+//static QTextOStream krOut(stdout);
+#define krOut kdDebug(50010)
+
+class Krusader : public KParts::MainWindow, public DCOPObject {
+ Q_OBJECT
+ public:
+ Krusader();
+ virtual ~Krusader();
+ void refreshView(); // re-create the main view
+ void configChanged();
+ /**
+ * This returns a defferent icon if krusader runs with root-privileges
+ * @return a character string with the specitif icon-name
+ */
+ static const char* privIcon();
+ static QStringList supportedTools(); // find supported tools
+
+ virtual bool process (const QCString &fun, const QByteArray &data, QCString &replyType, QByteArray &replyData);
+ void moveToTop();
+
+ public slots:
+ // increase the internal progress bar
+ void incProgress( KProcess *, char *buffer, int buflen );
+ void statusBarUpdate( QString& mess );
+ // in use by Krusader only
+ void saveSettings();
+ void savePosition();
+ void updateGUI( bool enforce = false );
+ void slotClose();
+ void setDirectExit() { directExit = true; }
+
+ protected:
+ bool queryExit() {
+ config->sync();
+ return true;
+ }
+ bool queryClose();
+ void setupActions();
+ void setupAccels();
+ bool versionControl(); // handle version differences in krusaderrc
+ void showEvent ( QShowEvent * );
+ void hideEvent ( QHideEvent * );
+ void moveEvent ( QMoveEvent * );
+ void resizeEvent ( QResizeEvent * );
+
+ public:
+ static Krusader *App; // a kApp style pointer
+ KMountMan *mountMan; // krusader's Mount Manager
+ KrusaderView *mainView; // The GUI
+ KConfig *config; // allow everyone to access the config
+ KIconLoader *iconLoader; // the app's icon loader
+ PopularUrls *popularUrls; // holds a sorted list of the most popular urls visited
+ QueueManager *queueManager;
+ // Actions
+ static KAction *actProperties, *actPack, *actUnpack, *actTest, *actCompare, *actCmdlinePopup;
+ static KAction *actCalculate, *actSelect, *actUnselect, *actSelectAll, *actLocate, *actSwitchFullScreenTE;
+ static KAction *actUnselectAll, *actInvert, *actSync, *actDiskUsage, *actSavePosition, *actCompDirs;
+ static KAction *actHomeTerminal, *actFTPConnect, *actFTPNewConnect, *actFTPDisconnect, *actProfiles;
+ static KAction *actExecFilter, *actCustomFilter, *actMountMan, *actNewTool, *actSwapPanels, *actSwapSides;
+ static KAction *actKonfigurator, *actToolsSetup, *actBack, *actRoot, *actFind, *actDirUp;
+ static KAction *actSelectColorMask, *actMultiRename, *actAllFilter, *actOpenLeftBm, *actOpenRightBm;
+ static KAction *actNewTab, *actDupTab, *actCloseTab, *actPreviousTab, *actNextTab, *actSplit;
+ static KAction *actCombine, *actUserMenu, *actManageUseractions, *actSyncDirs, *actSyncBrowse;
+ static KAction *actF2, *actF3, *actF4, *actF5, *actF6, *actF7, *actF8, *actF9, *actF10;
+ static KAction *actPopularUrls, *actLocationBar, *actJumpBack, *actSetJumpBack, *actCreateChecksum, *actMatchChecksum;
+ static KAction *actDetailedView, *actBriefView, *actCopy, *actPaste;
+ static KToggleAction *actToggleTerminal, *actVerticalMode;
+ static KRadioAction *actSelectNewerAndSingle, *actSelectNewer, *actSelectSingle,
+ *actSelectDifferentAndSingle, *actSelectDifferent;
+ /** actions for setting the execution mode of commands from commanddline */
+ static KRadioAction *actExecStartAndForget,
+ *actExecCollectSeparate,*actExecCollectTogether,
+ *actExecTerminalExternal,*actExecTerminalEmbedded;
+ KToggleAction *actToggleFnkeys, *actToggleCmdline, *actShowToolBar,
+ *actShowStatusBar, *actToggleHidden, *actCompareDirs;
+
+ static KRadioAction **compareArray[];
+ /** actions for setting the execution mode of commands from commanddline */
+ static KRadioAction **execTypeArray[];
+
+ // return a path to a temp dir or file we can use.
+ QString getTempDir();
+ QString getTempFile();
+
+ // the internal progress bar variales + functions
+ KRPleaseWaitHandler* plzWait;
+ void startWaiting( QString msg = "Please Wait", int count = 0 , bool cancel = false );
+ void stopWait();
+ bool wasWaitingCancelled() const;
+
+ KrusaderStatus *status;
+ KRslots *slot;
+ KAccel *accels; // global accelerators
+
+ static KPopupMenu *userActionMenu;
+ static UserMenu *userMenu;
+ static UserAction *userAction;
+ static KrBookmarkHandler *bookman;
+
+ #ifdef __KJSEMBED__
+ static KrJS *js;
+ static KAction *actShowJSConsole;
+ #endif
+
+ signals:
+ void changeMessage( QString );
+
+ private:
+ KSystemTray *sysTray;
+ QPoint oldPos;
+ QSize oldSize;
+ bool isStarting;
+ bool isExiting;
+ bool directExit;
+};
+
+// main modules
+#define krApp Krusader::App
+#define krConfig Krusader::App->config
+#define krMtMan (*(Krusader::App->mountMan))
+#define krBookMan Krusader::App->bookman
+#define SLOTS Krusader::App->slot
+#define krLoader Krusader::App->iconLoader
+
+#define MAIN_VIEW (krApp->mainView)
+#define ACTIVE_MNG (MAIN_VIEW->activeManager())
+#define ACTIVE_PANEL (MAIN_VIEW->activePanel)
+#define ACTIVE_FUNC (ACTIVE_PANEL->func)
+#define OTHER_MNG (MAIN_VIEW->inactiveManager())
+#define OTHER_PANEL (ACTIVE_PANEL->otherPanel)
+#define OTHER_FUNC (OTHER_PANEL->func)
+#define LEFT_PANEL (MAIN_VIEW->left)
+#define LEFT_FUNC (LEFT_PANEL->func)
+#define LEFT_MNG (MAIN_VIEW->leftMng)
+#define RIGHT_PANEL (MAIN_VIEW->right)
+#define RIGHT_FUNC (RIGHT_PANEL->func)
+#define RIGHT_MNG (MAIN_VIEW->rightMng)
+
+// krusader's actions - things krusader can do!
+#define krProperties Krusader::App->actProperties // file properties
+#define krPack Krusader::App->actPack // pack files into an archive
+#define krUnpack Krusader::App->actUnpack // unpack archive
+#define krTest Krusader::App->actTest // test archive
+#define krCompare Krusader::App->actCompare // compare 2 files by content
+#define krCalculate Krusader::App->actCalculate // calculate occupied space
+#define krCreateCS Krusader::App->actCreateChecksum
+#define krMatchCS Krusader::App->actMatchChecksum
+#define krSelect Krusader::App->actSelect // select a group by filter
+#define krSelectAll Krusader::App->actSelectAll // select all files
+#define krUnselect Krusader::App->actUnselect // unselect by filter
+#define krUnselectAll Krusader::App->actUnselectAll // remove all selections
+#define krInvert Krusader::App->actInvert // invert the selection
+#define krSyncDirs Krusader::App->actSync // syncronize directories
+#define krHomeTerm Krusader::App->actHomeTerminal // open terminal@home dir
+#define krFTPConnect Krusader::App->actFTPConnect // connect to an ftp
+#define krFTPNew Krusader::App->actFTPNewConnect // create a new connection
+#define krFTPDiss Krusader::App->actFTPDisconnect // disconnect an FTP session
+#define krAllFiles Krusader::App->actAllFilter // show all files in list
+#define krExecFiles Krusader::App->actExecFilter // show only executables
+#define krCustomFiles Krusader::App->actCustomFilter // show a custom set of files
+#define krMountMan Krusader::App->actMountMan // run Mount-manager
+#define krNewTool Krusader::App->actNewTool // Add a new tool to menu
+#define krKonfigurator Krusader::App->actKonfigurator
+#define krToolsSetup Krusader::App->actToolsSetup // setup the tools menu
+#define krBack Krusader::App->actBack
+#define krRoot Krusader::App->actRoot
+#define krFind Krusader::App->actFind // find files
+#define krMultiRename Krusader::App->actMultiRename
+#define krToggleTerminal Krusader::App->actToggleTerminal
+#define krToggleSortByExt Krusader::App->actToggleSortByExt// Sort by extention
+#define krOpenLeftBm Krusader::App->actOpenLeftBm // open left bookmarks
+#define krOpenRightBm Krusader::App->actOpenRightBm // open left bookmarks
+#define krDirUp Krusader::App->actDirUp
+#define krCmdlinePopup Krusader::App->actCmdlinePopup
+#define krNewTab Krusader::App->actNewTab
+#define krDupTab Krusader::App->actDupTab
+#define krCloseTab Krusader::App->actCloseTab
+#define krNextTab Krusader::App->actNextTab
+#define krPreviousTab Krusader::App->actPreviousTab
+#define krSplit Krusader::App->actSplit
+#define krCombine Krusader::App->actCombine
+#define krUserMenu Krusader::App->actUserMenu
+#define krUserActionMenu Krusader::App->userActionMenu
+#define krUserAction Krusader::App->userAction
+#define krF2 Krusader::App->actF2
+#define krF3 Krusader::App->actF3
+#define krF4 Krusader::App->actF4
+#define krF5 Krusader::App->actF5
+#define krF6 Krusader::App->actF6
+#define krF7 Krusader::App->actF7
+#define krF8 Krusader::App->actF8
+#define krF9 Krusader::App->actF9
+#define krF10 Krusader::App->actF10
+#define krPopularUrls Krusader::App->actPopularUrls
+#define krLocationBar Krusader::App->actLocationBar
+#define krJumpBack Krusader::App->actJumpBack
+#define krSetJumpBack Krusader::App->actSetJumpBack
+
+#ifdef __KJSEMBED__
+#define krJS Krusader::App->js
+#define krJSConsole Krusader::App->actShowJSConsole
+#endif
+
+#endif
diff --git a/krusader/krusader_root-mode.desktop b/krusader/krusader_root-mode.desktop
new file mode 100644
index 0000000..7922927
--- /dev/null
+++ b/krusader/krusader_root-mode.desktop
@@ -0,0 +1,90 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Krusader - root-mode
+Name[de]=Krusader - root-Modus
+Name[cs]=Krusader s právy roota
+Exec=krusader -caption "%c" %i %m
+Icon=krusader_root.png
+Terminal=false
+Type=Application
+DocPath=krusader/index.html
+Categories=Qt;KDE;System;
+OnlyShowIn=KDE;
+X-KDE-SubstituteUID=true
+X-KDE-Username=root
+Comment=Twin-Panel File Manager with root-privileges
+Comment[de]=Zwei-Fenster Dateimanager (Systemverwaltungsmodus)
+Comment[cs]=Dvojpanelový správce souborů s právy Roota
+GenericName=File Manager
+GenericName[af]=Lêer Bestuurder
+GenericName[ar]=مدير الملفات
+GenericName[az]=Fayl İdarəcisi
+GenericName[be]=Мэнэджэр файлаў
+GenericName[bg]=Файлов браузър
+GenericName[bn]=ফাইল ম্যানেজার
+GenericName[br]=Merour restroù
+GenericName[bs]=Upravitelj datotekama
+GenericName[ca]=Gestor de fitxers
+GenericName[cs]=Správce souborů
+GenericName[cy]=Rheolydd Ffeiliau
+GenericName[da]=Filhåndtering
+GenericName[de]=Dateimanager
+GenericName[el]=Διαχειριστής αρχείων
+GenericName[eo]=Dosieradministrilo
+GenericName[es]=Administrador de archivos
+GenericName[et]=Failihaldur
+GenericName[eu]=Fitxategi Kudeatzailea
+GenericName[fa]=مدیر پرونده
+GenericName[fi]=Tiedostonhallinta
+GenericName[fo]=Fíluhandfarari
+GenericName[fr]=Gestionnaire de fichiers
+GenericName[ga]=Bainisteoir Chomhad
+GenericName[gl]=Xestor de Ficheiros
+GenericName[he]=מנהל הקבצים
+GenericName[hi]=फ़ाइल प्रबंधक
+GenericName[hr]=Upravitelj datotekama
+GenericName[hsb]=Rjadowar datajow
+GenericName[hu]=Fájlkezelő
+GenericName[id]=Manajer File
+GenericName[is]=Skráastjóri
+GenericName[it]=File manager
+GenericName[ja]=ファイルマネージャ
+GenericName[ko]=파일 관리자
+GenericName[lo]=ເຄື່ອງມືການຈັດການແຟ້ມ
+GenericName[lt]=Bylų Tvarkyklė
+GenericName[lv]=Failu Menedžeris
+GenericName[mk]=Менаџер на датотеки
+GenericName[mn]=Файл удирдагч
+GenericName[ms]=Pengurus Fail
+GenericName[mt]=Manager tal-Fajls
+GenericName[nb]=Filbehandler
+GenericName[nds]=Dateimanager
+GenericName[nl]=Bestandsbeheerder
+GenericName[nn]=Filbehandlar
+GenericName[nso]=Molaodi wa Faele
+GenericName[oc]=Gestionari de fiquièrs
+GenericName[pl]=Menedżer plików
+GenericName[pt]=Gestor de Ficheiros
+GenericName[pt_BR]=Gerenciador de Arquivos
+GenericName[ro]=Managerul de fişiere
+GenericName[ru]=Файловый менеджер
+GenericName[sk]=Správca súborov
+GenericName[sl]=Upravljalnik datotek
+GenericName[sr]=Менаџер фајлова
+GenericName[sr@Latn]=Menadžer fajlova
+GenericName[ss]=Siphatsi selifayela
+GenericName[sv]=Filhanterare
+GenericName[ta]=கோப்பு மேலாளர்
+GenericName[tg]=Мудири файл
+GenericName[th]=เครื่องมือจัดการแฟ้ม
+GenericName[tr]=Dosya Yöneticisi
+GenericName[uk]=Менеджер файлів
+GenericName[uz]=Файл бошқарувчиси
+GenericName[ven]=Mulanguli wa faela
+GenericName[vi]=Trình quản lí file
+GenericName[wa]=Manaedjeu di fitchîs
+GenericName[xh]=Umphathi Wefayile
+GenericName[xx]=xxFile Managerxx
+GenericName[zh_CN]=文件管理器
+GenericName[zh_TW]=檔案管理程式
+GenericName[zu]=imenenja yamafayela
diff --git a/krusader/krusaderapp.h b/krusader/krusaderapp.h
new file mode 100644
index 0000000..2004147
--- /dev/null
+++ b/krusader/krusaderapp.h
@@ -0,0 +1,31 @@
+#ifndef KRUSADERAPP_H
+#define KRUSADERAPP_H
+
+#include <kapplication.h>
+#include "X11/Xlib.h"
+
+// declare a dummy kapplication, just to get the X focusin focusout events
+class KrusaderApp: public KApplication {
+ Q_OBJECT
+public:
+ KrusaderApp(): KApplication() {}
+ bool x11EventFilter ( XEvent *e ) {
+ switch (e->type) {
+ case FocusIn:
+ emit windowActive();
+ break;
+ case FocusOut:
+ emit windowInactive();
+ break;
+
+ }
+ //return false; // event should be processed normally
+ return KApplication::x11EventFilter(e);
+ }
+signals:
+ void windowActive();
+ void windowInactive();
+};
+
+
+#endif // KRUSADERAPP_H
diff --git a/krusader/krusaderui.rc b/krusader/krusaderui.rc
new file mode 100644
index 0000000..54c649e
--- /dev/null
+++ b/krusader/krusaderui.rc
@@ -0,0 +1,193 @@
+<!DOCTYPE kpartgui ><kpartgui version="16" name="krusader" >
+ <MenuBar>
+ <Menu name="file" >
+ <text>&amp;File</text>
+ <Action name="edit_new_file" />
+ <Action name="F7_Mkdir" />
+ <Action name="new symlink" />
+ <Separator/>
+ <Action name="F3_View" />
+ <Action name="F4_Edit" />
+ <Action name="F5_Copy" />
+ <Action name="F6_Move" />
+ <Separator/>
+ <Action name="pack" />
+ <Action name="unpack" />
+ <Action name="test archives" />
+ <Separator/>
+ <Action name="compare" />
+ <Action name="multirename" />
+ <Separator/>
+ <Action name="create checksum" />
+ <Action name="match checksum" />
+ <Separator/>
+ <Action name="split" />
+ <Action name="combine" />
+ <Separator/>
+ <!--
+ <Action name="std_print" />
+ <Separator/>
+ -->
+ <Action name="std_quit" />
+ </Menu>
+ <Action name="rightclick menu" />
+ <Action name="cmdline popup" />
+ <Menu name="edit">
+ <text>&amp;Edit</text>
+ <Action name="std_cut" />
+ <Action name="std_copy" />
+ <Action name="std_paste" />
+ <Action name="F9_Rename" />
+ <Action name="F8_Delete" />
+ <Separator/>
+ <Action name="select group" />
+ <Action name="unselect group" />
+ <Action name="select all" />
+ <Action name="unselect all" />
+ <Action name="invert" />
+ <Separator/>
+ <Action name="compare dirs" />
+ <Menu name="compare setup">
+ <text>Compare Se&amp;tup</text>
+ <Action name="select_newer_and_single" />
+ <Action name="select_single" />
+ <Action name="select_newer" />
+ <Action name="select_different_and_single" />
+ <Action name="select_different" />
+ </Menu>
+ <Separator/>
+ <Action name="calculate" />
+ <Action name="properties" />
+ </Menu>
+ <Menu name="myview" >
+ <text>&amp;View</text>
+ <Action name="detailed_view" />
+ <Action name="brief_view" />
+ <Separator/>
+ <Action name="toggle hidden files" />
+ <Action name="all files" />
+ <Action name="exec files" />
+ <Action name="custom files" />
+ <Separator/>
+ <Action name="changeremoteencoding" />
+ <Separator/>
+ <Action name="std_redisplay" />
+ </Menu>
+ <Menu name="go" >
+ <text>&amp;Go</text>
+ <Action name="back" />
+ <Action name="dirUp" />
+ <Action name="root" />
+ <Action name="std_home" />
+ <Action name="Popular_Urls" />
+ <Separator/>
+ <Action name="set_jump_back" />
+ <Action name="jump_back" />
+ </Menu>
+ <Menu name="useractionmenu" >
+ <text>User&amp;actions</text>
+ <Action name="manage useractions" />
+ <Separator/>
+ </Menu>
+ <Menu name="_tools" ><!-- FIXME tools menu won't show up before the options menu, but does when the name attribute is renamed?! -->
+ <text>&amp;Tools</text>
+ <Action name="find" />
+ <Action name="locate" />
+ <Separator/>
+ <Action name="sync dirs" />
+ <Action name="mountman" />
+ <Action name="disk usage" />
+ <Separator/>
+ <Action name="ftp new connection" />
+ <Action name="ftp disconnect" />
+ <Separator/>
+ <Action name="terminal@home" />
+ <Action name="F2_Terminal" />
+ <Action name="root krusader" />
+ <Separator/>
+ <Action name="JS_Console" />
+ <!-- <Action name="user menu" /> -->
+ <!--
+ <Separator/>
+ <Action name="add tool" />
+ <Separator/>
+ -->
+ </Menu>
+ <Menu name="options" >
+ <text>&amp;Settings</text>
+ <!-- Show Menubar -->
+ <Action name="std_menubar" />
+ <Action name="std_toolbar" />
+ <Action name="toggle actions toolbar"/>
+ <Action name="std_statusbar" />
+ <Action name="toggle fn bar" />
+ <Action name="toggle terminal emulator" />
+ <Action name="toggle command line" />
+ <Menu name="command_execution_mode" >
+ <text>Command Execution Mode Se&amp;tup</text>
+ <Action name="exec_start_and_forget" />
+ <Action name="exec_collect_separate" />
+ <Action name="exec_collect_together" />
+ <Action name="exec_terminal_external" />
+ <Action name="exec_terminal_embedded" />
+ </Menu>
+ <Separator/>
+ <Action name="std_config_keys" />
+ <Action name="std_config_toolbar" />
+ <!-- <Action name="tools setup" /> -->
+ <Action name="konfigurator" />
+ </Menu>
+ <Menu name="window" >
+ <text>&amp;Window</text>
+ <Action name="new tab" />
+ <Action name="duplicate tab" />
+ <Action name="close tab" />
+ <Action name="next tab" />
+ <Action name="previous tab" />
+ <Separator/>
+ <Action name="profile" />
+ <Separator/>
+ <Action name="swap panels" />
+ <Action name="toggle swap sides" />
+ <Action name="toggle vertical mode" />
+ <Separator/>
+ <Action name="switch_fullscreen_te" />
+ <Action name="save position" />
+ </Menu>
+ <Menu name="help" >
+ <text>&amp;Help</text>
+ </Menu>
+ </MenuBar>
+ <ToolBar noMerge="1" name="mainToolBar" fullWidth="true" >
+ <Action name="back" />
+ <Action name="dirUp" />
+ <Action name="std_home" />
+ <Action name="std_redisplay" />
+ <Separator name="separator_2" />
+ <Action name="select all" />
+ <Action name="unselect all" />
+ <Action name="select group" />
+ <Separator name="separator_1" />
+ <Action name="find" />
+ <Action name="edit_new_file" />
+ <Action name="compare" />
+ <Action name="unpack" />
+ <Action name="pack" />
+ <Separator name="separator_0" />
+ <Action name="mountman" />
+ <Action name="ftp connect" />
+ <Action name="ftp new connection" />
+ <Action name="profile" />
+ </ToolBar>
+ <ToolBar noMerge="1" name="actionsToolBar" fullWidth="false" >
+ </ToolBar>
+ <ActionProperties>
+ <Action accel="" name="sysinfo" />
+ </ActionProperties>
+</kpartgui>
+
+<!--
+ <Action name="full panel" />
+ <Action name="tree panel" />
+ <Action name="quickview panel" />
+-->
diff --git a/krusader/krusaderview.cpp b/krusader/krusaderview.cpp
new file mode 100644
index 0000000..b203d1d
--- /dev/null
+++ b/krusader/krusaderview.cpp
@@ -0,0 +1,415 @@
+/***************************************************************************
+ krusaderview.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+ Description
+***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+// Qt includes
+#include <qwhatsthis.h>
+#include <kstatusbar.h>
+#include <kmenubar.h>
+#include <kshortcut.h>
+// Krusader includes
+#include "krusaderview.h"
+#include "krusader.h"
+#include "krslots.h"
+#include "defaults.h"
+#include "Panel/listpanel.h"
+#include "Panel/panelfunc.h"
+#include "GUI/kcmdline.h"
+#include "GUI/kfnkeys.h"
+#include "resources.h"
+#include "panelmanager.h"
+#include <klibloader.h> //<>
+#include "GUI/profilemanager.h"
+#include "Dialogs/percentalsplitter.h"
+#include "krservices.h"
+#include <qclipboard.h>
+
+KrusaderView::KrusaderView( QWidget *parent ) : QWidget( parent, "KrusaderView" ), activePanel(0),
+ konsole_part( 0L ) {}
+
+void KrusaderView::start( QStringList leftTabs, QStringList leftTypes, QValueList<int> leftProps, int leftActiveTab,
+ QStringList rightTabs, QStringList rightTypes, QValueList<int> rightProps, int rightActiveTab,
+ bool leftSideActive ) {
+ ////////////////////////////////
+ // make a 1x1 mainLayout, it will auto-expand:
+ mainLayout = new QGridLayout( this, 1, 1 );
+ // vertical splitter
+ vert_splitter = new QSplitter( this ); // splits between panels and terminal/cmdline
+ vert_splitter->setOrientation( QObject::Vertical );
+ // horizontal splitter
+ horiz_splitter = new PercentalSplitter( vert_splitter );
+ ( terminal_dock = new QHBox( vert_splitter ) ) ->hide(); // create it hidden
+ // create a command line thing
+ cmdLine = new KCMDLine( this );
+
+ // add a panel manager for each side of the splitter
+ leftMng = new PanelManager(horiz_splitter, true );
+ rightMng = new PanelManager(horiz_splitter, false );
+
+ // now, create the panels inside the manager
+ //left = new ListPanel( leftMng, true );
+ //right = new ListPanel( rightMng, false );
+ left = leftMng->createPanel( leftTypes[ 0 ] );
+ right = rightMng->createPanel( rightTypes[ 0 ] );
+
+ left->setOther( right );
+ right->setOther( left );
+
+ // create the function keys widget
+ fnKeys = new KFnKeys( this );
+ fnKeys->hide();
+ QWhatsThis::add
+ ( fnKeys, i18n( "Function keys allow performing fast "
+ "operations on files." ) );
+
+ // and insert the whole thing into the main layout... at last
+ mainLayout->addWidget( vert_splitter, 0, 0 ); //<>
+ mainLayout->addWidget( cmdLine, 1, 0 );
+ mainLayout->addWidget( fnKeys, 2, 0 );
+ mainLayout->activate();
+
+ // get the last saved sizes of the splitter
+ krConfig->setGroup( "Private" );
+ QValueList<int> lst = krConfig->readIntListEntry( "Splitter Sizes" );
+ if ( lst.isEmpty() )
+ {
+ lst = horiz_splitter->sizes();
+ int avg = (lst[ 0 ] + lst[ 1 ] )/2;
+ lst[ 0 ] = lst[ 1 ] = avg;
+ }
+ horiz_splitter->setSizes( lst );
+
+ verticalSplitterSizes = krConfig->readIntListEntry( "Terminal Emulator Splitter Sizes" );
+
+ show();
+
+ qApp->processEvents();
+
+ // make the left panel focused at program start
+ rightMng->startPanel( right, rightTabs[ 0 ] );
+ leftMng->startPanel( left, leftTabs[ 0 ] );
+ activePanel = left;
+ activePanel->slotFocusOnMe(); // left starts out active
+ left->setProperties( leftProps[ 0 ] );
+ right->setProperties( rightProps[ 0 ] );
+
+ for(unsigned int i = 1; i < leftTabs.count(); i++ )
+ leftMng->slotNewTab( leftTabs[ i ], false, leftTypes[ i ], leftProps[ i ] );
+
+ for(unsigned int j = 1; j < rightTabs.count(); j++ )
+ rightMng->slotNewTab( rightTabs[ j ], false, rightTypes[ j ], rightProps[ j ] );
+
+ leftMng->setActiveTab( leftActiveTab );
+ rightMng->setActiveTab( rightActiveTab );
+
+ if( leftSideActive )
+ MAIN_VIEW->left->slotFocusOnMe();
+ else
+ MAIN_VIEW->right->slotFocusOnMe();
+}
+
+// updates the command line whenever current panel changes
+//////////////////////////////////////////////////////////
+void KrusaderView::slotCurrentChanged( QString p ) {
+ cmdLine->setCurrent( p );
+ if ( konsole_part != 0L && konsole_part->widget() != 0L ) {
+ KConfigGroupSaver grp(krConfig, "General");
+ if (krConfig->readBoolEntry("Send CDs", _SendCDs)) // hopefully, this is cached in kconfig
+ if( !konsole_part->url().equals( KURL( p ), true ) )
+ konsole_part->openURL( KURL( p ) );
+ }
+}
+
+void KrusaderView::cmdLineFocus() { // command line receive's keyboard focus
+ cmdLine->setFocus();
+}
+
+void KrusaderView::cmdLineUnFocus() { // return focus to the active panel
+ activePanel->slotFocusOnMe();
+}
+
+/** if the KonsolePart for the Terminal Emulator is not yet loaded, load it */
+void KrusaderView::createTE() {
+ if ( konsole_part == 0L ) { // konsole part is not yet loaded
+ KLibFactory * factory = KLibLoader::self() ->factory( "libkonsolepart" );
+ if ( factory ) {
+ QWidget *focusW = qApp->focusWidget();
+ // Create the part
+ konsole_part = ( KParts::ReadOnlyPart * )
+ factory->create( terminal_dock, "konsolepart",
+ "KParts::ReadOnlyPart" );
+ if( konsole_part ) { //loaded successfully
+ connect( konsole_part, SIGNAL( destroyed() ),
+ this, SLOT( killTerminalEmulator() ) );
+ qApp->installEventFilter( this );
+ } else {
+ qApp->removeEventFilter( this );
+ }
+ /*the Terminal Emulator may be hidden (if we are creating it only
+ to send command there and see the results later */
+ if( focusW ) {
+ focusW->setFocus();
+ }
+ else {
+ activePanel->slotFocusOnMe();
+ }
+ } else
+ konsole_part = 0L;
+ }
+}
+
+// Tab - switch focus
+void KrusaderView::panelSwitch() { activePanel->otherPanel->slotFocusOnMe(); }
+void KrusaderView::slotSetActivePanel( ListPanel *p ) { activePanel = p; }
+
+void KrusaderView::slotTerminalEmulator( bool show ) {
+ KConfigGroupSaver grp(krConfig, "Look&Feel");
+ bool fullscreen = krConfig->readBoolEntry("Fullscreen Terminal Emulator", false);
+ static bool fnKeysShown=true; // first time init. should be overridden
+ static bool cmdLineShown=true;
+ static bool statusBarShown=true;
+ static bool toolBarShown=true;
+ static bool menuBarShown=true;
+
+ if ( !show ) { // hiding the terminal
+ activePanel->slotFocusOnMe();
+ if( terminal_dock->isVisible() && !fullscreen )
+ verticalSplitterSizes = vert_splitter->sizes();
+
+ // BUGFIX: when the terminal emulator is toggled on, first it is shown in minimum size
+ // then QSplitter resizes it to the desired size.
+ // this minimum resize scrolls up the content of the konsole widget
+ // SOLUTION:
+ // we hide the console widget while the resize ceremony happens, then reenable it
+ if( konsole_part )
+ konsole_part->widget()->hide(); // hide the widget to prevent from resize
+
+ terminal_dock->hide();
+ QValueList<int> newSizes;
+ newSizes.push_back( vert_splitter->height() );
+ newSizes.push_back( 0 );
+ vert_splitter->setSizes( newSizes );
+ // in full screen, we unhide everything that was hidden before
+ if (fullscreen) {
+ leftMng->show();
+ rightMng->show();
+ if (fnKeysShown) fnKeys->show();
+ if (cmdLineShown) cmdLine->show();
+ if (statusBarShown) krApp->statusBar()->show();
+ if (toolBarShown) {
+ krApp->toolBar()->show();
+ krApp->toolBar("actionsToolBar")->show();
+ }
+ if (menuBarShown) krApp->menuBar()->show();
+ }
+ return ;
+ }
+ // else implied
+ createTE();
+ if ( konsole_part ) { // if we succeeded in creating the konsole
+ if( !verticalSplitterSizes.empty() )
+ vert_splitter->setSizes( verticalSplitterSizes );
+
+ terminal_dock->show();
+ slotCurrentChanged( activePanel->realPath() );
+
+ // BUGFIX: TE scrolling bug (see upper)
+ // show the Konsole part delayed
+ QTimer::singleShot( 0, konsole_part->widget(), SLOT( show() ) );
+
+ if( konsole_part->widget() ) {
+ konsole_part->widget()->setFocus();
+
+ }
+ krToggleTerminal->setChecked( true );
+ // in full screen mode, we hide everything else, but first, see what was actually shown
+ if (fullscreen) {
+ fnKeysShown = !fnKeys->isHidden();
+ cmdLineShown = !cmdLine->isHidden();
+ statusBarShown = !krApp->statusBar()->isHidden();
+ toolBarShown = !krApp->toolBar()->isHidden();
+ menuBarShown = !krApp->menuBar()->isHidden();
+ leftMng->hide();
+ rightMng->hide();
+ fnKeys->hide();
+ cmdLine->hide();
+ krApp->statusBar()->hide();
+ krApp->toolBar()->hide();
+ krApp->toolBar("actionsToolBar")->hide();
+ krApp->menuBar()->hide();
+ }
+ } else {
+ terminal_dock->hide();
+ krToggleTerminal->setChecked( false );
+ }
+}
+
+void KrusaderView::focusTerminalEmulator()
+{
+ if ( MAIN_VIEW->terminal_dock->isVisible() && MAIN_VIEW->konsole_part && MAIN_VIEW->konsole_part->widget() )
+ MAIN_VIEW->konsole_part->widget()->setFocus();
+}
+
+void KrusaderView::switchFullScreenTE()
+{
+ if( terminal_dock->isVisible() && konsole_part && konsole_part->widget() && konsole_part->widget()->isVisible() ) {
+ KConfigGroup grp(krConfig, "Look&Feel");
+ bool fullscreen=grp.readBoolEntry("Fullscreen Terminal Emulator", false);
+ slotTerminalEmulator( false );
+ grp.writeEntry("Fullscreen Terminal Emulator", !fullscreen);
+ slotTerminalEmulator( true );
+ }
+}
+
+
+bool KrusaderView::eventFilter ( QObject * watched, QEvent * e ) {
+ if( e->type() == QEvent::AccelOverride && konsole_part && konsole_part->widget() == watched ) {
+ QKeyEvent *ke = (QKeyEvent *)e;
+ if( ( ke->key() == Key_Insert ) && ( ke->state() == ShiftButton ) ) {
+ ke->accept();
+ return true;
+ }
+ if( ( ke->state() == 0 || ke->state() == ShiftButton ) &&
+ ( ke->key() >= 32 ) && (ke->key() <= 127 ) ) {
+ ke->accept();
+ return true;
+ }
+ }
+ else if( e->type() == QEvent::KeyPress && konsole_part && konsole_part->widget() == watched ) {
+ QKeyEvent *ke = (QKeyEvent *)e;
+ KKey pressedKey( ke );
+
+ if( Krusader::actToggleTerminal->shortcut().contains( pressedKey ) ) {
+ Krusader::actToggleTerminal->activate();
+ return true;
+ }
+
+ if( Krusader::actSwitchFullScreenTE->shortcut().contains( pressedKey ) ) {
+ Krusader::actSwitchFullScreenTE->activate();
+ return true;
+ }
+
+ if( ( ke->key() == Key_Enter || ke->key() == Key_Return ) && ( ( ke->state() & ~ShiftButton ) == ControlButton ) ) {
+
+ QString filename = ACTIVE_PANEL->view->getCurrentItem();
+ if( filename == QString::null || filename == ".." )
+ return true;
+ if( ke->state() & ShiftButton ) {
+ QString path=vfs::pathOrURL( ACTIVE_FUNC->files()->vfs_getOrigin(), 1 );
+ filename = path+filename;
+ }
+
+ filename = KrServices::quote( filename );
+
+ QKeyEvent keyEvent( QEvent::KeyPress, 0, -1, 0, QString( " " ) + filename + QString( " " ));
+ QApplication::sendEvent( konsole_part->widget(), &keyEvent );
+ return true;
+ } else if( ( ke->key() == Key_Down ) && ( ke->state() == ControlButton ) ) {
+ if( cmdLine->isVisible() )
+ cmdLine->setFocus();
+ return true;
+ } else if( ( ( ke->key() == Key_Up ) && ( ke->state() == ControlButton ) ) ||
+ ( ke->state() == ( ControlButton | ShiftButton ) ) ) {
+ ACTIVE_PANEL->slotFocusOnMe();
+ return true;
+ } else if( Krusader::actPaste->shortcut().contains( pressedKey ) ) {
+ QString text = QApplication::clipboard()->text();
+ if ( ! text.isEmpty() )
+ {
+ text.replace("\n", "\r");
+ QKeyEvent keyEvent(QEvent::KeyPress, 0,-1,0, text);
+ QApplication::sendEvent( konsole_part->widget(), &keyEvent );
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+QValueList<int> KrusaderView::getTerminalEmulatorSplitterSizes() {
+ if( terminal_dock->isVisible() )
+ return vert_splitter->sizes();
+ else
+ return verticalSplitterSizes;
+}
+
+void KrusaderView::killTerminalEmulator() {
+ konsole_part = 0L;
+ slotTerminalEmulator( false ); // hide the docking widget
+ krToggleTerminal->setChecked( false );
+}
+
+
+void KrusaderView::profiles( QString profileName )
+{
+ ProfileManager profileManager( "Panel" );
+ profileManager.hide();
+ connect( &profileManager, SIGNAL( saveToProfile( QString ) ), this, SLOT( savePanelProfiles( QString ) ) );
+ connect( &profileManager, SIGNAL( loadFromProfile( QString ) ), this, SLOT( loadPanelProfiles( QString ) ) );
+ if( profileName.isEmpty() )
+ profileManager.profilePopup();
+ else
+ profileManager.loadProfile( profileName );
+}
+
+void KrusaderView::loadPanelProfiles( QString group )
+{
+ krConfig->setGroup( group );
+ MAIN_VIEW->leftMng->loadSettings( krConfig, "Left Tabs" );
+ krConfig->setGroup( group );
+ MAIN_VIEW->rightMng->loadSettings( krConfig, "Right Tabs" );
+ krConfig->setGroup( group );
+ MAIN_VIEW->leftMng->setActiveTab( krConfig->readNumEntry( "Left Active Tab", 0 ) );
+ krConfig->setGroup( group );
+ MAIN_VIEW->rightMng->setActiveTab( krConfig->readNumEntry( "Right Active Tab", 0 ) );
+ krConfig->setGroup( group );
+ if( krConfig->readBoolEntry( "Left Side Is Active", true ) )
+ MAIN_VIEW->left->slotFocusOnMe();
+ else
+ MAIN_VIEW->right->slotFocusOnMe();
+}
+
+void KrusaderView::savePanelProfiles( QString group )
+{
+ krConfig->setGroup( group );
+
+ MAIN_VIEW->leftMng->saveSettings( krConfig, "Left Tabs", false );
+ krConfig->writeEntry( "Left Active Tab", MAIN_VIEW->leftMng->activeTab() );
+ MAIN_VIEW->rightMng->saveSettings( krConfig, "Right Tabs", false );
+ krConfig->writeEntry( "Right Active Tab", MAIN_VIEW->rightMng->activeTab() );
+ krConfig->writeEntry( "Left Side Is Active", MAIN_VIEW->activePanel->isLeft() );
+}
+
+void KrusaderView::toggleVerticalMode() {
+ if (horiz_splitter->orientation() == QSplitter::Vertical)
+ horiz_splitter->setOrientation(QSplitter::Horizontal);
+ else horiz_splitter->setOrientation(QSplitter::Vertical);
+}
+
+#include "krusaderview.moc"
diff --git a/krusader/krusaderview.h b/krusader/krusaderview.h
new file mode 100644
index 0000000..1f4f566
--- /dev/null
+++ b/krusader/krusaderview.h
@@ -0,0 +1,110 @@
+/***************************************************************************
+ krusaderview.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KRUSADERVIEW_H
+#define KRUSADERVIEW_H
+
+// KDE includes
+#include <klistview.h>
+#include <klocale.h>
+#include <kaccel.h>
+#include <kapplication.h>
+#include <kparts/part.h>
+
+// QT includes
+#include <qlayout.h>
+#include <qsplitter.h>
+#include <qwidget.h>
+#include <qpushbutton.h>
+#include <qhbox.h>
+#include <qvaluelist.h>
+
+class PanelManager;
+class ListPanel;
+
+// forward declaration
+class KFnKeys;
+class KCMDLine;
+
+class KrusaderView : public QWidget {
+ Q_OBJECT
+
+public:
+ KrusaderView(QWidget *parent=0);
+ virtual ~KrusaderView(){}
+ void start(QStringList leftTabs, QStringList leftTypes, QValueList<int> leftProps, int leftActiveTab,
+ QStringList rightTabs, QStringList rightTypes, QValueList<int> rightProps, int rightActiveTab,
+ bool leftSideActive);
+ void cmdLineFocus(); // command line receive's keyboard focus
+ void cmdLineUnFocus();// return focus from command line to active panel
+ inline PanelManager *activeManager() const { return (activePanel==left ? leftMng : rightMng); }
+ inline PanelManager *inactiveManager() const { return (activePanel==left ? rightMng : leftMng); }
+ QValueList<int> getTerminalEmulatorSplitterSizes();
+ virtual bool eventFilter ( QObject * watched, QEvent * e );
+ /** if the KonsolePart for the Terminal Emulator is not yet loaded, load it */
+ void createTE();
+
+public slots:
+ void slotCurrentChanged(QString p);
+ void slotSetActivePanel(ListPanel *p);
+ void slotTerminalEmulator(bool);
+ // manage the function keys to the CURRENT vfs
+ //////////////////////////////////////////////
+ // Tab - switch focus
+ void panelSwitch();
+ void toggleVerticalMode();
+
+ void focusTerminalEmulator();
+ void switchFullScreenTE();
+
+ void profiles( QString profileName = QString::null );
+ void loadPanelProfiles( QString group );
+ void savePanelProfiles( QString group );
+
+protected slots:
+ void killTerminalEmulator();
+
+public:
+ ListPanel *activePanel;
+ ListPanel *left,*right; // the actual panels
+ PanelManager *leftMng, *rightMng; // saving them for panel swaps
+ KFnKeys *fnKeys; // function keys
+ KCMDLine *cmdLine; // command line widget
+ QHBox *terminal_dock; // docking widget for terminal emulator
+ KParts::ReadOnlyPart *konsole_part; // the actual part pointer
+ QSplitter *horiz_splitter, *vert_splitter;
+ QValueList<int> verticalSplitterSizes;
+
+private:
+ QGridLayout *mainLayout, *terminal_layout;
+};
+
+#endif
diff --git a/krusader/lo16-app-krusader.png b/krusader/lo16-app-krusader.png
new file mode 100644
index 0000000..0698970
--- /dev/null
+++ b/krusader/lo16-app-krusader.png
Binary files differ
diff --git a/krusader/lo32-app-krusader.png b/krusader/lo32-app-krusader.png
new file mode 100644
index 0000000..55d0a92
--- /dev/null
+++ b/krusader/lo32-app-krusader.png
Binary files differ
diff --git a/krusader/lo32-app-krusader2.png b/krusader/lo32-app-krusader2.png
new file mode 100644
index 0000000..6e8d04a
--- /dev/null
+++ b/krusader/lo32-app-krusader2.png
Binary files differ
diff --git a/krusader/main.cpp b/krusader/main.cpp
new file mode 100644
index 0000000..a70a071
--- /dev/null
+++ b/krusader/main.cpp
@@ -0,0 +1,248 @@
+/***************************************************************************
+ main.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+// KDE includes
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <ksplashscreen.h>
+#include <unistd.h>
+#include <signal.h>
+#include <qeventloop.h>
+
+// Krusader includes
+#include "krusader.h"
+#include "krslots.h"
+#include "krusaderapp.h"
+#include "defaults.h"
+#include <dcopclient.h>
+#include <kstartupinfo.h>
+#include <stdlib.h>
+
+static const char *description =
+ I18N_NOOP("Krusader\nTwin-Panel File Manager for KDE");
+// INSERT A DESCRIPTION FOR YOUR APPLICATION HERE
+
+static KCmdLineOptions options[] =
+{
+ { "left <path>", I18N_NOOP("Start left panel at <path>"), 0},
+ { "right <path>", I18N_NOOP("Start right panel at <path>"), 0},
+ { "profile <panel-profile>", I18N_NOOP("Load this profile on startup"), 0},
+ { 0, 0, 0 }
+ // INSERT YOUR COMMANDLINE OPTIONS HERE
+};
+
+static void sigterm_handler(int i)
+{
+ fprintf(stderr,"Signal: %d\n",i);
+
+ QApplication::eventLoop()->wakeUp();
+ KApplication::exit( - 15 );
+}
+
+int main(int argc, char *argv[]) {
+
+// ============ begin icon-stuff ===========
+// If the user has no icon specified over the commandline we set up uor own.
+// this is acording to the users privileges. The icons are in Krusader::privIcon()
+
+ bool hasIcon = false;
+ int i = 0;
+ char * myArgv[argc+2];
+
+ // if no --miniicon is given, --icon is used. So we don't need to check for --miniicon separately
+ for ( i = 0; i < argc; ++i ) {
+ if ( strstr(argv[ i ], "-icon") != 0 ) // important: just one dash because both can appear!
+ hasIcon = true;
+ }
+
+ static const char* const icon_text="--icon";
+ const char* icon_name=Krusader::privIcon();
+ char addedParams[strlen(icon_text)+strlen(icon_name)+2];
+
+ if ( ! hasIcon ) {
+ for ( i = 0; i < argc; ++i )
+ myArgv[ i ] = argv[ i ];
+
+ strcpy(addedParams,icon_text);
+ strcpy(addedParams+strlen(icon_text)+1,icon_name);
+
+ myArgv[ argc ] = addedParams;
+ myArgv[ ++argc ] = addedParams+strlen(icon_text)+1;
+ myArgv[ ++argc ] = 0;
+
+ argv = myArgv;
+ }
+// ============ end icon-stuff ===========
+
+ // ABOUT data information
+#ifdef RELEASE_NAME
+ QString versionName = QString("%1 \"%2\"").arg(VERSION).arg(RELEASE_NAME);
+#else
+ QString versionName = VERSION;
+#endif
+ KAboutData aboutData( "krusader", ( geteuid() ? I18N_NOOP("Krusader") :
+ I18N_NOOP("Krusader - ROOT PRIVILEGES")),
+ versionName.latin1(), description, KAboutData::License_GPL,
+ "(c) 2000-2003, Shie Erlich, Rafi Yanai\n(c) 2004-2007, Krusader Krew",
+ I18N_NOOP("Feedback\nhttp://www.krusader.org/phpBB/\n\n"
+ "IRC\nserver: irc.freenode.net, channel: #krusader"),
+ "http://www.krusader.org",
+ "krusader@users.sourceforge.net");
+
+ aboutData.addAuthor("Rafi Yanai","Author", "yanai@users.sourceforge.net");
+ aboutData.addAuthor("Shie Erlich","Author", "erlich@users.sourceforge.net");
+ aboutData.addAuthor("Karai Csaba", "Developer", "ckarai@users.sourceforge.net", 0);
+ aboutData.addAuthor("Heiner Eichmann","Developer", "h.eichmann@gmx.de", 0);
+ aboutData.addAuthor("Jonas Baehr", "Developer", "jonas.baehr@web.de", 0);
+ aboutData.addAuthor("Dirk Eschler", "Webmaster and i18n coordinator", "deschler@users.sourceforge.net", 0);
+ aboutData.addAuthor("Frank Schoolmeesters", "Documentation and marketing coordinator", "frank_schoolmeesters@yahoo.com", 0);
+ aboutData.addAuthor("Richard Holt", "Documentation & Proofing", "richard.holt@gmail.com", 0);
+ aboutData.addAuthor("Matej Urbancic", " Marketing & Product Research", "matej.urban@gmail.com", 0);
+ aboutData.addCredit("Václav Juza", "QA, bug-hunting, patches and general help", "vaclavjuza@gmail.com", 0);
+ aboutData.addCredit("Jiri Palecek", "QA, bug-hunting, patches and general help", "jpalecek@web.de", 0);
+ aboutData.addCredit("Andrew Neupokoev", "Killer Logo and Icons for Krusader (contest winner)", "doom-blue@yandex.ru", 0);
+ aboutData.addCredit("The UsefulArts Organization", "Icon for krusader", "mail@usefularts.rg", 0);
+ aboutData.addCredit("Gábor Lehel", "Viewer module for 3rd Hand", "illissius@gmail.com", 0);
+ aboutData.addCredit("Mark Eatough", "Handbook Proof-Reader", "markeatough@yahoo.com", 0);
+ aboutData.addCredit("Jan Halasa", "The old Bookmark Module", "xhalasa@fi.muni.cz", 0);
+ aboutData.addCredit("Hans Loeffler", "Dir history button", 0, 0);
+ aboutData.addCredit("Szombathelyi György", "ISO KIO slave", 0, 0);
+ aboutData.addCredit("Jan Willem van de Meent (Adios)", "Icons for Krusader", "janwillem@lorentz.leidenuniv.nl", 0);
+ aboutData.addCredit("Mikolaj Machowski", "Usability and QA", "<mikmach@wp.pl>", 0);
+ aboutData.addCredit("Cristi Dumitrescu","QA, bug-hunting, patches and general help","cristid@chip.ro",0);
+ aboutData.addCredit("Aurelien Gateau","patch for KViewer","aurelien.gateau@free.fr",0);
+ aboutData.addCredit("Milan Brabec","the first patch ever !","mbrabec@volny.cz",0);
+ aboutData.addCredit("Asim Husanovic","Bosnian translation","asim@megatel.ba",0);
+ aboutData.addCredit("Doutor Zero","Brazilian Portuguese","doutor.zero@gmail.com",0);
+ aboutData.addCredit("Milen Ivanov","Bulgarian translation","milen.ivanov@abv.bg",0);
+ aboutData.addCredit("Quim Perez","Catalan translation","noguer@osona.com",0);
+ aboutData.addCredit("Jinghua Luo","Chinese Simplified translation","luojinghua@msn.com",0);
+ aboutData.addCredit("Mitek","Old Czech translation","mitek@email.cz",0);
+ aboutData.addCredit("Martin Sixta","Old Czech translation","lukumo84@seznam.cz",0);
+ aboutData.addCredit("Vaclav Juza","Czech translation","VaclavJuza@gmail.com",0);
+ aboutData.addCredit("Anders Bruun Olsen", "Old Danish translation", "anders@bruun-olsen.net", 0);
+ aboutData.addCredit("Peter H. Sorensen", "Danish translation", "peters@skydebanen.net", 0);
+ aboutData.addCredit("Frank Schoolmeesters","Dutch translation","frank_schoolmeesters@yahoo.com",0);
+ aboutData.addCredit("Rene-Pierre Lehmann","Old French translation","ripi@lepi.org",0);
+ aboutData.addCredit("David Guillerm","French translation","dguillerm@gmail.com",0);
+ aboutData.addCredit("Christoph Thielecke","Old German translation","crissi99@gmx.de",0);
+ aboutData.addCredit("Dirk Eschler", "German translation", "deschler@users.sourceforge.net", 0);
+ aboutData.addCredit("Spiros Georgaras", "Greek translation", "sngeorgaras@gmail.com", 0);
+ aboutData.addCredit("Kukk Zoltan","Old Hungarian translation","kukkzoli@freemail.hu",0);
+ aboutData.addCredit("Arpad Biro","Hungarian translation","biro_arpad@yahoo.com",0);
+ aboutData.addCredit("Giuseppe Bordoni", "Italian translation", "geppo@geppozone.com", 0);
+ aboutData.addCredit("Hideki Kimura", "Japanese translation", "hangyo1973@gmail.com", 0);
+ aboutData.addCredit("UTUMI Hirosi", "Old Japanese translation", "utuhiro@mx12.freecom.ne.jp", 0);
+ aboutData.addCredit("Dovydas Sankauskas", "Lithuanian translation", "laisve@gmail.com", 0);
+ aboutData.addCredit("Bruno Queiros", "Portuguese translation", "brunoqueiros@portugalmail.com", 0);
+ aboutData.addCredit("Lukasz Janyst","Old Polish translation","ljan@wp.pl",0);
+ aboutData.addCredit("Pawel Salawa","Polish translation","boogie@myslenice.one.pl",0);
+ aboutData.addCredit("Tomek Grzejszczyk","Polish translation","tgrzej@onet.eu",0);
+ aboutData.addCredit("Dmitry A. Bugay","Russian translation","sam@vhnet.ru",0);
+ aboutData.addCredit("Dmitry Chernyak","Old Russian translation","chernyak@mail.ru",0);
+ aboutData.addCredit("Sasa Tomic","Serbian translation","stomic@gmx.net",0);
+ aboutData.addCredit("Zdenko Podobna","Slovak translation","zdpo@mailbox.sk",0);
+ aboutData.addCredit("Matej Urbancic","Slovenian translation","matej.urban@gmail.com",0);
+ aboutData.addCredit("Rafael Munoz","Old Spanish translation","muror@hotpop.com",0);
+ aboutData.addCredit("Alejandro Araiza Alvarado","Spanish translation","mebrelith@gmail.com",0);
+ aboutData.addCredit("Erik Johanssen","Old Swedish translation","erre@telia.com",0);
+ aboutData.addCredit("Anders Linden","Old Swedish translation","connyosis@gmx.net",0);
+ aboutData.addCredit("Peter Landgren","Swedish translation","peter.talken@telia.com",0);
+ aboutData.addCredit("Bekir Sonat","Turkish translation","bekirsonat@kde.org.tr",0);
+ aboutData.addCredit("Ivan Petrouchtchak","Ukrainian translation","connyosis@gmx.net",0);
+
+ // Command line arguments ...
+ KCmdLineArgs::init( argc, argv, &aboutData );
+ KCmdLineArgs::addCmdLineOptions( options ); // Add our own options.
+
+ // check for command line arguments
+
+ // create the application
+ KrusaderApp app;
+
+ {
+ KConfigGroupSaver saver(app.config(), "Look&Feel");
+ bool singleInstanceMode = app.config()->readBoolEntry( "Single Instance Mode", _SingleInstanceMode );
+
+ // register with the dcop server
+ DCOPClient* client = KApplication::kApplication() ->dcopClient();
+ if ( !client->attach() )
+ exit( 0 );
+ QCString regName = client->registerAs( KApplication::kApplication() ->name(), !singleInstanceMode );
+ if( singleInstanceMode && regName != KApplication::kApplication()->name() ) {
+ fprintf( stderr, i18n( "Application already running!\n" ).ascii() );
+
+ DCOPClient::mainClient()->send( KApplication::kApplication() ->name(), "Krusader-Interface",
+ "moveToTop()", QByteArray() );
+ KStartupInfo::appStarted();
+
+ return 1;
+ }
+ }
+
+ // splash screen - if the user wants one
+ KSplashScreen *splash = 0;
+ { // don't remove bracket
+ KConfigGroupSaver saver(app.config(), "Look&Feel");
+ if (app.config()->readBoolEntry( "Show splashscreen", _ShowSplashScreen )) {
+ QString splashFilename = locate( "data", "krusader/splash.png" );
+ QPixmap pixmap( splashFilename );
+ if (!pixmap.isNull()) {
+ splash = new KSplashScreen( pixmap );
+ splash->show();
+ }
+ }
+ } // don't remove bracket
+
+ Krusader krusader;
+
+ // catching SIGTERM, SIGHUP, SIGQUIT
+ signal(SIGTERM,sigterm_handler);
+ signal(SIGPIPE,sigterm_handler);
+ signal(SIGHUP,sigterm_handler);
+
+ // make sure we receive X's focus in/out events
+ QObject::connect(&app, SIGNAL(windowActive()), krusader.slot, SLOT(windowActive()));
+ QObject::connect(&app, SIGNAL(windowInactive()), krusader.slot, SLOT(windowInactive()));
+
+ // and set krusader to be the main widget in it
+ app.setMainWidget(&krusader);
+
+ // hide splashscreen
+ if (splash) {
+ splash->finish( &krusader );
+ delete splash;
+ }
+
+ // let's go.
+ return app.exec();
+}
diff --git a/krusader/midnight_cmd_AHamann.color b/krusader/midnight_cmd_AHamann.color
new file mode 100644
index 0000000..e5a82d6
--- /dev/null
+++ b/krusader/midnight_cmd_AHamann.color
Binary files differ
diff --git a/krusader/midnight_commander.color b/krusader/midnight_commander.color
new file mode 100644
index 0000000..f42b788
--- /dev/null
+++ b/krusader/midnight_commander.color
Binary files differ
diff --git a/krusader/midnight_commander.keymap b/krusader/midnight_commander.keymap
new file mode 100644
index 0000000..3e664d6
--- /dev/null
+++ b/krusader/midnight_commander.keymap
Binary files differ
diff --git a/krusader/midnight_commander.keymap.info b/krusader/midnight_commander.keymap.info
new file mode 100644
index 0000000..12e19e8
--- /dev/null
+++ b/krusader/midnight_commander.keymap.info
@@ -0,0 +1,42 @@
+Please note that the following shortcuts are KDE global shortcuts:
+ALT-F1, ALT-F2, ALT-F5, ALT-F9
+
+This means that in order for Krusader to use them, you must
+first disable them in KDE's global shortcut panel.
+To do so, open KDE's Control Center, open "Keyboard Shortcuts"
+and in the "Global Shortcuts" tab, disable the mentioned shortcuts.
+
+Modified keybindings for Midnight Commander:
+"Ctrl+O" "F2_Terminal"
+"Ctrl+Q" "toggle popup panel"
+"Shift+Insert" "std_paste"
+"Ctrl+Minus" "unselect all"
+"Shift+Plus" "select group"
+"Alt+Ctrl+3" "sort_by_size"
+"Ctrl+E" "sample_edit_as_root"
+"Ctrl+L" "locate"
+"Alt+F9" "unpack"
+"Ctrl+L" "calculate"
+"Ctrl+T" "new tab"
+"Alt+Ctrl+4" "sort_by_modified"
+"Alt+Ctrl+2" "sort_by_extension"
+"Shift+Asterisk" "invert"
+"Shift+Delete" "std_cut"
+"Win+A" "sample_amarok_enqueue"
+"Ctrl+C" "std_copy"
+"Alt+Ctrl+M" "sample_newmount"
+"Alt+Shift+Question" "find"
+"Alt+F5" "pack"
+"Alt+F1" "left bookmarks"
+"Alt+F2" "right bookmarks"
+"Ctrl+Shift+Plus" "select all"
+"Alt+Return" "properties"
+"Alt+F8" "cmdline popup"
+"F2" "user menu"
+"Ctrl+M" "multirename"
+"Alt+Ctrl+1" "sort_by_name"
+"Ctrl+Delete" "filename_to_clipboard"
+"Minus" "unselect group"
+"Alt+Ctrl+Equal" "sample_panesize"
+"Shift+F6" "F9_Rename"
+
diff --git a/krusader/mount.js b/krusader/mount.js
new file mode 100644
index 0000000..3aadcc8
--- /dev/null
+++ b/krusader/mount.js
@@ -0,0 +1,37 @@
+/*
+ This is an extension for the Krusader filemanager
+ http://krusader.sf.net/
+
+ Author: Jonas Bhr, http://www.jonas-baehr.de/
+
+ This script shows a dialog for mounting a device. The commandline which is
+ returned by this is executed by Krusader's UserAction-system
+ Krusader looks for the variable 'cmd'.
+
+ scriptDir is a string-variable set by Krusader with the directory of the currently
+ executed script. This is usefull for relative path's inside scripts.
+*/
+
+var ui = Factory.loadui( scriptDir + 'mount.ui' );
+
+ui.child('device').setFocus();
+
+var m = ui.exec();
+
+var cmd = "@CANCEL@"; //FIXME: replace this with UserAction.cancel
+
+if (m) {
+ var cmd = "mount";
+ var device = ui.child('device').url;
+ var mountpoint = ui.child('mountpoint').url;
+ var filesystem = ui.child('filesystem').currentText;
+ var options = ui.child('options').text;
+
+ if ( filesystem != '<auto>' && filesystem != '' )
+ cmd += " -t " + filesystem;
+ if ( options != '' )
+ cmd += " " + options;
+
+ cmd += " " + device + " " + mountpoint;
+}
+
diff --git a/krusader/mount.ui b/krusader/mount.ui
new file mode 100644
index 0000000..cb80f43
--- /dev/null
+++ b/krusader/mount.ui
@@ -0,0 +1,208 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>mountDlg</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>mountDlg</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>396</width>
+ <height>185</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="caption">
+ <string>Mount a Filesystem</string>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>true</bool>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="5" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>Layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>Horizontal Spacing2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonOk</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonCancel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>labelDevice</cstring>
+ </property>
+ <property name="text">
+ <string>Device</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="0" column="1">
+ <property name="name">
+ <cstring>device</cstring>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="1" column="1">
+ <property name="name">
+ <cstring>mountpoint</cstring>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="2" column="1">
+ <item>
+ <property name="text">
+ <string>&lt;auto&gt;</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>ext2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>ext3</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>vfat</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>ntfs</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>filesystem</cstring>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>labelFilesystem</cstring>
+ </property>
+ <property name="text">
+ <string>Filesystem</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>labelMountpoint</cstring>
+ </property>
+ <property name="text">
+ <string>Mountpoint</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>labelOptions</cstring>
+ </property>
+ <property name="text">
+ <string>additional mount-options:</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="4" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>options</cstring>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>buttonOk</sender>
+ <signal>clicked()</signal>
+ <receiver>mountDlg</receiver>
+ <slot>accept()</slot>
+ </connection>
+ <connection>
+ <sender>buttonCancel</sender>
+ <signal>clicked()</signal>
+ <receiver>mountDlg</receiver>
+ <slot>reject()</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="local" impldecl="in implementation">mount.ui.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+</includehints>
+</UI>
diff --git a/krusader/panelmanager.cpp b/krusader/panelmanager.cpp
new file mode 100644
index 0000000..dbdf25a
--- /dev/null
+++ b/krusader/panelmanager.cpp
@@ -0,0 +1,352 @@
+#include <qwidgetstack.h>
+#include <qtoolbutton.h>
+#include <klocale.h>
+#include <qimage.h>
+#include <kdebug.h>
+#include <kconfig.h>
+#include <kiconloader.h>
+#include "panelmanager.h"
+#include "Panel/listpanel.h"
+#include "Panel/panelfunc.h"
+#include "krusaderview.h"
+#include "defaults.h"
+
+#define HIDE_ON_SINGLE_TAB false
+
+#define SHOW { _newTab->show(); _tabbar->show(); _closeTab->show(); }
+#define HIDE { _newTab->hide(); _tabbar->hide(); _closeTab->hide(); }
+
+#define _self (*_selfPtr)
+#define _other (*_otherPtr)
+
+PanelManager::PanelManager( QWidget *parent, bool left ) :
+QWidget( parent, "PanelManager" ), _layout( 0 ), _left( left ),
+ _selfPtr( _left ? &MAIN_VIEW->left : &MAIN_VIEW->right ),
+ _otherPtr( _left ? &MAIN_VIEW->right : &MAIN_VIEW->left ) {
+ _layout = new QGridLayout( this, 1, 1 );
+ _stack = new QWidgetStack( this );
+
+ // new tab button
+ _newTab = new QToolButton( this );
+ _newTab->setFixedSize( 22, 22 );
+ _newTab->setTextLabel( i18n( "Open a new tab in home" ) );
+ _newTab->setIconSet( SmallIcon( "tab_new" ) );
+ _newTab->adjustSize();
+ connect( _newTab, SIGNAL( clicked() ), this, SLOT( slotNewTab() ) );
+
+ // close tab button
+ _closeTab = new QToolButton( this );
+ _closeTab->setFixedSize( 22, 22 );
+ _closeTab->setTextLabel( i18n( "Close current tab" ) );
+ _closeTab->setIconSet( SmallIcon( "tab_remove" ) );
+ _closeTab->adjustSize();
+ connect( _closeTab, SIGNAL( clicked() ), this, SLOT( slotCloseTab() ) );
+ _closeTab->setEnabled( false ); // disabled when there's only 1 tab
+
+ // tab-bar
+ _tabbar = new PanelTabBar( this );
+ connect( _tabbar, SIGNAL( changePanel( ListPanel* ) ), this, SLOT( slotChangePanel( ListPanel * ) ) );
+ connect( _tabbar, SIGNAL( closeCurrentTab() ), this, SLOT( slotCloseTab() ) );
+ connect( _tabbar, SIGNAL( newTab( const KURL& ) ), this, SLOT( slotNewTab( const KURL& ) ) );
+
+ _layout->addMultiCellWidget( _stack, 0, 0, 0, 2 );
+ _layout->addWidget( _newTab, 1, 0 );
+ _layout->addWidget( _tabbar, 1, 1 );
+ _layout->addWidget( _closeTab, 1, 2 );
+
+ if ( HIDE_ON_SINGLE_TAB ) HIDE
+ else SHOW
+}
+
+void PanelManager::slotChangePanel( ListPanel *p ) {
+ _self = p;
+ _self->otherPanel = _other;
+ _other->otherPanel = _self;
+
+ _stack->raiseWidget( _self );
+ kapp->processEvents();
+ _self->slotFocusOnMe();
+}
+
+ListPanel* PanelManager::createPanel( QString type, bool setCurrent ) {
+ // create the panel and add it into the widgetstack
+ ListPanel * p = new ListPanel( type, _stack, _left );
+ _stack->addWidget( p );
+
+ // now, create the corrosponding tab
+ _tabbar->addPanel( p, setCurrent );
+
+ // allow close button if more than 1 tab
+ if ( _tabbar->count() > 1 ) {
+ _closeTab->setEnabled( true );
+ SHOW // needed if we were hidden
+ }
+ if( setCurrent )
+ _stack->raiseWidget( p );
+
+ // connect the activePanelChanged signal to enable/disable actions
+ connect( p, SIGNAL( activePanelChanged( ListPanel* ) ), this, SLOT( slotRefreshActions() ) );
+ return p;
+}
+
+void PanelManager::startPanel( ListPanel *panel, const KURL& path ) {
+ panel->start( path );
+}
+
+void PanelManager::saveSettings( KConfig *config, const QString& key, bool localOnly ) {
+ QStringList l;
+ QStringList types;
+ QValueList<int> props;
+ int i=0, cnt=0;
+ while (cnt < _tabbar->count()) {
+ PanelTab *t = dynamic_cast<PanelTab*>(_tabbar->tabAt(i));
+ if (t && t->panel) {
+ l << ( localOnly ? t->panel->realPath() : vfs::pathOrURL( t->panel->virtualPath() ) );
+ types << t->panel->getType();
+ props << t->panel->getProperties();
+ ++cnt;
+ }
+ ++i;
+ }
+ config->writePathEntry( key, l );
+ config->writeEntry( key + " Types", types );
+ config->writeEntry( key + " Props", props );
+}
+
+void PanelManager::loadSettings( KConfig *config, const QString& key ) {
+ QStringList l = config->readPathListEntry( key );
+ QStringList types = config->readListEntry( key + " Types" );
+ QValueList<int> props = config->readIntListEntry( key + " Props" );
+
+ if( l.count() < 1 )
+ return;
+
+ while( types.count() < l.count() )
+ {
+ KConfigGroupSaver saver( config, "Look&Feel");
+ types << krConfig->readEntry( "Default Panel Type", _DefaultPanelType );
+ }
+ while( props.count() < l.count() )
+ props << 0;
+
+ int i=0, totalTabs = _tabbar->count();
+
+ while (i < totalTabs && i < (int)l.count() )
+ {
+ PanelTab *t = dynamic_cast<PanelTab*>(_tabbar->tabAt(i));
+ if (t && t->panel)
+ {
+ if( t->panel->getType() != types[ i ] )
+ t->panel->changeType( types[ i ] );
+ t->panel->setProperties( props[ i ] );
+ t->panel->otherPanel = _other;
+ _other->otherPanel = t->panel;
+ t->panel->func->files()->vfs_enableRefresh( true );
+ t->panel->func->immediateOpenUrl( vfs::fromPathOrURL( l[ i ] ) );
+ }
+ ++i;
+ }
+
+ while( i < totalTabs )
+ slotCloseTab( --totalTabs );
+
+ for(; i < (int)l.count(); i++ )
+ slotNewTab( vfs::fromPathOrURL(l[i]), false, types[ i ], props[ i ] );
+}
+
+void PanelManager::slotNewTab(const KURL& url, bool setCurrent, QString type, int props ) {
+ if( type.isNull() )
+ {
+ krConfig->setGroup( "Look&Feel" );
+ type = krConfig->readEntry( "Default Panel Type", _DefaultPanelType );
+ }
+ ListPanel *p = createPanel( type, setCurrent );
+ // update left/right pointers
+ p->otherPanel = _other;
+ if( setCurrent )
+ {
+ _self = p;
+ _other->otherPanel = _self;
+ }
+ startPanel( p, url );
+ p->setProperties( props );
+}
+
+void PanelManager::slotNewTab() {
+ slotNewTab( QDir::home().absPath() );
+}
+
+void PanelManager::slotCloseTab() {
+ if ( _tabbar->count() <= 1 ) /* if this is the last tab don't close it */
+ return ;
+
+ // setup current one
+ ListPanel * oldp;
+ _self = _tabbar->removeCurrentPanel( oldp );
+ _stack->raiseWidget( _self );
+ _stack->removeWidget( oldp );
+ deletePanel( oldp );
+
+ // setup pointers
+ _self->otherPanel = _other;
+ _other->otherPanel = _self;
+ _self->slotFocusOnMe();
+
+ // disable close button if only 1 tab is left
+ if ( _tabbar->count() == 1 ) {
+ _closeTab->setEnabled( false );
+ if ( HIDE_ON_SINGLE_TAB ) HIDE
+ }
+}
+
+void PanelManager::slotCloseTab( int index ) {
+ PanelTab *t = dynamic_cast<PanelTab*>(_tabbar->tabAt( index ));
+ if (t && t->panel)
+ {
+ ListPanel *oldp = t->panel;
+ disconnect( oldp );
+ if( t->identifier() == _tabbar->currentTab() )
+ {
+ PanelTab *newCurrent = dynamic_cast<PanelTab*>( _tabbar->tabAt( 0 ) );
+ if( newCurrent != 0 )
+ {
+ _tabbar->setCurrentTab( newCurrent );
+ _self = newCurrent->panel;
+ _self->otherPanel = _other;
+ _other->otherPanel = _self;
+ }
+ }
+ _tabbar->removeTab( t );
+
+ _stack->removeWidget( oldp );
+ deletePanel( oldp );
+ }
+
+ if ( _tabbar->count() == 1 )
+ {
+ _closeTab->setEnabled( false );
+ if ( HIDE_ON_SINGLE_TAB ) HIDE
+ }
+}
+
+void PanelManager::slotRefreshActions() {
+ krCloseTab->setEnabled( _tabbar->count() > 1 );
+ krNextTab->setEnabled(_tabbar->count() > 1);
+ krPreviousTab->setEnabled(_tabbar->count() > 1);
+}
+
+int PanelManager::activeTab()
+{
+ return _tabbar->indexOf( _tabbar->currentTab() );
+}
+
+void PanelManager::setActiveTab( int panelIndex )
+{
+ QTab *current = _tabbar->tabAt( panelIndex );
+ if( current == 0 )
+ return;
+ _tabbar->setCurrentTab( current );
+ slotChangePanel ( dynamic_cast<PanelTab*>( _tabbar->tabAt( panelIndex ) )->panel );
+}
+
+void PanelManager::setCurrentTab( int panelIndex )
+{
+ PanelTab *current = dynamic_cast<PanelTab*>(_tabbar->tabAt( panelIndex ) );
+ if( current == 0 )
+ return;
+ _tabbar->setCurrentTab( current );
+ _self = current->panel;
+ _self->otherPanel = _other;
+ _other->otherPanel = _self;
+
+ _stack->raiseWidget( _self );
+}
+
+void PanelManager::slotRecreatePanels() {
+ int actTab = activeTab();
+
+ for( int i = 0; i != _tabbar->count(); i++ )
+ {
+ PanelTab *updatedPanel = dynamic_cast<PanelTab*>(_tabbar->tabAt( i ) );
+
+ ListPanel *oldPanel = updatedPanel->panel;
+ QString type = oldPanel->getType();
+ ListPanel *newPanel = new ListPanel( type, _stack, _left );
+ _stack->addWidget( newPanel, i );
+ _stack->removeWidget( oldPanel );
+
+ disconnect( oldPanel );
+ connect( newPanel, SIGNAL( activePanelChanged( ListPanel* ) ), this, SLOT( slotRefreshActions() ) );
+ connect( newPanel, SIGNAL( pathChanged(ListPanel*) ), _tabbar, SLOT(updateTab(ListPanel*)));
+
+ newPanel->otherPanel = _other;
+ if( _other->otherPanel == oldPanel )
+ _other->otherPanel = newPanel;
+ updatedPanel->panel = newPanel;
+ newPanel->start( oldPanel->virtualPath(), true );
+ if( _self == oldPanel )
+ {
+ _self = newPanel;
+ _self->otherPanel = _other;
+ _other->otherPanel = _self;
+ }
+ deletePanel( oldPanel );
+
+ _tabbar->updateTab( newPanel );
+ }
+
+ setActiveTab( actTab );
+}
+
+void PanelManager::slotNextTab() {
+ int currTab = _tabbar->currentTab();
+ int nextInd = (_tabbar->indexOf(currTab) == _tabbar->count()-1 ? 0 : _tabbar->indexOf(currTab)+1);
+ ListPanel *nextp = dynamic_cast<PanelTab*>(_tabbar->tabAt(nextInd))->panel;
+ _tabbar->setCurrentTab(_tabbar->tabAt(nextInd));
+ slotChangePanel(nextp);
+}
+
+
+void PanelManager::slotPreviousTab() {
+ int currTab = _tabbar->currentTab();
+ int nextInd = (_tabbar->indexOf(currTab) == 0 ? _tabbar->count()-1 : _tabbar->indexOf(currTab)-1);
+ ListPanel *nextp = dynamic_cast<PanelTab*>(_tabbar->tabAt(nextInd))->panel;
+ _tabbar->setCurrentTab(_tabbar->tabAt(nextInd));
+ slotChangePanel(nextp);
+}
+
+void PanelManager::refreshAllTabs( bool invalidate ) {
+ int i=0;
+ while (i < _tabbar->count()) {
+ PanelTab *t = dynamic_cast<PanelTab*>(_tabbar->tabAt(i));
+ if (t && t->panel && t->panel->func ) {
+ vfs * vfs = t->panel->func->files();
+ if( vfs ) {
+ if( invalidate )
+ vfs->vfs_invalidate();
+ vfs->vfs_refresh();
+ }
+ }
+ ++i;
+ }
+}
+
+void PanelManager::deletePanel( ListPanel * p ) {
+ if( ACTIVE_PANEL == p )
+ ACTIVE_PANEL = _self;
+
+ if( p && p->func && p->func->files() && !p->func->files()->vfs_canDelete() ) {
+ connect( p->func->files(), SIGNAL( deleteAllowed() ), p, SLOT( deleteLater() ) );
+ p->func->files()->vfs_requestDelete();
+ return;
+ }
+ delete p;
+}
+
+void PanelManager::swapPanels() {
+ _left = !_left;
+ _selfPtr = _left ? &MAIN_VIEW->left : &MAIN_VIEW->right;
+ _otherPtr = _left ? &MAIN_VIEW->right : &MAIN_VIEW->left;
+}
+
+#include "panelmanager.moc"
diff --git a/krusader/panelmanager.h b/krusader/panelmanager.h
new file mode 100644
index 0000000..2016b77
--- /dev/null
+++ b/krusader/panelmanager.h
@@ -0,0 +1,78 @@
+#ifndef _PANEL_MANAGER_H
+#define _PANEL_MANAGER_H
+
+#include <qwidget.h>
+#include <qlayout.h>
+#include "paneltabbar.h"
+
+class KConfig;
+class ListPanel;
+class QWidgetStack;
+class QToolButton;
+
+/**
+ * Implements tabbed-browsing by managing a list of tabs and corrosponding panels.
+ */
+class PanelManager: public QWidget {
+ Q_OBJECT
+
+ public:
+ /**
+ * PanelManager is created where once panels were created. It accepts three references to pointers
+ * (self, other, active), which enables it to manage pointers held by the panels transparently.
+ * It also receives a bool (left) which is true if the manager is the left one, or false otherwise.
+ */
+ PanelManager( QWidget *parent, bool left );
+ /**
+ * Called once by KrusaderView to create the first panel. Subsequent called are done internally
+ * Note: only creates the panel, but doesn't start the VFS inside it. Use startPanel() for that.
+ */
+ ListPanel* createPanel( QString type, bool setCurrent = true );
+ /**
+ * Called once by KrusaderView to start the first panel. Subsequent called are done internally
+ * Only starts the VFS inside the panel, you must first use createPanel() !
+ */
+ void startPanel(ListPanel *panel, const KURL& path);
+ /**
+ * Swaps the left / right directions of the panel
+ */
+ void swapPanels();
+
+ void saveSettings(KConfig *config, const QString& key, bool localOnly = true );
+ void loadSettings(KConfig *config, const QString& key);
+ int activeTab();
+ void setActiveTab( int );
+ void setCurrentTab( int );
+ void refreshAllTabs( bool invalidate = false );
+
+ public slots:
+ /**
+ * Called externally to start a new tab. Example of usage would be the "open in a new tab"
+ * action, from the context-menu.
+ */
+ void slotNewTab(const KURL& url, bool setCurrent = true, QString type = QString::null, int props = 0 );
+ void slotNewTab();
+ void slotNextTab();
+ void slotPreviousTab();
+ void slotCloseTab();
+ void slotCloseTab( int index );
+ void slotRecreatePanels();
+
+ protected slots:
+ void slotChangePanel(ListPanel *p);
+ void slotRefreshActions();
+
+ private:
+ void deletePanel( ListPanel *p );
+
+ QGridLayout *_layout;
+ QHBoxLayout *_barLayout;
+ bool _left;
+ PanelTabBar *_tabbar;
+ QWidgetStack *_stack;
+ QToolButton *_newTab, *_closeTab;
+ ListPanel **_selfPtr, **_otherPtr;
+};
+
+
+#endif // _PANEL_MANAGER_H
diff --git a/krusader/paneltabbar.cpp b/krusader/paneltabbar.cpp
new file mode 100644
index 0000000..6208255
--- /dev/null
+++ b/krusader/paneltabbar.cpp
@@ -0,0 +1,262 @@
+/***************************************************************************
+ paneltabbar.cpp - description
+ -------------------
+ begin : Sun Jun 2 2002
+ copyright : (C) 2002 by Shie Erlich & Rafi Yanai
+ email :
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "paneltabbar.h"
+#include "Panel/listpanel.h"
+#include "krusaderview.h"
+#include "krslots.h"
+#include "defaults.h"
+#include <kaction.h>
+#include <klocale.h>
+#include <kshortcut.h>
+#include <qevent.h>
+#include <qwidgetstack.h>
+#include <qfontmetrics.h>
+#include <qtooltip.h>
+#include <kdebug.h>
+
+#define DISPLAY(X) (X.isLocalFile() ? X.path() : X.prettyURL())
+
+PanelTabBar::PanelTabBar(QWidget *parent): QTabBar(parent), _maxTabLength(0) {
+ _panelActionMenu = new KActionMenu( i18n("Panel"), this );
+
+ setAcceptDrops(true);
+ insertAction(krNewTab);
+ insertAction(krDupTab);
+ insertAction(krPreviousTab);
+ insertAction(krNextTab);
+ insertAction(krCloseTab);
+ krCloseTab->setEnabled(false); //can't close a single tab
+
+ setShape(QTabBar::TriangularBelow);
+}
+
+void PanelTabBar::mousePressEvent( QMouseEvent* e ) {
+ QTab* clickedTab = selectTab( e->pos() );
+ if( !clickedTab ) { // clicked on nothing ...
+ QTabBar::mousePressEvent(e);
+ return;
+ }
+ // else implied
+ setCurrentTab( clickedTab );
+ emit changePanel(dynamic_cast<PanelTab*>(clickedTab)->panel);
+
+ if ( e->button() == Qt::RightButton ) {
+ // show the popup menu
+ _panelActionMenu->popup( e->globalPos() );
+ } else
+ if ( e->button() == Qt::LeftButton ) { // we need to change tabs
+ // first, find the correct panel to load
+ int id = currentTab();
+ ListPanel *listpanel = dynamic_cast<PanelTab*>(tab(id))->panel;
+ emit changePanel(listpanel);
+ } else
+ if (e->button() == Qt::MidButton) { // close the current tab
+ emit closeCurrentTab();
+ }
+ QTabBar::mousePressEvent(e);
+}
+
+void PanelTabBar::insertAction( KAction* action ) {
+ _panelActionMenu->insert( action );
+}
+
+int PanelTabBar::addPanel(ListPanel *panel, bool setCurrent ) {
+ int newId = addTab(new PanelTab(squeeze(DISPLAY(panel->virtualPath())), panel));
+
+ // make sure all tabs lengths are correct
+ for (int i=0; i<count(); i++)
+ tabAt(i)->setText(squeeze(DISPLAY(dynamic_cast<PanelTab*>(tabAt(i))->panel->virtualPath()), i));
+ layoutTabs();
+
+ if( setCurrent )
+ setCurrentTab(newId);
+
+ // enable close-tab action
+ if (count()>1) {
+ krCloseTab->setEnabled(true);
+ }
+
+ connect(dynamic_cast<PanelTab*>(tab(newId))->panel, SIGNAL(pathChanged(ListPanel*)),
+ this, SLOT(updateTab(ListPanel*)));
+
+ return newId;
+}
+
+ListPanel* PanelTabBar::removeCurrentPanel(ListPanel* &panelToDelete) {
+ int id = currentTab();
+ ListPanel *oldp = dynamic_cast<PanelTab*>(tab(id))->panel; // old panel to kill later
+ disconnect(dynamic_cast<PanelTab*>(tab(id))->panel);
+ removeTab(tab(id));
+
+ for (int i=0; i<count(); i++)
+ tabAt(i)->setText(squeeze(DISPLAY(dynamic_cast<PanelTab*>(tabAt(i))->panel->virtualPath()), i));
+ layoutTabs();
+
+ // setup current one
+ id = currentTab();
+ ListPanel *p = dynamic_cast<PanelTab*>(tab(id))->panel;
+ // disable close action?
+ if (count()==1) {
+ krCloseTab->setEnabled(false);
+ }
+
+ panelToDelete = oldp;
+ return p;
+}
+
+void PanelTabBar::updateTab(ListPanel *panel) {
+ // find which is the correct tab
+ for (int i=0; i<count(); i++) {
+ if (dynamic_cast<PanelTab*>(tabAt(i))->panel == panel) {
+ tabAt(i)->setText(squeeze(DISPLAY(panel->virtualPath()),i));
+ break;
+ }
+ }
+}
+
+void PanelTabBar::duplicateTab() {
+ int id = currentTab();
+ emit newTab(dynamic_cast<PanelTab*>(tab(id))->panel->virtualPath());
+}
+
+void PanelTabBar::closeTab() {
+ emit closeCurrentTab();
+}
+
+QString PanelTabBar::squeeze(QString text, int index) {
+ QString originalText = text;
+
+ QString lastGroup = krConfig->group();
+ krConfig->setGroup( "Look&Feel" );
+ bool longNames = krConfig->readBoolEntry( "Fullpath Tab Names", _FullPathTabNames );
+ krConfig->setGroup( lastGroup );
+
+ if( !longNames )
+ {
+ while( text.endsWith( "/" ) )
+ text.truncate( text.length() -1 );
+ if( text.isEmpty() || text.endsWith(":") )
+ text += "/";
+ else
+ {
+ QString shortName;
+
+ if( text.contains( ":/" ) )
+ shortName = text.left( text.find( ":/" ) ) + ":";
+
+ shortName += text.mid( text.findRev( "/" ) + 1 );
+ text = shortName;
+ }
+
+ if( index >= 0 )
+ setToolTip( index, originalText );
+
+ index = -1;
+ }
+
+ QFontMetrics fm(fontMetrics());
+
+ // set the real max length
+ _maxTabLength = (static_cast<QWidget*>(parent())->width()-(6*fm.width("W")))/fm.width("W");
+ // each tab gets a fair share of the max tab length
+ int _effectiveTabLength = _maxTabLength / (count() == 0 ? 1 : count());
+
+ int labelWidth = fm.width("W")*_effectiveTabLength;
+ int textWidth = fm.width(text);
+ if (textWidth > labelWidth) {
+ // start with the dots only
+ QString squeezedText = "...";
+ int squeezedWidth = fm.width(squeezedText);
+
+ // estimate how many letters we can add to the dots on both sides
+ int letters = text.length() * (labelWidth - squeezedWidth) / textWidth / 2;
+ if (labelWidth < squeezedWidth) letters=1;
+ squeezedText = text.left(letters) + "..." + text.right(letters);
+ squeezedWidth = fm.width(squeezedText);
+
+ if (squeezedWidth < labelWidth) {
+ // we estimated too short
+ // add letters while text < label
+ do {
+ letters++;
+ squeezedText = text.left(letters) + "..." + text.right(letters);
+ squeezedWidth = fm.width(squeezedText);
+ } while (squeezedWidth < labelWidth);
+ letters--;
+ squeezedText = text.left(letters) + "..." + text.right(letters);
+ } else if (squeezedWidth > labelWidth) {
+ // we estimated too long
+ // remove letters while text > label
+ do {
+ letters--;
+ squeezedText = text.left(letters) + "..." + text.right(letters);
+ squeezedWidth = fm.width(squeezedText);
+ } while (letters && squeezedWidth > labelWidth);
+ }
+
+ if( index >= 0 )
+ setToolTip( index, originalText );
+
+ if (letters < 5) {
+ // too few letters added -> we give up squeezing
+ //return text;
+ return squeezedText;
+ } else {
+ return squeezedText;
+ }
+ } else {
+ if( index >= 0 )
+ removeToolTip( index );
+
+ return text;
+ };
+}
+
+void PanelTabBar::resizeEvent ( QResizeEvent *e ) {
+ QTabBar::resizeEvent( e );
+
+ for (int i=0; i<count(); i++)
+ tabAt(i)->setText(squeeze(DISPLAY(dynamic_cast<PanelTab*>(tabAt(i))->panel->virtualPath()), i));
+ layoutTabs();
+}
+
+
+void PanelTabBar::dragEnterEvent(QDragEnterEvent *e) {
+ QTab *t = selectTab(e->pos());
+ if (!t) return;
+ if (tab(currentTab()) != t) {
+ setCurrentTab(t);
+ emit changePanel(dynamic_cast<PanelTab*>(t)->panel);
+ }
+}
+
+void PanelTabBar::dragMoveEvent(QDragMoveEvent *e) {
+ QTab *t = selectTab(e->pos());
+ if (!t) return;
+ if (tab(currentTab()) != t) {
+ setCurrentTab(t);
+ emit changePanel(dynamic_cast<PanelTab*>(t)->panel);
+ }
+}
+
+// -----------------------------> PanelTab <----------------------------
+
+PanelTab::PanelTab(const QString & text): QTab(text) {}
+PanelTab::PanelTab(const QString & text, ListPanel *p): QTab(text), panel(p) {}
+
+#include "paneltabbar.moc"
diff --git a/krusader/paneltabbar.h b/krusader/paneltabbar.h
new file mode 100644
index 0000000..0e94f6d
--- /dev/null
+++ b/krusader/paneltabbar.h
@@ -0,0 +1,99 @@
+/*
+ * The concept for this code was taken from the k3b project. k3b is an
+ * excellent CD burning program for KDE, http://k3b.sourceforge.net
+ * Anyway, original code is copyrighted by Sebastian Trueg. Thanks!
+ */
+
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef PANELTABBAR_H
+#define PANELTABBAR_H
+
+#include <kurl.h>
+#include <qtabbar.h>
+#include <qvaluelist.h>
+
+class QMouseEvent;
+class KAction;
+class KActionMenu;
+class ListPanel;
+
+/**
+ * Extends QTab to include a pointer to the panel contained in this tab
+ */
+class PanelTab: public QTab {
+public:
+ PanelTab(const QString & text);
+ PanelTab(const QString & text, ListPanel *p);
+
+ ListPanel *panel;
+};
+
+/**
+ * This class extends QTabBar such that right-clicking on a tab pops-up a menu
+ * containing relevant actions for the tab. It also emits signals (caught by PanelManager)
+ * to create a new tab, close the current tab and change a panel when a tab was clicked
+ */
+class PanelTabBar : public QTabBar {
+ Q_OBJECT
+public:
+ PanelTabBar( QWidget *parent );
+
+public slots:
+ /**
+ * called by PanelManager with an already created panel, and creates the corrosponding tab
+ */
+ int addPanel(ListPanel *panel, bool setCurrent = true );
+ /**
+ * when the user changes the current path in a panel, this method updates the tab accordingly
+ */
+ void updateTab(ListPanel *panel);
+ /**
+ * actually removes the current tab WITHOUT actually deleting the panel.
+ * returns a pointer to the panel which is going to be displayed next.
+ * panelToDelete returns a reference to the pointer of the soon-to-die panel, to
+ * be used by PanelManager.
+ */
+ ListPanel* removeCurrentPanel(ListPanel* &panelToDelete); // returns the panel focused after removing the current
+
+signals:
+ /**
+ * This signal is emitted when the user clicked on a tab. PanelManager should change panels accordingly
+ */
+ void changePanel(ListPanel *p);
+ /**
+ * emitted when the user right-clicks and selected "close"
+ */
+ void closeCurrentTab();
+ /**
+ * emitted when the user right-clicks and selects an action that creates a new tab
+ */
+ void newTab(const KURL& path);
+
+protected:
+ void mousePressEvent( QMouseEvent* );
+ void insertAction( KAction* );
+ QString squeeze(QString text, int index=-1);
+ virtual void dragEnterEvent(QDragEnterEvent *);
+ virtual void dragMoveEvent(QDragMoveEvent *);
+ virtual void resizeEvent ( QResizeEvent *e );
+
+protected slots:
+ void closeTab();
+ void duplicateTab();
+
+private:
+ KActionMenu *_panelActionMenu;
+ bool _left;
+ int _maxTabLength;
+};
+
+#endif
diff --git a/krusader/recode.js b/krusader/recode.js
new file mode 100644
index 0000000..61cb5a3
--- /dev/null
+++ b/krusader/recode.js
@@ -0,0 +1,202 @@
+/*
+ This is an extension for the Krusader filemanager
+ http://krusader.sf.net/
+
+ Author: Vaclav Juza.
+ based on mount by Jonas B�r, http://www.jonas-baehr.de/
+
+ This script shows a dialog for recoding file names. The commandline which is
+ returned by this is executed by Krusader's UserAction-system
+ Krusader looks for the variable 'cmd'.
+
+ scriptDir is a string-variable set by Krusader with the directory of the currently
+ executed script. This is usefull for relative path's inside scripts.
+*/
+
+var cmd = "@CANCEL@"; //FIXME: replace this with UserAction.cancel
+//if an exception occurs, do not continue
+
+var charsetsRecode = ["UTF-8","UTF-7","ISO-8859-2","WINDOWS-1250","IBM852","Kamenicky","MacCentralEurope","ISO-8859-1"];
+var charsetsIconv = ["UTF-8","UTF-7","ISO_6937","ISO-8859-2","WINDOWS-1250","IBM852","ISO-8859-1"];
+var endLineTexts = ["UNIX","DOS","MAC"];
+var endLineVals = ["","/CR-LF","/CR"];
+var mimeTexts = ["NORMAL","BASE64","QUOTED-PRINTABLE"];
+var mimeVals = ["","/Base64","/Quoted-Printable"];
+var dumps = ["NORMAL","Hexadecimal-1","Hexadecimal-2","Hexadecimal-4","Decimal-1","Decimal-2","Decimal-4",
+ "Octal-1","Octal-2","Octal-4"];
+var methodTexts = ["Copy","Rename/move"];
+
+if(dstDir.indexOf(srcDir) == 0 || srcDir.indexOf(dstDir) == 0){ //would do weird things
+ throw new Error("Destination directory inside the source directory is not supported");
+}
+
+var ui = Factory.loadui( scriptDir + 'recode.ui' );
+
+var bc = [ ui.child('boxInCharset'), ui.child('boxOutCharset') ];
+var bl = [ ui.child('boxInLineend'), ui.child('boxOutLineend') ];
+var bm = [ ui.child('boxInMime'), ui.child('boxOutMime') ];
+var bd = [ ui.child('boxInDump'), ui.child('boxOutDump') ];
+var bMtd = ui.child('boxMethod');
+var cbName = ui.child('checkName');
+var cbContent = ui.child('checkContent');
+var cbDebug = ui.child('checkDebug');
+var loc = [ ui.child('locInput'), ui.child('locOutput') ];
+
+function fillCombo(kcombo, texts) {
+ var t = kcombo.child('in-combo');
+ for(i in texts) {
+ t.insertItem(texts[i]);
+ }
+ kcombo.currentItem = 0;
+}
+
+if(useRecode==1){
+ for(var d=0;d<=1;d++){
+ fillCombo(bc[d],charsetsRecode);
+ fillCombo(bl[d],endLineTexts);
+ fillCombo(bm[d],mimeTexts);
+ fillCombo(bd[d],dumps);
+ bc[0].currentItem = 2;
+ }
+}else{
+ for(var d=0;d<=1;d++){
+ fillCombo(bc[d],charsetsIconv);
+ bc[0].currentItem = 3;
+ bl[0].shown = 0;
+ bl[1].shown = 0;
+ bm[0].shown = 0;
+ bm[1].shown = 0;
+ bd[0].shown = 0;
+ bd[1].shown = 0;
+ }
+}
+fillCombo(bMtd,methodTexts);
+
+//defaults
+loc[0].url = srcDir;
+loc[1].url = dstDir;
+cbName.checked=1;
+cbContent.checked=0;
+cbDebug.checked=0;
+
+function quoteString(str) {
+ return "'" + str.replace(/'/g,"'\\''") + "'";
+}
+
+function indentString(str) {
+ return str.replace(/(^|\n)([^$])/g,"$1 $2");
+}
+
+function debugString(str) {
+ return str.replace(/(<|>|\\|;)/g,"\\$1").replace(/"/g,"\\\"\"");
+}
+
+bc[0].setFocus();
+var m = ui.exec();
+
+if(m) {
+ var isMove = ( bMtd.currentItem == 1 );
+ var rcName = cbName.checked;
+ var rcContent = cbContent.checked;
+ var debug = cbDebug.checked;
+
+ srcDir = loc[0].url;
+ dstDir = loc[1].url;
+ if(dstDir.indexOf(srcDir) == 0 || srcDir.indexOf(dstDir) == 0){ //would do weird things
+ throw new Error("Destination directory inside the source directory is not supported");
+ }
+
+ var listCmd =
+ "for i in " + toProcess + "\n"
+ +"do\n"
+ +" find \"${i}\" -name '*'\n"
+ +"done";
+
+ //the following contains user input, must be quoted
+ var recodeCmd, recodeSmallCmd;
+ if(useRecode==1){
+ var expr = new Array(2);
+ var smallExpr = new Array(2);
+ for(var d=0; d<=1; d++){
+ var chs = "";
+ chs = bc[d].currentText;
+ var le = endLineVals[ bl[d].currentItem ];
+ var me = mimeVals[ bm[d].currentItem ];
+ var du="";
+ if( bd[d].currentItem > 0 ) {
+ du = "/" + bd[d].currentText;
+ }
+ expr[d] = chs + le + me + du;
+ smallExpr[d] = chs + me;
+ }
+ recodeCmd="recode " + quoteString(expr[0] + ".." + expr[1]);
+ recodeSmallCmd="recode " + quoteString(smallExpr[0] + ".." + smallExpr[1]);
+ }else{
+ recodeCmd="iconv -f " + quoteString(bc[0].currentText) + " -t " + quoteString(bc[1].currentText);
+ recodeSmallCmd=recodeCmd;
+ }
+
+ var setupVarsCmd;
+ if(rcName){
+ setupVarsCmd =
+ "fnew=\"$(\n"
+ +" echo \"${forig}\" | " + recodeSmallCmd +"\n"
+ +")\"";
+ }else{
+ setupVarsCmd = "fnew=\"${forig}\"";
+ }
+ var dstStr = dstDir + "/\"${fnew}\"";
+ var oneDirCmd = "mkdir " + dstStr; //create the directory in new location
+ var oneFileCmd;
+ var oneSpcCmd;
+ if(isMove){
+ oneSpcCmd = "mv " + "\"${forig}\" " + dstStr;
+ }else{
+ oneSpcCmd = "cp -dp " + "\"${forig}\" " + dstStr;
+ }
+ if(rcContent){
+ oneFileCmd = recodeCmd + " \<\"${forig}\" \>"+dstStr;
+ if(isMove){
+ oneFileCmd += "&& rm -f \"${forig}\"";
+ }
+ }else{
+ oneFileCmd = oneSpcCmd;
+ }
+ oneDirCmdDbg="echo directory:" + debugString(oneDirCmd);
+ oneFileCmdDbg="echo file:" + debugString(oneFileCmd);
+ oneSpcCmdDbg="echo special:" + debugString(oneSpcCmd);
+ var oneItemCmd =
+ setupVarsCmd + "\n"
+ +"if [ ! -L \"${forig}\" ] && [ -d \"${forig}\" ]\n"
+ +"then\n"
+ +indentString(oneDirCmdDbg) + "\n"
+ + ( debug ? "" : indentString(oneDirCmd) + "\n" )
+ +"elif [ -f \"${forig}\" ]\n"
+ +"then\n"
+ +indentString(oneFileCmdDbg) + "\n"
+ + ( debug ? "" : indentString(oneFileCmd) + "\n" )
+ +"else\n"
+ +indentString(oneSpcCmdDbg) + "\n"
+ + ( debug ? "" : indentString(oneSpcCmd) + "\n" )
+ +"fi";
+ var processCmd =
+ "while read forig;\n"
+ +"do\n"
+ +indentString(oneItemCmd) + "\n"
+ +"done";
+ if(isMove){
+ var deleteOldCmd =
+ "for i in " + toProcess + "\n"
+ +"do\n"
+ +" [ / = \"$i\" ] || rm -rf \"${i}\"\n"
+ +"done";
+ var realCmd = "(\n" + indentString(listCmd) + "\n) | (\n" + indentString(processCmd) + "\n)\n"+ deleteOldCmd;
+ }else{
+ var realCmd = "(\n" + indentString(listCmd) + "\n) | (\n" + indentString(processCmd) + "\n)";
+ }
+ cmd = "sh -c " + quoteString("LANG=C; cd " + quoteString(srcDir) + "; " + realCmd);
+ /*if(debug){
+ cmd = "echo " + quoteString(cmd);
+ }*/
+}
+
diff --git a/krusader/recode.ui b/krusader/recode.ui
new file mode 100644
index 0000000..3c97d47
--- /dev/null
+++ b/krusader/recode.ui
@@ -0,0 +1,297 @@
+<!DOCTYPE UI>
+<UI version="3.3" stdsetdef="1">
+<class>recodeDlg</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>recodeDlg</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>396</width>
+ <height>185</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>10</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="caption">
+ <string>Recode file names</string>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>true</bool>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="9" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>Layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>Horizontal Spacing2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonOk</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonCancel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel" row="0" column="1">
+ <property name="name">
+ <cstring>labelInHdr</cstring>
+ </property>
+ <property name="text">
+ <string>INPUT:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="2">
+ <property name="name">
+ <cstring>labelOutHdr</cstring>
+ </property>
+ <property name="text">
+ <string>OUTPUT:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>labelCharset</cstring>
+ </property>
+ <property name="text">
+ <string>Charset: </string>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="1" column="1">
+ <property name="name">
+ <cstring>boxInCharset</cstring>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="1" column="2">
+ <property name="name">
+ <cstring>boxOutCharset</cstring>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>labelLineend</cstring>
+ </property>
+ <property name="text">
+ <string>End of line: </string>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="2" column="1">
+ <property name="name">
+ <cstring>boxInLineend</cstring>
+ </property>
+ <property name="editable">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="2" column="2">
+ <property name="name">
+ <cstring>boxOutLineend</cstring>
+ </property>
+ <property name="editable">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="0">
+ <property name="name">
+ <cstring>labelMime</cstring>
+ </property>
+ <property name="text">
+ <string>MIME Encoding: </string>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="3" column="1">
+ <property name="name">
+ <cstring>boxInMime</cstring>
+ </property>
+ <property name="editable">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="3" column="2">
+ <property name="name">
+ <cstring>boxOutMime</cstring>
+ </property>
+ <property name="editable">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="0">
+ <property name="name">
+ <cstring>labelDump</cstring>
+ </property>
+ <property name="text">
+ <string>Dump type: </string>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="4" column="1">
+ <property name="name">
+ <cstring>boxInDump</cstring>
+ </property>
+ <property name="editable">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="4" column="2">
+ <property name="name">
+ <cstring>boxOutDump</cstring>
+ </property>
+ <property name="editable">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QLabel" row="5" column="0">
+ <property name="name">
+ <cstring>labelLocation</cstring>
+ </property>
+ <property name="text">
+ <string>Location</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="5" column="1">
+ <property name="name">
+ <cstring>locInput</cstring>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="5" column="2">
+ <property name="name">
+ <cstring>locOutput</cstring>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="6" column="1">
+ <property name="name">
+ <cstring>boxMethod</cstring>
+ </property>
+ <property name="editable">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="7" column="1">
+ <property name="name">
+ <cstring>checkName</cstring>
+ </property>
+ <property name="text">
+ <cstring>recode file name</cstring>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="8" column="1">
+ <property name="name">
+ <cstring>checkContent</cstring>
+ </property>
+ <property name="text">
+ <cstring>recode file contents</cstring>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="7" column="2">
+ <property name="name">
+ <cstring>checkDebug</cstring>
+ </property>
+ <property name="text">
+ <cstring>test; only prints the commands</cstring>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>buttonOk</sender>
+ <signal>clicked()</signal>
+ <receiver>recodeDlg</receiver>
+ <slot>accept()</slot>
+ </connection>
+ <connection>
+ <sender>buttonCancel</sender>
+ <signal>clicked()</signal>
+ <receiver>recodeDlg</receiver>
+ <slot>reject()</slot>
+ </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+</includehints>
+</UI>
diff --git a/krusader/resources.h b/krusader/resources.h
new file mode 100644
index 0000000..bdcc1b1
--- /dev/null
+++ b/krusader/resources.h
@@ -0,0 +1,42 @@
+/***************************************************************************
+ resources.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef RESOURCES_H
+#define RESOURCES_H
+
+#include <kdebug.h>
+
+// STATUSBAR messages
+#define S_READY_ID 1001
+
+//////////////////////////// auxilary functions (macros) /////////////////////////
+#define MDISABLE(X) menuBar()->setItemEnabled(X,false)
+
+#endif
diff --git a/krusader/select_from_file.js b/krusader/select_from_file.js
new file mode 100644
index 0000000..3d00c32
--- /dev/null
+++ b/krusader/select_from_file.js
@@ -0,0 +1,13 @@
+/*
+ This is an extension for the Krusader filemanager
+ http://krusader.sourceforge.net/
+
+ Author: Dirk Eschler <deschler@users.sourceforge.net>
+
+ Reads a file that contains a list of files separated by newline and builds
+ a list separated by whitespace from it.
+
+ The script is supposed to be used in conjunction with the select_from_file
+ user action: http://www.kde-files.org/content/show.php?content=54518
+*/
+var filelist = shell("cat " + file).replace(/\n/g, ' ') || "";
diff --git a/krusader/splash.png b/krusader/splash.png
new file mode 100644
index 0000000..3c25a9e
--- /dev/null
+++ b/krusader/splash.png
Binary files differ
diff --git a/krusader/total_cmd_pleasent.color b/krusader/total_cmd_pleasent.color
new file mode 100644
index 0000000..4f0681e
--- /dev/null
+++ b/krusader/total_cmd_pleasent.color
Binary files differ
diff --git a/krusader/total_commander.color b/krusader/total_commander.color
new file mode 100644
index 0000000..8f7d15a
--- /dev/null
+++ b/krusader/total_commander.color
Binary files differ
diff --git a/krusader/total_commander.keymap b/krusader/total_commander.keymap
new file mode 100644
index 0000000..c8a6687
--- /dev/null
+++ b/krusader/total_commander.keymap
@@ -0,0 +1,112 @@
+[Shortcuts]
+F10_Quit=F10
+F2_Terminal=F2
+F3_View=F3
+F4_Edit=F4
+F5_Copy=F5
+F6_Move=F6
+F7_Mkdir=F7
+F8_Delete=F8
+F9_Rename=F9
+JS_Console=Alt+Ctrl+J
+Popular_Urls=Ctrl+Z
+all files=Shift+F10
+ar_pack=none
+ar_unpack=none
+back=none
+bookmark current=Ctrl+Shift+D
+bookmarks=Ctrl+D
+calculate=none
+close tab=Ctrl+W
+cmdline popup=Ctrl+Slash
+combine=Ctrl+B
+compare=none
+compare dirs=none
+create checksum=none
+custom files=Shift+F12
+decrypt_with_kgpg=none
+dirUp=Ctrl+PageUp
+disk usage=Alt+D
+duplicate tab=Alt+Ctrl+Shift+N
+edit_new_file=Shift+F4
+filename_to_clipboard=none
+find=Ctrl+S
+ftp disconnect=Ctrl+Shift+F
+ftp new connection=Ctrl+N
+help_about_app=none
+help_about_kde=none
+help_contents=F1
+help_report_bug=none
+help_whats_this=Shift+F1
+history=Ctrl+H
+invert=Alt+Asterisk
+jump_back=Ctrl+J
+konfigurator=none
+left bookmarks=Alt+Left
+left history=Alt+Ctrl+Left
+left media=Ctrl+Shift+Left
+locate=Ctrl+Shift+L
+location_bar=Ctrl+L
+manage useractions=none
+match checksum=none
+media=Ctrl+M
+mountman=Alt+Slash
+multirename=Shift+F9
+new symlink=Alt+Ctrl+S
+new tab=Alt+Ctrl+N
+next tab=Shift+Right
+pack=Alt+P
+previous tab=Shift+Left
+profile=Alt+L
+properties=Alt+KP_Enter
+right bookmarks=Alt+Right
+right history=Alt+Ctrl+Right
+right media=Ctrl+Shift+Right
+rightclick menu=Menu
+root=Ctrl+Backspace
+root krusader=Alt+K
+sample_edit_as_root=none
+sample_newmount=none
+sample_panesize=none
+save position=none
+select all=Alt+Plus
+select group=Ctrl+Plus
+select_different=none
+select_different_and_single=none
+select_newer=none
+select_newer_and_single=none
+select_single=none
+set_jump_back=Ctrl+Shift+J
+sort_by_extension=none
+sort_by_modified=none
+sort_by_name=none
+sort_by_size=none
+split=Ctrl+P
+std_config_keys=none
+std_config_toolbar=none
+std_copy=Ctrl+C;Ctrl+Insert
+std_cut=Ctrl+X;Shift+Delete
+std_home=Ctrl+Home;XF86HomePage
+std_paste=Ctrl+V;Shift+Insert
+std_quit=Ctrl+Q
+std_redisplay=Ctrl+R
+std_statusbar=none
+std_toolbar=none
+swap panels=Ctrl+U
+switch_fullscreen_te=Ctrl+F
+sync browse=Alt+Y
+sync dirs=Ctrl+Y
+sync panels=Alt+O
+terminal@home=none
+test archives=Alt+E
+toggle actions toolbar=none
+toggle command line=none
+toggle fn bar=none
+toggle hidden files=Ctrl+Period
+toggle popup panel=Alt+Down
+toggle swap sides=Ctrl+Shift+U
+toggle terminal emulator=Alt+Ctrl+T
+toggle vertical mode=Alt+Ctrl+R
+unpack=Alt+U
+unselect all=Alt+Minus
+unselect group=Ctrl+Minus
diff --git a/krusader/total_commander.keymap.info b/krusader/total_commander.keymap.info
new file mode 100644
index 0000000..0555574
--- /dev/null
+++ b/krusader/total_commander.keymap.info
@@ -0,0 +1,10 @@
+Please note that the following shortcuts are KDE global shortcuts:
+ALT-F1, ALT-F2, ALT-F5, ALT-F9
+
+This means that in order for Krusader to use them, you must
+first disable them in KDE's global shortcut panel.
+To do so, open KDE's Control Center, open "Keyboard Shortcuts"
+and in the "Global Shortcuts" tab, disable the mentioned shortcuts.
+
+
+
diff --git a/krusader/useraction_examples.xml b/krusader/useraction_examples.xml
new file mode 100644
index 0000000..443f12f
--- /dev/null
+++ b/krusader/useraction_examples.xml
@@ -0,0 +1,406 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE KrusaderUserActions>
+<KrusaderUserActions>
+ <action name="sample_panesize" >
+ <title>Equal panel-size</title>
+ <tooltip>Sets the ratio between the two panels to 50/50.</tooltip>
+ <icon>view_left_right</icon>
+ <category>User Interface</category>
+ <command>%aPanelSize(&quot;50&quot;)%</command>
+ <defaultshortcut>Alt+Ctrl+Equal</defaultshortcut>
+ </action>
+ <action name="sort_by_name" >
+ <title>Sort by Name</title>
+ <tooltip>Sort by Name.</tooltip>
+ <icon>view_text</icon>
+ <category>User Interface</category>
+ <description>Sorts the active panel by Name</description>
+ <command>%aColSort(&quot;Name&quot;)%</command>
+ <defaultshortcut>Win+1</defaultshortcut>
+ </action>
+ <action name="sort_by_extension" >
+ <title>Sort by Extension</title>
+ <tooltip>Sort by Extension.</tooltip>
+ <icon>view_text</icon>
+ <category>User Interface</category>
+ <description>Sorts the active panel by Extension</description>
+ <command>%aColSort(&quot;Ext&quot;)%</command>
+ <defaultshortcut>Win+2</defaultshortcut>
+ </action>
+ <action name="sort_by_size" >
+ <title>Sort by Size</title>
+ <tooltip>Sort by Size.</tooltip>
+ <icon>view_text</icon>
+ <category>User Interface</category>
+ <description>Sorts the active panel by Size</description>
+ <command>%aColSort(&quot;Size&quot;)%</command>
+ <defaultshortcut>Win+3</defaultshortcut>
+ </action>
+ <action name="sort_by_modified" >
+ <title>Sort by Modified</title>
+ <tooltip>Sort by Modified.</tooltip>
+ <icon>view_text</icon>
+ <category>User Interface</category>
+ <description>Sorts the active panel by Modified</description>
+ <command>%aColSort(&quot;Modified&quot;)%</command>
+ <defaultshortcut>Win+4</defaultshortcut>
+ </action>
+ <action name="sample_edit_as_root" >
+ <title>Edit as root</title>
+ <tooltip>Edit a file as root.</tooltip>
+ <icon>kwrite</icon>
+ <category>File</category>
+ <description>Edit a file with root permissions</description>
+ <command run_as="root" >kwrite %aCurrent%</command>
+ <defaultshortcut>Ctrl+E</defaultshortcut>
+ </action>
+ <action name="file_root_copy" >
+ <title>Copy as root</title>
+ <tooltip>Copy as root.</tooltip>
+ <icon>editcopy</icon>
+ <category>File</category>
+ <description>Copy selected files &amp; directories with root privileges, also inside archives!</description>
+ <command run_as="root" accept="url" >kfmclient copy %aList(&quot;Selected&quot;, &quot; &quot;, &quot;No&quot;)% %oPath%</command>
+ </action>
+ <action name="backup_current" >
+ <title>Backup current file</title>
+ <tooltip>Backup current file in current directory.</tooltip>
+ <icon>filesaveas</icon>
+ <category>File</category>
+ <description>Backups current file in current directory and asks the user for a new filename. By default &quot;.old&quot; is appended to the original filename.</description>
+ <command>%_Copy(&quot;%aCurrent%&quot;, &quot;%_Ask(&quot;New filename&quot;, &quot;%aCurrent%.old&quot;)%&quot;)%</command>
+ <defaultshortcut>Shift+F5</defaultshortcut>
+ </action>
+ <action name="file_search_replace" >
+ <title>Search and Replace in file</title>
+ <tooltip>Search and replace a string/regex in textfiles with sed.</tooltip>
+ <icon>xclipboard</icon>
+ <category>File</category>
+ <description>This UA uses the UNIX standard-tool sed (the stream-editor) so perform search and replace operations in all selected files
+It is possible to give a regular expression for both strings.
+Please note: The sed-command is &quot;s/search/repleace/&quot;, so you have to escape the slash when you need it!</description>
+ <command>sed -i -e 's/%_Ask(&quot;Search for:&quot;)%/%_Ask(&quot;Replace with:&quot;)%/' %aList(&quot;Selected&quot;)%</command>
+ </action>
+ <action name="sample_newmount" >
+ <title>Mount</title>
+ <tooltip>Mount a new filesystem.</tooltip>
+ <icon>hdd_mount</icon>
+ <category>System</category>
+ <command run_as="root" executionmode="collect_output" >mount -t %_Ask(&quot;Filesystem Type?&quot;)% %_Ask(&quot;Device ?&quot;)% %_Ask(&quot;Mount Point ?&quot;)%</command>
+ <defaultshortcut>Alt+Ctrl+M</defaultshortcut>
+ </action>
+ <action name="system_umount" >
+ <title>Unmount</title>
+ <tooltip>Umount filesystem of current directory.</tooltip>
+ <icon>kcmpartitions</icon>
+ <category>System</category>
+ <command run_as="root" executionmode="collect_output" >result=`umount '%aCurrent%' 2>&amp;1`; case &quot;$?&quot; in 0) kdialog --title Krusader --msgbox &quot;Filesystem unmounted&quot;; ;; 1) apps=`lsof | grep '%aCurrent%' | head | cut -d ' ' -f 1`; kdialog --title Krusader --error &quot;Could not unmount filesystem.\n\nIt is still in use by the following applications:\n$apps&quot;; ;; *) kdialog --title Krusader --error &quot;Could not unmount filesystem.\n$result&quot;; ;; esac</command>
+ </action>
+ <action name="system_Eject" >
+ <title>Eject cd/dvd</title>
+ <tooltip>Unmounts and ejects current cdrom/dvd.</tooltip>
+ <icon>player_eject</icon>
+ <category>System</category>
+ <command>umount %aCurrent% ; /usr/bin/eject -r %aCurrent%</command>
+ </action>
+ <action name="archive_gzip_current" >
+ <title>gzip current file</title>
+ <tooltip>Make gzip archive containing current file to other panel.</tooltip>
+ <icon>ark</icon>
+ <category>Archive</category>
+ <description>Gzip current file with maximum (9) compression, preserving original file. In case of directory, it is first tarred.</description>
+ <command>if [ -d %aCurrent(&quot;Yes&quot;)% ]; then tar cf - %aCurrent(&quot;Yes&quot;)% | gzip -9 >%oPath%%aCurrent(&quot;Yes&quot;)%.tar.gz; else cat %aCurrent(&quot;Yes&quot;)% | gzip -9 >%oPath%%aCurrent(&quot;Yes&quot;)%.gz; fi</command>
+ </action>
+ <action name="archive_7z_current" >
+ <title>7zip current file</title>
+ <tooltip>Make 7zip archive containing current file to other panel.</tooltip>
+ <icon>ark</icon>
+ <category>Archive</category>
+ <command>rm -f %aCurrent(&quot;Yes&quot;)%.7z; 7z a -mx=9 -mfb=128 -md=8m %oPath%%aCurrent(&quot;Yes&quot;)%.7z %aCurrent(&quot;Yes&quot;)%
+ </command>
+ </action>
+ <action name="archive_pack_lzma" >
+ <title>Lzma current file</title>
+ <tooltip>Make lzma archive containing current file to other panel.</tooltip>
+ <icon>ark</icon>
+ <category>Archive</category>
+ <description>Lzma current file and keep input files to other panel.</description>
+ <command>lzma -zkc %aCurrent% > %oPath%%aCurrent(&quot;Yes&quot;)%.lzma</command>
+ </action>
+ <action name="archive_tgz_current" >
+ <title>tar.gz selected files</title>
+ <tooltip>Make tar.gz archive containing selected files to other panel.</tooltip>
+ <icon>ark</icon>
+ <category>Archive</category>
+ <command>tar cf - %aList(&quot;Selected&quot;, &quot; &quot;, &quot;Yes&quot;)% | gzip -9 > %oPath%%aCurrent(&quot;Yes&quot;)%.tar.gz</command>
+ </action>
+ <action name="archive_tar_lzma" >
+ <title>tar.lzma selected files</title>
+ <tooltip>Make tar.lzma archive containing selected files to other panel.</tooltip>
+ <icon>ark</icon>
+ <category>Archive</category>
+ <command>tar cf - %aList(&quot;Selected&quot;, &quot; &quot;, &quot;Yes&quot;)% | lzma -z > %oPath%%aCurrent(&quot;Yes&quot;)%.tar.lzma</command>
+ </action>
+ <action name="archive_ar_pack" >
+ <title>ar selected files</title>
+ <tooltip>Make ar (.a, .deb, ...) archive of selected files to other panel.</tooltip>
+ <icon>ark</icon>
+ <category>Archive</category>
+ <description>Make an archive using the ar utility, which is used for static libraries (*.a) or debian packages. Like tar, ar does not use any compression.</description>
+ <command executionmode="terminal" >sh -c 'A=%_Ask(&quot;Enter file name of the archive:&quot;, &quot;%oPath%%aCurrent(\&quot;Yes\&quot;)%.a&quot;, &quot;ar pack&quot;)% ; rm -f &quot;$A&quot;; ar -rc &quot;$A&quot; %aList(&quot;Selected&quot;, &quot; &quot;, &quot;Yes&quot;)% '</command>
+ </action>
+ <action name="archive_tar_7z" >
+ <title>tar.7z selected files</title>
+ <tooltip>Make tar.7z archive containing selected files to other panel.</tooltip>
+ <icon>ark</icon>
+ <category>Archive</category>
+ <command executionmode="collect_output" >tar cf - %aList(&quot;Selected&quot;, &quot; &quot;, &quot;Yes&quot;)% | 7z a -si %oPath%%aCurrent(&quot;Yes&quot;)%.tar.7z</command>
+ </action>
+ <action name="archive_archive2dir" >
+ <title>Unpack archive to dir</title>
+ <tooltip>Creates a directory with the archive name before unpacking.</tooltip>
+ <icon>package</icon>
+ <category>Archive</category>
+ <description>Creates a directory with the current archive name in the other panel before unpacking the files into it. It uses ark and tries to guess the directory name (archive name without file extension).</description>
+ <command>ark --guess-name --extract-to %oPath% %aCurrent%</command>
+ </action>
+ <action name="archive_unpack_tar_7z" >
+ <title>Unpack current tar.7z</title>
+ <tooltip>Unpack current tar.7z to other panel.</tooltip>
+ <icon>package</icon>
+ <category>Archive</category>
+ <command executionmode="collect_output" >sh -c 'cd %oPath%; 7z x -so &quot;%aCurrent%&quot; | tar xf -'</command>
+ </action>
+ <action name="archive_unpack_tar_lzma" >
+ <title>Unpack current tar.lzma</title>
+ <tooltip>Unpack current tar.lzma to other panel.</tooltip>
+ <icon>package</icon>
+ <category>Archive</category>
+ <description>Unpack current tar.lzma to other panel and keep original input file.</description>
+ <command>sh -c 'cd &quot;%oPath%&quot;; lzma -dkc &quot;%aCurrent%&quot; | tar xf -'</command>
+ </action>
+ <action name="archive_unpack_lzma" >
+ <title>Unpack current lzma</title>
+ <tooltip>Unpack current lzma to other panel.</tooltip>
+ <icon>package</icon>
+ <category>Archive</category>
+ <description>Unpack current lzma to other panel and keep original input file.</description>
+ <command>lzma -dkc %aCurrent% >%oPath%/`basename %aCurrent% .lzma`</command>
+ </action>
+ <action name="archive_ar_unpack" >
+ <title>Unpack ar archive (.a, .deb, ...)</title>
+ <icon>package</icon>
+ <category>Archive</category>
+ <description>Extract an ar archive using the ar utility, which is used for static libraries (*.a) or debian packages (you can extract debian packages this way without having dpkg installed). Like tar, ar does not use any compression.</description>
+ <command executionmode="terminal" >sh -c 'A=%_Ask(&quot;Enter the path, where the archive should be unpacked to:&quot;, &quot;%oPath%&quot;, &quot;ar unpack&quot;)% ; cd &quot;$A&quot;; for i in %aList(&quot;Selected&quot;)% ; do ar x &quot;$i&quot;; done '</command>
+ </action>
+ <action name="archive_multi_zip_unpack" >
+ <title>Unpack multiple zip arc&amp;hives</title>
+ <icon>package</icon>
+ <tooltip>Unpack multiple zip archives</tooltip>
+ <category>Archive</category>
+ <description>Unpack all selected zip archives into separate direcories. The new directory name has the same as the zip archive name.</description>
+ <command executionmode="collect_output" >for file in %aList("Selected")%; do dir=`basename $file|sed -e 's/.zip//g'`; unzip $file -d %oPath%/$dir; done</command>
+ </action>
+ <action name="filename_to_clipboard" >
+ <title>Copy current item to clipboard</title>
+ <icon>editpaste</icon>
+ <category>System</category>
+ <command>%_Clipboard(&quot;%aCurrent%&quot;)%</command>
+ <defaultshortcut>Alt+Ctrl+C</defaultshortcut>
+ </action>
+ <action name="sample_amarok_enqueue" >
+ <title>Enqueue in Amarok</title>
+ <tooltip>Append selected item(s) to Amarok playlist.</tooltip>
+ <icon>amarok</icon>
+ <category>Multimedia</category>
+ <command>amarok --append %aList(&quot;Selected&quot;)%</command>
+ <defaultshortcut>Win+A</defaultshortcut>
+ </action>
+ <action name="Multimedia_Split_mp3" >
+ <title>Split large mp3</title>
+ <tooltip>Splits large mp3's using mp3splt.</tooltip>
+ <icon>kcmsound</icon>
+ <category>Multimedia</category>
+ <command executionmode="terminal" >mp3splt %aCurrent(&quot;Yes&quot;)% -c *.cue -a -f -o &quot;@n - @p - @t&quot;</command>
+ </action>
+ <action name="encryption_encrypt_with_kgpg" >
+ <title>Encrypt with kgpg</title>
+ <tooltip>Encrypts the current file with kpgp (which has to be in your $PATH).</tooltip>
+ <icon>kgpg_key1</icon>
+ <category>Encryption</category>
+ <command>kgpg -e %aCurrent%</command>
+ </action>
+ <action name="encryption_decrypt_with_kgpg" >
+ <title>Decrypt with kgpg</title>
+ <tooltip>Decrypts the current file with kpgp (which has to be in your $PATH).</tooltip>
+ <icon>kgpg_show</icon>
+ <category>Encryption</category>
+ <command>kgpg %aCurrent%</command>
+ </action>
+ <action name="encryption_sign_with_kgpg" >
+ <title>Sign with kgpg</title>
+ <tooltip>Signs the current file with kpgp (which has to be in your $PATH).</tooltip>
+ <icon>kgpg_sign</icon>
+ <category>Encryption</category>
+ <command>kgpg -S %aCurrent%</command>
+ </action>
+ <action name="encryption_verify_sig_with_kpgp" >
+ <title>Verify signature with kgpg</title>
+ <tooltip>Tries to verify the signature of the current file with kpgp (which has to be in your $PATH).</tooltip>
+ <icon>kgpg_identity</icon>
+ <category>Encryption</category>
+ <command>kgpg -V %aCurrent%</command>
+ </action>
+ <action name="file_uudecode" >
+ <title>Uudecode</title>
+ <tooltip>Decode current file created with uuencode.</tooltip>
+ <icon>binary</icon>
+ <category>File</category>
+ <description>Decode a file created with uuencode. Requirements: Sharutils</description>
+ <command>uudecode %aCurrent%</command>
+ </action>
+ <action name="file_uuencode" >
+ <title>Uuencode</title>
+ <tooltip>Uuencode current file.</tooltip>
+ <icon>ascii</icon>
+ <category>File</category>
+ <description>Uuencode creates an encoded ASCII copy of a file. Requirements: Sharutils</description>
+ <command>uuencode %aCurrent(&quot;Yes&quot;)% %aCurrent(&quot;Yes&quot;)% > %oPath%\/%_Ask(&quot;Name of output file (without extension):&quot;, &quot;%aCurrent(&quot;Yes&quot;)%&quot;, &quot;uuencode&quot;)%.uue</command>
+ </action>
+ <action name="Jscript_select_from_file" >
+ <title>Javascript, select from file</title>
+ <icon>kr_select</icon>
+ <category>File</category>
+ <description>TC-like &quot;load selection from file&quot;. Use this action on a text file which contains a list of filenames and these files will be selected.</description>
+ <command>%aSelect(&quot;%_Script(&quot;select_from_file.js&quot;, &quot;return=filelist;file=%aCurrent%&quot;)%&quot;)%</command>
+ </action>
+ <action name="Jscript_file_recode_gnu" >
+ <title>Javascript, recode files using GNU recode</title>
+ <icon>charset</icon>
+ <category>File</category>
+ <description>A javascript useraction, which converts either file names or their content or both from one to another character encoding. It processes all selected files and directories in the active panel (for the directories, recurse their content). You can select, whether a recoded copy is created or if the file is moved (there is no warranty, so don't test move on any important data)
+Requirements:
+You need krusader compiled with javascript support and GNU recode installed.</description>
+ <command executionmode="terminal" >%_Script(&quot;recode.js&quot;, &quot;return=cmd;toProcess=%aList(\&quot;Selected\&quot;, \&quot; \&quot;, \&quot;Yes\&quot;)%;dstDir=%oPath%;srcDir=%aPath%;useRecode=1&quot;)%</command>
+ </action>
+ <action name="Jscript_file_recode_iconv" >
+ <title>Javascript, recode files using iconv</title>
+ <icon>charset</icon>
+ <category>File</category>
+ <description>A javascript useraction, which converts either file names or their content or both from one to another character encoding. It processes all selected files and directories in the active panel (for the directories, recurse their content). You can select, whether a recoded copy is created or if the file is moved (there is no warranty, so don't test move on any important data)
+Requirements:
+You need krusader compiled with javascript support and iconv installed.</description>
+ <command executionmode="terminal" >%_Script(&quot;recode.js&quot;, &quot;return=cmd;toProcess=%aList(\&quot;Selected\&quot;, \&quot; \&quot;, \&quot;Yes\&quot;)%;dstDir=%oPath%;srcDir=%aPath%;useRecode=0&quot;)%</command>
+ </action>
+ <action name="Jscript_root-mount" >
+ <title>Javascript, mount as root</title>
+ <tooltip>Mounts a device with root-privileges</tooltip>
+ <icon>hdd_mount</icon>
+ <category>System</category>
+ <description>Requirements:
+You need krusader compiled with javascript support.</description>
+ <command run_as="root" executionmode="collect_output" >%_Script(&quot;mount.js&quot;, &quot;return=cmd&quot;)%</command>
+ </action>
+ <action name="js_calc" >
+ <title>JavaScript, calculator</title>
+ <icon>xcalc</icon>
+ <category>Misc</category>
+ <description>Requirements:
+You need krusader compiled with javascript support.</description>
+ <command>%_Script(&quot;calc.js&quot;)%</command>
+ </action>
+ <action name="archive2dir" >
+ <title>Archive to Dir</title>
+ <tooltip>Creates a directory with the archive name before unpacking</tooltip>
+ <icon>ark</icon>
+ <category>System</category>
+ <description>Creates a directory with the current archive name in the other panel before unpacking the files into it. It uses ark and tries to guess the directory name (archive name without file extension).</description>
+ <command>ark --guess-name --extract-to %oPath% %aCurrent%</command>
+ <defaultshortcut>Alt+Ctrl+U</defaultshortcut>
+ </action>
+ <action name="7z_current" >
+ <title>7zip current</title>
+ <tooltip>make an 7zip archive containing current file</tooltip>
+ <category>Compression</category>
+ <command>rm -f %aCurrent(&quot;Yes&quot;)%.7z; 7z a -mx=9 -mfb=128 -md=8m %aCurrent(&quot;Yes&quot;)%.7z %aCurrent(&quot;Yes&quot;)%</command>
+ <defaultshortcut>Ctrl+Ampersand</defaultshortcut>
+ </action>
+ <action name="7z_pack" >
+ <title>7zip pack</title>
+ <tooltip>7zip selected files with dialog and terminal with progress.</tooltip>
+ <category>Compression</category>
+ <command executionmode="terminal" >sh -c 'A=%_Ask(&quot;Enter file name of the archive:&quot;, &quot;%oPath%%aCurrent(\&quot;Yes\&quot;)%.7z&quot;, &quot;7zip pack&quot;)% ; rm -f &quot;$A&quot;; 7z a -mx=9 -mfb=128 -md=8m &quot;$A&quot; %aList(&quot;Selected&quot;, &quot; &quot;, &quot;Yes&quot;)% '</command>
+ </action>
+ <action name="7z_unpack" >
+ <title>7zip unpack</title>
+ <tooltip>unpack 7zip archives with dialog and terminal with progress.</tooltip>
+ <category>Compression</category>
+ <command executionmode="terminal" >sh -c 'A=%_Ask(&quot;Enter the path, where the archive should be unpacked to:&quot;, &quot;%oPath%&quot;, &quot;7zip unpack&quot;)% ; cd &quot;$A&quot;; for i in %aList(&quot;Selected&quot;)% ; do 7z x &quot;$i&quot;; done '</command>
+ </action>
+ <action name="tar.7z_pack" >
+ <title>make tar.7z archive</title>
+ <tooltip>7zip selected files with dialog and terminal with progress.</tooltip>
+ <category>Compression</category>
+ <command executionmode="terminal" >sh -c 'A=%_Ask(&quot;Enter file name of the archive:&quot;, &quot;%oPath%%aCurrent(\&quot;Yes\&quot;)%.tar.7z&quot;, &quot;7zip pack&quot;)% ; rm -f &quot;$A&quot;; tar cvf - %aList(&quot;Selected&quot;, &quot; &quot;, &quot;Yes&quot;)% | 7z a -mx=9 -mfb=128 -md=8m -si &quot;$A&quot; >/dev/null '</command>
+ </action>
+ <action name="tar.7z_unpack" >
+ <title>unpack tar.7z archive</title>
+ <tooltip>unpack 7zip archives with dialog and terminal with progress.</tooltip>
+ <category>Compression</category>
+ <command executionmode="terminal" >sh -c 'A=%_Ask(&quot;Enter the path, where the archive should be unpacked to:&quot;, &quot;%oPath%&quot;, &quot;7zip unpack&quot;)% ; cd &quot;$A&quot;; for i in %aList(&quot;Selected&quot;)% ; do 7z x -so &quot;$i&quot; 2>/dev/null | tar xvf - ; done '</command>
+ </action>
+ <action name="tgz_current" >
+ <title>zatarovat and zagzipovat</title>
+ <category>Compression</category>
+ <command>tar cf - %aCurrent(&quot;Yes&quot;)% | gzip -9 >%aCurrent%.tar.gz</command>
+ <defaultshortcut>Ctrl+Shift+Z</defaultshortcut>
+ </action>
+ <action name="gzip_current" >
+ <title>gzip current</title>
+ <tooltip>gzip current file with maximum (9) compression, preserving original file. In case of directory, it is first tarred.</tooltip>
+ <category>Compression</category>
+ <command>if [ -d %aCurrent(&quot;Yes&quot;)% ]; then tar cf - %aCurrent(&quot;Yes&quot;)% | gzip -9 >%aCurrent(&quot;Yes&quot;)%.tar.gz; else cat %aCurrent(&quot;Yes&quot;)% | gzip -9 >%aCurrent(&quot;Yes&quot;)%.gz; fi</command>
+ <defaultshortcut>Ctrl+Shift+G</defaultshortcut>
+ </action>
+ <action name="ar_pack" >
+ <title>pack an ar archive (.a, .deb, ...)</title>
+ <command>sh -c 'A=%_Ask(&quot;Enter file name of the archive:&quot;, &quot;%oPath%%aCurrent(\&quot;Yes\&quot;)%.a&quot;, &quot;ar pack&quot;)% ; rm -f &quot;$A&quot;; ar -rc &quot;$A&quot; %aList(&quot;Selected&quot;, &quot; &quot;, &quot;Yes&quot;)% '</command>
+ </action>
+ <action name="ar_unpack" >
+ <title>Unpack an ar archive (.a, .deb, ...)</title>
+ <command>sh -c 'A=%_Ask(&quot;Enter the path, where the archive should be unpacked to:&quot;, &quot;%oPath%&quot;, &quot;ar unpack&quot;)% ; cd &quot;$A&quot;; for i in %aList(&quot;Selected&quot;)% ; do ar x &quot;$i&quot;; done '</command>
+ </action>
+ <action name="decrypt_with_kgpg" >
+ <title>Decrypt with kgpg</title>
+ <tooltip>Decrypt with kgpg</tooltip>
+ <icon>kgpg_show</icon>
+ <category>System</category>
+ <description same_as="tooltip" />
+ <command>kgpg %aCurrent%</command>
+ </action>
+ <action name="encrypt_with_kgpg" >
+ <title>Encrypt with kgpg</title>
+ <tooltip>Encrypt with kgpg</tooltip>
+ <icon>kgpg_key1</icon>
+ <category>System</category>
+ <description same_as="tooltip" />
+ <command>kgpg -e %aCurrent%</command>
+ </action>
+ <action name="sign_with_kgpg" >
+ <title>Sign with kgpg</title>
+ <tooltip>Sign with kgpg</tooltip>
+ <icon>kgpg_sign</icon>
+ <category>System</category>
+ <description same_as="tooltip" />
+ <command>kgpg -S %aCurrent%</command>
+ </action>
+ <action name="verify_sig_with_kpgp" >
+ <title>Verify signature with kgpg</title>
+ <tooltip>Verify signature with kgpg</tooltip>
+ <icon>kgpg_identity</icon>
+ <category>System</category>
+ <description same_as="tooltip" />
+ <command>kgpg -V %aCurrent%</command>
+ </action>
+</KrusaderUserActions>
diff --git a/krusader/x-ace.desktop b/krusader/x-ace.desktop
new file mode 100644
index 0000000..c8f5270
--- /dev/null
+++ b/krusader/x-ace.desktop
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Comment=ACE archive
+Hidden=false
+Icon=tgz
+MimeType=application/x-ace
+Patterns=*.ace;*.ACE
+Type=MimeType