summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am10
-rw-r--r--src/app/ActionMan/Makefile.am14
-rw-r--r--src/app/ActionMan/actionman.cpp60
-rw-r--r--src/app/ActionMan/actionman.h37
-rw-r--r--src/app/ActionMan/actionproperty.cpp470
-rw-r--r--src/app/ActionMan/actionproperty.h147
-rw-r--r--src/app/ActionMan/actionpropertybase.cpp463
-rw-r--r--src/app/ActionMan/actionpropertybase.ui1116
-rw-r--r--src/app/ActionMan/addplaceholderpopup.cpp582
-rw-r--r--src/app/ActionMan/addplaceholderpopup.h322
-rw-r--r--src/app/ActionMan/useractionlistview.cpp232
-rw-r--r--src/app/ActionMan/useractionlistview.h81
-rw-r--r--src/app/ActionMan/useractionpage.cpp317
-rw-r--r--src/app/ActionMan/useractionpage.h74
-rw-r--r--src/app/BookMan/Makefile.am11
-rw-r--r--src/app/BookMan/kraddbookmarkdlg.cpp117
-rw-r--r--src/app/BookMan/kraddbookmarkdlg.h40
-rw-r--r--src/app/BookMan/krbookmark.cpp92
-rw-r--r--src/app/BookMan/krbookmark.h46
-rw-r--r--src/app/BookMan/krbookmarkbutton.cpp38
-rw-r--r--src/app/BookMan/krbookmarkbutton.h24
-rw-r--r--src/app/BookMan/krbookmarkhandler.cpp576
-rw-r--r--src/app/BookMan/krbookmarkhandler.h64
-rw-r--r--src/app/CMakeL10n.txt3
-rw-r--r--src/app/Dialogs/Makefile.am22
-rw-r--r--src/app/Dialogs/checksumdlg.cpp603
-rw-r--r--src/app/Dialogs/checksumdlg.h54
-rw-r--r--src/app/Dialogs/krdialogs.cpp256
-rw-r--r--src/app/Dialogs/krdialogs.h116
-rw-r--r--src/app/Dialogs/krkeydialog.cpp157
-rw-r--r--src/app/Dialogs/krkeydialog.h38
-rw-r--r--src/app/Dialogs/krmaskchoice.cpp179
-rw-r--r--src/app/Dialogs/krmaskchoice.h77
-rw-r--r--src/app/Dialogs/krpleasewait.cpp153
-rw-r--r--src/app/Dialogs/krpleasewait.h84
-rw-r--r--src/app/Dialogs/krprogress.cpp270
-rw-r--r--src/app/Dialogs/krprogress.h87
-rw-r--r--src/app/Dialogs/krspecialwidgets.cpp239
-rw-r--r--src/app/Dialogs/krspecialwidgets.h129
-rw-r--r--src/app/Dialogs/krspwidgets.cpp316
-rw-r--r--src/app/Dialogs/krspwidgets.h110
-rw-r--r--src/app/Dialogs/krsqueezedtextlabel.cpp80
-rw-r--r--src/app/Dialogs/krsqueezedtextlabel.h45
-rw-r--r--src/app/Dialogs/kurllistrequester.cpp202
-rw-r--r--src/app/Dialogs/kurllistrequester.h77
-rw-r--r--src/app/Dialogs/newftpgui.cpp182
-rw-r--r--src/app/Dialogs/newftpgui.h55
-rw-r--r--src/app/Dialogs/packgui.cpp122
-rw-r--r--src/app/Dialogs/packgui.h54
-rw-r--r--src/app/Dialogs/packguibase.cpp468
-rw-r--r--src/app/Dialogs/packguibase.h110
-rw-r--r--src/app/Dialogs/percentalsplitter.cpp193
-rw-r--r--src/app/Dialogs/percentalsplitter.h59
-rw-r--r--src/app/Dialogs/popularurls.cpp307
-rw-r--r--src/app/Dialogs/popularurls.h86
-rw-r--r--src/app/DiskUsage/Makefile.am17
-rw-r--r--src/app/DiskUsage/diskusage.cpp1147
-rw-r--r--src/app/DiskUsage/diskusage.h206
-rw-r--r--src/app/DiskUsage/diskusagegui.cpp227
-rw-r--r--src/app/DiskUsage/diskusagegui.h90
-rw-r--r--src/app/DiskUsage/dufilelight.cpp236
-rw-r--r--src/app/DiskUsage/dufilelight.h81
-rw-r--r--src/app/DiskUsage/dulines.cpp522
-rw-r--r--src/app/DiskUsage/dulines.h79
-rw-r--r--src/app/DiskUsage/dulistview.cpp293
-rw-r--r--src/app/DiskUsage/dulistview.h145
-rw-r--r--src/app/DiskUsage/filelightParts/Config.cpp50
-rw-r--r--src/app/DiskUsage/filelightParts/Config.h37
-rw-r--r--src/app/DiskUsage/filelightParts/Makefile.am9
-rw-r--r--src/app/DiskUsage/filelightParts/debug.h14
-rw-r--r--src/app/DiskUsage/filelightParts/fileTree.cpp78
-rw-r--r--src/app/DiskUsage/filelightParts/fileTree.h299
-rw-r--r--src/app/DiskUsage/radialMap/Makefile.am13
-rw-r--r--src/app/DiskUsage/radialMap/builder.cpp139
-rw-r--r--src/app/DiskUsage/radialMap/builder.h37
-rw-r--r--src/app/DiskUsage/radialMap/labels.cpp342
-rw-r--r--src/app/DiskUsage/radialMap/map.cpp432
-rw-r--r--src/app/DiskUsage/radialMap/radialMap.h71
-rw-r--r--src/app/DiskUsage/radialMap/segmentTip.cpp163
-rw-r--r--src/app/DiskUsage/radialMap/segmentTip.h33
-rw-r--r--src/app/DiskUsage/radialMap/sincos.h17
-rw-r--r--src/app/DiskUsage/radialMap/widget.cpp199
-rw-r--r--src/app/DiskUsage/radialMap/widget.h111
-rw-r--r--src/app/DiskUsage/radialMap/widgetEvents.cpp241
-rw-r--r--src/app/Filter/Makefile.am11
-rw-r--r--src/app/Filter/advancedfilter.cpp711
-rw-r--r--src/app/Filter/advancedfilter.h116
-rw-r--r--src/app/Filter/filterbase.h51
-rw-r--r--src/app/Filter/filterdialog.cpp87
-rw-r--r--src/app/Filter/filterdialog.h61
-rw-r--r--src/app/Filter/filtertabs.cpp133
-rw-r--r--src/app/Filter/filtertabs.h81
-rw-r--r--src/app/Filter/generalfilter.cpp536
-rw-r--r--src/app/Filter/generalfilter.h107
-rw-r--r--src/app/GUI/Makefile.am18
-rw-r--r--src/app/GUI/dirhistorybutton.cpp82
-rw-r--r--src/app/GUI/dirhistorybutton.h57
-rw-r--r--src/app/GUI/dirhistoryqueue.cpp87
-rw-r--r--src/app/GUI/dirhistoryqueue.h48
-rw-r--r--src/app/GUI/kcmdline.cpp253
-rw-r--r--src/app/GUI/kcmdline.h101
-rw-r--r--src/app/GUI/kcmdmodebutton.cpp74
-rw-r--r--src/app/GUI/kcmdmodebutton.h53
-rw-r--r--src/app/GUI/kfnkeys.cpp133
-rw-r--r--src/app/GUI/kfnkeys.h55
-rw-r--r--src/app/GUI/krremoteencodingmenu.cpp207
-rw-r--r--src/app/GUI/krremoteencodingmenu.h68
-rw-r--r--src/app/GUI/krusaderstatus.cpp46
-rw-r--r--src/app/GUI/krusaderstatus.h57
-rw-r--r--src/app/GUI/mediabutton.cpp692
-rw-r--r--src/app/GUI/mediabutton.h107
-rw-r--r--src/app/GUI/profilemanager.cpp198
-rw-r--r--src/app/GUI/profilemanager.h70
-rw-r--r--src/app/GUI/syncbrowsebutton.cpp72
-rw-r--r--src/app/GUI/syncbrowsebutton.h67
-rw-r--r--src/app/KViewer/Makefile.am11
-rw-r--r--src/app/KViewer/diskusageviewer.cpp129
-rw-r--r--src/app/KViewer/diskusageviewer.h69
-rw-r--r--src/app/KViewer/kimagefilepreview.cpp136
-rw-r--r--src/app/KViewer/kimagefilepreview.h71
-rw-r--r--src/app/KViewer/krviewer.cpp702
-rw-r--r--src/app/KViewer/krviewer.h130
-rw-r--r--src/app/KViewer/panelviewer.cpp307
-rw-r--r--src/app/KViewer/panelviewer.h91
-rw-r--r--src/app/Konfigurator/Makefile.am23
-rw-r--r--src/app/Konfigurator/kgadvanced.cpp133
-rw-r--r--src/app/Konfigurator/kgadvanced.h45
-rw-r--r--src/app/Konfigurator/kgarchives.cpp157
-rw-r--r--src/app/Konfigurator/kgarchives.h55
-rw-r--r--src/app/Konfigurator/kgcolors.cpp633
-rw-r--r--src/app/Konfigurator/kgcolors.h140
-rw-r--r--src/app/Konfigurator/kgdependencies.cpp170
-rw-r--r--src/app/Konfigurator/kgdependencies.h59
-rw-r--r--src/app/Konfigurator/kggeneral.cpp214
-rw-r--r--src/app/Konfigurator/kggeneral.h55
-rw-r--r--src/app/Konfigurator/kglookfeel.cpp373
-rw-r--r--src/app/Konfigurator/kglookfeel.h70
-rw-r--r--src/app/Konfigurator/kgprotocols.cpp419
-rw-r--r--src/app/Konfigurator/kgprotocols.h87
-rw-r--r--src/app/Konfigurator/kgstartup.cpp117
-rw-r--r--src/app/Konfigurator/kgstartup.h53
-rw-r--r--src/app/Konfigurator/kguseractions.cpp106
-rw-r--r--src/app/Konfigurator/kguseractions.h52
-rw-r--r--src/app/Konfigurator/kgwelcome.cpp50
-rw-r--r--src/app/Konfigurator/kgwelcome.h45
-rw-r--r--src/app/Konfigurator/konfigurator.cpp220
-rw-r--r--src/app/Konfigurator/konfigurator.h82
-rw-r--r--src/app/Konfigurator/konfiguratoritems.cpp815
-rw-r--r--src/app/Konfigurator/konfiguratoritems.h428
-rw-r--r--src/app/Konfigurator/konfiguratorpage.cpp334
-rw-r--r--src/app/Konfigurator/konfiguratorpage.h523
-rw-r--r--src/app/Konfigurator/krresulttable.cpp380
-rw-r--r--src/app/Konfigurator/krresulttable.h142
-rw-r--r--src/app/Konfigurator/krresulttabledialog.cpp97
-rw-r--r--src/app/Konfigurator/krresulttabledialog.h84
-rw-r--r--src/app/Konfigurator/searchobject.cpp106
-rw-r--r--src/app/Konfigurator/searchobject.h131
-rw-r--r--src/app/KrJS/Makefile.am13
-rw-r--r--src/app/KrJS/krjs.cpp89
-rw-r--r--src/app/KrJS/krjs.h32
-rw-r--r--src/app/Locate/Makefile.am7
-rw-r--r--src/app/Locate/locate.cpp613
-rw-r--r--src/app/Locate/locate.h101
-rw-r--r--src/app/Makefile.am195
-rw-r--r--src/app/MountMan/Makefile.am10
-rw-r--r--src/app/MountMan/kdiskfreesp.cpp168
-rw-r--r--src/app/MountMan/kdiskfreesp.h89
-rw-r--r--src/app/MountMan/kmountman.cpp327
-rw-r--r--src/app/MountMan/kmountman.h103
-rw-r--r--src/app/MountMan/kmountmangui.cpp396
-rw-r--r--src/app/MountMan/kmountmangui.h199
-rw-r--r--src/app/Panel/Makefile.am29
-rw-r--r--src/app/Panel/krbriefview.cpp1462
-rw-r--r--src/app/Panel/krbriefview.h173
-rw-r--r--src/app/Panel/krbriefviewitem.cpp225
-rw-r--r--src/app/Panel/krbriefviewitem.h79
-rw-r--r--src/app/Panel/krcalcspacedialog.cpp187
-rw-r--r--src/app/Panel/krcalcspacedialog.h107
-rw-r--r--src/app/Panel/krcolorcache.cpp761
-rw-r--r--src/app/Panel/krcolorcache.h102
-rw-r--r--src/app/Panel/krdetailedview.cpp1588
-rw-r--r--src/app/Panel/krdetailedview.h181
-rw-r--r--src/app/Panel/krdetailedviewitem.cpp313
-rw-r--r--src/app/Panel/krdetailedviewitem.h73
-rw-r--r--src/app/Panel/krdrag.cpp103
-rw-r--r--src/app/Panel/krdrag.h63
-rw-r--r--src/app/Panel/krpopupmenu.cpp354
-rw-r--r--src/app/Panel/krpopupmenu.h78
-rw-r--r--src/app/Panel/krpreviewpopup.cpp68
-rw-r--r--src/app/Panel/krpreviewpopup.h49
-rw-r--r--src/app/Panel/krselectionmode.cpp61
-rw-r--r--src/app/Panel/krselectionmode.h97
-rw-r--r--src/app/Panel/krview.cpp332
-rw-r--r--src/app/Panel/krview.h248
-rw-r--r--src/app/Panel/krviewitem.cpp106
-rw-r--r--src/app/Panel/krviewitem.h76
-rw-r--r--src/app/Panel/listpanel.cpp1115
-rw-r--r--src/app/Panel/listpanel.h212
-rw-r--r--src/app/Panel/panelfunc.cpp1202
-rw-r--r--src/app/Panel/panelfunc.h106
-rw-r--r--src/app/Panel/panelpopup.cpp400
-rw-r--r--src/app/Panel/panelpopup.h74
-rw-r--r--src/app/Queue/Makefile.am10
-rw-r--r--src/app/Queue/queue.cpp22
-rw-r--r--src/app/Queue/queue.h33
-rw-r--r--src/app/Queue/queue_mgr.cpp31
-rw-r--r--src/app/Queue/queue_mgr.h26
-rw-r--r--src/app/Queue/queuewidget.cpp10
-rw-r--r--src/app/Queue/queuewidget.h15
-rw-r--r--src/app/RemoteMan/Makefile.am9
-rw-r--r--src/app/RemoteMan/remoteman.cpp385
-rw-r--r--src/app/RemoteMan/remoteman.h71
-rw-r--r--src/app/RemoteMan/remotemanbase.cpp331
-rw-r--r--src/app/RemoteMan/remotemanbase.h83
-rw-r--r--src/app/Search/Makefile.am9
-rw-r--r--src/app/Search/krsearchdialog.cpp628
-rw-r--r--src/app/Search/krsearchdialog.h184
-rw-r--r--src/app/Search/krsearchmod.cpp253
-rw-r--r--src/app/Search/krsearchmod.h86
-rw-r--r--src/app/Splitter/Makefile.am11
-rw-r--r--src/app/Splitter/combiner.cpp328
-rw-r--r--src/app/Splitter/combiner.h93
-rw-r--r--src/app/Splitter/crc32.cpp69
-rw-r--r--src/app/Splitter/crc32.h48
-rw-r--r--src/app/Splitter/splitter.cpp252
-rw-r--r--src/app/Splitter/splitter.h84
-rw-r--r--src/app/Splitter/splittergui.cpp213
-rw-r--r--src/app/Splitter/splittergui.h180
-rwxr-xr-xsrc/app/Synchronizer/Makefile.am13
-rw-r--r--src/app/Synchronizer/feedtolistboxdialog.cpp200
-rw-r--r--src/app/Synchronizer/feedtolistboxdialog.h66
-rw-r--r--src/app/Synchronizer/synchronizedialog.cpp199
-rw-r--r--src/app/Synchronizer/synchronizedialog.h92
-rw-r--r--src/app/Synchronizer/synchronizer.cpp1493
-rw-r--r--src/app/Synchronizer/synchronizer.h205
-rw-r--r--src/app/Synchronizer/synchronizerdirlist.cpp216
-rw-r--r--src/app/Synchronizer/synchronizerdirlist.h73
-rw-r--r--src/app/Synchronizer/synchronizerfileitem.h170
-rw-r--r--src/app/Synchronizer/synchronizergui.cpp2478
-rw-r--r--src/app/Synchronizer/synchronizergui.h225
-rw-r--r--src/app/Synchronizer/synchronizertask.cpp343
-rw-r--r--src/app/Synchronizer/synchronizertask.h170
-rw-r--r--src/app/UserAction/Makefile.am17
-rw-r--r--src/app/UserAction/expander.cpp1242
-rw-r--r--src/app/UserAction/expander.h245
-rw-r--r--src/app/UserAction/kraction.cpp586
-rw-r--r--src/app/UserAction/kraction.h170
-rw-r--r--src/app/UserAction/kractionbase.cpp77
-rw-r--r--src/app/UserAction/kractionbase.h97
-rw-r--r--src/app/UserAction/tstring.h116
-rw-r--r--src/app/UserAction/useraction.cpp212
-rw-r--r--src/app/UserAction/useraction.h145
-rw-r--r--src/app/UserAction/useractionpopupmenu.cpp26
-rw-r--r--src/app/UserAction/useractionpopupmenu.h25
-rw-r--r--src/app/UserMenu/Makefile.am7
-rw-r--r--src/app/UserMenu/usermenu.cpp85
-rw-r--r--src/app/UserMenu/usermenu.h46
-rw-r--r--src/app/VFS/Makefile.am19
-rw-r--r--src/app/VFS/arc_vfs.cpp866
-rw-r--r--src/app/VFS/arc_vfs.h131
-rw-r--r--src/app/VFS/ftp_vfs.cpp297
-rw-r--r--src/app/VFS/ftp_vfs.h80
-rw-r--r--src/app/VFS/krarchandler.cpp785
-rw-r--r--src/app/VFS/krarchandler.h151
-rw-r--r--src/app/VFS/krdirwatch.cpp124
-rw-r--r--src/app/VFS/krdirwatch.h80
-rw-r--r--src/app/VFS/krpermhandler.cpp355
-rw-r--r--src/app/VFS/krpermhandler.h89
-rw-r--r--src/app/VFS/krquery.cpp653
-rw-r--r--src/app/VFS/krquery.h209
-rw-r--r--src/app/VFS/krvfshandler.cpp71
-rw-r--r--src/app/VFS/krvfshandler.h40
-rw-r--r--src/app/VFS/normal_vfs.cpp437
-rw-r--r--src/app/VFS/normal_vfs.h93
-rw-r--r--src/app/VFS/preservingcopyjob.cpp319
-rw-r--r--src/app/VFS/preservingcopyjob.h85
-rw-r--r--src/app/VFS/temp_vfs.cpp136
-rw-r--r--src/app/VFS/temp_vfs.h60
-rw-r--r--src/app/VFS/vfile.cpp311
-rw-r--r--src/app/VFS/vfile.h167
-rw-r--r--src/app/VFS/vfs.cpp393
-rw-r--r--src/app/VFS/vfs.h187
-rw-r--r--src/app/VFS/virt_vfs.cpp341
-rw-r--r--src/app/VFS/virt_vfs.h77
-rw-r--r--src/app/VFS/virtualcopyjob.cpp316
-rw-r--r--src/app/VFS/virtualcopyjob.h126
-rw-r--r--src/app/alpa-yellow.colorbin0 -> 2468 bytes
-rw-r--r--src/app/bash.colorbin0 -> 2650 bytes
-rw-r--r--src/app/calc.js64
-rw-r--r--src/app/calc.ui267
-rw-r--r--src/app/cr16-app-krusader_blue.pngbin0 -> 827 bytes
-rw-r--r--src/app/cr16-app-krusader_red.pngbin0 -> 891 bytes
-rw-r--r--src/app/cr16-app-krusader_root.pngbin0 -> 168 bytes
-rw-r--r--src/app/cr16-app-krusader_user.pngbin0 -> 155 bytes
-rw-r--r--src/app/cr22-app-krusader_blue.pngbin0 -> 1264 bytes
-rw-r--r--src/app/cr22-app-krusader_red.pngbin0 -> 1395 bytes
-rw-r--r--src/app/cr22-app-krusader_root.pngbin0 -> 460 bytes
-rw-r--r--src/app/cr22-app-krusader_shield.pngbin0 -> 1254 bytes
-rw-r--r--src/app/cr22-app-krusader_user.pngbin0 -> 439 bytes
-rw-r--r--src/app/cr32-app-krusader_blue.pngbin0 -> 2248 bytes
-rw-r--r--src/app/cr32-app-krusader_red.pngbin0 -> 2509 bytes
-rw-r--r--src/app/cr32-app-krusader_root.pngbin0 -> 601 bytes
-rw-r--r--src/app/cr32-app-krusader_shield.pngbin0 -> 2090 bytes
-rw-r--r--src/app/cr32-app-krusader_user.pngbin0 -> 643 bytes
-rw-r--r--src/app/cr48-app-krusader_blue.pngbin0 -> 4124 bytes
-rw-r--r--src/app/cr48-app-krusader_red.pngbin0 -> 4375 bytes
-rw-r--r--src/app/cr48-app-krusader_root.pngbin0 -> 1657 bytes
-rw-r--r--src/app/cr48-app-krusader_shield.pngbin0 -> 3383 bytes
-rw-r--r--src/app/cr48-app-krusader_user.pngbin0 -> 1641 bytes
-rw-r--r--src/app/cr64-app-krusader_blue.pngbin0 -> 5908 bytes
-rw-r--r--src/app/cr64-app-krusader_red.pngbin0 -> 6299 bytes
-rw-r--r--src/app/cr64-app-krusader_root.pngbin0 -> 2130 bytes
-rw-r--r--src/app/cr64-app-krusader_shield.pngbin0 -> 4818 bytes
-rw-r--r--src/app/cr64-app-krusader_user.pngbin0 -> 2114 bytes
-rw-r--r--src/app/defaults.h308
-rw-r--r--src/app/dos_navigator.colorbin0 -> 2674 bytes
-rw-r--r--src/app/kicons.cpp377
-rw-r--r--src/app/kicons.h29
-rw-r--r--src/app/krservices.cpp216
-rw-r--r--src/app/krservices.h79
-rw-r--r--src/app/krslots.cpp944
-rw-r--r--src/app/krslots.h188
-rw-r--r--src/app/krusader.cpp1263
-rw-r--r--src/app/krusader.desktop86
-rw-r--r--src/app/krusader.h275
-rw-r--r--src/app/krusader_root-mode.desktop90
-rw-r--r--src/app/krusaderapp.h32
-rw-r--r--src/app/krusaderui.rc193
-rw-r--r--src/app/krusaderview.cpp415
-rw-r--r--src/app/krusaderview.h111
-rw-r--r--src/app/lo16-app-krusader.pngbin0 -> 815 bytes
-rw-r--r--src/app/lo32-app-krusader.pngbin0 -> 3532 bytes
-rw-r--r--src/app/lo32-app-krusader2.pngbin0 -> 529 bytes
-rw-r--r--src/app/main.cpp248
-rw-r--r--src/app/midnight_cmd_AHamann.colorbin0 -> 2732 bytes
-rw-r--r--src/app/midnight_commander.colorbin0 -> 1776 bytes
-rw-r--r--src/app/midnight_commander.keymapbin0 -> 1375 bytes
-rw-r--r--src/app/midnight_commander.keymap.info42
-rw-r--r--src/app/mount.js37
-rw-r--r--src/app/mount.ui195
-rw-r--r--src/app/panelmanager.cpp352
-rw-r--r--src/app/panelmanager.h79
-rw-r--r--src/app/paneltabbar.cpp262
-rw-r--r--src/app/paneltabbar.h100
-rw-r--r--src/app/recode.js202
-rw-r--r--src/app/recode.ui286
-rw-r--r--src/app/resources.h42
-rw-r--r--src/app/select_from_file.js13
-rw-r--r--src/app/splash.pngbin0 -> 74631 bytes
-rw-r--r--src/app/total_cmd_pleasent.colorbin0 -> 2652 bytes
-rw-r--r--src/app/total_commander.colorbin0 -> 1760 bytes
-rw-r--r--src/app/total_commander.keymap112
-rw-r--r--src/app/total_commander.keymap.info10
-rw-r--r--src/app/useraction_examples.xml406
-rw-r--r--src/app/x-ace.desktop7
-rw-r--r--src/iso/Makefile.am64
-rw-r--r--src/iso/iso.cpp525
-rw-r--r--src/iso/iso.h51
-rw-r--r--src/iso/iso.protocol12
-rw-r--r--src/iso/isoservice.desktop14
-rw-r--r--src/iso/kiso.cpp469
-rw-r--r--src/iso/kiso.h112
-rw-r--r--src/iso/kisodirectory.cpp31
-rw-r--r--src/iso/kisodirectory.h40
-rw-r--r--src/iso/kisofile.cpp53
-rw-r--r--src/iso/kisofile.h49
-rw-r--r--src/iso/libisofs/COPYING280
-rw-r--r--src/iso/libisofs/ChangeLog6
-rw-r--r--src/iso/libisofs/Makefile.am18
-rw-r--r--src/iso/libisofs/README24
-rw-r--r--src/iso/libisofs/bswap.h94
-rw-r--r--src/iso/libisofs/configure.in.in1
-rw-r--r--src/iso/libisofs/el_torito.h63
-rw-r--r--src/iso/libisofs/iso_fs.h219
-rw-r--r--src/iso/libisofs/isofs.c876
-rw-r--r--src/iso/libisofs/isofs.h161
-rw-r--r--src/iso/libisofs/rock.h127
-rw-r--r--src/iso/qfilehack.cpp40
-rw-r--r--src/iso/qfilehack.h38
-rw-r--r--src/iso/tdeio_isorc2
-rw-r--r--src/krArc/CMakeL10n.txt3
-rw-r--r--src/krArc/Makefile.am59
-rw-r--r--src/krArc/krarc.cpp1692
-rw-r--r--src/krArc/krarc.h144
-rw-r--r--src/krArc/krarc.protocol18
-rw-r--r--src/tar/Makefile.am22
-rw-r--r--src/tar/ar.protocol12
-rw-r--r--src/tar/ktartest.cpp201
-rw-r--r--src/tar/tar.cpp482
-rw-r--r--src/tar/tar.h48
-rw-r--r--src/tar/tar.protocol12
-rw-r--r--src/tar/zip.protocol12
-rw-r--r--src/tdeconf_update/Makefile.am3
-rw-r--r--src/tdeconf_update/krusader_tqt_selection.upd4
-rw-r--r--src/virt/CMakeL10n.txt3
-rw-r--r--src/virt/Makefile.am17
-rw-r--r--src/virt/virt.cpp305
-rw-r--r--src/virt/virt.h55
-rw-r--r--src/virt/virt.protocol19
399 files changed, 73354 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..b87c8d0
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,10 @@
+# the condition for this is found in configure.in.in
+if with_tar
+TARDIR = tar
+endif
+
+if with_iso
+ISODIR = iso
+endif
+
+SUBDIRS = app krArc $(ISODIR) tdeconf_update virt $(TARDIR)
diff --git a/src/app/ActionMan/Makefile.am b/src/app/ActionMan/Makefile.am
new file mode 100644
index 0000000..e71563a
--- /dev/null
+++ b/src/app/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/src/app/ActionMan/actionman.cpp b/src/app/ActionMan/actionman.cpp
new file mode 100644
index 0000000..080ece3
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <tdemessagebox.h>
+
+#include "useractionpage.h"
+#include "../krusader.h"
+#include "../UserAction/useraction.h"
+
+
+ActionMan::ActionMan( TQWidget * 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, TQ_SIGNAL( changed() ), TQ_SLOT( slotEnableApplyButton() ) );
+ connect( userActionPage, TQ_SIGNAL( applied() ), TQ_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/src/app/ActionMan/actionman.h b/src/app/ActionMan/actionman.h
new file mode 100644
index 0000000..29ab30b
--- /dev/null
+++ b/src/app/ActionMan/actionman.h
@@ -0,0 +1,37 @@
+//
+// 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 {
+TQ_OBJECT
+
+public:
+ ActionMan( TQWidget* parent=0 );
+ ~ActionMan();
+
+protected slots:
+ void slotClose();
+ void slotApply();
+ void slotEnableApplyButton();
+ void slotDisableApplyButton();
+
+private:
+ UserActionPage* userActionPage;
+};
+
+#endif // ifndef ACTIONMAN_H
diff --git a/src/app/ActionMan/actionproperty.cpp b/src/app/ActionMan/actionproperty.cpp
new file mode 100644
index 0000000..361f0a9
--- /dev/null
+++ b/src/app/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 <tqtoolbutton.h>
+#include <tqcheckbox.h>
+#include <tqradiobutton.h>
+#include <tqbuttongroup.h>
+#include <tdelocale.h>
+#include <tdefiledialog.h>
+#include <klineedit.h>
+#include <kdebug.h>
+#include <tdemessagebox.h>
+#include <kinputdialog.h>
+#include <kkeybutton.h>
+#include <kcombobox.h>
+#include <kicondialog.h>
+#include <ktextedit.h>
+#include <kiconloader.h>
+
+#define ICON(N) TDEGlobal::iconLoader()->loadIcon(N, TDEIcon::Small)
+
+ActionProperty::ActionProperty( TQWidget *parent, const char *name, KrAction *action )
+ : ActionPropertyBase( parent, name ), _modified(false)
+ {
+ if ( action ) {
+ _action = action;
+ updateGUI( _action );
+ }
+
+ ButtonAddPlaceholder->setPixmap( ICON("add") );
+ ButtonAddStartpath->setPixmap( ICON("document-open") );
+
+ // fill with all existing categories
+ cbCategory->insertStringList( krUserAction->allCategories() );
+
+ connect( ButtonAddPlaceholder, TQ_SIGNAL( clicked() ), this, TQ_SLOT( addPlaceholder() ) );
+ connect( ButtonAddStartpath, TQ_SIGNAL( clicked() ), this, TQ_SLOT( addStartpath() ) );
+ connect( ButtonNewProtocol, TQ_SIGNAL( clicked() ), this, TQ_SLOT( newProtocol() ) );
+ connect( ButtonEditProtocol, TQ_SIGNAL( clicked() ), this, TQ_SLOT( editProtocol() ) );
+ connect( ButtonRemoveProtocol, TQ_SIGNAL( clicked() ), this, TQ_SLOT( removeProtocol() ) );
+ connect( ButtonAddPath, TQ_SIGNAL( clicked() ), this, TQ_SLOT( addPath() ) );
+ connect( ButtonEditPath, TQ_SIGNAL( clicked() ), this, TQ_SLOT( editPath() ) );
+ connect( ButtonRemovePath, TQ_SIGNAL( clicked() ), this, TQ_SLOT( removePath() ) );
+ connect( ButtonAddMime, TQ_SIGNAL( clicked() ), this, TQ_SLOT( addMime() ) );
+ connect( ButtonEditMime, TQ_SIGNAL( clicked() ), this, TQ_SLOT( editMime() ) );
+ connect( ButtonRemoveMime, TQ_SIGNAL( clicked() ), this, TQ_SLOT( removeMime() ) );
+ connect( ButtonNewFile, TQ_SIGNAL( clicked() ), this, TQ_SLOT( newFile() ) );
+ connect( ButtonEditFile, TQ_SIGNAL( clicked() ), this, TQ_SLOT( editFile() ) );
+ connect( ButtonRemoveFile, TQ_SIGNAL( clicked() ), this, TQ_SLOT( removeFile() ) );
+ connect( KeyButtonShortcut, TQ_SIGNAL( capturedShortcut(const TDEShortcut&) ), this, TQ_SLOT( changedShortcut(const TDEShortcut&) ) );
+ // track modifications:
+ connect( leDistinctName, TQ_SIGNAL( textChanged(const TQString&) ), TQ_SLOT( setModified() ) );
+ connect( leTitle, TQ_SIGNAL( textChanged(const TQString&) ), TQ_SLOT( setModified() ) );
+ connect( ButtonIcon, TQ_SIGNAL( iconChanged(TQString) ), TQ_SLOT( setModified() ) );
+ connect( cbCategory, TQ_SIGNAL( textChanged(const TQString&) ), TQ_SLOT( setModified() ) );
+ connect( leTooltip, TQ_SIGNAL( textChanged(const TQString&) ), TQ_SLOT( setModified() ) );
+ connect( textDescription, TQ_SIGNAL( textChanged() ), TQ_SLOT( setModified() ) );
+ connect( leDistinctName, TQ_SIGNAL( textChanged(const TQString&) ), TQ_SLOT( setModified() ) );
+ connect( leCommandline, TQ_SIGNAL( textChanged(const TQString&) ), TQ_SLOT( setModified() ) );
+ connect( leStartpath, TQ_SIGNAL( textChanged(const TQString&) ), TQ_SLOT( setModified() ) );
+ connect( bgExecType, TQ_SIGNAL( clicked(int) ), TQ_SLOT( setModified() ) );
+ connect( bgAccept, TQ_SIGNAL( clicked(int) ), TQ_SLOT( setModified() ) );
+ connect( KeyButtonShortcut, TQ_SIGNAL( capturedShortcut(const TDEShortcut&) ), TQ_SLOT( setModified() ) );
+ connect( leDifferentUser, TQ_SIGNAL( textChanged(const TQString&) ), TQ_SLOT( setModified() ) );
+ connect( chkDifferentUser, TQ_SIGNAL( clicked() ), TQ_SLOT( setModified() ) );
+ connect( chkConfirmExecution, TQ_SIGNAL( clicked() ), TQ_SLOT( setModified() ) );
+ // The modified-state of the ShowOnly-lists is tracked in the access-functions below
+}
+
+ActionProperty::~ActionProperty() {
+}
+
+void ActionProperty::changedShortcut( const TDEShortcut& 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( TDEShortcut(), 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() );
+
+ TQListBoxItem* lbi = lbShowonlyProtocol->firstItem();
+ TQStringList list;
+ while ( lbi ) {
+ list << lbi->text();
+ lbi = lbi->next();
+ }
+ _action->setShowonlyProtocol( list );
+
+ lbi = lbShowonlyPath->firstItem();
+ list = TQStringList();
+ while ( lbi ) {
+ list << lbi->text();
+ lbi = lbi->next();
+ }
+ _action->setShowonlyPath( list );
+
+ lbi = lbShowonlyMime->firstItem();
+ list = TQStringList();
+ while ( lbi ) {
+ list << lbi->text();
+ lbi = lbi->next();
+ }
+ _action->setShowonlyMime( list );
+
+ lbi = lbShowonlyFile->firstItem();
+ list = TQStringList();
+ 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 );
+ TQString exp = popup.getPlaceholder( mapToGlobal(
+ TQPoint(
+ ButtonAddPlaceholder->pos().x() + ButtonAddPlaceholder->width()+6, // 6 is the default margin
+ ButtonAddPlaceholder->pos().y()
+ )
+ ) );
+ leCommandline->insert( exp );
+}
+
+
+void ActionProperty::addStartpath() {
+ TQString folder = KFileDialog::getExistingDirectory(TQString(), this);
+ if (folder != TQString()) {
+ leStartpath->setText( folder );
+ }
+}
+
+
+void ActionProperty::newProtocol() {
+ bool ok;
+ TQString text = KInputDialog::getText(
+ i18n( "New protocol" ),
+ i18n( "Set a protocol:" ),
+ lbShowonlyProtocol->currentText(),
+ &ok, this );
+ if ( ok && !text.isEmpty() ) {
+ lbShowonlyProtocol->insertStringList( TQStringList::split( ";", text ) );
+ setModified();
+ }
+}
+
+void ActionProperty::editProtocol() {
+ if (lbShowonlyProtocol->currentItem() == -1)
+ return;
+
+ bool ok;
+ TQString 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() {
+ TQString folder = KFileDialog::getExistingDirectory(TQString(), this);
+ if (folder != TQString()) {
+ lbShowonlyPath->insertItem( folder );
+ setModified();
+ }
+}
+
+void ActionProperty::editPath() {
+ if (lbShowonlyPath->currentItem() == -1)
+ return;
+
+ bool ok;
+ TQString 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;
+ TQString text = KInputDialog::getText(
+ i18n( "New mime-type" ),
+ i18n( "Set a mime-type:" ),
+ lbShowonlyMime->currentText(),
+ &ok, this );
+ if ( ok && !text.isEmpty() ) {
+ lbShowonlyMime->insertStringList( TQStringList::split( ";", text ) );
+ setModified();
+ }
+}
+
+void ActionProperty::editMime() {
+ if (lbShowonlyMime->currentItem() == -1)
+ return;
+
+ bool ok;
+ TQString 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;
+ TQString text = KInputDialog::getText(
+ i18n( "New filename" ),
+ i18n( "Set a filename:" ),
+ lbShowonlyFile->currentText(),
+ &ok, this );
+ if ( ok && !text.isEmpty() ) {
+ lbShowonlyFile->insertStringList( TQStringList::split( ";", text ) );
+ setModified();
+ }
+}
+
+void ActionProperty::editFile() {
+ if (lbShowonlyFile->currentItem() == -1)
+ return;
+
+ bool ok;
+ TQString 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/src/app/ActionMan/actionproperty.h b/src/app/ActionMan/actionproperty.h
new file mode 100644
index 0000000..dfdc5a1
--- /dev/null
+++ b/src/app/ActionMan/actionproperty.h
@@ -0,0 +1,147 @@
+//
+// 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 TDEShortcut;
+
+/**
+ * Use this widget where ever you need to manipulate a UserAction
+ * @author Jonas Bähr (http://www.jonas-baehr.de)
+ */
+class ActionProperty : public ActionPropertyBase {
+ TQ_OBJECT
+
+public:
+ ActionProperty( TQWidget *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 TDEShortcut& shortcut);
+};
+
+#endif
diff --git a/src/app/ActionMan/actionpropertybase.cpp b/src/app/ActionMan/actionpropertybase.cpp
new file mode 100644
index 0000000..7facfa5
--- /dev/null
+++ b/src/app/ActionMan/actionpropertybase.cpp
@@ -0,0 +1,463 @@
+#include <kdialog.h>
+#include <tdelocale.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 <tqvariant.h>
+#include <tqpushbutton.h>
+#include <tqtabwidget.h>
+#include <tqtoolbutton.h>
+#include <tqlabel.h>
+#include <tqbuttongroup.h>
+#include <tqradiobutton.h>
+#include <klineedit.h>
+#include <kcombobox.h>
+#include <kicondialog.h>
+#include <ktextedit.h>
+#include <kkeybutton.h>
+#include <tqcheckbox.h>
+#include <tqgroupbox.h>
+#include <tdelistbox.h>
+#include <tqlayout.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+#include "klineedit.h"
+#include "kcombobox.h"
+#include "kicondialog.h"
+#include "ktextedit.h"
+#include "kkeybutton.h"
+#include "tdelistbox.h"
+
+/*
+ * Constructs a ActionPropertyBase as a child of 'parent', with the
+ * name 'name' and widget flags set to 'f'.
+ */
+ActionPropertyBase::ActionPropertyBase( TQWidget* parent, const char* name, WFlags fl )
+ : TQWidget( parent, name, fl )
+{
+ if ( !name )
+ setName( "ActionPropertyBase" );
+ ActionPropertyBaseLayout = new TQGridLayout( this, 1, 1, 0, 0, "ActionPropertyBaseLayout");
+
+ tabWidget3 = new TQTabWidget( this, "tabWidget3" );
+
+ tab = new TQWidget( tabWidget3, "tab" );
+ tabLayout = new TQGridLayout( tab, 1, 1, 11, 6, "tabLayout");
+
+ ButtonAddStartpath = new TQToolButton( tab, "ButtonAddStartpath" );
+
+ tabLayout->addWidget( ButtonAddStartpath, 8, 3 );
+
+ LabelDescription = new TQLabel( tab, "LabelDescription" );
+ LabelDescription->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)1, 0, 0, LabelDescription->sizePolicy().hasHeightForWidth() ) );
+
+ tabLayout->addWidget( LabelDescription, 4, 0 );
+
+ bgAccept = new TQButtonGroup( tab, "bgAccept" );
+ bgAccept->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)5, (TQSizePolicy::SizeType)1, 0, 0, bgAccept->sizePolicy().hasHeightForWidth() ) );
+ bgAccept->setColumnLayout(0, TQt::Vertical );
+ bgAccept->layout()->setSpacing( 6 );
+ bgAccept->layout()->setMargin( 11 );
+ bgAcceptLayout = new TQGridLayout( bgAccept->layout() );
+ bgAcceptLayout->setAlignment( TQt::AlignTop );
+
+ radioLocal = new TQRadioButton( bgAccept, "radioLocal" );
+ radioLocal->setChecked( true );
+
+ bgAcceptLayout->addWidget( radioLocal, 0, 0 );
+
+ radioUrl = new TQRadioButton( 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 TQLabel( tab, "LabelTitle" );
+ LabelTitle->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, LabelTitle->sizePolicy().hasHeightForWidth() ) );
+
+ tabLayout->addWidget( LabelTitle, 2, 0 );
+
+ layout3 = new TQHBoxLayout( 0, 0, 6, "layout3");
+
+ layout2 = new TQVBoxLayout( 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 TDEIconButton( tab, "ButtonIcon" );
+ ButtonIcon->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)0, 0, 0, ButtonIcon->sizePolicy().hasHeightForWidth() ) );
+ ButtonIcon->setMinimumSize( TQSize( 50, 50 ) );
+ ButtonIcon->setMaximumSize( TQSize( 50, 50 ) );
+ layout3->addWidget( ButtonIcon );
+
+ tabLayout->addMultiCellLayout( layout3, 0, 1, 1, 3 );
+
+ LabelDistinctName = new TQLabel( tab, "LabelDistinctName" );
+ LabelDistinctName->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, LabelDistinctName->sizePolicy().hasHeightForWidth() ) );
+
+ tabLayout->addWidget( LabelDistinctName, 0, 0 );
+
+ LabelCommandline = new TQLabel( tab, "LabelCommandline" );
+ LabelCommandline->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::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 TQLabel( tab, "LabelTooltip" );
+ LabelTooltip->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::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 TQLabel( tab, "LabelCategory" );
+ LabelCategory->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, LabelCategory->sizePolicy().hasHeightForWidth() ) );
+
+ tabLayout->addWidget( LabelCategory, 1, 0 );
+
+ ButtonAddPlaceholder = new TQToolButton( tab, "ButtonAddPlaceholder" );
+ ButtonAddPlaceholder->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)0, 0, 0, ButtonAddPlaceholder->sizePolicy().hasHeightForWidth() ) );
+ ButtonAddPlaceholder->setMinimumSize( TQSize( 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 TQLabel( tab, "LabelStartpath" );
+ LabelStartpath->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)0, 0, 0, LabelStartpath->sizePolicy().hasHeightForWidth() ) );
+
+ tabLayout->addWidget( LabelStartpath, 8, 0 );
+ spacer = new TQSpacerItem( 80, 19, TQSizePolicy::Minimum, TQSizePolicy::Expanding );
+ tabLayout->addItem( spacer, 6, 0 );
+
+ layout4 = new TQHBoxLayout( 0, 0, 6, "layout4");
+
+ LabelShortcut = new TQLabel( tab, "LabelShortcut" );
+ layout4->addWidget( LabelShortcut );
+ spacer6_2 = new TQSpacerItem( 161, 21, TQSizePolicy::Expanding, TQSizePolicy::Minimum );
+ layout4->addItem( spacer6_2 );
+
+ KeyButtonShortcut = new KKeyButton( tab, "KeyButtonShortcut" );
+ layout4->addWidget( KeyButtonShortcut );
+
+ tabLayout->addMultiCellLayout( layout4, 10, 10, 2, 3 );
+
+ bgExecType = new TQButtonGroup( tab, "bgExecType" );
+ bgExecType->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)5, (TQSizePolicy::SizeType)1, 0, 0, bgExecType->sizePolicy().hasHeightForWidth() ) );
+ bgExecType->setColumnLayout(0, TQt::Vertical );
+ bgExecType->layout()->setSpacing( 6 );
+ bgExecType->layout()->setMargin( 11 );
+ bgExecTypeLayout = new TQGridLayout( bgExecType->layout() );
+ bgExecTypeLayout->setAlignment( TQt::AlignTop );
+
+ radioCollectOutput = new TQRadioButton( bgExecType, "radioCollectOutput" );
+
+ bgExecTypeLayout->addWidget( radioCollectOutput, 2, 0 );
+
+ chkSeparateStdError = new TQCheckBox( bgExecType, "chkSeparateStdError" );
+ chkSeparateStdError->setEnabled( false );
+
+ bgExecTypeLayout->addWidget( chkSeparateStdError, 3, 0 );
+
+ radioNormal = new TQRadioButton( bgExecType, "radioNormal" );
+ radioNormal->setChecked( true );
+
+ bgExecTypeLayout->addWidget( radioNormal, 0, 0 );
+
+ radioTerminal = new TQRadioButton( bgExecType, "radioTerminal" );
+
+ bgExecTypeLayout->addWidget( radioTerminal, 1, 0 );
+
+ tabLayout->addMultiCellWidget( bgExecType, 9, 10, 0, 1 );
+ tabWidget3->insertTab( tab, TQString::fromLatin1("") );
+
+ tab_2 = new TQWidget( tabWidget3, "tab_2" );
+ tabLayout_2 = new TQGridLayout( tab_2, 1, 1, 11, 6, "tabLayout_2");
+
+ gbShowonly = new TQGroupBox( tab_2, "gbShowonly" );
+ gbShowonly->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)7, (TQSizePolicy::SizeType)7, 0, 0, gbShowonly->sizePolicy().hasHeightForWidth() ) );
+ gbShowonly->setColumnLayout(0, TQt::Vertical );
+ gbShowonly->layout()->setSpacing( 6 );
+ gbShowonly->layout()->setMargin( 11 );
+ gbShowonlyLayout = new TQGridLayout( gbShowonly->layout() );
+ gbShowonlyLayout->setAlignment( TQt::AlignTop );
+
+ tabShowonly = new TQTabWidget( gbShowonly, "tabShowonly" );
+ tabShowonly->setTabPosition( TQTabWidget::Top );
+ tabShowonly->setTabShape( TQTabWidget::Triangular );
+
+ TabPage = new TQWidget( tabShowonly, "TabPage" );
+ TabPageLayout = new TQGridLayout( TabPage, 1, 1, 11, 6, "TabPageLayout");
+
+ ButtonNewProtocol = new TQToolButton( TabPage, "ButtonNewProtocol" );
+ ButtonNewProtocol->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, ButtonNewProtocol->sizePolicy().hasHeightForWidth() ) );
+ ButtonNewProtocol->setMinimumSize( TQSize( 0, 0 ) );
+ ButtonNewProtocol->setMaximumSize( TQSize( 32767, 32767 ) );
+
+ TabPageLayout->addWidget( ButtonNewProtocol, 0, 1 );
+
+ ButtonEditProtocol = new TQToolButton( TabPage, "ButtonEditProtocol" );
+ ButtonEditProtocol->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, ButtonEditProtocol->sizePolicy().hasHeightForWidth() ) );
+ ButtonEditProtocol->setMinimumSize( TQSize( 0, 0 ) );
+ ButtonEditProtocol->setMaximumSize( TQSize( 32767, 32767 ) );
+
+ TabPageLayout->addWidget( ButtonEditProtocol, 1, 1 );
+ spacer6_3 = new TQSpacerItem( 21, 58, TQSizePolicy::Minimum, TQSizePolicy::Expanding );
+ TabPageLayout->addItem( spacer6_3, 3, 1 );
+
+ ButtonRemoveProtocol = new TQToolButton( TabPage, "ButtonRemoveProtocol" );
+ ButtonRemoveProtocol->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, ButtonRemoveProtocol->sizePolicy().hasHeightForWidth() ) );
+ ButtonRemoveProtocol->setMinimumSize( TQSize( 0, 0 ) );
+ ButtonRemoveProtocol->setMaximumSize( TQSize( 32767, 32767 ) );
+
+ TabPageLayout->addWidget( ButtonRemoveProtocol, 2, 1 );
+
+ lbShowonlyProtocol = new TDEListBox( TabPage, "lbShowonlyProtocol" );
+
+ TabPageLayout->addMultiCellWidget( lbShowonlyProtocol, 0, 3, 0, 0 );
+ tabShowonly->insertTab( TabPage, TQString::fromLatin1("") );
+
+ tab_3 = new TQWidget( tabShowonly, "tab_3" );
+ tabLayout_3 = new TQGridLayout( tab_3, 1, 1, 11, 6, "tabLayout_3");
+
+ lbShowonlyPath = new TDEListBox( tab_3, "lbShowonlyPath" );
+
+ tabLayout_3->addMultiCellWidget( lbShowonlyPath, 0, 3, 0, 0 );
+
+ ButtonAddPath = new TQToolButton( tab_3, "ButtonAddPath" );
+ ButtonAddPath->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, ButtonAddPath->sizePolicy().hasHeightForWidth() ) );
+ ButtonAddPath->setMinimumSize( TQSize( 0, 0 ) );
+ ButtonAddPath->setMaximumSize( TQSize( 32767, 32767 ) );
+
+ tabLayout_3->addWidget( ButtonAddPath, 0, 1 );
+
+ ButtonEditPath = new TQToolButton( tab_3, "ButtonEditPath" );
+ ButtonEditPath->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, ButtonEditPath->sizePolicy().hasHeightForWidth() ) );
+ ButtonEditPath->setMinimumSize( TQSize( 0, 0 ) );
+ ButtonEditPath->setMaximumSize( TQSize( 32767, 32767 ) );
+
+ tabLayout_3->addWidget( ButtonEditPath, 1, 1 );
+
+ ButtonRemovePath = new TQToolButton( tab_3, "ButtonRemovePath" );
+ ButtonRemovePath->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, ButtonRemovePath->sizePolicy().hasHeightForWidth() ) );
+ ButtonRemovePath->setMinimumSize( TQSize( 0, 0 ) );
+ ButtonRemovePath->setMaximumSize( TQSize( 32767, 32767 ) );
+
+ tabLayout_3->addWidget( ButtonRemovePath, 2, 1 );
+ spacer4 = new TQSpacerItem( 21, 61, TQSizePolicy::Minimum, TQSizePolicy::Expanding );
+ tabLayout_3->addItem( spacer4, 3, 1 );
+ tabShowonly->insertTab( tab_3, TQString::fromLatin1("") );
+
+ tab_4 = new TQWidget( tabShowonly, "tab_4" );
+ tabLayout_4 = new TQGridLayout( tab_4, 1, 1, 11, 6, "tabLayout_4");
+
+ lbShowonlyMime = new TDEListBox( tab_4, "lbShowonlyMime" );
+
+ tabLayout_4->addMultiCellWidget( lbShowonlyMime, 0, 3, 0, 0 );
+
+ ButtonAddMime = new TQToolButton( tab_4, "ButtonAddMime" );
+ ButtonAddMime->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, ButtonAddMime->sizePolicy().hasHeightForWidth() ) );
+ ButtonAddMime->setMinimumSize( TQSize( 0, 0 ) );
+ ButtonAddMime->setMaximumSize( TQSize( 32767, 32767 ) );
+
+ tabLayout_4->addWidget( ButtonAddMime, 0, 1 );
+
+ ButtonEditMime = new TQToolButton( tab_4, "ButtonEditMime" );
+ ButtonEditMime->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, ButtonEditMime->sizePolicy().hasHeightForWidth() ) );
+ ButtonEditMime->setMinimumSize( TQSize( 0, 0 ) );
+ ButtonEditMime->setMaximumSize( TQSize( 32767, 32767 ) );
+
+ tabLayout_4->addWidget( ButtonEditMime, 1, 1 );
+
+ ButtonRemoveMime = new TQToolButton( tab_4, "ButtonRemoveMime" );
+ ButtonRemoveMime->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, ButtonRemoveMime->sizePolicy().hasHeightForWidth() ) );
+ ButtonRemoveMime->setMinimumSize( TQSize( 0, 0 ) );
+ ButtonRemoveMime->setMaximumSize( TQSize( 32767, 32767 ) );
+
+ tabLayout_4->addWidget( ButtonRemoveMime, 2, 1 );
+ spacer5 = new TQSpacerItem( 21, 41, TQSizePolicy::Minimum, TQSizePolicy::Expanding );
+ tabLayout_4->addItem( spacer5, 3, 1 );
+ tabShowonly->insertTab( tab_4, TQString::fromLatin1("") );
+
+ TabPage_2 = new TQWidget( tabShowonly, "TabPage_2" );
+ TabPageLayout_2 = new TQGridLayout( TabPage_2, 1, 1, 11, 6, "TabPageLayout_2");
+
+ lbShowonlyFile = new TDEListBox( TabPage_2, "lbShowonlyFile" );
+
+ TabPageLayout_2->addMultiCellWidget( lbShowonlyFile, 0, 3, 0, 0 );
+
+ ButtonNewFile = new TQToolButton( TabPage_2, "ButtonNewFile" );
+ ButtonNewFile->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, ButtonNewFile->sizePolicy().hasHeightForWidth() ) );
+ ButtonNewFile->setMinimumSize( TQSize( 0, 0 ) );
+ ButtonNewFile->setMaximumSize( TQSize( 32767, 32767 ) );
+
+ TabPageLayout_2->addWidget( ButtonNewFile, 0, 1 );
+
+ ButtonEditFile = new TQToolButton( TabPage_2, "ButtonEditFile" );
+ ButtonEditFile->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, ButtonEditFile->sizePolicy().hasHeightForWidth() ) );
+ ButtonEditFile->setMinimumSize( TQSize( 0, 0 ) );
+ ButtonEditFile->setMaximumSize( TQSize( 32767, 32767 ) );
+
+ TabPageLayout_2->addWidget( ButtonEditFile, 1, 1 );
+
+ ButtonRemoveFile = new TQToolButton( TabPage_2, "ButtonRemoveFile" );
+ ButtonRemoveFile->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, ButtonRemoveFile->sizePolicy().hasHeightForWidth() ) );
+ ButtonRemoveFile->setMinimumSize( TQSize( 0, 0 ) );
+ ButtonRemoveFile->setMaximumSize( TQSize( 32767, 32767 ) );
+
+ TabPageLayout_2->addWidget( ButtonRemoveFile, 2, 1 );
+ spacer6 = new TQSpacerItem( 21, 41, TQSizePolicy::Minimum, TQSizePolicy::Expanding );
+ TabPageLayout_2->addItem( spacer6, 3, 1 );
+ tabShowonly->insertTab( TabPage_2, TQString::fromLatin1("") );
+
+ gbShowonlyLayout->addWidget( tabShowonly, 0, 0 );
+
+ tabLayout_2->addMultiCellWidget( gbShowonly, 0, 0, 0, 1 );
+
+ chkConfirmExecution = new TQCheckBox( tab_2, "chkConfirmExecution" );
+
+ tabLayout_2->addMultiCellWidget( chkConfirmExecution, 1, 1, 0, 1 );
+
+ chkDifferentUser = new TQCheckBox( 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 TQSpacerItem( 161, 102, TQSizePolicy::Minimum, TQSizePolicy::Expanding );
+ tabLayout_2->addMultiCell( spacer3, 3, 3, 0, 1 );
+ tabWidget3->insertTab( tab_2, TQString::fromLatin1("") );
+
+ ActionPropertyBaseLayout->addWidget( tabWidget3, 0, 0 );
+ languageChange();
+ resize( TQSize(485, 470).expandedTo(minimumSizeHint()) );
+ clearWState( WState_Polished );
+
+ // signals and slots connections
+ connect( radioCollectOutput, TQ_SIGNAL( toggled(bool) ), chkSeparateStdError, TQ_SLOT( setEnabled(bool) ) );
+ connect( chkDifferentUser, TQ_SIGNAL( toggled(bool) ), leDifferentUser, TQ_SLOT( setEnabled(bool) ) );
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+ActionPropertyBase::~ActionPropertyBase()
+{
+ // no need to delete child widgets, TQt 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:" ) );
+ TQWhatsThis::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)" ) );
+ TQWhatsThis::add( radioLocal, tr2i18n( "Substitute the <b>Placeholders</b> with local filenames." ) );
+ radioUrl->setText( tr2i18n( "URL's (remote and local)" ) );
+ TQWhatsThis::add( radioUrl, tr2i18n( "Substitute the <b>Placeholders</b> with valid URL's." ) );
+ TQWhatsThis::add( leTitle, tr2i18n( "The title displayed in the <b>Usermenu</b>." ) );
+ LabelTitle->setText( tr2i18n( "Title:" ) );
+ TQWhatsThis::add( LabelTitle, tr2i18n( "The title displayed in the <b>Usermenu</b>." ) );
+ TQWhatsThis::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." ) );
+ TQWhatsThis::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" ) );
+ TQWhatsThis::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:" ) );
+ TQWhatsThis::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:" ) );
+ TQWhatsThis::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>" ) );
+ TQWhatsThis::add( leTooltip, tr2i18n( "The <i>Tooltip</i> is shown when the mouse cursor is hold over an entry of the <b>Useraction Toolbar</b>." ) );
+ TQWhatsThis::add( leStartpath, tr2i18n( "The <i>Workdir</i> defines in which directory the <i>Command</i> will be executed." ) );
+ LabelTooltip->setText( tr2i18n( "Tooltip:" ) );
+ TQWhatsThis::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( TQString() );
+ TQWhatsThis::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:" ) );
+ TQWhatsThis::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" ) );
+ TQWhatsThis::add( ButtonAddPlaceholder, tr2i18n( "Add <b>Placeholders</b> for the selected files in the panel." ) );
+ TQWhatsThis::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:" ) );
+ TQWhatsThis::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" ) );
+ TQWhatsThis::add( KeyButtonShortcut, tr2i18n( "Set a default keyboard shortcut." ) );
+ bgExecType->setTitle( tr2i18n( "Execution mode" ) );
+ radioCollectOutput->setText( tr2i18n( "Collect output" ) );
+ TQWhatsThis::add( radioCollectOutput, tr2i18n( "Collect the output of the executed program." ) );
+ chkSeparateStdError->setText( tr2i18n( "Separate standard error" ) );
+ TQWhatsThis::add( chkSeparateStdError, tr2i18n( "Separate standard out and standard error in the output collection." ) );
+ radioNormal->setText( tr2i18n( "Normal" ) );
+ radioTerminal->setText( tr2i18n( "Run in terminal" ) );
+ TQWhatsThis::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" ) );
+ TQWhatsThis::add( lbShowonlyProtocol, tr2i18n( "Show the <b>Useraction</b> only for the values defined here." ) );
+ tabShowonly->changeTab( TabPage, tr2i18n( "Protocol" ) );
+ TQWhatsThis::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" ) );
+ TQWhatsThis::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" ) );
+ TQWhatsThis::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" ) );
+ TQWhatsThis::add( chkConfirmExecution, tr2i18n( "Allows to tweak the <i>Command</i> before it is executed." ) );
+ chkDifferentUser->setText( tr2i18n( "Run as different user:" ) );
+ TQWhatsThis::add( chkDifferentUser, tr2i18n( "Execute the <i>Command</i> under a different user-id." ) );
+ TQWhatsThis::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/src/app/ActionMan/actionpropertybase.ui b/src/app/ActionMan/actionpropertybase.ui
new file mode 100644
index 0000000..42cd052
--- /dev/null
+++ b/src/app/ActionMan/actionpropertybase.ui
@@ -0,0 +1,1116 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>ActionPropertyBase</class>
+<widget class="TQWidget">
+ <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="TQTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tabWidget3</cstring>
+ </property>
+ <widget class="TQWidget">
+ <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="TQToolButton" row="8" column="3">
+ <property name="name">
+ <cstring>ButtonAddStartpath</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" 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="TQButtonGroup" 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="TQRadioButton" 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="TQRadioButton" 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="TQLabel" 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="TQLayoutWidget" 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="TQLayoutWidget">
+ <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="TDEIconButton">
+ <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="TQLabel" 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="TQLabel" 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="TQLabel" 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="TQLabel" 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="TQToolButton" 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="TQLabel" 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="TQLayoutWidget" 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="TQLabel">
+ <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="TQButtonGroup" 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="TQRadioButton" 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="TQCheckBox" 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="TQRadioButton" 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="TQRadioButton" 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="TQWidget">
+ <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="TQGroupBox" 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="TQTabWidget" 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="TQWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>Protocol</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQToolButton" 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="TQToolButton" 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="TQToolButton" 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="TDEListBox" 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="TQWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Path</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TDEListBox" 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="TQToolButton" 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="TQToolButton" 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="TQToolButton" 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="TQWidget">
+ <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="TDEListBox" 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="TQToolButton" 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="TQToolButton" 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="TQToolButton" 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="TQWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>Filename</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TDEListBox" 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="TQToolButton" 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="TQToolButton" 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="TQToolButton" 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="TQCheckBox" 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="TQCheckBox" 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"/>
+<includes>
+ <include location="global" impldecl="in implementation">kcombobox.h</include>
+ <include location="global" impldecl="in implementation">kicondialog.h</include>
+ <include location="global" impldecl="in implementation">kkeybutton.h</include>
+ <include location="global" impldecl="in implementation">klineedit.h</include>
+ <include location="global" impldecl="in implementation">ktextedit.h</include>
+ <include location="global" impldecl="in implementation">tdelistbox.h</include>
+</includes>
+</UI>
diff --git a/src/app/ActionMan/addplaceholderpopup.cpp b/src/app/ActionMan/addplaceholderpopup.cpp
new file mode 100644
index 0000000..3fe7c29
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <tdefiledialog.h>
+#include <tdemessagebox.h>
+
+// for ParameterDialog
+#include "../krusader.h" // for konfig-access
+#include "../BookMan/krbookmarkbutton.h"
+#include "../GUI/profilemanager.h"
+
+#include <tqlayout.h>
+#include <tqhbox.h>
+#include <tqlabel.h>
+#include <tqtoolbutton.h>
+#include <klineedit.h>
+#include <tqcheckbox.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( TQWidget *parent ) : TDEPopupMenu( parent ) {
+
+ _activeSub = new TDEPopupMenu( this );
+ _otherSub = new TDEPopupMenu( this );
+ _leftSub = new TDEPopupMenu( this );
+ _rightSub = new TDEPopupMenu( this );
+ _independentSub = new TDEPopupMenu( 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 ) );
+ }
+ }
+
+}
+
+
+TQString AddPlaceholderPopup::getPlaceholder( const TQPoint& pos ) {
+ int res = exec( pos );
+ if ( res == -1 )
+ return TQString();
+
+ // add the selected flag to the command line
+ if ( res == EXECUTABLE_ID ) { // did the user need an executable ?
+ // select an executable
+ TQString filename = KFileDialog::getOpenFileName(TQString(), TQString(), this);
+ if (filename != TQString())
+ 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 TQString();
+// }
+ ParameterDialog* parameterDialog = new ParameterDialog( currentPlaceholder, this );
+ TQString 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 TQString();
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////// ParameterDialog ////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+
+ParameterDialog::ParameterDialog( const exp_placeholder* currentPlaceholder, TQWidget *parent ) : KDialogBase( Plain, i18n("User Action Parameter Dialog"), Default | Ok, Ok, parent ) {
+ _parameter.clear();
+ _parameterCount = currentPlaceholder->parameterCount();
+
+ TQVBoxLayout* layout = new TQVBoxLayout( plainPage() );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 11 );
+
+ new TQLabel( 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() ) );
+ }
+
+ TQFrame * line = new TQFrame( plainPage() );
+ line->setFrameShape( TQFrame::HLine );
+ line->setFrameShadow( TQFrame::Sunken );
+
+ connect( this, TQ_SIGNAL(defaultClicked()), this, TQ_SLOT(reset()) );
+}
+
+TQString ParameterDialog::getParameter() {
+ if ( _parameterCount == 0 ) // meaning no parameters
+ return TQString();
+
+ if ( exec() == -1 )
+ return TQString();
+
+ 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 TQString();
+
+ TQString 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, TQWidget* parent ) : ParameterBase( parameter, parent ) {
+ TQVBoxLayout* layout = new TQVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ new TQLabel( i18n( parameter.description().utf8() ), this );
+ _lineEdit = new KLineEdit( parameter.preset(), this );
+ _preset = parameter.preset();
+}
+
+TQString ParameterText::text() {
+ return _lineEdit->text();
+}
+TQString 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, TQWidget* parent ) : ParameterBase( parameter, parent ) {
+ TQVBoxLayout* layout = new TQVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ new TQLabel( i18n( parameter.description().utf8() ), this );
+ TQHBox * hbox = new TQHBox( this );
+ hbox->setSpacing( 6 );
+ _lineEdit = new KLineEdit( hbox );
+ _button = new TQToolButton( hbox);
+ _button->setText( i18n("add") );
+ connect( _button, TQ_SIGNAL(clicked()), this, TQ_SLOT(addPlaceholder()) );
+}
+
+TQString ParameterPlaceholder::text() {
+ return _lineEdit->text();
+}
+TQString ParameterPlaceholder::preset() {
+ return TQString();
+}
+void ParameterPlaceholder::reset() {
+ _lineEdit->setText( TQString() );
+}
+bool ParameterPlaceholder::valid() {
+ if ( _lineEdit->text().isEmpty() )
+ return false;
+ else
+ return true;
+}
+void ParameterPlaceholder::addPlaceholder() {
+ AddPlaceholderPopup* popup = new AddPlaceholderPopup( this );
+ TQString exp = popup->getPlaceholder( mapToGlobal( TQPoint( _button->pos().x() + _button->width() + 6, _button->pos().y() + _button->height() / 2 ) ) );
+ _lineEdit->insert( exp );
+ delete popup;
+}
+
+///////////// ParameterYes
+ParameterYes::ParameterYes( const exp_parameter& parameter, TQWidget* parent ) : ParameterBase( parameter, parent ) {
+ TQVBoxLayout* layout = new TQVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ _checkBox = new TQCheckBox( i18n( parameter.description().utf8() ), this );
+ _checkBox->setChecked( true );
+}
+
+TQString ParameterYes::text() {
+ if ( _checkBox->isChecked() )
+ return TQString();
+ else
+ return "No";
+}
+TQString ParameterYes::preset() {
+ return TQString();
+}
+void ParameterYes::reset() {
+ _checkBox->setChecked( true );
+}
+bool ParameterYes::valid() {
+ return true;
+}
+
+///////////// ParameterNo
+ParameterNo::ParameterNo( const exp_parameter& parameter, TQWidget* parent ) : ParameterBase( parameter, parent ) {
+ TQVBoxLayout* layout = new TQVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ _checkBox = new TQCheckBox( i18n( parameter.description().utf8() ), this );
+ _checkBox->setChecked( false );
+}
+
+TQString ParameterNo::text() {
+ if ( _checkBox->isChecked() )
+ return "Yes";
+ else
+ return TQString();
+}
+TQString ParameterNo::preset() {
+ return TQString();
+}
+void ParameterNo::reset() {
+ _checkBox->setChecked( false );
+}
+bool ParameterNo::valid() {
+ return true;
+}
+
+///////////// ParameterFile
+ParameterFile::ParameterFile( const exp_parameter& parameter, TQWidget* parent ) : ParameterBase( parameter, parent ) {
+ TQVBoxLayout* layout = new TQVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ new TQLabel( i18n( parameter.description().utf8() ), this );
+ TQHBox * hbox = new TQHBox( this );
+ hbox->setSpacing( 6 );
+ _lineEdit = new KLineEdit( hbox );
+ _button = new TQToolButton( hbox);
+ TDEIconLoader *iconLoader = new TDEIconLoader();
+ _button->setPixmap( iconLoader->loadIcon( "document-open", TDEIcon::Toolbar, 16 ) );
+ connect( _button, TQ_SIGNAL(clicked()), this, TQ_SLOT(addFile()) );
+}
+
+TQString ParameterFile::text() {
+ return _lineEdit->text();
+}
+TQString ParameterFile::preset() {
+ return TQString();
+}
+void ParameterFile::reset() {
+ _lineEdit->setText( TQString() );
+}
+bool ParameterFile::valid() {
+ if ( _lineEdit->text().isEmpty() )
+ return false;
+ else
+ return true;
+}
+void ParameterFile::addFile() {
+ TQString filename = KFileDialog::getOpenFileName(TQString(), TQString(), this);
+ _lineEdit->insert( filename );
+}
+
+///////////// ParameterChoose
+ParameterChoose::ParameterChoose( const exp_parameter& parameter, TQWidget* parent ) : ParameterBase( parameter, parent ) {
+ TQVBoxLayout* layout = new TQVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ new TQLabel( i18n( parameter.description().utf8() ), this );
+ _combobox = new KComboBox( this );
+ _combobox->insertStringList( TQStringList::split( ";", parameter.preset().section(":", 1) ) );
+}
+
+TQString ParameterChoose::text() {
+ return _combobox->currentText();
+}
+TQString ParameterChoose::preset() {
+ return _combobox->text( 0 );
+}
+void ParameterChoose::reset() {
+ _combobox->setCurrentItem( 0 );
+}
+bool ParameterChoose::valid() {
+ return true;
+}
+
+///////////// ParameterSelect
+ParameterSelect::ParameterSelect( const exp_parameter& parameter, TQWidget* parent ) : ParameterBase( parameter, parent ) {
+ TQVBoxLayout* layout = new TQVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ new TQLabel( i18n( parameter.description().utf8() ), this );
+ _combobox = new KComboBox( this );
+ _combobox->setEditable( true );
+
+ krConfig->setGroup( "Private" );
+ TQStrList lst;
+ int i = krConfig->readListEntry( "Predefined Selections", lst );
+ if ( i > 0 )
+ _combobox->insertStrList( lst );
+
+ _combobox->setCurrentText( "*" );
+}
+
+TQString ParameterSelect::text() {
+ return _combobox->currentText();
+}
+TQString ParameterSelect::preset() {
+ return "*";
+}
+void ParameterSelect::reset() {
+ _combobox->setCurrentText( "*" );
+}
+bool ParameterSelect::valid() {
+ return true;
+}
+
+///////////// ParameterGoto
+ParameterGoto::ParameterGoto( const exp_parameter& parameter, TQWidget* parent ) : ParameterBase( parameter, parent ) {
+ TQVBoxLayout* layout = new TQVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ new TQLabel( i18n( parameter.description().utf8() ), this );
+ TQHBox * hbox = new TQHBox( this );
+ hbox->setSpacing( 6 );
+ _lineEdit = new KLineEdit( hbox );
+ _lineEdit->setCompletionObject( new KURLCompletion( KURLCompletion::DirCompletion ) );
+ _dirButton = new TQToolButton( hbox );
+ TDEIconLoader *iconLoader = new TDEIconLoader();
+ _dirButton->setPixmap( iconLoader->loadIcon( "document-open", TDEIcon::Toolbar, 16 ) );
+ connect( _dirButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(setDir()) );
+ _placeholderButton = new TQToolButton( hbox);
+ _placeholderButton->setText( i18n("add") );
+ connect( _placeholderButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(addPlaceholder()) );
+}
+
+TQString ParameterGoto::text() {
+ return _lineEdit->text();
+}
+TQString ParameterGoto::preset() {
+ return TQString();
+}
+void ParameterGoto::reset() {
+ _lineEdit->setText( TQString() );
+}
+bool ParameterGoto::valid() {
+ if ( _lineEdit->text().isEmpty() )
+ return false;
+ else
+ return true;
+}
+void ParameterGoto::setDir() {
+ TQString folder = KFileDialog::getExistingDirectory(TQString(), this);
+ _lineEdit->setText( folder );
+}
+void ParameterGoto::addPlaceholder() {
+ AddPlaceholderPopup* popup = new AddPlaceholderPopup( this );
+ TQString exp = popup->getPlaceholder( mapToGlobal( TQPoint( _placeholderButton->pos().x() + _placeholderButton->width() + 6, _placeholderButton->pos().y() + _placeholderButton->height() / 2 ) ) );
+ _lineEdit->insert( exp );
+ delete popup;
+}
+
+///////////// ParameterSyncprofile
+ParameterSyncprofile::ParameterSyncprofile( const exp_parameter& parameter, TQWidget* parent ) : ParameterBase( parameter, parent ) {
+ TQVBoxLayout* layout = new TQVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ new TQLabel( i18n( parameter.description().utf8() ), this );
+ _combobox = new KComboBox( this );
+
+ _combobox->insertStringList( ProfileManager::availableProfiles("SynchronizerProfile") );
+}
+
+TQString ParameterSyncprofile::text() {
+ return _combobox->currentText();
+}
+TQString ParameterSyncprofile::preset() {
+ return _combobox->text( 0 );
+}
+void ParameterSyncprofile::reset() {
+ _combobox->setCurrentItem( 0 );
+}
+bool ParameterSyncprofile::valid() {
+ return true;
+}
+
+///////////// ParameterSearch
+ParameterSearch::ParameterSearch( const exp_parameter& parameter, TQWidget* parent ) : ParameterBase( parameter, parent ) {
+ TQVBoxLayout* layout = new TQVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ new TQLabel( i18n( parameter.description().utf8() ), this );
+ _combobox = new KComboBox( this );
+
+ _combobox->insertStringList( ProfileManager::availableProfiles("SearcherProfile") );
+}
+
+TQString ParameterSearch::text() {
+ return _combobox->currentText();
+}
+TQString ParameterSearch::preset() {
+ return _combobox->text( 0 );
+}
+void ParameterSearch::reset() {
+ _combobox->setCurrentItem( 0 );
+}
+bool ParameterSearch::valid() {
+ return true;
+}
+
+///////////// ParameterPanelprofile
+ParameterPanelprofile::ParameterPanelprofile( const exp_parameter& parameter, TQWidget* parent ) : ParameterBase( parameter, parent ) {
+ TQVBoxLayout* layout = new TQVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ new TQLabel( i18n( parameter.description().utf8() ), this );
+ _combobox = new KComboBox( this );
+
+ _combobox->insertStringList( ProfileManager::availableProfiles("Panel") );
+}
+
+TQString ParameterPanelprofile::text() {
+ return _combobox->currentText();
+}
+TQString ParameterPanelprofile::preset() {
+ return _combobox->text( 0 );
+}
+void ParameterPanelprofile::reset() {
+ _combobox->setCurrentItem( 0 );
+}
+bool ParameterPanelprofile::valid() {
+ return true;
+}
+
+///////////// ParameterInt
+ParameterInt::ParameterInt( const exp_parameter& parameter, TQWidget* parent ) : ParameterBase( parameter, parent ) {
+ TQHBoxLayout* layout = new TQHBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setSpacing( 6 );
+
+ new TQLabel( i18n( parameter.description().utf8() ), this );
+ _spinbox = new KIntSpinBox( this );
+ TQStringList para = TQStringList::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();
+}
+
+TQString ParameterInt::text() {
+ return _spinbox->text();
+}
+TQString ParameterInt::preset() {
+ return TQString( "%1" ).arg( _default );
+}
+void ParameterInt::reset() {
+ return _spinbox->setValue( _default );
+}
+bool ParameterInt::valid() {
+ return true;
+}
+
+
+#include "addplaceholderpopup.moc"
diff --git a/src/app/ActionMan/addplaceholderpopup.h b/src/app/ActionMan/addplaceholderpopup.h
new file mode 100644
index 0000000..c463dae
--- /dev/null
+++ b/src/app/ActionMan/addplaceholderpopup.h
@@ -0,0 +1,322 @@
+//
+// 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 <tdepopupmenu.h>
+#include <kdialogbase.h>
+#include "../UserAction/expander.h"
+
+class TQString;
+class KLineEdit;
+class TQToolButton;
+class TQCheckBox;
+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 TDEPopupMenu {
+
+public:
+ AddPlaceholderPopup( TQWidget *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
+ */
+ TQString getPlaceholder( const TQPoint& 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
+ */
+ TQString getParameter( exp_placeholder* currentPlaceholder );
+
+private:
+ TDEPopupMenu *_activeSub, *_otherSub, *_leftSub, *_rightSub, *_independentSub;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////// Parameter Widgets ///////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * abstract baseclass for all Parameter widgets
+ * @author Jonas Bhr (http://www.jonas-baehr.de)
+ */
+class ParameterBase : public TQWidget {
+public:
+ inline ParameterBase( const exp_parameter& parameter, TQWidget* parent ) : TQWidget( parent ) { _nessesary = parameter.nessesary(); }
+ /**
+ * @return the text for the parameter
+ */
+ virtual TQString text() = 0;
+ /**
+ * @return the default of the parameter
+ */
+ virtual TQString 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, TQWidget* parent );
+ TQString text();
+ TQString preset();
+ void reset();
+ bool valid();
+private:
+ KLineEdit * _lineEdit;
+ TQString _preset;
+};
+
+/**
+ * A line-edit with the "addPlaceholder"-button
+ * used with default = "__placeholder"
+ */
+class ParameterPlaceholder : public ParameterBase {
+TQ_OBJECT
+
+public:
+ ParameterPlaceholder( const exp_parameter& parameter, TQWidget* parent );
+ TQString text();
+ TQString preset();
+ void reset();
+ bool valid();
+private:
+ KLineEdit * _lineEdit;
+ TQToolButton* _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, TQWidget* parent );
+ TQString text();
+ TQString preset();
+ void reset();
+ bool valid();
+private:
+ TQCheckBox* _checkBox;
+};
+
+/**
+ * A Checkbox, default: unchecked; retuns "Yes" if checked
+ * used with default = "__no"
+ */
+class ParameterNo : public ParameterBase {
+public:
+ ParameterNo( const exp_parameter& parameter, TQWidget* parent );
+ TQString text();
+ TQString preset();
+ void reset();
+ bool valid();
+private:
+ TQCheckBox* _checkBox;
+};
+
+/**
+ * A line-edit with the "file open"-button
+ * used with default = "__file"
+ */
+class ParameterFile : public ParameterBase {
+TQ_OBJECT
+
+public:
+ ParameterFile( const exp_parameter& parameter, TQWidget* parent );
+ TQString text();
+ TQString preset();
+ void reset();
+ bool valid();
+private:
+ KLineEdit * _lineEdit;
+ TQToolButton* _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, TQWidget* parent );
+ TQString text();
+ TQString 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, TQWidget* parent );
+ TQString text();
+ TQString 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 {
+TQ_OBJECT
+
+public:
+ ParameterGoto( const exp_parameter& parameter, TQWidget* parent );
+ TQString text();
+ TQString preset();
+ void reset();
+ bool valid();
+private:
+ KLineEdit * _lineEdit;
+ TQToolButton* _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, TQWidget* parent );
+ TQString text();
+ TQString 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, TQWidget* parent );
+ TQString text();
+ TQString 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, TQWidget* parent );
+ TQString text();
+ TQString 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, TQWidget* parent );
+ TQString text();
+ TQString 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 {
+TQ_OBJECT
+
+public:
+ ParameterDialog( const exp_placeholder* currentPlaceholder, TQWidget *parent );
+
+ /**
+ * Use this to execute the dialog.
+ * @return a TQString with all paremeters; ommiting the optional ones if they have the default-value.
+ */
+ TQString getParameter();
+
+private:
+ typedef TQValueList<ParameterBase*> ParameterList;
+ ParameterList _parameter;
+ int _parameterCount;
+private slots:
+ void reset();
+ void slotOk();
+};
+
+
+#endif // ADDPLACEHOLDERPOPUP_H
diff --git a/src/app/ActionMan/useractionlistview.cpp b/src/app/ActionMan/useractionlistview.cpp
new file mode 100644
index 0000000..fe078e5
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <kiconloader.h>
+#include <tqptrlist.h>
+#include <tqdom.h>
+
+#include "../krusader.h"
+#include "../UserAction/kraction.h"
+#include "../UserAction/useraction.h"
+
+#define COL_TITLE 0
+#define COL_NAME 1
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////// UserActionListView /////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+UserActionListView::UserActionListView( TQWidget * parent, const char * name )
+ : TDEListView( parent, name )
+{
+ addColumn( i18n("Title") );
+ //addColumn( i18n("Identifier") );
+ setResizeMode( TQListView::AllColumns );
+
+ setRootIsDecorated( true );
+ setSelectionMode( TQListView::Extended ); // normaly select single items but one may use Ctrl or Shift to select multiple
+ setSorting( COL_TITLE );
+
+ update();
+}
+
+UserActionListView::~UserActionListView()
+{
+}
+
+TQSize UserActionListView::sizeHint() const {
+ return TQSize(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 {
+ TQListViewItem* categoryItem = findCategoryItem( action->category() );
+ if ( ! categoryItem ) {
+ categoryItem = new TDEListViewItem( 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;
+}
+
+TQListViewItem* UserActionListView::findCategoryItem( const TQString& category ) {
+ for ( TQListViewItem* 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 ( TQListViewItemIterator 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 ( TQListViewItemIterator it( this ); it.current(); ++it ) {
+ if ( UserActionListViewItem* item = dynamic_cast<UserActionListViewItem*>( it.current() ) ) {
+ setCurrentItem( item );
+ break;
+ }
+ } //for
+}
+
+void UserActionListView::setCurrentItem( TQListViewItem* item ) {
+ if ( ! item )
+ return;
+ ensureItemVisible( item );
+ TQListView::setCurrentItem( item );
+}
+
+TQDomDocument UserActionListView::dumpSelectedActions( TQDomDocument* mergeDoc ) const {
+ TQPtrList<TQListViewItem> list = selectedItems();
+ TQDomDocument doc;
+ if ( mergeDoc )
+ doc = *mergeDoc;
+ else
+ doc = UserAction::createEmptyDoc();
+ TQDomElement root = doc.documentElement();
+
+ for ( TQListViewItem* 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() {
+ TQPtrList<TQListViewItem> list = selectedItems();
+
+ for ( TQListViewItem* 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( TQListView* view, KrAction* action )
+ : TDEListViewItem( view )
+{
+ setAction( action );
+}
+
+UserActionListViewItem::UserActionListViewItem( TQListViewItem* item, KrAction * action )
+ : TDEListViewItem( item )
+{
+ setAction( action );
+}
+
+UserActionListViewItem::~UserActionListViewItem() {
+/* // remove category-item if the last member ofthiscategory disappears
+ if ( TQListViewItem* item = dynamic_cast<TQListViewItem*>( parent() ) ) {
+ if ( item->childCount() <= 1 )
+ item->deleteLater(); // not possible since not inherited from TQObject
+ }*/
+}
+
+
+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, TDEGlobal::iconLoader()->loadIcon( _action->icon(), TDEIcon::Small ) );
+ setText( COL_TITLE, _action->text() );
+ setText( COL_NAME, _action->name() );
+}
+
+int UserActionListViewItem::compare( TQListViewItem* 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 TQListViewItem::compare( i, col, ascending );
+}
+
+
diff --git a/src/app/ActionMan/useractionlistview.h b/src/app/ActionMan/useractionlistview.h
new file mode 100644
index 0000000..b423637
--- /dev/null
+++ b/src/app/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 <tdelistview.h>
+
+class KrAction;
+class TQString;
+class UserActionListViewItem;
+class TQDomDocument;
+
+/**
+ * @author Jonas Bähr
+ */
+class UserActionListView : public TDEListView {
+public:
+ UserActionListView( TQWidget* parent = 0, const char* name = 0 );
+ ~UserActionListView();
+ virtual TQSize sizeHint() const;
+
+ void update();
+ void update( KrAction* action );
+ UserActionListViewItem* insertAction( KrAction* action );
+
+ KrAction* currentAction() const;
+ void setCurrentAction( const KrAction* );
+
+ TQDomDocument dumpSelectedActions( TQDomDocument* 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( TQListViewItem* item );
+
+protected:
+ TQListViewItem* findCategoryItem( const TQString& category );
+ UserActionListViewItem* findActionItem( const KrAction* action );
+};
+
+
+/**
+ * @author Jonas Bähr
+ */
+class UserActionListViewItem : public TDEListViewItem {
+public:
+ UserActionListViewItem( TQListView* view, KrAction* action );
+ UserActionListViewItem( TQListViewItem* item, KrAction* action );
+ ~UserActionListViewItem();
+
+ void setAction( KrAction* action );
+ KrAction* action() const;
+ void update();
+
+ /**
+ * This reimplements TQt's compare-function in order to have categories on the top of the list
+ */
+ int compare ( TQListViewItem * i, int col, bool ascending ) const;
+
+private:
+ KrAction* _action;
+};
+
+
+#endif //USERACTIONLISTVIEW_H
diff --git a/src/app/ActionMan/useractionpage.cpp b/src/app/ActionMan/useractionpage.cpp
new file mode 100644
index 0000000..065b087
--- /dev/null
+++ b/src/app/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 <tqsplitter.h>
+#include <tqlayout.h>
+#include <tqtoolbutton.h>
+#include <tqtooltip.h>
+#include <klineedit.h>
+#include <tdemessagebox.h>
+#include <tdefiledialog.h>
+#include <kiconloader.h>
+#include <tdelocale.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) TDEGlobal::iconLoader()->loadIcon(N, TDEIcon::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( TQWidget* parent )
+ : TQWidget( parent, "UserActionPage" )
+{
+ TQVBoxLayout* layout = new TQVBoxLayout( this, 0, 6, "UserActionPageLayout" ); // 0px margin, 6px item-spacing
+
+ // ======== pseudo-toolbar start ========
+ TQHBoxLayout* toolbarLayout = new TQHBoxLayout( layout, 0, 0 ); // neither margin nor spacing for the toolbar with autoRaise
+
+ newButton = new TQToolButton( this, "newButton" );
+ newButton->setPixmap( ICON("document-new") );
+ newButton->setAutoRaise(true);
+ TQToolTip::add( newButton, i18n("Create new useraction") );
+
+ importButton = new TQToolButton( this, "importButton" );
+ importButton->setPixmap( ICON("fileimport") );
+ importButton->setAutoRaise(true);
+ TQToolTip::add( importButton, i18n("Import useractions") );
+
+ exportButton = new TQToolButton( this, "exportButton" );
+ exportButton->setPixmap( ICON("fileexport") );
+ exportButton->setAutoRaise(true);
+ TQToolTip::add( exportButton, i18n("Export useractions") );
+
+ copyButton = new TQToolButton( this, "copyButton" );
+ copyButton->setPixmap( ICON("edit-copy") );
+ copyButton->setAutoRaise(true);
+ TQToolTip::add( copyButton, i18n("Copy useractions to clipboard") );
+
+ pasteButton = new TQToolButton( this, "pasteButton" );
+ pasteButton->setPixmap( ICON("edit-paste") );
+ pasteButton->setAutoRaise(true);
+ TQToolTip::add( pasteButton, i18n("Paste useractions from clipboard") );
+
+ removeButton = new TQToolButton( this, "removeButton" );
+ removeButton->setPixmap( ICON("edit-delete") );
+ removeButton->setAutoRaise(true);
+ TQToolTip::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."
+ ),
+ TQString(), // caption
+ "show UserAction help" //dontShowAgainName for the config
+ );
+*/
+ TQSplitter *split = new TQSplitter( 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, TQ_SIGNAL( currentChanged(TQListViewItem*) ), TQ_SLOT( slotChangeCurrent() ) );
+ connect( newButton, TQ_SIGNAL( clicked() ), TQ_SLOT( slotNewAction() ) );
+ connect( removeButton, TQ_SIGNAL( clicked() ), TQ_SLOT( slotRemoveAction() ) );
+ connect( importButton, TQ_SIGNAL( clicked() ), TQ_SLOT( slotImport() ) );
+ connect( exportButton, TQ_SIGNAL( clicked() ), TQ_SLOT( slotExport() ) );
+ connect( copyButton, TQ_SIGNAL( clicked() ), TQ_SLOT( slotToClip() ) );
+ connect( pasteButton, TQ_SIGNAL( clicked() ), TQ_SLOT( slotFromClip() ) );
+
+ // forwards the changed signal of the properties
+ connect ( actionProperties, TQ_SIGNAL( changed() ), TQ_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, TQ_SIGNAL( currentChanged(TQListViewItem*) ), this, TQ_SLOT( slotChangeCurrent() ) );
+ actionTree->setCurrentAction( actionProperties->action() );
+ connect( actionTree, TQ_SIGNAL( currentChanged(TQListViewItem*) ), TQ_SLOT( slotChangeCurrent() ) );
+ return false;
+ }
+ if ( answer == KMessageBox::Yes ) {
+ if ( ! actionProperties->validProperties() ) {
+ disconnect( actionTree, TQ_SIGNAL( currentChanged(TQListViewItem*) ), this, TQ_SLOT( slotChangeCurrent() ) );
+ actionTree->setCurrentAction( actionProperties->action() );
+ connect( actionTree, TQ_SIGNAL( currentChanged(TQListViewItem*) ), TQ_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() {
+ TQString filename = KFileDialog::getOpenFileName(TQString(), 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;
+
+ TQString filename = KFileDialog::getSaveFileName(TQString(), i18n(FILE_FILTER), this);
+ if ( filename.isEmpty() )
+ return;
+
+ TQDomDocument doc = TQDomDocument( ACTION_DOCTYPE );
+ TQFile 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;
+
+ TQDomDocument doc = actionTree->dumpSelectedActions();
+ TDEApplication::clipboard()->setText( doc.toString() );
+}
+
+void UserActionPage::slotFromClip() {
+ TQDomDocument doc( ACTION_DOCTYPE );
+ if ( doc.setContent( TDEApplication::clipboard()->text() ) ) {
+ TQDomElement 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/src/app/ActionMan/useractionpage.h b/src/app/ActionMan/useractionpage.h
new file mode 100644
index 0000000..2a117f6
--- /dev/null
+++ b/src/app/ActionMan/useractionpage.h
@@ -0,0 +1,74 @@
+//
+// 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 <tqwidget.h>
+
+class UserActionListView;
+class ActionProperty;
+class TQToolButton;
+
+/**
+ * @author Jonas Bähr
+*/
+class UserActionPage : public TQWidget {
+TQ_OBJECT
+
+public:
+ UserActionPage( TQWidget* 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;
+ TQToolButton *importButton, *exportButton;
+ TQToolButton *copyButton, *pasteButton;
+ TQToolButton *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/src/app/BookMan/Makefile.am b/src/app/BookMan/Makefile.am
new file mode 100644
index 0000000..3f602d3
--- /dev/null
+++ b/src/app/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/src/app/BookMan/kraddbookmarkdlg.cpp b/src/app/BookMan/kraddbookmarkdlg.cpp
new file mode 100644
index 0000000..1af3736
--- /dev/null
+++ b/src/app/BookMan/kraddbookmarkdlg.cpp
@@ -0,0 +1,117 @@
+#include "kraddbookmarkdlg.h"
+#include "../krusader.h"
+#include "krbookmarkhandler.h"
+#include <tdelocale.h>
+#include <tqheader.h>
+#include <tqlayout.h>
+#include <tqlabel.h>
+#include <kinputdialog.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+
+KrAddBookmarkDlg::KrAddBookmarkDlg(TQWidget *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, TQ_SIGNAL(user1Clicked()), this, TQ_SLOT(newFolder()));
+
+ // create the main widget
+ TQWidget *page = new TQWidget(this);
+ setMainWidget(page);
+
+ TQGridLayout *layout = new TQGridLayout(page, 1, 1, 0, spacingHint()); // expanding
+ // name and url
+ TQLabel *lb1 = new TQLabel(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);
+
+ TQLabel *lb2 = new TQLabel(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
+ TQLabel *lb3 = new TQLabel(i18n("Create in:"), page);
+ _folder = new KLineEdit(page);
+ layout->addWidget(lb3, 2, 0);
+ layout->addWidget(_folder, 2, 1);
+ _folder->setReadOnly(true);
+
+ _createInBtn = new TQToolButton(page);
+ _createInBtn->setPixmap(krLoader->loadIcon("go-down", TDEIcon::Small));
+ _createInBtn->setToggleButton(true);
+ connect(_createInBtn, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(toggleCreateIn(bool )));
+ layout->addWidget(_createInBtn, 2, 2);
+
+ setDetailsWidget(createInWidget());
+
+ _name->setFocus();
+}
+
+void KrAddBookmarkDlg::toggleCreateIn(bool show) {
+ _createInBtn->setPixmap(krLoader->loadIcon(show ? "go-up" :"go-down", TDEIcon::Small));
+ showButton(KDialogBase::User1, show);
+ setDetails(show);
+}
+
+// creates the widget that lets you decide where to put the new bookmark
+TQWidget *KrAddBookmarkDlg::createInWidget() {
+ _createIn = new TDEListView(this);
+ _createIn->addColumn("Folders");
+ _createIn->header()->hide();
+ _createIn->setRootIsDecorated(true);
+ _createIn->setAlternateBackground(TQColor()); // disable alternate coloring
+
+ TDEListViewItem *item = new TDEListViewItem(_createIn, i18n("Bookmarks"));
+ item->setOpen(true);
+ item->setSelected(true);
+ _xr[item] = krBookMan->_root;
+
+ populateCreateInWidget(krBookMan->_root, item);
+ _createIn->setCurrentItem(item);
+ createInSelection(item);
+ connect(_createIn, TQ_SIGNAL(selectionChanged(TQListViewItem*)), this, TQ_SLOT(createInSelection(TQListViewItem*)));
+
+ return _createIn;
+}
+
+void KrAddBookmarkDlg::createInSelection(TQListViewItem *item) {
+ if (item) {
+ _folder->setText(_xr[static_cast<TDEListViewItem*>(item)]->text());
+ }
+}
+
+void KrAddBookmarkDlg::populateCreateInWidget(KrBookmark *root, TDEListViewItem *parent) {
+ for (KrBookmark *bm = root->children().first(); bm; bm = root->children().next()) {
+ if (bm->isFolder()) {
+ TDEListViewItem *item = new TDEListViewItem(parent, bm->text());
+ item->setOpen(true);
+ _xr[item] = bm;
+ populateCreateInWidget(bm, item);
+ }
+ }
+}
+
+void KrAddBookmarkDlg::newFolder() {
+ // get the name
+ TQString newFolder = KInputDialog::getText(i18n("New Folder"), i18n("Folder name:"), TQString(), 0, this);
+ if (newFolder == TQString())
+ return;
+ // add to the list in bookman
+ KrBookmark *bm = new KrBookmark(newFolder);
+ krBookMan->addBookmark(bm, _xr[static_cast<TDEListViewItem*>(_createIn->selectedItem())]);
+ // fix the gui
+ TDEListViewItem *item = new TDEListViewItem(_createIn->selectedItem(), bm->text());
+ _xr[item] = bm;
+
+ _createIn->setCurrentItem(item);
+ item->setSelected(true);
+}
+
+#include "kraddbookmarkdlg.moc"
diff --git a/src/app/BookMan/kraddbookmarkdlg.h b/src/app/BookMan/kraddbookmarkdlg.h
new file mode 100644
index 0000000..b270781
--- /dev/null
+++ b/src/app/BookMan/kraddbookmarkdlg.h
@@ -0,0 +1,40 @@
+#ifndef KRADDBOOKMARKDLG_H
+#define KRADDBOOKMARKDLG_H
+
+#include "krbookmark.h"
+#include "../VFS/vfs.h"
+#include <kdialogbase.h>
+#include <kurl.h>
+#include <klineedit.h>
+#include <tqmap.h>
+#include <tdelistview.h>
+#include <tqtoolbutton.h>
+
+class KrAddBookmarkDlg: public KDialogBase {
+ TQ_OBJECT
+
+public:
+ KrAddBookmarkDlg(TQWidget *parent, KURL url = 0);
+ KURL url() const { return vfs::fromPathOrURL(_url->text()); }
+ TQString name() const { return _name->text(); }
+ KrBookmark *folder() const { return _xr[static_cast<TDEListViewItem*>(_createIn->selectedItem())]; }
+
+protected:
+ TQWidget *createInWidget();
+ void populateCreateInWidget(KrBookmark *root, TDEListViewItem *parent);
+
+protected slots:
+ void toggleCreateIn(bool show);
+ void createInSelection(TQListViewItem *item);
+ void newFolder();
+
+private:
+ KLineEdit *_name;
+ KLineEdit *_url;
+ KLineEdit *_folder;
+ TDEListView *_createIn;
+ TQMap<TDEListViewItem*, KrBookmark*> _xr;
+ TQToolButton *_createInBtn;
+};
+
+#endif // KRADDBOOKMARKDLG_H
diff --git a/src/app/BookMan/krbookmark.cpp b/src/app/BookMan/krbookmark.cpp
new file mode 100644
index 0000000..cc67228
--- /dev/null
+++ b/src/app/BookMan/krbookmark.cpp
@@ -0,0 +1,92 @@
+#include "krbookmark.h"
+#include "../krusader.h"
+#include "../VFS/krarchandler.h"
+#include <tdeactioncollection.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <kdebug.h>
+
+#define BM_NAME(X) (TQString("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(TQString name, KURL url, TDEActionCollection *parent, TQString icon, TQString actionName ):
+ TDEAction(name, 0, 0, 0, parent, actionName.isNull() ? BM_NAME(name).latin1() : BM_NAME(actionName).latin1()),
+ _url(url), _folder(false), _separator(false) {
+ connect(this, TQ_SIGNAL(activated()), this, TQ_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("application-x-tar");
+ else setIcon("folder_html");
+ }
+ }
+
+ _children.setAutoDelete(true);
+}
+
+KrBookmark::KrBookmark(TQString name, TQString icon):
+ TDEAction(name, 0, 0, 0, 0), _folder(true), _separator(false) {
+ setIcon(icon=="" ? "folder" : icon);
+}
+
+KrBookmark* KrBookmark::getExistingBookmark(TQString actionName, TDEActionCollection *collection) {
+ return static_cast<KrBookmark*>(collection->action(BM_NAME(actionName).latin1()));
+}
+
+KrBookmark* KrBookmark::devices(TDEActionCollection *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", TDEIcon::Small));
+ }
+ return bm;
+}
+
+KrBookmark* KrBookmark::virt(TDEActionCollection *collection) {
+ KrBookmark *bm = getExistingBookmark(i18n(NAME_VIRTUAL), collection);
+ if (!bm) {
+ bm = new KrBookmark(i18n(NAME_VIRTUAL), "virt:/", collection);
+ bm->setIconSet(krLoader->loadIcon("pipe", TDEIcon::Small));
+ }
+ return bm;
+}
+
+KrBookmark* KrBookmark::lan(TDEActionCollection *collection) {
+ KrBookmark *bm = getExistingBookmark(i18n(NAME_LAN), collection);
+ if (!bm) {
+ bm = new KrBookmark(i18n(NAME_LAN), "lan:/", collection);
+ bm->setIconSet(krLoader->loadIcon("network", TDEIcon::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/src/app/BookMan/krbookmark.h b/src/app/BookMan/krbookmark.h
new file mode 100644
index 0000000..567b3c8
--- /dev/null
+++ b/src/app/BookMan/krbookmark.h
@@ -0,0 +1,46 @@
+#ifndef KRBOOKMARK_H
+#define KRBOOKMARK_H
+
+#include <tdeaction.h>
+#include <tqptrlist.h>
+#include <kurl.h>
+
+class TDEActionCollection;
+
+class KrBookmark: public TDEAction {
+ TQ_OBJECT
+
+public:
+ KrBookmark(TQString name, KURL url, TDEActionCollection *parent, TQString icon = "", TQString actionName = TQString() );
+ KrBookmark(TQString name, TQString 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; }
+ TQPtrList<KrBookmark>& children() { return _children; }
+
+ static KrBookmark* getExistingBookmark(TQString actionName, TDEActionCollection *collection);
+ // ----- special bookmarks
+ static KrBookmark* devices(TDEActionCollection *collection);
+ static KrBookmark* virt(TDEActionCollection *collection);
+ static KrBookmark* lan(TDEActionCollection *collection);
+ static KrBookmark* separator();
+
+signals:
+ void activated(const KURL& url);
+
+protected slots:
+ void activatedProxy();
+
+
+private:
+ KURL _url;
+ TQString _icon;
+ bool _folder;
+ bool _separator;
+ TQPtrList<KrBookmark> _children;
+};
+
+#endif // KRBOOKMARK_H
diff --git a/src/app/BookMan/krbookmarkbutton.cpp b/src/app/BookMan/krbookmarkbutton.cpp
new file mode 100644
index 0000000..b7ac61c
--- /dev/null
+++ b/src/app/BookMan/krbookmarkbutton.cpp
@@ -0,0 +1,38 @@
+#include "krbookmarkbutton.h"
+#include "krbookmarkhandler.h"
+#include "../krusader.h"
+#include <tqpixmap.h>
+#include <kiconloader.h>
+#include <tdeaction.h>
+#include <tdelocale.h>
+#include <tdepopupmenu.h>
+#include <kdebug.h>
+
+KrBookmarkButton::KrBookmarkButton(TQWidget *parent): TQToolButton(parent) {
+ TQPixmap icon = krLoader->loadIcon("bookmark", TDEIcon::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 TDEActionMenu(i18n("Bookmarks"), "bookmark", 0, 0);
+ acmBookmarks->setDelayed(false);
+ acmBookmarks->popupMenu()->setKeyboardShortcutsEnabled(true);
+ acmBookmarks->popupMenu()->setKeyboardShortcutsExecute(true);
+
+ setPopup(acmBookmarks->popupMenu());
+ connect(this, TQ_SIGNAL(pressed()), this, TQ_SLOT(populate()));
+ populate();
+}
+
+void KrBookmarkButton::populate() {
+ krBookMan->populate(static_cast<TDEPopupMenu*>(popup()));
+}
+
+void KrBookmarkButton::openPopup() {
+ populate();
+ popup()->exec(mapToGlobal(TQPoint(0, height())));
+}
+
+#include "krbookmarkbutton.moc"
diff --git a/src/app/BookMan/krbookmarkbutton.h b/src/app/BookMan/krbookmarkbutton.h
new file mode 100644
index 0000000..54136f2
--- /dev/null
+++ b/src/app/BookMan/krbookmarkbutton.h
@@ -0,0 +1,24 @@
+#ifndef KRBOOKMARK_BUTTON_H
+#define KRBOOKMARK_BUTTON_H
+
+#include <tqtoolbutton.h>
+#include "krbookmarkhandler.h"
+
+class KrBookmarkButton: public TQToolButton {
+ TQ_OBJECT
+
+public:
+ KrBookmarkButton(TQWidget *parent);
+ void openPopup();
+
+signals:
+ void openUrl(const KURL &url);
+
+protected slots:
+ void populate();
+
+private:
+ TDEActionMenu *acmBookmarks;
+};
+
+#endif // KRBOOKMARK_BUTTON_H
diff --git a/src/app/BookMan/krbookmarkhandler.cpp b/src/app/BookMan/krbookmarkhandler.cpp
new file mode 100644
index 0000000..e62515c
--- /dev/null
+++ b/src/app/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 <tdemessagebox.h>
+#include <tqptrlist.h>
+#include <tdeactioncollection.h>
+#include <tdelocale.h>
+#include <kdebug.h>
+#include <kbookmarkmanager.h>
+#include <kstandarddirs.h>
+#include <tqfile.h>
+#include <tqcursor.h>
+
+#define SPECIAL_BOOKMARKS true
+
+// ------------------------ for internal use
+#define BOOKMARKS_FILE "krusader/krbookmarks.xml"
+#define CONNECT_BM(X) { disconnect(X, TQ_SIGNAL(activated(const KURL&)), 0, 0); connect(X, TQ_SIGNAL(activated(const KURL&)), this, TQ_SLOT(slotActivated(const KURL&))); }
+
+KrBookmarkHandler::KrBookmarkHandler(): TQObject(0), _middleClick(false), _mainBookmarkPopup( 0 ), _specialBookmarkIDs(), _bookmarkIDTable() {
+ // create our own action collection and make the shortcuts apply only to parent
+ _privateCollection = new TDEActionCollection(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, TQ_SIGNAL(changed(const TQString&, const TQString& )), this, TQ_SLOT(bookmarksChanged(const TQString&, const TQString& )));
+}
+
+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(TQDomDocument &doc, TQDomElement &where, KrBookmark *bm) {
+ if( bm->isSeparator() ) {
+ TQDomElement bookmark = doc.createElement("separator");
+ where.appendChild(bookmark);
+ }
+ else {
+ TQDomElement bookmark = doc.createElement("bookmark");
+ // url
+ bookmark.setAttribute("href", bm->url().prettyURL());
+ // icon
+ bookmark.setAttribute("icon", bm->icon());
+ // title
+ TQDomElement title = doc.createElement("title");
+ title.appendChild(doc.createTextNode(bm->text()));
+ bookmark.appendChild(title);
+
+ where.appendChild(bookmark);
+ }
+}
+
+void KrBookmarkHandler::exportToFileFolder(TQDomDocument &doc, TQDomElement &parent, KrBookmark *folder) {
+ for (KrBookmark *bm = folder->children().first(); bm; bm = folder->children().next()) {
+ if (bm->isFolder()) {
+ TQDomElement newFolder = doc.createElement("folder");
+ newFolder.setAttribute("icon", bm->icon());
+ parent.appendChild(newFolder);
+ TQDomElement 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() {
+ TQDomDocument doc( "xbel" );
+ TQDomElement 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
+ TQDomProcessingInstruction instr = doc.createProcessingInstruction( "xml",
+ "version=\"1.0\" encoding=\"UTF-8\" ");
+ doc.insertBefore( instr, doc.firstChild() );
+ }
+
+
+ TQString filename = locateLocal( "data", BOOKMARKS_FILE );
+ TQFile file(filename);
+ if ( file.open( IO_WriteOnly ) ) {
+ TQTextStream 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(TQDomElement &e, KrBookmark *parent, TQString path, TQString *errorMsg) {
+ TQString 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
+ TQDomElement 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(TQDomNode &first, KrBookmark *parent, TQString path, TQString *errorMsg) {
+ TQString name;
+ TQDomNode n = first;
+ while (!n.isNull()) {
+ TQDomElement e = n.toElement();
+ if (e.tagName() == "bookmark") {
+ if (!importFromFileBookmark(e, parent, path, errorMsg))
+ return false;
+ } else if (e.tagName() == "folder") {
+ TQString iconName = "";
+ if (e.hasAttribute("icon")) iconName=e.attribute("icon");
+ // the title is the first child of the folder
+ TQDomElement 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);
+
+ TQDomNode 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);
+
+ TQString filename = locateLocal( "data", BOOKMARKS_FILE );
+ TQFile file( filename );
+ if ( !file.open(IO_ReadOnly))
+ return; // no bookmarks file
+
+ TQString errorMsg;
+ TQDomNode n;
+ TQDomElement e;
+ TQDomDocument 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(TDEPopupMenu *menu) {
+ _mainBookmarkPopup = menu;
+ menu->clear();
+ _bookmarkIDTable.clear();
+ _specialBookmarkIDs.clear();
+ buildMenu(_root, menu);
+}
+
+void KrBookmarkHandler::buildMenu(KrBookmark *parent, TDEPopupMenu *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;
+ TDEPopupMenu *newMenu = new TDEPopupMenu(menu);
+ int id = menu->insertItem(TQIconSet(krLoader->loadIcon(bm->icon(), TDEIcon::Small)),
+ bm->text(), newMenu, -1 /* dummy id */, -1 /* end of list */);
+
+ if( !_bookmarkIDTable.find( menu ) )
+ _bookmarkIDTable.insert( menu, new TQMap<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 TQMap<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
+ TDEPopupMenu *newMenu = new TDEPopupMenu(menu);
+ itemIndex = menu->insertItem(TQIconSet(krLoader->loadIcon("bookmark_folder", TDEIcon::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) {
+ TQString 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", TDEIcon::Small),
+ i18n("Bookmark Current"), BookmarkCurrent);
+ _specialBookmarkIDs.append( itemIndex );
+ itemIndex = menu->insertItem(krLoader->loadIcon("bookmark", TDEIcon::Small),
+ i18n("Manage Bookmarks"), ManageBookmarks);
+ _specialBookmarkIDs.append( itemIndex );
+
+ // make sure the menu is connected to us
+ disconnect(menu, TQ_SIGNAL(activated(int)), 0, 0);
+ connect(menu, TQ_SIGNAL(activated(int)), this, TQ_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 TQString&, const TQString&) {
+ importFromFile();
+}
+
+bool KrBookmarkHandler::eventFilter( TQObject *obj, TQEvent *ev ) {
+ if (ev->type() == TQEvent::MouseButtonRelease) {
+ switch (static_cast<TQMouseEvent*>(ev)->button()) {
+ case TQt::RightButton:
+ _middleClick = false;
+ if( obj->inherits( "TQPopupMenu" ) ) {
+ int id = static_cast<TQPopupMenu*>(obj)->idAt( static_cast<TQMouseEvent*>(ev)->pos() );
+
+ if( obj == _mainBookmarkPopup && _specialBookmarkIDs.contains( id ) ) {
+ rightClickOnSpecialBookmark();
+ return true;
+ }
+
+ if( _bookmarkIDTable.find( obj ) ) {
+ TQMap<int, KrBookmark*> * table = _bookmarkIDTable[ obj ];
+ if( table && table->count( id ) ) {
+ KrBookmark *bm = (*table)[ id ];
+ rightClicked( static_cast<TQPopupMenu*>(obj), id, bm );
+ return true;
+ }
+ }
+ }
+ case TQt::LeftButton:
+ _middleClick = false;
+ break;
+ case TQt::MidButton:
+ _middleClick = true;
+ break;
+ default:
+ break;
+ }
+ }
+ return TQObject::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 );
+
+ TQPopupMenu 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, TQ_SIGNAL( highlighted( int ) ), &menu, TQ_SLOT( close() ) );
+ connect( _mainBookmarkPopup, TQ_SIGNAL( activated( int ) ), &menu, TQ_SLOT( close() ) );
+
+ int result = menu.exec( TQCursor::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( TQPopupMenu *menu, int /*id*/, KrBookmark * bm ) {
+ TQPopupMenu popup( _mainBookmarkPopup );
+
+ popup.insertItem( krLoader->loadIcon( "document-open", TDEIcon::Panel ), i18n( "Open" ), OPEN_ID );
+ popup.insertItem( krLoader->loadIcon( "tab_new", TDEIcon::Panel ), i18n( "Open in a new tab" ), OPEN_NEW_TAB_ID );
+ popup.insertSeparator();
+ popup.insertItem( krLoader->loadIcon( "edit-delete", TDEIcon::Panel ), i18n( "Delete" ), DELETE_ID );
+
+ connect( menu, TQ_SIGNAL( highlighted( int ) ), &popup, TQ_SLOT( close() ) );
+ connect( menu, TQ_SIGNAL( activated( int ) ), &popup, TQ_SLOT( close() ) );
+
+ int result = popup.exec( TQCursor::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
+// TDEAction and TDEActionCollection.
+void KrBookmarkHandler::slotActivated(const KURL& url) {
+ if (_middleClick)
+ SLOTS->newTab(url);
+ else SLOTS->refresh(url);
+}
+
+
+#include "krbookmarkhandler.moc"
diff --git a/src/app/BookMan/krbookmarkhandler.h b/src/app/BookMan/krbookmarkhandler.h
new file mode 100644
index 0000000..818c3c9
--- /dev/null
+++ b/src/app/BookMan/krbookmarkhandler.h
@@ -0,0 +1,64 @@
+#ifndef KRBOOKMARK_HANDLER_H
+#define KRBOOKMARK_HANDLER_H
+
+#include "krbookmark.h"
+#include <tqobject.h>
+#include <tqguardedptr.h>
+#include <tdepopupmenu.h>
+#include <kurl.h>
+#include <tqptrdict.h>
+#include <tqvaluelist.h>
+#include <tqdom.h>
+#include <tqmap.h>
+
+class TDEActionCollection;
+class KBookmarkManager;
+
+class KrBookmarkHandler: public TQObject {
+ TQ_OBJECT
+
+ friend class KrAddBookmarkDlg;
+ enum Actions { BookmarkCurrent=0, ManageBookmarks };
+public:
+ KrBookmarkHandler();
+ ~KrBookmarkHandler();
+ void populate(TDEPopupMenu *menu);
+ void addBookmark(KrBookmark *bm, KrBookmark *parent = 0);
+ void bookmarkCurrent(KURL url);
+
+protected:
+ void deleteBookmark(KrBookmark *bm);
+ void importFromFile();
+ bool importFromFileBookmark(TQDomElement &e, KrBookmark *parent, TQString path, TQString *errorMsg);
+ bool importFromFileFolder(TQDomNode &first, KrBookmark *parent, TQString path, TQString *errorMsg);
+ void exportToFile();
+ void exportToFileFolder(TQDomDocument &doc, TQDomElement &parent, KrBookmark *folder);
+ void exportToFileBookmark(TQDomDocument &doc, TQDomElement &where, KrBookmark *bm);
+ void clearBookmarks(KrBookmark *root);
+ void buildMenu(KrBookmark *parent, TDEPopupMenu *menu);
+
+ bool eventFilter( TQObject *obj, TQEvent *ev );
+
+ void rightClicked( TQPopupMenu *menu, int id, KrBookmark *bm );
+ void rightClickOnSpecialBookmark();
+
+ void removeReferences( KrBookmark *root, KrBookmark *bmToRemove );
+
+protected slots:
+ void menuOperation(int id);
+ void bookmarksChanged(const TQString&, const TQString&);
+ void slotActivated(const KURL& url);
+
+private:
+ TDEActionCollection *_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
+
+ TQGuardedPtr<TDEPopupMenu> _mainBookmarkPopup; // main bookmark popup menu
+ TQValueList<int> _specialBookmarkIDs; // the ID list of the special bookmarks
+ TQPtrDict<TQMap<int,KrBookmark*> > _bookmarkIDTable; // the IDs of the bookmarks
+};
+
+#endif // KRBOOKMARK_HANDLER_H
diff --git a/src/app/CMakeL10n.txt b/src/app/CMakeL10n.txt
new file mode 100644
index 0000000..086cbe6
--- /dev/null
+++ b/src/app/CMakeL10n.txt
@@ -0,0 +1,3 @@
+##### create translation templates ##############
+
+tde_l10n_create_template( "messages/krusader/" )
diff --git a/src/app/Dialogs/Makefile.am b/src/app/Dialogs/Makefile.am
new file mode 100644
index 0000000..83cc13d
--- /dev/null
+++ b/src/app/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/src/app/Dialogs/checksumdlg.cpp b/src/app/Dialogs/checksumdlg.cpp
new file mode 100644
index 0000000..6e3191d
--- /dev/null
+++ b/src/app/Dialogs/checksumdlg.cpp
@@ -0,0 +1,603 @@
+#include "checksumdlg.h"
+#include "../krusader.h"
+#include <tdelocale.h>
+#include <tqlayout.h>
+#include <tqlabel.h>
+#include <tqcheckbox.h>
+#include <klineedit.h>
+#include <tdelistview.h>
+#include <tqpixmap.h>
+#include <kcursor.h>
+#include <tdemessagebox.h>
+#include <tqfile.h>
+#include <tqtextstream.h>
+#include <tdefiledialog.h>
+#include <tqframe.h>
+#include <kiconloader.h>
+#include <kcombobox.h>
+#include <tqfileinfo.h>
+#include <kurlrequester.h>
+#include "../krservices.h"
+#include <tqptrlist.h>
+#include <tqmap.h>
+#include <tdetempfile.h>
+#include <kstandarddirs.h>
+
+class CS_Tool; // forward
+typedef void PREPARE_PROC_FUNC(TDEProcess& proc, CS_Tool *self, const TQStringList& files,
+ const TQString checksumFile, bool recursive, const TQString& stdoutFileName,
+ const TQString& stderrFileName, const TQString& type);
+typedef TQStringList GET_FAILED_FUNC(const TQStringList& stdOut, const TQStringList& stdErr);
+
+class CS_Tool {
+public:
+ enum Type {
+ MD5=0, SHA1, SHA256, TIGER, WHIRLPOOL, SFV, CRC,
+ SHA224, SHA384, SHA512,
+ NumOfTypes
+ };
+
+ Type type;
+ TQString binary;
+ bool recursive;
+ bool standardFormat;
+ PREPARE_PROC_FUNC *create, *verify;
+ GET_FAILED_FUNC *failed;
+};
+
+class CS_ToolByType {
+public:
+ TQPtrList<CS_Tool> tools, r_tools; // normal and recursive tools
+};
+
+// handles md5sum and sha1sum
+void sumCreateFunc(TDEProcess& proc, CS_Tool *self, const TQStringList& files,
+ const TQString, bool recursive, const TQString& stdoutFileName,
+ const TQString& stderrFileName, const TQString&) {
+ proc.setUseShell(true, "/bin/bash");
+ proc << KrServices::fullPathName( self->binary );
+ Q_ASSERT(!recursive);
+ proc << files << "1>" << stdoutFileName << "2>" << stderrFileName;
+}
+
+void sumVerifyFunc(TDEProcess& proc, CS_Tool *self, const TQStringList& /* files */,
+ const TQString checksumFile, bool recursive, const TQString& stdoutFileName,
+ const TQString& stderrFileName, const TQString& /* type */) {
+ proc.setUseShell(true, "/bin/bash");
+ proc << KrServices::fullPathName( self->binary );
+ Q_ASSERT(!recursive);
+ proc << "-c" << checksumFile << "1>" << stdoutFileName << "2>" << stderrFileName;
+}
+
+TQStringList sumFailedFunc(const TQStringList& stdOut, const TQStringList& 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
+ TQStringList result;
+ if (stdErr.size()==0) return result;
+ result += stdErr;
+ // grep for the ":FAILED" substring
+ const TQString tmp = TQString(": 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(TDEProcess& proc, CS_Tool *self, const TQStringList& files,
+ const TQString, bool recursive, const TQString& stdoutFileName,
+ const TQString& stderrFileName, const TQString&) {
+ proc.setUseShell(true, "/bin/bash");
+ proc << KrServices::fullPathName( self->binary );
+ if (recursive) proc << "-r";
+ proc << "-l" << files << "1>" << stdoutFileName << "2>" << stderrFileName;
+}
+
+void deepVerifyFunc(TDEProcess& proc, CS_Tool *self, const TQStringList& files,
+ const TQString checksumFile, bool recursive, const TQString& stdoutFileName,
+ const TQString& stderrFileName, const TQString&) {
+ proc.setUseShell(true, "/bin/bash");
+ proc << KrServices::fullPathName( self->binary );
+ if (recursive) proc << "-r";
+ proc << "-x" << checksumFile << files << "1>" << stdoutFileName << "2>" << stderrFileName;
+}
+
+TQStringList deepFailedFunc(const TQStringList& stdOut, const TQStringList&/* stdErr */) {
+ // *deep dumps (via -x) all failed hashes to stdout
+ return stdOut;
+}
+
+// handles cfv binary
+void cfvCreateFunc(TDEProcess& proc, CS_Tool *self, const TQStringList& files,
+ const TQString, bool recursive, const TQString& stdoutFileName,
+ const TQString& stderrFileName, const TQString& 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(TDEProcess& proc, CS_Tool *self, const TQStringList& /* files */,
+ const TQString checksumFile, bool recursive, const TQString& stdoutFileName,
+ const TQString& stderrFileName, const TQString&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;
+}
+
+TQStringList cfvFailedFunc(const TQStringList& /* stdOut */, const TQStringList& 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},
+};
+
+TQMap<TQString, CS_Tool::Type> cs_textToType;
+TQMap<CS_Tool::Type, TQString> 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)
+ TQMap<TQString, 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 TQPtrList<CS_Tool> getTools(bool folders) {
+ TQPtrList<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 TQStringList& files, bool containFolders, const TQString& path):
+ KDialogBase(Plain, i18n("Create Checksum"), Ok | Cancel, Ok, krApp) {
+
+ TQPtrList<CS_Tool> tools = getTools(containFolders);
+
+ if (tools.count() == 0) { // nothing was suggested?!
+ TQString 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;
+ }
+
+ TQGridLayout *layout = new TQGridLayout( plainPage(), 1, 1,
+ KDialogBase::marginHint(), KDialogBase::spacingHint());
+
+ int row=0;
+
+ // title (icon+text)
+ TQHBoxLayout *hlayout = new TQHBoxLayout(layout, KDialogBase::spacingHint());
+ TQLabel *p = new TQLabel(plainPage());
+ p->setPixmap(krLoader->loadIcon("application-octet-stream", TDEIcon::Desktop, 32));
+ hlayout->addWidget(p);
+ TQLabel *l1 = new TQLabel(i18n("About to calculate checksum for the following files") +
+ (containFolders ? i18n(" and folders:") : ":"), plainPage());
+ hlayout->addWidget(l1);
+ layout->addMultiCellLayout(hlayout, row, row, 0, 1, TQt::AlignLeft);
+ ++row;
+
+ // file list
+ TDEListBox *lb = new TDEListBox(plainPage());
+ lb->insertStringList(files);
+ layout->addMultiCellWidget(lb, row, row, 0, 1);
+ ++row;
+
+ // checksum method
+ TQHBoxLayout *hlayout2 = new TQHBoxLayout(layout, KDialogBase::spacingHint());
+ TQLabel *l2 = new TQLabel(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, TQt::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" );
+ TDEProcess proc;
+ CS_Tool *mytool = tools.at(method->currentItem());
+ mytool->create(proc, mytool, KrServices::quote(files), TQString(), containFolders,
+ tmpOut->name(), tmpErr->name(), method->currentText());
+
+ krApp->startWaiting(i18n("Calculating checksums ..."), 0, true);
+ TQApplication::setOverrideCursor( KCursor::waitCursor() );
+ bool r = proc.start(TDEProcess::NotifyOnExit, TDEProcess::AllOutput);
+ if (r) while ( proc.isRunning() ) {
+ usleep( 500 );
+ tqApp->processEvents();
+ if (krApp->wasWaitingCancelled()) { // user cancelled
+ proc.kill();
+ TQApplication::restoreOverrideCursor();
+ return;
+ }
+ };
+ krApp->stopWait();
+ TQApplication::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
+ TQString 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
+ TQStringList 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
+
+TQString MatchChecksumDlg::checksumTypesFilter;
+
+MatchChecksumDlg::MatchChecksumDlg(const TQStringList& files, bool containFolders,
+ const TQString& path, const TQString& checksumFile):
+ KDialogBase(Plain, i18n("Verify Checksum"), Ok | Cancel, Ok, krApp) {
+
+ TQPtrList<CS_Tool> tools = getTools(containFolders);
+
+ if (tools.count() == 0) { // nothing was suggested?!
+ TQString 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;
+ }
+
+ TQGridLayout *layout = new TQGridLayout( plainPage(), 1, 1,
+ KDialogBase::marginHint(), KDialogBase::spacingHint());
+
+ int row=0;
+
+ // title (icon+text)
+ TQHBoxLayout *hlayout = new TQHBoxLayout(layout, KDialogBase::spacingHint());
+ TQLabel *p = new TQLabel(plainPage());
+ p->setPixmap(krLoader->loadIcon("application-octet-stream", TDEIcon::Desktop, 32));
+ hlayout->addWidget(p);
+ TQLabel *l1 = new TQLabel(i18n("About to verify checksum for the following files") +
+ (containFolders ? i18n(" and folders:") : ":"), plainPage());
+ hlayout->addWidget(l1);
+ layout->addMultiCellLayout(hlayout, row, row, 0, 1, TQt::AlignLeft);
+ ++row;
+
+ // file list
+ TDEListBox *lb = new TDEListBox(plainPage());
+ lb->insertStringList(files);
+ layout->addMultiCellWidget(lb, row, row, 0, 1);
+ ++row;
+
+ // checksum file
+ TQHBoxLayout *hlayout2 = new TQHBoxLayout(layout, KDialogBase::spacingHint());
+ TQLabel *l2 = new TQLabel(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, TQt::AlignLeft);
+
+ if (exec() != Accepted) return;
+ TQString file = checksumFileReq->url();
+ TQString 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" );
+ TDEProcess proc;
+ mytool->verify(proc, mytool, KrServices::quote(files), KrServices::quote(file), containFolders, tmpOut->name(), tmpErr->name(), extension);
+ krApp->startWaiting(i18n("Verifying checksums ..."), 0, true);
+ TQApplication::setOverrideCursor( KCursor::waitCursor() );
+ bool r = proc.start(TDEProcess::NotifyOnExit, TDEProcess::AllOutput);
+ if (r) while ( proc.isRunning() ) {
+ usleep( 500 );
+ tqApp->processEvents();
+ if (krApp->wasWaitingCancelled()) { // user cancelled
+ proc.kill();
+ TQApplication::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;
+ }
+ TQApplication::restoreOverrideCursor();
+ krApp->stopWait();
+ // send both stdout and stderr
+ TQStringList 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(TQString path, TQString& extension) {
+ TQFileInfo 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 TQStringList& failed):
+ KDialogBase(Plain, i18n("Verify Checksum"), Close, Close, krApp) {
+ TQGridLayout *layout = new TQGridLayout( plainPage(), 1, 1,
+ KDialogBase::marginHint(), KDialogBase::spacingHint());
+
+ bool errors = failed.size()>0;
+ int row = 0;
+
+ // create the icon and title
+ TQHBoxLayout *hlayout = new TQHBoxLayout(layout, KDialogBase::spacingHint());
+ TQLabel p(plainPage());
+ p.setPixmap(krLoader->loadIcon(errors ? "messagebox_critical" : "messagebox_info", TDEIcon::Desktop, 32));
+ hlayout->addWidget(&p);
+
+ TQLabel *l1 = new TQLabel((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, TQt::AlignLeft);
+ ++row;
+
+ if (errors) {
+ TQLabel *l3 = new TQLabel(i18n("The following files have failed:"), plainPage());
+ layout->addMultiCellWidget(l3, row, row, 0, 1);
+ ++row;
+ TDEListBox *lb2 = new TDEListBox(plainPage());
+ lb2->insertStringList(failed);
+ layout->addMultiCellWidget(lb2, row, row, 0, 1);
+ ++row;
+ }
+
+ exec();
+}
+
+// ------------- ChecksumResultsDlg
+
+ChecksumResultsDlg::ChecksumResultsDlg(const TQStringList& stdOut, const TQStringList& stdErr,
+ const TQString& suggestedFilename, const TQString& binary, const TQString& /* type */, bool standardFormat):
+ KDialogBase(Plain, i18n("Create Checksum"), Ok | Cancel, Ok, krApp), _binary(binary) {
+ TQGridLayout *layout = new TQGridLayout( 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
+ TQHBoxLayout *hlayout = new TQHBoxLayout(layout, KDialogBase::spacingHint());
+ TQLabel p(plainPage());
+ p.setPixmap(krLoader->loadIcon(errors ? "messagebox_critical" : "messagebox_info", TDEIcon::Desktop, 32));
+ hlayout->addWidget(&p);
+
+ TQLabel *l1 = new TQLabel((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, TQt::AlignLeft);
+ ++row;
+
+ if (successes) {
+ if (errors) {
+ TQLabel *l2 = new TQLabel(i18n("Here are the calculated checksums:"), plainPage());
+ layout->addMultiCellWidget(l2, row, row, 0, 1);
+ ++row;
+ }
+ TDEListView *lv = new TDEListView(plainPage());
+ if(standardFormat){
+ lv->addColumn(i18n("Hash"));
+ lv->addColumn(i18n("File"));
+ lv->setAllColumnsShowFocus(true);
+ } else {
+ lv->addColumn(i18n("File and hash"));
+ }
+ for ( TQStringList::ConstIterator it = stdOut.begin(); it != stdOut.end(); ++it ) {
+ TQString line = (*it);
+ if(standardFormat) {
+ int space = line.find(' ');
+ new TDEListViewItem(lv, line.left(space), line.mid(space+2));
+ } else {
+ new TDEListViewItem(lv, line);
+ }
+ }
+ layout->addMultiCellWidget(lv, row, row, 0, 1);
+ ++row;
+ }
+
+ if (errors) {
+ TQFrame *line1 = new TQFrame( plainPage() );
+ line1->setGeometry( TQRect( 60, 210, 501, 20 ) );
+ line1->setFrameShape( TQFrame::HLine );
+ line1->setFrameShadow( TQFrame::Sunken );
+ layout->addMultiCellWidget(line1, row, row, 0, 1);
+ ++row;
+
+ TQLabel *l3 = new TQLabel(i18n("Here are the errors received:"), plainPage());
+ layout->addMultiCellWidget(l3, row, row, 0, 1);
+ ++row;
+ TDEListBox *lb = new TDEListBox(plainPage());
+ lb->insertStringList(stdErr);
+ layout->addMultiCellWidget(lb, row, row, 0, 1);
+ ++row;
+ }
+
+ // save checksum to disk, if any hashes are found
+ KURLRequester *checksumFile=0;
+ TQCheckBox *saveFileCb=0;
+ if (successes) {
+ TQHBoxLayout *hlayout2 = new TQHBoxLayout(layout, KDialogBase::spacingHint());
+ saveFileCb = new TQCheckBox(i18n("Save checksum to file:"), plainPage());
+ saveFileCb->setChecked(true);
+ hlayout2->addWidget(saveFileCb);
+
+ checksumFile = new KURLRequester( suggestedFilename, plainPage() );
+ hlayout2->addWidget(checksumFile, TQt::AlignLeft);
+ layout->addMultiCellLayout(hlayout2, row, row,0,1, TQt::AlignLeft);
+ ++row;
+ connect(saveFileCb, TQ_SIGNAL(toggled(bool)), checksumFile, TQ_SLOT(setEnabled(bool)));
+ checksumFile->setFocus();
+ }
+
+ TQCheckBox *onePerFile=0;
+ if (stdOut.size() > 1 && standardFormat) {
+ onePerFile = new TQCheckBox(i18n("Checksum file for each source file"), plainPage());
+ onePerFile->setChecked(false);
+ // clicking this, disables the 'save as' part
+ connect(onePerFile, TQ_SIGNAL(toggled(bool)), saveFileCb, TQ_SLOT(toggle()));
+ connect(onePerFile, TQ_SIGNAL(toggled(bool)), saveFileCb, TQ_SLOT(setDisabled(bool)));
+ connect(onePerFile, TQ_SIGNAL(toggled(bool)), checksumFile, TQ_SLOT(setDisabled(bool)));
+ layout->addMultiCellWidget(onePerFile, row, row,0,1, TQt::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 TQStringList& data, TQString filename) {
+ if (TQFile::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(TQString(), "*", 0, i18n("Select a file to save to"));
+ if (filename.simplifyWhiteSpace().isEmpty()) return false;
+ }
+ TQFile file(filename);
+ if (!file.open(IO_WriteOnly)) {
+ KMessageBox::detailedError(0, i18n("Error saving file %1").arg(filename),
+ file.errorString());
+ return false;
+ }
+ TQTextStream stream(&file);
+ for ( TQStringList::ConstIterator it = data.constBegin(); it != data.constEnd(); ++it)
+ stream << *it << "\n";
+ file.close();
+ return true;
+}
+
+void ChecksumResultsDlg::savePerFile(const TQStringList& data, const TQString& type) {
+ krApp->startWaiting(i18n("Saving checksum files..."), 0);
+ for ( TQStringList::ConstIterator it = data.begin(); it != data.end(); ++it ) {
+ TQString line = (*it);
+ TQString 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/src/app/Dialogs/checksumdlg.h b/src/app/Dialogs/checksumdlg.h
new file mode 100644
index 0000000..a145a35
--- /dev/null
+++ b/src/app/Dialogs/checksumdlg.h
@@ -0,0 +1,54 @@
+#ifndef CHECKSUMDLG_H
+#define CHECKSUMDLG_H
+
+#include <kdialogbase.h>
+#include <tqvaluelist.h>
+
+class KTempFile;
+extern void initChecksumModule();
+
+class CreateChecksumDlg: public KDialogBase {
+public:
+ CreateChecksumDlg(const TQStringList& files, bool containFolders, const TQString& path);
+
+private:
+ KTempFile *tmpOut, *tmpErr;
+};
+
+
+class MatchChecksumDlg: public KDialogBase {
+public:
+ MatchChecksumDlg(const TQStringList& files, bool containFolders,
+ const TQString& path, const TQString& checksumFile=TQString());
+
+ static TQString checksumTypesFilter;
+
+protected:
+ bool verifyChecksumFile(TQString path, TQString& extension);
+
+private:
+ KTempFile *tmpOut, *tmpErr;
+};
+
+
+class ChecksumResultsDlg: public KDialogBase {
+public:
+ ChecksumResultsDlg(const TQStringList& stdOut, const TQStringList& stdErr,
+ const TQString& suggestedFilename, const TQString& binary, const TQString& type,
+ bool standardFormat);
+
+protected:
+ bool saveChecksum(const TQStringList& data, TQString filename);
+ void savePerFile(const TQStringList& data, const TQString& type);
+
+private:
+ TQString _binary;
+};
+
+
+class VerifyResultDlg: public KDialogBase {
+public:
+ VerifyResultDlg(const TQStringList& failed);
+};
+
+#endif // CHECKSUMDLG_H
diff --git a/src/app/Dialogs/krdialogs.cpp b/src/app/Dialogs/krdialogs.cpp
new file mode 100644
index 0000000..d5b2000
--- /dev/null
+++ b/src/app/Dialogs/krdialogs.cpp
@@ -0,0 +1,256 @@
+/***************************************************************************
+ 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"
+// TQt includes
+#include <tqmessagebox.h>
+#include <tqwidget.h>
+#include <tqapplication.h>
+#include <tqfontmetrics.h>
+#include <tqtooltip.h>
+// TDE includes
+#include <tdelocale.h>
+#include <kurlcompletion.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <klineedit.h>
+#include <kurlrequester.h>
+#include <kstandarddirs.h>
+#include <tdeversion.h>
+#include <tqcheckbox.h>
+#include <tderecentdocument.h>
+#include <tqhbox.h>
+// Krusader includes
+#include "../krusader.h"
+#include "../resources.h"
+#include "../VFS/vfs.h"
+#include "../defaults.h"
+#include <tqdir.h>
+
+KURL KChooseDir::getDir(TQString text,const KURL& url, const KURL& cwd) {
+ KURLRequesterDlg *dlg = new KURLRequesterDlg( vfs::pathOrURL( url, 1 ),text,krApp,"");
+ dlg->urlRequester()->completionObject()->setDir(cwd.url());
+ dlg->urlRequester()->setMode(KFile::LocalOnly | KFile::Directory);
+ KURL u;
+ if (dlg->exec() == TQDialog::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( TQDir( u.path() ).exists() )
+ u.setProtocol( "file" );
+ }
+ }
+ }
+ delete dlg;
+ return u;
+}
+
+KURL KChooseDir::getDir(TQString 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() == TQDialog::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( TQDir( u.path() ).exists() )
+ u.setProtocol( "file" );
+ }
+ }
+ }
+ preserveAttrs = dlg->preserveAttrs();
+ delete dlg;
+ return u;
+}
+
+KURL KChooseDir::getDir(TQString 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() == TQDialog::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( TQDir( 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 TQString& urlName, const TQString& _text, bool presAttrs, TQWidget *parent,
+ const char *name, bool modal, KURL baseURL )
+ : KDialogBase( Plain, TQString(), Ok|Cancel|User1, Ok, parent, name, modal, true, KStdGuiItem::clear() ),
+ baseUrlCombo( 0 ), copyDirStructureCB( 0 ) {
+
+ TQVBoxLayout * topLayout = new TQVBoxLayout( plainPage(), 0, spacingHint() );
+
+ TQLabel * label = new TQLabel( _text, plainPage() );
+ topLayout->addWidget( label );
+
+ urlRequester_ = new KURLRequester( urlName, plainPage(), "urlRequester" );
+ urlRequester_->setMinimumWidth( urlRequester_->sizeHint().width() * 3 );
+ topLayout->addWidget( urlRequester_ );
+ preserveAttrsCB = new TQCheckBox(i18n("Preserve attributes (only for local targets)"), plainPage());
+ preserveAttrsCB->setChecked( presAttrs );
+ topLayout->addWidget( preserveAttrsCB );
+ if( !baseURL.isEmpty() ) {
+ TQFrame *line = new TQFrame( plainPage(), "sepLine" );
+ line->setFrameStyle( TQFrame::HLine | TQFrame::Sunken );
+ topLayout->addWidget( line );
+ copyDirStructureCB = new TQCheckBox(i18n("Keep virtual directory structure"), plainPage());
+ connect( copyDirStructureCB, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( slotDirStructCBChanged() ) );
+ copyDirStructureCB->setChecked( false );
+ topLayout->addWidget( copyDirStructureCB );
+ TQHBox * hbox = new TQHBox( plainPage(), "copyDirStructure" );
+ new TQLabel( i18n("Base URL:"), hbox, "baseURLLabel" );
+
+ baseUrlCombo = new TQComboBox( hbox, "baseUrlRequester" );
+ baseUrlCombo->setMinimumWidth( baseUrlCombo->sizeHint().width() * 3 );
+ baseUrlCombo->setEnabled( copyDirStructureCB->isChecked() );
+ KURL temp = baseURL, tempOld;
+ do {
+ TQString 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(), TQ_SIGNAL(textChanged(const TQString&)),
+ TQ_SLOT(slotTextChanged(const TQString&)) );
+ bool state = !urlName.isEmpty();
+ enableButtonOK( state );
+ enableButton( KDialogBase::User1, state );
+ connect( this, TQ_SIGNAL( user1Clicked() ), TQ_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 TQString & 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() == TQDialog::Accepted ) {
+ KURL url = KURL::fromPathOrURL( urlRequester_->url() );
+ if( url.isValid() )
+ TDERecentDocument::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(TQDate date, TQWidget *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, TQ_SIGNAL(dateSelected(TQDate)), this, TQ_SLOT(setDate(TQDate)));
+ connect(dateWidget, TQ_SIGNAL(dateEntered(TQDate)), this, TQ_SLOT(setDate(TQDate)));
+
+ // keep the original date - incase ESC is pressed
+ originalDate = date;
+}
+
+TQDate KRGetDate::getDate() {
+ if (exec() == TQDialog::Rejected) chosenDate.setYMD(0,0,0);
+ hide();
+ return chosenDate;
+}
+
+void KRGetDate::setDate(TQDate date) {
+ chosenDate = date;
+ accept();
+}
+
+#include "krdialogs.moc"
diff --git a/src/app/Dialogs/krdialogs.h b/src/app/Dialogs/krdialogs.h
new file mode 100644
index 0000000..ca447bf
--- /dev/null
+++ b/src/app/Dialogs/krdialogs.h
@@ -0,0 +1,116 @@
+/***************************************************************************
+ 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
+
+// TDE includes
+#include <kdialog.h>
+#include <kanimwidget.h>
+#include <kurlrequesterdlg.h>
+#include <kdatepicker.h>
+#include <kdialogbase.h>
+// TQt includes
+#include <tqlineedit.h>
+#include <tqlayout.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqdatetime.h>
+#include <tqpixmap.h>
+#include <tqprogressdialog.h>
+#include <tqcheckbox.h>
+#include <tqcombobox.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(TQString text,const KURL& url, const KURL& cwd);
+ static KURL getDir(TQString text,const KURL& url, const KURL& cwd, bool & preserveAttrs );
+ static KURL getDir(TQString text,const KURL& url, const KURL& cwd, bool & preserveAttrs, KURL &baseURL );
+};
+
+class KURLRequesterDlgForCopy : public KDialogBase {
+ TQ_OBJECT
+
+public:
+ KURLRequesterDlgForCopy( const TQString& url, const TQString& text, bool presAttrs,
+ TQWidget *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 TQString &);
+ void slotDirStructCBChanged();
+private:
+ KURLRequester *urlRequester_;
+ TQComboBox *baseUrlCombo;
+ TQCheckBox *preserveAttrsCB;
+ TQCheckBox *copyDirStructureCB;
+};
+
+class KRGetDate : public KDialog {
+ TQ_OBJECT
+
+public:
+ KRGetDate(TQDate date=TQDate::currentDate(), TQWidget *parent = 0, const char *name = 0);
+ TQDate getDate();
+
+private slots:
+ void setDate(TQDate);
+
+private:
+ KDatePicker *dateWidget;
+ TQDate chosenDate, originalDate;
+};
+
+#endif
diff --git a/src/app/Dialogs/krkeydialog.cpp b/src/app/Dialogs/krkeydialog.cpp
new file mode 100644
index 0000000..0be43e7
--- /dev/null
+++ b/src/app/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 <tqlayout.h>
+#include <tqwhatsthis.h>
+#include <tdelocale.h>
+#include <kpushbutton.h>
+#include <tdemessagebox.h>
+#include <tdefiledialog.h>
+#include <tdeglobal.h>
+#include <kstandarddirs.h>
+#include <tdeconfig.h>
+#include <tdeactionshortcutlist.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( TQWidget * 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.
+ TQWidget* buttonBox = static_cast<TQWidget*>( actionButton(KDialogBase::Ok)->parent() );
+ TQBoxLayout* buttonBoxLayout = static_cast<TQBoxLayout*>( buttonBox->layout() );
+
+ KPushButton* importButton = new KPushButton( i18n("Import shortcuts"), buttonBox );
+ TQWhatsThis::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, TQ_SIGNAL( clicked() ), TQ_SLOT( slotImportShortcuts() ) );
+
+ KPushButton* exportButton = new KPushButton( i18n("Export shortcuts"), buttonBox );
+ TQWhatsThis::add( exportButton, i18n( "Save current keybindings in a keymap file." ) );
+ buttonBoxLayout->insertWidget( 2, exportButton );
+ connect( exportButton, TQ_SIGNAL( clicked() ), TQ_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 $TDEDIR/share/apps/krusader
+ TQString basedir = TDEGlobal::dirs()->findResourceDir("appdata", "total_commander.keymap");
+ // let the user select a file to load
+ TQString filename = KFileDialog::getOpenFileName(basedir, i18n(FILE_FILTER), 0, i18n("Select a keymap file"));
+ if ( filename.isEmpty() )
+ return;
+
+ TDEConfig 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 TQString& 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
+ TQFile info(file+".info");
+ if (info.open(IO_ReadOnly)) {
+ TQTextStream stream(&info);
+ TQStringList infoText = TQStringList::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
+ TQFile f(file);
+ if (!f.open(IO_ReadOnly)) {
+ krOut << "Error opening " << file << endl;
+ return;
+ }
+ char *actionName;
+ TQDataStream stream(&f);
+ int key;
+ TDEAction *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() {
+ TQString filename = KFileDialog::getSaveFileName( TQString(), i18n(FILE_FILTER), 0, i18n("Select a keymap file") );
+ if ( filename.isEmpty() )
+ return;
+ TQFile 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 TDEConfig'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;
+ }
+
+ TDEConfig 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 );
+ TDEActionShortcutList list( krApp->actionCollection() );
+ list.writeSettings( "Shortcuts", &conf, true /* write all actions */ );
+ // That does TDEActionShortcutList::writeSettings for us
+ //conf.sync(); // write back all changes
+}
+
+#include "krkeydialog.moc"
diff --git a/src/app/Dialogs/krkeydialog.h b/src/app/Dialogs/krkeydialog.h
new file mode 100644
index 0000000..082ac0a
--- /dev/null
+++ b/src/app/Dialogs/krkeydialog.h
@@ -0,0 +1,38 @@
+//
+// 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
+{
+TQ_OBJECT
+
+public:
+ KrKeyDialog( TQWidget* parent = 0 );
+ ~KrKeyDialog();
+
+private slots:
+ void slotImportShortcuts();
+ void slotExportShortcuts();
+
+private:
+ void importLegacyShortcuts( const TQString& file );
+ KKeyChooser* _chooser;
+};
+
+#endif
diff --git a/src/app/Dialogs/krmaskchoice.cpp b/src/app/Dialogs/krmaskchoice.cpp
new file mode 100644
index 0000000..159cbf9
--- /dev/null
+++ b/src/app/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 <tqcombobox.h>
+#include <tqgroupbox.h>
+#include <tqlabel.h>
+#include <tqlistbox.h>
+#include <tqpushbutton.h>
+#include <tqlayout.h>
+#include <tqvariant.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+#include <tqmessagebox.h>
+#include <tdelocale.h>
+#include <tqlineedit.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( TQWidget* parent, const char* name, bool modal, WFlags fl )
+ : TQDialog( parent, name, modal, fl )
+{
+ if ( !name )
+ setName( "KRMaskChoice" );
+ resize( 401, 314 );
+ setCaption( i18n( "Choose Files" ) );
+ setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)5, (TQSizePolicy::SizeType)5 ) );
+
+ selection = new TQComboBox( false, this, "selection" );
+ int height = TQFontMetrics( selection->font() ).height();
+ height = height + 5*(height > 14) + 6;
+ selection->setGeometry( TQRect( 12, 48, 377, height) );
+ selection->setEditable( true );
+ selection->setInsertionPolicy( TQComboBox::AtTop );
+ selection->setAutoCompletion( true );
+
+ TQWidget* Layout7 = new TQWidget( this, "Layout7" );
+ Layout7->setGeometry( TQRect( 10, 10, 380, 30 ) );
+ hbox = new TQHBoxLayout( Layout7 );
+ hbox->setSpacing( 6 );
+ hbox->setMargin( 0 );
+
+ PixmapLabel1 = new TQLabel( Layout7, "PixmapLabel1" );
+ PixmapLabel1->setScaledContents( true );
+ PixmapLabel1->setMaximumSize( TQSize( 31, 31 ) );
+ // now, add space for the pixmap
+ hbox->addWidget( PixmapLabel1 );
+
+ label = new TQLabel( Layout7, "label" );
+ label->setText( i18n( "Select the following files:" ) );
+ hbox->addWidget( label );
+
+ GroupBox1 = new TQGroupBox( this, "GroupBox1" );
+ GroupBox1->setGeometry( TQRect( 11, 77, 379, 190 ) );
+ GroupBox1->setTitle( i18n( "Predefined Selections" ) );
+
+ TQWidget* Layout6 = new TQWidget( GroupBox1, "Layout6" );
+ Layout6->setGeometry( TQRect( 10, 20, 360, 160 ) );
+ hbox_2 = new TQHBoxLayout( Layout6 );
+ hbox_2->setSpacing( 6 );
+ hbox_2->setMargin( 0 );
+
+ preSelections = new TQListBox( Layout6, "preSelections" );
+ preSelections->setVScrollBarMode( TQListBox::AlwaysOn );
+ TQWhatsThis::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 TQVBoxLayout;
+ vbox->setSpacing( 6 );
+ vbox->setMargin( 0 );
+
+ PushButton7 = new TQPushButton( Layout6, "PushButton7" );
+ PushButton7->setText( i18n( "Add" ) );
+ TQToolTip::add( PushButton7, i18n( "Adds the selection in the line-edit to the list" ) );
+ vbox->addWidget( PushButton7 );
+
+ PushButton7_2 = new TQPushButton( Layout6, "PushButton7_2" );
+ PushButton7_2->setText( i18n( "Delete" ) );
+ TQToolTip::add( PushButton7_2, i18n( "Delete the marked selection from the list" ) );
+ vbox->addWidget( PushButton7_2 );
+
+ PushButton7_3 = new TQPushButton( Layout6, "PushButton7_3" );
+ PushButton7_3->setText( i18n( "Clear" ) );
+ TQToolTip::add( PushButton7_3, i18n( "Clears the entire list of selections" ) );
+ vbox->addWidget( PushButton7_3 );
+ TQSpacerItem* spacer = new TQSpacerItem( 20, 54, TQSizePolicy::Fixed, TQSizePolicy::Expanding );
+ vbox->addItem( spacer );
+ hbox_2->addLayout( vbox );
+
+ TQWidget* Layout18 = new TQWidget( this, "Layout18" );
+ Layout18->setGeometry( TQRect( 10, 280, 379, 30 ) );
+ hbox_3 = new TQHBoxLayout( Layout18 );
+ hbox_3->setSpacing( 6 );
+ hbox_3->setMargin( 0 );
+ TQSpacerItem* spacer_2 = new TQSpacerItem( 205, 20, TQSizePolicy::Expanding, TQSizePolicy::Fixed );
+ hbox_3->addItem( spacer_2 );
+
+ PushButton3 = new TQPushButton( Layout18, "PushButton3" );
+ PushButton3->setText( i18n( "OK" ) );
+ hbox_3->addWidget( PushButton3 );
+
+ PushButton3_2 = new TQPushButton( Layout18, "PushButton3_2" );
+ PushButton3_2->setText( i18n( "Cancel" ) );
+ hbox_3->addWidget( PushButton3_2 );
+
+ // signals and slots connections
+ connect( PushButton3_2, TQ_SIGNAL( clicked() ), this, TQ_SLOT( reject() ) );
+ connect( PushButton3, TQ_SIGNAL( clicked() ), this, TQ_SLOT( accept() ) );
+ connect( PushButton7, TQ_SIGNAL( clicked() ), this, TQ_SLOT( addSelection() ) );
+ connect( PushButton7_2, TQ_SIGNAL( clicked() ), this, TQ_SLOT( deleteSelection() ) );
+ connect( PushButton7_3, TQ_SIGNAL( clicked() ), this, TQ_SLOT( clearSelections() ) );
+ connect( selection, TQ_SIGNAL( activated(const TQString&) ), selection, TQ_SLOT( setEditText(const TQString &) ) );
+ connect( selection->lineEdit(), TQ_SIGNAL( returnPressed() ), this, TQ_SLOT( accept() ));
+ connect( preSelections, TQ_SIGNAL( doubleClicked(TQListBoxItem*) ), this, TQ_SLOT( acceptFromList(TQListBoxItem *) ) );
+ connect( preSelections, TQ_SIGNAL( highlighted(const TQString&) ), selection, TQ_SLOT( setEditText(const TQString &) ) );
+ connect( preSelections, TQ_SIGNAL( returnPressed(TQListBoxItem*) ), this, TQ_SLOT( acceptFromList(TQListBoxItem *) ) );
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+KRMaskChoice::~KRMaskChoice()
+{
+ // no need to delete child widgets, TQt does it all for us
+}
+
+void KRMaskChoice::addSelection()
+{
+ tqWarning( "KRMaskChoice::addSelection(): Not implemented yet!" );
+}
+
+void KRMaskChoice::clearSelections()
+{
+ tqWarning( "KRMaskChoice::clearSelections(): Not implemented yet!" );
+}
+
+void KRMaskChoice::deleteSelection()
+{
+ tqWarning( "KRMaskChoice::deleteSelection(): Not implemented yet!" );
+}
+
+void KRMaskChoice::acceptFromList(TQListBoxItem *)
+{
+ tqWarning( "KRMaskChoice::acceptFromList(TQListBoxItem *): Not implemented yet!" );
+}
+
+#include "krmaskchoice.moc"
diff --git a/src/app/Dialogs/krmaskchoice.h b/src/app/Dialogs/krmaskchoice.h
new file mode 100644
index 0000000..a4324da
--- /dev/null
+++ b/src/app/Dialogs/krmaskchoice.h
@@ -0,0 +1,77 @@
+/***************************************************************************
+ 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 <tqdialog.h>
+class TQVBoxLayout;
+class TQHBoxLayout;
+class TQGridLayout;
+class TQComboBox;
+class TQGroupBox;
+class TQLabel;
+class TQListBox;
+class TQListBoxItem;
+class TQPushButton;
+
+class KRMaskChoice : public TQDialog
+{
+ TQ_OBJECT
+
+
+public:
+ KRMaskChoice( TQWidget* parent = 0, const char* name = 0, bool modal = false, WFlags fl = 0 );
+ ~KRMaskChoice();
+
+ TQComboBox* selection;
+ TQLabel* PixmapLabel1;
+ TQLabel* label;
+ TQGroupBox* GroupBox1;
+ TQListBox* preSelections;
+ TQPushButton* PushButton7;
+ TQPushButton* PushButton7_2;
+ TQPushButton* PushButton7_3;
+ TQPushButton* PushButton3;
+ TQPushButton* PushButton3_2;
+
+public slots:
+ virtual void addSelection();
+ virtual void clearSelections();
+ virtual void deleteSelection();
+ virtual void acceptFromList(TQListBoxItem *);
+
+protected:
+ TQHBoxLayout* hbox;
+ TQHBoxLayout* hbox_2;
+ TQHBoxLayout* hbox_3;
+ TQVBoxLayout* vbox;
+};
+
+#endif // KRMASKCHOICE_H
diff --git a/src/app/Dialogs/krpleasewait.cpp b/src/app/Dialogs/krpleasewait.cpp
new file mode 100644
index 0000000..55521f7
--- /dev/null
+++ b/src/app/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 <tqtimer.h>
+#include <tqdatetime.h>
+#include <tqapplication.h>
+#include <tqpushbutton.h>
+#include <unistd.h>
+#include "../krusader.h"
+#include "tdelocale.h"
+#include <kcursor.h>
+
+KRPleaseWait::KRPleaseWait( TQString msg, int count, bool cancel ):
+ TQProgressDialog( cancel ? 0 : krApp,0, !cancel) , inc(true) {
+
+ timer = new TQTimer(this);
+ setCaption( i18n( "Krusader::Wait" ) );
+
+ setMinimumDuration(500);
+ setAutoClose(false);
+ setAutoReset(false);
+
+ connect( timer,TQ_SIGNAL(timeout()), this, TQ_SLOT(cycleProgress()));
+
+ TQProgressBar* progress = new TQProgressBar(count,this);
+ progress->setCenterIndicator(true);
+ setBar(progress);
+
+ TQLabel* label = new TQLabel(this);
+ setLabel(label);
+
+ TQPushButton* btn = new TQPushButton(i18n("&Cancel"),this);
+ setCancelButton(btn);
+
+ btn->setEnabled(canClose = cancel);
+ setLabelText(msg);
+
+ show();
+}
+
+void KRPleaseWait::closeEvent ( TQCloseEvent * 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() : TQObject(), 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( TQString msg, int count , bool cancel){
+ if ( dlg == 0 ){
+ dlg = new KRPleaseWait( msg , count, cancel);
+ connect( dlg,TQ_SIGNAL(cancelled()),this,TQ_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) TQTimer::singleShot(2000,this,TQ_SLOT(cycleProgress()));
+ cycleMutex=false;
+}
+
+void KRPleaseWaitHandler::killJob(){
+ if( !job.isNull() ) job->kill(false);
+ stopWait();
+ _wasCancelled = true;
+}
+
+void KRPleaseWaitHandler::setJob(TDEIO::Job* j){ job=j; }
+
+void KRPleaseWaitHandler::incProgress(int i){
+ if (incMutex) return;
+ incMutex=true;
+ if(dlg) dlg->incProgress(i);
+ incMutex=false;
+}
+
+void KRPleaseWaitHandler::incProgress( TDEProcess *, 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/src/app/Dialogs/krpleasewait.h b/src/app/Dialogs/krpleasewait.h
new file mode 100644
index 0000000..246ef3c
--- /dev/null
+++ b/src/app/Dialogs/krpleasewait.h
@@ -0,0 +1,84 @@
+/***************************************************************************
+ 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 <tqprogressdialog.h>
+#include <tqtimer.h>
+#include <tqguardedptr.h>
+#include <tdeio/jobclasses.h>
+
+class TDEProcess;
+class KRPleaseWait;
+
+class KRPleaseWaitHandler : public TQObject {
+ TQ_OBJECT
+
+
+public:
+ KRPleaseWaitHandler();
+
+public slots:
+
+ void startWaiting(TQString msg, int count = 0, bool cancel = false);
+ void stopWait();
+ void cycleProgress();
+ void incProgress(int i);
+ void incProgress( TDEProcess *, char *buffer, int buflen );
+ void killJob();
+ void setJob(TDEIO::Job* j);
+ bool wasCancelled() const { return _wasCancelled; }
+
+private:
+ TQGuardedPtr<TDEIO::Job> job;
+ KRPleaseWait * dlg;
+ bool cycle, cycleMutex, incMutex, _wasCancelled;
+};
+
+
+class KRPleaseWait : public TQProgressDialog {
+ TQ_OBJECT
+
+public:
+ KRPleaseWait( TQString msg, int count = 0 ,bool cancel = false );
+
+public slots:
+ void incProgress(int howMuch);
+ void cycleProgress();
+
+protected:
+ bool inc;
+ TQTimer* timer;
+ virtual void closeEvent ( TQCloseEvent * e );
+ bool canClose;
+};
+
+#endif
diff --git a/src/app/Dialogs/krprogress.cpp b/src/app/Dialogs/krprogress.cpp
new file mode 100644
index 0000000..1d489d5
--- /dev/null
+++ b/src/app/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 <tqtimer.h>
+#include <tqlayout.h>
+#include <tqtooltip.h>
+#include <tqdatetime.h>
+
+#include <tdeapplication.h>
+#include <kdialog.h>
+#include <kstringhandler.h>
+#include <tdeglobal.h>
+#include <tdelocale.h>
+#include <kiconloader.h>
+#include <kpushbutton.h>
+#include <kstdguiitem.h>
+#include <twin.h>
+
+#include <tdeio/jobclasses.h>
+
+#include "krprogress.h"
+#include "../krusader.h"
+
+KrProgress::KrProgress( TDEIO::Job* job )
+ : ProgressBase( krApp ),
+ m_iTotalSize(0), m_iTotalFiles(0), m_iTotalDirs(0),
+ m_iProcessedSize(0), m_iProcessedDirs(0), m_iProcessedFiles(0){
+
+#ifdef TQ_WS_X11 //FIXME(E): Remove once all the KWin::foo calls have been ported to TQWS
+ // Set a useful icon for this window!
+ KWin::setIcons( winId(),
+ TDEGlobal::iconLoader()->loadIcon( "document-save", TDEIcon::NoGroup, 32 ),
+ TDEGlobal::iconLoader()->loadIcon( "document-save", TDEIcon::NoGroup, 16 ) );
+#endif
+
+ TQVBoxLayout *topLayout = new TQVBoxLayout( this, KDialog::marginHint(),
+ KDialog::spacingHint() );
+ topLayout->addStrut( 360 ); // makes dlg at least that wide
+
+ TQGridLayout *grid = new TQGridLayout( 2, 3 );
+ topLayout->addLayout(grid);
+ grid->addColSpacing(1, KDialog::spacingHint());
+ // filenames or action name
+ grid->addWidget(new TQLabel(i18n("Source:"), this), 0, 0);
+
+ sourceLabel = new KSqueezedTextLabel(this);
+ grid->addWidget(sourceLabel, 0, 2);
+
+ destInvite = new TQLabel(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
+ TQHBoxLayout *hBox = new TQHBoxLayout();
+ topLayout->addLayout(hBox);
+
+ sizeLabel = new TQLabel(this);
+ hBox->addWidget(sizeLabel);
+
+ resumeLabel = new TQLabel(this);
+ hBox->addWidget(resumeLabel);
+
+ progressLabel = new TQLabel( this );
+/* progressLabel->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding,
+ TQSizePolicy::Preferred ) );*/
+ progressLabel->setAlignment( TQLabel::AlignRight );
+ hBox->addWidget( progressLabel );
+
+ hBox = new TQHBoxLayout();
+ topLayout->addLayout(hBox);
+
+ speedLabel = new TQLabel(this);
+ hBox->addWidget(speedLabel, 1);
+
+ TQFrame *line = new TQFrame( this );
+ line->setFrameShape( TQFrame::HLine );
+ line->setFrameShadow( TQFrame::Sunken );
+ topLayout->addWidget( line );
+
+ hBox = new TQHBoxLayout();
+ topLayout->addLayout(hBox);
+
+ hBox->addStretch(1);
+
+ KPushButton *pb = new KPushButton( KStdGuiItem::cancel(), this );
+ connect( pb, TQ_SIGNAL( clicked() ), TQ_SLOT( slotStop() ) );
+ hBox->addWidget( pb );
+
+ resize( sizeHint() );
+ setMaximumHeight(sizeHint().height());
+
+ setCaption(i18n("Krusader Progress")); // show something better than tdeio_uiserver
+
+ setJob(job);
+ setOnlyClean(false);
+ setStopOnClose(true);
+ // Connect global progress info signals
+ connect( job, TQ_SIGNAL( percent( TDEIO::Job*, unsigned long ) ),
+ TQ_SLOT( slotPercent( TDEIO::Job*, unsigned long ) ) );
+ connect( job, TQ_SIGNAL( infoMessage( TDEIO::Job*, const TQString & ) ),
+ TQ_SLOT( slotInfoMessage( TDEIO::Job*, const TQString & ) ) );
+ connect( job, TQ_SIGNAL( totalSize( TDEIO::Job*, TDEIO::filesize_t ) ),
+ TQ_SLOT( slotTotalSize( TDEIO::Job*, TDEIO::filesize_t ) ) );
+ connect( job, TQ_SIGNAL( processedSize( TDEIO::Job*, TDEIO::filesize_t ) ),
+ TQ_SLOT( slotProcessedSize( TDEIO::Job*, TDEIO::filesize_t ) ) );
+ connect( job, TQ_SIGNAL( speed( TDEIO::Job*, unsigned long ) ),
+ TQ_SLOT( slotSpeed( TDEIO::Job*, unsigned long ) ) );
+
+ // change to modal & move to Krusader's center
+ TQPoint 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( TDEIO::Job*, TDEIO::filesize_t bytes ){
+ m_iTotalSize = bytes;
+}
+
+
+void KrProgress::slotTotalFiles( TDEIO::Job*, unsigned long files ){
+ m_iTotalFiles = files;
+ showTotals();
+}
+
+
+void KrProgress::slotTotalDirs( TDEIO::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 )
+ {
+ TQString 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( TDEIO::Job*, unsigned long percent ){
+ TQString tmp(i18n( "%1% of %2 ").arg( percent ).arg( TDEIO::convertSize(m_iTotalSize)));
+ m_pProgressBar->setValue( percent );
+ tmp.append(i18n(" (Reading)"));
+
+ setCaption( tmp );
+}
+
+
+void KrProgress::slotInfoMessage( TDEIO::Job*, const TQString & msg )
+{
+ speedLabel->setText( msg );
+ speedLabel->setAlignment( speedLabel->alignment() & ~TQt::WordBreak );
+}
+
+
+void KrProgress::slotProcessedSize( TDEIO::Job*, TDEIO::filesize_t bytes ) {
+ m_iProcessedSize = bytes;
+
+ TQString tmp;
+ tmp = i18n( "%1 of %2 complete").arg( TDEIO::convertSize(bytes) ).arg( TDEIO::convertSize(m_iTotalSize));
+ sizeLabel->setText( tmp );
+}
+
+
+void KrProgress::slotProcessedDirs( TDEIO::Job*, unsigned long dirs )
+{
+ m_iProcessedDirs = dirs;
+
+ TQString 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( TDEIO::Job*, unsigned long files )
+{
+ m_iProcessedFiles = files;
+
+ TQString 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( TDEIO::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 = TDEIO::calculateRemainingSeconds( m_iTotalSize, m_iProcessedSize, bytes_per_second );
+ TQString remaining = TDEIO::convertSeconds(seconds);
+#else
+ TQString remaining = TDEIO::calculateRemaining( m_iTotalSize, m_iProcessedSize, bytes_per_second ).toString();
+#endif
+ speedLabel->setText( i18n( "%1/s ( %2 remaining )").arg( TDEIO::convertSize( bytes_per_second )).arg( remaining ) );
+ }
+}
+
+
+void KrProgress::setDestVisible( bool visible )
+{
+ // We can't hide the destInvite/destLabel labels,
+ // because it screws up the TQGridLayout.
+ if (visible)
+ {
+ destInvite->setText( i18n("Destination:") );
+ }
+ else
+ {
+ destInvite->setText( TQString() );
+ destLabel->setText( TQString() );
+ }
+}
+
+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( TQCloseEvent* ) { hide(); slotStop(); }
+
+#include "krprogress.moc"
diff --git a/src/app/Dialogs/krprogress.h b/src/app/Dialogs/krprogress.h
new file mode 100644
index 0000000..70196df
--- /dev/null
+++ b/src/app/Dialogs/krprogress.h
@@ -0,0 +1,87 @@
+/* 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 <tqlabel.h>
+
+#include <tdeio/global.h>
+
+#include <kprogress.h>
+#include <ksqueezedtextlabel.h>
+
+#include <tdeio/progressbase.h>
+
+#include <tqobject.h>
+
+class KrProgress : public TDEIO::ProgressBase {
+ TQ_OBJECT
+
+public:
+
+ KrProgress(TDEIO::Job* job);
+ virtual ~KrProgress();
+
+public slots:
+ virtual void slotTotalSize( TDEIO::Job*, TDEIO::filesize_t bytes );
+ virtual void slotTotalFiles( TDEIO::Job*, unsigned long files );
+ virtual void slotTotalDirs( TDEIO::Job*, unsigned long dirs );
+
+ virtual void slotProcessedSize( TDEIO::Job*, TDEIO::filesize_t bytes );
+ virtual void slotProcessedFiles( TDEIO::Job*, unsigned long files );
+ virtual void slotProcessedDirs( TDEIO::Job*, unsigned long dirs );
+
+ virtual void slotSpeed( TDEIO::Job*, unsigned long bytes_per_second );
+ virtual void slotPercent( TDEIO::Job*, unsigned long percent );
+ virtual void slotInfoMessage( TDEIO::Job*, const TQString & msg );
+
+ virtual void slotStop();
+ virtual void closeEvent( TQCloseEvent* );
+
+protected:
+ void showTotals();
+ void setDestVisible( bool visible );
+
+ KSqueezedTextLabel* sourceLabel;
+ KSqueezedTextLabel* destLabel;
+ TQLabel* progressLabel;
+ TQLabel* destInvite;
+ TQLabel* speedLabel;
+ TQLabel* sizeLabel;
+ TQLabel* resumeLabel;
+
+ KProgress* m_pProgressBar;
+
+ TDEIO::filesize_t m_iTotalSize;
+ unsigned long m_iTotalFiles;
+ unsigned long m_iTotalDirs;
+
+ TDEIO::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/src/app/Dialogs/krspecialwidgets.cpp b/src/app/Dialogs/krspecialwidgets.cpp
new file mode 100644
index 0000000..ecc5e28
--- /dev/null
+++ b/src/app/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 <tdefileitem.h>
+#include <tdelocale.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))
+
+TQColor KRPie::colors[ 12 ] = {TQt::red, TQt::blue, TQt::green, TQt::cyan, TQt::magenta, TQt::gray,
+ TQt::black, TQt::white, TQt::darkRed, TQt::darkBlue, TQt::darkMagenta,
+ TQt::darkCyan};
+
+//////////////////////////////////////////////////////////////////////////////
+/////////////// KRFSDisplay - Filesystem / Freespace Display /////////////////
+//////////////////////////////////////////////////////////////////////////////
+// This is the full constructor: use it for a mounted filesystem
+KRFSDisplay::KRFSDisplay( TQWidget *parent, TQString _alias, TQString _realName,
+ TDEIO::filesize_t _total, TDEIO::filesize_t _free ) : TQWidget( 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( TQWidget *parent, TQString _alias, TQString _realName, bool sm ) :
+ TQWidget( 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( TQWidget *parent ) : TQWidget( parent ), empty( true ) {
+ resize( 150, 200 );
+ show();
+}
+
+
+// The main painter!
+void KRFSDisplay::paintEvent( TQPaintEvent * ) {
+ TQPainter paint( this );
+ if ( !empty ) {
+ // create the text
+ // first, name and location
+ paint.setFont( TQFont( "helvetica", 12, TQFont::Bold ) );
+ paint.drawText( 10, 20, alias );
+ paint.setFont( TQFont( "helvetica", 12, TQFont::Normal ) );
+ paint.drawText( 10, 37, "(" + realName + ")" );
+ if ( mounted ) { // incase the filesystem is already mounted
+ // second, the capacity
+ paint.drawText( 10, 70, i18n( "Capacity: " ) + TDEIO::convertSizeFromKB( totalSpace ) );
+ // third, the 2 boxes (used, free)
+ TQPen systemPen = paint.pen();
+ paint.setPen( TQt::black );
+ paint.drawRect( 10, 90, 10, 10 );
+ paint.fillRect( 11, 91, 8, 8, TQBrush( TQt::gray ) );
+ paint.drawRect( 10, 110, 10, 10 );
+ paint.fillRect( 11, 111, 8, 8, TQBrush( TQt::white ) );
+ // now, the text for the boxes
+ paint.setPen( systemPen );
+ paint.drawText( 25, 100, i18n( "Used: " ) + TDEIO::convertSizeFromKB( totalSpace - freeSpace ) );
+ paint.drawText( 25, 120, i18n( "Free: " ) + TDEIO::convertSizeFromKB( freeSpace ) );
+ // first, create the empty pie
+ // bottom...
+ paint.setPen( TQt::black );
+ paint.setBrush( TQt::white );
+ paint.drawPie( LEFT, BOTTOM, WIDTH, HEIGHT, STARTANGLE, DEG( 360 ) );
+ // body...
+ paint.setPen( TQt::lightGray );
+ for ( int i = 1; i < Z_HEIGHT; ++i )
+ paint.drawPie( LEFT, BOTTOM - i, WIDTH, HEIGHT, STARTANGLE, DEG( 360 ) );
+ // side lines...
+ paint.setPen( TQt::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( TQt::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( TQFont( "helvetica", 12, TQFont::Bold ) );
+ paint.drawText( 10, 60, i18n( "Not mounted." ) );
+ }
+ } else { // if the widget is in empty situation...
+
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+KRPie::KRPie( TDEIO::filesize_t _totalSize, TQWidget *parent ) : TQWidget( parent, 0 ), totalSize( _totalSize ) {
+ slices.setAutoDelete( true ); // kill items when they are removed
+ slices.append( new KRPieSlice( 100, TQt::yellow, "DEFAULT" ) );
+ sizeLeft = totalSize;
+ resize( 300, 300 );
+}
+
+void KRPie::paintEvent( TQPaintEvent * ) {
+ TQPainter 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( TQt::yellow ); // pen
+ paint.setBrush( TQt::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( TQt::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( TQt::black );
+ paint.drawArc( LEFT, BOTTOM, WIDTH, HEIGHT, STARTANGLE, 360 * 16 );
+
+}
+
+void KRPie::addSlice( TDEIO::filesize_t size, TQString 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, TQt::yellow, "DEFAULT" ) );
+}
+
+////////////////////////////////////////////////////
+/////////////////// KrQuickSearch /////////////////
+////////////////////////////////////////////////////
+KrQuickSearch::KrQuickSearch( TQWidget *parent, const char * name ) : KLineEdit( parent, name ) {}
+
+void KrQuickSearch::myKeyPressEvent( TQKeyEvent *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/src/app/Dialogs/krspecialwidgets.h b/src/app/Dialogs/krspecialwidgets.h
new file mode 100644
index 0000000..bcb8d0f
--- /dev/null
+++ b/src/app/Dialogs/krspecialwidgets.h
@@ -0,0 +1,129 @@
+/***************************************************************************
+ 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 <tqwidget.h>
+#include <tqpainter.h>
+#include <tqcolor.h>
+#include <tqptrlist.h>
+#include <klineedit.h>
+#include <tqevent.h>
+#include <tdeio/global.h>
+
+class KRPieSlice;
+
+class KRPie : public TQWidget {
+ TQ_OBJECT
+
+ public:
+ KRPie( TDEIO::filesize_t _totalSize, TQWidget *parent = 0 );
+ void addSlice( TDEIO::filesize_t size, TQString label );
+
+ protected:
+ void paintEvent( TQPaintEvent * );
+
+ private:
+ TQPtrList<KRPieSlice> slices;
+ TDEIO::filesize_t totalSize, sizeLeft;
+ static TQColor colors[ 12 ];
+};
+
+class KRFSDisplay : public TQWidget {
+ TQ_OBJECT
+
+ public:
+ // this constructor is used for a mounted filesystem
+ KRFSDisplay( TQWidget *parent, TQString _alias, TQString _realName,
+ TDEIO::filesize_t _total, TDEIO::filesize_t _free );
+ // this one is for an unmounted/supermount file system
+ KRFSDisplay( TQWidget *parent, TQString _alias, TQString _realName, bool sm = false );
+ // the last one is used inside MountMan(R), when no filesystem is selected
+ KRFSDisplay( TQWidget *parent );
+ inline void setTotalSpace( TDEIO::filesize_t t ) { totalSpace = t; }
+ inline void setFreeSpace( TDEIO::filesize_t t ) { freeSpace = t; }
+ inline void setAlias( TQString a ) { alias = a; }
+ inline void setRealName( TQString 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( TQPaintEvent * );
+
+ private:
+ TDEIO::filesize_t totalSpace, freeSpace;
+ TQString alias, realName;
+ bool mounted, empty, supermount;
+};
+
+class KRPieSlice {
+ public:
+ KRPieSlice( float _perct, TQColor _color, TQString _label ) :
+ perct( _perct ), color( _color ), label( _label ) {}
+ inline TQColor getColor() { return color; }
+ inline float getPerct() { return perct; }
+ inline TQString getLabel() { return label; }
+ inline void setPerct( float _perct ) { perct = _perct; }
+ inline void setLabel( TQString _label ) { label = _label; }
+
+ private:
+ float perct;
+ TQColor color;
+ TQString label;
+};
+
+class KrQuickSearch: public KLineEdit {
+ TQ_OBJECT
+
+ public:
+ KrQuickSearch(TQWidget *parent, const char * name = 0);
+ void addText(const TQString &str) { setText(text()+str); }
+ void myKeyPressEvent(TQKeyEvent *e);
+ void myIMStartEvent(TQIMEvent* e) {
+ imStartEvent(e);
+ }
+ void myIMEndEvent(TQIMEvent* e) {
+ imEndEvent(e);
+ }
+ void myIMComposeEvent(TQIMEvent* e) {
+ imComposeEvent(e);
+ }
+
+ signals:
+ void stop(TQKeyEvent *e);
+ void process(TQKeyEvent *e);
+ void otherMatching(const TQString &, int);
+
+};
+
+#endif
diff --git a/src/app/Dialogs/krspwidgets.cpp b/src/app/Dialogs/krspwidgets.cpp
new file mode 100644
index 0000000..b0fcf5d
--- /dev/null
+++ b/src/app/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 <tqcombobox.h>
+#include <tqlabel.h>
+#include <tqlineedit.h>
+#include <tqcheckbox.h>
+#include <tqlistbox.h>
+#include <tqspinbox.h>
+#include <tdelocale.h>
+#include <kcombobox.h>
+#include <kiconloader.h>
+#include <kcursor.h>
+#include <tqbitmap.h>
+#include "../resources.h"
+
+///////////////////// initiation of the static members ////////////////////////
+TQStrList KRSpWidgets::maskList;
+
+///////////////////////////////////////////////////////////////////////////////
+
+KRSpWidgets::KRSpWidgets(){
+}
+
+KRQuery KRSpWidgets::getMask(TQString 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;
+
+ TQString protocol = p->prefix->currentText();
+ protocol.truncate(protocol.length() - 3); // remove the trailing ://
+ TQString username = p->username->text().simplifyWhiteSpace();
+ TQString password = p->password->text().simplifyWhiteSpace();
+ TQString uri = p->url->currentText();
+
+ int uriStart = uri.findRev( '@' ); /* lets the user enter user and password in the URI field */
+ if( uriStart != -1 ) {
+ TQString uriUser = uri.left( uriStart );
+ TQString uriPsw = TQString();
+ 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;
+ }
+
+ TQString host = uri; /* separating the hostname and path from the uri */
+ TQString path = TQString();
+ 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");
+ TQStringList 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", TDEIcon::Desktop, 32));
+ label->setText(i18n("Enter a selection:"));
+ // the predefined selections list
+ krConfig->setGroup("Private");
+ TQStrList 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 (TQString(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
+ TQStrList list;
+ TQListBoxItem *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() {
+ TQString temp=selection->currentText();
+ bool itemExists=false;
+ TQListBoxItem *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(TQListBoxItem *i) {
+ selection->insertItem(i->text(),0);
+ accept();
+}
+
+////////////////////////// QuickNavLineEdit ////////////////////
+
+QuickNavLineEdit::QuickNavLineEdit(const TQString &string, TQWidget *parent, const char *name):
+ KLineEdit(string, parent, name) { init(); }
+
+QuickNavLineEdit::QuickNavLineEdit(TQWidget *parent, const char *name):
+ KLineEdit(parent, name) { init(); }
+
+int QuickNavLineEdit::findCharFromPos(const TQString & str, const TQFontMetrics & 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( TDEGlobalSettings::CompletionPopupAuto ); ==> removed by public demand
+}
+
+void QuickNavLineEdit::leaveEvent(TQEvent *) {
+ clearAll();
+}
+
+void QuickNavLineEdit::mousePressEvent( TQMouseEvent *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 TQMouseEvent * const m,TQString * 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 TQString 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( TQMouseEvent *m) {
+ if (m->state()!=ControlButton) { // works only with ctrl pressed
+ clearAll();
+ KLineEdit::mouseMoveEvent(m);
+ return;
+ }
+ TQString 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/src/app/Dialogs/krspwidgets.h b/src/app/Dialogs/krspwidgets.h
new file mode 100644
index 0000000..13098dc
--- /dev/null
+++ b/src/app/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 <tqstrlist.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( TQString caption, bool nameOnly=false ); // get file-mask for (un)selecting files
+ static KURL newFTP();
+
+private:
+ static TQStrList 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(TQListBoxItem *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 TQString &string, TQWidget *parent, const char *name=0);
+ QuickNavLineEdit(TQWidget *parent=0, const char *name=0);
+ virtual ~QuickNavLineEdit() {}
+ static int findCharFromPos(const TQString &, const TQFontMetrics &, int pos);
+protected:
+ void mouseMoveEvent( TQMouseEvent *m);
+ void leaveEvent( TQEvent * );
+ void mousePressEvent( TQMouseEvent *m );
+ inline void clearAll() { _numOfSelectedChars = 0; if (_pop) delete _pop; _dummyDisplayed=false; }
+ void init();
+
+private:
+ int charCount(const TQMouseEvent * const , TQString* const =0) ;
+ int _numOfSelectedChars;
+ bool _dummyDisplayed;
+ TQGuardedPtr<KPassivePopup> _pop;
+};
+
+#endif
diff --git a/src/app/Dialogs/krsqueezedtextlabel.cpp b/src/app/Dialogs/krsqueezedtextlabel.cpp
new file mode 100644
index 0000000..7a5ef8d
--- /dev/null
+++ b/src/app/Dialogs/krsqueezedtextlabel.cpp
@@ -0,0 +1,80 @@
+#include "krsqueezedtextlabel.h"
+#include <kstringhandler.h>
+#include <kurldrag.h>
+#include <tqtooltip.h>
+
+KrSqueezedTextLabel::KrSqueezedTextLabel(TQWidget *parent, const char *name):
+ KSqueezedTextLabel(parent, name), acceptDrops( false ), _index(-1), _length(-1) {
+}
+
+
+KrSqueezedTextLabel::~KrSqueezedTextLabel() {
+}
+
+void KrSqueezedTextLabel::mousePressEvent(TQMouseEvent *) {
+ emit clicked();
+
+}
+
+void KrSqueezedTextLabel::enableDrops( bool flag )
+{
+ setAcceptDrops( acceptDrops = flag );
+}
+
+void KrSqueezedTextLabel::dropEvent(TQDropEvent *e) {
+ emit dropped(e);
+}
+
+void KrSqueezedTextLabel::dragEnterEvent(TQDragEnterEvent *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 {
+ TQString sqtext=fullText;
+ TQFontMetrics 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=TQMIN(index, numOfExtraChars);
+ numOfExtraChars -= delta;
+ sqtext.replace(0, delta, "...");
+ }
+
+ if (numOfExtraChars>0 && ((int)sqtext.length() > length+3)) {
+ delta = TQMIN(numOfExtraChars, (int)sqtext.length() - (length+3));
+ sqtext.replace(sqtext.length()-delta, delta, "...");
+ }
+ TQLabel::setText(sqtext);
+
+ TQToolTip::remove( this );
+ TQToolTip::add( this, fullText );
+ } else {
+ TQLabel::setText(fullText);
+
+ TQToolTip::remove( this );
+ TQToolTip::hide();
+ }
+ }
+}
+
+void KrSqueezedTextLabel::setText( const TQString &text, int index, int length ) {
+ _index=index;
+ _length=length;
+ fullText = text;
+ squeezeTextToLabel(_index,_length);
+}
+
+#include "krsqueezedtextlabel.moc"
+
diff --git a/src/app/Dialogs/krsqueezedtextlabel.h b/src/app/Dialogs/krsqueezedtextlabel.h
new file mode 100644
index 0000000..320953f
--- /dev/null
+++ b/src/app/Dialogs/krsqueezedtextlabel.h
@@ -0,0 +1,45 @@
+#ifndef KRSQUEEZEDTEXTLABEL_H
+#define KRSQUEEZEDTEXTLABEL_H
+
+#include <ksqueezedtextlabel.h>
+
+class TQMouseEvent;
+class TQDropEvent;
+class TQDragEnterEvent;
+
+/**
+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 {
+TQ_OBJECT
+
+ public:
+ KrSqueezedTextLabel(TQWidget *parent = 0, const char *name = 0);
+ ~KrSqueezedTextLabel();
+
+ void enableDrops( bool flag );
+
+ public slots:
+ void setText( const TQString &text, int index=-1, int length=-1 );
+
+ signals:
+ void clicked(); /**< emitted when someone clicks on the label */
+ void dropped(TQDropEvent *); /**< emitted when someone drops URL onto the label */
+
+ protected:
+ void resizeEvent( TQResizeEvent * ) { squeezeTextToLabel(_index, _length); }
+ virtual void mousePressEvent(TQMouseEvent *e);
+ virtual void dropEvent(TQDropEvent *e);
+ virtual void dragEnterEvent(TQDragEnterEvent *e);
+ void squeezeTextToLabel(int index=-1, int length=-1);
+
+ private:
+ bool acceptDrops;
+ int _index, _length;
+};
+
+#endif
diff --git a/src/app/Dialogs/kurllistrequester.cpp b/src/app/Dialogs/kurllistrequester.cpp
new file mode 100644
index 0000000..449da8f
--- /dev/null
+++ b/src/app/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 <tqpixmap.h>
+#include <tqcursor.h>
+#include <tqlayout.h>
+#include <tdefiledialog.h>
+#include <tdepopupmenu.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+
+#define DELETE_ITEM_ID 100
+
+KURLListRequester::KURLListRequester( TQWidget *parent, const char * name ) : TQWidget( parent, name )
+{
+ TDEIconLoader *iconLoader = new TDEIconLoader();
+ TQPixmap imageAdd = iconLoader->loadIcon( "1downarrow", TDEIcon::Panel, 16 );
+ TQPixmap imageFolder = iconLoader->loadIcon( "folder", TDEIcon::Panel, 16 );
+
+ // Creating the widget
+
+ TQGridLayout *urlListRequesterGrid = new TQGridLayout( this );
+ urlListRequesterGrid->setSpacing( 0 );
+ urlListRequesterGrid->setMargin( 0 );
+
+ urlLineEdit = new KLineEdit( this, "urlLineEdit" );
+ urlListRequesterGrid->addWidget( urlLineEdit, 0, 0 );
+
+ urlListBox = new TQListBox( this, "urlListBox" );
+ urlListBox->setSelectionMode( TQListBox::Extended );
+ urlListRequesterGrid->addMultiCellWidget( urlListBox, 1, 1, 0, 2 );
+
+ urlAddBtn = new TQToolButton( this, "urlAddBtn" );
+ urlAddBtn->setText( "" );
+ urlAddBtn->setPixmap( imageAdd );
+ urlListRequesterGrid->addWidget( urlAddBtn, 0, 1 );
+
+ urlBrowseBtn = new TQToolButton( 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, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotAdd() ) );
+ connect( urlBrowseBtn, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotBrowse() ) );
+ connect( urlLineEdit, TQ_SIGNAL( returnPressed(const TQString&) ), this, TQ_SLOT( slotAdd() ) );
+ connect( urlListBox, TQ_SIGNAL( rightButtonClicked ( TQListBoxItem *, const TQPoint & ) ), this,
+ TQ_SLOT( slotRightClicked( TQListBoxItem * ) ) );
+}
+
+void KURLListRequester::slotAdd()
+{
+ TQString text = urlLineEdit->text().simplifyWhiteSpace();
+ if( text.length() )
+ {
+ TQString error = TQString();
+ emit checkValidity( text, error );
+
+ if( !error.isNull() )
+ KMessageBox::error( this, error );
+ else
+ {
+ urlListBox->insertItem( text );
+ urlLineEdit->clear();
+ }
+ }
+}
+
+void KURLListRequester::slotBrowse()
+{
+ KURL url = KFileDialog::getExistingURL( TQString(), this );
+ if( !url.isEmpty())
+ urlLineEdit->setText( vfs::pathOrURL( url ) );
+ urlLineEdit->setFocus();
+}
+
+void KURLListRequester::keyPressEvent(TQKeyEvent *e)
+{
+ if( e->key() == Key_Delete )
+ {
+ if( urlListBox->hasFocus() )
+ {
+ deleteSelectedItems();
+ return;
+ }
+ }
+
+ TQWidget::keyPressEvent( e );
+}
+
+void KURLListRequester::deleteSelectedItems()
+{
+ int i=0;
+ TQListBoxItem *item;
+
+ while( (item = urlListBox->item(i)) )
+ {
+ if( item->isSelected() )
+ {
+ urlListBox->removeItem( i );
+ continue;
+ }
+ i++;
+ }
+}
+
+void KURLListRequester::slotRightClicked( TQListBoxItem *item )
+{
+ if( item == 0 )
+ return;
+
+ TDEPopupMenu popupMenu( this );
+ popupMenu.insertItem( i18n( "Delete" ), DELETE_ITEM_ID );
+
+ switch( popupMenu.exec( TQCursor::pos() ) )
+ {
+ case DELETE_ITEM_ID:
+ if( item->isSelected() )
+ deleteSelectedItems();
+ else
+ urlListBox->removeItem( urlListBox->index( item ) );
+ break;
+ }
+}
+
+KURL::List KURLListRequester::urlList()
+{
+ KURL::List urls;
+
+ TQString text = urlLineEdit->text().simplifyWhiteSpace();
+ if (!text.isEmpty())
+ {
+ TQString error = TQString();
+ emit checkValidity( text, error );
+ if( error.isNull() )
+ urls.append( vfs::fromPathOrURL( text ) );
+ }
+
+ TQListBoxItem *item = urlListBox->firstItem();
+ while ( item )
+ {
+ TQString text = item->text().simplifyWhiteSpace();
+
+ TQString error = TQString();
+ 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/src/app/Dialogs/kurllistrequester.h b/src/app/Dialogs/kurllistrequester.h
new file mode 100644
index 0000000..8c49611
--- /dev/null
+++ b/src/app/Dialogs/kurllistrequester.h
@@ -0,0 +1,77 @@
+/***************************************************************************
+ 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 <tqwidget.h>
+#include <tqlistbox.h>
+#include <tqtoolbutton.h>
+#include <klineedit.h>
+#include <kurl.h>
+#include <kurlcompletion.h>
+
+class KURLListRequester : public TQWidget
+{
+ TQ_OBJECT
+
+
+public:
+ KURLListRequester( TQWidget *parent = 0, const char * name = 0 );
+
+ KURL::List urlList();
+ void setUrlList( KURL::List );
+
+ KLineEdit *lineEdit() {return urlLineEdit;}
+ TQListBox *listBox() {return urlListBox;}
+
+ void setCompletionDir( TQString dir ) { completion.setDir( dir ); }
+
+signals:
+ void checkValidity( TQString &text, TQString &error );
+
+protected slots:
+ void slotAdd();
+ void slotBrowse();
+ void slotRightClicked( TQListBoxItem * );
+
+protected:
+ virtual void keyPressEvent(TQKeyEvent *e);
+ void deleteSelectedItems();
+
+ KLineEdit *urlLineEdit;
+ TQListBox *urlListBox;
+ TQToolButton *urlAddBtn;
+ TQToolButton *urlBrowseBtn;
+
+ KURLCompletion completion;
+};
+
+#endif /* __KURLLISTREQUESTER_H__ */
diff --git a/src/app/Dialogs/newftpgui.cpp b/src/app/Dialogs/newftpgui.cpp
new file mode 100644
index 0000000..56eef7c
--- /dev/null
+++ b/src/app/Dialogs/newftpgui.cpp
@@ -0,0 +1,182 @@
+/****************************************************************************
+** 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 <tqlabel.h>
+#include <tqlineedit.h>
+#include <tqpushbutton.h>
+#include <tqspinbox.h>
+#include <tqlayout.h>
+#include <tqhbox.h>
+#include <tqgrid.h>
+#include <tqvariant.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+#include <tqimage.h>
+#include <tqpixmap.h>
+#include <tdelocale.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 TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)0 )
+
+newFTPGUI::newFTPGUI( TQWidget* parent, const char* name, bool modal, WFlags fl )
+ : TQDialog( parent, name, modal, fl ){
+
+ TQVBoxLayout * layout = new TQVBoxLayout( this, 11, 6, "newFTPGUI_layout" );
+ layout->setAutoAdd(true);
+
+ if ( !name )
+ setName( "newFTPGUI" );
+ resize( 342, 261 );
+ setCaption( i18n( "New Network Connection" ) );
+// setSizeGripEnabled( true );
+ setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)5, (TQSizePolicy::SizeType)5, sizePolicy().hasHeightForWidth() ) );
+ setMinimumSize( TQSize( 342, 261 ) );
+
+
+ TQHBox* hbox_image = new TQHBox( this, "hbox_image" );
+ hbox_image->setSpacing( 6 );
+
+ PixmapLabel1 = new TQLabel( hbox_image, "PixmapLabel1" );
+ PixmapLabel1->setPixmap( krLoader->loadIcon("network", TDEIcon::Desktop, 32) );
+ PixmapLabel1->setSizePolicy( SIZE_MINIMUM );
+
+ TextLabel3 = new TQLabel( i18n( "About to connect to..." ), hbox_image, "TextLabel3" );
+ TQFont TextLabel3_font( TextLabel3->font() );
+ TextLabel3_font.setBold( true );
+ TextLabel3->setFont( TextLabel3_font );
+
+
+ TQGrid* grid_host = new TQGrid( 3, this, "grid_host" );
+
+ TextLabel1 = new TQLabel( i18n( "Protocol:" ), grid_host, "TextLabel1" );
+ TextLabel1_22 = new TQLabel( i18n( "Host:"), grid_host, "TextLabel_2" );
+ TextLabel1_3 = new TQLabel( i18n( "Port:" ), grid_host, "TextLabel1_3" );
+
+ TQStringList 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,TQ_SIGNAL(activated(const TQString& )),
+ this,TQ_SLOT(slotTextChanged(const TQString& )));
+
+ url = new KHistoryCombo( grid_host, "url" );
+ url->setMaximumHeight( 20 );
+ url->setMaxCount( 25 );
+ url->setDuplicatesEnabled( false );
+ connect( url, TQ_SIGNAL( activated( const TQString& )),
+ url, TQ_SLOT( addToHistory( const TQString& )));
+ // load the history and completion list after creating the history combo
+ krConfig->setGroup("Private");
+ TQStringList list = krConfig->readListEntry( "newFTP Completion list" );
+ url->completionObject()->setItems( list );
+ list = krConfig->readListEntry( "newFTP History list" );
+ url->setHistoryItems( list );
+
+ port = new TQSpinBox( grid_host, "port" );
+ port->setMaxValue( 65535 );
+ port->setValue( 21 );
+ port->setSizePolicy( SIZE_MINIMUM );
+
+
+ TextLabel1_2 = new TQLabel( i18n( "Username:" ), this, "TextLabel1_2" );
+ username = new TQLineEdit( this, "username" );
+ TextLabel1_2_2 = new TQLabel( i18n( "Password:" ), this, "TextLabel1_2_2" );
+ password = new TQLineEdit( this, "password" );
+ password->setEchoMode( TQLineEdit::Password );
+
+
+ TQWidget* Layout6 = new TQWidget( this, "Layout6" );
+ hbox = new TQHBoxLayout( Layout6 );
+ hbox->setSpacing( 6 );
+ hbox->setMargin( 0 );
+
+ hbox->addItem(new TQSpacerItem(1,1,TQSizePolicy::Expanding));
+
+ connectBtn = new TQPushButton( i18n( "&Connect" ), Layout6, "connectBtn" );
+ connectBtn->setAutoDefault( true );
+ connectBtn->setDefault( true );
+ hbox->addWidget( connectBtn );
+
+ //saveBtn = new TQPushButton( i18n( "&Save" ), Layout6, "saveBtn" );
+ //saveBtn->setAutoDefault( true );
+ //hbox->addWidget( saveBtn );
+
+ cancelBtn = new TQPushButton( i18n( "&Cancel" ), Layout6, "cancelBtn" );
+ cancelBtn->setAutoDefault( true );
+ hbox->addWidget( cancelBtn );
+
+ // signals and slots connections
+ connect( connectBtn, TQ_SIGNAL( clicked() ), this, TQ_SLOT( accept() ) );
+ connect( cancelBtn, TQ_SIGNAL( clicked() ), this, TQ_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, TQt does it all for us
+}
+
+void newFTPGUI::slotTextChanged(const TQString& 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( TQEvent* ev ) {
+ bool ret = TQDialog::event( ev );
+ if ( ev->type() == TQEvent::ApplicationFontChange ) {
+ TQFont TextLabel3_font( TextLabel3->font() );
+ TextLabel3_font.setBold( true );
+ TextLabel3->setFont( TextLabel3_font );
+ }
+ return ret;
+}
+
+#include "newftpgui.moc"
diff --git a/src/app/Dialogs/newftpgui.h b/src/app/Dialogs/newftpgui.h
new file mode 100644
index 0000000..d3808e5
--- /dev/null
+++ b/src/app/Dialogs/newftpgui.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+** 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 <tqvariant.h>
+#include <tqdialog.h>
+class TQVBoxLayout;
+class TQHBoxLayout;
+class TQGridLayout;
+class TQLabel;
+class TQLineEdit;
+class TQPushButton;
+class TQSpinBox;
+class KComboBox;
+class KHistoryCombo;
+
+class newFTPGUI : public TQDialog {
+ TQ_OBJECT
+
+public:
+ newFTPGUI( TQWidget* parent = 0, const char* name = 0, bool modal = false, WFlags fl = 0 );
+ ~newFTPGUI();
+
+ TQLabel* TextLabel1;
+ KComboBox* prefix;
+ TQLabel* TextLabel1_2_2;
+ TQLabel* TextLabel1_22;
+ TQLabel* TextLabel1_2;
+ TQLabel* TextLabel1_3;
+ TQSpinBox* port;
+ TQLineEdit* password;
+ TQPushButton* connectBtn;
+ TQPushButton* saveBtn;
+ TQPushButton* cancelBtn;
+ TQLabel* PixmapLabel1;
+ TQLabel* TextLabel3;
+ TQLineEdit* username;
+ KHistoryCombo* url;
+
+public slots:
+ void slotTextChanged(const TQString& string);
+
+protected:
+ TQHBoxLayout* hbox;
+ bool event( TQEvent* );
+};
+
+#endif // NEWFTPGUI_H
diff --git a/src/app/Dialogs/packgui.cpp b/src/app/Dialogs/packgui.cpp
new file mode 100644
index 0000000..e479060
--- /dev/null
+++ b/src/app/Dialogs/packgui.cpp
@@ -0,0 +1,122 @@
+/***************************************************************************
+ 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 <tdefiledialog.h>
+#include "../krusader.h"
+#include "../defaults.h"
+#include <tqlineedit.h>
+#include <tqcheckbox.h>
+#include <tqstringlist.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+
+#define PS(x) lst.contains(x)>0
+
+// clear the statics first
+TQString PackGUI::filename=0;
+TQString PackGUI::destination=0;
+TQString PackGUI::type=0;
+TQMap<TQString, TQString> PackGUI::extraProps;
+
+PackGUI::PackGUI(TQString defaultName, TQString defaultPath, int noOfFiles, TQString 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");
+ TQStringList 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("tar") && PS("xz")) typeData->insertItem("tar.xz");
+ 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");
+ if (PS("xz")) typeData->insertItem("xz");
+ // set the last used packer as the top one
+ TQString tmp=krConfig->readEntry("lastUsedPacker",TQString());
+ if (tmp!=TQString()) {
+ 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() {
+ TQString temp=KFileDialog::getExistingDirectory(dirData->text(),0,i18n("Please select a directory"));
+ if (temp != TQString())
+ 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=TQString();
+ destination=TQString();
+ type=TQString();
+ PackGUIBase::reject();
+}
+
+#include "packgui.moc"
diff --git a/src/app/Dialogs/packgui.h b/src/app/Dialogs/packgui.h
new file mode 100644
index 0000000..2601b25
--- /dev/null
+++ b/src/app/Dialogs/packgui.h
@@ -0,0 +1,54 @@
+/***************************************************************************
+ 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 {
+ TQ_OBJECT
+
+public:
+ PackGUI(TQString defaultName, TQString defaultPath, int noOfFiles, TQString filename="");
+
+public slots:
+ void browse();
+
+protected slots:
+ void accept();
+ void reject();
+
+public:
+ static TQString filename, destination, type;
+ static TQMap<TQString, TQString> extraProps;
+};
+
+#endif
diff --git a/src/app/Dialogs/packguibase.cpp b/src/app/Dialogs/packguibase.cpp
new file mode 100644
index 0000000..1d66cd4
--- /dev/null
+++ b/src/app/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 <tqcheckbox.h>
+#include <tqcombobox.h>
+#include <tqlabel.h>
+#include <tqlineedit.h>
+#include <tqpushbutton.h>
+#include <tqtoolbutton.h>
+#include <tqlayout.h>
+#include <tqvariant.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+#include <tqimage.h>
+#include <tqpixmap.h>
+#include <tqspinbox.h>
+#include <tqslider.h>
+#include <tqhbox.h>
+#include <tqvbox.h>
+#include <kiconloader.h>
+#include <tdeglobalsettings.h>
+#include <kcombobox.h>
+#include <tdemessagebox.h>
+#include <tdeio/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( TQWidget* parent, const char* name, bool modal, WFlags fl )
+ : TQDialog( parent, name, modal, fl ), expanded( false )
+{
+ if ( !name )
+ setName( "PackGUIBase" );
+ resize( 430, 140 );
+ setCaption( i18n( "Pack" ) );
+ grid = new TQGridLayout( this );
+ grid->setSpacing( 6 );
+ grid->setMargin( 11 );
+
+ hbox = new TQHBoxLayout;
+ hbox->setSpacing( 6 );
+ hbox->setMargin( 0 );
+
+ TextLabel3 = new TQLabel( this, "TextLabel3" );
+ TextLabel3->setText( i18n( "To archive" ) );
+ hbox->addWidget( TextLabel3 );
+
+ nameData = new TQLineEdit( this, "nameData" );
+ hbox->addWidget( nameData );
+
+ typeData = new TQComboBox( false, this, "typeData" );
+ typeData->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0 ) );
+ connect( typeData, TQ_SIGNAL( activated( const TQString & ) ), this, TQ_SLOT( checkConsistency() ) );
+ connect( typeData, TQ_SIGNAL( highlighted( const TQString & ) ), this, TQ_SLOT( checkConsistency() ) );
+ hbox->addWidget( typeData );
+
+ grid->addLayout( hbox, 1, 0 );
+
+ hbox_2 = new TQHBoxLayout;
+ hbox_2->setSpacing( 6 );
+ hbox_2->setMargin( 0 );
+
+ TextLabel5 = new TQLabel( this, "TextLabel5" );
+ TextLabel5->setText( i18n( "In directory" ) );
+ hbox_2->addWidget( TextLabel5 );
+
+ dirData = new TQLineEdit( this, "dirData" );
+ hbox_2->addWidget( dirData );
+
+ browseButton = new TQToolButton( this, "browseButton" );
+ browseButton->setIconSet( SmallIcon( "document-open" ) );
+ hbox_2->addWidget( browseButton );
+ TQSpacerItem* spacer = new TQSpacerItem( 48, 20, TQSizePolicy::Fixed, TQSizePolicy::Fixed );
+ hbox_2->addItem( spacer );
+
+ grid->addLayout( hbox_2, 2, 0 );
+
+ hbox_3 = new TQHBoxLayout;
+ hbox_3->setSpacing( 6 );
+ hbox_3->setMargin( 0 );
+
+ PixmapLabel1 = new TQLabel( this, "PixmapLabel1" );
+ PixmapLabel1->setPixmap( krLoader->loadIcon("package", TDEIcon::Desktop, 32) );
+ PixmapLabel1->setScaledContents( true );
+ PixmapLabel1->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)0 ) );
+ hbox_3->addWidget( PixmapLabel1 );
+
+ TextLabel1 = new TQLabel( this, "TextLabel1" );
+ TextLabel1->setText( i18n( "Pack" ) );
+ hbox_3->addWidget( TextLabel1 );
+
+ grid->addLayout( hbox_3, 0, 0 );
+
+
+ hbox_4 = new TQHBoxLayout;
+ hbox_4->setSpacing( 6 );
+ hbox_4->setMargin( 0 );
+
+ TQSpacerItem* spacer_3 = new TQSpacerItem( 20, 26, TQSizePolicy::Fixed, TQSizePolicy::Expanding );
+ hbox_4->addItem( spacer_3 );
+ grid->addLayout( hbox_4, 3, 0 );
+
+ advancedWidget = new TQWidget( this, "advancedWidget" );
+
+ hbox_5 = new TQGridLayout( advancedWidget );
+ hbox_5->setSpacing( 6 );
+ hbox_5->setMargin( 0 );
+
+
+ TQVBoxLayout *compressLayout = new TQVBoxLayout;
+ compressLayout->setSpacing( 6 );
+ compressLayout->setMargin( 0 );
+
+ multipleVolume = new TQCheckBox( i18n( "Multiple volume archive" ), advancedWidget, "multipleVolume" );
+ connect( multipleVolume, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( checkConsistency() ) );
+ compressLayout->addWidget( multipleVolume, 0, 0 );
+
+ TQHBoxLayout * volumeHbox = new TQHBoxLayout;
+
+ TQSpacerItem* spacer_5 = new TQSpacerItem( 20, 26, TQSizePolicy::Fixed, TQSizePolicy::Fixed );
+ volumeHbox->addItem( spacer_5 );
+
+ TextLabel7 = new TQLabel( i18n("Size:" ), advancedWidget, "TextLabel7" );
+ volumeHbox->addWidget( TextLabel7 );
+
+ volumeSpinBox = new TQSpinBox( advancedWidget, "volumeSpinBox" );
+ volumeSpinBox->setMinValue( 1 );
+ volumeSpinBox->setMaxValue( 9999 );
+ volumeSpinBox->setValue( 1440 );
+ volumeHbox->addWidget( volumeSpinBox );
+
+ volumeUnitCombo = new TQComboBox( false, advancedWidget, "volumeUnitCombo" );
+ volumeUnitCombo->insertItem( "B" );
+ volumeUnitCombo->insertItem( "KB" );
+ volumeUnitCombo->insertItem( "MB" );
+ volumeUnitCombo->setCurrentItem( 1 );
+ volumeHbox->addWidget( volumeUnitCombo );
+
+ compressLayout->addLayout ( volumeHbox );
+
+ setCompressionLevel = new TQCheckBox( i18n( "Set compression level" ), advancedWidget, "multipleVolume" );
+ connect( setCompressionLevel, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( checkConsistency() ) );
+ compressLayout->addWidget( setCompressionLevel, 0, 0 );
+
+ TQHBoxLayout * sliderHbox = new TQHBoxLayout;
+
+ TQSpacerItem* spacer_6 = new TQSpacerItem( 20, 26, TQSizePolicy::Fixed, TQSizePolicy::Fixed );
+ sliderHbox->addItem( spacer_6 );
+
+ TQVBox * sliderVBox = new TQVBox( advancedWidget );
+
+ compressionSlider = new TQSlider( 1, 9, 1, 5, TQt::Horizontal, sliderVBox, "compressionSlider" );
+ compressionSlider->setTickmarks( TQSlider::Below );
+
+ TQHBox * minmaxHBox = new TQHBox( sliderVBox );
+ minLabel = new TQLabel( i18n("MIN"), minmaxHBox );
+ maxLabel = new TQLabel( i18n("MAX"), minmaxHBox );
+ maxLabel->setSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed );
+
+ sliderHbox->addWidget( sliderVBox );
+
+ compressLayout->addLayout( sliderHbox );
+
+ compressLayout->addStretch( 0 );
+ hbox_5->addLayout( compressLayout, 0, 0 );
+
+ TQFrame *vline = new TQFrame( advancedWidget, "vline" );
+ vline->setFrameStyle( TQFrame::VLine | TQFrame::Sunken );
+ vline->setMinimumWidth( 20 );
+ hbox_5->addWidget( vline, 0, 1 );
+
+
+ TQGridLayout * passwordGrid = new TQGridLayout;
+ passwordGrid->setSpacing( 6 );
+ passwordGrid->setMargin( 0 );
+
+ TextLabel4 = new TQLabel( advancedWidget, "TextLabel4" );
+ TextLabel4->setText( i18n( "Password" ) );
+ passwordGrid->addWidget( TextLabel4, 0, 0 );
+
+ password = new TQLineEdit( advancedWidget, "password" );
+ password->setEchoMode( TQLineEdit::Password );
+ connect( password, TQ_SIGNAL( textChanged ( const TQString & ) ), this, TQ_SLOT( checkConsistency() ) );
+
+ passwordGrid->addWidget( password, 0, 1 );
+
+ TextLabel6 = new TQLabel( advancedWidget, "TextLabel6" );
+ TextLabel6->setText( i18n( "Again" ) );
+ passwordGrid->addWidget( TextLabel6, 1, 0 );
+
+ passwordAgain = new TQLineEdit( advancedWidget, "password" );
+ passwordAgain->setEchoMode( TQLineEdit::Password );
+ connect( passwordAgain, TQ_SIGNAL( textChanged ( const TQString & ) ), this, TQ_SLOT( checkConsistency() ) );
+
+ passwordGrid->addWidget( passwordAgain, 1, 1 );
+
+ TQHBoxLayout *consistencyHbox = new TQHBoxLayout;
+
+ TQSpacerItem* spacer_cons = new TQSpacerItem( 48, 20, TQSizePolicy::Expanding, TQSizePolicy::Fixed );
+ consistencyHbox->addItem( spacer_cons );
+
+ passwordConsistencyLabel = new TQLabel( advancedWidget, "passwordConsistencyLabel" );
+ consistencyHbox->addWidget( passwordConsistencyLabel );
+ passwordGrid->addMultiCellLayout ( consistencyHbox, 2, 2, 0, 1 );
+
+ encryptHeaders = new TQCheckBox( i18n( "Encrypt headers" ), advancedWidget, "encryptHeaders" );
+ passwordGrid->addMultiCellWidget ( encryptHeaders, 3, 3, 0, 1 );
+
+ TQSpacerItem* spacer_psw = new TQSpacerItem( 20, 20, TQSizePolicy::Fixed, TQSizePolicy::Expanding );
+ passwordGrid->addItem( spacer_psw, 4, 0 );
+
+ hbox_5->addLayout( passwordGrid, 0, 2 );
+
+ hbox_7 = new TQHBoxLayout;
+ hbox_7->setSpacing( 6 );
+ hbox_7->setMargin( 0 );
+
+ TextLabel8 = new TQLabel( i18n( "Command line switches:" ), advancedWidget, "TextLabel8" );
+ TextLabel8->setSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed );
+ hbox_7->addWidget( TextLabel8 );
+
+ commandLineSwitches = new KHistoryCombo( advancedWidget, "commandLineSwitches" );
+ commandLineSwitches->setMaxCount(25); // remember 25 items
+ commandLineSwitches->setDuplicatesEnabled(false);
+ krConfig->setGroup("Archives");
+ TQStringList 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 TQHBoxLayout;
+ hbox_6->setSpacing( 6 );
+ hbox_6->setMargin( 0 );
+
+ advancedButton = new TQPushButton( this, "advancedButton" );
+ advancedButton->setText( i18n( "&Advanced" ) + " >>" );
+ hbox_6->addWidget( advancedButton );
+
+ TQSpacerItem* spacer_2 = new TQSpacerItem( 140, 20, TQSizePolicy::Expanding, TQSizePolicy::Fixed );
+ hbox_6->addItem( spacer_2 );
+
+ okButton = new TQPushButton( this, "okButton" );
+ okButton->setText( i18n( "Ok" ) );
+ okButton->setDefault( true );
+ hbox_6->addWidget( okButton );
+
+ cancelButton = new TQPushButton( this, "cancelButton" );
+ cancelButton->setText( i18n( "Cancel" ) );
+ hbox_6->addWidget( cancelButton );
+
+ grid->addLayout( hbox_6, 6, 0 );
+
+ // signals and slots connections
+ connect( okButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( accept() ) );
+ connect( advancedButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( expand() ) );
+ connect( cancelButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( reject() ) );
+ connect( browseButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( browse() ) );
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+PackGUIBase::~PackGUIBase()
+{
+ // no need to delete child widgets, TQt does it all for us
+}
+
+void PackGUIBase::browse()
+{
+ tqWarning( "PackGUIBase::browse(): Not implemented yet!" );
+}
+
+void PackGUIBase::expand() {
+ expanded = !expanded;
+
+ advancedButton->setText( i18n( "&Advanced" ) + ( expanded ? " <<" : " >>" ) );
+
+ if( expanded )
+ advancedWidget->show();
+ else {
+ advancedWidget->hide();
+ layout()->activate();
+ TQSize minSize = minimumSize();
+ resize( width(), minSize.height() );
+ }
+ show();
+}
+
+void PackGUIBase::checkConsistency() {
+ if( password->text().isEmpty() && passwordAgain->text().isEmpty()) {
+ passwordConsistencyLabel->setPaletteForegroundColor( TDEGlobalSettings::textColor() );
+ passwordConsistencyLabel->setText( i18n( "No password specified" ) );
+ }
+ else
+ if( password->text() == passwordAgain->text() ) {
+ passwordConsistencyLabel->setPaletteForegroundColor( TDEGlobalSettings::textColor() );
+ passwordConsistencyLabel->setText( i18n( "The passwords are equal" ) );
+ }
+ else {
+ passwordConsistencyLabel->setPaletteForegroundColor( TQt::red );
+ passwordConsistencyLabel->setText( i18n( "The passwords are different" ) );
+ }
+
+ TQString 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( TQMap<TQString,TQString> & 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() ) {
+ TDEIO::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;
+ }
+
+ TQString sbuffer;
+ sbuffer.sprintf("%llu",size);
+
+ inMap[ "VolumeSize" ] = sbuffer;
+ }
+
+ if( setCompressionLevel->isEnabled() && setCompressionLevel->isChecked() ) {
+ inMap[ "CompressionLevel" ] = TQString("%1").arg( compressionSlider->value() );
+ }
+
+ TQString cmdArgs = commandLineSwitches->currentText().stripWhiteSpace();
+ if( !cmdArgs.isEmpty() ) {
+ bool firstChar = true;
+ TQChar quote = '\0';
+
+ for( unsigned i=0; i < cmdArgs.length(); i++ ) {
+ TQChar 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 );
+ TQStringList list = commandLineSwitches->historyItems();
+ krConfig->setGroup("Archives");
+ krConfig->writeEntry("Command Line Switches", list);
+
+ inMap[ "CommandLineSwitches" ] = cmdArgs;
+ }
+ return true;
+}
+
+#include "packguibase.moc"
diff --git a/src/app/Dialogs/packguibase.h b/src/app/Dialogs/packguibase.h
new file mode 100644
index 0000000..202f67f
--- /dev/null
+++ b/src/app/Dialogs/packguibase.h
@@ -0,0 +1,110 @@
+/***************************************************************************
+ 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 <tdelocale.h>
+#include <tqdialog.h>
+#include <tqmap.h>
+
+
+class TQVBoxLayout;
+class TQHBoxLayout;
+class TQGridLayout;
+class TQCheckBox;
+class TQComboBox;
+class TQLabel;
+class TQLineEdit;
+class TQPushButton;
+class TQToolButton;
+class TQSpinBox;
+class TQSlider;
+class KHistoryCombo;
+
+class PackGUIBase : public TQDialog
+{
+ TQ_OBJECT
+
+
+public:
+ PackGUIBase( TQWidget* parent = 0, const char* name = 0, bool modal = false, WFlags fl = 0 );
+ ~PackGUIBase();
+
+ TQLabel* TextLabel3;
+ TQLineEdit* nameData;
+ TQComboBox* typeData;
+ TQLabel* TextLabel5;
+ TQLineEdit* dirData;
+ TQToolButton* browseButton;
+ TQWidget* advancedWidget;
+ TQLabel* PixmapLabel1;
+ TQLabel* TextLabel1;
+ TQLabel* TextLabel4;
+ TQLabel* TextLabel6;
+ TQLabel* TextLabel7;
+ TQLabel* TextLabel8;
+ TQLabel* minLabel;
+ TQLabel* maxLabel;
+ TQLineEdit* password;
+ TQLineEdit* passwordAgain;
+ TQLabel* passwordConsistencyLabel;
+ TQPushButton* okButton;
+ TQPushButton* cancelButton;
+ TQPushButton* advancedButton;
+ TQCheckBox* encryptHeaders;
+ TQCheckBox* multipleVolume;
+ TQSpinBox* volumeSpinBox;
+ TQComboBox* volumeUnitCombo;
+ TQCheckBox* setCompressionLevel;
+ TQSlider* compressionSlider;
+ KHistoryCombo *commandLineSwitches;
+
+public slots:
+ virtual void browse();
+ virtual bool extraProperties( TQMap<TQString,TQString> & );
+
+ void expand();
+ void checkConsistency();
+
+protected:
+ TQHBoxLayout* hbox;
+ TQHBoxLayout* hbox_2;
+ TQHBoxLayout* hbox_3;
+ TQHBoxLayout* hbox_4;
+ TQGridLayout* hbox_5;
+ TQHBoxLayout* hbox_6;
+ TQHBoxLayout* hbox_7;
+ TQGridLayout* grid;
+
+private:
+ bool expanded;
+};
+
+#endif // PACKGUIBASE_H
diff --git a/src/app/Dialogs/percentalsplitter.cpp b/src/app/Dialogs/percentalsplitter.cpp
new file mode 100644
index 0000000..4aefc41
--- /dev/null
+++ b/src/app/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 <tqtooltip.h>
+#include <tqpainter.h>
+#include <tqapplication.h>
+
+class PercentalSplitterToolTip : public TQToolTip {
+public:
+ PercentalSplitterToolTip( TQWidget * parent ) : TQToolTip( parent ) {
+ }
+
+ virtual ~PercentalSplitterToolTip() {
+ remove( parentWidget() );
+ }
+
+ void maybeTip( const TQPoint & point ) {
+ if( parentWidget()->inherits( "PercentalSplitter" ) ) {
+ PercentalSplitter *splitter = (PercentalSplitter *)parentWidget();
+
+ TQString tipString = splitter->toolTipString();
+ TQRect rect = TQRect( parentWidget()->rect() );
+
+ if( splitter->orientation() == TQt::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( TQWidget * parent, const char * name ) : TQSplitter( parent, name ), label( 0 ), opaqueOldPos( -1 ) {
+ toolTip = new PercentalSplitterToolTip( this );
+}
+
+PercentalSplitter::~PercentalSplitter() {
+ delete toolTip;
+}
+
+TQString PercentalSplitter::toolTipString( int p ) {
+ TQValueList<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 TQString( "%1.%2%3" ).arg( percent / 100 ).arg( ( percent / 10 )%10 ).arg( percent % 10 ) + "%";
+ }
+ return TQString();
+}
+
+void PercentalSplitter::setRubberband ( int p ) {
+ if( p == opaqueOldPos )
+ return;
+
+ TQPainter paint( this );
+ paint.setPen( gray );
+ paint.setBrush( gray );
+ paint.setRasterOp( XorROP );
+ TQRect r = contentsRect();
+ const int rBord = 3; // customizable?
+ int hw = handleWidth();
+
+ if( orientation() == TQt::Horizontal ) {
+ if ( opaqueOldPos >= 0 ) {
+ if( label == 0 )
+ paint.drawRect( opaqueOldPos + hw / 2 - rBord, r.y(), 2 * rBord, r.height() );
+ else {
+ TQPoint 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 {
+ TQPoint 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 = TQApplication::desktop()->screenNumber( this );
+
+ if( label == 0 ) {
+ label = new TQLabel( TQApplication::desktop()->screen( scr ), "SplitterPercent", WStyle_StaysOnTop |
+ WStyle_Customize | WStyle_NoBorder | WStyle_Tool | WX11BypassWM );
+ label->setMargin(1);
+ label->setAutoMask( false );
+ label->setFrameStyle( TQFrame::Plain | TQFrame::Box );
+ label->setLineWidth( 1 );
+ label->setAlignment( AlignAuto | AlignTop );
+ label->setIndent(0);
+
+ TQFontMetrics fm = label->fontMetrics();
+ label->setMinimumWidth( fm.width( "99.99%" ) + 5 );
+
+ label->polish();
+ }
+
+ label->setText( toolTipString( p ) );
+ label->adjustSize();
+
+ if( orientation() == TQt::Horizontal ) {
+ labelLocation = mapToGlobal( TQPoint( p - label->width()/2, r.y() + r.height()/2 ) );
+ if( labelLocation.x() < 0 )
+ labelLocation.setX( 0 );
+ } else {
+ labelLocation = mapToGlobal( TQPoint( r.x() + r.width()/2, p - label->height()/2 ) );
+ if( labelLocation.y() < 0 )
+ labelLocation.setY( 0 );
+ }
+
+#ifdef TQ_WS_MAC
+ TQRect screen = TQApplication::desktop()->availableGeometry( scr );
+#else
+ TQRect screen = TQApplication::desktop()->screenGeometry( scr );
+#endif
+
+ TQPoint labelLoc = mapFromGlobal( labelLocation );
+ if( orientation() == TQt::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/src/app/Dialogs/percentalsplitter.h b/src/app/Dialogs/percentalsplitter.h
new file mode 100644
index 0000000..414f133
--- /dev/null
+++ b/src/app/Dialogs/percentalsplitter.h
@@ -0,0 +1,59 @@
+/***************************************************************************
+ 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 <tqsplitter.h>
+#include <tqlabel.h>
+
+class PercentalSplitterToolTip;
+
+class PercentalSplitter : public TQSplitter {
+ TQ_OBJECT
+
+
+public:
+ PercentalSplitter( TQWidget * parent = 0, const char * name = 0 );
+ virtual ~PercentalSplitter();
+
+ TQString toolTipString( int p = -1 );
+
+protected:
+ virtual void setRubberband ( int p );
+
+private:
+ PercentalSplitterToolTip * toolTip;
+ TQLabel * label;
+ int opaqueOldPos;
+ TQPoint labelLocation;
+};
+
+#endif /* __PERCENTAL_SPLITTER__ */
diff --git a/src/app/Dialogs/popularurls.cpp b/src/app/Dialogs/popularurls.cpp
new file mode 100644
index 0000000..9fe2184
--- /dev/null
+++ b/src/app/Dialogs/popularurls.cpp
@@ -0,0 +1,307 @@
+#include <tdemessagebox.h>
+#include <tdelocale.h>
+#include <tqpushbutton.h>
+#include <tdelistview.h>
+#include <kiconloader.h>
+#include <tdelistviewsearchline.h>
+#include <tqheader.h>
+#include <tqlayout.h>
+#include <tqlabel.h>
+#include <tdetoolbarbutton.h>
+#include "../krusader.h"
+#include "../krslots.h"
+#include "popularurls.h"
+
+#define STARTING_RANK 20
+#define INCREASE 2
+#define DECREASE 1
+
+PopularUrls::PopularUrls(TQObject *parent, const char *name) : TQObject(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() {
+ TDEConfigGroupSaver svr(krConfig, "Private");
+ // prepare the string list containing urls and int list with ranks
+ TQStringList urlList;
+ TQValueList<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() {
+ TDEConfigGroupSaver svr(krConfig, "Private");
+ TQStringList urlList = krConfig->readListEntry("PopularUrls");
+ TQValueList<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
+ TQStringList::Iterator uit;
+ TQValueList<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) {
+ TQGridLayout *layout = new TQGridLayout( plainPage(), 0, KDialog::spacingHint() );
+
+ // listview to contain the urls
+ urls = new TDEListView(plainPage());
+ urls->header()->hide();
+ urls->addColumn("");
+ urls->setSorting(-1);
+ urls->setVScrollBarMode(TQScrollView::AlwaysOn);
+
+ // quick search
+ TQToolButton *btn = new TQToolButton(plainPage());
+ btn->setIconSet(SmallIcon("locationbar_erase"));
+ search = new TDEListViewSearchLine(plainPage(), urls);
+ search->setTrapReturnKey(true);
+ TQLabel *lbl = new TQLabel(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, TQ_SIGNAL(executed(TQListViewItem*)),
+ this, TQ_SLOT(slotItemSelected(TQListViewItem*)));
+ connect(urls, TQ_SIGNAL(returnPressed(TQListViewItem*)),
+ this, TQ_SLOT(slotItemSelected(TQListViewItem*)));
+ connect(btn, TQ_SIGNAL(clicked()), search, TQ_SLOT(clear()));
+ connect(search, TQ_SIGNAL(returnPressed(const TQString&)),
+ this, TQ_SLOT(slotSearchReturnPressed(const TQString&)));
+}
+
+void PopularUrlsDlg::slotItemSelected(TQListViewItem *it) {
+ selection = urls->itemIndex(it);
+ accept();
+}
+
+void PopularUrlsDlg::slotSearchReturnPressed(const TQString&) {
+ urls->setFocus();
+ // select the first visible item
+ TQListViewItemIterator 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) {
+ TDEListViewItem *item = new TDEListViewItem(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/src/app/Dialogs/popularurls.h b/src/app/Dialogs/popularurls.h
new file mode 100644
index 0000000..775a356
--- /dev/null
+++ b/src/app/Dialogs/popularurls.h
@@ -0,0 +1,86 @@
+#ifndef POPULARURLS_H
+#define POPULARURLS_H
+
+#include <tqobject.h>
+#include <kurl.h>
+#include <tqdict.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 TQObject {
+ TQ_OBJECT
+
+public:
+ PopularUrls(TQObject *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;
+ TQDict<UrlNode> ranks; // actually holds UrlNode*
+ int count;
+ static const int maxUrls = 30;
+ PopularUrlsDlg *dlg;
+};
+
+class TDEListView;
+class TDEListViewSearchLine;
+
+class PopularUrlsDlg: public KDialogBase {
+ TQ_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 TQString&);
+ void slotItemSelected(TQListViewItem *it);
+
+private:
+ TDEListView *urls;
+ TDEListViewSearchLine *search;
+ int selection;
+};
+
+
+#endif
diff --git a/src/app/DiskUsage/Makefile.am b/src/app/DiskUsage/Makefile.am
new file mode 100644
index 0000000..691d045
--- /dev/null
+++ b/src/app/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/src/app/DiskUsage/diskusage.cpp b/src/app/DiskUsage/diskusage.cpp
new file mode 100644
index 0000000..c372e8c
--- /dev/null
+++ b/src/app/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 <tqlayout.h>
+#include <tdelocale.h>
+#include <tdepopupmenu.h>
+#include <kmimetype.h>
+#include <tdemessagebox.h>
+#include <tdeglobalsettings.h>
+#include <tdeio/job.h>
+#include <tqpushbutton.h>
+#include <tqhbox.h>
+#include <tqapplication.h>
+#include <tqcursor.h>
+#include <tqpixmapcache.h>
+#include <tqgroupbox.h>
+#include <tqguardedptr.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( TQWidget *parent, const char *name ) : TQScrollView( parent, name ), cancelled( false )
+{
+ viewport()->setEraseColor( TQt::white );
+ widget = new TQWidget( parent );
+
+ TQGridLayout *loaderLayout = new TQGridLayout( widget );
+ loaderLayout->setSpacing( 0 );
+ loaderLayout->setMargin( 0 );
+
+ TQGroupBox *loaderBox = new TQGroupBox( widget, "loaderGroupBox" );
+ loaderBox->setFrameShape( TQGroupBox::Box );
+ loaderBox->setFrameShadow( TQGroupBox::Sunken );
+ loaderBox->setColumnLayout(0, TQt::Vertical );
+ loaderBox->layout()->setSpacing( 0 );
+ loaderBox->layout()->setMargin( 0 );
+ loaderBox->setSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed );
+ loaderBox->setFrameStyle( TQFrame::Panel + TQFrame::Raised );
+ loaderBox->setLineWidth( 2 );
+
+ TQGridLayout *synchGrid = new TQGridLayout( loaderBox->layout() );
+ synchGrid->setSpacing( 6 );
+ synchGrid->setMargin( 11 );
+
+ TQLabel *titleLabel = new TQLabel( i18n( "Loading Usage Information" ), loaderBox, "titleLabel" );
+ titleLabel->setAlignment( TQt::AlignHCenter );
+ synchGrid->addMultiCellWidget( titleLabel, 0, 0, 0, 1 );
+
+ TQLabel *filesLabel = new TQLabel( i18n( "Files:" ), loaderBox, "filesLabel" );
+ filesLabel->setFrameShape( TQLabel::StyledPanel );
+ filesLabel->setFrameShadow( TQLabel::Sunken );
+ synchGrid->addWidget( filesLabel, 1, 0 );
+
+ TQLabel *directoriesLabel = new TQLabel( i18n( "Directories:" ), loaderBox, "directoriesLabel" );
+ directoriesLabel->setFrameShape( TQLabel::StyledPanel );
+ directoriesLabel->setFrameShadow( TQLabel::Sunken );
+ synchGrid->addWidget( directoriesLabel, 2, 0 );
+
+ TQLabel *totalSizeLabel = new TQLabel( i18n( "Total Size:" ), loaderBox, "totalSizeLabel" );
+ totalSizeLabel->setFrameShape( TQLabel::StyledPanel );
+ totalSizeLabel->setFrameShadow( TQLabel::Sunken );
+ synchGrid->addWidget( totalSizeLabel, 3, 0 );
+
+ files = new TQLabel( loaderBox, "files" );
+ files->setFrameShape( TQLabel::StyledPanel );
+ files->setFrameShadow( TQLabel::Sunken );
+ files->setAlignment( TQt::AlignRight );
+ synchGrid->addWidget( files, 1, 1 );
+
+ directories = new TQLabel( loaderBox, "directories" );
+ directories->setFrameShape( TQLabel::StyledPanel );
+ directories->setFrameShadow( TQLabel::Sunken );
+ directories->setAlignment( TQt::AlignRight );
+ synchGrid->addWidget( directories, 2, 1 );
+
+ totalSize = new TQLabel( loaderBox, "totalSize" );
+ totalSize->setFrameShape( TQLabel::StyledPanel );
+ totalSize->setFrameShadow( TQLabel::Sunken );
+ totalSize->setAlignment( TQt::AlignRight );
+ synchGrid->addWidget( totalSize, 3, 1 );
+
+ int width;
+ searchedDirectory = new KSqueezedTextLabel( loaderBox, "searchedDirectory" );
+ searchedDirectory->setFrameShape( TQLabel::StyledPanel );
+ searchedDirectory->setFrameShadow( TQLabel::Sunken );
+ searchedDirectory->setMinimumWidth( width = TQFontMetrics(searchedDirectory->font()).width("W") * 30 );
+ searchedDirectory->setMaximumWidth( width );
+ synchGrid->addMultiCellWidget( searchedDirectory, 4, 4, 0, 1 );
+
+ TQFrame *line = new TQFrame( loaderBox, "duLine" );
+ line->setFrameStyle( TQFrame::HLine | TQFrame::Sunken );
+ synchGrid->addMultiCellWidget( line, 5, 5, 0, 1 );
+
+ TQHBox *hbox = new TQHBox( loaderBox, "hbox" );
+ TQSpacerItem* spacer = new TQSpacerItem( 0, 0, TQSizePolicy::Minimum, TQSizePolicy::Expanding );
+ hbox->layout()->addItem( spacer );
+ TQPushButton *cancelButton = new TQPushButton( hbox, "cancelButton" );
+ cancelButton->setText( i18n( "Cancel" ) );
+ synchGrid->addWidget( hbox, 6, 1 );
+
+ loaderLayout->addWidget( loaderBox, 0, 0 );
+
+ addChild( widget );
+
+ connect( cancelButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotCancelled() ) );
+}
+
+void LoaderWidget::resizeEvent ( TQResizeEvent *e )
+{
+ TQScrollView::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, TDEIO::filesize_t total )
+{
+ files->setText( TQString("%1").arg( fileNum ) );
+ directories->setText( TQString("%1").arg( dirNum ) );
+ totalSize->setText( TQString("%1").arg( KRpermHandler::parseSize( total ).stripWhiteSpace() ) );
+}
+
+void LoaderWidget::slotCancelled()
+{
+ cancelled = true;
+}
+
+DiskUsage::DiskUsage( TQString confGroup, TQWidget *parent, char *name ) : TQWidgetStack( 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, TQ_SIGNAL( timeout() ), this, TQ_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;
+
+ TQString 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( TQString dir )
+{
+ while( dir.endsWith( "/" ) )
+ dir.truncate( dir.length() - 1 );
+
+ if( dir.isEmpty() )
+ return root;
+
+ return contentMap.find( dir );
+}
+
+File * DiskUsage::getFile( TQString path )
+{
+ if( path == "" )
+ return root;
+
+ TQString dir = path;
+
+ int ndx = path.findRev( '/' );
+ TQString 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;
+
+ TDEIO::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();
+ }
+ }
+
+ TDEIO::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 ) ) {
+ TQString 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" );
+ }
+
+ TQStringList 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 );
+
+ TQString 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++;
+
+ TQGuardedPtr<TDEIO::Job> job;
+
+ if( trash )
+ {
+#if KDE_IS_VERSION(3,4,0)
+ job = TDEIO::trash( url, true );
+#else
+ job = new TDEIO::CopyJob( url,TDEGlobalSettings::trashPath(),TDEIO::CopyJob::Move,false,true );
+#endif
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),krApp,TQ_SLOT(changeTrashIcon()));
+ }
+ else
+ {
+ job = new TDEIO::DeleteJob( vfs::fromPathOrURL( file->fullPath() ), false, false);
+ }
+
+ deleting = true; // during tqApp->processEvent strange things can occur
+ grabMouse(); // that's why we disable the mouse and keyboard events
+ grabKeyboard();
+
+ while( !job.isNull() )
+ tqApp->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, TQString key )
+{
+ Properties * props = propertyMap.find( item );
+ if( props == 0 )
+ return 0;
+ return props->find( key );
+}
+
+void DiskUsage::addProperty( File *item, TQString 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, TQString 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, TDEPopupMenu *addPopup, TQString addPopupName )
+{
+ TDEPopupMenu 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( TQPixmap(), addPopup, ADDITIONAL_POPUP_ID );
+ popup.changeItem( ADDITIONAL_POPUP_ID, addPopupName );
+ }
+
+ TDEPopupMenu 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( TQPixmap(), &viewPopup, VIEW_POPUP_ID );
+ popup.changeItem( VIEW_POPUP_ID, i18n( "View" ) );
+
+ int result=popup.exec(TQCursor::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:
+ {
+ TQString 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( TQKeyEvent *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;
+ }
+ }
+ TQWidgetStack::keyPressEvent( e );
+}
+
+TQPixmap DiskUsage::getIcon( TQString mime )
+{
+ TQPixmap icon;
+
+ if ( !TQPixmapCache::find( mime, icon ) )
+ {
+ // get the icon.
+ if ( mime == "Broken Link !" )
+ icon = FL_LOADICON( "file_broken" );
+ else
+ icon = FL_LOADICON( KMimeType::mimeType( mime ) ->icon( TQString(), true ) );
+
+ // insert it into the cache
+ TQPixmapCache::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;
+}
+
+TQString DiskUsage::getToolTip( File *item )
+{
+ KMimeType::Ptr mimePtr = KMimeType::mimeType( item->mime() );
+ TQString mime = mimePtr->comment();
+
+ time_t tma = item->time();
+ struct tm* t=localtime((time_t *)&tma);
+ TQDateTime tmp(TQDate(t->tm_year+1900, t->tm_mon+1, t->tm_mday), TQTime(t->tm_hour, t->tm_min));
+ TQString date = TDEGlobal::locale()->formatDateTime(tmp);
+
+ TQString 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( TQEvent * e )
+{
+ if( deleting ) { // if we are deleting, disable the mouse and
+ switch( e->type() ) { // keyboard events
+ case TQEvent::MouseButtonPress:
+ case TQEvent::MouseButtonRelease:
+ case TQEvent::MouseButtonDblClick:
+ case TQEvent::MouseMove:
+ case TQEvent::KeyPress:
+ case TQEvent::KeyRelease:
+ return true;
+ default:
+ break;
+ }
+ }
+
+ if ( e->type() == TQEvent::AccelOverride )
+ {
+ TQKeyEvent* ke = (TQKeyEvent*) e;
+
+ if ( ke->state() == TQt::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 TQWidgetStack::event( e );
+}
+
+#include "diskusage.moc"
diff --git a/src/app/DiskUsage/diskusage.h b/src/app/DiskUsage/diskusage.h
new file mode 100644
index 0000000..ae70bdd
--- /dev/null
+++ b/src/app/DiskUsage/diskusage.h
@@ -0,0 +1,206 @@
+/***************************************************************************
+ 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 <tqdialog.h>
+#include <tqlabel.h>
+#include <tqdict.h>
+#include <tqptrlist.h>
+#include <tqptrdict.h>
+#include <tqvaluestack.h>
+#include <tqptrstack.h>
+#include <kurl.h>
+#include <ksqueezedtextlabel.h>
+#include <tqwidgetstack.h>
+#include <tqscrollview.h>
+#include <tqtimer.h>
+
+#define VIEW_LINES 0
+#define VIEW_DETAILED 1
+#define VIEW_FILELIGHT 2
+#define VIEW_LOADER 3
+
+typedef TQDict<void> Properties;
+
+class DUListView;
+class DULines;
+class DUFilelight;
+class TDEPopupMenu;
+class LoaderWidget;
+
+class DiskUsage : public TQWidgetStack
+{
+ TQ_OBJECT
+
+
+public:
+ DiskUsage( TQString confGroup, TQWidget *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( TQString path );
+ File * getFile( TQString path );
+
+ TQString getConfigGroup() { return configGroup; }
+
+ void * getProperty( File *, TQString );
+ void addProperty( File *, TQString, void * );
+ void removeProperty( File *, TQString );
+
+ int exclude( File *file, bool calcPercents = true, int depth = 0 );
+ void includeAll();
+
+ int del( File *file, bool calcPercents = true, int depth = 0 );
+
+ TQString getToolTip( File * );
+
+ void rightClickMenu( File *, TDEPopupMenu * = 0, TQString = TQString() );
+
+ void changeDirectory( Directory *dir );
+
+ Directory* getCurrentDir();
+ File* getCurrentFile();
+
+ TQPixmap getIcon( TQString 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( TQString );
+ void viewChanged( int );
+ void loadFinished( bool );
+ void newSearch();
+
+protected slots:
+ void slotLoadDirectory();
+
+protected:
+ TQDict< Directory > contentMap;
+ TQPtrDict<Properties> propertyMap;
+
+ Directory* currentDirectory;
+ TDEIO::filesize_t currentSize;
+
+ virtual void keyPressEvent( TQKeyEvent * );
+ virtual bool event( TQEvent * );
+
+ 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;
+
+ TQString configGroup;
+
+ bool first;
+ bool loading;
+ bool abortLoading;
+ bool clearAfterAbort;
+ bool deleting;
+
+ TQValueStack<TQString> directoryStack;
+ TQPtrStack<Directory> parentStack;
+
+ vfs * searchVfs;
+ vfile * currentVfile;
+ Directory * currentParent;
+ TQString dirToCheck;
+
+ int fileNum;
+ int dirNum;
+ int viewBeforeLoad;
+
+ TQTimer loadingTimer;
+};
+
+
+class LoaderWidget : public TQScrollView
+{
+ TQ_OBJECT
+
+
+public:
+ LoaderWidget( TQWidget *parent = 0, const char *name = 0 );
+
+ void init();
+ void setCurrentURL( KURL url );
+ void setValues( int fileNum, int dirNum, TDEIO::filesize_t total );
+ bool wasCancelled() { return cancelled; }
+
+public slots:
+ void slotCancelled();
+
+protected:
+ virtual void resizeEvent ( TQResizeEvent *e );
+
+ TQLabel *totalSize;
+ TQLabel *files;
+ TQLabel *directories;
+
+ KSqueezedTextLabel *searchedDirectory;
+ TQWidget *widget;
+
+ bool cancelled;
+};
+
+#endif /* __DISK_USAGE_GUI_H__ */
diff --git a/src/app/DiskUsage/diskusagegui.cpp b/src/app/DiskUsage/diskusagegui.cpp
new file mode 100644
index 0000000..28b52ce
--- /dev/null
+++ b/src/app/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 <tqtimer.h>
+#include <tqhbox.h>
+#include <tdelocale.h>
+#include <tqtooltip.h>
+
+DiskUsageGUI::DiskUsageGUI( KURL openDir, TQWidget* parent, const char *name )
+ : TQDialog( parent, name, false, 0 ), exitAtFailure( true )
+{
+ setCaption( i18n("Krusader::Disk Usage") );
+
+ baseDirectory = openDir;
+ if( !newSearch() )
+ return;
+
+ TQGridLayout *duGrid = new TQGridLayout( this );
+ duGrid->setSpacing( 6 );
+ duGrid->setMargin( 11 );
+
+ TQHBox *duTools = new TQHBox( this, "duTools" );
+ duTools->setSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed );
+
+ btnNewSearch = new TQToolButton( duTools, "btnNewSearch" );
+ btnNewSearch->setIconSet( TQIconSet(krLoader->loadIcon("document-open",TDEIcon::Desktop)) );
+ TQToolTip::add( btnNewSearch, i18n( "Start new disk usage search" ) );
+
+ btnRefresh = new TQToolButton( duTools, "btnRefresh" );
+ btnRefresh->setIconSet( TQIconSet(krLoader->loadIcon("reload",TDEIcon::Desktop)) );
+ TQToolTip::add( btnRefresh, i18n( "Refresh" ) );
+
+ btnDirUp = new TQToolButton( duTools, "btnDirUp" );
+ btnDirUp->setIconSet( TQIconSet(krLoader->loadIcon("go-up",TDEIcon::Desktop)) );
+ TQToolTip::add( btnDirUp, i18n( "Parent directory" ) );
+
+ TQWidget * separatorWidget = new TQWidget( duTools, "separatorWidget" );
+ separatorWidget->setMinimumWidth( 10 );
+
+ btnLines = new TQToolButton( duTools, "btnLines" );
+ btnLines->setIconSet( TQIconSet(krLoader->loadIcon("format-justify-left",TDEIcon::Desktop)) );
+ btnLines->setToggleButton( true );
+ TQToolTip::add( btnLines, i18n( "Line view" ) );
+
+ btnDetailed = new TQToolButton( duTools, "btnDetailed" );
+ btnDetailed->setIconSet( TQIconSet(krLoader->loadIcon("view_detailed",TDEIcon::Desktop)) );
+ btnDetailed->setToggleButton( true );
+ TQToolTip::add( btnDetailed, i18n( "Detailed view" ) );
+
+ btnFilelight = new TQToolButton( duTools, "btnFilelight" );
+ btnFilelight->setIconSet( TQIconSet(krLoader->loadIcon("kr_diskusage",TDEIcon::Desktop)) );
+ btnFilelight->setToggleButton( true );
+ TQToolTip::add( btnFilelight, i18n( "Filelight view" ) );
+
+ TQWidget *spacerWidget = new TQWidget( duTools, "spacerWidget" );
+ TQHBoxLayout *hboxlayout = new TQHBoxLayout( spacerWidget );
+ TQSpacerItem* spacer = new TQSpacerItem( 0, 0, TQSizePolicy::Expanding, TQSizePolicy::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( TQLabel::StyledPanel );
+ status->setFrameShadow( TQLabel::Sunken );
+ duGrid->addWidget( status, 2, 0 );
+
+ connect( diskUsage, TQ_SIGNAL( status( TQString ) ), this, TQ_SLOT( setStatus( TQString ) ) );
+ connect( diskUsage, TQ_SIGNAL( viewChanged( int ) ), this, TQ_SLOT( slotViewChanged( int ) ) );
+ connect( diskUsage, TQ_SIGNAL( newSearch() ), this, TQ_SLOT( newSearch() ) );
+ connect( diskUsage, TQ_SIGNAL( loadFinished( bool ) ), this, TQ_SLOT( slotLoadFinished( bool ) ) );
+ connect( btnNewSearch, TQ_SIGNAL( clicked() ), this, TQ_SLOT( newSearch() ) );
+ connect( btnRefresh, TQ_SIGNAL( clicked() ), this, TQ_SLOT( loadUsageInfo() ) );
+ connect( btnDirUp, TQ_SIGNAL( clicked() ), diskUsage, TQ_SLOT( dirUp() ) );
+ connect( btnLines, TQ_SIGNAL( clicked() ), this, TQ_SLOT( selectLinesView() ) );
+ connect( btnDetailed, TQ_SIGNAL( clicked() ), this, TQ_SLOT( selectListView() ) );
+ connect( btnFilelight, TQ_SIGNAL( clicked() ), this, TQ_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", TQFontMetrics(font()).width("W") * 70 );
+ sizeY = krConfig->readNumEntry( "Window Height", TQFontMetrics(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( TQResizeEvent *e )
+{
+ if( !isMaximized() )
+ {
+ sizeX = e->size().width();
+ sizeY = e->size().height();
+ }
+ TQDialog::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() );
+
+ TQDialog::reject();
+}
+
+void DiskUsageGUI::loadUsageInfo()
+{
+ diskUsage->load( baseDirectory );
+}
+
+void DiskUsageGUI::setStatus( TQString 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;
+
+ TQTimer::singleShot( 0, this, TQ_SLOT( loadUsageInfo() ) );
+ return true;
+}
+
+#include "diskusagegui.moc"
diff --git a/src/app/DiskUsage/diskusagegui.h b/src/app/DiskUsage/diskusagegui.h
new file mode 100644
index 0000000..1c75a79
--- /dev/null
+++ b/src/app/DiskUsage/diskusagegui.h
@@ -0,0 +1,90 @@
+/***************************************************************************
+ 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 <tqdialog.h>
+#include <tqlayout.h>
+#include <tqtoolbutton.h>
+#include <kurl.h>
+#include <ksqueezedtextlabel.h>
+
+#include "diskusage.h"
+
+class DiskUsageGUI : public TQDialog
+{
+ TQ_OBJECT
+
+
+public:
+ DiskUsageGUI( KURL openDir, TQWidget* parent=0, const char *name = 0 );
+ ~DiskUsageGUI();
+
+
+public slots:
+ void loadUsageInfo();
+ bool newSearch();
+ void setStatus( TQString );
+
+ 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( TQResizeEvent *e );
+
+ DiskUsage *diskUsage;
+ KURL baseDirectory;
+
+ KSqueezedTextLabel *status;
+
+ TQToolButton *btnNewSearch;
+ TQToolButton *btnRefresh;
+ TQToolButton *btnDirUp;
+
+ TQToolButton *btnLines;
+ TQToolButton *btnDetailed;
+ TQToolButton *btnFilelight;
+
+ int sizeX;
+ int sizeY;
+
+ bool exitAtFailure;
+};
+
+#endif /* __DISK_USAGE_GUI_H__ */
+
diff --git a/src/app/DiskUsage/dufilelight.cpp b/src/app/DiskUsage/dufilelight.cpp
new file mode 100644
index 0000000..debdb06
--- /dev/null
+++ b/src/app/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 <tdepopupmenu.h>
+#include <tdelocale.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( TQWidget::StrongFocus );
+
+ connect( diskUsage, TQ_SIGNAL( enteringDirectory( Directory * ) ), this, TQ_SLOT( slotDirChanged( Directory * ) ) );
+ connect( diskUsage, TQ_SIGNAL( clearing() ), this, TQ_SLOT( clear() ) );
+ connect( diskUsage, TQ_SIGNAL( changed( File * ) ), this, TQ_SLOT( slotChanged( File * ) ) );
+ connect( diskUsage, TQ_SIGNAL( deleted( File * ) ), this, TQ_SLOT( slotChanged( File * ) ) );
+ connect( diskUsage, TQ_SIGNAL( changeFinished() ), this, TQ_SLOT( slotRefresh() ) );
+ connect( diskUsage, TQ_SIGNAL( deleteFinished() ), this, TQ_SLOT( slotRefresh() ) );
+ connect( diskUsage, TQ_SIGNAL( aboutToShow( TQWidget * ) ), this, TQ_SLOT( slotAboutToShow( TQWidget * ) ) );
+}
+
+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( TQMouseEvent *event )
+{
+ if( event->button() == TQt::RightButton )
+ {
+ File * file = 0;
+
+ const RadialMap::Segment * focus = focusSegment();
+
+ if( focus && !focus->isFake() && focus->file() != currentDir )
+ file = (File *)focus->file();
+
+ TDEPopupMenu filelightPopup;
+ filelightPopup.insertItem( i18n("Zoom In"), this, TQ_SLOT( zoomIn() ), Key_Plus );
+ filelightPopup.insertItem( i18n("Zoom Out"), this, TQ_SLOT( zoomOut() ), Key_Minus );
+
+ TDEPopupMenu schemePopup;
+ schemePopup.insertItem( i18n("Rainbow"), this, TQ_SLOT( schemeRainbow() ) );
+ schemePopup.insertItem( i18n("High Contrast"), this, TQ_SLOT( schemeHighContrast() ) );
+ schemePopup.insertItem( i18n("TDE"), this, TQ_SLOT( schemeKDE() ) );
+
+ filelightPopup.insertItem( TQPixmap(), &schemePopup, SCHEME_POPUP_ID );
+ filelightPopup.changeItem( SCHEME_POPUP_ID, i18n( "Scheme" ) );
+
+ filelightPopup.insertItem( i18n("Increase contrast"), this, TQ_SLOT( increaseContrast() ) );
+ filelightPopup.insertItem( i18n("Decrease contrast"), this, TQ_SLOT( decreaseContrast() ) );
+
+ int aid = filelightPopup.insertItem( i18n("Use anti-aliasing" ), this, TQ_SLOT( changeAntiAlias() ) );
+ filelightPopup.setItemChecked( aid, Filelight::Config::antiAliasFactor > 1 );
+
+ int sid = filelightPopup.insertItem( i18n("Show small files" ), this, TQ_SLOT( showSmallFiles() ) );
+ filelightPopup.setItemChecked( sid, Filelight::Config::showSmallFiles );
+
+ int vid = filelightPopup.insertItem( i18n("Vary label font sizes" ), this, TQ_SLOT( varyLabelFontSizes() ) );
+ filelightPopup.setItemChecked( vid, Filelight::Config::varyLabelFontSizes );
+
+ filelightPopup.insertItem( i18n("Minimum font size"), this, TQ_SLOT( minFontSize() ) );
+
+ diskUsage->rightClickMenu( file, &filelightPopup, i18n( "Filelight" ) );
+ return;
+ }else if( event->button() == TQt::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( TQWidget *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/src/app/DiskUsage/dufilelight.h b/src/app/DiskUsage/dufilelight.h
new file mode 100644
index 0000000..9ef8ccb
--- /dev/null
+++ b/src/app/DiskUsage/dufilelight.h
@@ -0,0 +1,81 @@
+/***************************************************************************
+ 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
+{
+ TQ_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( TQWidget *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( TQMouseEvent* );
+
+ void setScheme( Filelight::MapScheme );
+
+ DiskUsage *diskUsage;
+ Directory *currentDir;
+
+private:
+ bool refreshNeeded;
+};
+
+#endif /* __DU_FILELIGHT_H__ */
+
diff --git a/src/app/DiskUsage/dulines.cpp b/src/app/DiskUsage/dulines.cpp
new file mode 100644
index 0000000..ba10a04
--- /dev/null
+++ b/src/app/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 <tqheader.h>
+#include <tdelocale.h>
+#include <tqpen.h>
+#include <tqpainter.h>
+#include <tqfontmetrics.h>
+#include <tqtimer.h>
+#include <tqtooltip.h>
+#include <tdepopupmenu.h>
+
+class DULinesItem : public TQListViewItem
+{
+public:
+ DULinesItem( DiskUsage *diskUsageIn, File *fileItem, TQListView * parent, TQString label1,
+ TQString label2, TQString label3, unsigned int italicPos ) : TQListViewItem( parent, label1, label2, label3 ),
+ diskUsage( diskUsageIn ), file( fileItem ), isTruncated( false ), italicTextPos( italicPos ) {}
+ DULinesItem( DiskUsage *diskUsageIn, File *fileItem, TQListView * parent, TQListViewItem * after,
+ TQString label1, TQString label2, TQString label3, unsigned int italicPos ) : TQListViewItem( parent, after, label1,
+ label2, label3 ), diskUsage( diskUsageIn ), file( fileItem ), isTruncated( false ), italicTextPos( italicPos ) {}
+
+ virtual int compare ( TQListViewItem * 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 );
+
+ TQString buf1,buf2;
+
+ switch( col )
+ {
+ case 0:
+ case 1:
+ buf1.sprintf("%025llu",file->size());
+ buf2.sprintf("%025llu",compWith->file->size());
+ return -TQString::compare( buf1, buf2 );
+ default:
+ return TQListViewItem::compare( i, col, ascending );
+ }
+ }
+
+ virtual void paintCell( TQPainter * p, const TQColorGroup & cg, int column, int width, int align )
+ {
+ if( column == 2 )
+ {
+ if ( isSelected() )
+ p->fillRect( 0, 0, width, height(), cg.brush( TQColorGroup::Highlight ) );
+ else
+ p->fillRect( 0, 0, width, height(), cg.brush( TQColorGroup::Base ) );
+
+ TQListView *lv = listView();
+
+ int pos = lv->itemMargin();
+
+ const TQPixmap *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;
+ }
+
+ TQFontMetrics fm( p->fontMetrics() );
+
+ if( isSelected() )
+ p->setPen( cg.highlightedText() );
+ else
+ p->setPen( cg.text() );
+
+ TQString t = text( column );
+ TQString 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 )
+ {
+ TQFont font( p->font() );
+ font.setItalic( true );
+ p->setFont( font );
+
+ TQFontMetrics 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
+ TQListViewItem::paintCell( p, cg, column, width, align );
+ }
+
+ inline File * getFile() { return file; }
+
+private:
+ DiskUsage *diskUsage;
+ File *file;
+
+ bool isTruncated;
+ unsigned int italicTextPos;
+};
+
+class DULinesToolTip : public TQToolTip
+{
+public:
+ DULinesToolTip( DiskUsage *usage, TQWidget *parent, TQListView *lv );
+ void maybeTip( const TQPoint &pos );
+
+ virtual ~DULinesToolTip() {}
+private:
+ TQListView *view;
+ DiskUsage *diskUsage;
+};
+
+DULinesToolTip::DULinesToolTip( DiskUsage *usage, TQWidget *parent, TQListView *lv )
+ : TQToolTip( parent ), view( lv ), diskUsage( usage )
+{
+}
+
+void DULinesToolTip::maybeTip( const TQPoint &pos )
+{
+ TQListViewItem *item = view->itemAt( pos );
+ TQPoint contentsPos = view->viewportToContents( pos );
+ if ( !item )
+ return;
+
+ int col = view->header()->sectionAt( contentsPos.x() );
+
+ int width = item->width( TQFontMetrics( view->font() ), view, col );
+
+ TQRect 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 )
+ : TQListView( usage, name ), diskUsage( usage ), refreshNeeded( false )
+{
+ setAllColumnsShowFocus(true);
+ setVScrollBarMode(TQScrollView::Auto);
+ setHScrollBarMode(TQScrollView::Auto);
+ setShowSortIndicator(true);
+ setTreeStepSize( 10 );
+
+ int defaultSize = TQFontMetrics(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,TQListView::Manual);
+ int precentWidth = krConfig->readNumEntry("L Percent Width", defaultSize * 6 );
+ addColumn( i18n("Percent"), precentWidth );
+ setColumnWidthMode(1,TQListView::Manual);
+ int nameWidth = krConfig->readNumEntry("L Name Width", defaultSize * 20 );
+ addColumn( i18n("Name"), nameWidth );
+ setColumnWidthMode(2,TQListView::Manual);
+
+ setColumnAlignment( 1, TQt::AlignRight );
+
+ header()->setStretchEnabled( true, 0 );
+
+ setSorting( 1 );
+
+ toolTip = new DULinesToolTip( diskUsage, viewport(), this );
+
+ connect( diskUsage, TQ_SIGNAL( enteringDirectory( Directory * ) ), this, TQ_SLOT( slotDirChanged( Directory * ) ) );
+ connect( diskUsage, TQ_SIGNAL( clearing() ), this, TQ_SLOT( clear() ) );
+
+ connect( header(), TQ_SIGNAL( sizeChange( int, int, int ) ), this, TQ_SLOT( sectionResized( int ) ) );
+
+ connect( this, TQ_SIGNAL(rightButtonPressed(TQListViewItem *, const TQPoint &, int)),
+ this, TQ_SLOT( slotRightClicked(TQListViewItem *) ) );
+ connect( diskUsage, TQ_SIGNAL( changed( File * ) ), this, TQ_SLOT( slotChanged( File * ) ) );
+ connect( diskUsage, TQ_SIGNAL( deleted( File * ) ), this, TQ_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();
+
+ TQListViewItem * lastItem = 0;
+
+ if( ! ( dirEntry->parent() == 0 ) )
+ {
+ lastItem = new TQListViewItem( this, ".." );
+ lastItem->setPixmap( 0, FL_LOADICON( "go-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;
+
+ TQString fileName = item->name();
+
+ unsigned int italicStart = fileName.length();
+
+ if( showFileSize )
+ fileName += " [" + TDEIO::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() );
+}
+
+TQPixmap DULines::createPixmap( int percent, int maxPercent, int maxWidth )
+{
+ if( percent < 0 || percent > maxPercent || maxWidth < 2 || maxPercent == 0 )
+ return TQPixmap();
+ maxWidth -= 2;
+
+ int actualWidth = maxWidth*percent/maxPercent;
+ if( actualWidth == 0 )
+ return TQPixmap();
+
+ TQPen pen;
+ pen.setColor( TQt::black );
+ TQPainter painter;
+
+ int size = TQFontMetrics(font()).height()-2;
+ TQRect rect( 0, 0, actualWidth, size );
+ TQPixmap 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( TQColor( 255-color, 255, 0 ) );
+ else
+ pen.setColor( TQColor( color-256, 511-color, 0 ) );
+
+ painter.setPen( pen );
+ painter.drawLine( i, 1, i, size-1 );
+ }
+
+ pen.setColor( TQt::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( TQListViewItem * 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 ( TQMouseEvent * e )
+{
+ if ( e || e->button() == TQt::LeftButton )
+ {
+ TQPoint vp = contentsToViewport(e->pos());
+ TQListViewItem * item = itemAt( vp );
+
+ if( doubleClicked( item ) )
+ return;
+
+ }
+ TQListView::contentsMouseDoubleClickEvent( e );
+}
+
+
+void DULines::keyPressEvent( TQKeyEvent *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;
+ }
+ TQListView::keyPressEvent( e );
+}
+
+void DULines::slotRightClicked( TQListViewItem *item )
+{
+ File * file = 0;
+
+ if ( item && item->text( 0 ) != ".." )
+ file = ((DULinesItem *)item)->getFile();
+
+ TDEPopupMenu linesPopup;
+ int lid = linesPopup.insertItem( i18n("Show file sizes"), this, TQ_SLOT( slotShowFileSizes() ) );
+ linesPopup.setItemChecked( lid, showFileSize );
+
+ diskUsage->rightClickMenu( file, &linesPopup, i18n( "Lines" ) );
+}
+
+void DULines::slotShowFileSizes()
+{
+ showFileSize = !showFileSize;
+ slotDirChanged( diskUsage->getCurrentDir() );
+}
+
+File * DULines::getCurrentFile()
+{
+ TQListViewItem *item = currentItem();
+
+ if( item == 0 || item->text( 0 ) == ".." )
+ return 0;
+
+ return ((DULinesItem *)item)->getFile();
+}
+
+void DULines::slotChanged( File * item )
+{
+ TQListViewItem *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;
+ TQTimer::singleShot( 0, this, TQ_SLOT( slotRefresh() ) );
+ }
+ break;
+ }
+ }
+ lvitem = lvitem->nextSibling();
+ }
+}
+
+void DULines::slotDeleted( File * item )
+{
+ TQListViewItem *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/src/app/DiskUsage/dulines.h b/src/app/DiskUsage/dulines.h
new file mode 100644
index 0000000..7531c86
--- /dev/null
+++ b/src/app/DiskUsage/dulines.h
@@ -0,0 +1,79 @@
+/***************************************************************************
+ 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 <tqlistview.h>
+#include <tqpixmap.h>
+#include "diskusage.h"
+
+class DULinesToolTip;
+
+class DULines : public TQListView
+{
+ TQ_OBJECT
+
+
+public:
+ DULines( DiskUsage *usage, const char *name );
+ ~DULines();
+
+ File * getCurrentFile();
+
+public slots:
+ void slotDirChanged( Directory *dirEntry );
+ void sectionResized( int );
+ void slotRightClicked(TQListViewItem *);
+ void slotChanged( File * );
+ void slotDeleted( File * );
+ void slotShowFileSizes();
+ void slotRefresh() { refreshNeeded = false; sectionResized( 0 ); }
+
+protected:
+ DiskUsage *diskUsage;
+
+ virtual void contentsMouseDoubleClickEvent ( TQMouseEvent * e );
+ virtual void keyPressEvent( TQKeyEvent *e );
+
+private:
+ TQPixmap createPixmap( int percent, int maxPercent, int maxWidth );
+
+ bool doubleClicked( TQListViewItem * item );
+
+ bool refreshNeeded;
+
+ bool showFileSize;
+
+ DULinesToolTip *toolTip;
+};
+
+#endif /* __DU_LINES_H__ */
+
diff --git a/src/app/DiskUsage/dulistview.cpp b/src/app/DiskUsage/dulistview.cpp
new file mode 100644
index 0000000..dc40690
--- /dev/null
+++ b/src/app/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 <tqfontmetrics.h>
+#include <tdelocale.h>
+#include <kmimetype.h>
+#include <tdeglobal.h>
+#include <tqheader.h>
+#include <time.h>
+
+DUListView::DUListView( DiskUsage *usage, const char *name )
+ : TQListView( usage, name ), diskUsage( usage )
+{
+ setAllColumnsShowFocus(true);
+ setVScrollBarMode(TQScrollView::Auto);
+ setHScrollBarMode(TQScrollView::Auto);
+ setShowSortIndicator(true);
+ setRootIsDecorated( true );
+ setTreeStepSize( 10 );
+
+ int defaultSize = TQFontMetrics(font()).width("W");
+
+ krConfig->setGroup( diskUsage->getConfigGroup() );
+ int nameWidth = krConfig->readNumEntry("D Name Width", defaultSize * 20 );
+ addColumn( i18n("Name"), nameWidth );
+ setColumnWidthMode(0,TQListView::Manual);
+ int percentWidth = krConfig->readNumEntry("D Percent Width", defaultSize * 5 );
+ addColumn( i18n("Percent"), percentWidth );
+ setColumnWidthMode(1,TQListView::Manual);
+ int totalSizeWidth = krConfig->readNumEntry("D Total Size Width", defaultSize * 10 );
+ addColumn( i18n("Total size"), totalSizeWidth );
+ setColumnWidthMode(1,TQListView::Manual);
+ int ownSizeWidth = krConfig->readNumEntry("D Own Size Width", defaultSize * 10 );
+ addColumn( i18n("Own size"), ownSizeWidth );
+ setColumnWidthMode(2,TQListView::Manual);
+ int typeWidth = krConfig->readNumEntry("D Type Width", defaultSize * 10 );
+ addColumn( i18n("Type"), typeWidth );
+ setColumnWidthMode(3,TQListView::Manual);
+ int dateWidth = krConfig->readNumEntry("D Date Width", defaultSize * 10 );
+ addColumn( i18n("Date"), dateWidth );
+ setColumnWidthMode(4,TQListView::Manual);
+ int permissionsWidth = krConfig->readNumEntry("D Permissions Width", defaultSize * 6 );
+ addColumn( i18n("Permissions"), permissionsWidth );
+ setColumnWidthMode(5,TQListView::Manual);
+ int ownerWidth = krConfig->readNumEntry("D Owner Width", defaultSize * 5 );
+ addColumn( i18n("Owner"), ownerWidth );
+ setColumnWidthMode(6,TQListView::Manual);
+ int groupWidth = krConfig->readNumEntry("D Group Width", defaultSize * 5 );
+ addColumn( i18n("Group"), groupWidth );
+ setColumnWidthMode(7,TQListView::Manual);
+
+ setColumnAlignment( 1, TQt::AlignRight );
+ setColumnAlignment( 2, TQt::AlignRight );
+ setColumnAlignment( 3, TQt::AlignRight );
+
+ setSorting( 2 );
+
+ connect( diskUsage, TQ_SIGNAL( enteringDirectory( Directory * ) ), this, TQ_SLOT( slotDirChanged( Directory * ) ) );
+ connect( diskUsage, TQ_SIGNAL( clearing() ), this, TQ_SLOT( clear() ) );
+ connect( diskUsage, TQ_SIGNAL( changed( File * ) ), this, TQ_SLOT( slotChanged( File * ) ) );
+ connect( diskUsage, TQ_SIGNAL( deleted( File * ) ), this, TQ_SLOT( slotDeleted( File * ) ) );
+
+ connect( this, TQ_SIGNAL(rightButtonPressed(TQListViewItem *, const TQPoint &, int)),
+ this, TQ_SLOT( slotRightClicked(TQListViewItem *) ) );
+ connect( this, TQ_SIGNAL( expanded ( TQListViewItem * ) ),
+ this, TQ_SLOT( slotExpanded( TQListViewItem * ) ) );
+}
+
+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, TQListViewItem *parent )
+{
+ TQListViewItem * lastItem = 0;
+
+ if( parent == 0 && ! ( dirEntry->parent() == 0 ) )
+ {
+ lastItem = new TQListViewItem( this, ".." );
+ lastItem->setPixmap( 0, FL_LOADICON( "go-up" ) );
+ lastItem->setSelectable( false );
+ }
+
+ for( Iterator<File> it = dirEntry->iterator(); it != dirEntry->end(); ++it )
+ {
+ File *item = *it;
+
+ KMimeType::Ptr mimePtr = KMimeType::mimeType( item->mime() );
+ TQString mime = mimePtr->comment();
+
+ time_t tma = item->time();
+ struct tm* t=localtime((time_t *)&tma);
+ TQDateTime tmp(TQDate(t->tm_year+1900, t->tm_mon+1, t->tm_mday), TQTime(t->tm_hour, t->tm_min));
+ TQString date = TDEGlobal::locale()->formatDateTime(tmp);
+
+ TQString totalSize = KRpermHandler::parseSize( item->size() ) + " ";
+ TQString ownSize = KRpermHandler::parseSize( item->ownSize() ) + " ";
+ TQString 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 );
+ }
+
+ TQListViewItem *first = firstChild();
+ if( first )
+ setCurrentItem( first );
+}
+
+void DUListView::slotDirChanged( Directory *dirEntry )
+{
+ clear();
+ addDirectory( dirEntry, 0 );
+}
+
+File * DUListView::getCurrentFile()
+{
+ TQListViewItem *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( TQListViewItem *item )
+{
+ File * file = 0;
+
+ if ( item && item->text( 0 ) != ".." )
+ file = ((DUListViewItem *)item)->getFile();
+
+ diskUsage->rightClickMenu( file );
+}
+
+bool DUListView::doubleClicked( TQListViewItem * 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 ( TQMouseEvent * e )
+{
+ if ( e || e->button() == TQt::LeftButton )
+ {
+ TQPoint vp = contentsToViewport(e->pos());
+ TQListViewItem * item = itemAt( vp );
+
+ if( doubleClicked( item ) )
+ return;
+
+ }
+ TQListView::contentsMouseDoubleClickEvent( e );
+}
+
+void DUListView::keyPressEvent( TQKeyEvent *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;
+ }
+ TQListView::keyPressEvent( e );
+}
+
+void DUListView::slotExpanded( TQListViewItem *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/src/app/DiskUsage/dulistview.h b/src/app/DiskUsage/dulistview.h
new file mode 100644
index 0000000..9e9fdb4
--- /dev/null
+++ b/src/app/DiskUsage/dulistview.h
@@ -0,0 +1,145 @@
+/***************************************************************************
+ 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 <tqlistview.h>
+#include "diskusage.h"
+
+class DUListViewItem : public TQListViewItem
+{
+public:
+ DUListViewItem( DiskUsage *diskUsageIn, File *fileIn, TQListView * parent, TQString label1,
+ TQString label2, TQString label3, TQString label4, TQString label5, TQString label6,
+ TQString label7, TQString label8, TQString label9 )
+ : TQListViewItem( 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, TQListViewItem * parent, TQString label1,
+ TQString label2, TQString label3, TQString label4, TQString label5, TQString label6,
+ TQString label7, TQString label8, TQString label9 )
+ : TQListViewItem( 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, TQListView * parent, TQListViewItem * after,
+ TQString label1, TQString label2, TQString label3, TQString label4, TQString label5,
+ TQString label6, TQString label7, TQString label8, TQString label9 )
+ : TQListViewItem( 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, TQListViewItem * parent, TQListViewItem * after,
+ TQString label1, TQString label2, TQString label3, TQString label4, TQString label5,
+ TQString label6, TQString label7, TQString label8, TQString label9 )
+ : TQListViewItem( 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 ( TQListViewItem * 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 );
+
+ TQString buf1,buf2;
+
+ switch( col )
+ {
+ case 1:
+ case 2:
+ buf1.sprintf("%025llu",file->size());
+ buf2.sprintf("%025llu",compWith->file->size());
+ return -TQString::compare( buf1, buf2 );
+ case 3:
+ buf1.sprintf("%025llu",file->ownSize());
+ buf2.sprintf("%025llu",compWith->file->ownSize());
+ return -TQString::compare( buf1, buf2 );
+ case 5:
+ return TQListViewItem::compare( i, col, !ascending );
+ default:
+ return TQListViewItem::compare( i, col, ascending );
+ }
+ }
+
+ inline File * getFile() { return file; }
+
+private:
+ DiskUsage *diskUsage;
+ File *file;
+};
+
+class DUListView : public TQListView
+{
+ TQ_OBJECT
+
+
+public:
+ DUListView( DiskUsage *usage, const char *name );
+ ~DUListView();
+
+ File * getCurrentFile();
+
+public slots:
+ void slotDirChanged( Directory * );
+ void slotChanged( File * );
+ void slotDeleted( File * );
+ void slotRightClicked(TQListViewItem *);
+ void slotExpanded( TQListViewItem * );
+
+protected:
+ DiskUsage *diskUsage;
+
+ virtual void contentsMouseDoubleClickEvent ( TQMouseEvent * e );
+ virtual void keyPressEvent( TQKeyEvent *e );
+
+private:
+ void addDirectory( Directory *dirEntry, TQListViewItem *parent );
+ bool doubleClicked( TQListViewItem * item );
+};
+
+#endif /* __DU_LISTVIEW_H__ */
+
diff --git a/src/app/DiskUsage/filelightParts/Config.cpp b/src/app/DiskUsage/filelightParts/Config.cpp
new file mode 100644
index 0000000..bf25a29
--- /dev/null
+++ b/src/app/DiskUsage/filelightParts/Config.cpp
@@ -0,0 +1,50 @@
+
+#include "Config.h"
+#include <tdeconfig.h>
+#include <tdeglobal.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 TDEConfig&
+Filelight::Config::tdeconfig()
+{
+ TDEConfig *config = TDEGlobal::config();
+ config->setGroup( "DiskUsage" );
+ return *config;
+}
+
+void
+Filelight::Config::read()
+{
+ const TDEConfig &config = tdeconfig();
+
+ varyLabelFontSizes = config.readBoolEntry( "varyLabelFontSizes", true );
+ showSmallFiles = config.readBoolEntry( "showSmallFiles", false );
+ contrast = config.readNumEntry( "contrast", 50 );
+ antiAliasFactor = config.readNumEntry( "antiAliasFactor", 2 );
+ minFontPitch = config.readNumEntry( "minFontPitch", TQFont().pointSize() - 3);
+ scheme = (MapScheme) config.readNumEntry( "scheme", 0 );
+
+ defaultRingDepth = 4;
+}
+
+void
+Filelight::Config::write()
+{
+ TDEConfig &config = tdeconfig();
+
+ 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/src/app/DiskUsage/filelightParts/Config.h b/src/app/DiskUsage/filelightParts/Config.h
new file mode 100644
index 0000000..52a98b7
--- /dev/null
+++ b/src/app/DiskUsage/filelightParts/Config.h
@@ -0,0 +1,37 @@
+
+#ifndef Config_H
+#define Config_H
+
+#include <tqstringlist.h>
+
+class TDEConfig;
+
+
+namespace Filelight
+{
+ enum MapScheme { Rainbow, HighContrast, KDE, FileDensity, ModTime };
+
+ class Config
+ {
+ static TDEConfig& tdeconfig();
+
+ 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/src/app/DiskUsage/filelightParts/Makefile.am b/src/app/DiskUsage/filelightParts/Makefile.am
new file mode 100644
index 0000000..002f461
--- /dev/null
+++ b/src/app/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/src/app/DiskUsage/filelightParts/debug.h b/src/app/DiskUsage/filelightParts/debug.h
new file mode 100644
index 0000000..252a001
--- /dev/null
+++ b/src/app/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/src/app/DiskUsage/filelightParts/fileTree.cpp b/src/app/DiskUsage/filelightParts/fileTree.cpp
new file mode 100644
index 0000000..0afd4d4
--- /dev/null
+++ b/src/app/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 <tdeglobal.h>
+#include <tdelocale.h>
+#include <tqstring.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" };
+
+TQString
+File::fullPath( const Directory *root /*= 0*/ ) const
+{
+ TQString 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;
+}
+
+TQString
+File::humanReadableSize( UnitPrefix key /*= mega*/ ) const //FIXME inline
+{
+ return humanReadableSize( m_size, key );
+}
+
+TQString
+File::humanReadableSize( FileSize size, UnitPrefix key /*= mega*/ ) //static
+{
+ TQString s;
+ double prettySize = (double)size / (double)DENOMINATOR[key];
+ const TDELocale &locale = *TDEGlobal::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/src/app/DiskUsage/filelightParts/fileTree.h b/src/app/DiskUsage/filelightParts/fileTree.h
new file mode 100644
index 0000000..2ba79ae
--- /dev/null
+++ b/src/app/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 <tdeio/global.h>
+
+//TODO these are pointlessly general purpose now, make them incredibly specific
+
+
+
+typedef TDEIO::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 TQString;
+class KURL;
+
+class File
+{
+protected:
+ Directory *m_parent; //0 if this is treeRoot
+ TQString m_name; //< file name
+ TQString 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
+ TQString m_owner; //< file owner name
+ TQString m_group; //< file group name
+ TQString 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
+ TQString 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 TQString &nameIn, const TQString &dir, FileSize sizeIn, mode_t modeIn,
+ const TQString &ownerIn, const TQString &groupIn, const TQString &permIn, time_t timeIn, bool symLinkIn,
+ const TQString &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 TQString &nameIn, FileSize sizeIn )
+ : m_parent( 0 ), m_name( nameIn ), m_directory( TQString() ), m_size( sizeIn ), m_ownSize( sizeIn ), m_mode( 0 ),
+ m_owner( TQString() ), m_group( TQString() ), m_perm( TQString() ), m_time( -1 ),
+ m_symLink( false ), m_mimeType( TQString() ), m_excluded( false ), m_percent( -1 )
+ {
+ }
+
+ virtual ~File() {}
+
+ inline const TQString & name() const {return m_name;}
+ inline const TQString & 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 TQString & owner() const {return m_owner;}
+ inline const TQString & group() const {return m_group;}
+ inline const TQString & perm() const {return m_perm;}
+ inline const time_t time() const {return m_time;}
+ inline const TQString & 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 TQString percent() const {if( m_percent < 0 )
+ return "INV";
+ TQString 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( TDEIO::filesize_t totalSize, TDEIO::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];
+
+ TQString fullPath( const Directory* = 0 ) const;
+ TQString humanReadableSize( UnitPrefix key = mega ) const;
+
+ static TQString 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 TQString &nameIn, const TQString &dir, FileSize sizeIn, mode_t modeIn,
+ const TQString &ownerIn, const TQString &groupIn, const TQString &permIn, time_t timeIn, bool symLinkIn,
+ const TQString &mimeTypeIn )
+ : File( parentIn, nameIn, dir, sizeIn, modeIn, ownerIn, groupIn, permIn, timeIn, symLinkIn, mimeTypeIn ),
+ m_fileCount( 0 )
+ {}
+
+ Directory( const TQString &name, TQString 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/src/app/DiskUsage/radialMap/Makefile.am b/src/app/DiskUsage/radialMap/Makefile.am
new file mode 100644
index 0000000..ab5effd
--- /dev/null
+++ b/src/app/DiskUsage/radialMap/Makefile.am
@@ -0,0 +1,13 @@
+noinst_LIBRARIES = libradialmap.a
+
+INCLUDES = -I$(top_srcdir)/src/app/DiskUsage/filelightParts $(all_includes)
+
+METASOURCES = AUTO
+
+libradialmap_a_SOURCES = \
+ widget.cpp \
+ builder.cpp \
+ map.cpp \
+ widgetEvents.cpp \
+ labels.cpp \
+ segmentTip.cpp
diff --git a/src/app/DiskUsage/radialMap/builder.cpp b/src/app/DiskUsage/radialMap/builder.cpp
new file mode 100644
index 0000000..8edb70c
--- /dev/null
+++ b/src/app/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 <tdeglobal.h> //locale object
+#include <tdelocale.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 TQString s = i18n( "%1 files: ~ %2" ).arg( TDEGlobal::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/src/app/DiskUsage/radialMap/builder.h b/src/app/DiskUsage/radialMap/builder.h
new file mode 100644
index 0000000..2fddbe0
--- /dev/null
+++ b/src/app/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/src/app/DiskUsage/radialMap/labels.cpp b/src/app/DiskUsage/radialMap/labels.cpp
new file mode 100644
index 0000000..5d61b7a
--- /dev/null
+++ b/src/app/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 <tqfont.h>
+#include <tqfontmetrics.h>
+#include <tqpainter.h>
+#include <tqptrlist.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;
+
+ TQString qs;
+ };
+
+ class LabelList : public TQPtrList<Label>
+ {
+ protected:
+ int compareItems( TQPtrCollection::Item item1, TQPtrCollection::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( TQPainter &paint ) const
+{
+ //we are a friend of RadialMap::Map
+
+ LabelList list; list.setAutoDelete( true );
+ TQPtrListIterator<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();
+ TQPtrListIterator<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;
+
+ TQFont font;
+
+ for( it.toFirst(); it != 0; ++it )
+ {
+ //** bear in mind that text is drawn with TQPoint param as BOTTOM left corner of text box
+ if( varySizes ) font.setPointSize( sizes[(*it)->lvl] );
+ TQFontMetrics 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;
+
+ TQString 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( TQPen( TQt::black, 1 ) );
+
+ for( it.toFirst(); it != 0; ++it )
+ {
+ if( varySizes )
+ {
+ //**** how much overhead in making new TQFont each time?
+ // (implicate sharing remember)
+ TQFont 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/src/app/DiskUsage/radialMap/map.cpp b/src/app/DiskUsage/radialMap/map.cpp
new file mode 100644
index 0000000..329b8bc
--- /dev/null
+++ b/src/app/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 <tdeglobalsettings.h> //kdeColours
+#include <kimageeffect.h> //desaturate()
+#include <tqapplication.h> //make()
+#include <tqimage.h> //make() & paint()
+#include <tqfont.h> //ctor
+#include <tqfontmetrics.h> //ctor
+#include <tqpainter.h>
+
+#include "builder.h"
+#include "Config.h"
+#include "fileTree.h"
+#include "sincos.h"
+#include "widget.h"
+
+#define COLOR_GREY TQColor( 0, 0, 140, TQColor::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 = TQFontMetrics( TQFont() ).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 )
+ {
+ TQImage 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
+ TQApplication::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();
+
+ TQApplication::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 TQRect &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 TQRect 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()
+{
+ TQColor cp, cb;
+ double darkness = 1;
+ double contrast = (double)Config::contrast / (double)100;
+ int h, s1, s2, v1, v2;
+
+ TQColor kdeColour[2] = { TDEGlobalSettings::inactiveTitleColor(), TDEGlobalSettings::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 = TQApplication::palette().active().color( TQColorGroup::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 = TQt::gray;
+ cb = TQt::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 TQt::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)
+ TQApplication::setOverrideCursor( KCursor::waitCursor() );
+ paint( Config::antiAliasFactor );
+ TQApplication::restoreOverrideCursor();
+}
+
+void
+RadialMap::Map::paint( unsigned int scaleFactor )
+{
+ if( scaleFactor == 0 ) //just in case
+ scaleFactor = 1;
+
+ TQPainter paint;
+ TQRect 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
+ TQPointArray pts( 3 );
+ TQPoint pos, cpos = rect.center();
+ uint 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();
+ TQPen pen = paint.pen();
+ int width = 2 * scaleFactor;
+ pen.setWidth( width );
+ paint.setPen( pen );
+ TQRect 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( TQt::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 );
+
+ TQImage img = this->convertToImage();
+ img = img.smoothScale( this->size() / (int)scaleFactor );
+ this->convertFromImage( img );
+
+ paint.begin( this );
+ paint.setPen( COLOR_GREY );
+ paint.setBrush( TQt::white );
+ }
+
+ paint.drawText( rect, TQt::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/src/app/DiskUsage/radialMap/radialMap.h b/src/app/DiskUsage/radialMap/radialMap.h
new file mode 100644
index 0000000..c5edf65
--- /dev/null
+++ b/src/app/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 <tqcolor.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 TQColor& pen() const { return m_pen; }
+ const TQColor& 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 TQColor &p, const TQColor &b ) { m_pen = p; m_brush = b; }
+
+ const uint m_angleStart, m_angleSegment;
+ const File* const m_file;
+ TQColor 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/src/app/DiskUsage/radialMap/segmentTip.cpp b/src/app/DiskUsage/radialMap/segmentTip.cpp
new file mode 100644
index 0000000..2f2b31c
--- /dev/null
+++ b/src/app/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 <tdeapplication.h> //installing eventFilters
+#include <tdeglobal.h>
+#include <tdeglobalsettings.h>
+#include <tdelocale.h>
+#include <kpixmapeffect.h>
+#include <tqpainter.h>
+#include <tqtooltip.h> //for its palette
+
+
+
+namespace RadialMap {
+
+SegmentTip::SegmentTip( uint h )
+ : TQWidget( 0, 0, WNoAutoErase | WStyle_Customize | WStyle_NoBorder | WStyle_Tool | WStyle_StaysOnTop | WX11BypassWM )
+ , m_cursorHeight( -h )
+{
+ setBackgroundMode( TQt::NoBackground );
+}
+
+void
+SegmentTip::moveto( TQPoint p, const TQWidget &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 TQRect screen = TDEGlobalSettings::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 TQPoint to determine where to offset the bitBlt in m_pixmap
+ TQPoint offset = canvas.mapToGlobal( TQPoint() ) - p;
+ if( offset.x() < 0 ) offset.setX( 0 );
+ if( offset.y() < 0 ) offset.setY( 0 );
+
+
+ const TQRect alphaMaskRect( canvas.mapFromGlobal( p ), size() );
+ const TQRect 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, TQt::CopyROP );
+
+ TQPainter paint( &m_pixmap );
+ paint.setPen( TQt::black );
+ paint.setBrush( TQt::NoBrush );
+ paint.drawRect( rect() );
+ paint.end();
+
+ m_pixmap = KPixmapEffect::fade( m_pixmap, 0.6, TQToolTip::palette().color( TQPalette::Active, TQColorGroup::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 TQString s1 = file->fullPath( root );
+ TQString s2 = file->humanReadableSize();
+ TDELocale *loc = TDEGlobal::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 += TQString( " (%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());
+ TQString s3 = i18n( "Files: %1" ).arg( loc->formatNumber( files, 0 ) );
+
+ if( pc > 0 ) s3 += TQString( " (%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( TQEvent *e )
+{
+ switch( e->type() )
+ {
+ case TQEvent::Show:
+ kapp->installEventFilter( this );
+ break;
+ case TQEvent::Hide:
+ kapp->removeEventFilter( this );
+ break;
+ case TQEvent::Paint:
+ {
+ //TQPainter( this ).drawPixmap( 0, 0, m_pixmap );
+ bitBlt( this, 0, 0, &m_pixmap );
+ return true;
+ }
+ default:
+ ;
+ }
+
+ return false/*TQWidget::event( e )*/;
+}
+
+bool
+SegmentTip::eventFilter( TQObject*, TQEvent *e )
+{
+ switch ( e->type() )
+ {
+ case TQEvent::Leave:
+// case TQEvent::MouseButtonPress:
+// case TQEvent::MouseButtonRelease:
+ case TQEvent::KeyPress:
+ case TQEvent::KeyRelease:
+ case TQEvent::FocusIn:
+ case TQEvent::FocusOut:
+ case TQEvent::Wheel:
+ hide(); //FALL THROUGH
+ default:
+ return false; //allow this event to passed to target
+ }
+}
+
+} //namespace RadialMap
diff --git a/src/app/DiskUsage/radialMap/segmentTip.h b/src/app/DiskUsage/radialMap/segmentTip.h
new file mode 100644
index 0000000..7f279cb
--- /dev/null
+++ b/src/app/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 <tqwidget.h>
+
+class File;
+class Directory;
+
+namespace RadialMap
+{
+ class SegmentTip : public TQWidget
+ {
+ public:
+ SegmentTip( uint );
+
+ void updateTip( const File*, const Directory* );
+ void moveto( TQPoint, const TQWidget&, bool );
+
+ private:
+ virtual bool eventFilter( TQObject*, TQEvent* );
+ virtual bool event( TQEvent* );
+
+ uint m_cursorHeight;
+ KPixmap m_pixmap;
+ TQString m_text;
+ };
+}
+
+#endif
diff --git a/src/app/DiskUsage/radialMap/sincos.h b/src/app/DiskUsage/radialMap/sincos.h
new file mode 100644
index 0000000..5e66e54
--- /dev/null
+++ b/src/app/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/src/app/DiskUsage/radialMap/widget.cpp b/src/app/DiskUsage/radialMap/widget.cpp
new file mode 100644
index 0000000..4ed038f
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <kurl.h>
+#include <tqapplication.h> //sendEvent
+#include <tqbitmap.h> //ctor - finding cursor size
+#include <tqcursor.h> //slotPostMouseEvent()
+#include <tqtimer.h> //member
+
+#include "Config.h"
+#include "debug.h"
+#include "fileTree.h"
+#include "radialMap.h" //constants
+#include "widget.h"
+
+
+
+RadialMap::Widget::Widget( TQWidget *parent, const char *name )
+ : TQWidget( parent, name, TQt::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( TQt::white );
+
+ connect( this, TQ_SIGNAL(created( const Directory* )), TQ_SLOT(sendFakeMouseEvent()) );
+ connect( this, TQ_SIGNAL(created( const Directory* )), TQ_SLOT(update()) );
+ connect( &m_timer, TQ_SIGNAL(timeout()), TQ_SLOT(resizeTimeout()) );
+}
+
+TQString
+RadialMap::Widget::path() const
+{
+ if( m_tree == 0 )
+ return TQString();
+ 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
+{
+ TQMouseEvent me( TQEvent::MouseMove, mapFromGlobal( TQCursor::pos() ), TQt::NoButton, TQt::NoButton );
+ TQApplication::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/src/app/DiskUsage/radialMap/widget.h b/src/app/DiskUsage/radialMap/widget.h
new file mode 100644
index 0000000..83c6baa
--- /dev/null
+++ b/src/app/DiskUsage/radialMap/widget.h
@@ -0,0 +1,111 @@
+//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 <tqtimer.h>
+#include "segmentTip.h"
+
+template <class T> class Chain;
+class Directory;
+class File;
+namespace TDEIO { class Job; }
+class KURL;
+
+namespace RadialMap
+{
+ class Segment;
+
+ class Map : public KPixmap
+ {
+ public:
+ Map();
+ ~Map();
+
+ void make( const Directory *, bool = false );
+ bool resize( const TQRect& );
+
+ 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;
+
+ TQRect m_rect;
+ uint m_ringBreadth; ///ring breadth
+ uint m_innerRadius; ///radius of inner circle
+ uint m_visibleDepth; ///visible level depth of system
+ TQString m_centerText;
+
+ uint MAP_2MARGIN;
+ };
+
+ class Widget : public TQWidget
+ {
+ TQ_OBJECT
+
+
+ public:
+ Widget( TQWidget* = 0, const char* = 0 );
+
+ TQString 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( TDEIO::Job* );
+ void createFromCache( const Directory* );
+
+ signals:
+ void activated( const KURL& );
+ void invalidated( const KURL& );
+ void created( const Directory* );
+ void mouseHover( const TQString& );
+
+ protected:
+ virtual void paintEvent( TQPaintEvent* );
+ virtual void resizeEvent( TQResizeEvent* );
+ virtual void mouseMoveEvent( TQMouseEvent* );
+ virtual void mousePressEvent( TQMouseEvent* );
+
+ protected:
+ const Segment *segmentAt( TQPoint& ) 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( TQPainter& ) const;
+
+ const Directory *m_tree;
+ const Segment *m_focus;
+ TQPoint m_offset;
+ TQTimer m_timer;
+ Map m_map;
+ SegmentTip m_tip;
+ Segment *m_rootSegment;
+ };
+}
+
+#endif
diff --git a/src/app/DiskUsage/radialMap/widgetEvents.cpp b/src/app/DiskUsage/radialMap/widgetEvents.cpp
new file mode 100644
index 0000000..0cc11af
--- /dev/null
+++ b/src/app/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 <tdeio/job.h> //::mousePressEvent()
+#include <tdelocale.h>
+#include <tdemessagebox.h> //::mousePressEvent()
+#include <tdepopupmenu.h> //::mousePressEvent()
+#include <krun.h> //::mousePressEvent()
+#include <math.h> //::segmentAt()
+#include <tqapplication.h>//TQApplication::setOverrideCursor()
+#include <tqpainter.h>
+#include <tqtimer.h> //::resizeEvent()
+
+
+
+void
+RadialMap::Widget::resizeEvent( TQResizeEvent* )
+{
+ 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( TQPaintEvent* )
+{
+ //bltBit for some TQt setups will bitBlt _after_ the labels are painted. Which buggers things up!
+ //shame as bitBlt is faster, possibly TQt bug? Should report the bug? - seems to be race condition
+ //bitBlt( this, m_offset, &m_map );
+
+ TQPainter 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( TQPoint &e ) const
+{
+ //determine which segment TQPoint 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( TQMouseEvent *e )
+{
+ //set m_focus to what we hover over, update UI if it's a new segment
+
+ Segment const * const oldFocus = m_focus;
+ TQPoint 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( TQString() );
+ }
+}
+
+void
+RadialMap::Widget::mousePressEvent( TQMouseEvent *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() == TQt::RightButton )
+ {
+ TDEPopupMenu 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( "document-open" ), i18n( "&Open" ), 3 );
+
+ popup.insertSeparator();
+ popup.insertItem( SmallIconSet( "edit-delete" ), i18n( "&Delete" ), 4 );
+
+ switch( popup.exec( e->globalPos(), 1 ) ) {
+ case 0:
+ //KRun::runCommand will show an error message if there was trouble
+ KRun::runCommand( TQString( "kfmclient openURL '%1'" ).arg( url.url() ) );
+ break;
+
+ case 1:
+ KRun::runCommand( TQString( "konsole --workdir '%1'" ).arg( url.url() ) );
+ break;
+
+ case 2:
+ case 3:
+ goto sectionTwo;
+
+ case 4:
+ {
+ const KURL url = Widget::url( m_focus->file() );
+ const TQString 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, TQString(), KGuiItem( i18n("&Delete"), "edit-delete" ) );
+
+ if( userIntention == KMessageBox::Continue ) {
+ TDEIO::Job *job = TDEIO::del( url );
+ job->setWindow( this );
+ connect( job, TQ_SIGNAL(result( TDEIO::Job* )), TQ_SLOT(deleteJobFinished( TDEIO::Job* )) );
+ TQApplication::setOverrideCursor( KCursor::workingCursor() );
+ }
+ }
+
+ default:
+ //ensure m_focus is set for new mouse position
+ sendFakeMouseEvent();
+ }
+
+ } else {
+
+ sectionTwo:
+
+ const TQRect rect( e->x() - 20, e->y() - 20, 40, 40 );
+
+ m_tip.hide(); //user expects this
+
+ if( !isDir || e->button() == TQt::MidButton )
+ {
+ TDEIconEffect::visualActivate( this, rect );
+ new KRun( url, this, true ); //FIXME see above
+ }
+ else if( m_focus->file() != m_tree ) //is left mouse button
+ {
+ TDEIconEffect::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( TDEIO::Job *job )
+{
+ TQApplication::restoreOverrideCursor();
+ if( !job->error() )
+ invalidate();
+ else
+ job->showErrorDialog( this );
+}
diff --git a/src/app/Filter/Makefile.am b/src/app/Filter/Makefile.am
new file mode 100644
index 0000000..98b044b
--- /dev/null
+++ b/src/app/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/src/app/Filter/advancedfilter.cpp b/src/app/Filter/advancedfilter.cpp
new file mode 100644
index 0000000..299a5d8
--- /dev/null
+++ b/src/app/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 <tqgroupbox.h>
+#include <tdelocale.h>
+#include <tqlayout.h>
+#include <tqlabel.h>
+#include <tqbuttongroup.h>
+#include <tqfile.h>
+#include <kdebug.h>
+#include <tdemessagebox.h>
+#include <time.h>
+#include <kiconloader.h>
+
+#define USERSFILE TQString("/etc/passwd")
+#define GROUPSFILE TQString("/etc/group")
+
+AdvancedFilter::AdvancedFilter( FilterTabs *tabs, TQWidget *parent, const char *name ) : TQWidget( parent, name ), fltTabs( tabs )
+{
+ TQGridLayout *filterLayout = new TQGridLayout( this );
+ filterLayout->setSpacing( 6 );
+ filterLayout->setMargin( 11 );
+
+ // Options for size
+
+ TQGroupBox *sizeGroup = new TQGroupBox( this, "sizeGroup" );
+ sizeGroup->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)5, (TQSizePolicy::SizeType)1, sizeGroup->sizePolicy().hasHeightForWidth() ) );
+ sizeGroup->setTitle( i18n( "Size" ) );
+ sizeGroup->setColumnLayout(0, TQt::Vertical );
+ sizeGroup->layout()->setSpacing( 0 );
+ sizeGroup->layout()->setMargin( 0 );
+ TQGridLayout *sizeLayout = new TQGridLayout( sizeGroup->layout() );
+ sizeLayout->setAlignment( TQt::AlignTop );
+ sizeLayout->setSpacing( 6 );
+ sizeLayout->setMargin( 11 );
+
+ biggerThanEnabled = new TQCheckBox( sizeGroup, "biggerThanEnabled" );
+ biggerThanEnabled->setText( i18n( "&Bigger than" ) );
+ sizeLayout->addWidget( biggerThanEnabled, 0, 0 );
+
+ biggerThanAmount = new TQLineEdit( sizeGroup, "biggerThanAmount" );
+ biggerThanAmount->setEnabled( false );
+ biggerThanAmount->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::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 TQCheckBox( sizeGroup, "smallerThanEnabled" );
+ smallerThanEnabled->setText( i18n( "&Smaller than" ) );
+ sizeLayout->addWidget( smallerThanEnabled, 0, 3 );
+
+ smallerThanAmount = new TQLineEdit( sizeGroup, "smallerThanAmount" );
+ smallerThanAmount->setEnabled( false );
+ smallerThanAmount->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::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 = TQFontMetrics(biggerThanType->font()).height()+2;
+ biggerThanType->setMaximumHeight(height);
+ smallerThanType->setMaximumHeight(height);
+
+ filterLayout->addWidget( sizeGroup, 0, 0 );
+
+ // Options for date
+
+ TQPixmap iconDate = krLoader->loadIcon( "date", TDEIcon::Toolbar, 16 );
+
+ TQButtonGroup *dateGroup = new TQButtonGroup( this, "dateGroup" );
+ dateGroup->setTitle( i18n( "Date" ) );
+ dateGroup->setExclusive( true );
+ dateGroup->setColumnLayout(0, TQt::Vertical );
+ dateGroup->layout()->setSpacing( 0 );
+ dateGroup->layout()->setMargin( 0 );
+ TQGridLayout *dateLayout = new TQGridLayout( dateGroup->layout() );
+ dateLayout->setAlignment( TQt::AlignTop );
+ dateLayout->setSpacing( 6 );
+ dateLayout->setMargin( 11 );
+
+ modifiedBetweenEnabled = new TQRadioButton( dateGroup, "modifiedBetweenEnabled" );
+ modifiedBetweenEnabled->setText( i18n( "&Modified between" ) );
+ dateGroup->insert( modifiedBetweenEnabled, 0 );
+
+ dateLayout->addMultiCellWidget( modifiedBetweenEnabled, 0, 0, 0, 1 );
+
+ modifiedBetweenData1 = new TQLineEdit( dateGroup, "modifiedBetweenData1" );
+ modifiedBetweenData1->setEnabled( false );
+ modifiedBetweenData1->setText( "" );
+ dateLayout->addMultiCellWidget( modifiedBetweenData1, 0, 0, 2, 3 );
+
+ modifiedBetweenBtn1 = new TQToolButton( dateGroup, "modifiedBetweenBtn1" );
+ modifiedBetweenBtn1->setEnabled( false );
+ modifiedBetweenBtn1->setText( "" );
+ modifiedBetweenBtn1->setPixmap( iconDate );
+ dateLayout->addWidget( modifiedBetweenBtn1, 0, 4 );
+
+ TQLabel *andLabel = new TQLabel( dateGroup, "andLabel" );
+ andLabel->setText( i18n( "an&d" ) );
+ dateLayout->addWidget( andLabel, 0, 5 );
+
+ modifiedBetweenData2 = new TQLineEdit( dateGroup, "modifiedBetweenData2" );
+ modifiedBetweenData2->setEnabled( false );
+ modifiedBetweenData2->setText( "" );
+ andLabel->setBuddy(modifiedBetweenData2);
+ dateLayout->addWidget( modifiedBetweenData2, 0, 6 );
+
+ modifiedBetweenBtn2 = new TQToolButton( dateGroup, "modifiedBetweenBtn2" );
+ modifiedBetweenBtn2->setEnabled( false );
+ modifiedBetweenBtn2->setText( "" );
+ modifiedBetweenBtn2->setPixmap( iconDate );
+ dateLayout->addWidget( modifiedBetweenBtn2, 0, 7 );
+
+ notModifiedAfterEnabled = new TQRadioButton( dateGroup, "notModifiedAfterEnabled" );
+ notModifiedAfterEnabled->setText( i18n( "&Not modified after" ) );
+ dateGroup->insert( notModifiedAfterEnabled, 0 );
+ dateLayout->addMultiCellWidget( notModifiedAfterEnabled, 1, 1, 0, 1 );
+
+ notModifiedAfterData = new TQLineEdit( dateGroup, "notModifiedAfterData" );
+ notModifiedAfterData->setEnabled( false );
+ notModifiedAfterData->setText( "" );
+ dateLayout->addMultiCellWidget( notModifiedAfterData, 1, 1, 2, 3 );
+
+ notModifiedAfterBtn = new TQToolButton( dateGroup, "notModifiedAfterBtn" );
+ notModifiedAfterBtn->setEnabled( false );
+ notModifiedAfterBtn->setText( "" );
+ notModifiedAfterBtn->setPixmap( iconDate );
+ dateLayout->addWidget( notModifiedAfterBtn, 1, 4 );
+
+ modifiedInTheLastEnabled = new TQRadioButton( dateGroup, "modifiedInTheLastEnabled" );
+ modifiedInTheLastEnabled->setText( i18n("Mod&ified in the last") );
+ dateGroup->insert( modifiedInTheLastEnabled, 0 );
+ dateLayout->addWidget( modifiedInTheLastEnabled, 2, 0 );
+
+ modifiedInTheLastData = new TQLineEdit( dateGroup, "modifiedInTheLastData" );
+ modifiedInTheLastData->setEnabled( false );
+ modifiedInTheLastData->setText( "" );
+ dateLayout->addWidget( modifiedInTheLastData, 2, 2 );
+
+ modifiedInTheLastType = new TQComboBox( 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 TQLineEdit( dateGroup, "notModifiedInTheLastData" );
+ notModifiedInTheLastData->setEnabled( false );
+ notModifiedInTheLastData->setText( "" );
+ dateLayout->addWidget( notModifiedInTheLastData, 3, 2 );
+
+ TQLabel *notModifiedInTheLastLbl = new TQLabel( dateGroup, "notModifiedInTheLastLbl" );
+ notModifiedInTheLastLbl->setText( i18n( "No&t modified in the last" ) );
+ notModifiedInTheLastLbl->setBuddy(notModifiedInTheLastData);
+ dateLayout->addWidget( notModifiedInTheLastLbl, 3, 0 );
+
+ notModifiedInTheLastType = new TQComboBox( 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
+
+ TQGroupBox *ownershipGroup = new TQGroupBox( this, "ownershipGroup" );
+ ownershipGroup->setTitle( i18n( "Ownership" ) );
+ ownershipGroup->setColumnLayout(0, TQt::Vertical );
+ ownershipGroup->layout()->setSpacing( 0 );
+ ownershipGroup->layout()->setMargin( 0 );
+ TQGridLayout *ownershipLayout = new TQGridLayout( ownershipGroup->layout() );
+ ownershipLayout->setAlignment( TQt::AlignTop );
+ ownershipLayout->setSpacing( 6 );
+ ownershipLayout->setMargin( 11 );
+
+ TQHBoxLayout *hboxLayout = new TQHBoxLayout();
+ hboxLayout->setSpacing( 6 );
+ hboxLayout->setMargin( 0 );
+
+ belongsToUserEnabled = new TQCheckBox( ownershipGroup, "belongsToUserEnabled" );
+ belongsToUserEnabled->setText( i18n( "Belongs to &user" ) );
+ hboxLayout->addWidget( belongsToUserEnabled );
+
+ belongsToUserData = new TQComboBox( false, ownershipGroup, "belongsToUserData" );
+ belongsToUserData->setEnabled( false );
+ belongsToUserData->setEditable( false );
+ hboxLayout->addWidget( belongsToUserData );
+
+ belongsToGroupEnabled = new TQCheckBox( ownershipGroup, "belongsToGroupEnabled" );
+ belongsToGroupEnabled->setText( i18n( "Belongs to gr&oup" ) );
+ hboxLayout->addWidget( belongsToGroupEnabled );
+
+ belongsToGroupData = new TQComboBox( false, ownershipGroup, "belongsToGroupData" );
+ belongsToGroupData->setEnabled( false );
+ belongsToGroupData->setEditable( false );
+ hboxLayout->addWidget( belongsToGroupData );
+
+ ownershipLayout->addMultiCellLayout( hboxLayout, 0, 0, 0, 3 );
+
+ permissionsEnabled = new TQCheckBox( ownershipGroup, "permissionsEnabled" );
+ permissionsEnabled->setText( i18n( "P&ermissions" ) );
+ ownershipLayout->addWidget( permissionsEnabled, 1, 0 );
+
+ TQGroupBox *ownerGroup = new TQGroupBox( ownershipGroup, "ownerGroup" );
+ ownerGroup->setTitle( i18n( "O&wner" ) );
+ int width = 2*height + height / 2;
+
+ ownerR = new TQComboBox( false, ownerGroup, "ownerR" );
+ ownerR->insertItem( i18n( "?" ) );
+ ownerR->insertItem( i18n( "r" ) );
+ ownerR->insertItem( i18n( "-" ) );
+ ownerR->setEnabled( false );
+ ownerR->setGeometry( TQRect( 10, 20, width, height+6 ) );
+
+ ownerW = new TQComboBox( false, ownerGroup, "ownerW" );
+ ownerW->insertItem( i18n( "?" ) );
+ ownerW->insertItem( i18n( "w" ) );
+ ownerW->insertItem( i18n( "-" ) );
+ ownerW->setEnabled( false );
+ ownerW->setGeometry( TQRect( 10 + width, 20, width, height+6 ) );
+
+ ownerX = new TQComboBox( false, ownerGroup, "ownerX" );
+ ownerX->insertItem( i18n( "?" ) );
+ ownerX->insertItem( i18n( "x" ) );
+ ownerX->insertItem( i18n( "-" ) );
+ ownerX->setEnabled( false );
+ ownerX->setGeometry( TQRect( 10 + 2*width, 20, width, height+6 ) );
+
+ ownershipLayout->addWidget( ownerGroup, 1, 1 );
+
+ TQGroupBox *groupGroup = new TQGroupBox( ownershipGroup, "groupGroup" );
+ groupGroup->setTitle( i18n( "Grou&p" ) );
+
+ groupR = new TQComboBox( false, groupGroup, "groupR" );
+ groupR->insertItem( i18n( "?" ) );
+ groupR->insertItem( i18n( "r" ) );
+ groupR->insertItem( i18n( "-" ) );
+ groupR->setEnabled( false );
+ groupR->setGeometry( TQRect( 10, 20, width, height+6 ) );
+
+ groupW = new TQComboBox( false, groupGroup, "groupW" );
+ groupW->insertItem( i18n( "?" ) );
+ groupW->insertItem( i18n( "w" ) );
+ groupW->insertItem( i18n( "-" ) );
+ groupW->setEnabled( false );
+ groupW->setGeometry( TQRect( 10 + width, 20, width, height+6 ) );
+
+ groupX = new TQComboBox( false, groupGroup, "groupX" );
+ groupX->insertItem( i18n( "?" ) );
+ groupX->insertItem( i18n( "x" ) );
+ groupX->insertItem( i18n( "-" ) );
+ groupX->setEnabled( false );
+ groupX->setGeometry( TQRect( 10 + 2*width, 20, width, height+6 ) );
+
+ ownershipLayout->addWidget( groupGroup, 1, 2 );
+
+ TQGroupBox *allGroup = new TQGroupBox( ownershipGroup, "allGroup" );
+ allGroup->setTitle( i18n( "A&ll" ) );
+
+ allR = new TQComboBox( false, allGroup, "allR" );
+ allR->insertItem( i18n( "?" ) );
+ allR->insertItem( i18n( "r" ) );
+ allR->insertItem( i18n( "-" ) );
+ allR->setEnabled( false );
+ allR->setGeometry( TQRect( 10, 20, width, height+6 ) );
+
+ allW = new TQComboBox( false, allGroup, "allW" );
+ allW->insertItem( i18n( "?" ) );
+ allW->insertItem( i18n( "w" ) );
+ allW->insertItem( i18n( "-" ) );
+ allW->setEnabled( false );
+ allW->setGeometry( TQRect( 10 + width, 20, width, height+6 ) );
+
+ allX = new TQComboBox( false, allGroup, "allX" );
+ allX->insertItem( i18n( "?" ) );
+ allX->insertItem( i18n( "x" ) );
+ allX->insertItem( i18n( "-" ) );
+ allX->setEnabled( false );
+ allX->setGeometry( TQRect( 10 + 2*width, 20, width, height+6 ) );
+
+ ownershipLayout->addWidget( allGroup, 1, 3 );
+
+ TQLabel *infoLabel = new TQLabel( ownershipGroup, "TextLabel4" );
+ TQFont 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, TQt::AlignRight );
+
+ filterLayout->addWidget( ownershipGroup, 2, 0 );
+
+ // Connection table
+
+ connect( biggerThanEnabled, TQ_SIGNAL( toggled(bool) ), biggerThanAmount, TQ_SLOT( setEnabled(bool) ) );
+ connect( biggerThanEnabled, TQ_SIGNAL( toggled(bool) ), biggerThanType, TQ_SLOT( setEnabled(bool) ) );
+ connect( smallerThanEnabled, TQ_SIGNAL( toggled(bool) ), smallerThanAmount, TQ_SLOT( setEnabled(bool) ) );
+ connect( smallerThanEnabled, TQ_SIGNAL( toggled(bool) ), smallerThanType, TQ_SLOT( setEnabled(bool) ) );
+ connect( modifiedBetweenEnabled, TQ_SIGNAL( toggled(bool) ), modifiedBetweenData1, TQ_SLOT( setEnabled(bool) ) );
+ connect( modifiedBetweenEnabled, TQ_SIGNAL( toggled(bool) ), modifiedBetweenBtn1, TQ_SLOT( setEnabled(bool) ) );
+ connect( modifiedBetweenEnabled, TQ_SIGNAL( toggled(bool) ), modifiedBetweenData2, TQ_SLOT( setEnabled(bool) ) );
+ connect( modifiedBetweenEnabled, TQ_SIGNAL( toggled(bool) ), modifiedBetweenBtn2, TQ_SLOT( setEnabled(bool) ) );
+ connect( notModifiedAfterEnabled, TQ_SIGNAL( toggled(bool) ), notModifiedAfterData, TQ_SLOT( setEnabled(bool) ) );
+ connect( notModifiedAfterEnabled, TQ_SIGNAL( toggled(bool) ), notModifiedAfterBtn, TQ_SLOT( setEnabled(bool) ) );
+ connect( modifiedInTheLastEnabled, TQ_SIGNAL( toggled(bool) ), modifiedInTheLastData, TQ_SLOT( setEnabled(bool) ) );
+ connect( modifiedInTheLastEnabled, TQ_SIGNAL( toggled(bool) ), modifiedInTheLastType, TQ_SLOT( setEnabled(bool) ) );
+ connect( modifiedInTheLastEnabled, TQ_SIGNAL( toggled(bool) ), notModifiedInTheLastData, TQ_SLOT( setEnabled(bool) ) );
+ connect( modifiedInTheLastEnabled, TQ_SIGNAL( toggled(bool) ), notModifiedInTheLastType, TQ_SLOT( setEnabled(bool) ) );
+ connect( belongsToUserEnabled, TQ_SIGNAL( toggled(bool) ), belongsToUserData, TQ_SLOT( setEnabled(bool) ) );
+ connect( belongsToGroupEnabled, TQ_SIGNAL( toggled(bool) ), belongsToGroupData, TQ_SLOT( setEnabled(bool) ) );
+ connect( permissionsEnabled, TQ_SIGNAL( toggled(bool) ), ownerR, TQ_SLOT( setEnabled(bool) ) );
+ connect( permissionsEnabled, TQ_SIGNAL( toggled(bool) ), ownerW, TQ_SLOT( setEnabled(bool) ) );
+ connect( permissionsEnabled, TQ_SIGNAL( toggled(bool) ), ownerX, TQ_SLOT( setEnabled(bool) ) );
+ connect( permissionsEnabled, TQ_SIGNAL( toggled(bool) ), groupR, TQ_SLOT( setEnabled(bool) ) );
+ connect( permissionsEnabled, TQ_SIGNAL( toggled(bool) ), groupW, TQ_SLOT( setEnabled(bool) ) );
+ connect( permissionsEnabled, TQ_SIGNAL( toggled(bool) ), groupX, TQ_SLOT( setEnabled(bool) ) );
+ connect( permissionsEnabled, TQ_SIGNAL( toggled(bool) ), allR, TQ_SLOT( setEnabled(bool) ) );
+ connect( permissionsEnabled, TQ_SIGNAL( toggled(bool) ), allW, TQ_SLOT( setEnabled(bool) ) );
+ connect( permissionsEnabled, TQ_SIGNAL( toggled(bool) ), allX, TQ_SLOT( setEnabled(bool) ) );
+ connect( modifiedBetweenBtn1, TQ_SIGNAL( clicked() ), this, TQ_SLOT( modifiedBetweenSetDate1() ) );
+ connect( modifiedBetweenBtn2, TQ_SIGNAL( clicked() ), this, TQ_SLOT( modifiedBetweenSetDate2() ) );
+ connect( notModifiedAfterBtn, TQ_SIGNAL( clicked() ), this, TQ_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(TQLineEdit *p) {
+ // check if the current date is valid
+ TQDate d = TDEGlobal::locale()->readDate(p->text());
+ if (!d.isValid()) d = TQDate::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(TDEGlobal::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, TQDate 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(TQComboBox *list, TQString filename) {
+ TQFile data(filename);
+ if (!data.open(IO_ReadOnly))
+ {
+ krOut << "Search: Unable to read " << filename << " !!!" << endl;
+ return;
+ }
+ // and read it into the temporary array
+ TQTextStream t(&data);
+ while (!data.atEnd())
+ {
+ TQString s = t.readLine();
+ TQString name = s.left(s.find(':'));
+ list->insertItem(name);
+ }
+}
+
+void AdvancedFilter::invalidDateMessage(TQLineEdit *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 )
+{
+ TDEIO::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
+ TQDate d1 = TDEGlobal::locale()->readDate(modifiedBetweenData1->text());
+ if (!d1.isValid()) { invalidDateMessage(modifiedBetweenData1); return false; }
+ TQDate d2 = TDEGlobal::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() ) {
+ TQDate d = TDEGlobal::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()) ) {
+ TQDate d1 = TQDate::currentDate(); TQDate d2 = TQDate::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()) {
+ TQString 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( TQString 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 ) );
+
+ TQString user = krConfig->readEntry( "Belongs To User", "" );
+ for( int i = belongsToUserData->count(); i >= 0; i-- )
+ {
+ belongsToUserData->setCurrentItem( i );
+ if( belongsToUserData->currentText() == user )
+ break;
+ }
+
+ TQString 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( TQString 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/src/app/Filter/advancedfilter.h b/src/app/Filter/advancedfilter.h
new file mode 100644
index 0000000..48cf85e
--- /dev/null
+++ b/src/app/Filter/advancedfilter.h
@@ -0,0 +1,116 @@
+/***************************************************************************
+ 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 <tqwidget.h>
+#include <tqcheckbox.h>
+#include <kcombobox.h>
+#include <klineedit.h>
+#include <tqradiobutton.h>
+#include <tqtoolbutton.h>
+
+class AdvancedFilter : public TQWidget, public FilterBase
+{
+ TQ_OBJECT
+
+
+public:
+ AdvancedFilter( FilterTabs *tabs, TQWidget *parent = 0, const char *name = 0 );
+
+ virtual void queryAccepted() {}
+ virtual bool fillQuery( KRQuery *query );
+ virtual void loadFromProfile( TQString name );
+ virtual void saveToProfile( TQString name );
+ virtual TQString name() { return "AdvancedFilter";}
+ virtual FilterTabs * filterTabs() { return fltTabs; }
+
+public slots:
+ void modifiedBetweenSetDate1();
+ void modifiedBetweenSetDate2();
+ void notModifiedAfterSetDate();
+
+public:
+ TQCheckBox* smallerThanEnabled;
+ TQLineEdit* smallerThanAmount;
+ KComboBox* smallerThanType;
+
+ TQCheckBox* biggerThanEnabled;
+ KComboBox* biggerThanType;
+ TQLineEdit* biggerThanAmount;
+
+ TQRadioButton* modifiedBetweenEnabled;
+ TQRadioButton* notModifiedAfterEnabled;
+ TQRadioButton* modifiedInTheLastEnabled;
+
+ TQLineEdit* modifiedBetweenData1;
+ TQLineEdit* modifiedBetweenData2;
+
+ TQToolButton* modifiedBetweenBtn1;
+ TQToolButton* modifiedBetweenBtn2;
+ TQToolButton* notModifiedAfterBtn;
+
+ TQLineEdit* notModifiedAfterData;
+ TQLineEdit* modifiedInTheLastData;
+ TQLineEdit* notModifiedInTheLastData;
+ TQComboBox* modifiedInTheLastType;
+ TQComboBox* notModifiedInTheLastType;
+
+ TQCheckBox* belongsToUserEnabled;
+ TQComboBox* belongsToUserData;
+ TQCheckBox* belongsToGroupEnabled;
+ TQComboBox* belongsToGroupData;
+
+ TQCheckBox* permissionsEnabled;
+
+ TQComboBox* ownerW;
+ TQComboBox* ownerR;
+ TQComboBox* ownerX;
+ TQComboBox* groupW;
+ TQComboBox* groupR;
+ TQComboBox* groupX;
+ TQComboBox* allW;
+ TQComboBox* allX;
+ TQComboBox* allR;
+
+ FilterTabs *fltTabs;
+
+private:
+ void changeDate(TQLineEdit *p);
+ void fillList(TQComboBox *list, TQString filename);
+ void qdate2time_t(time_t *dest, TQDate d, bool start);
+ void invalidDateMessage(TQLineEdit *p);
+};
+
+#endif /* ADVANCEDFILTER_H */
diff --git a/src/app/Filter/filterbase.h b/src/app/Filter/filterbase.h
new file mode 100644
index 0000000..bdcdce0
--- /dev/null
+++ b/src/app/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 <tqstring.h>
+
+class FilterTabs;
+
+class FilterBase
+{
+public:
+ virtual bool fillQuery( KRQuery *query ) = 0;
+ virtual void queryAccepted() = 0;
+ virtual void loadFromProfile( TQString name ) = 0;
+ virtual void saveToProfile( TQString name ) = 0;
+ virtual TQString name() = 0;
+ virtual FilterTabs * filterTabs() = 0;
+ virtual ~FilterBase() {}
+};
+
+#endif /* FILTERBASE_H */
diff --git a/src/app/Filter/filterdialog.cpp b/src/app/Filter/filterdialog.cpp
new file mode 100644
index 0000000..dc1e3e6
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+
+FilterDialog::FilterDialog( TQWidget *parent, const char *name )
+ : KDialogBase( parent, name, true, i18n("Krusader::Choose Files"), Ok|Cancel )
+{
+ TQGridLayout *filterGrid = new TQGridLayout( this->layout() );
+ filterGrid->setSpacing( 6 );
+ filterGrid->setMargin( 11 );
+
+ TQTabWidget *filterWidget = new TQTabWidget( 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, TQ_SIGNAL( closeRequest(bool) ), this, TQ_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/src/app/Filter/filterdialog.h b/src/app/Filter/filterdialog.h
new file mode 100644
index 0000000..c4c96d9
--- /dev/null
+++ b/src/app/Filter/filterdialog.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+ 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
+{
+ TQ_OBJECT
+
+
+public:
+ FilterDialog( TQWidget *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/src/app/Filter/filtertabs.cpp b/src/app/Filter/filtertabs.cpp
new file mode 100644
index 0000000..f1e5339
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+
+FilterTabs::FilterTabs( int properties, TQTabWidget *tabWidget, TQObject *parent ) :
+ TQObject( 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( TQTabWidget *tabWidget, int props )
+{
+ return new FilterTabs( props, tabWidget, tabWidget );
+}
+
+void FilterTabs::saveToProfile( TQString name )
+{
+ FilterBase *filter = filterList.first();
+
+ while( filter )
+ {
+ filter->saveToProfile( name );
+ filter = filterList.next();
+ }
+}
+
+void FilterTabs::loadFromProfile( TQString 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( TQString name )
+{
+ FilterBase *filter = filterList.first();
+
+ while( filter )
+ {
+ if( filter->name() == name )
+ return filter;
+
+ filter = filterList.next();
+ }
+
+ return 0;
+}
+
+KRQuery FilterTabs::getQuery( TQWidget *parent, const char *name )
+{
+ FilterDialog dialog( parent, name );
+ return dialog.getQuery();
+}
+
+#include "filtertabs.moc"
+
diff --git a/src/app/Filter/filtertabs.h b/src/app/Filter/filtertabs.h
new file mode 100644
index 0000000..ae8e3ec
--- /dev/null
+++ b/src/app/Filter/filtertabs.h
@@ -0,0 +1,81 @@
+/***************************************************************************
+ 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 <tqtabwidget.h>
+#include <tqptrlist.h>
+
+#include "filterbase.h"
+
+class FilterTabs : public TQObject
+{
+ TQ_OBJECT
+
+
+ public:
+
+ enum
+ {
+ HasRemoteContentSearch = 0x0800,
+ HasProfileHandler = 0x1000,
+ HasRecurseOptions = 0x2000,
+ HasSearchIn = 0x4000,
+ HasDontSearchIn = 0x8000,
+
+ Default = 0xe000
+ };
+
+ static FilterTabs * addTo( TQTabWidget *tabWidget, int props = FilterTabs::Default );
+ static KRQuery getQuery( TQWidget *parent = 0, const char *name = 0 );
+
+ FilterBase *get( TQString name );
+
+ public slots:
+ void loadFromProfile( TQString );
+ void saveToProfile( TQString );
+ bool fillQuery( KRQuery *query );
+ void close( bool accept = true ) { emit closeRequest( accept ); }
+
+ signals:
+ void closeRequest( bool accept = true );
+
+ private:
+ FilterTabs( int properties, TQTabWidget *tabWidget, TQObject *parent );
+ void acceptQuery();
+
+ TQPtrList<FilterBase> filterList;
+ TQValueList<int> pageNumbers;
+
+ TQTabWidget * tabWidget;
+};
+
+#endif /* FILTERTABS_H */
diff --git a/src/app/Filter/generalfilter.cpp b/src/app/Filter/generalfilter.cpp
new file mode 100644
index 0000000..70be90f
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <tdefiledialog.h>
+#include <tdemessagebox.h>
+#include <kiconloader.h>
+#include <tqwhatsthis.h>
+#include <tqpushbutton.h>
+
+GeneralFilter::GeneralFilter( FilterTabs *tabs, int properties, TQWidget *parent, const char *name ) : TQWidget( parent, name ),
+ profileManager( 0 ), fltTabs( tabs )
+{
+ TQGridLayout *filterLayout = new TQGridLayout( this );
+ filterLayout->setSpacing( 6 );
+ filterLayout->setMargin( 11 );
+
+ this->properties = properties;
+
+ // Options for name filtering
+
+ TQGroupBox *nameGroup = new TQGroupBox( this, "nameGroup" );
+ nameGroup->setTitle( i18n( "File name" ) );
+ nameGroup->setColumnLayout(0, TQt::Vertical );
+ nameGroup->layout()->setSpacing( 0 );
+ nameGroup->layout()->setMargin( 0 );
+ TQGridLayout *nameGroupLayout = new TQGridLayout( nameGroup->layout() );
+ nameGroupLayout->setAlignment( TQt::AlignTop );
+ nameGroupLayout->setSpacing( 6 );
+ nameGroupLayout->setMargin( 11 );
+
+ searchForCase = new TQCheckBox( nameGroup, "searchForCase" );
+ searchForCase->setText( i18n( "&Case sensitive" ) );
+ searchForCase->setChecked( false );
+ nameGroupLayout->addWidget( searchForCase, 1, 2 );
+
+ TQLabel *searchForLabel = new TQLabel( nameGroup, "searchForLabel" );
+ searchForLabel->setText( i18n( "Search &for:" ) );
+ nameGroupLayout->addWidget( searchForLabel, 0, 0 );
+
+ searchFor = new KHistoryCombo( false, nameGroup, "searchFor" );
+ searchFor->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)7, (TQSizePolicy::SizeType)0, searchFor->sizePolicy().hasHeightForWidth() ) );
+ searchFor->setEditable( true );
+ searchFor->setDuplicatesEnabled( false );
+ searchFor->setMaxCount( 25 );
+ searchForLabel->setBuddy( searchFor );
+ nameGroupLayout->addMultiCellWidget( searchFor, 0, 0, 1, 2 );
+
+ TQString 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>");
+ TQWhatsThis::add(searchFor, s);
+ TQWhatsThis::add(searchForLabel, s);
+
+ TQLabel *searchType = new TQLabel( nameGroup, "searchType" );
+ searchType->setText( i18n( "&Of type:" ) );
+ nameGroupLayout->addWidget( searchType, 1, 0 );
+
+ ofType = new KComboBox( false, nameGroup, "ofType" );
+ ofType->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)7, (TQSizePolicy::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 TQHBoxLayout();
+ middleLayout->setSpacing( 6 );
+ middleLayout->setMargin( 0 );
+ TQSpacerItem* middleSpacer = new TQSpacerItem( 1, 1, TQSizePolicy::Fixed, TQSizePolicy::Fixed );
+ middleLayout->addItem( middleSpacer );
+
+ if( properties & FilterTabs::HasProfileHandler )
+ {
+ // The profile handler
+
+ TQGroupBox *profileHandler = new TQGroupBox( this, "profileHandler" );
+ profileHandler->setTitle( i18n( "&Profile handler" ) );
+ profileHandler->setColumnLayout(0, TQt::Vertical );
+ profileHandler->layout()->setSpacing( 0 );
+ profileHandler->layout()->setMargin( 0 );
+ TQGridLayout *profileLayout = new TQGridLayout( profileHandler->layout() );
+ profileLayout->setAlignment( TQt::AlignTop );
+ profileLayout->setSpacing( 6 );
+ profileLayout->setMargin( 11 );
+
+ profileListBox = new TQListBox( profileHandler, "profileListBox" );
+ profileLayout->addMultiCellWidget( profileListBox, 0, 3, 0, 0 );
+
+ profileAddBtn = new TQPushButton( i18n( "&Add" ), profileHandler, "profileAddBtn" );
+ profileLayout->addWidget( profileAddBtn, 0, 1 );
+
+ profileLoadBtn = new TQPushButton( i18n( "&Load" ), profileHandler, "profileLoadBtn" );
+ profileLoadBtn->setEnabled( false );
+ profileLayout->addWidget( profileLoadBtn, 1, 1 );
+
+ profileOverwriteBtn = new TQPushButton( i18n( "&Overwrite" ), profileHandler, "profileOverwriteBtn" );
+ profileOverwriteBtn->setEnabled( false );
+ profileLayout->addWidget( profileOverwriteBtn, 2, 1 );
+
+ profileRemoveBtn = new TQPushButton( 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
+
+ TQGroupBox *searchInGroup = new TQGroupBox( this, "searchInGroup" );
+ searchInGroup->setTitle( i18n( "&Search in" ) );
+ searchInGroup->setColumnLayout(0, TQt::Vertical );
+ searchInGroup->layout()->setSpacing( 0 );
+ searchInGroup->layout()->setMargin( 0 );
+ TQGridLayout *searchInLayout = new TQGridLayout( searchInGroup->layout() );
+ searchInLayout->setAlignment( TQt::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
+
+ TQGroupBox *dontSearchInGroup = new TQGroupBox( this, "dontSearchInGroup" );
+ dontSearchInGroup->setTitle( i18n( "&Don't search in" ) );
+ dontSearchInGroup->setColumnLayout(0, TQt::Vertical );
+ dontSearchInGroup->layout()->setSpacing( 0 );
+ dontSearchInGroup->layout()->setMargin( 0 );
+ TQGridLayout *dontSearchInLayout = new TQGridLayout( dontSearchInGroup->layout() );
+ dontSearchInLayout->setAlignment( TQt::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
+
+ TQGroupBox *containsGroup = new TQGroupBox( this, "containsGroup" );
+ containsGroup->setTitle( i18n( "Containing text" ) );
+ containsGroup->setColumnLayout(0, TQt::Vertical );
+ containsGroup->layout()->setSpacing( 0 );
+ containsGroup->layout()->setMargin( 0 );
+ TQGridLayout *containsLayout = new TQGridLayout( containsGroup->layout() );
+ containsLayout->setAlignment( TQt::AlignTop );
+ containsLayout->setSpacing( 6 );
+ containsLayout->setMargin( 11 );
+
+ TQHBoxLayout *containsTextLayout = new TQHBoxLayout();
+ containsTextLayout->setSpacing( 6 );
+ containsTextLayout->setMargin( 0 );
+
+ TQLabel *containsLabel = new TQLabel( containsGroup, "containsLabel" );
+ containsLabel->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)1, containsLabel->sizePolicy().hasHeightForWidth() ) );
+ containsLabel->setText( i18n( "&Text:" ) );
+ containsTextLayout->addWidget( containsLabel );
+
+ containsText = new KHistoryCombo( false, containsGroup, "containsText" );
+ containsText->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)7, (TQSizePolicy::SizeType)0, containsText->sizePolicy().hasHeightForWidth() ) );
+ containsText->setDuplicatesEnabled( false );
+ containsText->setMaxCount( 25 );
+ containsTextLayout->addWidget( containsText );
+ containsLabel->setBuddy(containsText);
+
+ containsLayout->addLayout( containsTextLayout, 0, 0 );
+
+ TQHBoxLayout *containsCbsLayout = new TQHBoxLayout();
+ containsCbsLayout->setSpacing( 6 );
+ containsCbsLayout->setMargin( 0 );
+ TQSpacerItem* cbSpacer = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum );
+ containsCbsLayout->addItem( cbSpacer );
+
+ remoteContentSearch = new TQCheckBox( containsGroup, "remoteContentSearch" );
+ remoteContentSearch->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)5, (TQSizePolicy::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 TQCheckBox( containsGroup, "containsWholeWord" );
+ containsWholeWord->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)5, (TQSizePolicy::SizeType)0, containsWholeWord->sizePolicy().hasHeightForWidth() ) );
+ containsWholeWord->setText( i18n( "&Match whole word only" ) );
+ containsWholeWord->setChecked( false );
+ containsCbsLayout->addWidget( containsWholeWord );
+
+ containsTextCase = new TQCheckBox( containsGroup, "containsTextCase" );
+ containsTextCase->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)5, (TQSizePolicy::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
+
+ TQHBoxLayout *recurseLayout = new TQHBoxLayout();
+ recurseLayout->setSpacing( 6 );
+ recurseLayout->setMargin( 0 );
+ TQSpacerItem* recurseSpacer = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum );
+ recurseLayout->addItem( recurseSpacer );
+
+ searchInDirs = new TQCheckBox( this, "searchInDirs" );
+ searchInDirs->setText( i18n( "Search in s&ubdirectories" ) );
+ searchInDirs->setChecked( true );
+ recurseLayout->addWidget( searchInDirs );
+
+ searchInArchives = new TQCheckBox( this, "searchInArchives" );
+ searchInArchives->setText( i18n( "Search in arch&ives" ) );
+ recurseLayout->addWidget( searchInArchives );
+
+ followLinks = new TQCheckBox( this, "followLinks" );
+ followLinks->setText( i18n( "Follow &links" ) );
+ recurseLayout->addWidget( followLinks );
+
+ filterLayout->addLayout( recurseLayout, 3, 0 );
+ }
+
+ // Connection table
+
+ if( properties & FilterTabs::HasProfileHandler )
+ {
+ connect( profileAddBtn, TQ_SIGNAL(clicked()) , this, TQ_SLOT( slotAddBtnClicked() ) );
+ connect( profileLoadBtn, TQ_SIGNAL(clicked()) , this, TQ_SLOT( slotLoadBtnClicked() ) );
+ connect( profileOverwriteBtn, TQ_SIGNAL(clicked()) , this, TQ_SLOT( slotOverwriteBtnClicked() ) );
+ connect( profileRemoveBtn, TQ_SIGNAL(clicked()) , this, TQ_SLOT( slotRemoveBtnClicked() ) );
+ connect( profileListBox, TQ_SIGNAL(doubleClicked(TQListBoxItem *)) , this, TQ_SLOT( slotProfileDoubleClicked(TQListBoxItem *) ) );
+ connect( profileManager, TQ_SIGNAL(loadFromProfile(TQString )), fltTabs, TQ_SLOT( loadFromProfile(TQString ) ) );
+ connect( profileManager, TQ_SIGNAL(saveToProfile(TQString )), fltTabs, TQ_SLOT( saveToProfile(TQString ) ) );
+ }
+
+ connect( searchFor, TQ_SIGNAL(activated(const TQString&)), searchFor, TQ_SLOT(addToHistory(const TQString&)));
+ connect( containsText, TQ_SIGNAL(activated(const TQString&)), containsText, TQ_SLOT(addToHistory(const TQString&)));
+
+ // load the completion and history lists
+ // ==> search for
+ krConfig->setGroup("Search");
+ TQStringList 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
+ TQStringList 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( TQString() );
+
+ 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( TQString 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", "" ) );
+
+ TQString 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();
+ TQStringList 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();
+ TQStringList dontSearchInList = krConfig->readListEntry( "Dont Search In List" );
+ if( !dontSearchInList.isEmpty() )
+ dontSearchIn->listBox()->insertStringList( dontSearchInList );
+ }
+}
+
+void GeneralFilter::saveToProfile( TQString 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() );
+
+ TQStringList searchInList;
+ for ( TQListBoxItem *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() );
+
+ TQStringList dontSearchInList;
+ for ( TQListBoxItem *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()
+{
+ TQListBoxItem *item = profileListBox->item( profileListBox->currentItem() );
+ if( item != 0 )
+ profileManager->overwriteProfile( item->text() );
+}
+
+void GeneralFilter::slotRemoveBtnClicked()
+{
+ TQListBoxItem *item = profileListBox->item( profileListBox->currentItem() );
+ if( item != 0 )
+ {
+ profileManager->deleteProfile( item->text() );
+ refreshProfileListBox();
+ }
+}
+
+void GeneralFilter::slotProfileDoubleClicked( TQListBoxItem *item )
+{
+ if( item != 0 )
+ {
+ TQString profileName = item->text();
+ profileManager->loadProfile( profileName );
+ fltTabs->close( true );
+ }
+}
+
+void GeneralFilter::slotLoadBtnClicked()
+{
+ TQListBoxItem *item = profileListBox->item( profileListBox->currentItem() );
+ if( item != 0 )
+ profileManager->loadProfile( item->text() );
+}
+
+#include "generalfilter.moc"
diff --git a/src/app/Filter/generalfilter.h b/src/app/Filter/generalfilter.h
new file mode 100644
index 0000000..d968551
--- /dev/null
+++ b/src/app/Filter/generalfilter.h
@@ -0,0 +1,107 @@
+/***************************************************************************
+ 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 <tqwidget.h>
+#include <tqlayout.h>
+#include <tqgroupbox.h>
+#include <tqcheckbox.h>
+#include <tqlabel.h>
+#include <tqlistbox.h>
+#include <kcombobox.h>
+#include <kshellcompletion.h>
+
+class GeneralFilter : public TQWidget, public FilterBase
+{
+ TQ_OBJECT
+
+
+public:
+ GeneralFilter( FilterTabs *tabs, int properties, TQWidget *parent = 0, const char *name = 0 );
+ ~GeneralFilter();
+
+ virtual bool fillQuery( KRQuery *query );
+ virtual void queryAccepted();
+ virtual void loadFromProfile( TQString name );
+ virtual void saveToProfile( TQString name );
+ virtual TQString name() { return "GeneralFilter";}
+ virtual FilterTabs * filterTabs() { return fltTabs; }
+
+public slots:
+ void slotAddBtnClicked();
+ void slotLoadBtnClicked();
+ void slotOverwriteBtnClicked();
+ void slotRemoveBtnClicked();
+ void slotProfileDoubleClicked( TQListBoxItem * );
+ void refreshProfileListBox();
+
+public:
+ TQCheckBox* searchForCase;
+ TQCheckBox* remoteContentSearch;
+ TQCheckBox* containsTextCase;
+ TQCheckBox* containsWholeWord;
+ TQCheckBox* searchInDirs;
+ TQCheckBox* searchInArchives;
+ TQCheckBox* followLinks;
+
+ KURLListRequester *searchIn;
+ KURLListRequester *dontSearchIn;
+ TQHBoxLayout *middleLayout;
+
+ KHistoryCombo* searchFor;
+ KHistoryCombo* containsText;
+
+ KComboBox* ofType;
+
+ KShellCompletion completion;
+
+ TQListBox* profileListBox;
+
+ TQPushButton *profileAddBtn;
+ TQPushButton *profileLoadBtn;
+ TQPushButton *profileOverwriteBtn;
+ TQPushButton *profileRemoveBtn;
+
+ ProfileManager *profileManager;
+
+ int properties;
+
+ FilterTabs *fltTabs;
+
+};
+
+#endif /* GENERALFILTER_H */
diff --git a/src/app/GUI/Makefile.am b/src/app/GUI/Makefile.am
new file mode 100644
index 0000000..f7d9c9e
--- /dev/null
+++ b/src/app/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/src/app/GUI/dirhistorybutton.cpp b/src/app/GUI/dirhistorybutton.cpp
new file mode 100644
index 0000000..a311b0a
--- /dev/null
+++ b/src/app/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 <tqpopupmenu.h>
+#include <tqdir.h>
+#include <tdelocale.h>
+#include <kiconloader.h>
+
+#include <kdebug.h>
+
+DirHistoryButton::DirHistoryButton( DirHistoryQueue* hQ, TQWidget *parent, const char *name ) : TQToolButton( parent, name ) {
+ TDEIconLoader * iconLoader = new TDEIconLoader();
+ TQPixmap icon = iconLoader->loadIcon( "history", TDEIcon::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 TQPopupMenu( this );
+ TQ_CHECK_PTR( popupMenu );
+
+ setPopup( popupMenu );
+ popupMenu->setCheckable( true );
+
+ historyQueue = hQ;
+
+ connect( popupMenu, TQ_SIGNAL( aboutToShow() ), this, TQ_SLOT( slotAboutToShow() ) );
+ connect( popupMenu, TQ_SIGNAL( activated( int ) ), this, TQ_SLOT( slotPopupActivated( int ) ) );
+}
+
+DirHistoryButton::~DirHistoryButton() {}
+
+void DirHistoryButton::openPopup() {
+ TQPopupMenu * pP = popup();
+ if ( pP ) {
+ popup() ->exec( mapToGlobal( TQPoint( 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/src/app/GUI/dirhistorybutton.h b/src/app/GUI/dirhistorybutton.h
new file mode 100644
index 0000000..ae0da17
--- /dev/null
+++ b/src/app/GUI/dirhistorybutton.h
@@ -0,0 +1,57 @@
+/***************************************************************************
+ 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 <tqwidget.h>
+#include <tqtoolbutton.h>
+#include <kurl.h>
+
+class TQPopupMenu;
+class DirHistoryQueue;
+
+/**
+ *@author Shie Erlich & Rafi Yanai
+ */
+
+class DirHistoryButton : public TQToolButton {
+ TQ_OBJECT
+
+public:
+ DirHistoryButton(DirHistoryQueue* hQ, TQWidget *parent=0, const char *name=0);
+ ~DirHistoryButton();
+
+ void openPopup();
+
+private:
+ TQPopupMenu* 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/src/app/GUI/dirhistoryqueue.cpp b/src/app/GUI/dirhistoryqueue.cpp
new file mode 100644
index 0000000..08c384e
--- /dev/null
+++ b/src/app/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, TQ_SIGNAL( pathChanged( ListPanel* ) ), this, TQ_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 TQString& path ) {
+ TQStringList::iterator it;
+ it = pathQueue.find( path );
+ if ( it != pathQueue.end() ) {
+ pathQueue.remove( it );
+ }
+}
+
+bool DirHistoryQueue::checkPath( const TQString& path ) {
+ KURL url( path );
+
+ TQString p = url.path();
+ // kdDebug() << "url:" << p << ", file: " << url.fileName() << ", dir: " << url.directory() << endl;
+ if ( url.protocol() == "file" ) {
+ TQDir dir( path );
+ if ( !dir.exists() ) {
+ RemovePath( path );
+ return false;
+ }
+ }
+
+ return true;
+
+}
+#endif
+
+#include "dirhistoryqueue.moc"
diff --git a/src/app/GUI/dirhistoryqueue.h b/src/app/GUI/dirhistoryqueue.h
new file mode 100644
index 0000000..30a23a4
--- /dev/null
+++ b/src/app/GUI/dirhistoryqueue.h
@@ -0,0 +1,48 @@
+/***************************************************************************
+ 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 <tqobject.h>
+#include <kurl.h>
+
+class ListPanel;
+
+/**
+ *@author Shie Erlich & Rafi Yanai
+ */
+
+class DirHistoryQueue : public TQObject {
+ TQ_OBJECT
+
+public:
+ DirHistoryQueue(ListPanel* p);
+ ~DirHistoryQueue();
+ KURL::List urlQueue;
+// bool checkPath(const TQString& path);
+// void RemovePath(const TQString& path);
+
+public slots: // Public slots
+ /** No descriptions */
+ void slotPathChanged(ListPanel* p);
+private:
+// void addUrl(const KURL& url);
+ ListPanel* panel;
+};
+
+#endif
diff --git a/src/app/GUI/kcmdline.cpp b/src/app/GUI/kcmdline.cpp
new file mode 100644
index 0000000..15ba45f
--- /dev/null
+++ b/src/app/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 <tqmessagebox.h>
+#include <kprocess.h>
+#include <tqiconset.h>
+#include <tqwhatsthis.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 <tqdir.h>
+#include <kstandarddirs.h>
+#include <tdelocale.h>
+#include <tdeglobalsettings.h>
+#include <tqfontmetrics.h>
+#include <tqimage.h>
+#include <tqstringlist.h>
+#include <tqsizepolicy.h>
+#include <tdetempfile.h>
+
+KCMDLine::KCMDLine( TQWidget *parent, const char *name ) : TQWidget( parent, name ) {
+ TQGridLayout * layout = new TQGridLayout( this, 1, 4 );
+ path = new TQLabel( this );
+ TQWhatsThis::add
+ ( path, i18n( "Name of directory where command will be processed." ) );
+ path->setAlignment( TQt::AlignRight );
+ path->setFrameStyle( TQFrame::Box | TQFrame::Sunken );
+ path->setLineWidth( 1 );
+ path->setFont( TDEGlobalSettings::generalFont() );
+ int height = TQFontMetrics( TDEGlobalSettings::generalFont() ).height();
+ height = height + 5*(height > 14) + 6;
+ path->setMaximumHeight( height );
+ path->setSizePolicy(TQSizePolicy(TQSizePolicy::Maximum, TQSizePolicy::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( TDEGlobalSettings::generalFont() );
+ cmdLine->setMaximumHeight( height );
+ cmdLine->setCompletionObject( &completion );
+ cmdLine->setSizePolicy(TQSizePolicy(TQSizePolicy::Preferred, TQSizePolicy::Fixed));
+ // load the history
+ TDEConfigGroupSaver grpSvr( krConfig, "Private" );
+ TQStringList list = krConfig->readListEntry( "cmdline history" );
+ cmdLine->setHistoryItems( list );
+
+ connect( cmdLine, TQ_SIGNAL( returnPressed(const TQString &) ), this, TQ_SLOT( slotRun() ) );
+ connect( cmdLine, TQ_SIGNAL( returnPressed(const TQString &) ), cmdLine, TQ_SLOT( clearEdit() ) );
+ connect( cmdLine, TQ_SIGNAL( returnToPanel() ), this, TQ_SLOT( slotReturnFocus() ));
+
+ TQWhatsThis::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 TQToolButton( this, "ButtonAddPlaceholder" );
+ buttonAddPlaceholder->setFixedSize(22,20);
+ buttonAddPlaceholder->adjustSize();
+ buttonAddPlaceholder->setPixmap( SmallIcon( "add" ) );
+ connect( buttonAddPlaceholder, TQ_SIGNAL( clicked() ), this, TQ_SLOT( addPlaceholder() ) );
+ TQWhatsThis::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 );
+ TQString exp = popup.getPlaceholder(
+ buttonAddPlaceholder->mapToGlobal( TQPoint( 0, 0) )
+ );
+ this->addText( exp );
+}
+
+void KCMDLine::setCurrent( const TQString &p ) {
+
+ TQString pathName = p;
+ TQFontMetrics 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() {
+ TDEConfigGroupSaver grpSvr( krConfig, "Private" );
+ TQStringList list = cmdLine->historyItems();
+ //krOut << list[0] << endl;
+ krConfig->writeEntry( "cmdline history", list );
+ krConfig->sync();
+}
+
+void KCMDLine::slotRun() {
+ const TQString command1(cmdLine->currentText());
+ if ( command1.isEmpty() )
+ return ;
+ TQString panelPath = path->text().left( path->text().length() - 1 );
+
+ cmdLine->addToHistory(command1);
+
+ if ( command1.simplifyWhiteSpace().left( 3 ) == "cd " ) { // cd command effect the active panel
+ TQString dir = command1.right( command1.length() - command1.find( " " ) ).stripWhiteSpace();
+ if ( dir == "~" )
+ dir = TQDir::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,
+};
+
+TQString KCMDLine::command() const {
+ return cmdLine->currentText();
+}
+
+KrActionBase::ExecType KCMDLine::execType() const {
+ TDEConfigGroup grp( krConfig, "Private" );
+ int i = grp.readNumEntry("Command Execution Mode",0);
+ return execModesMenu[i];
+}
+
+TQString KCMDLine::startpath() const {
+ return path->text().left( path->text().length() - 1 );
+}
+
+TQString KCMDLine::user() const {
+ return TQString();
+}
+
+TQString 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(TQString text) {
+ cmdLine->setCurrentText( text );
+}
+
+void KrHistoryCombo::keyPressEvent( TQKeyEvent *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/src/app/GUI/kcmdline.h b/src/app/GUI/kcmdline.h
new file mode 100644
index 0000000..be141c1
--- /dev/null
+++ b/src/app/GUI/kcmdline.h
@@ -0,0 +1,101 @@
+/***************************************************************************
+ 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
+
+// TQt includes
+#include <tqwidget.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqtoolbutton.h>
+
+// TDE includes
+#include <klineedit.h>
+#include <kshellcompletion.h>
+#include <kcombobox.h>
+
+#include "../UserAction/kractionbase.h"
+
+class KCMDModeButton;
+
+class KrHistoryCombo: public KHistoryCombo {
+ TQ_OBJECT
+
+
+ public:
+ KrHistoryCombo(TQWidget *parent): KHistoryCombo(parent) {}
+
+ protected:
+ void keyPressEvent( TQKeyEvent *e );
+
+ signals:
+ void returnToPanel();
+};
+
+class KCMDLine : public TQWidget, KrActionBase {
+ TQ_OBJECT
+
+ public:
+ KCMDLine( TQWidget *parent = 0, const char *name = 0 );
+ ~KCMDLine();
+ void setCurrent( const TQString & );
+ //virtual methods from KrActionBase
+ void setText(TQString text);
+ TQString command() const;
+ ExecType execType() const;
+ TQString startpath() const;
+ TQString user() const;
+ TQString text() const;
+ bool acceptURLs() const;
+ bool confirmExecution() const;
+ bool doSubstitution() const;
+ signals:
+ void signalRun();
+ public slots:
+ inline void setFocus() { cmdLine->setFocus(); } // overloaded for TDECmdLine
+ void slotReturnFocus(); // returns keyboard focus to panel
+ void slotRun();
+ void addPlaceholder();
+ void addText( TQString text ) { cmdLine->setCurrentText( cmdLine->currentText() + text ); }
+ void popup() { cmdLine->popup(); }
+
+
+ private:
+ TQLabel *path;
+ KrHistoryCombo *cmdLine;
+ KCMDModeButton *terminal;
+ TQToolButton *buttonAddPlaceholder;
+ KShellCompletion completion;
+};
+
+#endif
diff --git a/src/app/GUI/kcmdmodebutton.cpp b/src/app/GUI/kcmdmodebutton.cpp
new file mode 100644
index 0000000..b1e4a72
--- /dev/null
+++ b/src/app/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 <tdeactionclasses.h>
+#include <tdelocale.h>
+#include <kiconloader.h>
+#include <tdepopupmenu.h>
+
+#include <kdebug.h>
+
+KCMDModeButton::KCMDModeButton( TQWidget *parent, const char *name ) : TQToolButton( parent, name ) {
+ setFixedSize( 22, 20 );
+/* // from the old terminal-button:
+ setTextLabel( i18n( "If pressed, Krusader executes command line in a terminal." ) );
+ TQWhatsThis::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 TDEActionMenu( i18n("Execution mode") );
+ TQ_CHECK_PTR( action );
+ for( int i=0; Krusader::execTypeArray[i] != 0; i++ )
+ {
+ action->insert( *Krusader::execTypeArray[i] );
+ }
+ TQPopupMenu *pP = action->popupMenu();
+ TQ_CHECK_PTR( pP );
+ setPopup( pP );
+ setPopupDelay( 10 );
+ setAcceptDrops( false );
+}
+
+KCMDModeButton::~KCMDModeButton() {
+ delete action;
+}
+
+/** called when clicked to the button */
+void KCMDModeButton::openPopup() {
+ TQPopupMenu * pP = popup();
+ if ( pP ) {
+ popup() ->exec( mapToGlobal( TQPoint( 0, 0 ) ) );
+ }
+}
+
+
+
+#include "kcmdmodebutton.moc"
diff --git a/src/app/GUI/kcmdmodebutton.h b/src/app/GUI/kcmdmodebutton.h
new file mode 100644
index 0000000..cb00290
--- /dev/null
+++ b/src/app/GUI/kcmdmodebutton.h
@@ -0,0 +1,53 @@
+/***************************************************************************
+ 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 <tqtoolbutton.h>
+
+class TDEActionMenu;
+
+/**
+ * @author Vaclav Juza
+ *
+ * represents a button for switching the command-line execution mode
+ * It extends TQToolButton, set the icon etc., and creates a popup menu
+ * containing the actions to actually switch the mode.
+ */
+class KCMDModeButton : public TQToolButton {
+ TQ_OBJECT
+
+public:
+ /** Constructor. Sets up the menu, and the icon */
+ KCMDModeButton(TQWidget *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 */
+ TDEActionMenu *action;
+};
+
+#endif
diff --git a/src/app/GUI/kfnkeys.cpp b/src/app/GUI/kfnkeys.cpp
new file mode 100644
index 0000000..1db34c6
--- /dev/null
+++ b/src/app/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 <tqtooltip.h>
+#include <tdelocale.h>
+#include <tdeglobalsettings.h>
+#include <tqfontmetrics.h>
+#include <tqwhatsthis.h>
+#include "kfnkeys.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include "../krslots.h"
+
+KFnKeys::KFnKeys(TQWidget *parent, char *name): TQWidget(parent,name) {
+ krConfig->setGroup("Look&Feel");
+ ////////////////////////////////
+#define SETUP(TARGET) {\
+ TARGET->setMinimumWidth(45);\
+}
+
+ setFont( TDEGlobalSettings::generalFont() );
+ layout=new TQGridLayout(this,1,9); // 9 keys
+ F2=new TQPushButton( i18n("F2 Term ") ,this);
+ TQToolTip::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,TQ_SIGNAL(clicked()), SLOTS, TQ_SLOT(terminal()));
+ SETUP(F2);
+
+ F3=new TQPushButton( i18n("F3 View ") ,this);
+ TQToolTip::add( F3, i18n( "Open file in viewer." ) );
+ connect(F3,TQ_SIGNAL(clicked()), SLOTS, TQ_SLOT(view()));
+ SETUP(F3);
+
+ F4=new TQPushButton( i18n("F4 Edit ") ,this);
+ TQToolTip::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,TQ_SIGNAL(clicked()), SLOTS, TQ_SLOT(edit()));
+ SETUP(F4);
+
+ F5=new TQPushButton( i18n("F5 Copy ") ,this);
+ TQToolTip::add( F5, i18n( "Copy file from one panel to the other." ) );
+ connect(F5,TQ_SIGNAL(clicked()), SLOTS, TQ_SLOT(copyFiles()));
+ SETUP(F5);
+
+ F6=new TQPushButton( i18n("F6 Move") ,this);
+ TQToolTip::add( F6, i18n( "Move file from one panel to the other." ) );
+ connect(F6,TQ_SIGNAL(clicked()), SLOTS, TQ_SLOT(moveFiles()));
+ SETUP(F6);
+
+ F7=new TQPushButton( i18n("F7 Mkdir ") ,this);
+ TQToolTip::add( F7, i18n( "Create directory in current panel." ) );
+ connect(F7,TQ_SIGNAL(clicked()), SLOTS, TQ_SLOT(mkdir()));
+ SETUP(F7);
+
+ F8=new TQPushButton( i18n("F8 Delete") ,this);
+ TQToolTip::add( F8, i18n( "Delete file, directory, etc." ) );
+ connect(F8,TQ_SIGNAL(clicked()), SLOTS, TQ_SLOT(deleteFiles()));
+ SETUP(F8);
+
+ F9=new TQPushButton( i18n("F9 Rename") ,this);
+ TQToolTip::add( F9, i18n( "Rename file, directory, etc." ) );
+ connect(F9,TQ_SIGNAL(clicked()), SLOTS, TQ_SLOT(rename()));
+ SETUP(F9);
+
+ F10=new TQPushButton( i18n("F10 Quit ") ,this);
+ TQToolTip::add( F10, i18n( "Quit Krusader." ) );
+ connect(F10,TQ_SIGNAL(clicked()),krApp, TQ_SLOT(slotClose()));
+ SETUP(F10);
+
+ // set a tighter box around the keys
+ int h = TQFontMetrics(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/src/app/GUI/kfnkeys.h b/src/app/GUI/kfnkeys.h
new file mode 100644
index 0000000..86fc30c
--- /dev/null
+++ b/src/app/GUI/kfnkeys.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+ 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 <tqwidget.h>
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+
+// Function Keys widget
+///////////////////////
+class KFnKeys : public TQWidget {
+ TQ_OBJECT
+
+
+public:
+ // constructor
+ KFnKeys(TQWidget *parent, char *name=0);
+ void updateShortcuts();
+
+private:
+ TQPushButton *F2 ,*F3,*F4,*F5,*F6,*F7,*F8,*F9,*F10;
+ TQGridLayout *layout;
+};
+
+#endif
diff --git a/src/app/GUI/krremoteencodingmenu.cpp b/src/app/GUI/krremoteencodingmenu.cpp
new file mode 100644
index 0000000..2b9f19c
--- /dev/null
+++ b/src/app/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 <tdepopupmenu.h>
+#include <kcharsets.h>
+#include <tdeio/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 TQString::fromLatin1("Charset")
+
+KrRemoteEncodingMenu::KrRemoteEncodingMenu(const TQString &text, const TQString &icon, TQObject *parent, const char *name) :
+ TDEActionMenu( text, icon, parent, name ), settingsLoaded( false )
+{
+ connect(popupMenu(), TQ_SIGNAL(aboutToShow()), this, TQ_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();
+
+ TQString charset = TDEIO::SlaveConfig::self()->configData(currentURL.protocol(), currentURL.host(), DATA_KEY);
+ if (!charset.isEmpty())
+ {
+ int id = 1;
+ TQStringList::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 = TDEGlobal::charsets()->descriptiveEncodingNames();
+
+ TDEPopupMenu *menu = popupMenu();
+ menu->clear();
+
+ TQStringList::ConstIterator it;
+ int count = 0;
+ for (it = encodingNames.begin(); it != encodingNames.end(); ++it)
+ menu->insertItem(*it, this, TQ_SLOT(slotItemSelected(int)), 0, ++count);
+ menu->insertSeparator();
+
+ menu->insertItem(i18n("Reload"), this, TQ_SLOT(slotReload()), 0, ++count);
+ menu->insertItem(i18n("Default"), this, TQ_SLOT(slotDefault()), 0, ++count);
+ defaultID = count;
+}
+
+int KrRemoteEncodingMenu::plug( TQWidget *widget, int index )
+{
+ if( widget->inherits( "TQPopupMenu" ) )
+ {
+ connect( widget, TQ_SIGNAL(aboutToShow()), this, TQ_SLOT(slotCheckEnabled()));
+ slotCheckEnabled();
+ }
+
+ return TDEActionMenu::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();
+
+ TDEConfig config(("tdeio_" + currentURL.protocol() + "rc").latin1());
+ TQString host = currentURL.host();
+
+ if (!popupMenu()->isItemChecked(id))
+ {
+ TQString charset = TDEGlobal::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.
+ TDEConfig config(("tdeio_" + currentURL.protocol() + "rc").latin1());
+
+ TQStringList partList = TQStringList::split('.', currentURL.host(), false);
+ if (!partList.isEmpty())
+ {
+ partList.remove(partList.begin());
+
+ TQStringList 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 (TQStringList::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;
+
+ TQByteArray data;
+ TQDataStream stream(data, IO_WriteOnly);
+ stream << TQString();
+ client->send("*", "TDEIO::Scheduler", "reparseSlaveConfiguration(TQString)", data);
+ delete client;
+
+ // Reload the page with the new charset
+ TQTimer::singleShot( 500, ACTIVE_FUNC, TQ_SLOT( refresh() ) );
+}
+
+#include "krremoteencodingmenu.moc"
diff --git a/src/app/GUI/krremoteencodingmenu.h b/src/app/GUI/krremoteencodingmenu.h
new file mode 100644
index 0000000..254be82
--- /dev/null
+++ b/src/app/GUI/krremoteencodingmenu.h
@@ -0,0 +1,68 @@
+/***************************************************************************
+ 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 <tqstringlist.h>
+#include <kurl.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+
+class KrRemoteEncodingMenu: public TDEActionMenu
+{
+ TQ_OBJECT
+
+public:
+ KrRemoteEncodingMenu (const TQString &text, const TQString &icon, TQObject *parent=0, const char *name=0);
+
+ virtual int plug( TQWidget *widget, int index = -1);
+
+protected slots:
+
+ void slotAboutToShow();
+ void slotCheckEnabled();
+
+ void slotItemSelected(int);
+ void slotReload();
+ void slotDefault();
+
+private:
+
+ void loadSettings();
+ void updateKIOSlaves();
+
+ TQStringList encodingNames;
+ bool settingsLoaded;
+ int defaultID;
+};
+
+#endif /* REMOTEENCODING_MENU_H */
diff --git a/src/app/GUI/krusaderstatus.cpp b/src/app/GUI/krusaderstatus.cpp
new file mode 100644
index 0000000..aa5f7f0
--- /dev/null
+++ b/src/app/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 <tqfontmetrics.h>
+#include "krusaderstatus.h"
+#include "../resources.h"
+
+
+KrusaderStatus::KrusaderStatus(TQWidget *parent, const char *name ):
+ KStatusBar(parent,name){
+ insertItem(i18n("Ready."), S_READY_ID);
+ setMaximumHeight(TQFontMetrics(font()).height()+2);
+}
+
+KrusaderStatus::~KrusaderStatus(){
+}
+
+#include "krusaderstatus.moc"
diff --git a/src/app/GUI/krusaderstatus.h b/src/app/GUI/krusaderstatus.h
new file mode 100644
index 0000000..de8bec7
--- /dev/null
+++ b/src/app/GUI/krusaderstatus.h
@@ -0,0 +1,57 @@
+/***************************************************************************
+ 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
+
+// TQt includes
+#include <tqlabel.h>
+#include <tqwidget.h>
+#include <tqframe.h>
+
+// TDE includes
+#include <kstatusbar.h>
+#include <tdelocale.h>
+
+class KrusaderStatus : public KStatusBar {
+ TQ_OBJECT
+
+public:
+ KrusaderStatus(TQWidget *parent=0, const char *name=0);
+ ~KrusaderStatus();
+
+private:
+ TQLabel *mess;
+
+};
+
+#endif
diff --git a/src/app/GUI/mediabutton.cpp b/src/app/GUI/mediabutton.cpp
new file mode 100644
index 0000000..c4cf6fd
--- /dev/null
+++ b/src/app/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 <tqpopupmenu.h>
+#include <tqfile.h>
+#include <tqfontmetrics.h>
+
+#include <tdelocale.h>
+#include <kiconloader.h>
+
+#include <tdeversion.h>
+#include <tdeio/job.h>
+#include <tdemessagebox.h>
+#include <kmimetype.h>
+#include <kprotocolinfo.h>
+#include <tdefileitem.h>
+#include <kprocess.h>
+#include <tqcursor.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 <tqfile.h>
+#endif
+
+
+
+MediaButton::MediaButton( TQWidget *parent, const char *name ) : TQToolButton( parent, name ),
+ popupMenu( 0 ), rightMenu( 0 ), hasMedia( false ), waitingForMount( -1 ), mountCheckerTimer()
+ {
+ TDEIconLoader * iconLoader = new TDEIconLoader();
+ TQPixmap icon = iconLoader->loadIcon( "blockdevice", TDEIcon::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 TQPopupMenu( this );
+ popupMenu->installEventFilter( this );
+ TQ_CHECK_PTR( popupMenu );
+
+ setPopup( popupMenu );
+
+ connect( popupMenu, TQ_SIGNAL( aboutToShow() ), this, TQ_SLOT( slotAboutToShow() ) );
+ connect( popupMenu, TQ_SIGNAL( aboutToHide() ), this, TQ_SLOT( slotAboutToHide() ) );
+ connect( popupMenu, TQ_SIGNAL( activated( int ) ), this, TQ_SLOT( slotPopupActivated( int ) ) );
+
+ connect( &mountCheckerTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( slotTimeout() ) );
+}
+
+MediaButton::~MediaButton() {
+ busy = false;
+}
+
+void MediaButton::slotAboutToShow() {
+ hasMedia = KProtocolInfo::isKnownProtocol( TQString( "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() {
+ TDEIO::ListJob *job = TDEIO::listDir( KURL( "media:/" ), false );
+ connect( job, TQ_SIGNAL( entries( TDEIO::Job*, const TDEIO::UDSEntryList& ) ),
+ this, TQ_SLOT( slotEntries( TDEIO::Job*, const TDEIO::UDSEntryList& ) ) );
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ),
+ this, TQ_SLOT( slotListResult( TDEIO::Job* ) ) );
+ busy = true;
+
+ if( !busy )
+ tqApp->processEvents();
+}
+
+void MediaButton::slotEntries( TDEIO::Job *, const TDEIO::UDSEntryList& entries )
+{
+ KMountPoint::List mountList = KMountPoint::currentMountPoints();
+
+ TDEIO::UDSEntryListConstIterator it = entries.begin();
+ TDEIO::UDSEntryListConstIterator end = entries.end();
+
+ while( it != end )
+ {
+ KURL url;
+ TQString text;
+ TQString mime;
+ TQString localPath;
+ bool mounted = false;
+
+ TDEIO::UDSEntry::ConstIterator it2 = (*it).begin();
+
+ for( ; it2 != (*it).end(); it2++ ) {
+ switch ((*it2).m_uds) {
+ case TDEIO::UDS_NAME:
+ text = KURL::decode_string((*it2).m_str);
+ break;
+ case TDEIO::UDS_URL:
+ url = KURL::fromPathOrURL( (*it2).m_str );
+ break;
+ case TDEIO::UDS_MIME_TYPE:
+ mime = (*it2).m_str;
+ if( !mime.endsWith( "unmounted" ) )
+ mounted = true;
+ break;
+#if KDE_IS_VERSION(3,4,0)
+ case TDEIO::UDS_LOCAL_PATH:
+ localPath = (*it2).m_str;
+ break;
+#endif
+ }
+ }
+
+ if( text != "." && text != ".." ) {
+ int index = popupMenu->count();
+ TQPixmap pixmap = FL_LOADICON( KMimeType::mimeType( mime ) ->icon( TQString(), 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( TDEIO::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) {
+ TQString name = (*it)->mountedFrom();
+ name = name.mid( name.findRev( "/" ) + 1 );
+ if( name == url.fileName() ) {
+ TQString 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, TQt 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 = "";
+ TQFontMetrics 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 );
+ }
+}
+
+TQString MediaButton::detectType( KMountPoint *mp )
+{
+ TQString typeName = TQString();
+#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;
+ TQString 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
+ TQFile m(TQString("/proc/ide/") + devname + "/media");
+ if(m.open(IO_ReadOnly))
+ {
+ TQTextStream in(&m);
+ TQString buf=in.readLine();
+ if(buf.contains("cdrom"))
+ isCd=true;
+ m.close();
+ }
+ }
+ if(isCd)
+ {
+ int device=::open((const char *)TQFile::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 TQString &mountPoint, unsigned long kBSize, unsigned long, unsigned long ) {
+ KURL mediaURL = KURL::fromPathOrURL( mountPoint );
+
+ TDEIO::filesize_t size = kBSize;
+ size *= 1024;
+ TQString sizeText = TDEIO::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
+ TQString mime = mimes[ i ];
+ if( mimes[ i ].endsWith( "_mounted" ) ) {
+ quasiMounted[ i ] = true;
+ mimes[ i ] = mimes[ i ].replace( "_mounted", "_unmounted" );
+ }
+
+ TQPixmap pixmap = FL_LOADICON( KMimeType::mimeType( mimes[ i ] ) ->icon( TQString(), 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() {
+ TQPopupMenu * pP = popup();
+ if ( pP ) {
+ popup() ->exec( mapToGlobal( TQPoint( 0, height() ) ) );
+ }
+}
+
+void MediaButton::addMountPoint( KMountPoint * mp, bool isMounted ) {
+ TQString 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;
+ }
+
+ TQString name;
+ TQString type = detectType( mp );
+
+ /* WORKAROUND CODE START */
+ /* add spaces to avoid widget resize in gettingSpaceData,
+ which is buggy in TQt when transparency is set */
+ TQString extSpc = ( isMounted && type == "hdd" ) ? extraSpaces : "";
+ /* WORKAROUND CODE END */
+
+#if KDE_IS_VERSION(3,4,0)
+ TQString mimeBase = "media/";
+#else
+ TQString mimeBase = "kdedevice/";
+#endif
+
+ TQString 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, TQ_SIGNAL( foundMountPoint( const TQString &, unsigned long, unsigned long, unsigned long ) ),
+ this, TQ_SLOT( gettingSpaceData( const TQString&, unsigned long, unsigned long, unsigned long ) ) );
+ }
+
+ TQPixmap pixmap = FL_LOADICON( KMimeType::mimeType( mime ) ->icon( TQString(), 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( TQObject *o, TQEvent *e ) {
+ if( o == popupMenu ) {
+ if( e->type() == TQEvent::MouseButtonPress || e->type() == TQEvent::MouseButtonRelease ) {
+ TQMouseEvent *m = static_cast<TQMouseEvent*>(e);
+ if( m->button() == TQt::RightButton ) {
+ if( e->type() == TQEvent::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();
+
+ TQString mime = mimes[ index ];
+ bool ejectable = mime.contains( "dvd_" ) || mime.contains( "dvdwriter_" ) || mime.contains( "cdrom_" ) || mime.contains( "cdwriter_" );
+ bool mounted = mime.contains( "_mounted" );
+
+ TQPopupMenu * myMenu = rightMenu = new TQPopupMenu( 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( TQCursor::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() ) {
+ TDEProcess proc;
+ proc << KrServices::fullPathName( "tdeio_media_mounthelper" ) << "-m" << mediaUrls[ index ].url();
+ proc.start( TDEProcess::DontCare );
+ } else {
+ krMtMan.mount( urls[ index ].path(), false );
+ }
+ }
+ return false;
+}
+
+bool MediaButton::umount( int index ) {
+ if ( (unsigned)index < mimes.count() ) {
+ if( !mediaUrls[ index ].isEmpty() ) {
+ TDEProcess proc;
+ proc << KrServices::fullPathName( "tdeio_media_mounthelper" ) << "-u" << mediaUrls[ index ].url();
+ proc.start( TDEProcess::DontCare );
+ } else {
+ krMtMan.unmount( urls[ index ].path(), false );
+ }
+ }
+ return false;
+}
+
+bool MediaButton::eject( int index ) {
+ if ( (unsigned)index < mimes.count() ) {
+ if( !mediaUrls[ index ].isEmpty() ) {
+ TDEProcess proc;
+ proc << KrServices::fullPathName( "tdeio_media_mounthelper" ) << "-e" << mediaUrls[ index ].url();
+ proc.start( TDEProcess::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;
+
+ TQString 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" );
+
+ TQPixmap pixmap = FL_LOADICON( KMimeType::mimeType( mimes[ index ] ) ->icon( TQString(), 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/src/app/GUI/mediabutton.h b/src/app/GUI/mediabutton.h
new file mode 100644
index 0000000..c416913
--- /dev/null
+++ b/src/app/GUI/mediabutton.h
@@ -0,0 +1,107 @@
+/***************************************************************************
+ 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 <tqwidget.h>
+#include <tqtoolbutton.h>
+#include <kurl.h>
+#include <tdeio/jobclasses.h>
+#include <tqvaluelist.h>
+#include <kmountpoint.h>
+#include <tqtimer.h>
+
+/**
+ *@author Csaba Karai
+ */
+
+class TQPopupMenu;
+class KMountPoint;
+
+class MediaButton : public TQToolButton {
+ TQ_OBJECT
+
+public:
+ MediaButton(TQWidget *parent=0, const char *name=0);
+ ~MediaButton();
+
+ TQString detectType( KMountPoint *mp );
+
+public slots:
+ void slotAboutToShow();
+ void slotAboutToHide();
+ void slotTimeout();
+ void slotPopupActivated( int );
+ void gettingSpaceData(const TQString &mountPoint, unsigned long kBSize, unsigned long kBUsed, unsigned long kBAvail);
+ void openPopup();
+ void slotEntries( TDEIO::Job*, const TDEIO::UDSEntryList& );
+ void slotListResult( TDEIO::Job* );
+
+signals:
+ void openUrl(const KURL&);
+
+protected:
+ bool eventFilter( TQObject *o, TQEvent *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 );
+
+ TQPopupMenu *popupMenu;
+ TQPopupMenu *rightMenu;
+
+ bool hasMedia;
+ bool busy;
+
+ int waitingForMount;
+ bool newTabAfterMount;
+ int maxMountWait;
+
+ TQValueList<KURL> urls;
+ TQValueList<KURL> mediaUrls;
+ TQValueList<TQString> mimes;
+ TQValueList<bool> quasiMounted;
+
+ TQString extraSpaces; //prevents from increasing the size of the widget
+
+ TQTimer mountCheckerTimer;
+};
+
+#endif /* MEDIABUTTON_H */
diff --git a/src/app/GUI/profilemanager.cpp b/src/app/GUI/profilemanager.cpp
new file mode 100644
index 0000000..8805845
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <tqtooltip.h>
+#include <tdepopupmenu.h>
+#include <tqcursor.h>
+#include <kinputdialog.h>
+#include <kiconloader.h>
+
+ProfileManager::ProfileManager( TQString profileType, TQWidget * parent, const char * name )
+ : TQPushButton( parent, name )
+{
+ setText( "" );
+ TDEIconLoader *iconLoader = new TDEIconLoader();
+ setPixmap( iconLoader->loadIcon( "kr_profile", TDEIcon::Toolbar, 16 ) );
+ TQToolTip::add( this, i18n( "Profiles" ) );
+
+ this->profileType = profileType;
+
+ connect( this, TQ_SIGNAL( clicked() ), this, TQ_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
+ TDEPopupMenu popup, removePopup, overwritePopup;
+ popup.insertTitle(i18n("Profiles"));
+
+ for( unsigned i=0; i != profileList.count() ; i++ )
+ {
+ krConfig->setGroup( profileType + " - " + profileList[i] );
+ TQString 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(TQCursor::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( TQString defaultName )
+{
+ TQString profile = KInputDialog::getText( i18n( "Krusader::ProfileManager" ), i18n( "Enter the profile name:" ),
+ defaultName, 0, this );
+ if( !profile.isEmpty() )
+ {
+ int profileNum = 1;
+ while( profileList.contains( TQString( "%1" ).arg( profileNum ) ) )
+ profileNum++;
+
+ TQString profileString = TQString( "%1" ).arg( profileNum );
+ TQString profileName = profileType + " - " + profileString;
+ profileList.append( TQString( "%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( TQString name )
+{
+ for( unsigned i=0; i != profileList.count() ; i++ )
+ {
+ krConfig->setGroup( profileType + " - " + profileList[ i ] );
+ TQString 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( TQString name )
+{
+ for( unsigned i=0; i != profileList.count() ; i++ )
+ {
+ krConfig->setGroup( profileType + " - " + profileList[ i ] );
+ TQString currentName = krConfig->readEntry( "Name" );
+
+ if( name == currentName )
+ {
+ emit saveToProfile( profileType + " - " + profileList[ i ] );
+ return;
+ }
+ }
+}
+
+bool ProfileManager::loadProfile( TQString name )
+{
+ for( unsigned i=0; i != profileList.count() ; i++ )
+ {
+ krConfig->setGroup( profileType + " - " + profileList[i] );
+ TQString currentName = krConfig->readEntry( "Name" );
+
+ if( name == currentName )
+ {
+ emit loadFromProfile( profileType + " - " + profileList[ i ] );
+ return true;
+ }
+ }
+ return false;
+}
+
+TQStringList ProfileManager::availableProfiles( TQString profileType ) {
+ krConfig->setGroup("Private");
+ TQStringList profiles = krConfig->readListEntry( profileType );
+ TQStringList 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/src/app/GUI/profilemanager.h b/src/app/GUI/profilemanager.h
new file mode 100644
index 0000000..9fb244e
--- /dev/null
+++ b/src/app/GUI/profilemanager.h
@@ -0,0 +1,70 @@
+/***************************************************************************
+ 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 <tqpushbutton.h>
+#include <tqstring.h>
+
+class ProfileManager : public TQPushButton
+{
+ TQ_OBJECT
+
+
+public:
+ ProfileManager( TQString profileType, TQWidget * parent = 0, const char * name = 0 );
+
+ /**
+ * @param profileType Type of the profile (sync, search, ...)
+ * @return A list of all available profile-names
+ */
+ static TQStringList availableProfiles( TQString profileType );
+
+ TQStringList getNames();
+
+public slots:
+ void profilePopup();
+
+ void newProfile( TQString defaultName = TQString() );
+ void deleteProfile( TQString name );
+ void overwriteProfile( TQString name );
+ bool loadProfile( TQString name );
+
+signals:
+ void saveToProfile( TQString profileName );
+ void loadFromProfile( TQString profileName );
+
+private:
+ TQString profileType;
+ TQStringList profileList;
+};
+
+#endif /* PROFILEMANAGER_H */
diff --git a/src/app/GUI/syncbrowsebutton.cpp b/src/app/GUI/syncbrowsebutton.cpp
new file mode 100644
index 0000000..1c4bde8
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <kiconloader.h>
+
+//#include <kdebug.h>
+
+SyncBrowseButton::SyncBrowseButton(TQWidget *parent, const char *name) : TQToolButton(parent,name)
+{
+ TDEIconLoader *iconLoader = new TDEIconLoader();
+ _icon_on = iconLoader->loadIcon( "kr_syncbrowse_on", TDEIcon::Toolbar, 16 );
+ _icon_off = iconLoader->loadIcon( "kr_syncbrowse_off", TDEIcon::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, TQ_SIGNAL(toggled(bool)), this, TQ_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/src/app/GUI/syncbrowsebutton.h b/src/app/GUI/syncbrowsebutton.h
new file mode 100644
index 0000000..75e8ed8
--- /dev/null
+++ b/src/app/GUI/syncbrowsebutton.h
@@ -0,0 +1,67 @@
+/***************************************************************************
+ 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 <tqtoolbutton.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 TQToolButton {
+ TQ_OBJECT
+
+public:
+ SyncBrowseButton(TQWidget *parent=0, const char *name=0);
+ ~SyncBrowseButton();
+
+ int state();
+
+protected:
+ int _state;
+ TQPixmap _icon_on;
+ TQPixmap _icon_off;
+
+private slots:
+ void slotToggled(bool on);
+};
+
+#endif
diff --git a/src/app/KViewer/Makefile.am b/src/app/KViewer/Makefile.am
new file mode 100644
index 0000000..f4bf90f
--- /dev/null
+++ b/src/app/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/src/app/KViewer/diskusageviewer.cpp b/src/app/KViewer/diskusageviewer.cpp
new file mode 100644
index 0000000..3e00283
--- /dev/null
+++ b/src/app/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( TQWidget *parent, char *name )
+ : TQWidget( parent, name ), diskUsage( 0 ), statusLabel( 0 )
+{
+ layout = new TQGridLayout( 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, TQ_SIGNAL( enteringDirectory( Directory * ) ), this, TQ_SLOT( slotUpdateStatus() ) );
+ connect( diskUsage, TQ_SIGNAL( status( TQString ) ), this, TQ_SLOT( slotUpdateStatus( TQString ) ) );
+ connect( diskUsage, TQ_SIGNAL( newSearch() ), this, TQ_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() ) )
+ {
+ TQString baseStr = baseURL.path( 1 ), urlStr = url.path( 1 );
+
+ if( urlStr.startsWith( baseStr ) )
+ {
+ TQString 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( TQLabel *statLabel, TQString pref )
+{
+ statusLabel = statLabel;
+ prefix = pref;
+}
+
+void DiskUsageViewer::slotUpdateStatus( TQString status )
+{
+ if( statusLabel ) {
+ if( status.isEmpty() ) {
+ Directory * dir = diskUsage->getCurrentDir();
+ if( dir )
+ status = prefix + dir->name() + " [" + TDEIO::convertSize( dir->size() ) + "]";
+ }
+ statusLabel->setText( status );
+ }
+}
+
+void DiskUsageViewer::slotNewSearch()
+{
+ diskUsage->load( ACTIVE_PANEL->func->files()->vfs_getOrigin() );
+}
+
+#include "diskusageviewer.moc"
diff --git a/src/app/KViewer/diskusageviewer.h b/src/app/KViewer/diskusageviewer.h
new file mode 100644
index 0000000..a46e123
--- /dev/null
+++ b/src/app/KViewer/diskusageviewer.h
@@ -0,0 +1,69 @@
+/***************************************************************************
+ 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 <tqlayout.h>
+#include <tqlabel.h>
+
+class DiskUsageViewer : public TQWidget
+{
+ TQ_OBJECT
+
+
+public:
+ DiskUsageViewer( TQWidget *parent = 0, char *name = 0 );
+ ~DiskUsageViewer();
+
+ void openURL( KURL url );
+ void closeURL();
+ void setStatusLabel( TQLabel *statLabel, TQString pref );
+
+ inline DiskUsage * getWidget() { return diskUsage; }
+
+signals:
+ void openURLRequest(const KURL &);
+
+protected slots:
+ void slotUpdateStatus( TQString status = TQString() );
+ void slotNewSearch();
+
+protected:
+ DiskUsage *diskUsage;
+ TQGridLayout *layout;
+
+ TQLabel *statusLabel;
+ TQString prefix;
+};
+
+#endif /* DISKUSAGEVIEWER_H */
diff --git a/src/app/KViewer/kimagefilepreview.cpp b/src/app/KViewer/kimagefilepreview.cpp
new file mode 100644
index 0000000..f41e061
--- /dev/null
+++ b/src/app/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 <tqlayout.h>
+#include <tqlabel.h>
+#include <tqcombobox.h>
+#include <tqcheckbox.h>
+#include <tqwhatsthis.h>
+#include <tqtimer.h>
+
+#include <tdeapplication.h>
+#include <tdeglobal.h>
+#include <kiconloader.h>
+#include <kpushbutton.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include <tdelocale.h>
+#include <tdefiledialog.h>
+#include <tdefileitem.h>
+#include <tdeio/previewjob.h>
+
+#include "kimagefilepreview.h"
+
+/**** KrusaderImageFilePreview ****/
+
+KrusaderImageFilePreview::KrusaderImageFilePreview( TQWidget *parent )
+ : KPreviewWidgetBase( parent ),
+m_job( 0L ) {
+ TQVBoxLayout *vb = new TQVBoxLayout( this, KDialog::marginHint() );
+
+ imageLabel = new TQLabel( this );
+ imageLabel->setFrameStyle( TQFrame::Panel | TQFrame::Sunken );
+ imageLabel->setAlignment( TQt::AlignHCenter | TQt::AlignVCenter );
+ imageLabel->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Ignored ) );
+ vb->addWidget( imageLabel, 1 );
+
+ timer = new TQTimer( this );
+ connect( timer, TQ_SIGNAL( timeout() ), TQ_SLOT( showPreview() ) );
+
+ setSupportedMimeTypes( TDEIO::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, TQ_SIGNAL( result( TDEIO::Job * ) ),
+ this, TQ_SLOT( slotResult( TDEIO::Job * ) ) );
+ connect( m_job, TQ_SIGNAL( gotPreview( const KFileItem*,
+ const TQPixmap& ) ),
+ TQ_SLOT( gotPreview( const KFileItem*, const TQPixmap& ) ) );
+
+ connect( m_job, TQ_SIGNAL( failed( const KFileItem* ) ),
+ this, TQ_SLOT( slotFailed( const KFileItem* ) ) );
+ }
+}
+
+void KrusaderImageFilePreview::resizeEvent( TQResizeEvent * ) {
+ timer->start( 100, true ); // forces a new preview
+}
+
+TQSize KrusaderImageFilePreview::sizeHint() const {
+ return TQSize( 20, 200 ); // otherwise it ends up huge???
+}
+
+TDEIO::PreviewJob * KrusaderImageFilePreview::createJob( const KURL& url, int w, int h ) {
+ KURL::List urls;
+ urls.append( url );
+ return TDEIO::filePreview( urls, w, h, 0, 0, true, false );
+}
+
+void KrusaderImageFilePreview::gotPreview( const KFileItem* item, const TQPixmap& 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", TDEIcon::SizeLarge,
+ TDEIcon::DisabledState ) );
+}
+
+void KrusaderImageFilePreview::slotResult( TDEIO::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/src/app/KViewer/kimagefilepreview.h b/src/app/KViewer/kimagefilepreview.h
new file mode 100644
index 0000000..ada0806
--- /dev/null
+++ b/src/app/KViewer/kimagefilepreview.h
@@ -0,0 +1,71 @@
+/*
+*
+* 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 <tqpixmap.h>
+
+#include <kurl.h>
+#include <kpreviewwidgetbase.h>
+
+class TQCheckBox;
+class TQPushButton;
+class TQLabel;
+class TQTimer;
+
+class KFileDialog;
+class KFileItem;
+
+class KrusaderImageFilePreview : public KPreviewWidgetBase {
+ TQ_OBJECT
+
+
+ public:
+ KrusaderImageFilePreview( TQWidget *parent );
+ ~KrusaderImageFilePreview();
+
+ virtual TQSize 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 TQPixmap& );
+
+ protected:
+ virtual void resizeEvent( TQResizeEvent *e );
+ virtual TDEIO::PreviewJob * createJob( const KURL& url,
+ int w, int h );
+
+ private slots:
+ void slotResult( TDEIO::Job * );
+ virtual void slotFailed( const KFileItem* );
+
+ private:
+ KURL currentURL;
+ TQTimer *timer;
+ TQLabel *imageLabel;
+ TQLabel *infoLabel;
+ TDEIO::PreviewJob *m_job;
+ protected:
+ virtual void virtual_hook( int id, void* data );
+ private:
+ class KrusaderImageFilePreviewPrivate;
+ KrusaderImageFilePreviewPrivate *d;
+};
+
+#endif // KrusaderImageFilePreview_H
diff --git a/src/app/KViewer/krviewer.cpp b/src/app/KViewer/krviewer.cpp
new file mode 100644
index 0000000..f6e0357
--- /dev/null
+++ b/src/app/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. *
+ * *
+ ***************************************************************************/
+// TQt includes
+#include <tqdatastream.h>
+#include <tqfile.h>
+#include <tqpopupmenu.h>
+#include <tqtimer.h>
+// TDE includes
+#include <tdemenubar.h>
+#include <kmimetype.h>
+#include <tdelocale.h>
+#include <tdeparts/part.h>
+#include <tdeparts/componentfactory.h>
+#include <tdemessagebox.h>
+#include <klibloader.h>
+#include <ktrader.h>
+#include <tdeio/netaccess.h>
+#include <tdeio/jobclasses.h>
+#include <tdeio/job.h>
+#include <kstatusbar.h>
+#include <kdebug.h>
+#include <klargefile.h>
+#include <tdehtml_part.h>
+#include <kprocess.h>
+#include <tdefileitem.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 "document-save-as"
+
+
+TQPtrList<KrViewer> KrViewer::viewers;
+
+KrViewer::KrViewer( TQWidget *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, TQ_SIGNAL( activePartChanged( KParts::Part* ) ),
+ this, TQ_SLOT( createGUI( KParts::Part* ) ) );
+ connect( &tabBar, TQ_SIGNAL( currentChanged( TQWidget *) ),
+ this, TQ_SLOT( tabChanged(TQWidget*) ) );
+ connect( &tabBar, TQ_SIGNAL( closeRequest( TQWidget *) ),
+ this, TQ_SLOT( tabCloseRequest(TQWidget*) ) );
+
+ tabBar.setTabReorderingEnabled(false);
+#if KDE_IS_VERSION(3,4,0)
+ tabBar.setAutomaticResizeTabs(true);
+#endif
+// "edit"
+// "document-save-as"
+ setCentralWidget( &tabBar );
+
+ printAction = KStdAction::print( this, TQ_SLOT( print() ), 0, 0 );
+ copyAction = KStdAction::copy( this, TQ_SLOT( copy() ), 0, 0 );
+
+ viewerMenu = new TQPopupMenu( this );
+ viewerMenu->insertItem( i18n( "&Generic viewer" ), this, TQ_SLOT( viewGeneric() ), CTRL + SHIFT + Key_G, 1 );
+ viewerMenu->insertItem( i18n( "&Text viewer" ), this, TQ_SLOT( viewText() ), CTRL + SHIFT + Key_T, 2 );
+ viewerMenu->insertItem( i18n( "&Hex viewer" ), this, TQ_SLOT( viewHex() ), CTRL + SHIFT + Key_H, 3 );
+ viewerMenu->insertSeparator();
+ viewerMenu->insertItem( i18n( "Text &editor" ), this, TQ_SLOT( editText() ), CTRL + SHIFT + Key_E, 4 );
+ viewerMenu->insertSeparator();
+ viewerMenu->insertItem( i18n( "&Next tab" ), this, TQ_SLOT( nextTab() ), ALT+Key_Right );
+ viewerMenu->insertItem( i18n( "&Previous tab" ), this, TQ_SLOT( prevTab() ), ALT+Key_Left );
+
+ detachActionIndex = viewerMenu->insertItem( i18n( "&Detach tab" ), this, TQ_SLOT( detachTab() ), CTRL + SHIFT + Key_D );
+ //no point in detaching only one tab..
+ viewerMenu->setItemEnabled(detachActionIndex,false);
+ viewerMenu->insertSeparator();
+ viewerMenu->insertItem( printAction->text(), this, TQ_SLOT( print() ), printAction->shortcut() );
+ viewerMenu->insertItem( copyAction->text(), this, TQ_SLOT( copy() ), copyAction->shortcut() );
+ viewerMenu->insertSeparator();
+ tabCloseID = viewerMenu->insertItem( i18n( "&Close current tab" ), this, TQ_SLOT( tabCloseRequest() ), Key_Escape );
+ closeID = viewerMenu->insertItem( i18n( "&Quit" ), this, TQ_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, TQ_SIGNAL( activePartChanged( KParts::Part* ) ),
+ this, TQ_SLOT( createGUI( KParts::Part* ) ) );
+
+ viewers.remove( this );
+ delete printAction;
+ delete copyAction;
+}
+
+void KrViewer::createGUI( KParts::Part* part ) {
+ if ( part == 0 ) /* TDEHTMLPart 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, TQ_SIGNAL( setStatusBarText( const TQString& ) ),
+ this, TQ_SLOT( slotSetStatusBarText( const TQString& ) ) );
+
+ 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 );
+ TQKeySequence 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 ( TQObject * /* watched */, TQEvent * e )
+{
+ if( e->type() == TQEvent::AccelOverride )
+ {
+ TQKeyEvent* ke = (TQKeyEvent*) 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 )
+ TQTimer::singleShot( 0, this, TQ_SLOT( tabCloseRequest() ) );
+ else if( id == closeID )
+ TQTimer::singleShot( 0, this, TQ_SLOT( close() ) );
+ else {
+ int index = viewerMenu->indexOf( id );
+ viewerMenu->activateItemAt( index );
+ }
+ }
+ return true;
+ }
+ }
+ else if( e->type() == TQEvent::KeyPress )
+ {
+ TQKeyEvent* ke = (TQKeyEvent*) e;
+ if( reservedKeys.contains( ke->key() ) )
+ {
+ ke->accept();
+ return true;
+ }
+ }
+ return false;
+}
+void KrViewer::keyPressEvent( TQKeyEvent *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, TQWidget * parent ) {
+ Mode defaultMode = Generic;
+ bool defaultWindow = false;
+
+ krConfig->setGroup( "General" );
+ defaultWindow = krConfig->readBoolEntry( "View In Separate Window",_ViewInSeparateWindow );
+
+ TQString 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, TQWidget * 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, TQWidget * parent ) {
+ edit( url, Text, -1, parent );
+}
+
+void KrViewer::edit( KURL url, Mode mode, int new_window, TQWidget * parent ) {
+ krConfig->setGroup( "General" );
+ TQString edit = krConfig->readEntry( "Editor", _Editor );
+
+ if( new_window == -1 )
+ new_window = krConfig->readBoolEntry( "View In Separate Window",_ViewInSeparateWindow );
+
+ if ( edit != "internal editor" ) {
+ TDEProcess 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 << TQStringList::split( ' ', edit ) << url.path();
+ else proc << TQStringList::split( ' ', edit ) << url.prettyURL();
+ if ( !proc.start( TDEProcess::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, TQString msg, TQString iconName ,KParts::Part* part){
+ if( !part ) return;
+
+ KURL url = pvb->url();
+ setCaption( msg+": " + url.prettyURL() );
+
+ TQIconSet icon = TQIconSet(krLoader->loadIcon(iconName,TDEIcon::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, TQ_SIGNAL( urlChanged( PanelViewerBase *, const KURL & ) ),
+ this, TQ_SLOT( tabURLChanged(PanelViewerBase *, const KURL & ) ) );
+}
+
+void KrViewer::tabURLChanged( PanelViewerBase *pvb, const KURL & url ) {
+ TQString msg = pvb->isEditor() ? i18n( "Editing" ) : i18n( "Viewing" );
+ tabBar.setTabLabel( pvb, url.fileName()+"("+msg+")" );
+ tabBar.setTabToolTip(pvb,msg+": " + url.prettyURL());
+}
+
+void KrViewer::tabChanged(TQWidget* 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(TQWidget *w){
+ if( !w ) return;
+
+ // important to save as returnFocusTo will be cleared at removePart
+ TQWidget * 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(){
+ TQTimer::singleShot( 1000, this, TQ_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() ){
+ TQString label = tabBar.tabLabel(pvb);
+ if( !label.startsWith("*" + pvb->part()->url().fileName() ) ){
+ label.prepend("*");
+ TQIconSet icon = TQIconSet(krLoader->loadIcon(MODIFIED_ICON,TDEIcon::Small));
+
+ tabBar.changeTab(pvb,icon,label);
+ }
+ }
+ // remove the * from previously modified files.
+ else {
+ TQString label = tabBar.tabLabel(pvb);
+ if( label.startsWith("*" + pvb->part()->url().fileName() ) ){
+ label = label.mid( 1 );
+ TQIconSet icon = TQIconSet(krLoader->loadIcon(EDIT_ICON,TDEIcon::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,TQPoint(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, TQ_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, TQ_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( TQString mimetype, KURL _url ) {
+ KParts::ReadWritePart * kedit_part = 0L;
+ KLibFactory *factory = 0;
+ TDETrader::OfferList offers = TDETrader::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
+ TDETrader::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() {
+ TQString 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" ) ) {
+ TDEHTMLPart * p = new TDEHTMLPart( this, 0, 0, 0, TDEHTMLPart::BrowserViewGUI );
+ connect( p->browserExtension(), TQ_SIGNAL( openURLRequest( const KURL &, const KParts::URLArgs & ) ),
+ this, TQ_SLOT( handleOpenURLRequest( const KURL &, const KParts::URLArgs & ) ) );
+ /* At JavaScript self.close() the TDEHTMLPart destroys itself. */
+ /* After destruction, just close the window */
+ connect( p, TQ_SIGNAL( destroyed() ), this, TQ_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 ) {
+ TQString file;
+ // files that are not local must first be downloaded
+ if ( !url.isLocalFile() ) {
+ if ( !TDEIO::NetAccess::download( url, file ) ) {
+ KMessageBox::sorry( this, i18n( "KrViewer is unable to download: " ) + url.url() );
+ return ;
+ }
+ } else file = url.path();
+
+
+ // create a hex file
+ TQFile f_in( file );
+ f_in.open( IO_ReadOnly );
+ TQDataStream in( &f_in );
+
+ FILE *out = KDE_fopen( tmpFile.name().local8Bit(), "w" );
+
+ TDEIO::filesize_t fileSize = f_in.size();
+ TDEIO::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() )
+ TDEIO::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/src/app/KViewer/krviewer.h b/src/app/KViewer/krviewer.h
new file mode 100644
index 0000000..c4d12db
--- /dev/null
+++ b/src/app/KViewer/krviewer.h
@@ -0,0 +1,130 @@
+/***************************************************************************
+ 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 <tqwidget.h>
+#include <tqptrlist.h>
+#include <tdeparts/mainwindow.h>
+#include <tdetempfile.h>
+#include <tdeparts/partmanager.h>
+#include <tdeparts/browserextension.h>
+#include <tqguardedptr.h>
+#include <ktabwidget.h>
+
+#include "../krusader.h"
+
+
+/**
+ *@author Shie Erlich & Rafi Yanai
+ */
+
+class TQPopupMenu;
+class PanelViewerBase;
+
+class KrViewer : public KParts::MainWindow {
+ TQ_OBJECT
+
+public:
+ virtual ~KrViewer();
+
+ enum Mode{Generic,Text,Hex};
+
+ static void view( KURL url, TQWidget * parent = krApp );
+ static void view( KURL url, Mode mode, bool new_window, TQWidget * parent = krApp );
+ static void edit( KURL url, TQWidget * parent );
+ static void edit( KURL url, Mode mode=Text, int new_window=-1, TQWidget * parent = krApp );
+
+ virtual bool eventFilter ( TQObject * watched, TQEvent * e );
+
+public slots:
+ void keyPressEvent( TQKeyEvent *e );
+ void createGUI( KParts::Part* );
+
+ void viewGeneric();
+ void viewText();
+ void viewHex();
+ void editText();
+
+ void print();
+ void copy();
+
+ void tabChanged(TQWidget* w);
+ void tabURLChanged( PanelViewerBase * pvb, const KURL &url );
+ void tabCloseRequest(TQWidget *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( TQFocusEvent * ){ if( viewers.remove( this ) ) viewers.prepend( this ); } // move to first
+
+private:
+ KrViewer( TQWidget *parent = 0, const char *name = 0 );
+ void addTab(PanelViewerBase* pvb, TQString msg,TQString iconName, KParts::Part* part);
+ PanelViewerBase * getPanelViewerBase( KParts::Part* part);
+ void updateActions( PanelViewerBase * base );
+
+ static KrViewer* getViewer(bool new_window);
+
+ KParts::PartManager manager;
+ TQPopupMenu* viewerMenu;
+ KTempFile tmpFile;
+ KTabWidget tabBar;
+ TQGuardedPtr<TQWidget> returnFocusTo;
+ PanelViewerBase * returnFocusTab;
+
+ int detachActionIndex;
+
+ TDEAction *printAction;
+ TDEAction *copyAction;
+
+ int tabCloseID;
+ int closeID;
+
+ static TQPtrList<KrViewer> viewers; // the first viewer is the active one
+ TQValueList<int> reservedKeys; // the reserved key sequences
+ TQValueList<int> reservedKeyIDs; // the IDs of the reserved keys
+};
+
+class Invoker : public TQObject {
+ TQ_OBJECT
+
+
+public:
+ Invoker( TQObject *recv, const char * slot ) {
+ connect( this, TQ_SIGNAL( invokeSignal() ), recv, slot );
+ }
+
+ void invoke() {
+ emit invokeSignal();
+ }
+
+signals:
+ void invokeSignal();
+};
+
+#endif
diff --git a/src/app/KViewer/panelviewer.cpp b/src/app/KViewer/panelviewer.cpp
new file mode 100644
index 0000000..32f6532
--- /dev/null
+++ b/src/app/KViewer/panelviewer.cpp
@@ -0,0 +1,307 @@
+#include <kurl.h>
+#include <tqstring.h>
+#include <tqwidgetstack.h>
+#include <tqapplication.h>
+#include <tdeparts/part.h>
+#include <tdeparts/browserextension.h>
+#include <tdemessagebox.h>
+#include <tqdict.h>
+#include <tqlabel.h>
+#include <kmimetype.h>
+#include <tdetempfile.h>
+#include <tdelocale.h>
+#include <klibloader.h>
+#include <kuserprofile.h>
+#include <kdebug.h>
+#include <tdefileitem.h>
+#include <tdeio/netaccess.h>
+#include <tqfile.h>
+#include <klargefile.h>
+#include "panelviewer.h"
+
+#define DICTSIZE 211
+
+/* ----==={ PanelViewerBase }===---- */
+
+PanelViewerBase::PanelViewerBase( TQWidget *parent ) :
+TQWidgetStack( parent ), mimes( 0 ), cpart( 0 ) {
+ setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Ignored ) );
+
+ mimes = new TQDict<KParts::ReadOnlyPart>( DICTSIZE, false );
+ mimes->setAutoDelete( true );
+ cpart = 0;
+ fallback = new TQLabel( 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( TQWidget *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( TQString mimetype ) {
+ KParts::ReadOnlyPart * part = 0L;
+ KLibFactory *factory = 0;
+ KService::Ptr ptr = KServiceTypeProfile::preferredService( mimetype, "KParts/ReadOnlyPart" );
+ if ( ptr ) {
+ TQStringList args;
+ TQVariant argsProp = ptr->property( "X-TDE-BrowserView-Args" );
+ if ( argsProp.isValid() ) {
+ TQString argStr = argsProp.toString();
+ args = TQStringList::split( " ", argStr );
+ }
+ TQVariant prop = ptr->property( "X-TDE-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(), TQString( "KParts::ReadOnlyPart" ).latin1(), args ) );
+ }
+ }
+ }
+ if ( part ) {
+ KParts::BrowserExtension * ext = KParts::BrowserExtension::childObject( part );
+ if ( ext ) {
+ connect( ext, TQ_SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ), this, TQ_SLOT( openURL( const KURL & ) ) );
+ connect( ext, TQ_SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ), this, TQ_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) {
+ TQString file;
+ // files that are not local must first be downloaded
+ if ( !curl.isLocalFile() ) {
+ if ( !TDEIO::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
+ TQFile f_in( file );
+ f_in.open( IO_ReadOnly );
+ TQDataStream in( &f_in );
+
+ FILE *out = KDE_fopen( tmpFile.name().local8Bit(), "w" );
+
+ TDEIO::filesize_t fileSize = f_in.size();
+ TDEIO::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() )
+ TDEIO::NetAccess::removeTempFile( file );
+
+ curl = tmpFile.name();
+}
+
+/* ----==={ PanelEditor }===---- */
+
+PanelEditor::PanelEditor( TQWidget *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;
+ TDEIO::StatJob* statJob = TDEIO::stat( url, false );
+ connect( statJob, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( slotStatResult( TDEIO::Job* ) ) );
+ busy = true;
+ while ( busy ) tqApp->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( TQString mimetype ) {
+ KParts::ReadWritePart * part = 0L;
+ KLibFactory *factory = 0;
+ KService::Ptr ptr = KServiceTypeProfile::preferredService( mimetype, "KParts/ReadWritePart" );
+ if ( ptr ) {
+ TQStringList args;
+ TQVariant argsProp = ptr->property( "X-TDE-BrowserView-Args" );
+ if ( argsProp.isValid() ) {
+ TQString argStr = argsProp.toString();
+ args = TQStringList::split( " ", argStr );
+ }
+ TQVariant prop = ptr->property( "X-TDE-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(), TQString( "KParts::ReadWritePart" ).latin1(), args ) );
+ }
+ }
+ }
+ if ( part ) {
+ KParts::BrowserExtension * ext = KParts::BrowserExtension::childObject( part );
+ if ( ext ) {
+ connect( ext, TQ_SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ), this, TQ_SLOT( openURL( const KURL & ) ) );
+ connect( ext, TQ_SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ), this, TQ_SIGNAL( openURLRequest( const KURL & ) ) );
+ }
+ }
+ return part;
+}
+
+void PanelEditor::slotStatResult( TDEIO::Job* job ) {
+ if( !job || job->error() ) entry = TDEIO::UDSEntry();
+ else entry = static_cast<TDEIO::StatJob*>(job)->statResult();
+ busy = false;
+}
+
+bool PanelEditor::isModified(){
+ return static_cast<KParts::ReadWritePart *>(cpart)->isModified();
+}
+
+#include "panelviewer.moc"
diff --git a/src/app/KViewer/panelviewer.h b/src/app/KViewer/panelviewer.h
new file mode 100644
index 0000000..2875f92
--- /dev/null
+++ b/src/app/KViewer/panelviewer.h
@@ -0,0 +1,91 @@
+#ifndef _SUPERVIEW_H
+#define _SUPERVIEW_H
+
+#include <kurl.h>
+#include <tqstring.h>
+#include <tqwidgetstack.h>
+#include <tdeparts/part.h>
+#include <tdeio/job.h>
+#include <tdetempfile.h>
+#include <tqdict.h>
+#include <tqlabel.h>
+
+#include "krviewer.h"
+
+
+class PanelViewerBase: public TQWidgetStack {
+ TQ_OBJECT
+
+
+public:
+ PanelViewerBase( TQWidget *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:
+ TQDict<KParts::ReadOnlyPart> *mimes;
+ KParts::ReadOnlyPart *cpart;
+
+ TQString cmimetype;
+ KURL curl;
+ TQLabel *fallback;
+
+};
+
+class PanelViewer: public PanelViewerBase {
+ TQ_OBJECT
+
+public slots:
+ KParts::ReadOnlyPart* openURL( const KURL &url, KrViewer::Mode mode=KrViewer::Generic );
+ bool closeURL();
+
+public:
+ PanelViewer( TQWidget *parent = 0 );
+ ~PanelViewer();
+
+ virtual bool isEditor() { return false; }
+
+protected:
+ KParts::ReadOnlyPart *getPart( TQString mimetype );
+ KParts::ReadOnlyPart* getHexPart();
+ void oldHexViewer(KTempFile& tmpFile);
+};
+
+class PanelEditor: public PanelViewerBase {
+ TQ_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( TDEIO::Job* job );
+
+public:
+ PanelEditor( TQWidget *parent = 0 );
+ ~PanelEditor();
+
+protected:
+ KParts::ReadWritePart* getPart( TQString mimetype );
+
+ bool busy;
+ TDEIO::UDSEntry entry;
+};
+
+#endif
diff --git a/src/app/Konfigurator/Makefile.am b/src/app/Konfigurator/Makefile.am
new file mode 100644
index 0000000..9f1776c
--- /dev/null
+++ b/src/app/Konfigurator/Makefile.am
@@ -0,0 +1,23 @@
+noinst_LIBRARIES = libKonfigurator.a
+
+INCLUDES = -I$(top_builddir)/src/app/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/src/app/Konfigurator/kgadvanced.cpp b/src/app/Konfigurator/kgadvanced.cpp
new file mode 100644
index 0000000..e6b753b
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <tqhbox.h>
+#include <tqwhatsthis.h>
+#include <sys/param.h>
+#include <tdeversion.h>
+#include <kprotocolinfo.h>
+
+KgAdvanced::KgAdvanced( bool first, TQWidget* parent, const char* name ) :
+ KonfiguratorPage( first, parent, name )
+{
+ TQGridLayout *kgAdvancedLayout = new TQGridLayout( parent );
+ kgAdvancedLayout->setSpacing( 6 );
+
+ // -------------------------- GENERAL GROUPBOX ----------------------------------
+
+ TQGroupBox *generalGrp = createFrame( i18n( "General" ), parent, "kgAdvGeneralGrp" );
+ TQGridLayout *generalGrid = createGridLayout( generalGrp->layout() );
+
+#if KDE_IS_VERSION( 3,5,1 )
+ bool dontUseMedia = false;
+#else
+ bool dontUseMedia = true;
+#endif
+
+ bool isMediaProtocolPresent = KProtocolInfo::isKnownProtocol( TQString( "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 TDE's media protocol for media button (if it's buggy or missing)" ), false, i18n( "Select if your media protocol is buggy (in some older TDE versions), or not present (no tdebase 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 -------------------------------
+
+ TQGroupBox *confirmGrp = createFrame( i18n( "Confirmations" ), parent, "confirmGrp" );
+ TQGridLayout *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 --------------------------------
+
+ TQGroupBox *fineTuneGrp = createFrame( i18n( "Fine-Tuning" ), parent, "kgFineTuneGrp" );
+ TQGridLayout *fineTuneGrid = createGridLayout( fineTuneGrp->layout() );
+ fineTuneGrid->setAlignment( TQt::AlignLeft | TQt::AlignTop );
+
+ TQLabel *label = new TQLabel( i18n( "Icon cache size (KB):" ), fineTuneGrp, "iconCacheLabel" );
+ TQWhatsThis::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 );
+ TQWhatsThis::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( TQSizePolicy::Fixed, TQSizePolicy::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/src/app/Konfigurator/kgadvanced.h b/src/app/Konfigurator/kgadvanced.h
new file mode 100644
index 0000000..1066c06
--- /dev/null
+++ b/src/app/Konfigurator/kgadvanced.h
@@ -0,0 +1,45 @@
+/***************************************************************************
+ 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
+{
+ TQ_OBJECT
+
+
+public:
+ KgAdvanced( bool first, TQWidget* parent=0, const char* name=0 );
+};
+
+#endif /* __KGADVANCED_H__ */
diff --git a/src/app/Konfigurator/kgarchives.cpp b/src/app/Konfigurator/kgarchives.cpp
new file mode 100644
index 0000000..950aed1
--- /dev/null
+++ b/src/app/Konfigurator/kgarchives.cpp
@@ -0,0 +1,157 @@
+/***************************************************************************
+ 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 <tqhbox.h>
+#include <tqpushbutton.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, TQWidget* parent, const char* name ) :
+ KonfiguratorPage( first, parent, name )
+{
+ TQGridLayout *kgArchivesLayout = new TQGridLayout( parent );
+ kgArchivesLayout->setSpacing( 6 );
+
+ // -------------------------- GENERAL GROUPBOX ----------------------------------
+
+ TQGroupBox *generalGrp = createFrame( i18n( "General" ), parent, "generalGrp" );
+ TQGridLayout *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, ""},
+ {"Archives","Do Xz", _DoXz, i18n( "Xz" ), false, ""}
+ };
+
+ cbs = createCheckBoxGroup( 3, 0, packers, 12, 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" );
+
+ TQHBox *hbox = new TQHBox( generalGrp );
+ createSpacer( hbox, "spacer1" );
+ TQPushButton *btnAutoConfigure = new TQPushButton( i18n( "Auto Configure" ), hbox, "kgAutoConfigure" );
+ createSpacer( hbox, "spacer2" );
+ generalGrid->addWidget( hbox, 3, 0 );
+ connect( btnAutoConfigure, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotAutoConfigure() ) );
+
+ kgArchivesLayout->addWidget( generalGrp, 0 ,0 );
+
+ // ------------------------ FINE-TUNING GROUPBOX --------------------------------
+
+ TQGroupBox *fineTuneGrp = createFrame( i18n( "Fine-Tuning" ), parent, "fineTuneGrp" );
+ TQGridLayout *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
+
+ TQStringList 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") );
+ cbs->find( "Do Xz" )->setEnabled(PS("xz"));
+
+ 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/src/app/Konfigurator/kgarchives.h b/src/app/Konfigurator/kgarchives.h
new file mode 100644
index 0000000..600c617
--- /dev/null
+++ b/src/app/Konfigurator/kgarchives.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+ 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
+{
+ TQ_OBJECT
+
+
+public:
+ KgArchives( bool first, TQWidget* 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/src/app/Konfigurator/kgcolors.cpp b/src/app/Konfigurator/kgcolors.cpp
new file mode 100644
index 0000000..06f3905
--- /dev/null
+++ b/src/app/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 <tdemessagebox.h>
+#include <tdelocale.h>
+#include <tdefiledialog.h>
+#include <tdeglobalsettings.h>
+#include <kstandarddirs.h>
+#include <tqhbox.h>
+#include <tqheader.h>
+#include <tqtabwidget.h>
+
+KgColors::KgColors( bool first, TQWidget* parent, const char* name ) :
+ KonfiguratorPage( first, parent, name ), offset( 0 )
+{
+ TQGridLayout *kgColorsLayout = new TQGridLayout( parent );
+ kgColorsLayout->setSpacing( 6 );
+
+ // -------------------------- GENERAL GROUPBOX ----------------------------------
+
+ TQGroupBox *generalGrp = createFrame( i18n( "General" ), parent, "kgColorsGeneralGrp" );
+ TQGridLayout *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 TDE colors" ), false, "<p><img src='toolbar|kcontrol'></p>" + i18n( "<p>Use TDE's global color configuration.</p><p><i>Trinity 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>TDE 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>TDE 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" ), TQ_SIGNAL( stateChanged( int ) ), this, TQ_SLOT( slotDisable() ) );
+ connect( generals->find( "Enable Alternate Background" ), TQ_SIGNAL( stateChanged( int ) ), this, TQ_SLOT( generatePreview() ) );
+ connect( generals->find( "Show Current Item Always" ), TQ_SIGNAL( stateChanged( int ) ), this, TQ_SLOT( slotDisable() ) );
+ connect( generals->find( "Dim Inactive Colors" ), TQ_SIGNAL( stateChanged( int ) ), this, TQ_SLOT( slotDisable() ) );
+
+ kgColorsLayout->addMultiCellWidget( generalGrp, 0 ,0, 0, 2 );
+ TQHBox *hbox = new TQHBox( parent );
+
+ // -------------------------- COLORS GROUPBOX ----------------------------------
+
+ TQGroupBox *colorsFrameGrp = createFrame( i18n( "Colors" ), hbox, "kgColorsColorsGrp" );
+ TQGridLayout *colorsFrameGrid = createGridLayout( colorsFrameGrp->layout() );
+ colorsFrameGrid->setSpacing( 0 );
+ colorsFrameGrid->setMargin( 3 );
+
+ colorTabWidget = new TQTabWidget( colorsFrameGrp, "colorTabWidget" );
+
+ connect( colorTabWidget, TQ_SIGNAL( currentChanged ( TQWidget * ) ), this, TQ_SLOT( generatePreview() ) );
+
+ colorsGrp = new TQWidget( colorTabWidget, "colorTab" );
+ colorTabWidget->insertTab( colorsGrp, i18n( "Active" ) );
+
+ colorsGrid = new TQGridLayout( colorsGrp );
+ colorsGrid->setSpacing( 0 );
+ colorsGrid->setMargin( 2 );
+
+ ADDITIONAL_COLOR transparent = { i18n("Transparent"), TQt::white, "transparent" };
+
+ addColorSelector( "Foreground", i18n( "Foreground:" ), TDEGlobalSettings::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:" ), TDEGlobalSettings::baseColor() );
+ ADDITIONAL_COLOR sameAsBckgnd = { i18n("Same as background"), getColorSelector( "Background" )->getColor(), "Background" };
+ addColorSelector( "Alternate Background", i18n( "Alternate background:" ), TDEGlobalSettings::alternateBackgroundColor(),"", &sameAsBckgnd, 1 );
+ addColorSelector( "Marked Foreground", i18n( "Selected foreground:" ), TDEGlobalSettings::highlightedTextColor(), "", &transparent, 1 );
+ addColorSelector( "Marked Background", i18n( "Selected background:" ), TDEGlobalSettings::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:" ), TQt::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:" ), TQt::white, i18n( "Not used" ), &sameAsMarkedForegnd, 1);
+ addColorSelector( "Current Background", i18n( "Current background:" ), TQt::white, i18n( "Not used" ), &sameAsBckgnd, 1 );
+
+ colorsGrid->addWidget(createSpacer(colorsGrp, ""), itemList.count() - offset, 1);
+
+ connect( getColorSelector( "Foreground" ), TQ_SIGNAL( colorChanged() ), this, TQ_SLOT( slotForegroundChanged() ) );
+ connect( getColorSelector( "Background" ), TQ_SIGNAL( colorChanged() ), this, TQ_SLOT( slotBackgroundChanged() ) );
+ connect( getColorSelector( "Alternate Background" ), TQ_SIGNAL( colorChanged() ), this, TQ_SLOT( slotAltBackgroundChanged() ) );
+ connect( getColorSelector( "Marked Background" ), TQ_SIGNAL( colorChanged() ), this, TQ_SLOT( slotMarkedBackgroundChanged() ) );
+
+ inactiveColorStack = new TQWidgetStack( colorTabWidget, "colorTab2" );
+ colorTabWidget->insertTab( inactiveColorStack, i18n( "Inactive" ) );
+
+ colorsGrp = normalInactiveWidget = new TQWidget( inactiveColorStack, "colorTab2" );
+
+ colorsGrid = new TQGridLayout( 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" ), TQ_SIGNAL( colorChanged() ), this, TQ_SLOT( slotInactiveForegroundChanged() ) );
+ connect( getColorSelector( "Inactive Background" ), TQ_SIGNAL( colorChanged() ), this, TQ_SLOT( slotInactiveBackgroundChanged() ) );
+ connect( getColorSelector( "Inactive Alternate Background" ), TQ_SIGNAL( colorChanged() ), this, TQ_SLOT( slotInactiveAltBackgroundChanged() ) );
+ connect( getColorSelector( "Inactive Marked Background" ), TQ_SIGNAL( colorChanged() ), this, TQ_SLOT( slotInactiveMarkedBackgroundChanged() ) );
+
+ offset = endOfPanelColors = itemList.count();
+
+ inactiveColorStack->addWidget( normalInactiveWidget );
+
+ colorsGrp = dimmedInactiveWidget = new TQWidget( inactiveColorStack, "colorTab2dimmed" );
+
+ colorsGrid = new TQGridLayout( dimmedInactiveWidget );
+ colorsGrid->setSpacing( 0 );
+ colorsGrid->setMargin( 2 );
+
+ addColorSelector( "Dim Target Color", i18n( "Dim target color:" ), TQt::white);
+
+ int index = itemList.count() - offset;
+ labelList.append( addLabel( colorsGrid, index, 0, i18n("Dim factor:"), colorsGrp, TQString( "ColorsLabel%1" ).arg( index ).ascii() ) );
+ dimFactor = createSpinBox("Colors", "Dim Factor", 100, 0, 100, colorsGrp);
+ dimFactor->setSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Fixed );
+ connect( dimFactor, TQ_SIGNAL( valueChanged( int ) ), this, TQ_SLOT( generatePreview() ) );
+ colorsGrid->addWidget( dimFactor, index++, 1 );
+
+ colorsGrid->addWidget(createSpacer(dimmedInactiveWidget, ""), itemList.count() + 1 - offset, 1);
+
+ inactiveColorStack->addWidget( dimmedInactiveWidget );
+
+ inactiveColorStack->raiseWidget( normalInactiveWidget );
+
+ colorsGrp = new TQWidget( colorTabWidget, "colorTab3" );
+ colorTabWidget->insertTab( colorsGrp, i18n( "Synchronizer" ) );
+
+ colorsGrid = new TQGridLayout( colorsGrp );
+ colorsGrid->setSpacing( 0 );
+ colorsGrid->setMargin( 2 );
+
+ ADDITIONAL_COLOR KDEDefaultBase = { i18n("TDE default"), TDEGlobalSettings::baseColor(), "KDE default" };
+ ADDITIONAL_COLOR KDEDefaultFore = { i18n("TDE default"), TDEGlobalSettings::textColor(), "KDE default" };
+
+ offset = endOfPanelColors = itemList.count();
+
+ addColorSelector( "Synchronizer Equals Foreground", i18n( "Equals foreground:" ), TQt::black, TQString(), &KDEDefaultFore, 1 );
+ addColorSelector( "Synchronizer Equals Background", i18n( "Equals background:" ), TDEGlobalSettings::baseColor(), TQString(), &KDEDefaultBase, 1 );
+ addColorSelector( "Synchronizer Differs Foreground", i18n( "Differing foreground:" ), TQt::red, TQString(), &KDEDefaultFore, 1 );
+ addColorSelector( "Synchronizer Differs Background", i18n( "Differing background:" ), TDEGlobalSettings::baseColor(), TQString(), &KDEDefaultBase, 1 );
+ addColorSelector( "Synchronizer LeftCopy Foreground", i18n( "Copy to left foreground:" ), TQt::blue, TQString(), &KDEDefaultFore, 1 );
+ addColorSelector( "Synchronizer LeftCopy Background", i18n( "Copy to left background:" ), TDEGlobalSettings::baseColor(), TQString(), &KDEDefaultBase, 1 );
+ addColorSelector( "Synchronizer RightCopy Foreground", i18n( "Copy to right foreground:" ), TQt::darkGreen, TQString(), &KDEDefaultFore, 1 );
+ addColorSelector( "Synchronizer RightCopy Background", i18n( "Copy to right background:" ), TDEGlobalSettings::baseColor(), TQString(), &KDEDefaultBase, 1 );
+ addColorSelector( "Synchronizer Delete Foreground", i18n( "Delete foreground:" ), TQt::white, TQString(), &KDEDefaultFore, 1 );
+ addColorSelector( "Synchronizer Delete Background", i18n( "Delete background:" ), TQt::red, TQString(), &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 TQListView( 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, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotImportColors()));
+ connect(exportBtn, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotExportColors()));
+
+ slotDisable();
+}
+
+int KgColors::addColorSelector( TQString cfgName, TQString name, TQColor dflt, TQString dfltName,
+ ADDITIONAL_COLOR *addColor, int addColNum )
+{
+ int index = itemList.count() - offset;
+
+ labelList.append( addLabel( colorsGrid, index, 0, name, colorsGrp, TQString( "ColorsLabel%1" ).arg( index ).ascii() ) );
+ KonfiguratorColorChooser *chooser = createColorChooser( "Colors", cfgName, dflt, colorsGrp, false, addColor, addColNum );
+ chooser->setSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Fixed );
+
+ if( !dfltName.isEmpty() )
+ chooser->setDefaultText( dfltName );
+
+ colorsGrid->addWidget( chooser, index, 1 );
+
+ connect( chooser, TQ_SIGNAL( colorChanged() ), this, TQ_SLOT( generatePreview() ) );
+ if( !offset )
+ connect( chooser, TQ_SIGNAL( colorChanged() ), this, TQ_SLOT( slotActiveChanged() ) );
+
+ itemList.append( chooser );
+ itemNames.append( cfgName );
+
+ return index;
+}
+
+KonfiguratorColorChooser *KgColors::getColorSelector( TQString name )
+{
+ TQValueList<TQString>::iterator it;
+ int position = 0;
+
+ for( it = itemNames.begin(); it != itemNames.end(); it++, position++ )
+ if( *it == name )
+ return itemList.at( position );
+
+ return 0;
+}
+
+TQLabel *KgColors::getSelectorLabel( TQString name )
+{
+ TQValueList<TQString>::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()
+{
+ TQColor 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()
+{
+ TQColor 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()
+{
+ TQColor color = getColorSelector( "Alternate Background" )->getColor();
+ getColorSelector( "Alternate Marked Background" )->changeAdditionalColor( 0, color );
+}
+
+void KgColors::slotMarkedBackgroundChanged()
+{
+ TQColor color = getColorSelector( "Marked Background" )->getColor();
+ getColorSelector( "Alternate Marked Background" )->setDefaultColor( color );
+}
+
+void KgColors::slotInactiveForegroundChanged()
+{
+ TQColor 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()
+{
+ TQColor 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()
+{
+ TQColor color = getColorSelector( "Inactive Alternate Background" )->getColor();
+ getColorSelector( "Inactive Alternate Marked Background" )->changeAdditionalColor( 0, color );
+}
+
+void KgColors::slotInactiveMarkedBackgroundChanged()
+{
+ TQColor color = getColorSelector( "Inactive Marked Background" )->getColor();
+ getColorSelector( "Inactive Alternate Marked Background" )->changeAdditionalColor( 1, color );
+}
+
+void KgColors::setColorWithDimming(PreviewItem * item, TQColor foreground, TQColor background, bool dimmed )
+{
+ if ( dimmed && dimFactor->value() < 100)
+ {
+ int dim = dimFactor->value();
+ TQColor dimColor = getColorSelector("Dim Target Color")->getColor();
+
+ foreground = TQColor((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 = TQColor((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
+ TQValueList<TQString> names = KrColorSettings::getColorNames();
+ for ( TQStringList::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, TQColor());
+ }
+
+ 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
+ TQColorGroup 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 $TDEDIR/share/apps/krusader
+ TQString basedir = TDEGlobal::dirs()->findResourceDir("appdata", "total_commander.keymap");
+ // let the user select a file to load
+ TQString file = KFileDialog::getOpenFileName(basedir, "*.color", 0, i18n("Select a color-scheme file"));
+ if (file == TQString()) return;
+ TQFile f(file);
+ if (!f.open(IO_ReadOnly)) {
+ KMessageBox::error(this, i18n("Error: unable to read from file"), i18n("Error"));
+ return;
+ }
+ TQDataStream stream(&f);
+ // ok, import away
+ deserialize(stream);
+ generatePreview();
+}
+
+void KgColors::slotExportColors() {
+ TQString file = KFileDialog::getSaveFileName(TQString(), "*", 0, i18n("Select a color scheme file"));
+ if (file == TQString()) return;
+ TQFile 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;
+ }
+ TQDataStream stream(&f);
+ serialize(stream);
+}
+
+void KgColors::serialize(TQDataStream & 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 << TQString("") << TQString("");
+}
+
+void KgColors::deserialize(TQDataStream & stream)
+{
+ for (;;)
+ {
+ TQString 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 TQDataStream & stream, const char * name)
+{
+ stream << TQString(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 << TQString( bValue ? "true" : "false" );
+ }
+ else if( strcmp( name, "Dim Factor") == 0 )
+ stream << TQString::number(dimFactor->value());
+ else
+ {
+ KonfiguratorColorChooser *selector = getColorSelector( name );
+ stream << selector->getValue();
+ }
+}
+
+#include "kgcolors.moc"
diff --git a/src/app/Konfigurator/kgcolors.h b/src/app/Konfigurator/kgcolors.h
new file mode 100644
index 0000000..054cb47
--- /dev/null
+++ b/src/app/Konfigurator/kgcolors.h
@@ -0,0 +1,140 @@
+/***************************************************************************
+ 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 <tqptrlist.h>
+#include <tqvaluelist.h>
+#include <tqlistview.h>
+#include <tqwidgetstack.h>
+
+class KgColors : public KonfiguratorPage
+{
+ TQ_OBJECT
+
+
+public:
+ KgColors( bool first, TQWidget* 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( TQString cfgName, TQString name, TQColor dflt, TQString dfltName = TQString(),
+ ADDITIONAL_COLOR *addColor = 0, int addColNum = 0);
+ KonfiguratorColorChooser *getColorSelector( TQString name );
+ TQLabel *getSelectorLabel( TQString name );
+ void serialize(class TQDataStream &);
+ void deserialize(class TQDataStream &);
+ void serializeItem(class TQDataStream &, const char * name);
+ void setColorWithDimming(PreviewItem * item, TQColor foreground, TQColor background, bool dimmed );
+
+private:
+ TQWidget *colorsGrp;
+ TQGridLayout *colorsGrid;
+ int offset;
+ int endOfActiveColors;
+ int endOfPanelColors;
+
+ TQGroupBox *previewGrp;
+ TQGridLayout *previewGrid;
+ TQTabWidget *colorTabWidget;
+
+ TQWidgetStack *inactiveColorStack;
+ TQWidget *normalInactiveWidget;
+ TQWidget *dimmedInactiveWidget;
+ KonfiguratorSpinBox *dimFactor;
+
+ KonfiguratorCheckBoxGroup *generals;
+
+ TQPtrList<TQLabel> labelList;
+ TQPtrList<KonfiguratorColorChooser> itemList;
+ TQValueList<TQString> itemNames;
+
+ TQListView *preview;
+ KPushButton *importBtn, *exportBtn;
+
+ class PreviewItem : public TQListViewItem
+ {
+ private:
+ TQColor defaultBackground;
+ TQColor defaultForeground;
+ TQString label;
+
+ public:
+ PreviewItem( TQListView * parent, TQString name ) : TQListViewItem( parent, name )
+ {
+ defaultBackground = TQColor( 255, 255, 255 );
+ defaultForeground = TQColor( 0, 0, 0 );
+ label = name;
+ }
+
+ void setColor( TQColor foregnd, TQColor backgnd )
+ {
+ defaultForeground = foregnd;
+ defaultBackground = backgnd;
+ listView()->repaintItem( this );
+ }
+
+ TQString text()
+ {
+ return label;
+ }
+
+ void paintCell ( TQPainter * p, const TQColorGroup & cg, int column, int width, int align )
+ {
+ TQColorGroup _cg( cg );
+ _cg.setColor( TQColorGroup::Base, defaultBackground );
+ _cg.setColor( TQColorGroup::Text, defaultForeground );
+ TQListViewItem::paintCell(p, _cg, column, width, align);
+ }
+ };
+};
+#endif /* __KGCOLORS_H__ */
diff --git a/src/app/Konfigurator/kgdependencies.cpp b/src/app/Konfigurator/kgdependencies.cpp
new file mode 100644
index 0000000..b7f6f9f
--- /dev/null
+++ b/src/app/Konfigurator/kgdependencies.cpp
@@ -0,0 +1,170 @@
+/***************************************************************************
+ 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 <tqtabwidget.h>
+#include <tdelocale.h>
+#include <tqhbox.h>
+#include <tdemessagebox.h>
+
+#define PAGE_GENERAL 0
+#define PAGE_PACKERS 1
+#define PAGE_CHECKSUM 2
+
+KgDependencies::KgDependencies( bool first, TQWidget* parent, const char* name ) :
+ KonfiguratorPage( first, parent, name )
+{
+ TQGridLayout *kgDependenciesLayout = new TQGridLayout( parent );
+ kgDependenciesLayout->setSpacing( 6 );
+
+ // ---------------------------- GENERAL TAB -------------------------------------
+ tabWidget = new TQTabWidget( parent, "tabWidget" );
+
+ TQWidget *general_tab = new TQWidget( tabWidget, "tab" );
+ tabWidget->insertTab( general_tab, i18n( "General" ) );
+
+ TQGridLayout *pathsGrid = new TQGridLayout( general_tab );
+ pathsGrid->setSpacing( 6 );
+ pathsGrid->setMargin( 11 );
+ pathsGrid->setAlignment( TQt::AlignTop );
+
+ addApplication( "df", pathsGrid, 0, general_tab, PAGE_GENERAL );
+ addApplication( "eject", pathsGrid, 1, general_tab, PAGE_GENERAL );
+ addApplication( "tdesu", 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 -------------------------------------
+ TQWidget *packers_tab = new TQWidget( tabWidget, "tab_3" );
+ tabWidget->insertTab( packers_tab, i18n( "Packers" ) );
+
+ TQGridLayout *archGrid1 = new TQGridLayout( packers_tab );
+ archGrid1->setSpacing( 6 );
+ archGrid1->setMargin( 11 );
+ archGrid1->setAlignment( TQt::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 );
+ addApplication( "xz", archGrid1,14, packers_tab, PAGE_PACKERS );
+
+ // ---------------------------- CHECKSUM TAB -------------------------------------
+ TQWidget *checksum_tab = new TQWidget( tabWidget, "tab_4" );
+ tabWidget->insertTab( checksum_tab, i18n( "Checksum Utilities" ) );
+
+ TQGridLayout *archGrid2 = new TQGridLayout( checksum_tab );
+ archGrid2->setSpacing( 6 );
+ archGrid2->setMargin( 11 );
+ archGrid2->setAlignment( TQt::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( TQString name, TQGridLayout *grid, int row, TQWidget *parent, int page, TQString additionalList )
+{
+ TQString dflt = KrServices::fullPathName( name ); /* try to autodetect the full path name */
+
+ if( dflt.isEmpty() ) {
+ TQStringList list = TQStringList::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, (TQString( "label:" )+name).ascii() );
+
+ KonfiguratorURLRequester *fullPath = createURLRequester( "Dependencies", name, dflt, parent, false, page );
+ connect( fullPath->extension(), TQ_SIGNAL( applyManually( TQObject *, TQString, TQString ) ),
+ this, TQ_SLOT( slotApply( TQObject *, TQString, TQString ) ) );
+ grid->addWidget( fullPath, row, 1 );
+}
+
+void KgDependencies::slotApply( TQObject *obj, TQString cls, TQString name )
+{
+ KonfiguratorURLRequester *urlRequester = (KonfiguratorURLRequester *) obj;
+
+ krConfig->setGroup( cls );
+ krConfig->writeEntry( name, urlRequester->url() );
+
+ TQString 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/src/app/Konfigurator/kgdependencies.h b/src/app/Konfigurator/kgdependencies.h
new file mode 100644
index 0000000..9593c1e
--- /dev/null
+++ b/src/app/Konfigurator/kgdependencies.h
@@ -0,0 +1,59 @@
+/***************************************************************************
+ 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 TQTabWidget;
+
+
+class KgDependencies : public KonfiguratorPage
+{
+ TQ_OBJECT
+
+
+public:
+ KgDependencies( bool first, TQWidget* parent=0, const char* name=0 );
+
+ virtual int activeSubPage();
+
+private:
+ void addApplication( TQString name, TQGridLayout *grid, int row, TQWidget *parent, int page, TQString additionalList=TQString() );
+
+public slots:
+ void slotApply( TQObject *obj, TQString cls, TQString name );
+
+private:
+ TQTabWidget *tabWidget;
+};
+
+#endif /* __KGDEPENDENCIES_H__ */
diff --git a/src/app/Konfigurator/kggeneral.cpp b/src/app/Konfigurator/kggeneral.cpp
new file mode 100644
index 0000000..390b912
--- /dev/null
+++ b/src/app/Konfigurator/kggeneral.cpp
@@ -0,0 +1,214 @@
+/***************************************************************************
+ 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 <tqlabel.h>
+#include <tqhbox.h>
+#include <tqvbox.h>
+#include <tqfontmetrics.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <kinputdialog.h>
+#include "krresulttabledialog.h"
+#include "kggeneral.h"
+#include "../defaults.h"
+#include "../krusader.h"
+#include "../kicons.h"
+
+KgGeneral::KgGeneral( bool first, TQWidget* parent, const char* name ) :
+ KonfiguratorPage( first, parent, name )
+{
+if( first )
+ slotFindTools();
+
+ TQGridLayout *kgGeneralLayout = new TQGridLayout( parent );
+ kgGeneralLayout->setSpacing( 6 );
+
+ // -------------------------- GENERAL GROUPBOX ----------------------------------
+
+ TQGroupBox *generalGrp = createFrame( i18n( "General" ), parent, "kgGenGeneralGrp" );
+ TQGridLayout *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 );
+
+ TQFrame *line1 = createLine( generalGrp, "line1" );
+ generalGrid->addMultiCellWidget( line1, 2, 2, 0, 1 );
+
+ // editor
+ TQLabel *label1 = new TQLabel( i18n( "Editor:" ), generalGrp, "EditorLabel" );
+ generalGrid->addWidget( label1, 3, 0 );
+ KonfiguratorURLRequester *urlReq = createURLRequester( "General", "Editor", "internal editor",
+ generalGrp, false );
+ generalGrid->addWidget( urlReq, 3, 1 );
+
+ TQLabel *label2 = new TQLabel( 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 );
+
+TQFrame *line2 = createLine( generalGrp, "line2" );
+ generalGrid->addMultiCellWidget( line2, 5, 5, 0, 1 );
+
+ // viewer
+
+ TQHBox * hbox2 = new TQHBox( generalGrp );
+ TQVBox * vbox = new TQVBox( hbox2 );
+
+ new TQLabel( 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
+ TQFrame * frame21 = createLine( hbox2, "line2.1", true );
+ frame21->setMinimumWidth( 15 );
+ TQVBox * vbox2 = new TQVBox( hbox2 );
+
+ TQHBox * hbox3 = new TQHBox( vbox2 );
+ TQLabel * atomLabel = new TQLabel( i18n("Atomic extensions:"), hbox3);
+
+ int size = TQFontMetrics( atomLabel->font() ).height();
+
+ TQToolButton *addButton = new TQToolButton( hbox3, "addBtnList" );
+ TQPixmap icon = krLoader->loadIcon("add",TDEIcon::Desktop, size );
+ addButton->setFixedSize( icon.width() + 4, icon.height() + 4 );
+ addButton->setPixmap( icon );
+ connect( addButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotAddExtension() ) );
+
+ TQToolButton *removeButton = new TQToolButton( hbox3, "removeBtnList" );
+ icon = krLoader->loadIcon("remove",TDEIcon::Desktop, size );
+ removeButton->setFixedSize( icon.width() + 4, icon.height() + 4 );
+ removeButton->setPixmap( icon );
+ connect( removeButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotRemoveExtension() ) );
+
+ TQStringList defaultAtomicExtensions;
+ defaultAtomicExtensions += ".tar.gz";
+ defaultAtomicExtensions += ".tar.bz2";
+ defaultAtomicExtensions += ".moc.cpp";
+ defaultAtomicExtensions += ".tar.xz";
+
+ listBox = createListBox( "Look&Feel", "Atomic Extensions",
+ defaultAtomicExtensions, vbox2, true, false );
+
+ TQFrame *line3 = createLine( generalGrp, "line3" );
+ generalGrid->addMultiCellWidget( line3, 9, 9, 0, 1 );
+
+ // terminal
+ TQLabel *label3 = new TQLabel( 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 );
+
+ TQFrame *line31 = createLine( generalGrp, "line4" );
+ generalGrid->addMultiCellWidget( line31, 12, 12, 0, 1 );
+
+ // temp dir
+ TQHBox *hbox = new TQHBox( generalGrp, "hbox" );
+ new TQLabel( i18n( "Temp Directory:" ), hbox, "TempDirectory" );
+ KonfiguratorURLRequester *urlReq3 = createURLRequester( "General", "Temp Directory", "/tmp/krusader.tmp",
+ hbox, false );
+ urlReq3->setMode( KFile::Directory );
+ connect( urlReq3->extension(), TQ_SIGNAL( applyManually(TQObject *,TQString, TQString) ),
+ this, TQ_SLOT( applyTempDir(TQObject *,TQString, TQString) ) );
+ generalGrid->addMultiCellWidget( hbox, 13, 13, 0, 1 );
+
+ TQLabel *label4 = new TQLabel( 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(TQObject *obj,TQString cls, TQString name)
+{
+ KonfiguratorURLRequester *urlReq = (KonfiguratorURLRequester *)obj;
+ TQString value = TQDir(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;
+ TQString atomExt =
+ KInputDialog::getText( i18n( "Add new atomic extension" ), i18n( "Extension: " ), TQString(), &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()
+{
+ TQListBoxItem * item = listBox->selectedItem();
+ if( item )
+ listBox->removeItem( item->text() );
+}
+
+#include "kggeneral.moc"
diff --git a/src/app/Konfigurator/kggeneral.h b/src/app/Konfigurator/kggeneral.h
new file mode 100644
index 0000000..0a83863
--- /dev/null
+++ b/src/app/Konfigurator/kggeneral.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+ 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
+{
+ TQ_OBJECT
+
+
+public:
+ KgGeneral( bool first, TQWidget* parent=0, const char* name=0 );
+
+public slots:
+ void applyTempDir(TQObject *,TQString, TQString);
+ void slotFindTools();
+
+ void slotAddExtension();
+ void slotRemoveExtension();
+
+private:
+ KonfiguratorListBox *listBox;
+};
+
+#endif /* __KGGENERAL_H__ */
diff --git a/src/app/Konfigurator/kglookfeel.cpp b/src/app/Konfigurator/kglookfeel.cpp
new file mode 100644
index 0000000..aa852ca
--- /dev/null
+++ b/src/app/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 <tqtabwidget.h>
+#include <tdelocale.h>
+#include <tqwhatsthis.h>
+#include <tqvalidator.h>
+#include <tqlistview.h>
+#include <tdemessagebox.h>
+#include <tdefiledialog.h>
+#include <tdeglobal.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, TQWidget* parent, const char* name ) :
+ KonfiguratorPage( first, parent, name )
+{
+ TQGridLayout *kgLookAndFeelLayout = new TQGridLayout( parent );
+ kgLookAndFeelLayout->setSpacing( 6 );
+
+ tabWidget = new TQTabWidget( parent, "tabWidget" );
+
+ setupOperationTab();
+ setupPanelTab();
+ setupPanelToolbarTab();
+ setupMouseModeTab();
+
+ kgLookAndFeelLayout->addWidget( tabWidget, 0, 0 );
+}
+
+// ---------------------------------------------------------------------------------------
+// ---------------------------- OPERATION TAB -------------------------------------
+// ---------------------------------------------------------------------------------------
+void KgLookFeel::setupOperationTab() {
+ TQWidget *tab = new TQWidget( tabWidget, "tab_operation" );
+ tabWidget->insertTab( tab, i18n( "Operation" ) );
+
+ TQGridLayout *lookAndFeelLayout = new TQGridLayout( tab );
+ lookAndFeelLayout->setSpacing( 6 );
+ lookAndFeelLayout->setMargin( 11 );
+
+ // -------------- General -----------------
+ TQGroupBox *lookFeelGrp = createFrame( i18n( "Look && Feel" ), tab, "kgLookAndFeelGrp" );
+ TQGridLayout *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 -----------------
+ TQGroupBox *quicksearchGroup = createFrame( i18n( "Quicksearch" ), tab, "kgQuicksearchGrp" );
+ TQGridLayout *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" ), TQ_SIGNAL( stateChanged( int ) ), this, TQ_SLOT( slotDisable() ) );
+ slotDisable();
+
+ lookAndFeelLayout->addWidget( quicksearchGroup, 1, 0 );
+}
+
+// ----------------------------------------------------------------------------------
+// ---------------------------- PANEL TAB -------------------------------------
+// ----------------------------------------------------------------------------------
+void KgLookFeel::setupPanelTab() {
+ TQWidget* tab_panel = new TQWidget( tabWidget, "tab_panel" );
+ tabWidget->insertTab( tab_panel, i18n( "Panel" ) );
+
+ TQGridLayout *panelLayout = new TQGridLayout( tab_panel );
+ panelLayout->setSpacing( 6 );
+ panelLayout->setMargin( 11 );
+ TQGroupBox *panelGrp = createFrame( i18n( "Panel settings" ), tab_panel, "kgPanelGrp" );
+ TQGridLayout *panelGrid = createGridLayout( panelGrp->layout() );
+
+ TQHBox *hbox = new TQHBox( panelGrp, "lookAndFeelHBox1" );
+ new TQLabel( i18n( "Panel font:" ), hbox, "lookAndFeelLabel" );
+ createFontChooser( "Look&Feel", "Filelist Font", _FilelistFont, hbox, true, PAGE_PANEL );
+ createSpacer ( hbox );
+ panelGrid->addWidget( hbox, 0, 0 );
+
+ TQHBox *hbox2 = new TQHBox( panelGrp, "lookAndFeelHBox2" );
+ TQLabel *lbl1 = new TQLabel( 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 TQRegExpValidator( TQRegExp( "[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 );
+
+ TQHBox *hbox3 = new TQHBox( panelGrp, "lookAndFeelHBox3" );
+ TQLabel *lbl2 = new TQLabel( 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() {
+ TQWidget *tab_4 = new TQWidget( tabWidget, "tab_4" );
+ tabWidget->insertTab( tab_4, i18n( "Panel Toolbar" ) );
+
+ TQBoxLayout * panelToolbarVLayout = new TQVBoxLayout( 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" ), TQ_SIGNAL( stateChanged( int ) ), this, TQ_SLOT( slotEnablePanelToolbar() ) );
+
+ TQGroupBox * panelToolbarGrp = createFrame( i18n( "Visible Panel Toolbar buttons" ), tab_4, "panelToolbarGrp");
+ TQGridLayout * 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() {
+ TQWidget *tab_mouse = new TQWidget( tabWidget, "tab_mouse" );
+ tabWidget->insertTab( tab_mouse, i18n( "Selection Mode" ) );
+ TQGridLayout *mouseLayout = new TQGridLayout( tab_mouse );
+ mouseLayout->setSpacing( 6 );
+ mouseLayout->setMargin( 11 );
+
+ // -------------- General -----------------
+ TQGroupBox *mouseGeneralGroup = createFrame( i18n( "General" ), tab_mouse, "mouseGeneralGroup" );
+ TQGridLayout *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, TQ_SIGNAL( clicked(int) ), TQ_SLOT( slotSelectionModeChanged() ) );
+
+ mouseLayout->addMultiCellWidget( mouseGeneralGroup, 0,0, 0,1 );
+
+ // -------------- Details -----------------
+ TQGroupBox *mouseDetailGroup = createFrame( i18n( "Details" ), tab_mouse, "mouseDetailGroup" );
+ TQGridLayout *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 TDE's global selection policy" ), "1", i18n( "<p>Use TDE's global setting:</p><p><i>Trinity 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", "TQt Selection", _TQtSelection,
+ i18n( "Based on TDE's selection mode" ), true,
+ i18n( "If checked, use a mode based on TDE'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 -----------------
+ TQGroupBox *mousePreviewGroup = createFrame( i18n( "Preview" ), tab_mouse, "mousePreviewGroup" );
+ TQGridLayout *mousePreviewGrid = createGridLayout( mousePreviewGroup->layout() );
+ // TODO preview
+ mousePreview = new TQListView( 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( "TQt 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/src/app/Konfigurator/kglookfeel.h b/src/app/Konfigurator/kglookfeel.h
new file mode 100644
index 0000000..dea119a
--- /dev/null
+++ b/src/app/Konfigurator/kglookfeel.h
@@ -0,0 +1,70 @@
+/***************************************************************************
+ 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 TQListView;
+
+class KgLookFeel : public KonfiguratorPage
+{
+ TQ_OBJECT
+
+
+public:
+ KgLookFeel( bool first, TQWidget* parent=0, const char* name=0 );
+
+ virtual int activeSubPage();
+
+protected:
+ KonfiguratorCheckBoxGroup *cbs;
+ KonfiguratorCheckBoxGroup* quicksearchCheckboxes;
+ KonfiguratorCheckBoxGroup *pnlcbs;
+ KonfiguratorCheckBoxGroup *panelToolbarActive;
+ KonfiguratorRadioButtons *mouseRadio;
+ KonfiguratorCheckBoxGroup *mouseCheckboxes;
+ TQListView* mousePreview;
+
+protected slots:
+ void slotDisable();
+ void slotEnablePanelToolbar();
+ void slotSelectionModeChanged();
+
+private:
+ void setupOperationTab();
+ void setupPanelTab();
+ void setupPanelToolbarTab();
+ void setupMouseModeTab();
+ TQTabWidget *tabWidget;
+};
+
+#endif /* __KGLOOKFEEL_H__ */
diff --git a/src/app/Konfigurator/kgprotocols.cpp b/src/app/Konfigurator/kgprotocols.cpp
new file mode 100644
index 0000000..1dcc81f
--- /dev/null
+++ b/src/app/Konfigurator/kgprotocols.cpp
@@ -0,0 +1,419 @@
+/***************************************************************************
+ 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 <tdelocale.h>
+#include <kprotocolinfo.h>
+#include <kmimetype.h>
+#include <tqvbox.h>
+#include <tqheader.h>
+#include <kiconloader.h>
+#include <tqwhatsthis.h>
+
+TQString KgProtocols::defaultProtocols = "krarc,iso,tar";
+TQString KgProtocols::defaultIsoMimes = "application/x-iso";
+TQString 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-rpm,"
+ "application/x-xz,"
+ "application/x-zip";
+TQString KgProtocols::defaultTarMimes = "application/x-tar,application/x-tarz,"
+ "application/x-compressed-tar,"
+ "application/x-tbz,application/x-tgz,application/x-txz";
+
+KgProtocols::KgProtocols( bool first, TQWidget* parent, const char* name ) :
+ KonfiguratorPage( first, parent, name )
+{
+ TQGridLayout *KgProtocolsLayout = new TQGridLayout( parent );
+ KgProtocolsLayout->setSpacing( 6 );
+
+ // -------------------------- LINK VIEW ----------------------------------
+
+ TQGroupBox *linkGrp = createFrame( i18n( "Links" ), parent, "linkGrp" );
+ TQGridLayout *linkGrid = createGridLayout( linkGrp->layout() );
+
+ linkList = new TQListView( 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 ----------------------------------
+
+ TQVBox *vbox1 = new TQVBox( parent, "vbox1" ) ;
+
+ addSpacer( vbox1 );
+ btnAddProtocol = new TQPushButton( vbox1, "btnAddProtocolButton" );
+ btnAddProtocol->setPixmap( krLoader->loadIcon( "1leftarrow", TDEIcon::Small ) );
+ TQWhatsThis::add( btnAddProtocol, i18n( "Add protocol to the link list." ) );
+ btnRemoveProtocol = new TQPushButton( vbox1, "btnRemoveProtocolButton" );
+ btnRemoveProtocol->setPixmap( krLoader->loadIcon( "1rightarrow", TDEIcon::Small ) );
+ TQWhatsThis::add( btnRemoveProtocol, i18n( "Remove protocol from the link list." ) );
+ addSpacer( vbox1 );
+
+ KgProtocolsLayout->addWidget( vbox1, 0 ,1 );
+
+ TQVBox *vbox2 = new TQVBox( parent, "vbox2" ) ;
+
+ addSpacer( vbox2 );
+ btnAddMime = new TQPushButton( vbox2, "btnAddMimeButton" );
+ btnAddMime->setPixmap( krLoader->loadIcon( "1leftarrow", TDEIcon::Small ) );
+ TQWhatsThis::add( btnAddMime, i18n( "Add mime to the selected protocol on the link list." ) );
+ btnRemoveMime = new TQPushButton( vbox2, "btnRemoveMimeButton" );
+ btnRemoveMime->setPixmap( krLoader->loadIcon( "1rightarrow", TDEIcon::Small ) );
+ TQWhatsThis::add( btnRemoveMime, i18n( "Remove mime from the link list." ) );
+ addSpacer( vbox2 );
+
+ KgProtocolsLayout->addWidget( vbox2, 1 ,1 );
+
+ // -------------------------- PROTOCOLS LISTBOX ----------------------------------
+
+ TQGroupBox *protocolGrp = createFrame( i18n( "Protocols" ), parent, "protocolGrp" );
+ TQGridLayout *protocolGrid = createGridLayout( protocolGrp->layout() );
+
+ protocolList = new TQListBox( protocolGrp, "protocolList" );
+ loadListCapableProtocols();
+ protocolGrid->addWidget( protocolList, 0, 0 );
+
+ KgProtocolsLayout->addWidget( protocolGrp, 0 ,2 );
+
+ // -------------------------- MIMES LISTBOX ----------------------------------
+
+ TQGroupBox *mimeGrp = createFrame( i18n( "Mimes" ), parent, "mimeGrp" );
+ TQGridLayout *mimeGrid = createGridLayout( mimeGrp->layout() );
+
+ mimeList = new TQListBox( mimeGrp, "protocolList" );
+ loadMimes();
+ mimeGrid->addWidget( mimeList, 0, 0 );
+
+ KgProtocolsLayout->addWidget( mimeGrp, 1 ,2 );
+
+ // -------------------------- CONNECT TABLE ----------------------------------
+
+ connect( protocolList, TQ_SIGNAL( selectionChanged() ), this, TQ_SLOT( slotDisableButtons() ) );
+ connect( linkList, TQ_SIGNAL( selectionChanged() ), this, TQ_SLOT( slotDisableButtons() ) );
+ connect( mimeList, TQ_SIGNAL( selectionChanged() ), this, TQ_SLOT( slotDisableButtons() ) );
+ connect( linkList, TQ_SIGNAL( currentChanged( TQListViewItem *) ), this, TQ_SLOT( slotDisableButtons() ) );
+ connect( btnAddProtocol, TQ_SIGNAL( clicked() ) , this, TQ_SLOT( slotAddProtocol() ) );
+ connect( btnRemoveProtocol, TQ_SIGNAL( clicked() ) , this, TQ_SLOT( slotRemoveProtocol() ) );
+ connect( btnAddMime, TQ_SIGNAL( clicked() ) , this, TQ_SLOT( slotAddMime() ) );
+ connect( btnRemoveMime, TQ_SIGNAL( clicked() ) , this, TQ_SLOT( slotRemoveMime() ) );
+
+ loadInitialValues();
+ slotDisableButtons();
+}
+
+TQWidget* KgProtocols::addSpacer( TQWidget *parent, const char *widgetName )
+{
+ TQWidget *widget = new TQWidget( parent, widgetName );
+ TQVBoxLayout *vboxlayout = new TQVBoxLayout( widget );
+ TQSpacerItem* spacer = new TQSpacerItem( 20, 20, TQSizePolicy::Minimum, TQSizePolicy::Expanding );
+ vboxlayout->addItem( spacer );
+ return widget;
+}
+
+void KgProtocols::loadListCapableProtocols()
+{
+ TQStringList protocols = KProtocolInfo::protocols();
+ protocols.sort();
+
+ for ( TQStringList::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( TQValueListIterator<KMimeType::Ptr> it = mimes.begin(); it != mimes.end(); it++ )
+ mimeList->insertItem( (*it)->name() );
+
+ mimeList->sort();
+}
+
+void KgProtocols::slotDisableButtons()
+{
+ btnAddProtocol->setEnabled( protocolList->selectedItem() != 0 );
+ TQListViewItem *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()
+{
+ TQListBoxItem *item = protocolList->selectedItem();
+ if( item )
+ {
+ addProtocol( item->text(), true );
+ slotDisableButtons();
+ emit sigChanged();
+ }
+}
+
+void KgProtocols::addProtocol( TQString name, bool changeCurrent )
+{
+ TQListBoxItem *item = protocolList->findItem( name, ExactMatch );
+ if( item )
+ {
+ protocolList->removeItem( protocolList->index( item ) );
+ TQListViewItem *listViewItem = new TQListViewItem( linkList, name );
+ listViewItem->setPixmap( 0, krLoader->loadIcon( "application-x-executable", TDEIcon::Small ) );
+
+ if( changeCurrent )
+ linkList->setCurrentItem( listViewItem );
+ }
+}
+
+void KgProtocols::slotRemoveProtocol()
+{
+ TQListViewItem *item = linkList->currentItem();
+ if( item )
+ {
+ removeProtocol( item->text( 0 ) );
+ slotDisableButtons();
+ emit sigChanged();
+ }
+}
+
+void KgProtocols::removeProtocol( TQString name )
+{
+ TQListViewItem *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()
+{
+ TQListBoxItem *item = mimeList->selectedItem();
+ if( item && linkList->currentItem() != 0 )
+ {
+ TQListViewItem *itemToAdd = linkList->currentItem();
+ if( itemToAdd->parent() )
+ itemToAdd = itemToAdd->parent();
+
+ addMime( item->text(), itemToAdd->text( 0 ) );
+ slotDisableButtons();
+ emit sigChanged();
+ }
+}
+
+void KgProtocols::addMime( TQString name, TQString protocol )
+{
+ TQListBoxItem *item = mimeList->findItem( name, ExactMatch );
+ TQListViewItem *currentListItem = linkList->findItem( protocol, 0 );
+
+ if( item && currentListItem && currentListItem->parent() == 0 )
+ {
+ mimeList->removeItem( mimeList->index( item ) );
+ TQListViewItem *listViewItem = new TQListViewItem( currentListItem, name );
+ listViewItem->setPixmap( 0, krLoader->loadIcon( "mime", TDEIcon::Small ) );
+ currentListItem->setOpen( true );
+ }
+}
+
+void KgProtocols::slotRemoveMime()
+{
+ TQListViewItem *item = linkList->currentItem();
+ if( item )
+ {
+ removeMime( item->text( 0 ) );
+ slotDisableButtons();
+ emit sigChanged();
+ }
+}
+
+void KgProtocols::removeMime( TQString name )
+{
+ TQListViewItem *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" );
+ TQStringList protList = krConfig->readListEntry( "Handled Protocols" );
+
+ for( TQStringList::Iterator it = protList.begin(); it != protList.end(); it++ )
+ {
+ addProtocol( *it );
+
+ TQStringList mimes = krConfig->readListEntry( TQString( "Mimes For %1" ).arg( *it ) );
+
+ for( TQStringList::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" );
+ TQStringList krarcMimes = TQStringList::split( ',', defaultKrarcMimes );
+ for( TQStringList::Iterator it = krarcMimes.begin(); it != krarcMimes.end(); it++ )
+ addMime( *it, "krarc" );
+
+ addProtocol( "tar" );
+ TQStringList tarMimes = TQStringList::split( ',', defaultTarMimes );
+ for( TQStringList::Iterator it = tarMimes.begin(); it != tarMimes.end(); it++ )
+ addMime( *it, "tar" );
+
+ slotDisableButtons();
+
+ if( isChanged() )
+ emit sigChanged();
+}
+
+bool KgProtocols::isChanged()
+{
+ krConfig->setGroup( "Protocols" );
+ TQStringList protList = krConfig->readListEntry( "Handled Protocols" );
+
+ if( (int)protList.count() != linkList->childCount() )
+ return true;
+
+ TQListViewItem *item = linkList->firstChild();
+ while( item )
+ {
+ if( !protList.contains( item->text( 0 ) ) )
+ return true;
+
+ TQStringList mimes = krConfig->readListEntry( TQString( "Mimes For %1" ).arg( item->text( 0 ) ) );
+
+ if( (int)mimes.count() != item->childCount() )
+ return true;
+ TQListViewItem *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" );
+
+ TQStringList protocolList;
+
+ TQListViewItem *item = linkList->firstChild();
+ while( item )
+ {
+ protocolList.append( item->text( 0 ) );
+
+ TQStringList mimes;
+ TQListViewItem *childs = item->firstChild();
+ while( childs )
+ {
+ mimes.append( childs->text( 0 ) );
+ childs = childs->nextSibling();
+ }
+ krConfig->writeEntry( TQString( "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/src/app/Konfigurator/kgprotocols.h b/src/app/Konfigurator/kgprotocols.h
new file mode 100644
index 0000000..c1734b2
--- /dev/null
+++ b/src/app/Konfigurator/kgprotocols.h
@@ -0,0 +1,87 @@
+/***************************************************************************
+ 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 <tqlistbox.h>
+#include <tqpushbutton.h>
+#include <tqlistview.h>
+
+class KgProtocols : public KonfiguratorPage
+{
+ TQ_OBJECT
+
+
+public:
+ KgProtocols( bool first, TQWidget* 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();
+ TQWidget* addSpacer( TQWidget *parent, const char *widgetName = 0);
+
+ void addProtocol( TQString name, bool changeCurrent = false );
+ void removeProtocol( TQString name );
+ void addMime( TQString name, TQString protocol );
+ void removeMime( TQString name );
+
+ TQListView *linkList;
+
+ TQListBox *protocolList;
+ TQListBox *mimeList;
+
+ TQPushButton *btnAddProtocol;
+ TQPushButton *btnRemoveProtocol;
+ TQPushButton *btnAddMime;
+ TQPushButton *btnRemoveMime;
+
+ static TQString defaultProtocols;
+ static TQString defaultIsoMimes;
+ static TQString defaultKrarcMimes;
+ static TQString defaultTarMimes;
+};
+
+#endif /* __KgProtocols_H__ */
diff --git a/src/app/Konfigurator/kgstartup.cpp b/src/app/Konfigurator/kgstartup.cpp
new file mode 100644
index 0000000..3da548e
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <klineedit.h>
+#include <tqwhatsthis.h>
+
+KgStartup::KgStartup( bool first, TQWidget* parent, const char* name ) :
+ KonfiguratorPage( first, parent, name ), profileCombo( 0 )
+{
+ TQGridLayout *kgStartupLayout = new TQGridLayout( parent );
+ kgStartupLayout->setSpacing( 6 );
+
+ // --------------------------- PANELS GROUPBOX ----------------------------------
+
+ TQGroupBox *panelsGrp = createFrame( i18n( "General" ), parent, "panelsGrp" );
+ TQGridLayout *panelsGrid = createGridLayout( panelsGrp->layout() );
+
+ TQString 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.");
+ TQLabel *label = addLabel( panelsGrid, 0, 0, i18n( "Startup profile:" ), panelsGrp, "Startup session" );
+ TQWhatsThis::add( label, s );
+ TQWhatsThis::add( panelsGrp, s );
+
+ TQStringList 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( TQSizePolicy::Expanding, TQSizePolicy::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 ------------------------------
+
+ TQGroupBox *uiGrp = createFrame( i18n( "User Interface" ), parent, "uiGrp" );
+ TQGridLayout *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" ), TQ_SIGNAL( stateChanged( int ) ), this, TQ_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/src/app/Konfigurator/kgstartup.h b/src/app/Konfigurator/kgstartup.h
new file mode 100644
index 0000000..3376cad
--- /dev/null
+++ b/src/app/Konfigurator/kgstartup.h
@@ -0,0 +1,53 @@
+/***************************************************************************
+ 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
+{
+ TQ_OBJECT
+
+
+public:
+ KgStartup( bool first, TQWidget* parent=0, const char* name=0 );
+
+public slots:
+ void slotDisable();
+
+protected:
+ KonfiguratorRadioButtons *saveRadio;
+ KonfiguratorCheckBoxGroup *uiCbGroup;
+ KonfiguratorComboBox *profileCombo;
+};
+
+#endif /* __KGSTARTUP_H__ */
diff --git a/src/app/Konfigurator/kguseractions.cpp b/src/app/Konfigurator/kguseractions.cpp
new file mode 100644
index 0000000..ba7436f
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <kpushbutton.h>
+#include <kdebug.h>
+
+
+KgUserActions::KgUserActions( bool first, TQWidget* parent, const char* name ) :
+ KonfiguratorPage( first, parent, name )
+{
+ TQGridLayout *kgUserActionLayout = new TQGridLayout( parent, 2, 1,
+ 0 /* margin */, 6 /* spacing */, "kgUserActionLayout" );
+
+ // ============= Info Group =============
+ TQGroupBox *InfoGroup = createFrame( i18n( "Information" ), parent, "kgUserActionInfoGroup" );
+ TQGridLayout *InfoGrid = createGridLayout( InfoGroup->layout() );
+
+ // terminal for the UserActions
+ TQLabel *labelInfo = new TQLabel( 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, TQ_SIGNAL( clicked() ), TQ_SLOT( startActionMan() ) );
+ InfoGrid->addWidget( actionmanButton, 1, 0 );
+
+ kgUserActionLayout->addWidget( InfoGroup, 0 ,0 );
+
+ // ============= Terminal Group =============
+ TQGroupBox *terminalGroup = createFrame( i18n( "Terminal execution" ), parent, "kgUserActionTerminalGroup" );
+ TQGridLayout *terminalGrid = createGridLayout( terminalGroup->layout() );
+
+ // terminal for the UserActions
+ TQLabel *labelTerminal = new TQLabel( 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 =============
+ TQGroupBox *outputGroup = createFrame( i18n( "Output collection" ), parent, "kgUserActionOutputGroup" );
+ TQGridLayout *outputGrid = createGridLayout( outputGroup->layout() );
+
+ TQHBox *hbox;
+ hbox = new TQHBox( outputGroup, "HBoxNormalFont" );
+ new TQLabel( i18n( "Normal font:" ), hbox, "NormalFontLabel" );
+ createFontChooser( "UserActions", "Normal Font", _UserActions_NormalFont, hbox );
+ createSpacer ( hbox );
+ outputGrid->addWidget( hbox, 2, 0 );
+
+ hbox = new TQHBox( outputGroup, "HBoxFixedFont" );
+ new TQLabel( 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<TQWidget*>(parent()) );
+}
+
+
+#include "kguseractions.moc"
diff --git a/src/app/Konfigurator/kguseractions.h b/src/app/Konfigurator/kguseractions.h
new file mode 100644
index 0000000..12b265c
--- /dev/null
+++ b/src/app/Konfigurator/kguseractions.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ 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
+{
+ TQ_OBJECT
+
+
+public:
+ KgUserActions( bool first, TQWidget* parent=0, const char* name=0 );
+
+public slots:
+ void startActionMan();
+};
+
+#endif /* __KGUSERACTIONS_H__ */
diff --git a/src/app/Konfigurator/kgwelcome.cpp b/src/app/Konfigurator/kgwelcome.cpp
new file mode 100644
index 0000000..d8a0a62
--- /dev/null
+++ b/src/app/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, TQWidget* parent, const char* name ) :
+ KonfiguratorPage( first, parent, name )
+{
+ TQGridLayout *kgWelcomeLayout = new TQGridLayout( parent );
+ kgWelcomeLayout->setSpacing( 6 );
+
+ TQString pix=TDEGlobal::dirs()->findResource("appdata","konfig_small.jpg");
+ TQPixmap image0( pix );
+
+ TQLabel *pixmapLabel = new TQLabel( parent, "pixmapLabel" );
+ pixmapLabel->setPixmap( image0 );
+ pixmapLabel->setScaledContents( true );
+
+ kgWelcomeLayout->addWidget( pixmapLabel, 0, 0 );
+}
+
+#include "kgwelcome.moc"
diff --git a/src/app/Konfigurator/kgwelcome.h b/src/app/Konfigurator/kgwelcome.h
new file mode 100644
index 0000000..e584150
--- /dev/null
+++ b/src/app/Konfigurator/kgwelcome.h
@@ -0,0 +1,45 @@
+/***************************************************************************
+ 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
+{
+ TQ_OBJECT
+
+
+public:
+ KgWelcome( bool first, TQWidget* parent=0, const char* name=0 );
+};
+
+#endif /* __KGWELCOME_H__ */
diff --git a/src/app/Konfigurator/konfigurator.cpp b/src/app/Konfigurator/konfigurator.cpp
new file mode 100644
index 0000000..0dd09e3
--- /dev/null
+++ b/src/app/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 <tdefiledialog.h>
+#include <tqwidget.h>
+#include <tdelocale.h>
+#include <tdeglobal.h>
+#include <kstandarddirs.h>
+#include <tdemessagebox.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, TQ_SIGNAL( aboutToShowPage(TQWidget *) ), this, TQ_SLOT( slotPageSwitch() ) );
+ connect( &restoreTimer, TQ_SIGNAL(timeout()), this, TQ_SLOT(slotRestorePage()));
+
+ createLayout( startPage );
+ setMainWidget(widget);
+ exec();
+}
+
+void Konfigurator::newContent(KonfiguratorPage *page)
+{
+ kgFrames.append(page);
+ connect( page, TQ_SIGNAL( sigChanged() ), this, TQ_SLOT( slotApplyEnable() ) );
+}
+
+void Konfigurator::createLayout( int startPage )
+{
+ // startup
+ newContent(new KgStartup(firstTime, widget->addPage(i18n("Startup"),
+ i18n("Krusader's settings upon startup"),TQPixmap(krLoader->loadIcon("kfm_home",
+ TDEIcon::Desktop,32)))));
+ // look n' feel
+ newContent(new KgLookFeel(firstTime, widget->addPage(i18n("Look & Feel"),
+ i18n("Look & Feel"),TQPixmap(krLoader->loadIcon("preferences-desktop",TDEIcon::Desktop,32)))));
+ // colors
+ newContent(new KgColors(firstTime, widget->addPage(i18n("Colors"),
+ i18n("Colors"),TQPixmap(krLoader->loadIcon("colors",TDEIcon::Desktop,32)))));
+ // general
+ newContent(new KgGeneral(firstTime, widget->addPage(i18n("General"),
+ i18n("Basic Operations"),TQPixmap(krLoader->loadIcon("configure",TDEIcon::Desktop,32)))));
+ // advanced
+ newContent(new KgAdvanced(firstTime, widget->addPage(i18n("Advanced"),
+ i18n("Be sure you know what you're doing!"),
+ TQPixmap(krLoader->loadIcon("messagebox_warning",TDEIcon::Desktop,32)))));
+ // archives
+ newContent(new KgArchives(firstTime, widget->addPage(i18n("Archives"),i18n("Customize the way Krusader deals with archives"),
+ TQPixmap(krLoader->loadIcon("application-x-tarz",TDEIcon::Desktop,32)))));
+ // dependencies
+ newContent(new KgDependencies(firstTime, widget->addPage(i18n("Dependencies"),i18n("Set the full path of the external applications"),
+ TQPixmap(krLoader->loadIcon("kr_dependencies",TDEIcon::Desktop,32)))));
+ // useractions
+ newContent(new KgUserActions(firstTime, widget->addPage(i18n("User Actions"),i18n("Configure your personal actions"),
+ TQPixmap(krLoader->loadIcon("kr_useractions",TDEIcon::Desktop,32)))));
+ // protocols
+ newContent(new KgProtocols(firstTime, widget->addPage(i18n("Protocols"),
+ i18n("Link mimes to protocols"), TQPixmap(krLoader->loadIcon("about_kde",TDEIcon::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."),
+// TQString(),"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."),
+// TQString(),"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/src/app/Konfigurator/konfigurator.h b/src/app/Konfigurator/konfigurator.h
new file mode 100644
index 0000000..8fa884c
--- /dev/null
+++ b/src/app/Konfigurator/konfigurator.h
@@ -0,0 +1,82 @@
+/***************************************************************************
+ 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 <tqwidget.h>
+#include <kdialogbase.h>
+#include <kjanuswidget.h>
+#include <tqtimer.h>
+
+class TQLineEdit;
+class TQString;
+
+class Konfigurator : public KDialogBase
+{
+ TQ_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:
+ TQPtrList<KonfiguratorPage> kgFrames;
+ KJanusWidget *widget;
+ bool firstTime;
+ int lastPage;
+ bool internalCall;
+ TQTimer restoreTimer;
+ bool restartGUI;
+};
+
+#endif
+
diff --git a/src/app/Konfigurator/konfiguratoritems.cpp b/src/app/Konfigurator/konfiguratoritems.cpp
new file mode 100644
index 0000000..4bbfdb4
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <tqpainter.h>
+#include <tqpen.h>
+#include <tqcolordialog.h>
+#include <kiconloader.h>
+
+KonfiguratorExtension::KonfiguratorExtension( TQObject *obj, TQString cfgClass, TQString cfgName, bool rst, int pg) :
+ TQObject(), objectPtr( obj ), applyConnected( false ), setDefaultsConnected( false ),
+ changed( false ), restartNeeded( rst ), subpage(pg), configClass( cfgClass ), configName( cfgName )
+{
+}
+
+void KonfiguratorExtension::connectNotify( const char *signal )
+{
+ TQString signalString = TQString( signal ).replace( " ", "" );
+ TQString applyString = TQString( TQ_SIGNAL( applyManually(TQObject *,TQString, TQString) ) ).replace( " ", "" );
+ TQString defaultsString = TQString( TQ_SIGNAL( setDefaultsManually(TQObject *) ) ).replace( " ", "" );
+
+ if( signalString == applyString )
+ applyConnected = true;
+ else if ( signalString == defaultsString )
+ setDefaultsConnected = true;
+
+ TQObject::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( TQString cls, TQString name, bool dflt, TQString text,
+ TQWidget *parent, const char *widgetName, bool rst, int pg ) : TQCheckBox( text, parent, widgetName ),
+ defaultValue( dflt )
+{
+ ext = new KonfiguratorExtension( this, cls, name, rst, pg );
+ connect( ext, TQ_SIGNAL( applyAuto(TQObject *,TQString, TQString) ), this, TQ_SLOT( slotApply(TQObject *,TQString, TQString) ) );
+ connect( ext, TQ_SIGNAL( setDefaultsAuto(TQObject *) ), this, TQ_SLOT( slotSetDefaults(TQObject *) ) );
+ connect( ext, TQ_SIGNAL( setInitialValue(TQObject *) ), this, TQ_SLOT( loadInitialValue() ) );
+
+ connect( this, TQ_SIGNAL( stateChanged( int ) ), ext, TQ_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(TQObject *,TQString cls, TQString name)
+{
+ krConfig->setGroup( cls );
+ krConfig->writeEntry( name, isChecked() );
+}
+
+void KonfiguratorCheckBox::slotSetDefaults(TQObject *)
+{
+ if( isChecked() != defaultValue )
+ setChecked( defaultValue );
+}
+
+// KonfiguratorSpinBox class
+///////////////////////////////
+
+KonfiguratorSpinBox::KonfiguratorSpinBox( TQString cls, TQString name, int dflt, int min, int max,
+ TQWidget *parent, const char *widgetName, bool rst, int pg ) : TQSpinBox( parent, widgetName ),
+ defaultValue( dflt )
+{
+ ext = new KonfiguratorExtension( this, cls, name, rst, pg );
+ connect( ext, TQ_SIGNAL( applyAuto(TQObject *,TQString, TQString) ), this, TQ_SLOT( slotApply(TQObject *,TQString, TQString) ) );
+ connect( ext, TQ_SIGNAL( setDefaultsAuto(TQObject *) ), this, TQ_SLOT( slotSetDefaults(TQObject *) ) );
+ connect( ext, TQ_SIGNAL( setInitialValue(TQObject *) ), this, TQ_SLOT( loadInitialValue() ) );
+
+ connect( this, TQ_SIGNAL( valueChanged(int) ), ext, TQ_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(TQObject *,TQString cls, TQString name)
+{
+ krConfig->setGroup( cls );
+ krConfig->writeEntry( name, value() );
+}
+
+void KonfiguratorSpinBox::slotSetDefaults(TQObject *)
+{
+ 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( TQString name )
+{
+ KonfiguratorCheckBox *checkBox = checkBoxList.first();
+
+ while( checkBox )
+ {
+ if( checkBox->extension()->getCfgName() == name )
+ return checkBox;
+ checkBox = checkBoxList.next();
+ }
+
+ return 0;
+}
+
+
+// KonfiguratorRadioButtons class
+///////////////////////////////
+
+KonfiguratorRadioButtons::KonfiguratorRadioButtons( TQString cls, TQString name,
+ TQString dflt, TQWidget *parent, const char *widgetName, bool rst, int pg ) :
+ TQButtonGroup( parent, widgetName ), defaultValue( dflt )
+{
+ ext = new KonfiguratorExtension( this, cls, name, rst, pg );
+ connect( ext, TQ_SIGNAL( applyAuto(TQObject *,TQString, TQString) ), this, TQ_SLOT( slotApply(TQObject *,TQString, TQString) ) );
+ connect( ext, TQ_SIGNAL( setDefaultsAuto(TQObject *) ), this, TQ_SLOT( slotSetDefaults(TQObject *) ) );
+ connect( ext, TQ_SIGNAL( setInitialValue(TQObject *) ), this, TQ_SLOT( loadInitialValue() ) );
+}
+
+KonfiguratorRadioButtons::~KonfiguratorRadioButtons()
+{
+ delete ext;
+}
+
+void KonfiguratorRadioButtons::addRadioButton( TQRadioButton *radioWidget, TQString name, TQString value )
+{
+ radioButtons.append( radioWidget );
+ radioNames.push_back( name );
+ radioValues.push_back( value );
+
+ connect( radioWidget, TQ_SIGNAL( stateChanged(int) ), ext, TQ_SLOT( setChanged() ) );
+}
+
+TQRadioButton * KonfiguratorRadioButtons::find( int index )
+{
+ return radioButtons.at( index );
+}
+
+TQRadioButton * KonfiguratorRadioButtons::find( TQString name )
+{
+ int index = radioNames.findIndex( name );
+ if( index == -1 )
+ return 0;
+
+ return radioButtons.at( index );
+}
+
+void KonfiguratorRadioButtons::selectButton( TQString value )
+{
+ int cnt = 0;
+ TQRadioButton *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() );
+ TQString initValue = krConfig->readEntry( ext->getCfgName(), defaultValue );
+
+ selectButton( initValue );
+ ext->setChanged( false );
+}
+
+void KonfiguratorRadioButtons::slotApply(TQObject *,TQString cls, TQString name)
+{
+ TQRadioButton *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(TQObject *)
+{
+ selectButton( defaultValue );
+}
+
+// KonfiguratorEditBox class
+///////////////////////////////
+
+KonfiguratorEditBox::KonfiguratorEditBox( TQString cls, TQString name, TQString dflt,
+ TQWidget *parent, const char *widgetName, bool rst, int pg ) : TQLineEdit( parent, widgetName ),
+ defaultValue( dflt )
+{
+ ext = new KonfiguratorExtension( this, cls, name, rst, pg );
+ connect( ext, TQ_SIGNAL( applyAuto(TQObject *,TQString, TQString) ), this, TQ_SLOT( slotApply(TQObject *,TQString, TQString) ) );
+ connect( ext, TQ_SIGNAL( setDefaultsAuto(TQObject *) ), this, TQ_SLOT( slotSetDefaults(TQObject *) ) );
+ connect( ext, TQ_SIGNAL( setInitialValue(TQObject *) ), this, TQ_SLOT( loadInitialValue() ) );
+
+ connect( this, TQ_SIGNAL( textChanged(const TQString &) ), ext, TQ_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(TQObject *,TQString cls, TQString name)
+{
+ krConfig->setGroup( cls );
+ krConfig->writeEntry( name, text() );
+}
+
+void KonfiguratorEditBox::slotSetDefaults(TQObject *)
+{
+ if( text() != defaultValue )
+ setText( defaultValue );
+}
+
+
+// KonfiguratorURLRequester class
+///////////////////////////////
+
+KonfiguratorURLRequester::KonfiguratorURLRequester( TQString cls, TQString name, TQString dflt,
+ TQWidget *parent, const char *widgetName, bool rst, int pg ) : KURLRequester( parent, widgetName ),
+ defaultValue( dflt )
+{
+ ext = new KonfiguratorExtension( this, cls, name, rst, pg );
+ connect( ext, TQ_SIGNAL( applyAuto(TQObject *,TQString, TQString) ), this, TQ_SLOT( slotApply(TQObject *,TQString, TQString) ) );
+ connect( ext, TQ_SIGNAL( setDefaultsAuto(TQObject *) ), this, TQ_SLOT( slotSetDefaults(TQObject *) ) );
+ connect( ext, TQ_SIGNAL( setInitialValue(TQObject *) ), this, TQ_SLOT( loadInitialValue() ) );
+
+ connect( this, TQ_SIGNAL( textChanged(const TQString &) ), ext, TQ_SLOT( setChanged() ) );
+
+ button()->setIconSet( SmallIcon( "document-open" ) );
+ loadInitialValue();
+}
+
+KonfiguratorURLRequester::~KonfiguratorURLRequester()
+{
+ delete ext;
+}
+
+void KonfiguratorURLRequester::loadInitialValue()
+{
+ krConfig->setGroup( ext->getCfgClass() );
+ setURL( krConfig->readEntry( ext->getCfgName(), defaultValue ) );
+ ext->setChanged( false );
+}
+
+void KonfiguratorURLRequester::slotApply(TQObject *,TQString cls, TQString name)
+{
+ krConfig->setGroup( cls );
+ krConfig->writeEntry( name, url() );
+}
+
+void KonfiguratorURLRequester::slotSetDefaults(TQObject *)
+{
+ if( url() != defaultValue )
+ setURL( defaultValue );
+}
+
+// KonfiguratorFontChooser class
+///////////////////////////////
+
+KonfiguratorFontChooser::KonfiguratorFontChooser( TQString cls, TQString name, TQFont *dflt,
+ TQWidget *parent, const char *widgetName, bool rst, int pg ) : TQHBox ( parent, widgetName ),
+ defaultValue( dflt )
+{
+ ext = new KonfiguratorExtension( this, cls, name, rst, pg );
+ connect( ext, TQ_SIGNAL( applyAuto(TQObject *,TQString, TQString) ), this, TQ_SLOT( slotApply(TQObject *,TQString, TQString) ) );
+ connect( ext, TQ_SIGNAL( setDefaultsAuto(TQObject *) ), this, TQ_SLOT( slotSetDefaults(TQObject *) ) );
+ connect( ext, TQ_SIGNAL( setInitialValue(TQObject *) ), this, TQ_SLOT( loadInitialValue() ) );
+
+ pLabel = new TQLabel( this );
+ pLabel->setMinimumWidth( 150 );
+ pToolButton = new TQToolButton( this );
+
+ connect( pToolButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotBrowseFont() ) );
+
+ pToolButton->setIconSet( SmallIcon( "document-open" ) );
+
+ 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()+TQString(", %1").arg(font.pointSize()) );
+}
+
+void KonfiguratorFontChooser::slotApply(TQObject *,TQString cls, TQString name)
+{
+ krConfig->setGroup( cls );
+ krConfig->writeEntry( name, font );
+}
+
+void KonfiguratorFontChooser::slotSetDefaults(TQObject *)
+{
+ font = *defaultValue;
+ ext->setChanged();
+ setFont();
+}
+
+void KonfiguratorFontChooser::slotBrowseFont()
+{
+ int ok=TDEFontDialog::getFont( font );
+ if (ok!=1) return; // cancelled by the user
+ ext->setChanged();
+ setFont();
+}
+
+// KonfiguratorComboBox class
+///////////////////////////////
+
+KonfiguratorComboBox::KonfiguratorComboBox( TQString cls, TQString name, TQString dflt,
+ KONFIGURATOR_NAME_VALUE_PAIR *listIn, int listInLen, TQWidget *parent,
+ const char *widgetName, bool rst, bool editable, int pg ) : TQComboBox ( 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, TQ_SIGNAL( applyAuto(TQObject *,TQString, TQString) ), this, TQ_SLOT( slotApply(TQObject *,TQString, TQString) ) );
+ connect( ext, TQ_SIGNAL( setDefaultsAuto(TQObject *) ), this, TQ_SLOT( slotSetDefaults(TQObject *) ) );
+ connect( ext, TQ_SIGNAL( setInitialValue(TQObject *) ), this, TQ_SLOT( loadInitialValue() ) );
+
+// connect( this, TQ_SIGNAL( highlighted(int) ), ext, TQ_SLOT( setChanged() ) ); /* Removed because of startup combo failure */
+ connect( this, TQ_SIGNAL( activated(int) ), ext, TQ_SLOT( setChanged() ) );
+ connect( this, TQ_SIGNAL( textChanged ( const TQString & ) ), ext, TQ_SLOT( setChanged() ) );
+
+ setEditable( editable );
+ loadInitialValue();
+}
+
+KonfiguratorComboBox::~KonfiguratorComboBox()
+{
+ delete []list;
+ delete ext;
+}
+
+void KonfiguratorComboBox::loadInitialValue()
+{
+ krConfig->setGroup( ext->getCfgClass() );
+ TQString select = krConfig->readEntry( ext->getCfgName(), defaultValue );
+ selectEntry( select );
+ ext->setChanged( false );
+}
+
+void KonfiguratorComboBox::slotApply(TQObject *,TQString cls, TQString name)
+{
+ TQString text = editable() ? lineEdit()->text() : currentText();
+ TQString 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( TQString 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(TQObject *)
+{
+ selectEntry( defaultValue );
+}
+
+
+// KonfiguratorColorChooser class
+///////////////////////////////
+
+KonfiguratorColorChooser::KonfiguratorColorChooser( TQString cls, TQString name, TQColor dflt,
+ TQWidget *parent, const char *widgetName, bool rst, ADDITIONAL_COLOR *addColPtr,
+ int addColNum, int pg ) : TQComboBox ( parent, widgetName ),
+ defaultValue( dflt ), disableColorChooser( true )
+{
+ ext = new KonfiguratorExtension( this, cls, name, rst, pg );
+
+ connect( ext, TQ_SIGNAL( applyAuto(TQObject *,TQString, TQString) ), this, TQ_SLOT( slotApply(TQObject *,TQString, TQString) ) );
+ connect( ext, TQ_SIGNAL( setDefaultsAuto(TQObject *) ), this, TQ_SLOT( slotSetDefaults(TQObject *) ) );
+ connect( ext, TQ_SIGNAL( setInitialValue(TQObject *) ), this, TQ_SLOT( loadInitialValue() ) );
+
+ addColor( i18n("Custom color" ), TQColor( 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" ), TQt::red );
+ addColor( i18n("Green" ), TQt::green );
+ addColor( i18n("Blue" ), TQt::blue );
+ addColor( i18n("Cyan" ), TQt::cyan );
+ addColor( i18n("Magenta" ), TQt::magenta );
+ addColor( i18n("Yellow" ), TQt::yellow );
+ addColor( i18n("Dark Red" ), TQt::darkRed );
+ addColor( i18n("Dark Green" ), TQt::darkGreen );
+ addColor( i18n("Dark Blue" ), TQt::darkBlue );
+ addColor( i18n("Dark Cyan" ), TQt::darkCyan );
+ addColor( i18n("Dark Magenta" ), TQt::darkMagenta );
+ addColor( i18n("Dark Yellow" ), TQt::darkYellow );
+ addColor( i18n("White" ), TQt::white );
+ addColor( i18n("Light Gray" ), TQt::lightGray );
+ addColor( i18n("Gray" ), TQt::gray );
+ addColor( i18n("Dark Gray" ), TQt::darkGray );
+ addColor( i18n("Black" ), TQt::black );
+
+ connect( this, TQ_SIGNAL( activated(int) ), this, TQ_SLOT( slotCurrentChanged( int ) ) );
+
+ loadInitialValue();
+}
+
+KonfiguratorColorChooser::~KonfiguratorColorChooser()
+{
+ delete ext;
+}
+
+TQPixmap KonfiguratorColorChooser::createPixmap( TQColor color )
+{
+ TQPainter painter;
+ TQPen pen;
+ int size = TQFontMetrics(font()).height()*3/4;
+ TQRect rect( 0, 0, size, size );
+ TQPixmap pixmap( rect.width(), rect.height() );
+
+ pen.setColor( TQt::black );
+
+ painter.begin( &pixmap );
+ TQBrush brush( color );
+ painter.fillRect( rect, brush );
+ painter.setPen( pen );
+ painter.drawRect( rect );
+ painter.end();
+
+ pixmap.detach();
+ return pixmap;
+}
+
+void KonfiguratorColorChooser::addColor( TQString text, TQColor color )
+{
+ insertItem( createPixmap(color), text );
+ palette.push_back( color );
+}
+
+void KonfiguratorColorChooser::loadInitialValue()
+{
+ krConfig->setGroup( ext->getCfgClass() );
+ TQString selected = krConfig->readEntry( ext->getCfgName(), "" );
+ setValue( selected );
+ ext->setChanged( false );
+}
+
+void KonfiguratorColorChooser::setDefaultColor( TQColor dflt )
+{
+ defaultValue = dflt;
+ palette[1] = defaultValue;
+ changeItem( createPixmap( defaultValue ), text( 1 ), 1 );
+
+ if( currentItem() == 1 )
+ emit colorChanged();
+}
+
+void KonfiguratorColorChooser::changeAdditionalColor( unsigned int num, TQColor 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( TQString text )
+{
+ changeItem( createPixmap( defaultValue ), text, 1 );
+}
+
+void KonfiguratorColorChooser::slotApply(TQObject *,TQString cls, TQString name)
+{
+ krConfig->setGroup( cls );
+ krConfig->writeEntry( name, getValue() );
+}
+
+void KonfiguratorColorChooser::setValue( TQString 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 );
+ TQColor 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;
+}
+
+TQString KonfiguratorColorChooser::getValue()
+{
+ TQColor 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 TQString( "%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(TQObject *)
+{
+ ext->setChanged();
+ setCurrentItem( 1 );
+ emit colorChanged();
+}
+
+void KonfiguratorColorChooser::slotCurrentChanged( int number )
+{
+ ext->setChanged();
+ if( number == 0 && !disableColorChooser )
+ {
+ TQColor color = TQColorDialog::getColor ( customValue, this, "ColorDialog" );
+ if( color.isValid() )
+ {
+ disableColorChooser = true;
+ customValue = color;
+ palette[0] = customValue;
+ changeItem( createPixmap( customValue ), text( 0 ), 0 );
+ disableColorChooser = false;
+ }
+ }
+
+ emit colorChanged();
+}
+
+TQColor KonfiguratorColorChooser::getColor()
+{
+ return palette[ currentItem() ];
+}
+
+// KonfiguratorListBox class
+///////////////////////////////
+
+KonfiguratorListBox::KonfiguratorListBox( TQString cls, TQString name, TQStringList dflt,
+ TQWidget *parent, const char *widgetName, bool rst, int pg ) : TQListBox( parent, widgetName ),
+ defaultValue( dflt )
+{
+ ext = new KonfiguratorExtension( this, cls, name, rst, pg );
+ connect( ext, TQ_SIGNAL( applyAuto(TQObject *,TQString, TQString) ), this, TQ_SLOT( slotApply(TQObject *,TQString, TQString) ) );
+ connect( ext, TQ_SIGNAL( setDefaultsAuto(TQObject *) ), this, TQ_SLOT( slotSetDefaults(TQObject *) ) );
+ connect( ext, TQ_SIGNAL( setInitialValue(TQObject *) ), this, TQ_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(TQObject *,TQString cls, TQString name)
+{
+ krConfig->setGroup( cls );
+ krConfig->writeEntry( name, list() );
+}
+
+void KonfiguratorListBox::slotSetDefaults(TQObject *)
+{
+ if( list() != defaultValue )
+ {
+ ext->setChanged();
+ setList( defaultValue );
+ }
+}
+
+void KonfiguratorListBox::setList( TQStringList list )
+{
+ clear();
+ insertStringList( list );
+}
+
+TQStringList KonfiguratorListBox::list()
+{
+ TQStringList lst;
+
+ for( unsigned i=0; i != count(); i++ )
+ lst += text( i );
+
+ return lst;
+}
+
+void KonfiguratorListBox::addItem( const TQString & item )
+{
+ if( !list().contains( item ) )
+ {
+ insertItem( item );
+ ext->setChanged();
+ }
+}
+
+void KonfiguratorListBox::removeItem( const TQString & item )
+{
+ TQListBoxItem * listItem = findItem( item );
+ if( listItem != 0 )
+ {
+ takeItem( listItem );
+ ext->setChanged();
+ }
+}
+
+#include "konfiguratoritems.moc"
diff --git a/src/app/Konfigurator/konfiguratoritems.h b/src/app/Konfigurator/konfiguratoritems.h
new file mode 100644
index 0000000..3348a71
--- /dev/null
+++ b/src/app/Konfigurator/konfiguratoritems.h
@@ -0,0 +1,428 @@
+/***************************************************************************
+ 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 <tqobject.h>
+#include <tqstring.h>
+#include <tqcheckbox.h>
+#include <tqspinbox.h>
+#include <tqpushbutton.h>
+#include <tqradiobutton.h>
+#include <tqptrlist.h>
+#include <tqvaluelist.h>
+#include <tqvaluevector.h>
+#include <tqbuttongroup.h>
+#include <tqlineedit.h>
+#include <kurlrequester.h>
+#include <tqhbox.h>
+#include <tdefontdialog.h>
+#include <tqlabel.h>
+#include <tqfont.h>
+#include <tqtoolbutton.h>
+#include <tqcombobox.h>
+
+#define FIRST_PAGE 0
+
+class KonfiguratorExtension : public TQObject
+{
+ TQ_OBJECT
+
+
+public:
+ KonfiguratorExtension(TQObject *obj, TQString cfgClass, TQString 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 TQObject *object() {return objectPtr;}
+
+ inline TQString getCfgClass() {return configClass;}
+ inline TQString getCfgName() {return configName;}
+
+public slots:
+ void setChanged() {emit sigChanged( changed = true);}
+ void setChanged( bool chg ) {emit sigChanged( changed = chg);}
+
+signals:
+ void applyManually(TQObject *,TQString, TQString);
+ void applyAuto(TQObject *,TQString, TQString);
+ void setDefaultsManually(TQObject *);
+ void setDefaultsAuto(TQObject *);
+ void setInitialValue(TQObject *);
+ void sigChanged( bool );
+
+protected:
+ TQObject *objectPtr;
+
+ bool applyConnected;
+ bool setDefaultsConnected;
+ bool changed;
+ bool restartNeeded;
+ int subpage;
+
+ TQString configClass;
+ TQString configName;
+
+ virtual void connectNotify( const char *signal );
+};
+
+
+// KonfiguratorCheckBox class
+///////////////////////////////
+
+class KonfiguratorCheckBox : public TQCheckBox
+{
+ TQ_OBJECT
+
+
+public:
+ KonfiguratorCheckBox( TQString cls, TQString name, bool dflt, TQString text,
+ TQWidget *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(TQObject *,TQString, TQString);
+ void slotSetDefaults(TQObject *);
+
+protected:
+ bool defaultValue;
+ KonfiguratorExtension *ext;
+};
+
+// KonfiguratorSpinBox class
+///////////////////////////////
+
+class KonfiguratorSpinBox : public TQSpinBox
+{
+ TQ_OBJECT
+
+
+public:
+ KonfiguratorSpinBox( TQString cls, TQString name, int dflt, int min, int max,
+ TQWidget *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(TQObject *,TQString, TQString);
+ void slotSetDefaults(TQObject *);
+
+protected:
+ int defaultValue;
+ KonfiguratorExtension *ext;
+};
+
+// KonfiguratorCheckBoxGroup class
+///////////////////////////////
+
+class KonfiguratorCheckBoxGroup : public TQWidget
+{
+public:
+ KonfiguratorCheckBoxGroup( TQWidget * parent = 0, const char * name = 0 ) :
+ TQWidget( parent, name ) {};
+
+ void add( KonfiguratorCheckBox * );
+ KonfiguratorCheckBox * find( int index );
+ KonfiguratorCheckBox * find( TQString name );
+
+private:
+ TQPtrList<KonfiguratorCheckBox> checkBoxList;
+};
+
+// KonfiguratorRadioButtons class
+///////////////////////////////
+
+class KonfiguratorRadioButtons : public TQButtonGroup
+{
+ TQ_OBJECT
+
+
+public:
+ KonfiguratorRadioButtons( TQString cls, TQString name, TQString dflt, TQWidget *parent=0,
+ const char *widgetName=0, bool rst=false, int pg=FIRST_PAGE );
+ ~KonfiguratorRadioButtons();
+
+ inline KonfiguratorExtension *extension() {return ext;}
+
+ void addRadioButton( TQRadioButton *radioWidget, TQString name, TQString value );
+
+ void selectButton( TQString value );
+
+ TQRadioButton* find( int index );
+ TQRadioButton* find( TQString name );
+
+public slots:
+ virtual void loadInitialValue();
+ void slotApply(TQObject *,TQString, TQString);
+ void slotSetDefaults(TQObject *);
+
+protected:
+ TQPtrList<TQRadioButton> radioButtons;
+ TQValueList<TQString> radioValues;
+ TQValueList<TQString> radioNames;
+
+ TQString defaultValue;
+ TQButtonGroup *buttonGroup;
+
+ KonfiguratorExtension *ext;
+};
+
+// KonfiguratorEditBox class
+///////////////////////////////
+
+class KonfiguratorEditBox : public TQLineEdit
+{
+ TQ_OBJECT
+
+
+public:
+ KonfiguratorEditBox( TQString cls, TQString name, TQString dflt, TQWidget *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(TQObject *,TQString, TQString);
+ void slotSetDefaults(TQObject *);
+
+protected:
+ TQString defaultValue;
+ KonfiguratorExtension *ext;
+};
+
+
+// KonfiguratorURLRequester class
+///////////////////////////////
+
+class KonfiguratorURLRequester : public KURLRequester
+{
+ TQ_OBJECT
+
+
+public:
+ KonfiguratorURLRequester( TQString cls, TQString name, TQString dflt, TQWidget *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(TQObject *,TQString, TQString);
+ void slotSetDefaults(TQObject *);
+
+protected:
+ TQString defaultValue;
+ KonfiguratorExtension *ext;
+};
+
+// KonfiguratorFontChooser class
+///////////////////////////////
+
+class KonfiguratorFontChooser : public TQHBox
+{
+ TQ_OBJECT
+
+
+public:
+ KonfiguratorFontChooser( TQString cls, TQString name, TQFont *dflt, TQWidget *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(TQObject *,TQString, TQString);
+ void slotSetDefaults(TQObject *);
+ void slotBrowseFont();
+
+protected:
+ TQFont * defaultValue;
+ TQFont font;
+ KonfiguratorExtension *ext;
+
+ TQLabel * pLabel;
+ TQToolButton * pToolButton;
+
+ void setFont();
+};
+
+// KONFIGURATOR_NAME_VALUE_PAIR structure
+///////////////////////////////
+
+struct KONFIGURATOR_NAME_VALUE_PAIR
+{
+ TQString text;
+ TQString value;
+};
+
+// KONFIGURATOR_NAME_VALUE_TIP structure
+///////////////////////////////
+
+struct KONFIGURATOR_NAME_VALUE_TIP
+{
+ TQString text;
+ TQString value;
+ TQString tooltip;
+};
+
+// KonfiguratorComboBox class
+///////////////////////////////
+
+class KonfiguratorComboBox : public TQComboBox
+{
+ TQ_OBJECT
+
+
+public:
+ KonfiguratorComboBox( TQString cls, TQString name, TQString dflt,
+ KONFIGURATOR_NAME_VALUE_PAIR *listIn, int listInLen,
+ TQWidget *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(TQObject *,TQString, TQString);
+ void slotSetDefaults(TQObject *);
+
+protected:
+ TQString defaultValue;
+ KONFIGURATOR_NAME_VALUE_PAIR *list;
+ int listLen;
+ KonfiguratorExtension *ext;
+
+ void selectEntry( TQString entry );
+};
+
+
+// KonfiguratorColorChooser class
+///////////////////////////////
+
+typedef struct
+{
+ TQString name;
+ TQColor color;
+ TQString value;
+} ADDITIONAL_COLOR;
+
+class KonfiguratorColorChooser : public TQComboBox
+{
+ TQ_OBJECT
+
+
+public:
+ KonfiguratorColorChooser( TQString cls, TQString name, TQColor dflt,
+ TQWidget *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( TQColor dflt );
+ void setDefaultText( TQString text );
+ TQColor getColor();
+ void changeAdditionalColor( unsigned int num, TQColor color );
+ TQString getValue();
+ bool isValueRGB();
+ void setValue( TQString value );
+
+public slots:
+ virtual void loadInitialValue();
+ void slotApply(TQObject *,TQString, TQString);
+ void slotSetDefaults(TQObject *);
+ void slotCurrentChanged( int number );
+
+signals:
+ void colorChanged();
+
+private:
+ void addColor( TQString text, TQColor color );
+ TQPixmap createPixmap( TQColor color );
+
+protected:
+ TQColor defaultValue;
+ TQColor customValue;
+ TQValueVector<TQColor> palette;
+ TQValueVector<ADDITIONAL_COLOR> additionalColors;
+ KonfiguratorExtension *ext;
+ bool disableColorChooser;
+};
+
+// KonfiguratorListBox class
+///////////////////////////////
+
+class KonfiguratorListBox : public TQListBox
+{
+ TQ_OBJECT
+
+
+public:
+ KonfiguratorListBox( TQString cls, TQString name, TQStringList dflt,
+ TQWidget *parent=0, const char *widgetName=0,
+ bool rst=false, int pg=FIRST_PAGE );
+ ~KonfiguratorListBox();
+
+ inline KonfiguratorExtension *extension() {return ext;}
+
+ void addItem( const TQString & );
+ void removeItem( const TQString & );
+
+public slots:
+ virtual void loadInitialValue();
+ void slotApply(TQObject *,TQString, TQString);
+ void slotSetDefaults(TQObject *);
+
+protected:
+ TQStringList list();
+ void setList( TQStringList );
+
+ TQStringList defaultValue;
+ KonfiguratorExtension *ext;
+};
+
+#endif /* __KONFIGURATOR_ITEMS_H__ */
+
diff --git a/src/app/Konfigurator/konfiguratorpage.cpp b/src/app/Konfigurator/konfiguratorpage.cpp
new file mode 100644
index 0000000..2f33029
--- /dev/null
+++ b/src/app/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 <tqlayout.h>
+#include "../krusader.h"
+#include <tqwhatsthis.h>
+
+KonfiguratorPage::KonfiguratorPage( bool firstTime, TQWidget* parent, const char* name ) :
+ TQFrame( 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( TQString cls, TQString name,
+ bool dflt, TQString text, TQWidget *parent, bool rst, TQString toolTip, int pg )
+{
+ KonfiguratorCheckBox *checkBox = new KonfiguratorCheckBox( cls, name, dflt, text,
+ parent, TQString(cls + "/" + name).ascii(), rst, pg );
+ if( !toolTip.isEmpty() )
+ TQWhatsThis::add( checkBox, toolTip );
+
+ registerObject( checkBox->extension() );
+ return checkBox;
+}
+
+KonfiguratorSpinBox* KonfiguratorPage::createSpinBox( TQString cls, TQString name,
+ int dflt, int min, int max, TQWidget *parent, bool rst, int pg )
+{
+ KonfiguratorSpinBox *spinBox = new KonfiguratorSpinBox( cls, name, dflt, min, max,
+ parent, TQString(cls + "/" + name).ascii(), rst, pg );
+
+ registerObject( spinBox->extension() );
+ return spinBox;
+}
+
+KonfiguratorEditBox* KonfiguratorPage::createEditBox( TQString cls, TQString name,
+ TQString dflt, TQWidget *parent, bool rst, int pg )
+{
+ KonfiguratorEditBox *editBox = new KonfiguratorEditBox( cls, name, dflt, parent,
+ TQString(cls + "/" + name).ascii(), rst, pg );
+
+ registerObject( editBox->extension() );
+ return editBox;
+}
+
+KonfiguratorListBox* KonfiguratorPage::createListBox( TQString cls, TQString name,
+ TQStringList dflt, TQWidget *parent, bool rst, int pg )
+{
+ KonfiguratorListBox *listBox = new KonfiguratorListBox( cls, name, dflt, parent,
+ TQString(cls + "/" + name).ascii(), rst, pg );
+
+ registerObject( listBox->extension() );
+ return listBox;
+}
+
+KonfiguratorURLRequester* KonfiguratorPage::createURLRequester( TQString cls, TQString name,
+ TQString dflt, TQWidget *parent, bool rst, int pg )
+{
+ KonfiguratorURLRequester *urlRequester = new KonfiguratorURLRequester( cls, name, dflt,
+ parent, TQString(cls + "/" + name).ascii(), rst, pg );
+
+ registerObject( urlRequester->extension() );
+ return urlRequester;
+}
+
+TQGroupBox* KonfiguratorPage::createFrame( TQString text, TQWidget *parent,
+ const char *widgetName )
+{
+ TQGroupBox *groupBox = new TQGroupBox( parent, widgetName );
+ groupBox->setFrameShape( TQGroupBox::Box );
+ groupBox->setFrameShadow( TQGroupBox::Sunken );
+ if( !text.isNull() )
+ groupBox->setTitle( text );
+ groupBox->setColumnLayout(0, TQt::Vertical );
+ groupBox->layout()->setSpacing( 0 );
+ groupBox->layout()->setMargin( 0 );
+ return groupBox;
+}
+
+TQGridLayout* KonfiguratorPage::createGridLayout( TQLayout *parent )
+{
+ TQGridLayout *gridLayout = new TQGridLayout( parent );
+ gridLayout->setAlignment( TQt::AlignTop );
+ gridLayout->setSpacing( 6 );
+ gridLayout->setMargin( 11 );
+ return gridLayout;
+}
+
+TQLabel* KonfiguratorPage::addLabel( TQGridLayout *layout, int x, int y, TQString label,
+ TQWidget *parent, const char *widgetName )
+{
+ TQLabel *lbl = new TQLabel( label, parent, widgetName );
+ layout->addWidget( lbl, x, y );
+ return lbl;
+}
+
+TQWidget* KonfiguratorPage::createSpacer( TQWidget *parent, const char *widgetName )
+{
+ TQWidget *widget = new TQWidget( parent, widgetName );
+ TQHBoxLayout *hboxlayout = new TQHBoxLayout( widget );
+ TQSpacerItem* spacer = new TQSpacerItem( 40, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum );
+ hboxlayout->addItem( spacer );
+ return widget;
+}
+
+KonfiguratorCheckBoxGroup* KonfiguratorPage::createCheckBoxGroup( int sizex, int sizey,
+ KONFIGURATOR_CHECKBOX_PARAM *params, int paramNum, TQWidget *parent,
+ const char *widgetName, int pg )
+{
+ KonfiguratorCheckBoxGroup *groupWidget = new KonfiguratorCheckBoxGroup( parent, widgetName );
+ TQGridLayout *layout = new TQGridLayout( 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( TQString cls,
+ TQString name, TQString dflt, int sizex, int sizey, KONFIGURATOR_NAME_VALUE_TIP *params,
+ int paramNum, TQWidget *parent, const char *widgetName, bool rst, int pg )
+{
+ KonfiguratorRadioButtons *radioWidget = new KonfiguratorRadioButtons( cls, name, dflt, parent, widgetName, rst, pg );
+ radioWidget->setFrameShape( TQButtonGroup::NoFrame );
+ radioWidget->setFrameShadow( TQButtonGroup::Sunken );
+ radioWidget->setTitle( "" );
+ radioWidget->setExclusive( true );
+ radioWidget->setRadioButtonExclusive( true );
+ radioWidget->setColumnLayout(0, TQt::Vertical );
+
+ TQGridLayout *layout = new TQGridLayout( radioWidget->layout() );
+ layout->setAlignment( TQt::AlignTop );
+ layout->setSpacing( 6 );
+ layout->setMargin( 0 );
+
+ int x = 0, y = 0;
+
+ for( int i=0; i != paramNum; i++ )
+ {
+ TQRadioButton *radBtn = new TQRadioButton( params[i].text, radioWidget,
+ TQString( cls + "/" + name + "/" + params[i].value ).ascii() );
+
+ if( !params[i].tooltip.isEmpty() )
+ TQWhatsThis::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( TQString cls, TQString name,
+ TQFont *dflt, TQWidget *parent, bool rst, int pg )
+{
+ KonfiguratorFontChooser *fontChooser = new KonfiguratorFontChooser( cls, name, dflt, parent,
+ TQString(cls + "/" + name).ascii(), rst, pg );
+
+ registerObject( fontChooser->extension() );
+ return fontChooser;
+}
+
+KonfiguratorComboBox *KonfiguratorPage::createComboBox( TQString cls, TQString name, TQString dflt,
+ KONFIGURATOR_NAME_VALUE_PAIR *params, int paramNum, TQWidget *parent, bool rst, bool editable, int pg )
+{
+ KonfiguratorComboBox *comboBox = new KonfiguratorComboBox( cls, name, dflt, params,
+ paramNum, parent, TQString(cls + "/" + name).ascii(),
+ rst, editable, pg );
+
+ registerObject( comboBox->extension() );
+ return comboBox;
+}
+
+TQFrame* KonfiguratorPage::createLine( TQWidget *parent, const char *widgetName, bool vertical )
+{
+ TQFrame *line = new TQFrame( parent, widgetName );
+ line->setFrameStyle( ( vertical ? TQFrame::VLine : TQFrame::HLine ) | TQFrame::Sunken );
+ return line;
+}
+
+void KonfiguratorPage::registerObject( KonfiguratorExtension *item )
+{
+ KonfiguratorExtension *currentItem = itemList.current();
+
+ itemList.append( item );
+ connect( item, TQ_SIGNAL( sigChanged( bool ) ), this, TQ_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( TQString cls, TQString name, TQColor dflt,
+ TQWidget *parent, bool rst,
+ ADDITIONAL_COLOR *addColPtr, int addColNum, int pg )
+{
+ KonfiguratorColorChooser *colorChooser = new KonfiguratorColorChooser( cls, name, dflt, parent,
+ TQString(cls + "/" + name).ascii(), rst, addColPtr, addColNum, pg );
+
+ registerObject( colorChooser->extension() );
+ return colorChooser;
+}
+
+#include "konfiguratorpage.moc"
diff --git a/src/app/Konfigurator/konfiguratorpage.h b/src/app/Konfigurator/konfiguratorpage.h
new file mode 100644
index 0000000..e1fcef9
--- /dev/null
+++ b/src/app/Konfigurator/konfiguratorpage.h
@@ -0,0 +1,523 @@
+/* **************************************************************************
+ 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 <tqframe.h>
+#include <tqptrlist.h>
+#include <tqgroupbox.h>
+#include <tqlabel.h>
+#include <tqlayout.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 TQFrame
+{
+ TQ_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, TQWidget* 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 TQString(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 TDEConfig (ex. "Archives")
+ * @param name The item name used in TDEConfig (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( TQString cls, TQString name, bool dflt,
+ TQString text, TQWidget *parent=0, bool rst=false,
+ TQString toolTip = TQString(), int pg=FIRST_PAGE );
+
+ /**
+ * Adds a new spinbox item to the page.
+ * <br>The spinbox widget's name is TQString(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 TDEConfig (ex. "Archives")
+ * @param name The item name used in TDEConfig (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( TQString cls, TQString name, int dflt, int min,
+ int max, TQWidget *parent = 0, bool rst = false, int pg=FIRST_PAGE );
+
+ /**
+ * Adds a new editbox item to the page.
+ * <br>The editbox widget's name is TQString(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 TDEConfig (ex. "Archives")
+ * @param name The itemname used in TDEConfig (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( TQString cls, TQString name, TQString dflt,
+ TQWidget *parent=0, bool rst=false, int pg=FIRST_PAGE );
+
+ /**
+ * Adds a new listbox item to the page.
+ * <br>The listbox widget's name is TQString(cls + "/" + name).ascii()<br>
+ *
+ * Sample:<br><br>
+ * TQStringList 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 TDEConfig (ex. "Archives")
+ * @param name The itemname used in TDEConfig (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( TQString cls, TQString name, TQStringList dflt,
+ TQWidget *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 TQString(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 TDEConfig (ex. "Archives")
+ * @param name The itemname used in TDEConfig (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( TQString cls, TQString name,
+ TQString dflt, TQWidget *parent, bool rst, int pg=FIRST_PAGE );
+
+ /**
+ * Adds a new font chooser item to the page.
+ * <br>The font chooser widget's name is TQString(cls + "/" + name).ascii()<br>
+ *
+ * Sample:<br><br>
+ * KonfiguratorFontChooser *myFontChooser = createFontChooser( "class", "name", new TQFont(), parentWidget );<br>
+ * myLayout->addWidget( myFontChooser, 0, 0 );
+ *
+ * @param cls The class name used in TDEConfig (ex. "Archives")
+ * @param name The item name used in TDEConfig (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( TQString cls, TQString name, TQFont *dflt,
+ TQWidget *parent=0, bool rst=false, int pg=FIRST_PAGE );
+
+ /**
+ * Adds a new combobox item to the page.
+ * <br>The combobox widget's name is TQString(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 TDEConfig (ex. "Archives")
+ * @param name The item name used in TDEConfig (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( TQString cls, TQString name, TQString dflt,
+ KONFIGURATOR_NAME_VALUE_PAIR *params, int paramNum,
+ TQWidget *parent=0, bool rst=false, bool editable=false, int pg=FIRST_PAGE );
+
+ /**
+ * Creates a frame on the page.
+ *
+ * Sample:<br><br>
+ * TQGroupBox *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
+ */
+ TQGroupBox *createFrame( TQString text = TQString(), TQWidget *parent=0,
+ const char *widgetName=0 );
+
+ /**
+ * Creates a new TQGridLayout element and sets its margins.
+ *
+ * Sample:<br><br>
+ * TQGroupBox *myGroup = createFrame( i18n( "MyFrameName" ), parentWidget, "frameName" );<br>
+ * TQGridLayout *myLayout = createGridLayout( myGroup->layout() );<br>
+ * myLayout->addWidget( myGroup, 0, 0 );
+ *
+ * @param parent Reference to the parent layout
+ *
+ * @return reference to the newly created TQGridLayout
+ */
+ TQGridLayout *createGridLayout( TQLayout *parent );
+
+ /**
+ * Adds a new label to a grid layout.
+ *
+ * Sample:<br><br>
+ * TQGroupBox *myGroup = createFrame( i18n( "MyFrameName" ), parentWidget, "frameName" );<br>
+ * TQGridLayout *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
+ */
+ TQLabel *addLabel( TQGridLayout *layout, int x, int y, TQString label,
+ TQWidget *parent=0, const char *widgetName=0 );
+
+ /**
+ * Creates a spacer object (for justifying in TQHBox).
+ *
+ * Sample:<br><br>
+ * TQHBox *hbox = new TQHBox( 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
+ */
+ TQWidget *createSpacer( TQWidget *parent=0, const char *widgetName=0 );
+
+ /**
+ * Creates a separator line.
+ *
+ * Sample:<br><br>
+ * TQFrame *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
+ */
+ TQFrame *createLine( TQWidget *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,
+ TQWidget *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 TDEConfig (ex. "Archives")
+ * @param name The item name used in TDEConfig (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( TQString cls, TQString name,
+ TQString dflt, int sizex, int sizey,
+ KONFIGURATOR_NAME_VALUE_TIP *params, int paramNum,
+ TQWidget *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 TQString(cls + "/" + name).ascii()<br>
+ *
+ * Sample:<br><br>
+ * KonfiguratorColorChooser *myColorChooser = createColorChooser( "class", "name", TQColor( 255, 0, 255 ), parentWidget );<br>
+ * myLayout->addWidget( myColorChooser, 0, 0 );
+ *
+ * @param cls The class name used in TDEConfig (ex. "Archives")
+ * @param name The item name used in TDEConfig (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( TQString cls, TQString name, TQColor dflt,
+ TQWidget *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:
+ TQPtrList<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 TDEConfig (ex. "Archives")
+ */
+ TQString configClass;
+ /**
+ * The item name used in TDEConfig (ex. "Do Tar")
+ */
+ TQString configName;
+ /**
+ * The default value of the checkbox
+ */
+ bool defaultValue;
+ /**
+ * The text field of the checkbox
+ */
+ TQString text;
+ /**
+ * The change of this parameter requires Krusader restart
+ */
+ bool restart;
+ /**
+ * The checkbox's tooltip
+ */
+ TQString toolTip;
+};
+
+#endif /* __KONFIGURATOR_PAGE_H__ */
diff --git a/src/app/Konfigurator/krresulttable.cpp b/src/app/Konfigurator/krresulttable.cpp
new file mode 100644
index 0000000..3aabc8f
--- /dev/null
+++ b/src/app/Konfigurator/krresulttable.cpp
@@ -0,0 +1,380 @@
+/***************************************************************************
+ 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(TQWidget* parent)
+ : TQWidget(parent),
+ _numRows(1)
+{
+}
+
+KrResultTable::~KrResultTable()
+{
+}
+
+
+TQGridLayout* KrResultTable::initTable()
+{
+ _grid = new TQGridLayout(this, _numRows, _numColumns);
+ _grid->setColStretch(_numColumns-1, 1); // stretch last column
+
+ // +++ Build and add table header +++
+ int column = 0;
+ for( TQStringList::Iterator it=_tableHeaders.begin(); it!=_tableHeaders.end(); ++it )
+ {
+ _label = new TQLabel(*it, this);
+ _label->setMargin(5);
+ _grid->addWidget(_label, 0, column);
+
+ // Set font
+ TQFont defFont = TDEGlobalSettings::generalFont();
+ defFont.setPointSize(defFont.pointSize()-1);
+ defFont.setBold(true);
+ _label->setFont(defFont);
+
+ ++column;
+ }
+
+ return _grid;
+}
+
+
+void KrResultTable::adjustRow(TQGridLayout* grid)
+{
+ TQLayoutIterator it = grid->iterator();
+ TQLayoutItem *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( TDEGlobalSettings::baseColor() );
+
+ ++it;
+ ++col;
+ }
+}
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+
+KrArchiverResultTable::KrArchiverResultTable(TQWidget* 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);
+ Archiver* xz = new Archiver("xz", "http://www.tukaani.org/xz", PS("xz"), 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);
+ addRow(xz, _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;
+ delete xz;
+}
+
+KrArchiverResultTable::~KrArchiverResultTable()
+{
+}
+
+
+bool KrArchiverResultTable::addRow(SearchObject* search, TQGridLayout* grid)
+{
+ Archiver* arch = dynamic_cast<Archiver*>(search);
+
+ // Name column
+ _label = new KURLLabel(arch->getWebsite(), arch->getSearchName(), this);
+ _label->setMargin(5);
+ _label->setAlignment(TQt::AlignTop);
+ grid->addWidget(_label, _numRows, 0);
+ connect(_label, TQ_SIGNAL(leftClickedURL(const TQString&)),
+ TQ_SLOT(website(const TQString&)));
+
+ // Found column
+ _label = new TQLabel( arch->getPath(), this );
+ _label->setMargin(5);
+ grid->addWidget(_label, _numRows, 1);
+
+ // Packing column
+ _label = new TQLabel(this);
+ _label->setMargin(5);
+ _label->setAlignment( TQt::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 TQLabel(this);
+ _label->setMargin(5);
+ _label->setAlignment( TQt::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 TQLabel(arch->getNote(), this);
+ _label->setMargin(5);
+ _label->setAlignment( TQt::AlignTop | TQt::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 TQString& url)
+{
+ (void) new KRun(url);
+}
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+
+KrToolResultTable::KrToolResultTable(TQWidget* parent)
+ : KrResultTable(parent)
+{
+ _supported = Krusader::supportedTools(); // get list of available tools
+
+ TQValueVector<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, TQGridLayout* grid)
+{
+ ApplicationGroup* appGroup = dynamic_cast<ApplicationGroup*>(search);
+ TQValueVector<Application*> _apps = appGroup->getAppVec();
+
+ // Name column
+ _label = new TQLabel(appGroup->getSearchName(), this);
+ _label->setMargin(5);
+ _label->setAlignment( TQt::AlignTop );
+ grid->addWidget(_label, _numRows, 0);
+
+ // Tool column
+ TQVBox* toolBox = new TQVBox(this);
+ for( TQValueVector<Application*>::Iterator it=_apps.begin(); it!=_apps.end(); it++ )
+ {
+ KURLLabel* l = new KURLLabel( (*it)->getWebsite(), (*it)->getAppName(), toolBox);
+ l->setAlignment(TQt::AlignLeft | TQt::AlignTop);
+ l->setMargin(5);
+ connect(l, TQ_SIGNAL(leftClickedURL(const TQString&)),
+ TQ_SLOT(website(const TQString&)));
+ }
+ grid->addWidget(toolBox, _numRows, 1);
+
+ // Found column
+ TQVBox* vbox = new TQVBox(this);
+ for( TQValueVector<Application*>::Iterator it=_apps.begin(); it!=_apps.end(); it++ )
+ {
+ _label = new TQLabel( (*it)->getPath(), vbox);
+ _label->setMargin(5);
+ _label->setAlignment( TQt::AlignTop );
+ }
+ grid->addWidget(vbox, _numRows, 2);
+
+ // Status column
+ _label = new TQLabel(this);
+ _label->setMargin(5);
+ _label->setAlignment( TQt::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 TQString& url)
+{
+ (void) new KRun(url);
+}
diff --git a/src/app/Konfigurator/krresulttable.h b/src/app/Konfigurator/krresulttable.h
new file mode 100644
index 0000000..b010a2b
--- /dev/null
+++ b/src/app/Konfigurator/krresulttable.h
@@ -0,0 +1,142 @@
+/***************************************************************************
+ 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 <tqstring.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqhbox.h>
+#include <tqvbox.h>
+#include <tqgrid.h>
+#include <tqstringlist.h>
+#include <tqvaluevector.h>
+
+#include <kiconloader.h>
+#include <tdeglobalsettings.h>
+#include <tdelocale.h>
+#include <tdelocale.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 TQWidget
+{
+public:
+ KrResultTable(TQWidget* parent);
+ virtual ~KrResultTable();
+
+ /**
+ * Adds a row of search results to the end of a TQGridLayout
+ * Each KrResultTable has to implement it
+ *
+ * @param const SearchObject* search Name of the SearchObject
+ * @param const TQGridLayout* 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, TQGridLayout* grid) = 0;
+
+protected:
+ TQStringList _supported;
+ TQStringList _tableHeaders;
+ int _numColumns;
+ int _numRows;
+
+ TQGridLayout* _grid;
+ TQHBox* _iconBox;
+ TQLabel* _label; // generic label
+
+ /**
+ * Creates the main grid layout and attaches the table header
+ *
+ * @return bool Pointer to the main grid layout
+ */
+ TQGridLayout* initTable();
+
+ /**
+ * Applies settings to each cell of the grid layout
+ * Supposed to be run after a row was added
+ *
+ * @param const TQGridLayout* grid The GridLayout
+ */
+ void adjustRow(TQGridLayout* grid);
+};
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+
+class KrArchiverResultTable : public KrResultTable
+{
+ TQ_OBJECT
+
+public:
+ KrArchiverResultTable(TQWidget* parent);
+ virtual ~KrArchiverResultTable();
+
+ bool addRow(SearchObject* search, TQGridLayout* grid);
+
+protected:
+ KURLLabel* _nameLabel;
+
+protected slots:
+ void website(const TQString&);
+};
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+
+class KrToolResultTable : public KrResultTable
+{
+ TQ_OBJECT
+
+public:
+ KrToolResultTable(TQWidget* parent);
+ virtual ~KrToolResultTable();
+
+ bool addRow(SearchObject* search, TQGridLayout* grid);
+
+protected:
+ TQValueVector<Application*> _apps;
+
+protected slots:
+ void website(const TQString&);
+};
+
+#endif
diff --git a/src/app/Konfigurator/krresulttabledialog.cpp b/src/app/Konfigurator/krresulttabledialog.cpp
new file mode 100644
index 0000000..9225875
--- /dev/null
+++ b/src/app/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( TQWidget *parent, DialogType type,
+ const TQString& caption, const TQString& heading, const TQString& headerIcon,
+ const TQString& hint)
+ : KDialogBase( parent, "KrSearchResultDialog", true, caption, KDialogBase::Help|KDialogBase::Ok,
+ KDialogBase::Ok, false )
+
+{
+ _page = new TQWidget(this);
+ setMainWidget(_page);
+ _topLayout = new TQVBoxLayout(_page, 0, spacingHint());
+ _topLayout->setAlignment( TQt::AlignTop );
+
+ // +++ Heading +++
+ // prepare the icon
+ _iconBox = new TQHBox(_page, "_iconBox");
+ _iconLabel = new TQLabel(_iconBox, "iconLabel");
+ _iconLabel->setPixmap(krLoader->loadIcon(headerIcon, TDEIcon::Desktop, 32));
+ _iconLabel->setMinimumWidth(fontMetrics().maxWidth()*20);
+ _iconLabel->setAlignment( TQt::AlignLeft | TQt::AlignVCenter );
+ _iconLabel->setFixedSize( _iconLabel->sizeHint() );
+ _headingLabel = new TQLabel(heading, _iconBox);
+ TQFont defFont = TDEGlobalSettings::generalFont();
+ defFont.setBold(true);
+ _headingLabel->setFont(defFont);
+ _headingLabel->setIndent(10);
+ _topLayout->addWidget(_iconBox);
+
+ // +++ Add some space between heading and table +++
+ TQSpacerItem* hSpacer1 = new TQSpacerItem(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(TQFrame::HLine, _page);
+ hSep->setMargin(5);
+ _topLayout->addWidget(hSep);
+
+ // +++ Hint +++
+ if(hint != TQString()) {
+ _hintLabel = new TQLabel(hint, _page);
+ _hintLabel->setIndent(5);
+ _hintLabel->setAlignment(TQt::AlignRight);
+ _topLayout->addWidget(_hintLabel);
+ }
+
+ this->setFixedSize( this->sizeHint() ); // make non-resizeable
+}
+
+KrResultTableDialog::~KrResultTableDialog()
+{
+}
diff --git a/src/app/Konfigurator/krresulttabledialog.h b/src/app/Konfigurator/krresulttabledialog.h
new file mode 100644
index 0000000..152e184
--- /dev/null
+++ b/src/app/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 <tqlabel.h>
+#include <tqvbox.h>
+#include <tqhbox.h>
+#include <tqlayout.h>
+#include <tqstringlist.h>
+#include <tqvaluevector.h>
+
+#include <kdialogbase.h>
+#include <kiconloader.h>
+#include <tdeglobalsettings.h>
+#include <tdelocale.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(TQWidget *parent, DialogType type, const TQString& caption, const TQString& heading, const TQString& headerIcon=TQString(), const TQString& hint=TQString());
+ virtual ~KrResultTableDialog();
+
+ const TQString& getHeading() const { return _heading; }
+ const TQString& getHint() const { return _hint; }
+ void setHeading(const TQString& s) { _heading = s; }
+ void setHint(const TQString& s) { _hint = s; }
+
+protected:
+ TQString _heading;
+ TQString _hint;
+
+ TQLabel* _headingLabel;
+ TQLabel* _iconLabel;
+ TQLabel* _hintLabel;
+ TQHBox* _iconBox;
+ TQWidget* _page;
+ TQVBoxLayout* _topLayout;
+ KrResultTable* _resultTable;
+};
+
+#endif
diff --git a/src/app/Konfigurator/searchobject.cpp b/src/app/Konfigurator/searchobject.cpp
new file mode 100644
index 0000000..8976cb5
--- /dev/null
+++ b/src/app/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 TQString& searchName, bool found, const TQString& note)
+ : _searchName(searchName),
+ _found(found),
+ _note(note)
+{
+}
+
+SearchObject::~SearchObject()
+{
+}
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+
+Application::Application()
+{
+}
+
+Application::Application(const TQString& searchName, bool found, const TQString& appName, const TQString& website, const TQString& note)
+ : SearchObject(searchName, found, note),
+ _appName(appName),
+ _website(website),
+ _path(KrServices::fullPathName(appName))
+{
+}
+
+Application::Application(const TQString& searchName, const TQString& website, bool found, const TQString& note)
+ : SearchObject(searchName, found, note),
+ _appName(searchName),
+ _website(website),
+ _path(KrServices::fullPathName(searchName))
+{
+}
+
+Application::~Application()
+{
+}
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+
+Archiver::Archiver()
+ : Application()
+{
+}
+
+Archiver::Archiver(const TQString& searchName, const TQString& website, bool found, bool isPacker, bool isUnpacker, const TQString& note)
+ : Application(searchName, website, found, note),
+ _isPacker(isPacker),
+ _isUnpacker(isUnpacker)
+{
+}
+
+Archiver::~Archiver()
+{
+}
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+
+ApplicationGroup::ApplicationGroup(const TQString& searchName, bool foundGroup, const TQValueVector<Application*>& apps, const TQString& note)
+ : SearchObject(searchName, foundGroup, note),
+ _apps(apps),
+ _foundGroup(foundGroup)
+{
+}
+
+ApplicationGroup::~ApplicationGroup()
+{
+}
diff --git a/src/app/Konfigurator/searchobject.h b/src/app/Konfigurator/searchobject.h
new file mode 100644
index 0000000..3f1da59
--- /dev/null
+++ b/src/app/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 <tqstring.h>
+#include <tqvaluevector.h>
+#include "../krservices.h"
+
+/**
+@author Dirk Eschler <deschler@users.sourceforge.net>
+*/
+class SearchObject
+{
+public:
+ SearchObject();
+ SearchObject(const TQString& name, bool found, const TQString& note);
+ virtual ~SearchObject();
+
+ const TQString& getSearchName() const { return _searchName; }
+ const TQString& getNote() const { return _note; }
+ const bool getFound() const { return _found; }
+ void setSearchName(const TQString& s) { _searchName = s; }
+ void setNote(const TQString& s) { _note = s; }
+ void setFound(const bool& b) { _found = b; }
+
+protected:
+ TQString _searchName;
+ bool _found;
+ TQString _note;
+};
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+
+/**
+@author Dirk Eschler <deschler@users.sourceforge.net>
+*/
+class Application : public SearchObject
+{
+public:
+ Application();
+ Application(const TQString& searchName, bool found, const TQString& appName, const TQString& website=TQString(), const TQString& note=TQString());
+ Application(const TQString& searchName, const TQString& website, bool found, const TQString& note=TQString());
+ virtual ~Application();
+
+ const TQString& getWebsite() const { return _website; }
+ const TQString& getAppName() const { return _appName; }
+ const TQString& getPath() const { return _path; }
+ void setWebsite(const TQString& s) { _website = s; }
+ void setAppName(const TQString& s) { _appName = s; }
+ void setPath(const TQString& s) { _path = s; }
+
+protected:
+ TQString _appName;
+ TQString _website;
+ TQString _path;
+};
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+
+/**
+@author Dirk Eschler <deschler@users.sourceforge.net>
+*/
+class Archiver : public Application
+{
+public:
+ Archiver();
+ Archiver(const TQString& searchName, const TQString& website, bool found, bool isPacker, bool isUnpacker, const TQString& note=TQString());
+ ~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 TQString& searchName, bool foundGroup, const TQValueVector<Application*>& apps, const TQString& note=TQString());
+ ~ApplicationGroup();
+
+ const TQValueVector<Application*>& getAppVec() const { return _apps; }
+ const bool getFoundGroup() const { return _foundGroup; }
+
+protected:
+ TQValueVector<Application*> _apps;
+ bool _foundGroup;
+};
+
+#endif
diff --git a/src/app/KrJS/Makefile.am b/src/app/KrJS/Makefile.am
new file mode 100644
index 0000000..af10182
--- /dev/null
+++ b/src/app/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/src/app/KrJS/krjs.cpp b/src/app/KrJS/krjs.cpp
new file mode 100644
index 0000000..8d1cffb
--- /dev/null
+++ b/src/app/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 <tdemessagebox.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 TQString & 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/tdebindings/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) );
+ TQString type = exception.get( exec, KJS::Identifier("name") ).toString(exec).qstring();
+ TQString 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 ?
+ TQString( i18n("In %1:\nUncaught JavaScript exception '%2'\n%3") ).arg(filename).arg(type).arg(message) :
+ TQString( 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
+ TQString(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/src/app/KrJS/krjs.h b/src/app/KrJS/krjs.h
new file mode 100644
index 0000000..256d07a
--- /dev/null
+++ b/src/app/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 TQString & filename);
+};
+
+#endif //KRJS_H
diff --git a/src/app/Locate/Makefile.am b/src/app/Locate/Makefile.am
new file mode 100644
index 0000000..5c4b95f
--- /dev/null
+++ b/src/app/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/src/app/Locate/locate.cpp b/src/app/Locate/locate.cpp
new file mode 100644
index 0000000..73db2f4
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <tqhbox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqfontmetrics.h>
+#include <tdemessagebox.h>
+#include <tdepopupmenu.h>
+#include <tqcursor.h>
+#include <tqeventloop.h>
+#include <kfinddialog.h>
+#include <kinputdialog.h>
+#include <tqregexp.h>
+#include <tqdir.h>
+#include <tqclipboard.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 TDEListView
+{
+public:
+ LocateListView( TQWidget * parent, const char * name = 0 ) : TDEListView( parent, name )
+ {
+ }
+
+ void startDrag()
+ {
+ KURL::List urls;
+
+ TQListViewItem * 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" ), TQPoint( -7, 0 ) );
+ d->dragCopy();
+ }
+};
+
+TDEProcess * 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 )
+{
+ TQWidget *widget=new TQWidget(this, "locateMainWidget");
+ TQGridLayout *grid = new TQGridLayout( widget );
+ grid->setSpacing( 6 );
+ grid->setMargin( 11 );
+
+ setPlainCaption( i18n( "Krusader::Locate" ) );
+
+ TQHBox *hbox = new TQHBox( widget, "locateHBox" );
+ TQLabel *label = new TQLabel( i18n( "Search for:" ), hbox, "locateLabel" );
+ locateSearchFor = new KHistoryCombo( false, hbox, "locateSearchFor" );
+ label->setBuddy( locateSearchFor );
+ krConfig->setGroup("Locate");
+ TQStringList list = krConfig->readListEntry("Search For");
+ locateSearchFor->setMaxCount(25); // remember 25 items
+ locateSearchFor->setHistoryItems(list);
+ locateSearchFor->setEditable( true );
+ locateSearchFor->setDuplicatesEnabled( false );
+ locateSearchFor->setSizePolicy(TQSizePolicy::Expanding,TQSizePolicy::Fixed);
+ locateSearchFor->lineEdit()->setFocus();
+
+ grid->addWidget( hbox, 0, 0 );
+
+ TQHBox *hbox2 = new TQHBox( widget, "locateHBox" );
+ TQSpacerItem* spacer = new TQSpacerItem( 40, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum );
+ hbox2->layout()->addItem( spacer );
+ dontSearchInPath = new TQCheckBox( i18n( "Don't search in path" ), hbox2, "dontSearchInPath" );
+ dontSearchInPath->setChecked( krConfig->readBoolEntry("Dont Search In Path") );
+ existingFiles = new TQCheckBox( i18n( "Show only the existing files" ), hbox2, "existingFiles" );
+ existingFiles->setChecked( krConfig->readBoolEntry("Existing Files") );
+ caseSensitive = new TQCheckBox( i18n( "Case Sensitive" ), hbox2, "caseSensitive" );
+ caseSensitive->setChecked( krConfig->readBoolEntry("Case Sensitive") );
+ grid->addWidget( hbox2, 1, 0 );
+
+ TQFrame *line1 = new TQFrame( widget, "locateLine1" );
+ line1->setFrameStyle( TQFrame::HLine | TQFrame::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(TQScrollView::Auto);
+ resultList->setHScrollBarMode(TQScrollView::Auto);
+ resultList->setShowSortIndicator(false);
+ resultList->setSorting(-1);
+ resultList->setSelectionMode( TQListView::Extended );
+
+ resultList->addColumn( i18n("Results"), TQFontMetrics(resultList->font()).width("W") * 60 );
+ resultList->setColumnWidthMode(0,TQListView::Maximum);
+
+ connect( resultList,TQ_SIGNAL(rightButtonPressed(TQListViewItem *, const TQPoint &, int)),
+ this, TQ_SLOT(slotRightClick(TQListViewItem *)));
+ connect( resultList,TQ_SIGNAL(doubleClicked(TQListViewItem *)),
+ this, TQ_SLOT(slotDoubleClick(TQListViewItem *)));
+ connect( resultList,TQ_SIGNAL(returnPressed(TQListViewItem *)),
+ this, TQ_SLOT(slotDoubleClick(TQListViewItem *)));
+
+ grid->addWidget( resultList, 3, 0 );
+
+ TQFrame *line2 = new TQFrame( widget, "locateLine2" );
+ line2->setFrameStyle( TQFrame::HLine | TQFrame::Sunken );
+ grid->addWidget( line2, 4, 0 );
+
+ enableButton( KDialogBase::User1, false ); /* disable the stop button */
+
+ if( updateProcess )
+ {
+ if( updateProcess->isRunning() )
+ {
+ connect( updateProcess, TQ_SIGNAL(processExited(TDEProcess *)), this, TQ_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 TDEProcess();
+ *updateProcess << KrServices::fullPathName( "updatedb" );
+ *updateProcess << KrServices::separateArgs( krConfig->readEntry( "UpdateDB Arguments", "" ) );
+
+ connect( updateProcess, TQ_SIGNAL(processExited(TDEProcess *)), this, TQ_SLOT(updateFinished()));
+ updateProcess->start(TDEProcess::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());
+ TQStringList 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();
+
+ tqApp->processEvents();
+
+ stopping = false;
+
+ TDEProcess locateProc;
+ connect( &locateProc, TQ_SIGNAL( receivedStdout(TDEProcess *, char *, int) ),
+ this, TQ_SLOT( processStdout(TDEProcess *, char *, int) ) );
+ connect( &locateProc, TQ_SIGNAL( receivedStderr(TDEProcess *, char *, int) ),
+ this, TQ_SLOT( processStderr(TDEProcess *, 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( TDEProcess::Block, TDEProcess::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(TDEProcess *proc, char *buffer, int length)
+{
+ char *buf = new char[ length+1 ];
+ memcpy( buf, buffer, length );
+ buf[ length ] = 0;
+
+ remaining += TQString::fromLocal8Bit( buf );
+ delete []buf;
+
+ TQStringList list = TQStringList::split("\n", remaining );
+ int items = list.size();
+
+ for ( TQStringList::Iterator it = list.begin(); it != list.end(); ++it )
+ {
+ if( --items == 0 && buffer[length-1] != '\n' )
+ remaining = *it;
+ else
+ {
+ if( dontSearchPath )
+ {
+ TQRegExp regExp( pattern, isCs, true );
+ TQString 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 TDEListViewItem( resultList, lastItem, *it );
+ else
+ lastItem = new TDEListViewItem( resultList, *it );
+
+ lastItem->setDragEnabled( true );
+ }
+ }
+
+ if( stopping )
+ proc->kill( SIGKILL );
+
+ tqApp->processEvents();
+}
+
+void LocateDlg::processStderr(TDEProcess *, char *buffer, int length)
+{
+ char *buf = new char[ length+1 ];
+ memcpy( buf, buffer, length );
+ buf[ length ] = 0;
+
+ collectedErr += TQString::fromLocal8Bit( buf );
+ delete []buf;
+}
+
+void LocateDlg::slotRightClick(TQListViewItem *item)
+{
+ if ( !item )
+ return;
+
+ // create the menu
+ TDEPopupMenu 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(TQCursor::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(TQListViewItem *item)
+{
+ if ( !item )
+ return;
+
+ TQString dirName = item->text(0);
+ TQString fileName;
+
+ if( !TQDir( dirName ).exists() )
+ {
+ fileName = dirName.mid( dirName.findRev( '/' ) + 1 );
+ dirName.truncate( dirName.findRev( '/' ) );
+ }
+
+ ACTIVE_FUNC->openUrl(vfs::fromPathOrURL( dirName ), fileName );
+ KDialogBase::accept();
+}
+
+void LocateDlg::keyPressEvent( TQKeyEvent *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;
+ }
+
+ TQDialog::keyPressEvent( e );
+}
+
+void LocateDlg::operate( TQListViewItem *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);
+ TQStringList list = krConfig->readListEntry("Find Patterns");
+
+ KFindDialog dlg( this, "locateFindDialog", options, list );
+ if ( dlg.exec() != TQDialog::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 = (TDEListViewItem *)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 = (TDEListViewItem *)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;
+
+ TQListViewItem * 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" ), TQPoint( -7, 0 ) );
+ TQApplication::clipboard()->setData( d );
+ }
+ break;
+ }
+}
+
+void LocateDlg::nextLine()
+{
+ if( findOptions & KFindDialog::FindBackwards )
+ findCurrentItem = (TDEListViewItem *)findCurrentItem->itemAbove();
+ else
+ findCurrentItem = (TDEListViewItem *)findCurrentItem->itemBelow();
+}
+
+bool LocateDlg::find()
+{
+ while( findCurrentItem )
+ {
+ TQString item = findCurrentItem->text( 0 );
+
+ if( findOptions & KFindDialog::RegularExpression )
+ {
+ if( item.contains( TQRegExp( 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 );
+ TQString queryName;
+ do {
+ queryName = i18n("Locate results")+TQString( " %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;
+ TQListViewItem * item = resultList->firstChild();
+ while( item )
+ {
+ urlList.push_back( vfs::fromPathOrURL( item->text( 0 ) ) );
+ item = item->nextSibling();
+ }
+ KURL url = KURL::fromPathOrURL(TQString("virt:/")+ queryName);
+ v.vfs_refresh( url );
+ v.vfs_addFiles( &urlList, TDEIO::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/src/app/Locate/locate.h b/src/app/Locate/locate.h
new file mode 100644
index 0000000..d4fa1be
--- /dev/null
+++ b/src/app/Locate/locate.h
@@ -0,0 +1,101 @@
+/***************************************************************************
+ 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 <tdelistview.h>
+#include <kprocess.h>
+#include <tqcheckbox.h>
+
+class LocateDlg : public KDialogBase
+{
+ TQ_OBJECT
+
+
+public:
+ LocateDlg();
+
+ static LocateDlg *LocateDialog;
+
+ virtual void slotUser1();
+ virtual void slotUser2();
+ virtual void slotUser3();
+ virtual void feedToListBox();
+
+ void reset();
+
+public slots:
+ void processStdout(TDEProcess *, char *, int);
+ void processStderr(TDEProcess *proc, char *buffer, int length);
+ void slotRightClick(TQListViewItem *);
+ void slotDoubleClick(TQListViewItem *);
+ void updateFinished();
+
+protected:
+ virtual void keyPressEvent( TQKeyEvent * );
+
+private:
+ void operate( TQListViewItem *item, int task );
+
+ bool find();
+ void nextLine();
+
+ bool stopping;
+
+ bool dontSearchPath;
+ bool onlyExist;
+ bool isCs;
+
+ bool isFeedToListBox;
+
+ TQString pattern;
+
+ KHistoryCombo *locateSearchFor;
+ TDEListView *resultList;
+ TQString remaining;
+ TDEListViewItem *lastItem;
+
+ TQString collectedErr;
+
+ long findOptions;
+ TQString findPattern;
+ TDEListViewItem *findCurrentItem;
+
+ TQCheckBox *dontSearchInPath;
+ TQCheckBox *existingFiles;
+ TQCheckBox *caseSensitive;
+
+ static TDEProcess *updateProcess;
+};
+
+#endif /* __LOCATE_H__ */
diff --git a/src/app/Makefile.am b/src/app/Makefile.am
new file mode 100644
index 0000000..75038fe
--- /dev/null
+++ b/src/app/Makefile.am
@@ -0,0 +1,195 @@
+# 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 -lkjs
+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, tqt and TDE
+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_TDEPARTS) \
+ $(LIB_TDEFILE) \
+ $(LIB_TDEHTML) \
+ $(LIB_TDEUI) \
+ $(LIB_TDECORE) \
+ $(LIB_TQT) \
+ $(LIBSOCKET) \
+ -ltdefx \
+ -ltdeutils \
+ -ltdewalletclient
+
+
+# the library search path.
+krusader_LDFLAGS = $(all_libraries) $(kde_RPATH) $(LIB_TQT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor -ltdewalletclient
+
+
+###########################################################
+###################### INSTALLING #########################
+##########################################################
+
+
+# this installs all the icons in the current dir.
+# see the comment in krusader_trinity/icons/Makefile.am for more info
+KDE_ICON = krusader krusader2 krusader_blue krusader_red krusader_root krusader_shield krusader_user
+
+# 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 TQt/TDE widget styles should go to.
+# kde_designerdir Where TQt Designer plugins should go to.
+
+
+# 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 \*.cpp`; \
+ if test -n "$$LIST"; then \
+ $(XGETTEXT) $$LIST -o $(podir)/krusader.pot; \
+ fi
diff --git a/src/app/MountMan/Makefile.am b/src/app/MountMan/Makefile.am
new file mode 100644
index 0000000..3e3f35c
--- /dev/null
+++ b/src/app/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/src/app/MountMan/kdiskfreesp.cpp b/src/app/MountMan/kdiskfreesp.cpp
new file mode 100644
index 0000000..b29304e
--- /dev/null
+++ b/src/app/MountMan/kdiskfreesp.cpp
@@ -0,0 +1,168 @@
+/*
+ * kdiskfreesp.cpp
+ *
+ * Copyright (c) 1999 Michael Kropfberger <michael.kropfberger@gmx.net>
+ *
+ * Requires the TQt 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 <tqfile.h>
+#include <tqtextstream.h>
+
+#include <kdebug.h>
+#include <kprocess.h>
+#include <tdeio/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(TQObject *parent, const char *name)
+ : TQObject(parent,name)
+{
+ dfProc = new TDEProcess(); TQ_CHECK_PTR(dfProc);
+ dfProc->setEnvironment("LANGUAGE", "C");
+ connect( dfProc, TQ_SIGNAL(receivedStdout(TDEProcess *, char *, int) ),
+ this, TQ_SLOT (receivedDFStdErrOut(TDEProcess *, char *, int)) );
+ connect(dfProc,TQ_SIGNAL(processExited(TDEProcess *) ),
+ this, TQ_SLOT(dfDone() ) );
+
+ readingDFStdErrOut=false;
+}
+
+
+/***************************************************************************
+ * destructor
+**/
+KDiskFreeSp::~KDiskFreeSp()
+{
+ delete dfProc;
+}
+
+/***************************************************************************
+ * is called, when the df-command writes on StdOut
+**/
+void KDiskFreeSp::receivedDFStdErrOut(TDEProcess *, char *data, int len)
+{
+ TQCString tmp(data,len+1); // adds a zero-byte
+ dfStringErrOut.append(tmp);
+}
+
+/***************************************************************************
+ * reads the df-commands results
+**/
+int KDiskFreeSp::readDF( const TQString & mountPoint )
+{
+ if (readingDFStdErrOut || dfProc->isRunning())
+ return -1;
+ m_mountPoint = mountPoint;
+ dfStringErrOut=""; // yet no data received
+ dfProc->clearArguments();
+ (*dfProc) << TQString::fromLocal8Bit(DF_COMMAND) << TQString::fromLocal8Bit(DF_ARGS) << mountPoint;
+ if (!dfProc->start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput ))
+ kdError() << "could not execute ["<< DF_COMMAND << "]" << endl;
+ return 1;
+}
+
+
+/***************************************************************************
+ * is called, when the df-command has finished
+**/
+void KDiskFreeSp::dfDone()
+{
+ readingDFStdErrOut=true;
+
+ TQTextStream t (dfStringErrOut, IO_ReadOnly);
+ TQString s=t.readLine();
+ if ( (s.isEmpty()) || ( s.left(10) != TQString::fromLatin1("Filesystem") ) )
+ kdError() << "Error running df command... got [" << s << "]" << endl;
+ while ( !t.eof() ) {
+ TQString u,v;
+ s=t.readLine();
+ s=s.simplifyWhiteSpace();
+ if ( !s.isEmpty() ) {
+ //kdDebug(tdefile_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(tdefile_area) << "SPECIAL GOT: [" << s << "]" << endl;
+ }//if silly linefeed
+
+ //kdDebug(tdefile_area) << "[" << s << "]" << endl;
+
+ //TQString deviceName = s.left(s.find(BLANK));
+ s=s.remove(0,s.find(BLANK)+1 );
+ //kdDebug(tdefile_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(tdefile_area) << " Size: [" << kBSize << "]" << endl;
+
+ u=s.left(s.find(BLANK));
+ unsigned long kBUsed = u.toULong();
+ s=s.remove(0,s.find(BLANK)+1 );
+ //kdDebug(tdefile_area) << " Used: [" << kBUsed << "]" << endl;
+
+ u=s.left(s.find(BLANK));
+ unsigned long kBAvail = u.toULong();
+ s=s.remove(0,s.find(BLANK)+1 );
+ //kdDebug(tdefile_area) << " Avail: [" << kBAvail << "]" << endl;
+
+
+ s=s.remove(0,s.find(BLANK)+1 ); // delete the capacity 94%
+ TQString mountPoint = s.stripWhiteSpace();
+ //kdDebug(tdefile_area) << " MountPoint: [" << mountPoint << "]" << endl;
+
+ if ( mountPoint == m_mountPoint )
+ {
+ //kdDebug(tdefile_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 TQString & path )
+{
+ KDiskFreeSp * job = new KDiskFreeSp;
+ TQString mountPoint = TDEIO::findPathMountPoint( path );
+ job->readDF( mountPoint );
+ return job;
+}
diff --git a/src/app/MountMan/kdiskfreesp.h b/src/app/MountMan/kdiskfreesp.h
new file mode 100644
index 0000000..0102c2a
--- /dev/null
+++ b/src/app/MountMan/kdiskfreesp.h
@@ -0,0 +1,89 @@
+/*
+ * kdiskfreesp.h
+ *
+ * Copyright (c) 1999 Michael Kropfberger <michael.kropfberger@gmx.net>
+ *
+ * Requires the TQt 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 <tqobject.h>
+#include <tqstring.h>
+
+class TDEProcess;
+
+/**
+ * This class parses the output of "df" to find the disk usage
+ * information for a given partition (mount point).
+ */
+class KDiskFreeSp : public TQObject
+{ TQ_OBJECT
+
+public:
+ KDiskFreeSp( TQObject *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 TQString & 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 TQString & path );
+
+signals:
+ void foundMountPoint( const TQString & 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 TQString& );
+ void done();
+
+private slots:
+ void receivedDFStdErrOut(TDEProcess *, char *data, int len);
+ void dfDone();
+
+private:
+ TDEProcess *dfProc;
+ TQCString dfStringErrOut;
+ TQString m_mountPoint;
+ bool readingDFStdErrOut;
+ class KDiskFreeSpPrivate;
+ KDiskFreeSpPrivate * d;
+};
+/***************************************************************************/
+
+
+#endif
diff --git a/src/app/MountMan/kmountman.cpp b/src/app/MountMan/kmountman.cpp
new file mode 100644
index 0000000..a9fc946
--- /dev/null
+++ b/src/app/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"
+// TDE includes
+#include <tdemessagebox.h>
+#include <kprocess.h>
+#include <tdelocale.h>
+#include <tdepopupmenu.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() : TQObject(), 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";
+ {
+ TDEConfigGroupSaver saver(krConfig, "Advanced");
+ TQStringList nonmount = TQStringList::split(",", krConfig->readEntry("Nonmount Points", _NonMountPoints));
+ nonmount_fs_mntpoint += nonmount;
+ // simplify the white space
+ for ( TQStringList::Iterator it = nonmount_fs_mntpoint.begin(); it != nonmount_fs_mntpoint.end(); ++it ) {
+ *it = (*it).simplifyWhiteSpace();
+ }
+ }
+
+}
+
+KMountMan::~KMountMan() {}
+
+bool KMountMan::invalidFilesystem(TQString type) {
+ return (invalid_fs.contains(type) > 0);
+}
+
+// this is an ugly hack, but type can actually be a mountpoint. oh well...
+bool KMountMan::nonmountFilesystem(TQString type, TQString 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, TQString 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(TDEIO::Job *job) {
+ waiting = false;
+ if ( job->error() )
+ job->showErrorDialog( 0 );
+}
+
+void KMountMan::mount( TQString 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
+ TDEIO::SimpleJob *job = TDEIO::mount(false, m->mountType().local8Bit(), m->mountedFrom(), m->mountPoint(), false);
+ new KrProgress(job);
+ connect(job, TQ_SIGNAL(result(TDEIO::Job* )), this, TQ_SLOT(jobResult(TDEIO::Job* )));
+ while (blocking && waiting) {
+ tqApp->processEvents();
+ usleep( 1000 );
+ }
+}
+
+void KMountMan::unmount( TQString mntPoint, bool blocking ) {
+ if (blocking)
+ waiting = true; // prepare to block
+ TDEIO::SimpleJob *job = TDEIO::unmount(mntPoint, false);
+ new KrProgress(job);
+ connect(job, TQ_SIGNAL(result(TDEIO::Job* )), this, TQ_SLOT(jobResult(TDEIO::Job* )));
+ while (blocking && waiting) {
+ tqApp->processEvents();
+ usleep( 1000 );
+ }
+}
+
+KMountMan::mntStatus KMountMan::getStatus( TQString 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( TQString 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( TQString path ) {
+ if ( getStatus( path ) == NOT_MOUNTED )
+ mount( path );
+}
+
+void KMountMan::eject( TQString mntPoint ) {
+ KShellProcess proc;
+ proc << KrServices::fullPathName( "eject" ) << "'" + mntPoint + "'";
+ proc.start( TDEProcess::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( TQString 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 TDEIO::convertSize, which deals
+// with large filesystems ==> >4GB, it actually recieve size in
+// a minimum block of 1024 ==> data is KB not bytes
+TQString KMountMan::convertSize( TDEIO::filesize_t size ) {
+ float fsize;
+ TQString 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( TDEGlobal::locale() ->formatNumber( fsize / ( float ) 1024, 1 ) );
+ else
+ s = i18n( "%1 TB" ).arg( TDEGlobal::locale() ->formatNumber( fsize, 1 ) );
+ }
+ // Giga-byte
+ else if ( size >= 1048576 ) {
+ fsize = ( float ) size / ( float ) 1048576;
+ s = i18n( "%1 GB" ).arg( TDEGlobal::locale() ->formatNumber( fsize, 1 ) );
+ }
+ // Mega-byte
+ else if ( size > 1024 ) {
+ fsize = ( float ) size / ( float ) 1024;
+ s = i18n( "%1 MB" ).arg( TDEGlobal::locale() ->formatNumber( fsize, 1 ) );
+ }
+ // Kilo-byte
+ else {
+ fsize = ( float ) size;
+ s = i18n( "%1 KB" ).arg( TDEGlobal::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
+ ( ( TDEToolBarPopupAction* ) 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 TQString[ 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 ] = TQString( needUmount ? "_U_" : "_M_" ) + m->mountPoint();
+ TQString text = TQString( ( needUmount ? i18n( "Unmount" ) : i18n( "Mount" ) ) ) + " " + m->mountPoint() +
+ " (" + m->mountedFrom() + ")";
+
+
+ ( ( TDEToolBarPopupAction* ) krMountMan ) ->popupMenu() ->insertItem( text, idx );
+ }
+ connect( ( ( TDEToolBarPopupAction* ) krMountMan ) ->popupMenu(), TQ_SIGNAL( activated( int ) ),
+ this, TQ_SLOT( delayedPerformAction( int ) ) );
+
+}
+
+void KMountMan::delayedPerformAction( int idx ) {
+ __delayedIdx = idx;
+ TQTimer::singleShot(0, this, TQ_SLOT(performAction(int)));
+}
+
+void KMountMan::performAction( int idx ) {
+ while ( tqApp->hasPendingEvents() )
+ tqApp->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_";
+ TQString mountPoint = _actions[ idx ].mid( 3 );
+ if ( !domount ) { // umount
+ unmount( mountPoint);
+ } else { // mount
+ mount( mountPoint);
+ }
+
+ // free memory
+ delete[] _actions;
+ _actions = 0L;
+ disconnect( ( ( TDEToolBarPopupAction* ) krMountMan ) ->popupMenu(), TQ_SIGNAL( activated( int ) ), 0, 0 );
+}
+
+#include "kmountman.moc"
diff --git a/src/app/MountMan/kmountman.h b/src/app/MountMan/kmountman.h
new file mode 100644
index 0000000..1503544
--- /dev/null
+++ b/src/app/MountMan/kmountman.h
@@ -0,0 +1,103 @@
+/***************************************************************************
+ 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
+
+// TQt includes
+#include <tqobject.h>
+#include <tqstring.h>
+
+// TDE includes
+#include <tdeversion.h>
+#include <tdeio/jobclasses.h>
+#include <tdeio/job.h>
+#include <tdeio/global.h>
+#include <kmountpoint.h>
+
+// krusader includes
+#include <stdlib.h>
+#include <math.h>
+
+class KMountManGUI;
+
+class KMountMan : public TQObject {
+ TQ_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( TQString mntPoint, bool blocking=true ); // this is probably what you need for mount
+ void unmount( TQString mntPoint, bool blocking=true ); // this is probably what you need for unmount
+ mntStatus getStatus( TQString mntPoint ); // return the status of a mntPoint (if any)
+ void autoMount( TQString path ); // just call it before refreshing into a dir
+ static void eject( TQString mntPoint );
+ bool ejectable( TQString path );
+ TQString convertSize( TDEIO::filesize_t size );
+ bool invalidFilesystem(TQString type);
+ bool nonmountFilesystem(TQString type, TQString mntPoint);
+
+ KMountMan();
+ ~KMountMan();
+
+public slots:
+ void delayedPerformAction( int idx );
+ void performAction( int idx );
+ void quickList();
+
+protected slots:
+ void jobResult(TDEIO::Job *job);
+
+protected:
+ // used internally
+ static KMountPoint *findInListByMntPoint(KMountPoint::List &lst, TQString value);
+ void toggleMount( TQString mntPoint );
+
+private:
+ TQString *_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
+ TQStringList invalid_fs;
+ TQStringList nonmount_fs;
+ // the following is the FS name
+ TQStringList nonmount_fs_mntpoint;
+};
+
+#endif
diff --git a/src/app/MountMan/kmountmangui.cpp b/src/app/MountMan/kmountmangui.cpp
new file mode 100644
index 0000000..338d2e0
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <tqpixmap.h>
+#include <tdepopupmenu.h>
+#include <tqbitmap.h>
+#include <tdemessagebox.h>
+#include <tqlayout.h>
+#include <tqgroupbox.h>
+#include <kprocess.h>
+#include <tqcursor.h>
+#include <kdebug.h>
+#include <kguiitem.h>
+#include <tqfileinfo.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 TQTimer( this );
+ connect( watcher, TQ_SIGNAL( timeout() ), this, TQ_SLOT( checkMountChange() ) );
+
+ connect( this, TQ_SIGNAL( finishedGettingSpaceData() ), this, TQ_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, TQ_SIGNAL( doubleClicked( TQListViewItem * ) ), this,
+ TQ_SLOT( doubleClicked( TQListViewItem* ) ) );
+ connect( mountList, TQ_SIGNAL( contextMenuRequested( TQListViewItem *, const TQPoint &, int ) ),
+ this, TQ_SLOT( clicked( TQListViewItem*, const TQPoint&, int ) ) );
+ connect( mountList, TQ_SIGNAL( clicked( TQListViewItem * ) ), this,
+ TQ_SLOT( changeActive( TQListViewItem * ) ) );
+ connect( mountList, TQ_SIGNAL( selectionChanged( TQListViewItem * ) ), this,
+ TQ_SLOT( changeActive( TQListViewItem * ) ) );
+
+ 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...
+ TQGridLayout *layout = new TQGridLayout( mainPage, 1, 1 );
+ mountList = new TQListView( mainPage ); // create the main container
+ krConfig->setGroup( "Look&Feel" );
+ mountList->setFont( krConfig->readFontEntry( "Filelist Font", _FilelistFont ) );
+ mountList->setAllColumnsShowFocus( true );
+ mountList->setMultiSelection( false );
+ mountList->setSelectionMode( TQListView::Single );
+ mountList->setVScrollBarMode( TQScrollView::AlwaysOn );
+ mountList->setHScrollBarMode( TQScrollView::Auto );
+ mountList->setShowSortIndicator( true );
+ int i = TQFontMetrics( mountList->font() ).width( "W" );
+ int j = TQFontMetrics( 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, TQListView::Maximum );
+ mountList->setColumnWidthMode( 1, TQListView::Maximum );
+ mountList->setColumnWidthMode( 2, TQListView::Maximum );
+ mountList->setColumnWidthMode( 3, TQListView::Maximum );
+ mountList->setColumnWidthMode( 4, TQListView::Maximum );
+ mountList->setColumnWidthMode( 5, TQListView::Maximum );
+ // now the list is created, time to fill it with data.
+ //=>krMtMan.forceUpdate();
+ TQGroupBox *box = new TQGroupBox( "MountMan.Info", mainPage );
+ box->setAlignment( TQt::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, TQ_SIGNAL( foundMountPoint( const TQString &, unsigned long, unsigned long, unsigned long ) ),
+ this, TQ_SLOT( gettingSpaceData( const TQString&, unsigned long, unsigned long, unsigned long ) ) );
+ connect( sp, TQ_SIGNAL( done() ), this, TQ_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 TQString &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( TQListView *lst, fsData &fs ) {
+ bool mtd = fs.mounted();
+
+ TQString tSize = TQString( "%1" ).arg( TDEIO::convertSizeFromKB( fs.totalBlks() ) );
+ TQString fSize = TQString( "%1" ).arg( TDEIO::convertSizeFromKB( fs.freeBlks() ) );
+ TQString sPrct = TQString( "%1%" ).arg( 100 - ( fs.usedPerct() ) );
+ TQListViewItem *item = new TQListViewItem( lst, fs.name(),
+ fs.type(), fs.mntPoint(),
+ ( mtd ? tSize : TQString( "N/A" ) ), ( mtd ? fSize : TQString( "N/A" ) ),
+ ( mtd ? sPrct : TQString( "N/A" ) ) );
+
+ TQString id = fs.name().left(7); // only works assuming devices start with "/dev/XX"
+ TQPixmap *icon = 0;
+ if ( id == "/dev/fd") {
+ icon = new TQPixmap( LOADICON( mtd ? "media-floppy-3_5-mounted" : "media-floppy-3_5-unmounted" ) );
+ } else if ( id == "/dev/cd" || fs.type() == "iso9660" ) {
+ icon = new TQPixmap( LOADICON( mtd ? "media-optical-cdrom-mounted" : "media-optical-cdrom-unmounted" ) );
+ } else if ( fs.type() == "nfs" || fs.type() == "smbfs" ) {
+ icon = new TQPixmap( LOADICON( mtd ? "nfs-mounted" : "nfs-unmounted" ) );
+ } else icon = new TQPixmap( LOADICON( mtd ? "drive-harddisk-mounted" : "drive-harddisk-unmounted" ) );
+
+ item->setPixmap( 0, *icon );
+ delete icon;
+}
+
+void KMountManGUI::updateList() {
+ mountList->clear();
+ // this handles the mounted ones
+ for ( TQValueList<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( TQListViewItem *i ) {
+ if ( !i )
+ return; // we don't want to refresh to swap, do we ?
+
+ // change the active panel to this mountpoint
+ connect( ( TQObject* ) this, TQ_SIGNAL( refreshPanel( const KURL & ) ), ( TQObject* ) SLOTS,
+ TQ_SLOT( refresh( const KURL & ) ) );
+ emit refreshPanel( vfs::fromPathOrURL( i->text(2) ) ); // text(2) ? so ugly ...
+ disconnect( this, TQ_SIGNAL( refreshPanel( const KURL & ) ), 0, 0 );
+ slotClose();
+}
+
+// when user clicks on a filesystem, change information
+void KMountManGUI::changeActive( TQListViewItem *i ) {
+ if ( !i ) return ;
+ fsData *system = 0;
+
+ for (TQValueList<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( TQListViewItem *item, const TQPoint& 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 (TQValueList<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
+ TDEPopupMenu 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 );
+ }
+
+ TQString 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());
+ }
+ TQString s = md5.hexDigest();
+ bool result = s != checksum;
+ checksum = s;
+#else
+ bool result = TQFileInfo(MTAB).lastModified() != lastMtab;
+ lastMtab = TQFileInfo(MTAB).lastModified();
+#endif
+ return result;
+}
+
+KrMountDetector krMountDetector;
+KrMountDetector * KrMountDetector::getInstance() {
+ return & krMountDetector;
+}
+
+#include "kmountmangui.moc"
diff --git a/src/app/MountMan/kmountmangui.h b/src/app/MountMan/kmountmangui.h
new file mode 100644
index 0000000..72fe8d2
--- /dev/null
+++ b/src/app/MountMan/kmountmangui.h
@@ -0,0 +1,199 @@
+/***************************************************************************
+ 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 <tqlistview.h>
+#include <kjanuswidget.h>
+#include <tqtimer.h>
+#include <kurl.h>
+#include <tqvaluelist.h>
+#include <kmountpoint.h>
+#include <tqdatetime.h>
+#include "kmountman.h"
+
+#define WATCHER_DELAY 3000
+
+class KRFSDisplay;
+class KRdirWatch;
+
+
+// forward definitions
+class fsData;
+
+class KMountManGUI : public KDialogBase {
+ TQ_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( TQListViewItem * );
+ void clicked( TQListViewItem *, const TQPoint& pos, int col );
+ void changeActive( TQListViewItem * );
+ void checkMountChange(); // check whether the mount table was changed
+
+ void updateList(); // fill-up the filesystems list
+ void getSpaceData();
+ void gettingSpaceData();
+ void gettingSpaceData(const TQString &mountPoint, unsigned long kBSize,
+ unsigned long kBUsed, unsigned long kBAvail);
+
+protected:
+ void addItemToMountList( TQListView *lst, fsData &fs );
+
+signals:
+ void refreshPanel( const KURL & );
+ void finishedGettingSpaceData();
+
+private:
+ KRFSDisplay *info;
+ TQFrame *mainPage;
+ KJanusWidget *widget;
+ TQListView *mountList;
+ TQTimer *watcher;
+ TQDateTime lastMtab;
+ // used for the getSpace - gotSpace functions
+ KMountPoint::List possible, mounted;
+ TQValueList<fsData> fileSystems;
+ TQValueList<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 TQString name() {
+ return Name;
+ }
+ inline TQString shortName() {
+ return Name.right( Name.length() - Name.find( "/", 1 ) - 1 );
+ }
+ inline TQString type() {
+ return Type;
+ }
+ inline TQString mntPoint() {
+ return MntPoint;
+ }
+ inline long totalBlks() {
+ return TotalBlks;
+ }
+ inline long freeBlks() {
+ return FreeBlks;
+ }
+ inline TDEIO::filesize_t totalBytes() {
+ return TotalBlks * 1024;
+ }
+ inline TDEIO::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( TQString n_ ) {
+ Name = n_;
+ }
+ inline void setType( TQString t_ ) {
+ Type = t_;
+ }
+ inline void setMntPoint( TQString 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:
+ TQString Name; // i.e: /dev/cdrom
+ TQString Type; // i.e: iso9600
+ TQString 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:
+ TQString options; // additional fstab options
+};
+
+class KrMountDetector {
+#if defined(BSD)
+ TQString checksum;
+#else
+ TQDateTime lastMtab;
+#endif
+public:
+ KrMountDetector();
+ static KrMountDetector * getInstance();
+ bool hasMountsChanged();
+};
+
+
+
+#endif
diff --git a/src/app/Panel/Makefile.am b/src/app/Panel/Makefile.am
new file mode 100644
index 0000000..3317a9b
--- /dev/null
+++ b/src/app/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/src/app/Panel/krbriefview.cpp b/src/app/Panel/krbriefview.cpp
new file mode 100644
index 0000000..687dc17
--- /dev/null
+++ b/src/app/Panel/krbriefview.cpp
@@ -0,0 +1,1462 @@
+/***************************************************************************
+ 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 <tqheader.h>
+#include <tqtooltip.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 TQToolTip
+{
+public:
+ KrBriefViewToolTip( KrBriefView *view, TQWidget *parent );
+ void maybeTip( const TQPoint &pos );
+
+ virtual ~KrBriefViewToolTip() {}
+private:
+ KrBriefView *view;
+};
+
+KrBriefViewToolTip::KrBriefViewToolTip( KrBriefView *lv, TQWidget *parent )
+ : TQToolTip( parent ), view( lv )
+{
+}
+
+void KrBriefViewToolTip::maybeTip( const TQPoint &pos )
+{
+ TQIconViewItem *item = view->findItem( view->viewportToContents( pos ) );
+
+ if ( !item )
+ return;
+
+ int width = TQFontMetrics( view->font() ).width( item->text() ) + 4;
+
+ TQRect r = item->rect();
+ r.setTopLeft( view->contentsToViewport( r.topLeft() ) );
+ if( width > item->textRect().width() )
+ tip( r, item->text() );
+}
+
+
+KrBriefView::KrBriefView( TQHeader * headerIn, TQWidget *parent, bool &left, TDEConfig *cfg, const char *name ):
+ TDEIconView(parent, name), KrView( cfg ), header( headerIn ), _currDragItem( 0 ),
+ currentlyRenamedItem( 0 ), pressedItem( 0 ), mouseEvent( 0 ) {
+ setWidget( this );
+ _nameInTDEConfig = TQString( "KrBriefView" ) + TQString( ( 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 TDEConfigGroupSaver will work correctly!
+ TDEConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ setFont( _config->readFontEntry( "Filelist Font", _FilelistFont ) );
+ // decide on single click/double click selection
+ if ( _config->readBoolEntry( "Single Click Selects", _SingleClickSelects ) &&
+ TDEGlobalSettings::singleClick() ) {
+ connect( this, TQ_SIGNAL( executed( TQIconViewItem* ) ), this, TQ_SLOT( slotExecuted( TQIconViewItem* ) ) );
+ } else {
+ connect( this, TQ_SIGNAL( clicked( TQIconViewItem* ) ), this, TQ_SLOT( slotClicked( TQIconViewItem* ) ) );
+ connect( this, TQ_SIGNAL( doubleClicked( TQIconViewItem* ) ), this, TQ_SLOT( slotDoubleClicked( TQIconViewItem* ) ) );
+ }
+
+ // a change in the selection needs to update totals
+ connect( this, TQ_SIGNAL( onItem( TQIconViewItem* ) ), this, TQ_SLOT( slotItemDescription( TQIconViewItem* ) ) );
+ connect( this, TQ_SIGNAL( contextMenuRequested( TQIconViewItem*, const TQPoint& ) ),
+ this, TQ_SLOT( handleContextMenu( TQIconViewItem*, const TQPoint& ) ) );
+ connect( this, TQ_SIGNAL( rightButtonPressed(TQIconViewItem*, const TQPoint&)),
+ this, TQ_SLOT(slotRightButtonPressed(TQIconViewItem*, const TQPoint&)));
+ connect( this, TQ_SIGNAL( currentChanged( TQIconViewItem* ) ), this, TQ_SLOT( setNameToMakeCurrent( TQIconViewItem* ) ) );
+ connect( this, TQ_SIGNAL( currentChanged( TQIconViewItem* ) ), this, TQ_SLOT( transformCurrentChanged( TQIconViewItem* ) ) );
+ connect( this, TQ_SIGNAL( mouseButtonClicked ( int, TQIconViewItem *, const TQPoint & ) ),
+ this, TQ_SLOT( slotMouseClicked ( int, TQIconViewItem *, const TQPoint & ) ) );
+ connect( &KrColorCache::getColorCache(), TQ_SIGNAL( colorsRefreshed() ), this, TQ_SLOT( refreshColors() ) );
+
+ // add whatever columns are needed to the listview
+ krConfig->setGroup( nameInTDEConfig() );
+
+ // determine basic settings for the view
+ setAcceptDrops( true );
+ setItemsMovable( false );
+ setItemTextPos( TQIconView::Right );
+ setArrangement( TQIconView::TopToBottom );
+ setWordWrapIconText( false );
+ setSpacing( 0 );
+ horizontalScrollBar()->installEventFilter( this );
+
+ // allow in-place renaming
+
+ connect( this, TQ_SIGNAL( itemRenamed ( TQIconViewItem * ) ),
+ this, TQ_SLOT( inplaceRenameFinished( TQIconViewItem * ) ) );
+ connect( &renameTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( renameCurrentItem() ) );
+ connect( &contextMenuTimer, TQ_SIGNAL (timeout()), this, TQ_SLOT (showContextMenu()));
+
+ setSelectionMode( TQIconView::Extended );
+
+ setFocusPolicy( TQWidget::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() ? TQt::Ascending : TQt::Descending );
+ connect( header, TQ_SIGNAL(clicked( int )), this, TQ_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 ( TQResizeEvent * resEvent )
+{
+ TQPoint pnt( contentsX(), contentsY() );
+ TQRect viewportRect( pnt, resEvent->oldSize() );
+ bool visible = false;
+ if( currentItem() )
+ visible = viewportRect.contains( currentItem()->rect() );
+
+ TDEIconView::resizeEvent( resEvent );
+ redrawColumns();
+
+ if( visible && currentItem() )
+ ensureItemVisible( currentItem() );
+}
+
+void KrBriefView::redrawColumns()
+{
+ bool ascending = sortDirection();
+ setSorting( false, ascending );
+
+ setGridX( width() / PROPS->numberOfColumns );
+
+ // TQt bug, it's important for recalculating the bounding rectangle
+ for( TQIconViewItem * item = firstItem(); item; item = item->nextItem() )
+ {
+ TQString 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 ) {
+ TQIconViewItem * item = firstItem();
+ TQIconViewItem * currentItem = item;
+
+ // add the up-dir arrow if needed
+ if ( addUpDir ) {
+ new KrBriefViewItem( this, ( TQIconViewItem* ) 0L, ( vfile* ) 0L );
+ }
+
+
+ // text for updating the status bar
+ TQString statusText = TQString("%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<TQIconViewItem*>(bvitem);
+ statusText = bvitem->description();
+ }
+ }
+
+
+ // re-enable sorting
+ setSorting( true, as );
+ sort( as );
+
+ if ( !currentItem )
+ currentItem = firstItem();
+ TDEIconView::setCurrentItem( currentItem );
+ ensureItemVisible( currentItem );
+
+ op()->emitItemDescription( statusText );
+}
+
+void KrBriefView::delItem( const TQString &name ) {
+ KrView::delItem( name );
+ arrangeItemsInGrid();
+}
+
+TQString KrBriefView::getCurrentItem() const {
+ TQIconViewItem * it = currentItem();
+ if ( !it )
+ return TQString();
+ else
+ return dynamic_cast<KrViewItem*>( it ) ->name();
+}
+
+void KrBriefView::setCurrentItem( const TQString& name ) {
+ KrBriefViewItem * it = dynamic_cast<KrBriefViewItem*>(_dict[ name ]);
+ if ( it )
+ TDEIconView::setCurrentItem( it );
+}
+
+void KrBriefView::clear() {
+ if( currentlyRenamedItem ) {
+ currentlyRenamedItem->cancelRename();
+ currentlyRenamedItem = 0;
+ }
+
+ op()->emitSelectionChanged(); /* to avoid rename crash at refresh */
+ TDEIconView::clear();
+ KrView::clear();
+}
+
+void KrBriefView::slotClicked( TQIconViewItem *item ) {
+ if ( !item ) return ;
+
+ if ( !modifierPressed ) {
+ if ( singleClicked && !renameTimer.isActive() ) {
+ TDEConfig * config = TDEGlobal::config();
+ config->setGroup( "KDE" );
+ int doubleClickInterval = config->readNumEntry( "DoubleClickInterval", 400 );
+
+ int msecsFromLastClick = clickTime.msecsTo( TQTime::currentTime() );
+
+ if ( msecsFromLastClick > doubleClickInterval && msecsFromLastClick < 5 * doubleClickInterval ) {
+ singleClicked = false;
+ renameTimer.start( doubleClickInterval, true );
+ return ;
+ }
+ }
+
+ CANCEL_TWO_CLICK_RENAME;
+ singleClicked = true;
+ clickTime = TQTime::currentTime();
+ clickedItem = item;
+ }
+}
+
+void KrBriefView::slotDoubleClicked( TQIconViewItem *item ) {
+ CANCEL_TWO_CLICK_RENAME;
+ if ( !item )
+ return ;
+ TQString 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;
+ TDEConfigGroupSaver 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( TQIconViewItem * item ) {
+ KrViewItem * it = static_cast<KrBriefViewItem*>( item );
+ if ( !it )
+ return ;
+ TQString desc = it->description();
+ op()->emitItemDescription(desc);
+}
+
+void KrBriefView::handleQuickSearchEvent( TQKeyEvent * e ) {
+ switch ( e->key() ) {
+ case Key_Insert:
+ {
+ TQKeyEvent ev = TQKeyEvent( TQKeyEvent::KeyPress, Key_Space, 0, 0 );
+ TDEIconView::keyPressEvent( & ev );
+ ev = TQKeyEvent( TQKeyEvent::KeyPress, Key_Down, 0, 0 );
+ keyPressEvent( & ev );
+ break;
+ }
+ case Key_Home:
+ {
+ TQIconView::setCurrentItem( firstItem() );
+ TQKeyEvent ev = TQKeyEvent( TQKeyEvent::KeyPress, Key_Down, 0, 0 );
+ keyPressEvent( & ev );
+ break;
+ }
+ case Key_End:
+ {
+ TQIconView::setCurrentItem( firstItem() );
+ TQKeyEvent ev = TQKeyEvent( TQKeyEvent::KeyPress, Key_Up, 0, 0 );
+ keyPressEvent( & ev );
+ break;
+ }
+ }
+}
+
+
+void KrBriefView::slotCurrentChanged( TQIconViewItem * item ) {
+ CANCEL_TWO_CLICK_RENAME;
+ if ( !item )
+ return ;
+ _nameToMakeCurrent = static_cast<KrBriefViewItem*>( item ) ->name();
+}
+
+void KrBriefView::contentsMousePressEvent( TQMouseEvent * e ) {
+ bool callDefaultHandler = true, processEvent = true, selectionChanged = false;
+ pressedItem = 0;
+
+ e = transformMouseEvent( e );
+
+ TQIconViewItem * oldCurrent = currentItem();
+ TQIconViewItem *newCurrent = findItem( e->pos() );
+ if (e->button() == TQt::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() == TQt::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
+ TDEConfigGroupSaver 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()->useTQTSelection()){
+ if ( oldCurrent && newCurrent && oldCurrent != newCurrent && e->state() & ShiftButton ) {
+ int oldPos = oldCurrent->index();
+ int newPos = newCurrent->index();
+ TQIconViewItem *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();
+ }
+ TQIconView::setCurrentItem( newCurrent );
+ callDefaultHandler = false;
+ }
+ if( e->state() & ShiftButton )
+ callDefaultHandler = false;
+ }
+
+ if (selectionChanged)
+ updateView(); // don't call triggerUpdate directly!
+
+ if (callDefaultHandler)
+ {
+ dragStartPos = TQPoint( -1, -1 );
+
+ TQString name = TQString(); // will the file be deleted by the mouse event?
+ if( newCurrent ) // save the name of the file
+ name = static_cast<KrBriefViewItem*>( newCurrent ) ->name();
+
+ TDEIconView::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 TQIconView::contentsMousePressEvent();
+ // the right click signal is not emitted as it is used for selection
+
+ TQPoint 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) TQIconView::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( TQMouseEvent * e ) {
+ if (e->button() == TQt::RightButton)
+ contextMenuTimer.stop();
+
+ e = transformMouseEvent( e );
+
+ TDEIconView::contentsMouseReleaseEvent( e );
+
+ if( pressedItem ) {
+ TQPoint vp = contentsToViewport( e->pos() );
+ TQIconViewItem *newCurrent = findItem( e->pos() );
+
+ if( pressedItem == newCurrent ) {
+ // emitting the missing signals from TQIconView::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 ( TQMouseEvent * e ) {
+ e = transformMouseEvent( e );
+
+ if ( ( singleClicked || renameTimer.isActive() ) && findItem( e->pos() ) != clickedItem )
+ CANCEL_TWO_CLICK_RENAME;
+
+ if ( dragStartPos != TQPoint( -1, -1 ) &&
+ e->state() & TQt::LeftButton && ( dragStartPos - e->pos() ).manhattanLength() > TQApplication::startDragDistance() )
+ startDrag();
+ if (KrSelectionMode::getSelectionHandler()->rightButtonPreservesSelection()
+ && KrSelectionMode::getSelectionHandler()->rightButtonSelects()
+ && KrSelectionMode::getSelectionHandler()->showContextMenu() >= 0 && e->state() == TQt::RightButton)
+ {
+ TQIconViewItem *newItem = findItem( e->pos() );
+ e->accept();
+ if (newItem != lastSwushPosition && newItem)
+ {
+ // is the new item above or below the previous one?
+ TQIconViewItem * above = newItem;
+ TQIconViewItem * 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 TQIconView::contentsMouseMoveEvent();
+ if( newItem )
+ emit onItem( newItem );
+ else
+ emit onViewport();
+ }
+ else
+ TDEIconView::contentsMouseMoveEvent( e );
+}
+
+void KrBriefView::contentsMouseDoubleClickEvent ( TQMouseEvent * e )
+{
+ e = transformMouseEvent ( e );
+ TDEIconView::contentsMouseDoubleClickEvent( e );
+}
+
+void KrBriefView::handleContextMenu( TQIconViewItem * it, const TQPoint & pos ) {
+ if ( !_focused )
+ op()->emitNeedFocus();
+ setFocus();
+
+ if ( !it )
+ return ;
+ if ( static_cast<KrBriefViewItem*>( it ) ->
+ name() == ".." )
+ return ;
+ int i = KrSelectionMode::getSelectionHandler()->showContextMenu();
+ contextMenuPoint = TQPoint( 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 TQPoint & vp ) {
+ return dynamic_cast<KrViewItem*>( TDEIconView::findItem( vp ) );
+}
+
+bool KrBriefView::acceptDrag( TQDropEvent* ) const {
+ return true;
+}
+
+void KrBriefView::contentsDropEvent( TQDropEvent * e ) {
+ _currDragItem = 0;
+ op()->emitGotDrop(e);
+ e->ignore();
+ TDEIconView::contentsDropEvent( e );
+}
+
+void KrBriefView::contentsDragMoveEvent( TQDragMoveEvent * e ) {
+ KrViewItem *oldDragItem = _currDragItem;
+
+ _currDragItem = getKrViewItemAt( e->pos() );
+ if( _currDragItem && !_currDragItem->VF->vfile_isDir() )
+ _currDragItem = 0;
+
+ TDEIconView::contentsDragMoveEvent( e );
+
+ if( _currDragItem != oldDragItem )
+ {
+ if( oldDragItem )
+ dynamic_cast<KrBriefViewItem *>( oldDragItem )->repaint();
+ if( _currDragItem )
+ dynamic_cast<KrBriefViewItem *>( _currDragItem )->repaint();
+ }
+}
+
+void KrBriefView::contentsDragLeaveEvent ( TQDragLeaveEvent *e )
+{
+ KrViewItem *oldDragItem = _currDragItem;
+
+ _currDragItem = 0;
+ TDEIconView::contentsDragLeaveEvent( e );
+
+ if( oldDragItem )
+ dynamic_cast<KrBriefViewItem *>( oldDragItem )->repaint();
+}
+
+void KrBriefView::imStartEvent(TQIMEvent* e)
+{
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ ACTIVE_PANEL->quickSearch->myIMStartEvent( e );
+ return ;
+ }else {
+ TDEConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ if ( !_config->readBoolEntry( "New Style Quicksearch", _NewStyleQuicksearch ) )
+ TDEIconView::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(TQIMEvent* e)
+{
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ ACTIVE_PANEL->quickSearch->myIMEndEvent( e );
+ return ;
+ }
+}
+
+void KrBriefView::imComposeEvent(TQIMEvent* e)
+{
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ ACTIVE_PANEL->quickSearch->myIMComposeEvent( e );
+ return ;
+ }
+}
+
+void KrBriefView::keyPressEvent( TQKeyEvent * 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()->useTQTSelection()) {
+ TQIconViewItem * i = currentItem();
+ if ( !i ) break;
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+ i = i->prevItem();
+ if ( i ) {
+ TQIconView::setCurrentItem( i );
+ TQIconView::ensureItemVisible( i );
+ }
+ } else TDEIconView::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()->useTQTSelection()){
+ TQIconViewItem * i = currentItem();
+ if ( !i ) break;
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected(), true );
+ i = i->nextItem();
+ if ( i ) {TQIconView::setCurrentItem( i ); TQIconView::ensureItemVisible( i ); }
+ } else TDEIconView::keyPressEvent(e);
+ break;
+ case Key_Next: if (!KrSelectionMode::getSelectionHandler()->useTQTSelection()){
+ TQIconViewItem * i = currentItem(), *j;
+ if ( !i ) break;
+ TQRect r( i->rect() );
+ if ( !r.height() ) break;
+ for ( int page = visibleHeight() / r.height() - 1; page > 0 && ( j = i->nextItem() ); --page )
+ i = j;
+ if ( i ) {TQIconView::setCurrentItem( i ); TQIconView::ensureItemVisible( i ); }
+ } else TDEIconView::keyPressEvent(e);
+ break;
+ case Key_Prior: if (!KrSelectionMode::getSelectionHandler()->useTQTSelection()){
+ TQIconViewItem * i = currentItem(), *j;
+ if ( !i ) break;
+ TQRect r( i->rect() );
+ if ( !r.height() ) break;
+ for ( int page = visibleHeight() / r.height() - 1; page > 0 && ( j = i->prevItem() ); --page )
+ i = j;
+ if ( i ) {TQIconView::setCurrentItem( i ); TQIconView::ensureItemVisible( i ); }
+ } else TDEIconView::keyPressEvent(e);
+ break;
+ case Key_Home: if (!KrSelectionMode::getSelectionHandler()->useTQTSelection()){
+ if ( e->state() & ShiftButton ) /* Shift+Home */
+ {
+ clearSelection();
+ TDEIconView::keyPressEvent( e );
+ op()->emitSelectionChanged();
+ arrangeItemsInGrid();
+ break;
+ } else {
+ TQIconViewItem * i = firstItem();
+ if ( i ) {TQIconView::setCurrentItem( i ); TQIconView::ensureItemVisible( i ); }
+ }
+ } else TDEIconView::keyPressEvent(e);
+ break;
+ case Key_End: if (!KrSelectionMode::getSelectionHandler()->useTQTSelection()){
+ if ( e->state() & ShiftButton ) /* Shift+End */
+ {
+ clearSelection();
+ TDEIconView::keyPressEvent( e );
+ op()->emitSelectionChanged();
+ arrangeItemsInGrid();
+ break;
+ } else {
+ TQIconViewItem *i = firstItem(), *j;
+ while ( ( j = i->nextItem() ) )
+ i = j;
+ while ( ( j = i->nextItem() ) )
+ i = j;
+ if ( i ) {TQIconView::setCurrentItem( i ); TQIconView::ensureItemVisible( i ); }
+ break;
+ }
+ } else TDEIconView::keyPressEvent(e);
+ break;
+ case Key_Enter :
+ case Key_Return : {
+ if ( e->state() & ControlButton ) // let the panel handle it
+ e->ignore();
+ else {
+ KrViewItem * i = getCurrentKrViewItem();
+ TQString 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()->useTQTSelection()) {
+ TQIconViewItem *i = currentItem();
+ TQIconViewItem *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 )
+ {
+ TQIconView::setCurrentItem( newCurrent );
+ TQIconView::ensureItemVisible( newCurrent );
+ }
+ } else TDEIconView::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()->useTQTSelection()) {
+ TQIconViewItem *i = currentItem();
+ TQIconViewItem *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 )
+ {
+ TQIconView::setCurrentItem( newCurrent );
+ TQIconView::ensureItemVisible( newCurrent );
+ }
+ } else TDEIconView::keyPressEvent(e);
+ break;
+
+ case Key_Delete : // kill file
+ SLOTS->deleteFiles( e->state() == ShiftButton || e->state() == ControlButton );
+
+ break ;
+ case Key_Insert : {
+ {
+ TQIconViewItem *i = currentItem();
+ if( !i )
+ break;
+
+ if (KrSelectionMode::getSelectionHandler()->insertMovesDown())
+ {
+ setSelected( i, !i->isSelected(), true );
+ if( i->nextItem() )
+ {
+ TQIconView::setCurrentItem( i->nextItem() );
+ TQIconView::ensureItemVisible( i->nextItem() );
+ }
+ }
+ else
+ {
+ setSelected( i, !i->isSelected(), true );
+ }
+ }
+ break ;
+ }
+ case Key_Space : {
+ {
+ TQIconViewItem *i = currentItem();
+ if( !i )
+ break;
+
+ if (KrSelectionMode::getSelectionHandler()->spaceMovesDown())
+ {
+ setSelected( i, !i->isSelected(), true );
+ if( i->nextItem() )
+ {
+ TQIconView::setCurrentItem( i->nextItem() );
+ TQIconView::ensureItemVisible( i->nextItem() );
+ }
+ }
+ else
+ {
+ setSelected( i, !i->isSelected(), true );
+ }
+ }
+ break ;
+ }
+ case Key_A : // mark all
+ if ( e->state() == ControlButton ) {
+ TDEIconView::keyPressEvent( e );
+ updateView();
+ break;
+ }
+ default:
+ if ( e->key() == Key_Escape ) {
+ TQIconView::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?
+ {
+ TDEConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ if ( !_config->readBoolEntry( "New Style Quicksearch", _NewStyleQuicksearch ) )
+ TDEIconView::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 );
+ }
+ TDEIconView::keyPressEvent( e );
+ }
+ }
+ // emit the new item description
+ slotItemDescription( currentItem() ); // actually send the TQIconViewItem
+}
+// overridden to make sure EXTENTION won't be lost during rename
+void KrBriefView::rename( TQIconViewItem * item ) {
+ currentlyRenamedItem = dynamic_cast< KrBriefViewItem * >( item );
+ currentlyRenamedItem->rename();
+ //TODO: renameLineEdit() ->selectAll();
+}
+
+void KrBriefView::renameCurrentItem() {
+ TQString 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<TQIconViewItem*>( it ) );
+ // if applicable, select only the name without extension
+/* TODO:
+ TDEConfigGroupSaver 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( TQIconViewItem * 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 TQString & str, int direction ) {
+ KrViewItem * item = getCurrentKrViewItem();
+ if (!item)
+ return;
+ TDEConfigGroupSaver 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( TQKeyEvent * 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( TQIconViewItem * it ) {
+ if (!it) return;
+ KrView::setNameToMakeCurrent( static_cast<KrBriefViewItem*>( it ) ->name() );
+}
+
+void KrBriefView::slotMouseClicked( int button, TQIconViewItem * item, const TQPoint& ) {
+ pressedItem = 0; // if the signals are emitted, don't emit twice at contentsMouseReleaseEvent
+ if ( button == TQt::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 );
+ TQColorGroup 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( TDEGlobalSettings::baseColor() );
+ }
+ slotUpdate();
+}
+
+bool KrBriefView::event( TQEvent *e ) {
+ modifierPressed = false;
+
+ switch ( e->type() ) {
+ case TQEvent::Timer:
+ case TQEvent::MouseMove:
+ case TQEvent::MouseButtonPress:
+ case TQEvent::MouseButtonRelease:
+ break;
+ default:
+ CANCEL_TWO_CLICK_RENAME;
+ }
+ if( e->type() == TQEvent::Wheel )
+ {
+ if ( !_focused )
+ op()->emitNeedFocus();
+ setFocus();
+ }
+ return TDEIconView::event( e );
+}
+
+
+bool KrBriefView::eventFilter( TQObject * watched, TQEvent * e )
+{
+ if( watched == horizontalScrollBar() )
+ {
+ if( e->type() == TQEvent::Hide || e->type() == TQEvent::Show )
+ {
+ bool res = TDEIconView::eventFilter( watched, e );
+ arrangeItemsInGrid();
+ return res;
+ }
+ }
+ else if( watched == header )
+ {
+ if( e->type() == TQEvent::MouseButtonPress && ((TQMouseEvent *)e )->button() == TQt::RightButton )
+ {
+ setColumnNr();
+ return true;
+ }
+ return false;
+ }
+ return TDEIconView::eventFilter( watched, e );
+}
+
+void KrBriefView::makeItemVisible( const KrViewItem *item ) {
+// tqApp->processEvents(); // Please don't remove the comment. Causes crash if it is inserted!
+ ensureItemVisible( (TQIconViewItem *)( static_cast<const KrBriefViewItem*>( item ) ) );
+}
+
+void KrBriefView::initOperator() {
+ _operator = new KrViewOperator(this, this);
+ // TQIconView emits selection changed, so chain them to operator
+ connect(this, TQ_SIGNAL(selectionChanged()), _operator, TQ_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( "*" );
+ TDEConfigGroupSaver 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 = TQString( "a" ).localeAwareCompare( "B" ) > 0; // see KDE bug #40131
+
+ TQStringList defaultAtomicExtensions;
+ defaultAtomicExtensions += ".tar.gz";
+ defaultAtomicExtensions += ".tar.bz2";
+ defaultAtomicExtensions += ".moc.cpp";
+ defaultAtomicExtensions += ".tar.xz";
+ TQStringList atomicExtensions = krConfig->readListEntry("Atomic Extensions", defaultAtomicExtensions);
+ for (TQStringList::iterator i = atomicExtensions.begin(); i != atomicExtensions.end(); )
+ {
+ TQString & 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( nameInTDEConfig() );
+ 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()
+{
+ TDEPopupMenu popup( this );
+ popup.insertTitle( i18n("Columns"));
+
+ int COL_ID = 14700;
+
+ for( int i=1; i <= MAX_COLS; i++ )
+ {
+ popup.insertItem( TQString( "%1" ).arg( i ), COL_ID + i );
+ popup.setItemChecked( COL_ID + i, PROPS->numberOfColumns == i );
+ }
+
+ int result=popup.exec(TQCursor::pos());
+
+ krConfig->setGroup( nameInTDEConfig() );
+
+ 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(TQIconViewItem*, const TQPoint& point) {
+ op()->emitEmptyContextMenu(point);
+}
+
+void KrBriefView::changeSortOrder()
+{
+ bool asc = !sortDirection();
+ header->setSortIndicator( 0, asc ? TQt::Ascending : TQt::Descending );
+ sort( asc );
+}
+
+TQMouseEvent * KrBriefView::transformMouseEvent( TQMouseEvent * e )
+{
+ if( findItem( e->pos() ) != 0 )
+ return e;
+
+ TQIconViewItem *closestItem = 0;
+ int mouseX = e->pos().x(), mouseY = e->pos().y();
+ int closestDelta = 0x7FFFFFFF;
+
+ int minX = ( mouseX / gridX() ) * gridX();
+ int maxX = minX + gridX();
+
+ TQIconViewItem *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 )
+ {
+ TQRect 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;
+ TQPoint newPos( mouseX, mouseY );
+ TQPoint glPos;
+ if( !e->globalPos().isNull() )
+ {
+ glPos = TQPoint( mouseX - e->pos().x() + e->globalPos().x(),
+ mouseY - e->pos().y() + e->globalPos().y() );
+ }
+
+ if( mouseEvent )
+ delete mouseEvent;
+ return mouseEvent = new TQMouseEvent( e->type(), newPos, glPos, e->button(), e->state() );
+ }
+
+ return e;
+}
+
+#include "krbriefview.moc"
diff --git a/src/app/Panel/krbriefview.h b/src/app/Panel/krbriefview.h
new file mode 100644
index 0000000..e567ab9
--- /dev/null
+++ b/src/app/Panel/krbriefview.h
@@ -0,0 +1,173 @@
+/***************************************************************************
+ 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 <tqtimer.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 TQDragMoveEvent;
+class TQToolTip;
+class TQHeader;
+
+/**
+ * KrBriefView implements everthing and anything regarding a brief view in a filemananger.
+ * IT MUST USE KrViewItem as the children to it's *TDEIconView. 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 TDEIconView, public KrView {
+ friend class KrBriefViewItem;
+ TQ_OBJECT
+
+public:
+ KrBriefView( TQHeader *header, TQWidget *parent, bool &left, TDEConfig *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<TQIconViewItem*>( current ) ->nextItem() ); }
+ virtual inline KrViewItem *getPrev( KrViewItem *current ) { return dynamic_cast<KrViewItem*>( dynamic_cast<TQIconViewItem*>( current ) ->prevItem() ); }
+ virtual inline KrViewItem *getCurrentKrViewItem() { return dynamic_cast<KrViewItem*>( currentItem() ); }
+ virtual KrViewItem *getKrViewItemAt(const TQPoint &vp);
+ virtual inline KrViewItem *findItemByName(const TQString &name) { return dynamic_cast<KrViewItem*>( findItem( name, TQt::ExactMatch ) ); }
+ virtual void addItems(vfs* v, bool addUpDir = true);
+ virtual void delItem(const TQString &);
+ virtual TQString getCurrentItem() const;
+ virtual void makeItemVisible(const KrViewItem * item );
+ virtual void setCurrentItem(const TQString& name );
+ virtual void updateView();
+ virtual void updateItem(KrViewItem* item );
+ virtual void clear();
+ virtual void sort() { if( sortDirection() ) sortOrderChanged();TDEIconView::sort( true ); }
+ virtual void sort( bool ascending ) { if( sortDirection() != ascending ) sortOrderChanged();TDEIconView::sort( ascending ); }
+ virtual void prepareForActive();
+ virtual void prepareForPassive();
+ virtual void saveSettings() {}
+ virtual void restoreSettings() {}
+ virtual TQString nameInTDEConfig() {return _nameInTDEConfig;}
+ virtual void resizeEvent ( TQResizeEvent * );
+
+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( TQKeyEvent *e );
+ virtual void imStartEvent( TQIMEvent* e );
+ virtual void imEndEvent( TQIMEvent *e );
+ virtual void imComposeEvent( TQIMEvent *e );
+ virtual void contentsMousePressEvent( TQMouseEvent *e );
+ virtual void contentsMouseReleaseEvent (TQMouseEvent *e);
+ virtual void contentsMouseMoveEvent ( TQMouseEvent * e );
+ virtual void contentsMouseDoubleClickEvent ( TQMouseEvent * e );
+ virtual bool acceptDrag( TQDropEvent* e ) const;
+ virtual void contentsDropEvent( TQDropEvent *e );
+ virtual void contentsDragMoveEvent( TQDragMoveEvent *e );
+ virtual void contentsDragLeaveEvent ( TQDragLeaveEvent * );
+ virtual void startDrag() { op()->startDrag(); }
+ virtual bool event( TQEvent *e );
+ virtual bool eventFilter( TQObject * watched, TQEvent * e );
+ TQMouseEvent * transformMouseEvent( TQMouseEvent * );
+
+protected slots:
+ void rename( TQIconViewItem *item );
+ void slotClicked( TQIconViewItem *item );
+ void slotDoubleClicked( TQIconViewItem *item );
+ void slotItemDescription( TQIconViewItem * );
+ void slotCurrentChanged( TQIconViewItem *item );
+ void handleContextMenu( TQIconViewItem*, const TQPoint& );
+ virtual void renameCurrentItem();
+ virtual void showContextMenu( );
+ void inplaceRenameFinished( TQIconViewItem *it );
+ void setNameToMakeCurrent( TQIconViewItem *it );
+ void sortOrderChanged();
+ void slotRightButtonPressed(TQIconViewItem*, const TQPoint& point);
+ void transformCurrentChanged( TQIconViewItem * item ) { emit currentChanged( dynamic_cast<KrViewItem *>(item ) ); }
+
+ /**
+ * used internally to produce the signal middleButtonClicked()
+ */
+ void slotMouseClicked( int button, TQIconViewItem * item, const TQPoint & pos );
+ inline void slotExecuted( TQIconViewItem* i ) {
+ TQString tmp = dynamic_cast<KrViewItem*>( i ) ->name();
+ op()->emitExecuted( tmp );
+ }
+
+public slots:
+ void refreshColors();
+ void quickSearch( const TQString &, int = 0 );
+ void stopQuickSearch( TQKeyEvent* );
+ void handleQuickSearchEvent( TQKeyEvent* );
+ void changeSortOrder();
+
+
+signals:
+ void letsDrag(TQStringList items, TQPixmap icon);
+ void gotDrop(TQDropEvent *);
+
+private:
+ TQHeader * header;
+ bool swushSelects;
+ TQPoint dragStartPos;
+ TQIconViewItem *lastSwushPosition;
+ KrViewItem *_currDragItem;
+ bool singleClicked;
+ bool modifierPressed;
+ TQTime clickTime;
+ TQIconViewItem *clickedItem;
+ TQTimer renameTimer;
+ TQTimer contextMenuTimer;
+ TQPoint contextMenuPoint;
+ KrBriefViewItem *currentlyRenamedItem;
+ TQIconViewItem *pressedItem;
+ TQMouseEvent *mouseEvent;
+ TQToolTip *toolTip;
+};
+
+#endif
diff --git a/src/app/Panel/krbriefviewitem.cpp b/src/app/Panel/krbriefviewitem.cpp
new file mode 100644
index 0000000..8bcdca9
--- /dev/null
+++ b/src/app/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 <tdeconfig.h>
+#include "krcolorcache.h"
+
+#include <tqpainter.h>
+#include <tqpointarray.h>
+
+#define PROPS _viewProperties
+#define VF getVfile()
+
+#ifdef FASTER
+int KrBriefViewItem::expHeight = 0;
+#endif // FASTER
+
+KrBriefViewItem::KrBriefViewItem(KrBriefView *parent, TQIconViewItem *after, vfile *vf):
+ TDEIconViewItem(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) {
+ TDEConfigGroupSaver svr(krConfig, "Look&Feel");
+ expHeight = 2 + (krConfig->readEntry("Filelist Icon Size",_FilelistIconSize)).toInt();
+ }
+ if( PROPS->displayIcons )
+ itemIcon = TQPixmap( 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, TQString(), TQString(), 0);
+
+ setText("..");
+ if ( PROPS->displayIcons )
+ setPixmap( FL_LOADICON( "go-up" ) );
+ setSelectable( false );
+ setDragEnabled( false );
+ setDropEnabled( false );
+#ifdef FASTER
+ initiated = true;
+#endif // FASTER
+ }
+
+ setRenameEnabled( false );
+ setDragEnabled( true );
+ setDropEnabled( true );
+ repaintItem();
+}
+
+
+int KrBriefViewItem::compare(TQIconViewItem *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;
+
+ TQString text0 = name();
+ if (text0 == "..") return 1*asc;
+
+ TQString 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 TQString::compare(text0, itext0);
+ } else return TQString::localeAwareCompare(text0,itext0);
+}
+
+void KrBriefViewItem::paintItem(TQPainter *p, const TQColorGroup &cg) {
+#ifdef FASTER
+ if (!initiated && !dummyVfile) {
+ // display an icon if needed
+ initiated = true;
+ if (PROPS->displayIcons)
+ itemIcon =KrView::getIcon(_vf);
+ }
+#endif
+
+ TQColorGroup _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( TQt::NoPen );
+ p->setBrush( TQBrush( _cg.background() ) );
+ p->drawRect( rect() );
+ p->restore();
+ }
+
+ TQIconViewItem::paintItem(p, _cg);
+
+ paintFocus( p, cg );
+}
+
+void KrBriefViewItem::paintFocus(TQPainter *p, const TQColorGroup &cg) {
+ if ( ( iconView()->hasFocus() && this == iconView()->currentItem() ) ||
+ ((KrBriefView *)iconView())->_currDragItem == this )
+ {
+ p->save();
+ TQPen pen( cg.shadow(), 0, TQt::DotLine );
+ p->setPen( pen );
+
+ // we manually draw the focus rect by points
+ TQRect rec = rect();
+ TQPointArray 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(TQStyle::PE_FocusRect, p,
+// TQRect( rect().x(), rect().y(), rect().width(), rect().height() ), cg,
+// TQStyle::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 TQString & text_ )
+{
+ TDEIconViewItem::calcRect( text_ );
+ TQRect 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/src/app/Panel/krbriefviewitem.h b/src/app/Panel/krbriefviewitem.h
new file mode 100644
index 0000000..c663bd1
--- /dev/null
+++ b/src/app/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 <tqguardedptr.h>
+
+#define FASTER
+
+class TQPixmap;
+class KrBriefView;
+
+class KrBriefViewItem : public TDEIconViewItem, public KrViewItem {
+friend class KrBriefView;
+friend class KrCalcSpaceDialog;
+public:
+ KrBriefViewItem(KrBriefView *parent, TQIconViewItem *after, vfile *vf);
+ inline bool isSelected() const { return TDEIconViewItem::isSelected(); }
+ inline void setSelected(bool s) { TDEIconViewItem::setSelected(s); }
+ inline void cancelRename() { removeRenameBox(); }
+ int compare(TQIconViewItem *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 TQPixmap * pixmap() const {return const_cast<TQPixmap *>(&itemIcon);}
+ virtual void setPixmap ( const TQPixmap &icon ) { itemIcon = icon;}
+#endif
+
+protected:
+ virtual void paintItem(TQPainter *p, const TQColorGroup &cg);
+ virtual void paintFocus(TQPainter *p, const TQColorGroup &cg);
+ virtual void calcRect ( const TQString & text_ = TQString() );
+
+private:
+#ifdef FASTER
+ bool initiated;
+ static int expHeight;
+ TQPixmap itemIcon;
+#endif // FASTER
+ // TODO:
+ static const TQColor & setColorIfContrastIsSufficient(const TQColor & /* background */, const TQColor & /* color1 */, const TQColor & /* color2 */ ) {static TQColor col; return col;}
+
+// static int expHeight;
+};
+
+#endif
diff --git a/src/app/Panel/krcalcspacedialog.cpp b/src/app/Panel/krcalcspacedialog.cpp
new file mode 100644
index 0000000..4309f6d
--- /dev/null
+++ b/src/app/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. *
+* *
+***************************************************************************/
+
+// TQt Includes
+#include <tqtimer.h>
+#include <tqlayout.h>
+#include <tqlabel.h>
+// TDE Includes
+#include <tdelocale.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 TQStringList & 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 ( TQStringList::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(TQWidget *parent, ListPanel * files, const TQStringList & 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 TQTimer(this);
+ TQWidget * mainWidget = new TQWidget( this );
+ setMainWidget(mainWidget);
+ TQVBoxLayout *topLayout = new TQVBoxLayout( mainWidget, 0, spacingHint() );
+
+ m_label = new TQLabel( "", 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;
+ TQString msg;
+ TQString fileName = ( ( m_thread->getItems().count() == 1 ) ? ( i18n( "Name: " ) + m_thread->getItems().first() + "\n" ) : TQString( "" ) );
+ msg = fileName + i18n( "Total occupied space: %1").arg( TDEIO::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, TQ_SIGNAL(timeout()), this, TQ_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/src/app/Panel/krcalcspacedialog.h b/src/app/Panel/krcalcspacedialog.h
new file mode 100644
index 0000000..859178e
--- /dev/null
+++ b/src/app/Panel/krcalcspacedialog.h
@@ -0,0 +1,107 @@
+/***************************************************************************
+ 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> }==-- */
+
+// TDE Includes
+#include <kdialogbase.h>
+#include <tdeio/jobclasses.h>
+// TQt Includes
+#include <tqthread.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{
+ TQ_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 TQThread{
+ TDEIO::filesize_t m_totalSize, m_currentSize;
+ unsigned long m_totalFiles;
+ unsigned long m_totalDirs;
+ const TQStringList m_items;
+ vfs * m_files;
+ KrView *m_view;
+ KrCalcSpaceDialog * m_parent;
+ TQMutex m_synchronizeUsageAccess;
+ bool m_threadInUse; // true: caller needs the thread
+ bool m_stop;
+ void cleanUp(); // Deletes this, if possible
+ public:
+ TDEIO::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 TQStringList & getItems() const {return m_items;} // list of directories to calculate
+ CalcThread(KrCalcSpaceDialog * parent, ListPanel * panel, const TQStringList & 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 TQTimer * m_pollTimer;
+ TQLabel * 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, TDEIO::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(TQWidget *parent, ListPanel * panel, const TQStringList & items, bool autoclose);
+ ~KrCalcSpaceDialog();
+ TDEIO::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/src/app/Panel/krcolorcache.cpp b/src/app/Panel/krcolorcache.cpp
new file mode 100644
index 0000000..494966f
--- /dev/null
+++ b/src/app/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 <tdeglobalsettings.h>
+#include <tqfile.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 TQMap<TQString, bool> s_colorNames;
+ static TQMap<TQString, bool> s_numNames;
+ static TQMap<TQString, bool> s_boolNames;
+ static void initialize();
+public:
+ static TQValueList<TQString> getColorNames();
+ static bool isColorNameValid(const TQString & settingName);
+ static TQValueList<TQString> getNumNames();
+ static bool isNumNameValid(const TQString & settingName);
+ static TQValueList<TQString> getBoolNames();
+ static bool isBoolNameValid(const TQString & settingName);
+} krColorSettingNames;
+
+TQMap<TQString, bool> KrColorSettingNames::s_colorNames;
+TQMap<TQString, bool> KrColorSettingNames::s_numNames;
+TQMap<TQString, 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;
+}
+
+TQValueList<TQString> KrColorSettingNames::getColorNames()
+{
+ initialize();
+ return s_colorNames.keys();
+}
+
+bool KrColorSettingNames::isColorNameValid(const TQString & settingName)
+{
+ initialize();
+ return s_colorNames.contains(settingName);
+}
+
+TQValueList<TQString> KrColorSettingNames::getNumNames()
+{
+ initialize();
+ return s_numNames.keys();
+}
+
+bool KrColorSettingNames::isNumNameValid(const TQString & settingName)
+{
+ initialize();
+ return s_numNames.contains(settingName);
+}
+
+TQValueList<TQString> KrColorSettingNames::getBoolNames()
+{
+ initialize();
+ return s_boolNames.keys();
+}
+
+bool KrColorSettingNames::isBoolNameValid(const TQString & settingName)
+{
+ initialize();
+ return s_boolNames.contains(settingName);
+}
+
+
+
+/*
+KrColorSettings implementation. Contains all properties in TQMaps. loadFromConfig initializes them from krConfig.
+*/
+class KrColorSettingsImpl
+{
+ friend class KrColorSettings;
+ TQMap<TQString, TQString> m_colorTextValues;
+ TQMap<TQString, TQColor> m_colorValues;
+ TQMap<TQString, int> m_numValues;
+ TQMap<TQString, bool> m_boolValues;
+ void loadFromConfig();
+};
+
+void KrColorSettingsImpl::loadFromConfig()
+{
+ krConfig->setGroup("Colors");
+ TQValueList<TQString> names = KrColorSettingNames::getColorNames();
+ for ( TQStringList::Iterator it = names.begin(); it != names.end(); ++it )
+ {
+ m_colorTextValues[*it] = krConfig->readEntry(*it, "");
+ m_colorValues[*it] = krConfig->readColorEntry(*it);
+ }
+ names = KrColorSettingNames::getNumNames();
+ for ( TQStringList::Iterator it = names.begin(); it != names.end(); ++it )
+ {
+ if (krConfig->readEntry(*it) != TQString())
+ m_numValues[*it] = krConfig->readNumEntry(*it);
+ }
+ names = KrColorSettingNames::getBoolNames();
+ for ( TQStringList::Iterator it = names.begin(); it != names.end(); ++it )
+ {
+ if (krConfig->readEntry(*it) != TQString())
+ 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;
+ TQValueList<TQString> names = KrColorSettingNames::getColorNames();
+ for ( TQStringList::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 ( TQMap<TQString, 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 ( TQMap<TQString, 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;
+}
+
+TQValueList<TQString> KrColorSettings::getColorNames()
+{
+ return KrColorSettingNames::getColorNames();
+}
+
+bool KrColorSettings::isColorNameValid(const TQString & settingName)
+{
+ return KrColorSettingNames::isColorNameValid(settingName);
+}
+
+bool KrColorSettings::setColorValue(const TQString & settingName, const TQColor & color)
+{
+ if (!isColorNameValid(settingName))
+ {
+ krOut << "Invalid color setting name: " << settingName << endl;
+ return false;
+ }
+ m_impl->m_colorValues[settingName] = color;
+ return true;
+}
+
+TQColor KrColorSettings::getColorValue(const TQString & settingName) const
+{
+ if (!isColorNameValid(settingName))
+ {
+ krOut << "Invalid color setting name: " << settingName << endl;
+ return TQColor();
+ }
+ return m_impl->m_colorValues[settingName];
+}
+
+bool KrColorSettings::setColorTextValue(const TQString & settingName, const TQString & colorText)
+{
+ if (!isColorNameValid(settingName))
+ {
+ krOut << "Invalid color setting name: " << settingName << endl;
+ return false;
+ }
+ m_impl->m_colorTextValues[settingName] = colorText;
+ return true;
+}
+
+TQString KrColorSettings::getColorTextValue(const TQString & settingName) const
+{
+ if (!isColorNameValid(settingName))
+ {
+ krOut << "Invalid color setting name: " << settingName << endl;
+ return TQString();
+ }
+ return m_impl->m_colorTextValues[settingName];
+}
+
+TQValueList<TQString> KrColorSettings::getNumNames()
+{
+ return KrColorSettingNames::getNumNames();
+}
+
+bool KrColorSettings::isNumNameValid(const TQString & settingName)
+{
+ return KrColorSettingNames::isNumNameValid(settingName);
+}
+
+bool KrColorSettings::setNumValue(const TQString & 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 TQString & 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];
+}
+
+TQValueList<TQString> KrColorSettings::getBoolNames()
+{
+ return KrColorSettingNames::getBoolNames();
+}
+
+bool KrColorSettings::isBoolNameValid(const TQString & settingName)
+{
+ return KrColorSettingNames::isBoolNameValid(settingName);
+}
+
+bool KrColorSettings::setBoolValue(const TQString & 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 TQString & 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;
+ TQMap<TQString, TQColorGroup> m_cachedColors;
+ KrColorSettings m_colorSettings;
+ TQColorGroup getColors(const KrColorItemType & type) const;
+ static const TQColor & setColorIfContrastIsSufficient(const TQColor & background, const TQColor & color1, const TQColor & color2);
+ TQColor getForegroundColor(bool isActive) const;
+ TQColor getSpecialForegroundColor(const TQString & type, bool isActive) const;
+ TQColor getBackgroundColor(bool isActive) const;
+ TQColor getAlternateBackgroundColor(bool isActive) const;
+ TQColor getMarkedForegroundColor(bool isActive) const;
+ TQColor getMarkedBackgroundColor(bool isActive) const;
+ TQColor getAlternateMarkedBackgroundColor(bool isActive) const;
+ TQColor getCurrentForegroundColor(bool isActive) const;
+ TQColor getCurrentBackgroundColor(bool isActive) const;
+ TQColor getCurrentMarkedForegroundColor(bool isActive) const;
+ TQColor dimColor(TQColor color, bool isBackgroundColor) const;
+};
+
+TQColorGroup KrColorCacheImpl::getColors(const KrColorItemType & type) const
+{
+ TQColorGroup result;
+ if (m_colorSettings.getBoolValue("KDE Default", _KDEDefaultColors))
+ {
+ // KDE default? Getcolors from TDEGlobalSettings.
+ bool enableAlternateBackground = m_colorSettings.getBoolValue("Enable Alternate Background", _AlternateBackground);
+ TQColor background = enableAlternateBackground && type.m_alternateBackgroundColor ?
+ TDEGlobalSettings::alternateBackgroundColor()
+ : TDEGlobalSettings::baseColor();
+ result.setColor(TQColorGroup::Base, background);
+ result.setColor(TQColorGroup::Background, background);
+ result.setColor(TQColorGroup::Text, TDEGlobalSettings::textColor());
+ result.setColor(TQColorGroup::HighlightedText, TDEGlobalSettings::highlightedTextColor());
+ result.setColor(TQColorGroup::Highlight, TDEGlobalSettings::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.
+ TQColor background = type.m_alternateBackgroundColor ?
+ getAlternateBackgroundColor(isActive)
+ : getBackgroundColor(isActive);
+ TQColor 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(TQColorGroup::Base, background);
+ result.setColor(TQColorGroup::Background, background);
+
+ // set the foreground color
+ result.setColor(TQColorGroup::Text, foreground);
+
+ // now the color of a marked item
+ TQColor markedBackground = type.m_alternateBackgroundColor ?
+ getAlternateMarkedBackgroundColor(isActive)
+ : getMarkedBackgroundColor(isActive);
+ TQColor 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(TQColorGroup::HighlightedText, markedForeground);
+ result.setColor(TQColorGroup::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
+ TQColor currentBackground = getCurrentBackgroundColor(isActive);
+
+ if (!currentBackground.isValid()) // transparent
+ currentBackground = background;
+
+ // set the background
+ result.setColor(TQColorGroup::Highlight, currentBackground);
+ result.setColor(TQColorGroup::Base, currentBackground);
+ result.setColor(TQColorGroup::Background, currentBackground);
+
+ TQColor 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(TQColorGroup::Text, color);
+ result.setColor(TQColorGroup::HighlightedText, color);
+ }
+
+ if (dimBackground && !type.m_activePanel)
+ {
+ // if color dimming is choosen, dim the colors for the inactive panel
+ result.setColor(TQColorGroup::Base, dimColor(result.base(), true));
+ result.setColor(TQColorGroup::Background, dimColor(result.base(), true));
+ result.setColor(TQColorGroup::Text, dimColor(result.text(), false));
+ result.setColor(TQColorGroup::HighlightedText, dimColor(result.highlightedText(), false));
+ result.setColor(TQColorGroup::Highlight, dimColor(result.highlight(), true));
+ }
+ return result;
+}
+
+const TQColor & KrColorCacheImpl::setColorIfContrastIsSufficient(const TQColor & background, const TQColor & color1, const TQColor & 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;
+}
+
+TQColor KrColorCacheImpl::getForegroundColor(bool isActive) const
+{
+ TQColor color = TDEGlobalSettings::textColor();
+ SETCOLOR(color, m_colorSettings.getColorValue("Foreground"));
+ if (!isActive) SETCOLOR(color, m_colorSettings.getColorValue("Inactive Foreground"));
+ return color;
+}
+
+TQColor KrColorCacheImpl::getSpecialForegroundColor(const TQString & type, bool isActive) const
+{
+ TQString colorName = "Inactive " + type + " Foreground";
+ if (!isActive && m_colorSettings.getColorTextValue(colorName) == "Inactive Foreground")
+ return getForegroundColor(false);
+ TQColor color = m_colorSettings.getColorValue(type + " Foreground");
+ if (!isActive) SETCOLOR(color, m_colorSettings.getColorValue(colorName));
+ if (!color.isValid())
+ return getForegroundColor(isActive);
+ return color;
+}
+
+TQColor KrColorCacheImpl::getBackgroundColor(bool isActive) const
+{
+ TQColor color = TDEGlobalSettings::baseColor();
+ SETCOLOR(color, m_colorSettings.getColorValue("Background"));
+ if (!isActive) SETCOLOR(color, m_colorSettings.getColorValue("Inactive Background"));
+ return color;
+}
+
+TQColor 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);
+ TQColor color = isActive ?
+ m_colorSettings.getColorValue("Alternate Background")
+ : m_colorSettings.getColorValue("Inactive Alternate Background");
+ if (!color.isValid())
+ color = TDEGlobalSettings::alternateBackgroundColor();
+ if (!color.isValid())
+ color = TDEGlobalSettings::baseColor();
+ return color;
+}
+
+TQColor KrColorCacheImpl::getMarkedForegroundColor(bool isActive) const
+{
+ TQString colorName = isActive?"Marked Foreground":"Inactive Marked Foreground";
+ if (m_colorSettings.getColorTextValue(colorName) == "transparent")
+ return TQColor();
+ if (isActive && m_colorSettings.getColorTextValue(colorName) == "")
+ return TDEGlobalSettings::highlightedTextColor();
+ if (!isActive && m_colorSettings.getColorTextValue(colorName) == "")
+ return getMarkedForegroundColor(true);
+ return m_colorSettings.getColorValue(colorName);
+}
+
+TQColor KrColorCacheImpl::getMarkedBackgroundColor(bool isActive) const
+{
+ if (isActive && m_colorSettings.getColorTextValue("Marked Background") == "")
+ return TDEGlobalSettings::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");
+}
+
+TQColor 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");
+}
+
+TQColor KrColorCacheImpl::getCurrentForegroundColor(bool isActive) const
+{
+ TQColor color = m_colorSettings.getColorValue("Current Foreground");
+ if (!isActive) SETCOLOR(color, m_colorSettings.getColorValue("Inactive Current Foreground"));
+ return color;
+}
+
+TQColor KrColorCacheImpl::getCurrentBackgroundColor(bool isActive) const
+{
+ if (isActive && m_colorSettings.getColorTextValue("Current Background") == "")
+ return TQColor();
+ 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");
+}
+
+TQColor KrColorCacheImpl::getCurrentMarkedForegroundColor(bool isActive) const
+{
+ TQString colorName = isActive?"Marked Current Foreground":"Inactive Marked Current Foreground";
+ if (isActive && m_colorSettings.getColorTextValue(colorName) == "")
+ return TQColor();
+ 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);
+}
+
+TQColor KrColorCacheImpl::dimColor(TQColor color, bool /* isBackgroundColor */) const
+{
+ krConfig->setGroup("Colors");
+ int dimFactor = m_colorSettings.getNumValue("Dim Factor", 100);
+ TQColor targetColor = m_colorSettings.getColorValue("Dim Target Color");
+ if (!targetColor.isValid())
+ targetColor = TQColor(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(TQColorGroup & 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 TQColorGroup & col = m_impl->m_cachedColors[hashKey];
+
+ // copy colors in question to result color group
+ result.setColor(TQColorGroup::Base, col.base());
+ result.setColor(TQColorGroup::Background, col.base());
+ result.setColor(TQColorGroup::Text, col.text());
+ result.setColor(TQColorGroup::HighlightedText, col.highlightedText());
+ result.setColor(TQColorGroup::Highlight, col.highlight());
+}
+
+TQColor KrColorCache::dimColor(const TQColor & color, int dim, const TQColor & targetColor)
+{
+ return TQColor((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/src/app/Panel/krcolorcache.h b/src/app/Panel/krcolorcache.h
new file mode 100644
index 0000000..8b401ee
--- /dev/null
+++ b/src/app/Panel/krcolorcache.h
@@ -0,0 +1,102 @@
+#ifndef KRCOLORCACHE_H
+#define KRCOLORCACHE_H
+
+#include <tqobject.h>
+#include <tqdict.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(TQColor()) should be called.
+*/
+class KrColorSettings
+{
+ class KrColorSettingsImpl * m_impl;
+public:
+ KrColorSettings();
+ KrColorSettings(const KrColorSettings &);
+ ~KrColorSettings();
+ const KrColorSettings & operator= (const KrColorSettings &);
+
+ static bool isColorNameValid(const TQString & settingName);
+ static TQValueList<TQString> getColorNames();
+ bool setColorValue(const TQString & settingName, const TQColor & color);
+ TQColor getColorValue(const TQString & settingName) const;
+ bool setColorTextValue(const TQString & settingName, const TQString & colorText);
+ TQString getColorTextValue(const TQString & settingName) const;
+
+ static bool isNumNameValid(const TQString & settingName);
+ static TQValueList<TQString> getNumNames();
+ bool setNumValue(const TQString & settingName, int value);
+ int getNumValue(const TQString & settingName, int defaultValue = 0) const;
+
+ static bool isBoolNameValid(const TQString & settingName);
+ static TQValueList<TQString> getBoolNames();
+ bool setBoolValue(const TQString & settingName, bool value);
+ int getBoolValue(const TQString & 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 TQObject
+{
+ TQ_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(TQColorGroup & result, const KrColorItemType & type) const;
+ static TQColor dimColor(const TQColor & color, int dim, const TQColor & targetColor);
+public slots:
+ void refreshColors();
+ void setColors(const KrColorSettings &);
+signals:
+ void colorsRefreshed();
+};
+
+#endif
diff --git a/src/app/Panel/krdetailedview.cpp b/src/app/Panel/krdetailedview.cpp
new file mode 100644
index 0000000..c8c9bbb
--- /dev/null
+++ b/src/app/Panel/krdetailedview.cpp
@@ -0,0 +1,1588 @@
+/***************************************************************************
+ 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 <tqlayout.h>
+#include <tqdir.h>
+#include <tqwhatsthis.h>
+#include <tqheader.h>
+#include <tqstyle.h>
+#include <kprogress.h>
+#include <kstatusbar.h>
+#include <kinputdialog.h>
+#include <tdemessagebox.h>
+#include <tdelocale.h>
+#include <tdepopupmenu.h>
+#include <tqdict.h>
+
+//////////////////////////////////////////////////////////////////////////
+// The following is KrDetailedView's settings in TDEConfig:
+// 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
+
+TQString KrDetailedView::ColumnName[ KrDetailedViewProperties::MAX_COLUMNS ];
+
+KrDetailedView::KrDetailedView( TQWidget *parent, bool &left, TDEConfig *cfg, const char *name ) :
+ TDEListView( parent, name ), KrView( cfg ), _currDragItem( 0L ), currentlyRenamedItem( 0 ),
+ pressedItem( 0 ) {
+ setWidget( this );
+ _nameInTDEConfig=TQString( "KrDetailedView" ) + TQString( ( 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 TDEConfigGroupSaver will work correctly!
+ TDEConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ setFont( _config->readFontEntry( "Filelist Font", _FilelistFont ) );
+ // decide on single click/double click selection
+ if ( _config->readBoolEntry( "Single Click Selects", _SingleClickSelects ) &&
+ TDEGlobalSettings::singleClick() ) {
+ connect( this, TQ_SIGNAL( executed( TQListViewItem* ) ), this, TQ_SLOT( slotExecuted( TQListViewItem* ) ) );
+ } else {
+ connect( this, TQ_SIGNAL( clicked( TQListViewItem* ) ), this, TQ_SLOT( slotClicked( TQListViewItem* ) ) );
+ connect( this, TQ_SIGNAL( doubleClicked( TQListViewItem* ) ), this, TQ_SLOT( slotDoubleClicked( TQListViewItem* ) ) );
+ }
+
+ // a change in the selection needs to update totals
+ connect( this, TQ_SIGNAL( onItem( TQListViewItem* ) ), this, TQ_SLOT( slotItemDescription( TQListViewItem* ) ) );
+ connect( this, TQ_SIGNAL( contextMenuRequested( TQListViewItem*, const TQPoint&, int ) ),
+ this, TQ_SLOT( handleContextMenu( TQListViewItem*, const TQPoint&, int ) ) );
+ connect( this, TQ_SIGNAL( rightButtonPressed(TQListViewItem*, const TQPoint&, int)),
+ this, TQ_SLOT(slotRightButtonPressed(TQListViewItem*, const TQPoint&, int)));
+ connect( this, TQ_SIGNAL( currentChanged( TQListViewItem* ) ), this, TQ_SLOT( setNameToMakeCurrent( TQListViewItem* ) ) );
+ connect( this, TQ_SIGNAL( currentChanged( TQListViewItem* ) ), this, TQ_SLOT( transformCurrentChanged( TQListViewItem* ) ) );
+ connect( this, TQ_SIGNAL( mouseButtonClicked ( int, TQListViewItem *, const TQPoint &, int ) ),
+ this, TQ_SLOT( slotMouseClicked ( int, TQListViewItem *, const TQPoint &, int ) ) );
+ connect( &KrColorCache::getColorCache(), TQ_SIGNAL( colorsRefreshed() ), this, TQ_SLOT( refreshColors() ) );
+ connect( header(), TQ_SIGNAL(clicked(int)), this, TQ_SLOT(sortOrderChanged(int )));
+ }
+
+ // add whatever columns are needed to the listview
+ krConfig->setGroup( nameInTDEConfig() );
+
+ newColumn( KrDetailedViewProperties::Name ); // we always have a name
+ setColumnWidthMode( COLUMN(Name), TQListView::Manual );
+ if ( _config->readBoolEntry( "Ext Column", _ExtColumn ) ) {
+ newColumn( KrDetailedViewProperties::Extention );
+ setColumnWidthMode( COLUMN(Extention), TQListView::Manual );
+ setColumnWidth( COLUMN(Extention), TQFontMetrics( font() ).width( "tar.bz2" ) );
+ }
+ if ( _config->readBoolEntry( "Mime Column", _MimeColumn ) ) {
+ newColumn( KrDetailedViewProperties::Mime );
+ setColumnWidthMode( COLUMN(Mime), TQListView::Manual );
+ setColumnWidth( COLUMN(Mime), TQFontMetrics( font() ).width( 'X' ) * 6 );
+ }
+ if ( _config->readBoolEntry( "Size Column", _SizeColumn ) ) {
+ newColumn( KrDetailedViewProperties::Size );
+ setColumnWidthMode( COLUMN(Size), TQListView::Manual );
+ setColumnWidth( COLUMN(Size), TQFontMetrics( font() ).width( "9" ) * 10 );
+ setColumnAlignment( COLUMN(Size), TQt::AlignRight ); // right-align numbers
+ }
+ if ( _config->readBoolEntry( "DateTime Column", _DateTimeColumn ) ) {
+ newColumn( KrDetailedViewProperties::DateTime );
+ setColumnWidthMode( COLUMN(DateTime), TQListView::Manual );
+ //setColumnWidth( column( DateTime ), TQFontMetrics( font() ).width( "99/99/99 99:99" ) );
+ setColumnWidth( COLUMN(DateTime), TQFontMetrics( font() ).width( TDEGlobal::locale() ->formatDateTime(
+ TQDateTime ( TQDate( 2099, 12, 29 ), TQTime( 23, 59 ) ) ) ) + 3 );
+ }
+ if ( _config->readBoolEntry( "Perm Column", _PermColumn ) ) {
+ newColumn( KrDetailedViewProperties::Permissions );
+ setColumnWidthMode( COLUMN(Permissions), TQListView::Manual );
+ setColumnWidth( COLUMN(Permissions), TQFontMetrics( font() ).width( "drwxrwxrwx" ) );
+ }
+ if ( _config->readBoolEntry( "KrPerm Column", _KrPermColumn ) ) {
+ newColumn( KrDetailedViewProperties::KrPermissions );
+ setColumnWidthMode( COLUMN(KrPermissions), TQListView::Manual );
+ setColumnWidth( COLUMN(KrPermissions), TQFontMetrics( font() ).width( "RWX" ) );
+ }
+ if ( _config->readBoolEntry( "Owner Column", _OwnerColumn ) ) {
+ newColumn( KrDetailedViewProperties::Owner );
+ setColumnWidthMode( COLUMN(Owner), TQListView::Manual );
+ setColumnWidth( COLUMN(Owner), TQFontMetrics( font() ).width( 'X' ) * 6 );
+ }
+ if ( _config->readBoolEntry( "Group Column", _GroupColumn ) ) {
+ newColumn( KrDetailedViewProperties::Group );
+ setColumnWidthMode( COLUMN(Group), TQListView::Manual );
+ setColumnWidth( COLUMN(Group), TQFontMetrics( font() ).width( 'X' ) * 6 );
+ }
+
+ // determine basic settings for the listview
+ setAcceptDrops( true );
+ setDragEnabled( true );
+ setTooltipColumn( COLUMN(Name) );
+ setDropVisualizer(false);
+ setDropHighlighter(true);
+ setSelectionModeExt( TDEListView::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(), TQ_SIGNAL( done( TQListViewItem *, int ) ),
+ this, TQ_SLOT( inplaceRenameFinished( TQListViewItem*, int ) ) );
+ connect( &renameTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( renameCurrentItem() ) );
+ connect( &contextMenuTimer, TQ_SIGNAL (timeout()), this, TQ_SLOT (showContextMenu()));
+
+ connect( header(), TQ_SIGNAL(clicked(int)), this, TQ_SLOT(slotSortOrderChanged(int )));
+
+ setFocusPolicy( TQWidget::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 ) {
+ TQString size = KRpermHandler::parseSize( vf->vfile_getSize() );
+ TQString 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 ) {
+ TQListViewItem * viewItem = dynamic_cast<TQListViewItem*>( item );
+ if( viewItem == currentlyRenamedItem ) {
+ currentlyRenamedItem = 0;
+ TQKeyEvent escEvent( TQEvent::KeyPress, Key_Escape, 27, 0 );
+ TQApplication::sendEvent( renameLineEdit(), &escEvent );
+ }
+ }
+ /* KDE HACK END */
+ return true;
+}
+
+void KrDetailedView::addItems( vfs *v, bool addUpDir ) {
+ TQListViewItem * item = firstChild();
+ TQListViewItem *currentItem = item;
+ TQString size, name;
+
+ // add the up-dir arrow if needed
+ if ( addUpDir ) {
+ new KrDetailedViewItem( this, ( TQListViewItem* ) 0L, ( vfile* ) 0L );
+ }
+
+ // text for updating the status bar
+ TQString statusText = TQString("%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<TQListViewItem*>(dvitem);
+ statusText = dvitem->description();
+ }
+
+ cnt++;
+ }
+
+
+ // re-enable sorting
+ setSorting( cl, as );
+ sort();
+
+ if ( !currentItem )
+ currentItem = firstChild();
+ TDEListView::setCurrentItem( currentItem );
+ ensureItemVisible( currentItem );
+
+ op()->emitItemDescription( statusText );
+}
+
+TQString KrDetailedView::getCurrentItem() const {
+ TQListViewItem * it = currentItem();
+ if ( !it )
+ return TQString();
+ else
+ return dynamic_cast<KrViewItem*>( it ) ->name();
+}
+
+void KrDetailedView::setCurrentItem( const TQString& name ) {
+ KrDetailedViewItem * it = dynamic_cast<KrDetailedViewItem*>(_dict[ name ]);
+ if ( it )
+ TDEListView::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;
+ TQKeyEvent escEvent( TQEvent::KeyPress, Key_Escape, 27, 0 );
+ TQApplication::sendEvent( renameLineEdit(), &escEvent );
+ }
+ /* KDE HACK END */
+
+ op()->emitSelectionChanged(); /* to avoid rename crash at refresh */
+ TDEListView::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 );
+ TDEListView::sort();
+}
+
+void KrDetailedView::slotClicked( TQListViewItem *item ) {
+ if ( !item ) return ;
+
+ if ( !modifierPressed ) {
+ if ( singleClicked && !renameTimer.isActive() ) {
+ TDEConfig * config = TDEGlobal::config();
+ config->setGroup( "KDE" );
+ int doubleClickInterval = config->readNumEntry( "DoubleClickInterval", 400 );
+
+ int msecsFromLastClick = clickTime.msecsTo( TQTime::currentTime() );
+
+ if ( msecsFromLastClick > doubleClickInterval && msecsFromLastClick < 5 * doubleClickInterval ) {
+ singleClicked = false;
+ renameTimer.start( doubleClickInterval, true );
+ return ;
+ }
+ }
+
+ CANCEL_TWO_CLICK_RENAME;
+ singleClicked = true;
+ clickTime = TQTime::currentTime();
+ clickedItem = item;
+ }
+}
+
+void KrDetailedView::slotDoubleClicked( TQListViewItem *item ) {
+ CANCEL_TWO_CLICK_RENAME;
+ if ( !item )
+ return ;
+ TQString 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();
+ TDEConfigGroupSaver 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( TQListViewItem * item ) {
+ KrViewItem * it = static_cast<KrDetailedViewItem*>( item );
+ if ( !it )
+ return ;
+ TQString desc = it->description();
+ op()->emitItemDescription(desc);
+}
+
+void KrDetailedView::handleQuickSearchEvent( TQKeyEvent * e ) {
+ switch ( e->key() ) {
+ case Key_Insert:
+ {
+ TQKeyEvent ev = TQKeyEvent( TQKeyEvent::KeyPress, Key_Space, 0, 0 );
+ TDEListView::keyPressEvent( & ev );
+ ev = TQKeyEvent( TQKeyEvent::KeyPress, Key_Down, 0, 0 );
+ keyPressEvent( & ev );
+ break;
+ }
+ case Key_Home:
+ {
+ TQListView::setCurrentItem( firstChild() );
+ TQKeyEvent ev = TQKeyEvent( TQKeyEvent::KeyPress, Key_Down, 0, 0 );
+ keyPressEvent( & ev );
+ break;
+ }
+ case Key_End:
+ {
+ TQListView::setCurrentItem( firstChild() );
+ TQKeyEvent ev = TQKeyEvent( TQKeyEvent::KeyPress, Key_Up, 0, 0 );
+ keyPressEvent( & ev );
+ break;
+ }
+ }
+}
+
+
+void KrDetailedView::slotCurrentChanged( TQListViewItem * item ) {
+ CANCEL_TWO_CLICK_RENAME;
+ if ( !item )
+ return ;
+ _nameToMakeCurrent = static_cast<KrDetailedViewItem*>( item ) ->name();
+}
+
+void KrDetailedView::contentsMousePressEvent( TQMouseEvent * e ) {
+ bool callDefaultHandler = true, processEvent = true, selectionChanged = false;
+ pressedItem = 0;
+
+ TQListViewItem * oldCurrent = currentItem();
+ TQListViewItem *newCurrent = itemAt( contentsToViewport( e->pos() ) );
+ if (e->button() == TQt::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() == TQt::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
+ TDEConfigGroupSaver 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()->useTQTSelection()){
+ if ( oldCurrent && newCurrent && oldCurrent != newCurrent && e->state() & ShiftButton ) {
+ int oldPos = oldCurrent->itemPos();
+ int newPos = newCurrent->itemPos();
+ TQListViewItem *top = 0, *bottom = 0;
+ if ( oldPos > newPos ) {
+ top = newCurrent;
+ bottom = oldCurrent;
+ } else {
+ top = oldCurrent;
+ bottom = newCurrent;
+ }
+ TQListViewItemIterator it( top );
+ for ( ; it.current(); ++it ) {
+ if ( !it.current() ->isSelected() ) {
+ it.current() ->setSelected( true );
+ selectionChanged = true;
+ }
+ if ( it.current() == bottom )
+ break;
+ }
+ TQListView::setCurrentItem( newCurrent );
+ callDefaultHandler = false;
+ }
+ }
+
+ if (selectionChanged)
+ updateView(); // don't call triggerUpdate directly!
+
+ // TQListViewItem * i = itemAt( contentsToViewport( e->pos() ) );
+ if (callDefaultHandler)
+ {
+ dragStartPos = TQPoint( -1, -1 );
+
+ TQString name = TQString(); // will the file be deleted by the mouse event?
+ if( newCurrent ) // save the name of the file
+ name = static_cast<KrDetailedViewItem*>( newCurrent ) ->name();
+
+ TDEListView::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 TQListView::contentsMousePressEvent();
+ // the right click signal is not emitted as it is used for selection
+
+ TQPoint 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) TQListView::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( TQMouseEvent * e ) {
+ if (e->button() == TQt::RightButton)
+ contextMenuTimer.stop();
+ TDEListView::contentsMouseReleaseEvent( e );
+
+ if( pressedItem ) {
+ TQPoint vp = contentsToViewport( e->pos() );
+ TQListViewItem *newCurrent = itemAt( vp );
+
+ if( pressedItem == newCurrent ) {
+ // emitting the missing signals from TQListView::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 ( TQMouseEvent * e ) {
+ if ( ( singleClicked || renameTimer.isActive() ) && itemAt( contentsToViewport( e->pos() ) ) != clickedItem )
+ CANCEL_TWO_CLICK_RENAME;
+ if ( dragStartPos != TQPoint( -1, -1 ) &&
+ e->state() & TQt::LeftButton && ( dragStartPos - e->pos() ).manhattanLength() > TQApplication::startDragDistance() )
+ startDrag();
+ if (KrSelectionMode::getSelectionHandler()->rightButtonPreservesSelection()
+ && KrSelectionMode::getSelectionHandler()->rightButtonSelects()
+ && KrSelectionMode::getSelectionHandler()->showContextMenu() >= 0 && e->state() == TQt::RightButton)
+ {
+ TQListViewItem *newItem = itemAt( contentsToViewport( e->pos() ) );
+ e->accept();
+ if (newItem != lastSwushPosition && newItem)
+ {
+ // is the new item above or below the previous one?
+ TQListViewItem * above = newItem;
+ TQListViewItem * 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 TQListView::contentsMouseMoveEvent();
+ if( newItem )
+ emit onItem( newItem );
+ else
+ emit onViewport();
+ }
+ else
+ TDEListView::contentsMouseMoveEvent( e );
+}
+
+void KrDetailedView::contentsWheelEvent( TQWheelEvent * e ) {
+ if ( !_focused )
+ op()->emitNeedFocus();
+ TDEListView::contentsWheelEvent( e );
+}
+
+void KrDetailedView::handleContextMenu( TQListViewItem * it, const TQPoint & pos, int ) {
+ if ( !_focused )
+ op()->emitNeedFocus();
+ if ( !it )
+ return ;
+ if ( static_cast<KrDetailedViewItem*>( it ) ->
+ name() == ".." )
+ return ;
+ int i = KrSelectionMode::getSelectionHandler()->showContextMenu();
+ contextMenuPoint = TQPoint( 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 TQPoint & vp ) {
+ return dynamic_cast<KrViewItem*>( TDEListView::itemAt( vp ) );
+}
+
+bool KrDetailedView::acceptDrag( TQDropEvent* ) const {
+ return true;
+}
+
+TQRect KrDetailedView::drawItemHighlighter(TQPainter *painter, TQListViewItem *item)
+{
+ TQRect r;
+ if( _currDragItem && item ) {
+ r = itemRect(item);
+
+ if (painter)
+ style().drawPrimitive(TQStyle::PE_FocusRect, painter, r, colorGroup(),
+ TQStyle::Style_FocusAtBorder, colorGroup().highlight());
+ }
+ return r;
+}
+
+void KrDetailedView::contentsDropEvent( TQDropEvent * e ) {
+ e->setPoint( contentsToViewport( e->pos() ) );
+ op()->emitGotDrop(e);
+ e->ignore();
+ TDEListView::contentsDropEvent( e );
+}
+
+void KrDetailedView::contentsDragMoveEvent( TQDragMoveEvent * e ) {
+ _currDragItem = getKrViewItemAt(contentsToViewport(e->pos()));
+ if( _currDragItem && !_currDragItem->VF->vfile_isDir() )
+ _currDragItem = 0;
+
+ TDEListView::contentsDragMoveEvent( e );
+}
+
+void KrDetailedView::imStartEvent(TQIMEvent* e)
+{
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ ACTIVE_PANEL->quickSearch->myIMStartEvent( e );
+ return ;
+ }else {
+ TDEConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ if ( !_config->readBoolEntry( "New Style Quicksearch", _NewStyleQuicksearch ) )
+ TDEListView::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(TQIMEvent* e)
+{
+ if ( ACTIVE_PANEL->quickSearch->isShown() ) {
+ ACTIVE_PANEL->quickSearch->myIMEndEvent( e );
+ return ;
+ }
+}
+
+void KrDetailedView::imComposeEvent(TQIMEvent* 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( TQKeyEvent * 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()->useTQTSelection()) {
+ TQListViewItem * i = currentItem();
+ if ( !i ) break;
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected() );
+ i = i->itemAbove();
+ if ( i ) {
+ TQListView::setCurrentItem( i );
+ TQListView::ensureItemVisible( i );
+ }
+ } else TDEListView::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()->useTQTSelection()){
+ TQListViewItem * i = currentItem();
+ if ( !i ) break;
+ if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected() );
+ i = i->itemBelow();
+ if ( i ) {TQListView::setCurrentItem( i ); TQListView::ensureItemVisible( i ); }
+ } else TDEListView::keyPressEvent(e);
+ break;
+ case Key_Next: if (!KrSelectionMode::getSelectionHandler()->useTQTSelection()){
+ TQListViewItem * i = currentItem(), *j;
+ if ( !i ) break;
+ TQRect r( itemRect( i ) );
+ if ( !r.height() ) break;
+ for ( int page = visibleHeight() / r.height() - 1; page > 0 && ( j = i->itemBelow() ); --page )
+ i = j;
+ if ( i ) {TQListView::setCurrentItem( i ); TQListView::ensureItemVisible( i ); }
+ } else TDEListView::keyPressEvent(e);
+ break;
+ case Key_Prior: if (!KrSelectionMode::getSelectionHandler()->useTQTSelection()){
+ TQListViewItem * i = currentItem(), *j;
+ if ( !i ) break;
+ TQRect r( itemRect( i ) );
+ if ( !r.height() ) break;
+ for ( int page = visibleHeight() / r.height() - 1; page > 0 && ( j = i->itemAbove() ); --page )
+ i = j;
+ if ( i ) {TQListView::setCurrentItem( i ); TQListView::ensureItemVisible( i ); }
+ } else TDEListView::keyPressEvent(e);
+ break;
+ case Key_Home: if (!KrSelectionMode::getSelectionHandler()->useTQTSelection()){
+ if ( e->state() & ShiftButton ) /* Shift+Home */
+ {
+ clearSelection();
+ TDEListView::keyPressEvent( e );
+ op()->emitSelectionChanged();
+ triggerUpdate();
+ break;
+ } else {
+ TQListViewItem * i = firstChild();
+ if ( i ) {TQListView::setCurrentItem( i ); TQListView::ensureItemVisible( i ); }
+ }
+ } else TDEListView::keyPressEvent(e);
+ break;
+ case Key_End: if (!KrSelectionMode::getSelectionHandler()->useTQTSelection()){
+ if ( e->state() & ShiftButton ) /* Shift+End */
+ {
+ clearSelection();
+ TDEListView::keyPressEvent( e );
+ op()->emitSelectionChanged();
+ triggerUpdate();
+ break;
+ } else {
+ TQListViewItem *i = firstChild(), *j;
+ while ( ( j = i->nextSibling() ) )
+ i = j;
+ while ( ( j = i->itemBelow() ) )
+ i = j;
+ if ( i ) {TQListView::setCurrentItem( i ); TQListView::ensureItemVisible( i ); }
+ break;
+ }
+ } else TDEListView::keyPressEvent(e);
+ break;
+ case Key_Enter :
+ case Key_Return : {
+ if ( e->state() & ControlButton ) // let the panel handle it
+ e->ignore();
+ else {
+ KrViewItem * i = getCurrentKrViewItem();
+ TQString 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,
+ TQString 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();
+ TQString mime = ((vfile *)(i->VF))->vfile_getMime();
+ TQString 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 :
+ //TDEListView::keyPressEvent( e );
+ //break;
+/*#ifndef _newSelectionHandling
+ case Key_Down :
+ if ( e->state() == ControlButton ) { // let the panel handle it
+ e->ignore();
+ break;
+ } else
+ TDEListView::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())
+ TDEListView::keyPressEvent( e );
+ else
+ {
+ TQKeyEvent ev = TQKeyEvent( TQKeyEvent::KeyPress, Key_Space, 0, 0 );
+ TDEListView::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())
+ {
+ TQKeyEvent ev = TQKeyEvent( TQKeyEvent::KeyPress, Key_Insert, 0, 0 );
+ TDEListView::keyPressEvent( & ev );
+ }
+ else
+ TDEListView::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.
+ //
+ TDEIO::filesize_t totalSize = 0;
+ unsigned long totalFiles = 0, totalDirs = 0;
+ TQStringList 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())
+ {
+ TQKeyEvent ev = TQKeyEvent( TQKeyEvent::KeyPress, Key_Insert, 0, 0 );
+ TDEListView::keyPressEvent( & ev );
+ }
+ else
+ TDEListView::keyPressEvent( e );
+ }
+ break;
+ case Key_A : // mark all
+ if ( e->state() == ControlButton ) {
+ TDEListView::keyPressEvent( e );
+ updateView();
+ break;
+ }
+ default:
+ if ( e->key() == Key_Escape ) {
+ TQListView::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?
+ {
+ TDEConfigGroupSaver grpSvr( _config, "Look&Feel" );
+ if ( !_config->readBoolEntry( "New Style Quicksearch", _NewStyleQuicksearch ) )
+ TDEListView::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 );
+ }
+ TDEListView::keyPressEvent( e );
+ }
+ }
+ // emit the new item description
+ slotItemDescription( currentItem() ); // actually send the TQListViewItem
+}
+
+// overridden to make sure EXTENTION won't be lost during rename
+void KrDetailedView::rename( TQListViewItem * 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 ), TQString() );
+ repaintItem( item );
+ }
+
+ currentlyRenamedItem = item;
+ renameLineEdit()->setBackgroundMode(TQt::FixedColor);
+ renameLineEdit()->setPaletteBackgroundColor(TQt::white);
+ renameLineEdit()->setPaletteForegroundColor(TQt::black);
+ TDEListView::rename( item, c );
+ renameLineEdit() ->selectAll();
+}
+
+void KrDetailedView::renameCurrentItem() {
+ int c;
+ TQString 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<TQListViewItem*>( it ), c );
+ // if applicable, select only the name without extension
+ TDEConfigGroupSaver 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( TQListViewItem * 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
+
+ TQString 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 TQString & str, int direction ) {
+ KrViewItem * item = getCurrentKrViewItem();
+ if (!item)
+ return;
+ TDEConfigGroupSaver 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( TQKeyEvent * 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( TQListViewItem * it ) {
+ if (!it) return;
+ KrView::setNameToMakeCurrent( static_cast<KrDetailedViewItem*>( it ) ->name() );
+}
+
+void KrDetailedView::slotMouseClicked( int button, TQListViewItem * item, const TQPoint&, int ) {
+ pressedItem = 0; // if the signals are emitted, don't emit twice at contentsMouseReleaseEvent
+ if ( button == TQt::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 );
+ TQColorGroup 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( TDEGlobalSettings::baseColor() );
+ // Set the alternate color to its default or to an invalid color, to turn alternate the background off.
+ setAlternateBackground( alternateBackgroundEnabled ? TDEGlobalSettings::alternateBackgroundColor() : TQColor() );
+ }
+}
+
+bool KrDetailedView::event( TQEvent *e ) {
+ modifierPressed = false;
+
+ switch ( e->type() ) {
+ case TQEvent::Timer:
+ case TQEvent::MouseMove:
+ case TQEvent::MouseButtonPress:
+ case TQEvent::MouseButtonRelease:
+ break;
+ default:
+ CANCEL_TWO_CLICK_RENAME;
+ }
+ return TDEListView::event( e );
+}
+
+bool KrDetailedView::eventFilter( TQObject * watched, TQEvent * e )
+{
+ if( watched == renameLineEdit() )
+ {
+ if( currentlyRenamedItem && e->type() == TQEvent::Hide )
+ {
+ /* checking if the currentlyRenamedItem pointer is valid (vfs_refresh can delete this item) */
+ for( TQListViewItem *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() == TQEvent::MouseButtonPress && ((TQMouseEvent *)e )->button() == TQt::RightButton )
+ {
+ selectColumns();
+ return true;
+ }
+ return false;
+ }
+ return TDEListView::eventFilter( watched, e );
+}
+
+void KrDetailedView::makeItemVisible( const KrViewItem *item ) {
+// tqApp->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);
+ // tdelistview emits selection changed, so chain them to operator
+ connect(this, TQ_SIGNAL(selectionChanged()), _operator, TQ_SIGNAL(selectionChanged()));
+}
+
+void KrDetailedView::initProperties() {
+ _properties = new KrDetailedViewProperties;
+ TDEConfigGroupSaver 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 = TQString( "a" ).localeAwareCompare( "B" ) > 0; // see KDE bug #40131
+ TQStringList defaultAtomicExtensions;
+ defaultAtomicExtensions += ".tar.gz";
+ defaultAtomicExtensions += ".tar.bz2";
+ defaultAtomicExtensions += ".moc.cpp";
+ defaultAtomicExtensions += ".tar.xz";
+ TQStringList atomicExtensions = krConfig->readListEntry("Atomic Extensions", defaultAtomicExtensions);
+ for (TQStringList::iterator i = atomicExtensions.begin(); i != atomicExtensions.end(); )
+ {
+ TQString & 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()
+{
+ TDEPopupMenu 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(TQCursor::pos());
+
+ krConfig->setGroup( nameInTDEConfig() );
+
+ 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;
+ TQTimer::singleShot( 0, p, TQ_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(TQListViewItem*, const TQPoint& 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: tqFatal("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/src/app/Panel/krdetailedview.h b/src/app/Panel/krdetailedview.h
new file mode 100644
index 0000000..4d8c8b2
--- /dev/null
+++ b/src/app/Panel/krdetailedview.h
@@ -0,0 +1,181 @@
+/***************************************************************************
+ 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 <tdelistview.h>
+#include <ksqueezedtextlabel.h>
+#include <tdelocale.h>
+#include <tqwidget.h>
+#include <tqtimer.h>
+#include <tqdatetime.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 TQDragMoveEvent;
+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 *TDEListView. 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 TDEListView, public KrView {
+ TQ_OBJECT
+
+ friend class KrDetailedViewItem;
+
+public:
+ KrDetailedView( TQWidget *parent, bool &left, TDEConfig *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<TDEListViewItem*>( current ) ->itemBelow() ); }
+ virtual inline KrViewItem *getPrev( KrViewItem *current ) { return dynamic_cast<KrViewItem*>( dynamic_cast<TDEListViewItem*>( current ) ->itemAbove() ); }
+ virtual inline KrViewItem *getCurrentKrViewItem() { return dynamic_cast<KrViewItem*>( currentItem() ); }
+ virtual KrViewItem *getKrViewItemAt( const TQPoint &vp );
+ virtual inline KrViewItem *findItemByName( const TQString &name ) { return dynamic_cast<KrViewItem*>( findItem( name, 0 ) ); }
+ virtual void addItems( vfs *v, bool addUpDir = true );
+ virtual TQString getCurrentItem() const;
+ virtual void makeItemVisible( const KrViewItem *item );
+ virtual void setCurrentItem( const TQString& name );
+ virtual void updateView();
+ virtual void updateItem(KrViewItem* item);
+ virtual void clear();
+ virtual void sort() { TDEListView::sort(); }
+ virtual void setSortMode( KrViewProperties::SortSpec mode );
+ virtual void prepareForActive();
+ virtual void prepareForPassive();
+ virtual inline void saveSettings() { TDEListView::saveLayout( _config, nameInTDEConfig() ); }
+ virtual inline void restoreSettings() { TDEListView::restoreLayout( _config, nameInTDEConfig() ); }
+
+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( TQKeyEvent *e );
+ virtual void imStartEvent( TQIMEvent* e );
+ virtual void imEndEvent( TQIMEvent *e );
+ virtual void imComposeEvent( TQIMEvent *e );
+ virtual void contentsMousePressEvent( TQMouseEvent *e );
+ virtual void contentsMouseReleaseEvent (TQMouseEvent *e);
+ virtual void contentsMouseMoveEvent ( TQMouseEvent * e );
+ virtual void contentsWheelEvent( TQWheelEvent *e );
+ virtual bool acceptDrag( TQDropEvent* e ) const;
+ virtual void contentsDropEvent( TQDropEvent *e );
+ virtual void contentsDragMoveEvent( TQDragMoveEvent *e );
+ virtual TQRect drawItemHighlighter(TQPainter *painter, TQListViewItem *item);
+ virtual void startDrag() { op()->startDrag(); }
+ virtual bool event( TQEvent *e );
+ virtual bool eventFilter( TQObject * watched, TQEvent * e );
+
+protected slots:
+ void rename( TQListViewItem *item, int c );
+ void slotClicked( TQListViewItem *item );
+ void slotDoubleClicked( TQListViewItem *item );
+ void slotItemDescription( TQListViewItem *item );
+ void slotCurrentChanged( TQListViewItem *item );
+ void handleContextMenu( TQListViewItem*, const TQPoint&, int );
+ virtual void renameCurrentItem();
+ virtual void showContextMenu( );
+ void inplaceRenameFinished( TQListViewItem *it, int col );
+ void setNameToMakeCurrent( TQListViewItem *it );
+ void sortOrderChanged(int);
+ void slotRightButtonPressed(TQListViewItem*, const TQPoint& point, int);
+ void slotSortOrderChanged(int col);
+ void transformCurrentChanged( TQListViewItem * item ) { emit currentChanged( dynamic_cast<KrViewItem *>(item ) ); }
+
+ /**
+ * used internally to produce the signal middleButtonClicked()
+ */
+ void slotMouseClicked( int button, TQListViewItem * item, const TQPoint & pos, int c );
+ inline void slotExecuted( TQListViewItem* i ) {
+ TQString tmp = dynamic_cast<KrViewItem*>( i ) ->name();
+ op()->emitExecuted( tmp );
+ }
+
+public slots:
+ void refreshColors();
+ void quickSearch( const TQString &, int = 0 );
+ void stopQuickSearch( TQKeyEvent* );
+ void handleQuickSearchEvent( TQKeyEvent* );
+
+private:
+ static TQString ColumnName[ KrDetailedViewProperties::MAX_COLUMNS ];
+ bool swushSelects;
+ TQPoint dragStartPos;
+ TQListViewItem *lastSwushPosition;
+ bool caseSensitiveSort;
+ KrViewItem *_currDragItem;
+ bool singleClicked;
+ bool modifierPressed;
+ TQTime clickTime;
+ TQListViewItem *clickedItem;
+ TQTimer renameTimer;
+ TQTimer contextMenuTimer;
+ TQPoint contextMenuPoint;
+ TQListViewItem *currentlyRenamedItem;
+ TQListViewItem *pressedItem;
+};
+
+#endif /* KRDETAILEDVIEW_H */
diff --git a/src/app/Panel/krdetailedviewitem.cpp b/src/app/Panel/krdetailedviewitem.cpp
new file mode 100644
index 0000000..1c1c5e9
--- /dev/null
+++ b/src/app/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 <tqpainter.h>
+#include <pwd.h>
+#include <grp.h>
+#include <stdlib.h>
+#include <tqpalette.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, TQListViewItem *after, vfile *vf):
+ TDEListViewItem(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) {
+ TDEConfigGroupSaver 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, TQString(), TQString(), 0);
+
+ setText(COLUMN(Name), "..");
+ setText(COLUMN(Size), i18n("<DIR>") );
+ if ( PROPS->displayIcons )
+ setPixmap( COLUMN(Name), FL_LOADICON( "go-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
+ TDEListViewItem::setup();
+ setHeight(expHeight);
+}
+#endif
+
+void KrDetailedViewItem::repaintItem() {
+ if ( dummyVfile ) return;
+ TQString 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 ? TDEIO::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=TQString();
+ 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
+ TQString 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
+}
+
+TQString num2qstring(TDEIO::filesize_t num){
+ TQString buf;
+ buf.sprintf("%025llu",num);
+ return buf;
+}
+
+void KrDetailedViewItem::paintCell(TQPainter *p, const TQColorGroup &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
+
+ TQColorGroup _cg(cg);
+
+ // This is ugly! I had to dublicate TDEListViewItem::paintCell() code, as the
+ // TDEListViewItem::paintCell() overwrites my color settings. So KrDetailedViewItem::paintCell
+ // must dublicate the TDEListViewItem::paintCell() code, do the required color settings
+ // and call TQListViewItem::paintCell() afterwards (the base class of TDEListViewItem).
+ // This tabooed in the object oriented heaven, but necessary here. Blame the KDE team for
+ // this really poor paintCell implementation!
+
+ const TQPixmap *pm = listView()->viewport()->backgroundPixmap();
+ if (pm && !pm->isNull())
+ {
+ _cg.setBrush(TQColorGroup::Base, TQBrush(backgroundColor(), *pm));
+ p->setBrushOrigin( -listView()->contentsX(), -listView()->contentsY() );
+ }
+ else if (isAlternate())
+ if (listView()->viewport()->backgroundMode()==TQt::FixedColor)
+ _cg.setColor(TQColorGroup::Background, static_cast< TDEListView* >(listView())->alternateBackground());
+ else
+ _cg.setColor(TQColorGroup::Base, static_cast< TDEListView* >(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))
+ TQListViewItem::paintCell(p, _cg, column, width, align);
+ else {
+ if (dummyVfile) {
+ TQListViewItem::paintCell(p, _cg, column, width, TQt::AlignHCenter); // updir
+ } else {
+ if (_vf->vfile_isDir() && _vf->vfile_getSize()<=0)
+ TQListViewItem::paintCell(p, _cg, column, width, TQt::AlignHCenter);
+ else TQListViewItem::paintCell(p, _cg, column, width, align); // size
+ }
+ }
+}
+
+const TQColor & KrDetailedViewItem::setColorIfContrastIsSufficient(const TQColor & background, const TQColor & color1, const TQColor & 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(TQListViewItem *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
+ TQString text0 = name();
+ TQString 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 TQString::compare(text0, itext0);
+ } else return TQString::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 {
+ TQString e1 = (!ignoreCase ? text(col) : text(col).lower());
+ TQString 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 TQString::compare(e1, e2);
+ } else return TQString::localeAwareCompare(e1, e2);
+ }
+}
+
+void KrDetailedViewItem::itemHeightChanged() {
+#ifdef FASTER
+ expHeight = 0;
+#endif
+}
diff --git a/src/app/Panel/krdetailedviewitem.h b/src/app/Panel/krdetailedviewitem.h
new file mode 100644
index 0000000..1bca596
--- /dev/null
+++ b/src/app/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 <tdelistview.h>
+#include <tqguardedptr.h>
+
+#define FASTER
+
+class TQPixmap;
+class KrDetailedView;
+
+class KrDetailedViewItem : public TDEListViewItem, public KrViewItem {
+friend class KrDetailedView;
+friend class KrCalcSpaceDialog;
+public:
+ KrDetailedViewItem(KrDetailedView *parent, TQListViewItem *after, vfile *vf);
+ inline bool isSelected() const { return TDEListViewItem::isSelected(); }
+ inline void setSelected(bool s) { TDEListViewItem::setSelected(s); }
+ int compare(TQListViewItem *i,int col,bool ascending ) const;
+ void paintCell(TQPainter *p, const TQColorGroup &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 TQString text(int column) const { return TDEListViewItem::text(column); }
+
+private:
+ static const TQColor & setColorIfContrastIsSufficient(const TQColor & background, const TQColor & color1, const TQColor & color2);
+#ifdef FASTER
+ bool initiated;
+ static int expHeight;
+#endif
+};
+
+#endif
diff --git a/src/app/Panel/krdrag.cpp b/src/app/Panel/krdrag.cpp
new file mode 100644
index 0000000..d886404
--- /dev/null
+++ b/src/app/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, TQWidget * dragSource, const char* name )
+{
+ // See KURLDrag::newDrag
+ TQStrList 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 TQStrList & urls, bool move, TQWidget * dragSource, const char* name )
+ : TQUriDrag( 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-tde-cutselection";
+ else if ( i == 2 )
+ return "text/plain";
+ else return 0;
+}
+
+TQByteArray KRDrag::encodedData( const char* mime ) const
+{
+ TQByteArray a;
+ TQCString mimetype( mime );
+ if ( mimetype == "text/uri-list" )
+ return TQUriDrag::encodedData( mime );
+ else if ( mimetype == "application/x-tde-cutselection" ) {
+ TQCString 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" )
+ {
+ TQStringList uris;
+ for (TQStrListIterator it(m_urls); *it; ++it)
+ uris.append(KURLDrag::stringToUrl(*it).prettyURL());
+ TQCString 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 TQMimeSource *e )
+{
+ TQByteArray a = e->encodedData( "application/x-tde-cutselection" );
+ if ( a.isEmpty() )
+ return false;
+ else
+ {
+ return (a.at(0) == '1'); // true if "1", or similar
+ }
+ }
+
+#include "krdrag.moc"
diff --git a/src/app/Panel/krdrag.h b/src/app/Panel/krdrag.h
new file mode 100644
index 0000000..8889bbe
--- /dev/null
+++ b/src/app/Panel/krdrag.h
@@ -0,0 +1,63 @@
+/***************************************************************************
+ 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 <tqdragobject.h>
+#include <kurl.h>
+
+class KRDrag : public TQUriDrag
+{
+ TQ_OBJECT
+
+public:
+ static KRDrag * newDrag( const KURL::List & urls, bool move, TQWidget * dragSource = 0, const char* name = 0 );
+
+protected:
+ KRDrag( const TQStrList & urls, bool move, TQWidget * dragSource, const char* name );
+
+public:
+ virtual ~KRDrag() {}
+
+ virtual const char* format( int i ) const;
+ virtual TQByteArray 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 TQMimeSource *e );
+
+protected:
+ bool m_bCutSelection;
+ TQStrList m_urls;
+};
+
+#endif /* KRDRAG_H */
diff --git a/src/app/Panel/krpopupmenu.cpp b/src/app/Panel/krpopupmenu.cpp
new file mode 100644
index 0000000..03c6f02
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <kprocess.h>
+#include <kshred.h>
+#include <krun.h>
+#include <kiconloader.h>
+#include <tdemessagebox.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 TQPoint &pos, ListPanel *panel) {
+ KrPopupMenu menu(panel);
+ int result = menu.exec(pos);
+ menu.performAction(result);
+}
+
+KrPopupMenu::KrPopupMenu(ListPanel *thePanel, TQWidget *parent) : TDEPopupMenu(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", TDEIcon::Panel ), i18n( "Open in New Tab" ) );
+ }
+ insertSeparator();
+ }
+
+ // ------------- Preview - normal vfs only ?
+ if ( panel->func->files()->vfs_getType() == vfs::NORMAL ) {
+ // create the preview popup
+ TQStringList 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 !
+ TQString 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 = TQString();
+ 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( TDEIcon::Small ), service->name() );
+ }
+ }
+ openWith.insertSeparator();
+ if ( vf->vfile_isDir() )
+ openWith.insertItem( krLoader->loadIcon( "konsole", TDEIcon::Small ), i18n( "Terminal" ), OPEN_TERM_ID );
+ openWith.insertItem( i18n( "Other..." ), CHOOSE_ID );
+ insertItem( TQPixmap(), &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 TDEActionCollection(this);
+ konqMenu = new KonqPopupMenu( KonqBookmarkManager::self(), _items, panel->func->files()->vfs_getOrigin(), *actions, 0, this,
+ KonqPopupMenu::NoFlags, KParts::BrowserExtension::DefaultPopupItems );
+ insertItem( TQPixmap(), 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
+ TDEConfigGroupSaver 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( TQPixmap(), &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", TDEIcon::Small ), i18n("Folder..."), MKDIR_ID);
+ createNewPopup.insertItem( krLoader->loadIcon( "text-plain", TDEIcon::Small ), i18n("Text File..."), NEW_TEXT_FILE_ID);
+
+ insertItem( TQPixmap(), &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()),
+ TQString(), 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 :
+ {
+ TQStringList 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 ) {
+ TQString name = ( *it2 ) ->name();
+ if( !selectedNames.contains( name ) )
+ selectedNames.append( name );
+ }
+ }
+ SLOTS->slotSynchronizeDirs( selectedNames );
+ }
+ break;
+ case OPEN_TERM_ID :
+ TQString save = getcwd( 0, 0 );
+ chdir( panel->func->files() ->vfs_getFile( item->name() ).path( -1 ).local8Bit() );
+ TDEProcess proc;
+ {
+ TDEConfigGroupSaver saver(krConfig, "General");
+ TQString 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( TDEProcess::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 ) {
+ TQStringList names;
+ panel->getSelectedNames( &names );
+ KRun::run( *( offers[ id - SERVICE_LIST_ID ].service() ),
+ *( panel->func->files() ->vfs_getFiles( &names ) ) );
+ }
+}
+
+#include "krpopupmenu.moc"
diff --git a/src/app/Panel/krpopupmenu.h b/src/app/Panel/krpopupmenu.h
new file mode 100644
index 0000000..a60d9b5
--- /dev/null
+++ b/src/app/Panel/krpopupmenu.h
@@ -0,0 +1,78 @@
+#ifndef KRPOPUPMENU_H
+#define KRPOPUPMENU_H
+
+#include <tdepopupmenu.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 TDEPopupMenu {
+ TQ_OBJECT
+
+public:
+ static void run(const TQPoint &pos, ListPanel *panel);
+
+protected:
+ KrPopupMenu(ListPanel *thePanel, TQWidget *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;
+ TDEPopupMenu openWith, linkPopup, createNewPopup;
+ KrPreviewPopup preview;
+ TDEActionCollection *actions;
+ KrViewItemList items; // list of selected items
+ KrViewItem *item; // the (first) selected item
+ KFileItemList _items;
+ TQValueList<KServiceOffer> offers;
+#ifdef __LIBKONQ__
+ KonqPopupMenu *konqMenu;
+#endif
+};
+
+#endif
diff --git a/src/app/Panel/krpreviewpopup.cpp b/src/app/Panel/krpreviewpopup.cpp
new file mode 100644
index 0000000..1a65540
--- /dev/null
+++ b/src/app/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 <tdeio/previewjob.h>
+#include "krpreviewpopup.h"
+#include <kdebug.h>
+#include <tdelocale.h>
+#include <keditcl.h>
+#include "../KViewer/krviewer.h"
+#include "../krusader.h"
+
+KrPreviewPopup::KrPreviewPopup(): id(1),noPreview(true){
+ connect(this,TQ_SIGNAL(activated(int)),this,TQ_SLOT(view(int)));
+}
+
+void KrPreviewPopup::setUrls(const KURL::List* urls){
+ //insertItem(i18n("Configure preview"),0);
+ insertItem(i18n("Preview not available"),0);
+
+ TDEIO::PreviewJob* pjob;
+ TQStringList plugins = TDEIO::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 TDEIO::PreviewJob(files,200,200,200,1,true,true,0);
+ connect(pjob,TQ_SIGNAL(gotPreview(const KFileItem*,const TQPixmap&)),
+ this,TQ_SLOT(addPreview(const KFileItem*,const TQPixmap&)));
+}
+
+KrPreviewPopup::~KrPreviewPopup(){}
+
+void KrPreviewPopup::addPreview(const KFileItem* file,const TQPixmap& 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/src/app/Panel/krpreviewpopup.h b/src/app/Panel/krpreviewpopup.h
new file mode 100644
index 0000000..7afdee2
--- /dev/null
+++ b/src/app/Panel/krpreviewpopup.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ 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 <tqpopupmenu.h>
+#include <tqpixmap.h>
+#include <tdefileitem.h>
+#include <kurl.h>
+
+/**
+ *@author Shie Erlich & Rafi Yanai
+ */
+
+class KrPreviewPopup : public TQPopupMenu {
+ TQ_OBJECT
+
+public:
+ KrPreviewPopup();
+ ~KrPreviewPopup();
+
+ void setUrls(const KURL::List* urls);
+public slots:
+ void addPreview(const KFileItem* file,const TQPixmap& preview);
+ void view(int id);
+
+protected:
+ KFileItemList files;
+ int id;
+ bool noPreview;
+ KURL::List availablePreviews;
+};
+
+#endif
diff --git a/src/app/Panel/krselectionmode.cpp b/src/app/Panel/krselectionmode.cpp
new file mode 100644
index 0000000..93a1deb
--- /dev/null
+++ b/src/app/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" );
+ TQString 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");
+ _useTQTSelection = krConfig->readBoolEntry("TQt Selection", _TQtSelection);
+ _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/src/app/Panel/krselectionmode.h b/src/app/Panel/krselectionmode.h
new file mode 100644
index 0000000..1e6770a
--- /dev/null
+++ b/src/app/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 useTQTSelection() { return _useTQTSelection; }
+ 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 _useTQTSelection, _spaceMovesDown, _insertMovesDown, _spaceCalculatesDiskSpace;
+ bool _rightButtonSelects, _leftButtonSelects, _rightButtonPreservesSelection;
+ bool _leftButtonPreservesSelection, _shiftCtrlRightButtonSelects, _shiftCtrlLeftButtonSelects;
+ int _showContextMenu;
+};
+
+class KonqSelectionMode : public KrSelectionMode {
+public:
+ void init() {
+ _useTQTSelection = 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() {
+ _useTQTSelection = 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() {
+ _useTQTSelection = 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/src/app/Panel/krview.cpp b/src/app/Panel/krview.cpp
new file mode 100644
index 0000000..8330f16
--- /dev/null
+++ b/src/app/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 <tqnamespace.h>
+#include <tqpixmapcache.h>
+#include <tqdir.h>
+#include <tqbitmap.h>
+#include <kmimetype.h>
+#include <tdelocale.h>
+#include <kinputdialog.h>
+
+
+#define VF getVfile()
+
+
+// ----------------------------- operator
+KrViewOperator::KrViewOperator(KrView *view, TQWidget *widget): _view(view), _widget(widget) {
+}
+
+KrViewOperator::~KrViewOperator() {
+}
+
+void KrViewOperator::startDrag() {
+ TQStringList items;
+ _view->getSelectedItems( &items );
+ if ( items.empty() )
+ return ; // don't drag an empty thing
+ TQPixmap 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( TDEConfig *cfg ) : _config( cfg ), _widget(0), _nameToMakeCurrent( TQString() ), _nameToMakeCurrentIfAdded( TQString() ),
+_numSelected( 0 ), _count( 0 ), _numDirs( 0 ), _countSize( 0 ), _selectedSize( 0 ), _properties(0), _focused( false ), _nameInTDEConfig(TQString()) {
+}
+
+KrView::~KrView() {
+ if (_properties)
+ tqFatal("A class inheriting KrView didn't delete _properties!");
+ if (_operator)
+ tqFatal("A class inheriting KrView didn't delete _operator!");
+}
+
+void KrView::init() {
+ // sanity checks:
+ if (_nameInTDEConfig.isEmpty())
+ tqFatal("_nameInTDEConfig must be set during construction of KrView inheritors");
+ if (!_widget)
+ tqFatal("_widget must be set during construction of KrView inheritors");
+ // ok, continue
+ initProperties();
+ initOperator();
+ setup();
+}
+
+TQPixmap KrView::getIcon( vfile *vf /*, KRListItem::cmpColor color*/ ) {
+ //krConfig->setGroup("Advanced");
+ //////////////////////////////
+ TQPixmap icon;
+ TQString icon_name = vf->vfile_getIcon();
+ //TQPixmapCache::setCacheLimit( krConfig->readNumEntry("Icon Cache Size",_IconCacheSize) );
+
+ if( icon_name.isNull() )
+ icon_name="";
+
+ // first try the cache
+ if ( !TQPixmapCache::find( icon_name, icon ) ) {
+ icon = FL_LOADICON( icon_name );
+ // insert it into the cache
+ TQPixmapCache::insert( icon_name, icon );
+ }
+ // if it's a symlink - add an arrow overlay
+ if ( vf->vfile_isSymLink() ) {
+ TQPixmap link( link_xpm );
+ bitBlt ( &icon, 0, icon.height() - 11, &link, 0, 21, 10, 11, TQt::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( TQString mask, TQStringList* names, bool dirs, bool files ) {
+ for ( KrViewItem * it = getFirst(); it != 0; it = getNext( it ) ) {
+ if ( ( it->name() == ".." ) || !TQDir::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( TQStringList *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
+ TQString item = getCurrentItem();
+ if ( names->empty() && item!=TQString() && 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
+ TQString item = getCurrentItem();
+ if ( items->empty() && item!=TQString() && item!=".." ) items->append( getCurrentKrViewItem() );
+}
+
+TQString 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();
+ }
+ TQString tmp = TQString(i18n("%1 out of %2, %3 (%4) out of %5 (%6)"))
+ .arg( _numSelected ).arg( _count ).arg( TDEIO::convertSize( _selectedSize ) )
+ .arg( KRpermHandler::parseSize(_selectedSize) )
+ .arg( TDEIO::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 ) {
+ TDEConfigGroupSaver 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() {
+ TDEConfigGroupSaver grpSvr( _config, "Look&Feel" /*nameInTDEConfig()*/ );
+ 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 );
+}
+
+TQString 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 TQString();
+ return iterator->name();
+}
+
+void KrView::delItem(const TQString &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(TQString());
+ 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() {
+ TQString 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/src/app/Panel/krview.h b/src/app/Panel/krview.h
new file mode 100644
index 0000000..c4f89ec
--- /dev/null
+++ b/src/app/Panel/krview.h
@@ -0,0 +1,248 @@
+/***************************************************************************
+ 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 <tqpixmap.h>
+#include <tqvariant.h>
+#include <tqdict.h>
+#include "../krusader.h"
+#include "../VFS/vfile.h"
+#include "../VFS/vfs.h"
+#include "../VFS/krquery.h"
+
+#include <kdebug.h>
+
+class KrView;
+class KrViewItem;
+typedef TQValueList<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
+ TQStringList 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 tdelistview for example)
+// 2. if the view HAS A widget (a krview-son has a member of tdelistview)
+// 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 TQObject {
+ TQ_OBJECT
+
+public:
+ KrViewOperator(KrView *view, TQWidget *widget);
+ ~KrViewOperator();
+ KrView *view() const { return _view; }
+ TQWidget *widget() const { return _widget; }
+ void startDrag();
+
+ void emitSelectionChanged() { emit selectionChanged(); }
+ void emitGotDrop(TQDropEvent *e) { emit gotDrop(e); }
+ void emitLetsDrag(TQStringList items, TQPixmap icon ) { emit letsDrag(items, icon); }
+ void emitItemDescription(TQString &desc) { emit itemDescription(desc); }
+ void emitContextMenu(const TQPoint &point) { emit contextMenu(point); }
+ void emitEmptyContextMenu(const TQPoint &point) { emit emptyContextMenu(point); }
+ void emitRenameItem(const TQString &oldName, const TQString &newName) { emit renameItem(oldName, newName); }
+ void emitExecuted( TQString &name ) { emit executed(name); }
+ void emitNeedFocus() { emit needFocus(); }
+
+signals:
+ void selectionChanged();
+ void gotDrop( TQDropEvent *e );
+ void letsDrag( TQStringList items, TQPixmap icon );
+ void itemDescription( TQString &desc );
+ void contextMenu( const TQPoint &point );
+ void emptyContextMenu( const TQPoint& point );
+ void renameItem( const TQString &oldName, const TQString &newName );
+ void executed( TQString &name );
+ void needFocus();
+
+
+protected:
+ // never delete those
+ KrView *_view;
+ TQWidget *_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 TQValueList with KrViewItems
+ * 3) getCurrentItem, setCurrentItem - work with TQString
+ * 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 TQString
+ *
+ * IMPORTANT NOTE: every one who subclasses this must call initProperties() in the constructor !!!
+ */
+class KrView {
+friend class KrViewItem;
+friend class KrBriefViewItem;
+friend class KrDetailedViewItem;
+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() { tqFatal("Please implement your own initProperties() method"); }
+ virtual void initOperator() { tqFatal("Please implement your own initOperator() method"); }
+ virtual void setup() { tqFatal("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 TQPoint &vp) = 0;
+ virtual KrViewItem *findItemByName(const TQString &name) = 0;
+ virtual void addItems(vfs* v, bool addUpDir = true) = 0; // kill me, kill me now
+ virtual TQString getCurrentItem() const = 0;
+ virtual void setCurrentItem(const TQString& 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 TQString nameInTDEConfig() const { return _nameInTDEConfig; }
+
+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 TQString &name);
+ virtual uint numSelected() const { return _numSelected; }
+ virtual TDEIO::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 TDEIO::filesize_t countSize() const { return _countSize; }
+ virtual void getSelectedItems(TQStringList* names);
+ virtual void getItemsByMask(TQString mask, TQStringList* 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 TQString nameToMakeCurrent() const { return _nameToMakeCurrent; }
+ virtual void setNameToMakeCurrent(const TQString name) { _nameToMakeCurrent = name; }
+ virtual TQString nameToMakeCurrentIfAdded() const { return _nameToMakeCurrentIfAdded; }
+ virtual void setNameToMakeCurrentIfAdded(const TQString name) { _nameToMakeCurrentIfAdded = name; }
+ virtual TQString firstUnmarkedBelowCurrent();
+ virtual TQString 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 TQWidget *widget() { return _widget; }
+ inline void setWidget(TQWidget *w) { _widget = w; }
+
+ // todo: what about selection modes ???
+ virtual ~KrView();
+protected:
+ KrView(TDEConfig *cfg = krConfig);
+ static TQPixmap getIcon(vfile *vf);
+ void changeSelection(const KRQuery& filter, bool select, bool includeDirs = false);
+
+
+protected:
+ TDEConfig *_config;
+ TQWidget *_widget;
+ TQString _nameToMakeCurrent;
+ TQString _nameToMakeCurrentIfAdded;
+ uint _numSelected, _count, _numDirs;
+ TDEIO::filesize_t _countSize, _selectedSize;
+ bool _left;
+ KrViewProperties *_properties;
+ KrViewOperator *_operator;
+ TQDict<KrViewItem> _dict;
+ bool _focused;
+ TQString _nameInTDEConfig;
+};
+
+#endif /* KRVIEW_H */
diff --git a/src/app/Panel/krviewitem.cpp b/src/app/Panel/krviewitem.cpp
new file mode 100644
index 0000000..916ed91
--- /dev/null
+++ b/src/app/Panel/krviewitem.cpp
@@ -0,0 +1,106 @@
+#include "krviewitem.h"
+#include "../VFS/krpermhandler.h"
+#include <tdelocale.h>
+#include <kmimetype.h>
+#include <sys/types.h>
+#include <time.h>
+#include <stdlib.h>
+
+#define PROPS static_cast<const KrViewProperties*>(_viewProperties)
+
+TQString atomicExtensions[] = {
+ ".tar.gz",
+ ".tar.bz2",
+ ".moc.cpp"
+ ".tar.xz",
+};
+
+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 TQString& 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 (TQStringList::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 TQString& KrViewItem::name(bool withExtension) const {
+ if (!withExtension && _hasExtension) return _name;
+ else return _vf->vfile_getName();
+}
+
+TQString KrViewItem::description() const {
+ if (dummyVfile) return i18n("Climb up the directory tree");
+ // else is implied
+ TQString text = _vf->vfile_getName();
+ TQString comment = KMimeType::mimeType(_vf->vfile_getMime())->comment(text, false);
+ TQString myLinkDest = _vf->vfile_getSymDest();
+ TDEIO::filesize_t mySize = _vf->vfile_getSize();
+
+ TQString text2 = text.copy();
+ mode_t m_fileMode = _vf->vfile_getMode();
+
+ if (_vf->vfile_isSymLink() ){
+ TQString 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 = TQString("%1 (%2)").arg(text2).arg( PROPS->humanReadableSize ?
+ KRpermHandler::parseSize(_vf->vfile_getSize()) : TDEIO::convertSize( mySize ) );
+ text += " ";
+ text += comment;
+ } else if ( S_ISDIR ( m_fileMode ) ){
+ text += "/ ";
+ text += comment;
+ } else {
+ text += " ";
+ text += comment;
+ }
+ return text;
+}
+
+TQString KrViewItem::dateTime() const {
+ // convert the time_t to struct tm
+ time_t time = _vf->vfile_getTime_t();
+ struct tm* t=localtime((time_t *)&time);
+
+ TQDateTime tmp(TQDate(t->tm_year+1900, t->tm_mon+1, t->tm_mday), TQTime(t->tm_hour, t->tm_min));
+ return TDEGlobal::locale()->formatDateTime(tmp);
+}
+
+TQPixmap KrViewItem::icon() {
+#if 0
+ TQPixmap *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 TQPixmap*
+ // 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 TQPixmap();
+ else return KrView::getIcon(_vf);
+}
diff --git a/src/app/Panel/krviewitem.h b/src/app/Panel/krviewitem.h
new file mode 100644
index 0000000..b57afbd
--- /dev/null
+++ b/src/app/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 <tdeio/global.h>
+#include "../VFS/vfile.h"
+#include "krview.h"
+
+class TQString;
+class TQPixmap;
+
+class KrViewItem {
+ friend class KrView;
+
+public:
+ virtual const TQString& name(bool withExtension=true) const;
+ virtual inline bool hasExtension() const { return _hasExtension; }
+ virtual inline const TQString& extension() const { return _extension; }
+ virtual TQString dateTime() const;
+ virtual TQString description() const;
+ virtual bool isSelected() const = 0;
+ virtual void setSelected( bool s ) = 0;
+ virtual TQPixmap 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(TDEIO::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;
+ TQString _name;
+ TQString _extension;
+};
+
+#endif
diff --git a/src/app/Panel/listpanel.cpp b/src/app/Panel/listpanel.cpp
new file mode 100644
index 0000000..8d444df
--- /dev/null
+++ b/src/app/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>
+// TQt includes
+#include <tqbitmap.h>
+#include <tqwhatsthis.h>
+#include <tqstringlist.h>
+#include <tqstrlist.h>
+#include <kurldrag.h>
+#include <tqheader.h>
+#include <tqtimer.h>
+#include <tqregexp.h>
+#include <tqsplitter.h>
+// TDE includes
+#include <tdepopupmenu.h>
+#include <kprocess.h>
+#include <tdemessagebox.h>
+#include <tdelocale.h>
+#include <kmimetype.h>
+#include <kurl.h>
+#include <ktrader.h>
+#include <kopenwith.h>
+#include <kuserprofile.h>
+#include <kiconloader.h>
+#include <kcursor.h>
+#include <tdemessagebox.h>
+#include <kstandarddirs.h>
+#include <tdeglobalsettings.h>
+#include <tqtooltip.h>
+#include <tdeversion.h>
+#include <tqimage.h>
+#include <tqtabbar.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 TQValueList<KServiceOffer> OfferList;
+
+#define URL(X) KURL::fromPathOrURL(X)
+
+/////////////////////////////////////////////////////
+// The list panel constructor //
+/////////////////////////////////////////////////////
+ListPanel::ListPanel( TQString typeIn, TQWidget *parent, bool &left, const char *name ) :
+ TQWidget( 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 TQGridLayout( this, 3, 3 );
+
+ mediaButton = new MediaButton( this, "mediaButton" );
+ connect( mediaButton, TQ_SIGNAL( pressed() ), this, TQ_SLOT( slotFocusOnMe() ) );
+ connect( mediaButton, TQ_SIGNAL( openUrl( const KURL& ) ), func, TQ_SLOT( openUrl( const KURL& ) ) );
+
+ status = new KrSqueezedTextLabel( this );
+ krConfig->setGroup( "Look&Feel" );
+ status->setFont( krConfig->readFontEntry( "Filelist Font", _FilelistFont ) );
+ status->setBackgroundMode( PaletteBackground );
+ status->setFrameStyle( TQFrame::Box | TQFrame::Raised );
+ status->setLineWidth( 1 ); // a nice 3D touch :-)
+ status->setText( "" ); // needed for initialization code!
+ status->enableDrops( true );
+ int sheight = TQFontMetrics( status->font() ).height() + 4;
+ status->setMaximumHeight( sheight );
+ TQWhatsThis::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, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotFocusOnMe() ) );
+ connect( status, TQ_SIGNAL( dropped( TQDropEvent *) ), this, TQ_SLOT( handleDropOnStatus(TQDropEvent *) ) );
+
+ // ... create the history button
+ dirHistoryQueue = new DirHistoryQueue( this );
+ historyButton = new DirHistoryButton( dirHistoryQueue, this, "historyButton" );
+ connect( historyButton, TQ_SIGNAL( pressed() ), this, TQ_SLOT( slotFocusOnMe() ) );
+ connect( historyButton, TQ_SIGNAL( openUrl( const KURL& ) ), func, TQ_SLOT( openUrl( const KURL& ) ) );
+
+ bookmarksButton = new KrBookmarkButton(this);
+ connect( bookmarksButton, TQ_SIGNAL( pressed() ), this, TQ_SLOT( slotFocusOnMe() ) );
+ connect( bookmarksButton, TQ_SIGNAL( openUrl( const KURL& ) ), func, TQ_SLOT( openUrl( const KURL& ) ) );
+ TQWhatsThis::add
+ ( bookmarksButton, i18n( "Open menu with bookmarks. You can also add "
+ "current location to the list, edit bookmarks "
+ "or add subfolder to the list." ) );
+
+ TQHBoxLayout *totalsLayout = new TQHBoxLayout;
+ totals = new KrSqueezedTextLabel( this );
+ krConfig->setGroup( "Look&Feel" );
+ totals->setFont( krConfig->readFontEntry( "Filelist Font", _FilelistFont ) );
+ totals->setFrameStyle( TQFrame::Box | TQFrame::Raised );
+ totals->setBackgroundMode( PaletteBackground );
+ totals->setLineWidth( 1 ); // a nice 3D touch :-)
+ totals->setMaximumHeight( sheight );
+ totals->enableDrops( true );
+ TQWhatsThis::add
+ ( totals, i18n( "The totals bar shows how many files exist, "
+ "how many selected and the bytes math" ) );
+ connect( totals, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotFocusOnMe() ) );
+ connect( totals, TQ_SIGNAL( dropped( TQDropEvent *) ), this, TQ_SLOT( handleDropOnTotals(TQDropEvent *) ) );
+
+ // a cancel button for the inplace refresh mechanism
+ inlineRefreshCancelButton = new KPushButton(this);
+ inlineRefreshCancelButton->setFixedSize( 22, 20 );
+ inlineRefreshCancelButton->setPixmap(krLoader->loadIcon("cancel", TDEIcon::Toolbar, 16));
+ connect(inlineRefreshCancelButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(inlineRefreshCancel()));
+
+ // a quick button to open the popup panel
+ popupBtn = new TQToolButton( this, "popupbtn" );
+ popupBtn->setFixedSize( 22, 20 );
+ popupBtn->setPixmap(krLoader->loadIcon("1uparrow", TDEIcon::Toolbar, 16));
+ connect(popupBtn, TQ_SIGNAL(clicked()), this, TQ_SLOT(togglePanelPopup()));
+ TQToolTip::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( TQFrame::Box | TQFrame::Raised );
+ quickSearch->setLineWidth( 1 ); // a nice 3D touch :-)
+ quickSearch->setMaximumHeight( sheight );
+
+ TQHBox * hbox = new TQHBox( this );
+
+ // clear-origin button
+ bool clearButton = krConfig->readBoolEntry("Clear Location Bar Visible", _ClearLocation);
+ if (clearButton){
+ clearOrigin = new TQToolButton(hbox, "clearorigin");
+ clearOrigin->setPixmap(krLoader->loadIcon("locationbar_erase", TDEIcon::Toolbar, 16));
+ TQToolTip::add( clearOrigin, i18n( "Clear the location bar" ) );
+ }
+
+ QuickNavLineEdit *qnle = new QuickNavLineEdit(this);
+ origin = new KURLRequester( qnle, hbox );
+ TQPixmap pixMap = origin->button() ->iconSet() ->pixmap( TQIconSet::Small, TQIconSet::Normal );
+ origin->button() ->setFixedSize( pixMap.width() + 4, pixMap.height() + 4 );
+ TQWhatsThis::add
+ ( origin, i18n( "Use superb TDE file dialog to choose location. " ) );
+ origin->setShowLocalProtocol( false );
+ origin->lineEdit() ->setURLDropsEnabled( true );
+ origin->lineEdit() ->installEventFilter( this );
+ TQWhatsThis::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, TQ_SIGNAL( returnPressed( const TQString& ) ), func, TQ_SLOT( openUrl( const TQString& ) ) );
+ connect( origin, TQ_SIGNAL( returnPressed( const TQString& ) ), this, TQ_SLOT( slotFocusOnMe() ) );
+ connect( origin, TQ_SIGNAL( urlSelected( const TQString& ) ), func, TQ_SLOT( openUrl( const TQString& ) ) );
+ connect( origin, TQ_SIGNAL( urlSelected( const TQString& ) ), this, TQ_SLOT( slotFocusOnMe() ) );
+
+ // this is here on purpose, do not move up!
+ if (clearButton) {
+ clearOrigin->setFixedSize( 20, origin->button() ->height() );
+ connect(clearOrigin, TQ_SIGNAL(clicked()), origin->lineEdit(), TQ_SLOT(clear()));
+ connect(clearOrigin, TQ_SIGNAL(clicked()), origin->lineEdit(), TQ_SLOT(setFocus()));
+ }
+ //
+
+ cdOtherButton = new TQToolButton( hbox, "cdOtherButton" );
+ cdOtherButton->setFixedSize( 20, origin->button() ->height() );
+ cdOtherButton->setText( i18n( "=" ) );
+ TQToolTip::add( cdOtherButton, i18n( "Equal" ) );
+ connect( cdOtherButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotFocusAndCDOther() ) );
+
+ cdUpButton = new TQToolButton( hbox, "cdUpButton" );
+ cdUpButton->setFixedSize( 20, origin->button() ->height() );
+ cdUpButton->setText( i18n( ".." ) );
+ TQToolTip::add( cdUpButton, i18n( "Up" ) );
+ connect( cdUpButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotFocusAndCDup() ) );
+
+ cdHomeButton = new TQToolButton( hbox, "cdHomeButton" );
+ cdHomeButton->setFixedSize( 20, origin->button() ->height() );
+ cdHomeButton->setText( i18n( "~" ) );
+ TQToolTip::add( cdHomeButton, i18n( "Home" ) );
+ connect( cdHomeButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotFocusAndCDHome() ) );
+
+ cdRootButton = new TQToolButton( hbox, "cdRootButton" );
+ cdRootButton->setFixedSize( 20, origin->button() ->height() );
+ cdRootButton->setText( i18n( "/" ) );
+ TQToolTip::add( cdRootButton, i18n( "Root" ) );
+ connect( cdRootButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotFocusAndCDRoot() ) );
+
+ // ... creates the button for sync-browsing
+ syncBrowseButton = new SyncBrowseButton( hbox );
+
+ setPanelToolbar();
+
+ header = new TQHeader( this );
+ header->hide();
+
+ // create a splitter to hold the view and the popup
+ splt = new PercentalSplitter(this);
+ splt->setChildrenCollapsible(true);
+ splt->setOrientation(TQt::Vertical);
+
+ createView();
+
+ // make sure that a focus/path change reflects in the command line and activePanel
+ connect( this, TQ_SIGNAL( cmdLineUpdate( TQString ) ), SLOTS, TQ_SLOT( slotCurrentChanged( TQString ) ) );
+ connect( this, TQ_SIGNAL( activePanelChanged( ListPanel * ) ), SLOTS, TQ_SLOT( slotSetActivePanel( ListPanel * ) ) );
+
+ // add a popup
+ popup = new PanelPopup(splt, left);
+ connect(popup, TQ_SIGNAL(selection(const KURL&)), SLOTS, TQ_SLOT(refresh(const KURL&)));
+ connect(popup, TQ_SIGNAL(hideMe()), this, TQ_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 ), TQ_SIGNAL( middleButtonClicked( KrViewItem * ) ), SLOTS, TQ_SLOT( newTab( KrViewItem * ) ) );
+ connect( dynamic_cast<KrBriefView*>( view ), TQ_SIGNAL( currentChanged( KrViewItem * ) ),
+ SLOTS, TQ_SLOT( updatePopupPanel( KrViewItem* ) ) );
+
+ // connect quicksearch
+ connect( quickSearch, TQ_SIGNAL( textChanged( const TQString& ) ),
+ dynamic_cast<KrBriefView*>( view ), TQ_SLOT( quickSearch( const TQString& ) ) );
+ connect( quickSearch, TQ_SIGNAL( otherMatching( const TQString&, int ) ),
+ dynamic_cast<KrBriefView*>( view ), TQ_SLOT( quickSearch( const TQString& , int ) ) );
+ connect( quickSearch, TQ_SIGNAL( stop( TQKeyEvent* ) ),
+ dynamic_cast<KrBriefView*>( view ), TQ_SLOT( stopQuickSearch( TQKeyEvent* ) ) );
+ connect( quickSearch, TQ_SIGNAL( process( TQKeyEvent* ) ),
+ dynamic_cast<KrBriefView*>( view ), TQ_SLOT( handleQuickSearchEvent( TQKeyEvent* ) ) );
+ } else { /* Detailed */
+ panelType = "Detailed";
+ view = new KrDetailedView( splt, _left, krConfig );
+ view->init();
+ connect( dynamic_cast<KrDetailedView*>( view ), TQ_SIGNAL( middleButtonClicked( KrViewItem * ) ), SLOTS, TQ_SLOT( newTab( KrViewItem * ) ) );
+ connect( dynamic_cast<KrDetailedView*>( view ), TQ_SIGNAL( currentChanged( KrViewItem * ) ),
+ SLOTS, TQ_SLOT( updatePopupPanel( KrViewItem * ) ) );
+ // connect quicksearch
+ connect( quickSearch, TQ_SIGNAL( textChanged( const TQString& ) ),
+ dynamic_cast<KrDetailedView*>( view ), TQ_SLOT( quickSearch( const TQString& ) ) );
+ connect( quickSearch, TQ_SIGNAL( otherMatching( const TQString&, int ) ),
+ dynamic_cast<KrDetailedView*>( view ), TQ_SLOT( quickSearch( const TQString& , int ) ) );
+ connect( quickSearch, TQ_SIGNAL( stop( TQKeyEvent* ) ),
+ dynamic_cast<KrDetailedView*>( view ), TQ_SLOT( stopQuickSearch( TQKeyEvent* ) ) );
+ connect( quickSearch, TQ_SIGNAL( process( TQKeyEvent* ) ),
+ dynamic_cast<KrDetailedView*>( view ), TQ_SLOT( handleQuickSearchEvent( TQKeyEvent* ) ) );
+ }
+
+ connect( view->op(), TQ_SIGNAL( renameItem( const TQString &, const TQString & ) ),
+ func, TQ_SLOT( rename( const TQString &, const TQString & ) ) );
+ connect( view->op(), TQ_SIGNAL( executed( TQString& ) ), func, TQ_SLOT( execute( TQString& ) ) );
+ connect( view->op(), TQ_SIGNAL( needFocus() ), this, TQ_SLOT( slotFocusOnMe() ) );
+ connect( view->op(), TQ_SIGNAL( selectionChanged() ), this, TQ_SLOT( slotUpdateTotals() ) );
+ connect( view->op(), TQ_SIGNAL( itemDescription( TQString& ) ), krApp, TQ_SLOT( statusBarUpdate( TQString& ) ) );
+ connect( view->op(), TQ_SIGNAL( contextMenu( const TQPoint & ) ), this, TQ_SLOT( popRightClickMenu( const TQPoint & ) ) );
+ connect( view->op(), TQ_SIGNAL( emptyContextMenu( const TQPoint &) ),
+ this, TQ_SLOT( popEmptyRightClickMenu( const TQPoint & ) ) );
+ connect( view->op(), TQ_SIGNAL( letsDrag( TQStringList, TQPixmap ) ), this, TQ_SLOT( startDragging( TQStringList, TQPixmap ) ) );
+ connect( view->op(), TQ_SIGNAL( gotDrop( TQDropEvent * ) ), this, TQ_SLOT( handleDropOnView( TQDropEvent * ) ) );
+}
+
+void ListPanel::changeType( const TQString & 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 ( TQObject * watched, TQEvent * e ) {
+ if( e->type() == TQEvent::KeyPress && origin->lineEdit() == watched ) {
+ TQKeyEvent *ke = (TQKeyEvent *)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<TQSplitter*>(popup->parent())->setSizes(popupSizes);
+ } else { // on the first time, resize to 50%
+ TQValueList<int> lst;
+ lst << height()/2 << height()/2;
+ dynamic_cast<TQSplitter*>(popup->parent())->setSizes(lst);
+ }
+
+ popup->show();
+ popupBtn->setPixmap(krLoader->loadIcon("1downarrow", TDEIcon::Toolbar, 16));
+ TQToolTip::add( popupBtn, i18n( "Close the popup panel" ) );
+ } else {
+ popupSizes.clear();
+ popupSizes = dynamic_cast<TQSplitter*>(popup->parent())->sizes();
+ popup->hide();
+ popupBtn->setPixmap(krLoader->loadIcon("1uparrow", TDEIcon::Toolbar, 16));
+ TQToolTip::add( popupBtn, i18n( "Open the popup panel" ) );
+
+ TQValueList<int> lst;
+ lst << height() << 0;
+ dynamic_cast<TQSplitter*>(popup->parent())->setSizes(lst);
+ if( ACTIVE_PANEL )
+ ACTIVE_PANEL->slotFocusOnMe();
+ }
+}
+
+KURL ListPanel::virtualPath() const {
+ return func->files()->vfs_getOrigin();
+}
+
+TQString 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( TQString( "~" ), TQString() );
+}
+
+void ListPanel::slotFocusAndCDup() {
+ slotFocusOnMe();
+ func->dirUp();
+}
+
+void ListPanel::slotFocusAndCDRoot() {
+ slotFocusOnMe();
+ func->openUrl( TQString( "/" ), TQString() );
+}
+
+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'
+ TQPalette q( otherPanel->status->palette() );
+ q.setColor( TQColorGroup::Foreground, TDEGlobalSettings::textColor() );
+ q.setColor( TQColorGroup::Background, TDEGlobalSettings::baseColor() );
+
+ otherPanel->status->setPalette( q );
+ otherPanel->totals->setPalette( q );
+ otherPanel->view->prepareForPassive();
+
+ // now, take care of this panel
+ TQPalette p( status->palette() );
+ p.setColor( TQColorGroup::Foreground, TDEGlobalSettings::highlightedTextColor() );
+ p.setColor( TQColorGroup::Background, TDEGlobalSettings::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
+ TQString protocol = func->files() ->vfs_getOrigin().protocol();
+ bool isFtp = ( protocol == "ftp" || protocol == "smb" || protocol == "sftp" || protocol == "fish" );
+
+ TQString 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;
+ TQString 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, TQ_SIGNAL( foundMountPoint( const TQString &, unsigned long, unsigned long, unsigned long ) ),
+ this, TQ_SLOT( gotStats( const TQString &, unsigned long, unsigned long, unsigned long ) ) );
+}
+
+void ListPanel::gotStats( const TQString &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();
+ TQString fstype = i18n("unknown");
+ for (KMountPoint::List::iterator it = lst.begin(); it != lst.end(); ++it) {
+ if ((*it)->mountPoint() == mountPoint) {
+ fstype = (*it)->mountType();
+ break;
+ }
+ }
+
+ TQString stats = i18n( "%1 free out of %2 (%3%) on %4 [ (%5) ]" )
+ .arg( TDEIO::convertSizeFromKB( kBAvail ) )
+ .arg( TDEIO::convertSizeFromKB( kBSize ) ).arg( perc )
+ .arg( mountPoint ).arg( fstype );
+ status->setText( stats );
+}
+
+void ListPanel::handleDropOnTotals( TQDropEvent *e ) {
+ handleDropOnView( e, totals );
+}
+
+void ListPanel::handleDropOnStatus( TQDropEvent *e ) {
+ handleDropOnView( e, status );
+}
+
+void ListPanel::handleDropOnView( TQDropEvent *e, TQWidget *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;
+ }
+
+ TDEIO::CopyJob::CopyMode mode = TDEIO::CopyJob::Copy;
+
+ // the KURL::List is finished, let's go
+ // --> display the COPY/MOVE/LINK menu
+ TQPopupMenu 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 );
+ TQPoint tmp = widget->mapToGlobal( e->pos() );
+ int result = popup.exec( tmp );
+ switch ( result ) {
+ case 1 :
+ mode = TDEIO::CopyJob::Copy;
+ break;
+ case 2 :
+ mode = TDEIO::CopyJob::Move;
+ break;
+ case 3 :
+ mode = TDEIO::CopyJob::Link;
+ break;
+ case - 1 : // user pressed outside the menu
+ case 4:
+ return ; // cancel was pressed;
+ }
+
+ TQString dir = "";
+ if ( copyToDirInPanel ) {
+ dir = i->name();
+ }
+ TQWidget *notify = ( !e->source() ? 0 : e->source() );
+ tempFiles->vfs_addFiles( &URLs, mode, notify, dir );
+}
+
+void ListPanel::startDragging( TQStringList names, TQPixmap 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, TQPoint( -7, 0 ) );
+ d->dragCopy();
+
+ delete urls; // free memory
+}
+
+// pops a right-click menu for items
+void ListPanel::popRightClickMenu( const TQPoint &loc ) {
+ // run it, on the mouse location
+ int j = TQFontMetrics( font() ).height() * 2;
+ KrPopupMenu::run(TQPoint( loc.x() + 5, loc.y() + j ), this);
+}
+
+void ListPanel::popEmptyRightClickMenu( const TQPoint &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();
+}
+
+TQString ListPanel::getCurrentName() {
+ TQString name = view->getCurrentItem();
+ if ( name != ".." )
+ return name;
+ else
+ return TQString();
+}
+
+void ListPanel::prepareToDelete() {
+ view->setNameToMakeCurrent( view->firstUnmarkedBelowCurrent() );
+}
+
+void ListPanel::keyPressEvent( TQKeyEvent *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() == TQt::NoButton )
+ MAIN_VIEW->cmdLine->addText( e->text() );
+
+ //e->ignore();
+ }
+}
+
+void ListPanel::slotItemAdded(vfile *vf) {
+ view->addItem(vf);
+}
+
+void ListPanel::slotItemDeleted(const TQString& name) {
+ view->delItem(name);
+}
+
+void ListPanel::slotItemUpdated(vfile *vf) {
+ view->updateItem(vf);
+}
+
+void ListPanel::slotCleared() {
+ view->clear();
+}
+
+void ListPanel::showEvent( TQShowEvent *e ) {
+ panelActive();
+ TQWidget::showEvent(e);
+}
+
+void ListPanel::hideEvent( TQHideEvent *e ) {
+ panelInactive();
+ TQWidget::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(TDEIO::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, TQ_SIGNAL( infoMessage( TDEIO::Job*, const TQString & ) ),
+ TQ_SLOT( inlineRefreshInfoMessage( TDEIO::Job*, const TQString & ) ) );
+ connect( job, TQ_SIGNAL( percent( TDEIO::Job*, unsigned long ) ),
+ TQ_SLOT( inlineRefreshPercent( TDEIO::Job*, unsigned long ) ) );
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),
+ this,TQ_SLOT(inlineRefreshListResult(TDEIO::Job*)));
+ connect(job,TQ_SIGNAL(canceled(TDEIO::Job*)),
+ this,TQ_SLOT(inlineRefreshListResult(TDEIO::Job*)));
+
+ inlineRefreshJob = job;
+
+ totals->setText(i18n(">> Reading..."));
+ inlineRefreshCancelButton->show();
+}
+
+void ListPanel::inlineRefreshCancel() {
+ if (inlineRefreshJob) {
+ inlineRefreshJob->kill(false);
+ inlineRefreshJob = 0;
+ }
+}
+
+void ListPanel::inlineRefreshPercent( TDEIO::Job*, unsigned long perc) {
+ TQString msg = TQString(">> %1: %2 % complete...").arg(i18n("Reading")).arg(perc);
+ totals->setText(msg);
+}
+
+void ListPanel::inlineRefreshInfoMessage( TDEIO::Job*, const TQString &msg ) {
+ totals->setText(">> " + i18n("Reading: ") + msg);
+}
+
+void ListPanel::inlineRefreshListResult(TDEIO::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/src/app/Panel/listpanel.h b/src/app/Panel/listpanel.h
new file mode 100644
index 0000000..e78e2fb
--- /dev/null
+++ b/src/app/Panel/listpanel.h
@@ -0,0 +1,212 @@
+/***************************************************************************
+ 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 <tdefileitem.h>
+#include <kurl.h>
+#include <tqwidget.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqstring.h>
+#include <tqpixmap.h>
+#include <tqtoolbutton.h>
+#include <tqpopupmenu.h>
+#include <tqdir.h>
+#include <tqpixmapcache.h>
+#include <tqiconset.h>
+#include <tqptrstack.h>
+#include <tqtextbrowser.h>
+#include <keditcl.h>
+#include <klineedit.h>
+#include <tqguardedptr.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 TQHeader;
+
+class ListPanel : public TQWidget {
+ friend class ListPanelFunc;
+ TQ_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( TQString panelType, TQWidget *parent, bool &left, const char *name = 0 );
+ ~ListPanel();
+ void start( KURL url = KURL(), bool immediate = false );
+
+ const TQString & getType() { return panelType; }
+ void changeType( const TQString & );
+
+ KURL virtualPath() const;
+ TQString realPath() const;
+ TQString getCurrentName();
+ void getSelectedNames( TQStringList* 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 TQString &mountPoint, unsigned long kBSize, unsigned long kBUsed, unsigned long kBAvail); // displays filesystem status
+ void popRightClickMenu( const TQPoint& );
+ void popEmptyRightClickMenu( const TQPoint & );
+ 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 TQString& 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( TQKeyEvent *e );
+ virtual void showEvent( TQShowEvent * );
+ virtual void hideEvent( TQHideEvent * );
+ virtual bool eventFilter ( TQObject * watched, TQEvent * e );
+
+ void createView();
+
+protected slots:
+ void handleDropOnView(TQDropEvent *, TQWidget *destWidget=0); // handles drops on the view only
+ void handleDropOnTotals( TQDropEvent * ); // handles drops on the totals line
+ void handleDropOnStatus( TQDropEvent * ); // handles drops on the status line
+ void startDragging( TQStringList, TQPixmap );
+ // those handle the in-panel refresh notifications
+ void slotJobStarted(TDEIO::Job* job);
+ void inlineRefreshInfoMessage( TDEIO::Job* job, const TQString &msg );
+ void inlineRefreshListResult(TDEIO::Job* job);
+ void inlineRefreshPercent( TDEIO::Job*, unsigned long );
+ void inlineRefreshCancel();
+
+signals:
+ void signalStatus( TQString msg ); // emmited when we need to update the status bar
+ void cmdLineUpdate( TQString 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:
+ TQString panelType;
+ ListPanelFunc *func;
+ KrView *view;
+ ListPanel *otherPanel;
+ int colorMask;
+ bool compareMode;
+ //FilterSpec filter;
+ KRQuery filterMask;
+ TQPixmap currDragPix;
+ TQListViewItem *currDragItem;
+ KDiskFreeSp* statsAgent;
+ KrSqueezedTextLabel *status, *totals;
+ KrQuickSearch *quickSearch;
+ KURLRequester *origin;
+ TQGridLayout *layout;
+ TQToolButton *cdRootButton;
+ TQToolButton *cdHomeButton;
+ TQToolButton *cdUpButton;
+ TQToolButton *cdOtherButton;
+ TQToolButton *popupBtn;
+ TQToolButton *clearOrigin;
+ PanelPopup *popup;
+ KrBookmarkButton *bookmarksButton;
+ DirHistoryQueue* dirHistoryQueue;
+ DirHistoryButton* historyButton;
+ MediaButton *mediaButton;
+ SyncBrowseButton *syncBrowseButton;
+ KPushButton *inlineRefreshCancelButton;
+ TDEIO::Job *inlineRefreshJob;
+ TQSplitter *splt;
+ TQHeader * header;
+
+protected:
+ KURL _realPath; // named with _ to keep realPath() compatability
+ KURL _jumpBackURL;
+
+
+private:
+ bool &_left;
+ TQValueList<int> popupSizes;
+};
+
+#endif
diff --git a/src/app/Panel/panelfunc.cpp b/src/app/Panel/panelfunc.cpp
new file mode 100644
index 0000000..7d1fa68
--- /dev/null
+++ b/src/app/Panel/panelfunc.cpp
@@ -0,0 +1,1202 @@
+/***************************************************************************
+ 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>
+// TQt Includes
+#include <tqdir.h>
+#include <tqtextstream.h>
+#include <tqeventloop.h>
+#include <tqclipboard.h>
+// TDE Includes
+#include <tdelocale.h>
+#include <kprocess.h>
+#include <kpropertiesdialog.h>
+#include <kopenwith.h>
+#include <tdemessagebox.h>
+#include <kcursor.h>
+#include <kstandarddirs.h>
+#include <tdetempfile.h>
+#include <kurl.h>
+#include <krun.h>
+#include <kinputdialog.h>
+#include <kdebug.h>
+#include <tdeio/netaccess.h>
+#include <kstandarddirs.h>
+#include <ktempdir.h>
+#include <kurlrequester.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, TQ_SIGNAL( timeout() ), this, TQ_SLOT( doOpenUrl() ) );
+}
+
+void ListPanelFunc::openUrl( const TQString& url, const TQString& 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( TQDir::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, TQ_SIGNAL( deleteAllowed() ), vfsP, TQ_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(), TQ_SIGNAL(startJob(TDEIO::Job* )),
+ panel, TQ_SLOT(slotJobStarted(TDEIO::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(), TQ_SIGNAL( addedVfile( vfile* ) ), 0, 0 );
+ disconnect( files(), TQ_SIGNAL( updatedVfile( vfile* ) ), 0, 0 );
+ disconnect( files(), TQ_SIGNAL( deletedVfile( const TQString& ) ), 0, 0 );
+ disconnect( files(), TQ_SIGNAL( cleared() ), 0, 0 );
+ // connect to the vfs's dirwatch signals
+ connect( files(), TQ_SIGNAL( addedVfile( vfile* ) ),
+ panel, TQ_SLOT( slotItemAdded( vfile* ) ) );
+ connect( files(), TQ_SIGNAL( updatedVfile( vfile* ) ),
+ panel, TQ_SLOT( slotItemUpdated( vfile* ) ) );
+ connect( files(), TQ_SIGNAL( deletedVfile( const TQString& ) ),
+ panel, TQ_SLOT( slotItemDeleted( const TQString& ) ) );
+ connect( files(), TQ_SIGNAL( cleared() ),
+ panel, TQ_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 TQString& 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 tqApp->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 ;
+
+ TQString file = files() ->vfs_getFile( vf->vfile_getName() ).path( -1 );
+ TQString 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;
+ TQString 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 ;
+ }
+
+ TQString name = panel->getCurrentName();
+
+ // ask the new link name..
+ bool ok = false;
+ TQString 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() {
+ TQString 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() {
+ TQString save = getcwd( 0, 0 );
+ chdir( panel->realPath().local8Bit() );
+
+ TDEProcess proc;
+ krConfig->setGroup( "General" );
+ TQString 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( TDEProcess::DontCare ) )
+ KMessageBox::sorry( krApp, i18n( "<qt>Can't open <b>%1</b></qt>" ).arg(term) );
+
+ chdir( save.local8Bit() );
+}
+
+void ListPanelFunc::editFile() {
+ TQString 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;
+
+ TQStringList fileNames;
+ panel->getSelectedNames( &fileNames );
+ if ( fileNames.isEmpty() )
+ return ; // safety
+
+ KURL dest = panel->otherPanel->virtualPath();
+ KURL virtualBaseURL;
+
+ TQString 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 );
+ TQString 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, TDEIO::CopyJob::Move, false, true );
+ connect( vjob, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( refresh() ) );
+ if ( dest.equals( panel->otherPanel->virtualPath(), true ) )
+ connect( vjob, TQ_SIGNAL( result( TDEIO::Job* ) ), panel->otherPanel->func, TQ_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);
+ TDEIO::Job* job = PreservingCopyJob::createCopyJob( pmode, *fileUrls, dest, TDEIO::CopyJob::Move, false, true );
+ job->setAutoErrorHandlingEnabled( true );
+ // refresh our panel when done
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( refresh() ) );
+ // and if needed the other panel as well
+ if ( dest.equals( panel->otherPanel->virtualPath(), true ) )
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), panel->otherPanel->func, TQ_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, TDEIO::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 TQString &oldname, const TQString &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;
+ TQString dirName =
+ KInputDialog::getText( i18n( "New directory" ), i18n( "Directory's name:" ), "", &ok, krApp );
+
+ // if the user canceled - quit
+ if ( !ok || dirName.isEmpty() )
+ return ;
+
+ TQStringList dirTree = TQStringList::split( "/", dirName );
+
+ for ( TQStringList::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();
+
+ TQStringList 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;
+
+ TQStringList 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 );
+ TQString 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, TDEIO::CopyJob::Copy, false, true );
+ connect( vjob, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( refresh() ) );
+ if ( dest.equals( panel->otherPanel->virtualPath(), true ) )
+ connect( vjob, TQ_SIGNAL( result( TDEIO::Job* ) ), panel->otherPanel->func, TQ_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);
+ TDEIO::Job* job = PreservingCopyJob::createCopyJob( pmode, *fileUrls, dest, TDEIO::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, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_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, TDEIO::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
+ TQStringList 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 ) ) {
+ TQString 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 ) );
+
+ TQDir dir;
+ for ( TQStringList::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(TQDir::All | TQDir::System | TQDir::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),
+ TQString(), 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( TQString& name ) {
+ if ( name == ".." ) {
+ dirUp();
+ return ;
+ }
+ vfile *vf = files() ->vfs_search( name );
+ if ( vf == 0 )
+ return ;
+
+ KURL origin = files() ->vfs_getOrigin();
+
+ TQString protocol = origin.isLocalFile() ? KrServices::registerdProtocol( vf->vfile_getMime() ) : "";
+ if ( protocol == "tar" || protocol == "krarc" ) {
+ bool encrypted;
+ TQString 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( TQString() );
+ 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() {
+ TQStringList fileNames;
+ panel->getSelectedNames( &fileNames );
+ if ( fileNames.isEmpty() )
+ return ; // safety
+
+ if ( fileNames.count() == 0 )
+ return ; // nothing to pack
+
+ // choose the default name
+ TQString 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 == TQString() )
+ return ; // the user canceled
+
+ // check for partial URLs
+ if( !PackGUI::destination.contains(":/") && !PackGUI::destination.startsWith("/") ){
+ PackGUI::destination = panel->virtualPath().prettyURL()+"/"+PackGUI::destination;
+ }
+
+ TQString 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;
+ TQString 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( TQString(), "." + PackGUI::type );
+ tempDestFile->setAutoDelete( true );
+ arcFile = tempDestFile->name();
+ TQFile::remove
+ ( arcFile );
+ }
+
+ if ( TQFileInfo( arcFile ).exists() ) {
+ TQString 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,TQString(),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 );
+
+ TDEIO::filesize_t totalSize = 0;
+ unsigned long totalDirs = 0, totalFiles = 0;
+ if( !calcSpace( fileNames, totalSize, totalFiles, totalDirs ) )
+ return;
+
+ // download remote URL-s if necessary
+ TQString 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 );
+ TDEIO::NetAccess::dircopy( *urlList, vfs::fromPathOrURL( arcDir ), 0 );
+ delete urlList;
+ }
+
+ // pack the files
+ // we must chdir() first because we supply *names* not URL's
+ TQString 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 ) {
+ TDEIO::NetAccess::file_move( vfs::fromPathOrURL( arcFile ), destURL );
+ delete tempDestFile;
+ }
+
+ if ( packToOtherPanel )
+ panel->otherPanel->func->refresh();
+}
+
+void ListPanelFunc::testArchive() {
+ TQString arcName = panel->getCurrentName();
+ if ( arcName.isNull() )
+ return ;
+ if ( arcName == ".." )
+ return ; // safety
+
+ KURL arcURL = files() ->vfs_getFile( arcName );
+ TQString url = TQString();
+
+ // download the file if it's on a remote filesystem
+ if ( !arcURL.isLocalFile() ) {
+ url = locateLocal( "tmp", TQString( arcName ) );
+ if ( !TDEIO::NetAccess::download( arcURL, url, 0 ) ) {
+ KMessageBox::sorry( krApp, i18n( "Krusader is unable to download: " ) + arcURL.fileName() );
+ return ;
+ }
+ } else
+ url = arcURL.path( -1 );
+
+ TQString mime = files() ->vfs_search( arcName ) ->vfile_getMime();
+ bool encrypted = false;
+ TQString 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 ;
+ }
+
+ TQString password = encrypted ? KRarcHandler::getPassword( url ) : TQString();
+
+ // 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 ) )
+ TQFile( url ).remove();
+}
+
+void ListPanelFunc::unpack() {
+ TQStringList fileNames;
+ panel->getSelectedNames( &fileNames );
+ if ( fileNames.isEmpty() )
+ return ; // safety
+
+ TQString 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 ) {
+ TQString 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 );
+ TQString url = TQString();
+ if ( !arcURL.isLocalFile() ) {
+ url = locateLocal( "tmp", TQString( arcName ) );
+ if ( !TDEIO::NetAccess::download( arcURL, url, 0 ) ) {
+ KMessageBox::sorry( krApp, i18n( "Krusader is unable to download: " ) + arcURL.fileName() );
+ continue;
+ }
+ } else
+ url = arcURL.path( -1 );
+
+ // for local destionation, check whether it exists or not
+ if ( dest.isLocalFile() ) {
+ TQDir destdir = TQDir(dest.path(1));
+ if (!destdir.exists()) {
+ // Destination folder does not exists
+ int res = KMessageBox::warningContinueCancel( NULL,
+ i18n("The destination folder does not exist.\nDo you want to create it?"),
+ i18n("Create folder"));
+ if ( res != KMessageBox::Continue ) {
+ return;
+ }
+ // Create destination folder. If failed, return
+ if (!destdir.mkdir(destdir.absPath())) {
+ KMessageBox::error(NULL, i18n("Unable to create the destionation folder. Aborting operation."), i18n("Error!"));
+ }
+ }
+ }
+
+ // 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
+ TQString mime = files() ->vfs_search( arcName ) ->vfile_getMime();
+ bool encrypted = false;
+ TQString 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;
+ }
+
+ TQString password = encrypted ? KRarcHandler::getPassword( url ) : TQString();
+
+ // unpack the files
+ KRarcHandler::unpack( url, type, password, dest.path( -1 ) );
+
+ // remove the downloaded file if necessary
+ if ( url != arcURL.path( -1 ) )
+ TQFile( url ).remove();
+
+ // copy files to the destination directory at remote files
+ if ( tempDir ) {
+ TQStringList nameList = TQDir( 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 )
+ TDEIO::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, TQStringList& 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() {
+ TQStringList args;
+ bool folders;
+ checksum_wrapper(panel, args, folders);
+ CreateChecksumDlg dlg(args, folders, panel->realPath());
+}
+
+void ListPanelFunc::matchChecksum() {
+ TQStringList args;
+ bool folders;
+ checksum_wrapper(panel, args, folders);
+ TQValueList<vfile*> checksumFiles = files()->vfs_search(
+ KRQuery(MatchChecksumDlg::checksumTypesFilter)
+ );
+ MatchChecksumDlg dlg(args, folders, panel->realPath(),
+ (checksumFiles.size()==1 ? checksumFiles[0]->vfile_getUrl().prettyURL() : TQString()));
+}
+
+void ListPanelFunc::calcSpace() {
+ TQStringList 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 ( TQStringList::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 TQStringList & items, TDEIO::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( TQString() );
+ 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() {
+ TQStringList 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, TQ_SIGNAL( applied() ), SLOTS, TQ_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, TQ_SIGNAL( deleteAllowed() ), vfsP, TQ_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;
+ }
+
+ TQStringList 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" );
+ TQApplication::clipboard() ->setData( urlData );
+
+ if( move && files()->vfs_getType() == vfs::VIRT )
+ ( static_cast<virt_vfs*>( files() ) )->vfs_removeFiles( &fileNames );
+
+ delete fileUrls;
+ }
+}
+
+void ListPanelFunc::pasteFromClipboard() {
+ TQClipboard * cb = TQApplication::clipboard();
+ TQMimeSource * 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 ? TDEIO::CopyJob::Move : TDEIO::CopyJob::Copy, otherFunc()->files(),
+ "", PM_DEFAULT );
+ }
+}
+
+#include "panelfunc.moc"
diff --git a/src/app/Panel/panelfunc.h b/src/app/Panel/panelfunc.h
new file mode 100644
index 0000000..be6c362
--- /dev/null
+++ b/src/app/Panel/panelfunc.h
@@ -0,0 +1,106 @@
+/***************************************************************************
+ 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 <tqobject.h>
+#include <tqvaluestack.h>
+#include <tqtimer.h>
+
+class ListPanelFunc : public TQObject{
+friend class ListPanel;
+ TQ_OBJECT
+
+public slots:
+ inline vfile* getVFile(KrViewItem *item) { return files()->vfs_search(item->name()); }
+ inline vfile* getVFile(const TQString& name) { return files()->vfs_search(name); }
+ void execute(TQString&);
+ void openUrl(const KURL& path, const TQString& nameToMakeCurrent = TQString());
+ void openUrl(const TQString& path, const TQString& nameToMakeCurrent = TQString());
+ void immediateOpenUrl( const KURL& path);
+ void doOpenUrl();
+ void refresh();
+ void rename(const TQString &oldname, const TQString &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 TQStringList & items,TDEIO::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
+ TQValueStack<KURL> urlStack; // Path stack for the "back" button
+ bool inRefresh; // true when we are in refresh()
+ vfs* vfsP; // pointer to vfs.
+ TQTimer delayTimer;
+ KURL delayURL;
+ TQString nameToMakeCurrent;
+};
+
+#endif
diff --git a/src/app/Panel/panelpopup.cpp b/src/app/Panel/panelpopup.cpp
new file mode 100644
index 0000000..d54692e
--- /dev/null
+++ b/src/app/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 <tqtooltip.h>
+#include <tqbuttongroup.h>
+#include <tqtoolbutton.h>
+#include <tdefiletreeview.h>
+#include <tdelocale.h>
+#include <tqcursor.h>
+#include <tqlayout.h>
+#include <tqlabel.h>
+#include <tqheader.h>
+#include <krview.h>
+#include <krviewitem.h>
+#include <klineedit.h>
+#include <tdeio/jobclasses.h>
+#include "../KViewer/kimagefilepreview.h"
+#include "../KViewer/panelviewer.h"
+#include "../KViewer/diskusageviewer.h"
+
+PanelPopup::PanelPopup( TQSplitter *parent, bool left ) : TQWidget( parent ),
+ _left( left ), _hidden(true), stack( 0 ), viewer( 0 ), pjob( 0 ), splitterSizes() {
+ splitter = parent;
+ TQGridLayout * layout = new TQGridLayout(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, TQ_SIGNAL( clicked() ), this, TQ_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 );
+ TQPalette q( dataLine->palette() );
+ q.setColor( TQColorGroup::Foreground, TDEGlobalSettings::textColor() );
+ q.setColor( TQColorGroup::Background, TDEGlobalSettings::baseColor() );
+ dataLine->setPalette( q );
+ dataLine->setFrameStyle( TQFrame::Box | TQFrame::Raised );
+ dataLine->setLineWidth( 1 ); // a nice 3D touch :-)
+ int sheight = TQFontMetrics( dataLine->font() ).height() + 4;
+ dataLine->setMaximumHeight( sheight );
+
+ btns = new TQButtonGroup(this);
+ btns->setExclusive(true);
+ btns->hide(); // it should be invisible
+ connect(btns, TQ_SIGNAL(clicked(int)), this, TQ_SLOT(tabSelected(int)));
+
+ treeBtn = new TQToolButton(this);
+ TQToolTip::add(treeBtn, i18n("Tree Panel: a tree view of the local file system"));
+ treeBtn->setPixmap(krLoader->loadIcon( "view_tree", TDEIcon::Toolbar, 16 ));
+ treeBtn->setFixedSize(20, 20);
+ treeBtn->setToggleButton(true);
+ btns->insert(treeBtn, Tree);
+
+
+ previewBtn = new TQToolButton(this);
+ TQToolTip::add(previewBtn, i18n("Preview Panel: display a preview of the current file"));
+ previewBtn->setPixmap(krLoader->loadIcon( "thumbnail", TDEIcon::Toolbar, 16 ));
+ previewBtn->setFixedSize(20, 20);
+ previewBtn->setToggleButton(true);
+ btns->insert(previewBtn, Preview);
+
+ quickBtn = new TQToolButton(this);
+ TQToolTip::add(quickBtn, i18n("Quick Panel: quick way to perform actions"));
+ quickBtn->setPixmap(krLoader->loadIcon( "misc", TDEIcon::Toolbar, 16 ));
+ quickBtn->setFixedSize(20, 20);
+ quickBtn->setToggleButton(true);
+ btns->insert(quickBtn, QuickPanel);
+
+ viewerBtn = new TQToolButton(this);
+ TQToolTip::add(viewerBtn, i18n("View Panel: view the current file"));
+ viewerBtn->setPixmap(krLoader->loadIcon( "viewmag", TDEIcon::Toolbar, 16 ));
+ viewerBtn->setFixedSize(20, 20);
+ viewerBtn->setToggleButton(true);
+ btns->insert(viewerBtn, View);
+
+ duBtn = new TQToolButton(this);
+ TQToolTip::add(duBtn, i18n("Disk Usage Panel: view the usage of a directory"));
+ duBtn->setPixmap(krLoader->loadIcon( "kr_diskusage", TDEIcon::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 TQWidgetStack( this );
+
+ // create the tree part ----------
+ tree = new KFileTreeView( stack );
+ tree->setAcceptDrops(true);
+ connect(tree, TQ_SIGNAL(dropped (TQWidget *, TQDropEvent *, KURL::List &, KURL &)),
+ this, TQ_SLOT(slotDroppedOnTree(TQWidget *, TQDropEvent *, KURL::List&, KURL& )));
+ stack->addWidget( tree, Tree );
+ tree->addColumn( "" );
+ // add ~
+ tree->addBranch( TQDir::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, TQ_SIGNAL(doubleClicked(TQListViewItem*)), this, TQ_SLOT(treeSelection(TQListViewItem*)));
+ // 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, TQ_SIGNAL(openURLRequest(const KURL &)), this, TQ_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, TQ_SIGNAL(openURLRequest(const KURL &)), this, TQ_SLOT(handleOpenURLRequest(const KURL &)));
+
+ // create the quick-panel part ----
+
+ TQWidget *quickPanel = new TQWidget(stack);
+ TQGridLayout *qlayout = new TQGridLayout(quickPanel);
+ // --- quick select
+ TQLabel *selectLabel = new TQLabel(i18n("Quick Select"), quickPanel);
+ quickSelectCombo = new KComboBox( quickPanel );
+ quickSelectCombo->setEditable( true );
+ krConfig->setGroup( "Private" );
+ TQStrList lst;
+ int i = krConfig->readListEntry( "Predefined Selections", lst );
+ if ( i > 0 )
+ quickSelectCombo->insertStrList( lst );
+ quickSelectCombo->setCurrentText( "*" );
+ quickSelectCombo->setSizePolicy( TQSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Preferred ) );
+
+ connect(quickSelectCombo, TQ_SIGNAL(returnPressed(const TQString& )),
+ this, TQ_SLOT(quickSelect(const TQString& )));
+
+ TQToolButton *qselectBtn = new TQToolButton(quickPanel);
+ qselectBtn->setPixmap(krLoader->loadIcon( "kr_selectall", TDEIcon::Toolbar, 16 ));
+ qselectBtn->setFixedSize(20, 20);
+ TQToolTip::add( qselectBtn, i18n("apply the selection") );
+ connect(qselectBtn, TQ_SIGNAL(clicked()), this, TQ_SLOT(quickSelect()));
+
+ TQToolButton *qstoreBtn = new TQToolButton(quickPanel);
+ qstoreBtn->setPixmap(krLoader->loadIcon( "document-save", TDEIcon::Toolbar, 16 ));
+ qstoreBtn->setFixedSize(20, 20);
+ TQToolTip::add( qstoreBtn, i18n("store the current selection") );
+ connect(qstoreBtn, TQ_SIGNAL(clicked()), this, TQ_SLOT(quickSelectStore()));
+
+ TQToolButton *qsettingsBtn = new TQToolButton(quickPanel);
+ qsettingsBtn->setPixmap(krLoader->loadIcon( "configure", TDEIcon::Toolbar, 16 ));
+ qsettingsBtn->setFixedSize(20, 20);
+ TQToolTip::add( qsettingsBtn, i18n("select group dialog") );
+ connect(qsettingsBtn, TQ_SIGNAL(clicked()), krSelect, TQ_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() {
+ TQWidget::show();
+ if( _hidden )
+ splitter->setSizes( splitterSizes );
+ _hidden = false;
+ tabSelected( stack->id(stack->visibleWidget()) );
+}
+
+
+void PanelPopup::hide() {
+ if( !_hidden )
+ splitterSizes = splitter->sizes();
+ TQWidget::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(TQListViewItem*) {
+ emit selection(tree->currentURL());
+ //emit hideMe();
+}
+
+// ------------------- quick panel
+
+void PanelPopup::quickSelect() {
+ SLOTS->markGroup(quickSelectCombo->currentText(), true);
+}
+
+void PanelPopup::quickSelect(const TQString &mask) {
+ SLOTS->markGroup(mask, true);
+}
+
+void PanelPopup::quickSelectStore() {
+ krConfig->setGroup( "Private" );
+ TQStringList lst = krConfig->readListEntry( "Predefined Selections" );
+ if ( lst.find(quickSelectCombo->currentText()) == lst.end() )
+ lst.append( quickSelectCombo->currentText() );
+ krConfig->writeEntry( "Predefined Selections", lst );
+}
+
+void PanelPopup::slotDroppedOnTree(TQWidget *widget, TQDropEvent *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?
+ TQPopupMenu 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 );
+ TQPoint tmp = widget->mapToGlobal( e->pos() );
+ int result = popup.exec( TQCursor::pos() );
+
+ TDEIO::CopyJob *job;
+ switch ( result ) {
+ case 1 :
+ job = TDEIO::copy(lst, dest, true);
+ break;
+ case 2 :
+ job = TDEIO::move(lst, dest, true);
+ break;
+ case 3 :
+ job = TDEIO::link(lst, dest, true);
+ break;
+ case - 1 : // user pressed outside the menu
+ case 4:
+ return ; // cancel was pressed;
+ }
+}
+
+#include "panelpopup.moc"
diff --git a/src/app/Panel/panelpopup.h b/src/app/Panel/panelpopup.h
new file mode 100644
index 0000000..47b6c94
--- /dev/null
+++ b/src/app/Panel/panelpopup.h
@@ -0,0 +1,74 @@
+#ifndef _PANELPOPUP_H
+#define _PANELPOPUP_H
+
+#include <tqwidget.h>
+#include <tqwidgetstack.h>
+#include <tqpixmap.h>
+#include <tqvaluelist.h>
+#include <tdefileitem.h>
+#include <tqguardedptr.h>
+#include <tdeio/previewjob.h>
+#include <kurl.h>
+
+class TQButtonGroup;
+class TQLabel;
+class TQListViewItem;
+class TQSplitter;
+class KFileTreeView;
+class TQToolButton;
+class KrSqueezedTextLabel;
+class KLineEdit;
+class KComboBox;
+class KrusaderImageFilePreview;
+class PanelViewer;
+class DiskUsageViewer;
+
+class PanelPopup: public TQWidget {
+ TQ_OBJECT
+
+ enum Parts { Tree, Preview, QuickPanel, View, DskUsage, Last=0xFF };
+public:
+ PanelPopup( TQSplitter *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(TQListViewItem*);
+ void slotDroppedOnTree(TQWidget *widget, TQDropEvent *e, KURL::List &lst, KURL &);
+ void handleOpenURLRequest(const KURL &url);
+ void quickSelect();
+ void quickSelect(const TQString &);
+ void quickSelectStore();
+
+protected:
+ bool _left;
+ bool _hidden;
+ TQWidgetStack *stack;
+ KrusaderImageFilePreview *viewer;
+ KrSqueezedTextLabel *dataLine;
+ TQGuardedPtr<TDEIO::PreviewJob> pjob;
+ KFileTreeView *tree;
+ TQToolButton *treeBtn, *previewBtn, *quickBtn, *viewerBtn, *duBtn;
+ TQButtonGroup *btns;
+ KLineEdit *quickFilter;
+ KComboBox *quickSelectCombo;
+ PanelViewer *panelviewer;
+ DiskUsageViewer *diskusage;
+ TQValueList<int> splitterSizes;
+ TQSplitter *splitter;
+};
+
+#endif // _PANELPOPUP_H
diff --git a/src/app/Queue/Makefile.am b/src/app/Queue/Makefile.am
new file mode 100644
index 0000000..1630c6a
--- /dev/null
+++ b/src/app/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/src/app/Queue/queue.cpp b/src/app/Queue/queue.cpp
new file mode 100644
index 0000000..f6677f6
--- /dev/null
+++ b/src/app/Queue/queue.cpp
@@ -0,0 +1,22 @@
+#include "queue.h"
+
+Queue::Queue(const TQString& name): _name(name)
+{
+}
+
+Queue::~Queue()
+{
+ // TODO: save queue on delete? or just delete jobs
+}
+
+void Queue::enqueue(TDEIO::Job *job)
+{
+ _jobs.append(job);
+
+ dumpQueue();
+}
+
+void Queue::dumpQueue()
+{
+ tqDebug("Queue: %s", name().latin1());
+}
diff --git a/src/app/Queue/queue.h b/src/app/Queue/queue.h
new file mode 100644
index 0000000..8f3a598
--- /dev/null
+++ b/src/app/Queue/queue.h
@@ -0,0 +1,33 @@
+#ifndef QUEUE_H
+#define QUEUE_H
+
+#include <tqobject.h>
+#include <tdeio/jobclasses.h>
+#include <tqptrlist.h>
+
+/**
+ * Queue can hold anything which inherits TDEIO::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 TQObject
+{
+ TQ_OBJECT
+
+public:
+ Queue(const TQString& name);
+ virtual ~Queue();
+
+ inline const TQString& name() const { return _name; }
+ void enqueue(TDEIO::Job *job);
+
+protected:
+ void dumpQueue();
+
+ TQString _name;
+ TQPtrList<TDEIO::Job> _jobs;
+};
+
+#endif // QUEUE_H
diff --git a/src/app/Queue/queue_mgr.cpp b/src/app/Queue/queue_mgr.cpp
new file mode 100644
index 0000000..f7f0b27
--- /dev/null
+++ b/src/app/Queue/queue_mgr.cpp
@@ -0,0 +1,31 @@
+#include "queue_mgr.h"
+
+const TQString QueueManager::defaultName="default";
+TQMap<TQString, Queue*> QueueManager::_queues;
+
+QueueManager::QueueManager()
+{
+ Queue *defaultQ = new Queue(defaultName);
+ _queues.insert(defaultQ->name(), defaultQ);
+}
+
+QueueManager::~QueueManager()
+{
+ TQMap<TQString, Queue*>::iterator it;
+ for (it = _queues.begin(); it != _queues.end(); ++it )
+ delete it.data();
+ _queues.clear();
+}
+
+Queue* QueueManager::queue(const TQString& queueName)
+{
+ if (!_queues.contains(queueName))
+ return 0;
+ return _queues[queueName];
+}
+
+TQValueList<TQString> QueueManager::queues() const
+{
+ return _queues.keys();
+}
+
diff --git a/src/app/Queue/queue_mgr.h b/src/app/Queue/queue_mgr.h
new file mode 100644
index 0000000..c2b8bc9
--- /dev/null
+++ b/src/app/Queue/queue_mgr.h
@@ -0,0 +1,26 @@
+#ifndef QUEUE_MGR_H
+#define QUEUE_MGR_H
+
+#include "queue.h"
+#include <tqmap.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 TQString defaultName;
+public:
+ QueueManager();
+ ~QueueManager();
+
+ static Queue* queue(const TQString& queueName=defaultName);
+ TQValueList<TQString> queues() const;
+
+protected:
+ static TQMap<TQString, Queue*> _queues;
+};
+
+#endif // QUEUE_MGR_H
diff --git a/src/app/Queue/queuewidget.cpp b/src/app/Queue/queuewidget.cpp
new file mode 100644
index 0000000..65c11da
--- /dev/null
+++ b/src/app/Queue/queuewidget.cpp
@@ -0,0 +1,10 @@
+#include "queuewidget.h"
+
+QueueWidget::QueueWidget(): KTabWidget()
+{
+}
+
+
+QueueWidget::~QueueWidget()
+{
+}
diff --git a/src/app/Queue/queuewidget.h b/src/app/Queue/queuewidget.h
new file mode 100644
index 0000000..090622e
--- /dev/null
+++ b/src/app/Queue/queuewidget.h
@@ -0,0 +1,15 @@
+#ifndef QUEUE_WIDGET_H
+#define QUEUE_WIDGET_H
+
+#include <ktabwidget.h>
+
+class QueueWidget: public KTabWidget
+{
+ TQ_OBJECT
+
+public:
+ QueueWidget();
+ ~QueueWidget();
+};
+
+#endif // QUEUE_WIDGET_H
diff --git a/src/app/RemoteMan/Makefile.am b/src/app/RemoteMan/Makefile.am
new file mode 100644
index 0000000..cff7637
--- /dev/null
+++ b/src/app/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/src/app/RemoteMan/remoteman.cpp b/src/app/RemoteMan/remoteman.cpp
new file mode 100644
index 0000000..2374f86
--- /dev/null
+++ b/src/app/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 <tqlineedit.h>
+#include <tdelocale.h>
+#include <tqpixmap.h>
+#include <tqspinbox.h>
+#include <tqmultilineedit.h>
+#include <tqpushbutton.h>
+#include <tqstringlist.h>
+#include <tqmessagebox.h>
+#include <tqcheckbox.h>
+#include <kstandarddirs.h>
+
+TQString remoteMan::url=TQString();
+
+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(TQLineEdit::Password);
+ // ===> should be moved to remoteManBase <=====
+ connect( hostName, TQ_SIGNAL( textChanged(const TQString&) ),
+ this, TQ_SLOT( updateConnect(const TQString&) ) );
+ connect( sessions, TQ_SIGNAL(doubleClicked(TQListViewItem *)), this, TQ_SLOT(connection()));
+ connect( sessions, TQ_SIGNAL(returnPressed(TQListViewItem *)), this, TQ_SLOT(connection()));
+ // execute the main dialog
+ exec();
+}
+
+void remoteMan::expandDecos(TQListViewItem* i) {
+ if (i->text(1)!="SESSION") i->setPixmap(0,LOADICON("folder_open"));
+}
+void remoteMan::collapseDecos(TQListViewItem* i) {
+ if (i->text(1)!="SESSION") i->setPixmap(0,LOADICON("folder_open"));
+}
+
+// This is the static memeber, you'd want to call this directly !
+TQString remoteMan::getHost() {
+ remoteMan *p=new remoteMan();
+ delete p;
+ return url;
+}
+
+// adds a new group submenu
+void remoteMan::addGroup() {
+ TQListViewItem *i=0,*current;
+ current=sessions->currentItem();
+ if (!current) // no item is current, or the list is empty (shouldn't happen)
+ i=new TQListViewItem(sessions,i18n("New group"),"GROUP"); // insert into the backplane
+ else
+ if (current->text(1).left(5)=="GROUP")
+ i=new TQListViewItem(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() {
+ TQListViewItem *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 TQListViewItem(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
+ TQListViewItem *i;
+ if (currentItem->parent()) i=currentItem->parent()->firstChild();
+ else i=sessions->firstChild();
+ while (i) {
+ if (i->text(0)==currentItem->text(0) && i!=currentItem) {
+ TQString 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=TQString("<%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);
+ TQListViewItem *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 TQString &text) {
+ TQListViewItem *i=sessions->currentItem();
+ i->setText(0,text);
+}
+
+void remoteMan::updateConnect(const TQString &) {
+ // 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
+TQString item2connection(TQListViewItem *item) {
+ TQString con=item->text(0);
+ TQListViewItem *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
+ TQString 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,TQChar('\''));
+ 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
+TQListViewItem* remoteMan::findItem(const TQString &name, TQListViewItem *p) {
+ TQListViewItem *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 TQListViewItem(sessions,name.left(loc),"GROUP");
+ else it=new TQListViewItem(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");
+ TQStringList lst=krConfig->readListEntry("Connections");
+ if (lst.count()<1) { // no such list in the config file - create the basics
+ // add the default groups
+ TQListViewItem *i;
+ i=new TQListViewItem(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 TQListViewItem(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...
+ TQStringList::Iterator it;
+ TQListViewItem *item=0;
+ for( it = lst.begin(); it != lst.end(); ++it ) {
+ TQString 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
+ TQStringList newLst=krConfig->readListEntry(*it); // and fill in
+ bool group=(newLst[1]!="SESSION");
+ TQListViewItem *newItem;
+ if (item==0) // if this item originating from the backplane
+ newItem=new TQListViewItem(sessions,t,group ? "GROUP" : "SESSION");
+ else
+ newItem=new TQListViewItem(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");
+ TQStringList lst;
+ TQListViewItemIterator it(sessions);
+ while (it.current()) { // while there are still items in the tree
+ TQString 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");
+ TQStringList 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...
+ TQListViewItem *i=sessions->currentItem();
+ if (i->text(1)!="SESSION") {
+ i->setOpen(i->isOpen());
+ return;
+ }
+ // build a url
+ if (anonymous->isChecked()) {
+ userName->setText(TQString());
+ password->setText(TQString());
+ } 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());
+
+ TQString 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() {
+
+ TQListViewItem *it=sessions->currentItem();
+ if (!it) return; // don't do anything if no item is selected
+ switch( TQMessageBox::warning( this, i18n("RemoteMan"),
+ i18n("Are you sure you want to delete this item ???"),
+ TQMessageBox::Yes,
+ TQMessageBox::No | TQMessageBox::Default | TQMessageBox::Escape)) {
+ case TQMessageBox::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=TQString(); // 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=TQString(); // this signals getHost() we didn't click CONNECT
+ remoteManBase::reject();
+}
+
+#include "remoteman.moc"
diff --git a/src/app/RemoteMan/remoteman.h b/src/app/RemoteMan/remoteman.h
new file mode 100644
index 0000000..795d597
--- /dev/null
+++ b/src/app/RemoteMan/remoteman.h
@@ -0,0 +1,71 @@
+/***************************************************************************
+ 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 <tqlistview.h>
+
+class remoteMan : public remoteManBase {
+ TQ_OBJECT
+
+public:
+ remoteMan();
+ static TQString getHost(); // we call remoteMan mainly with this function
+
+protected:
+ void config2tree(); // internal
+ void tree2config(); // internal
+ TQListViewItem *findItem(const TQString &name, TQListViewItem *p);
+
+public slots:
+ void addGroup();
+ void refreshData() ; // called whenver the current session changes
+ void updateName(const TQString&); // update the session/group name in real-time
+ void updateConnect(const TQString&); // enable/disable the connect button in real-time
+ void addSession();
+ void connection();
+ void removeSession();
+ void expandDecos(TQListViewItem*);
+ void collapseDecos(TQListViewItem*);
+
+protected slots:
+ void accept();
+ void reject();
+
+private:
+ TQListViewItem *currentItem;
+ static TQString url;
+};
+
+#endif
diff --git a/src/app/RemoteMan/remotemanbase.cpp b/src/app/RemoteMan/remotemanbase.cpp
new file mode 100644
index 0000000..a48f9dc
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <tqcheckbox.h>
+#include <tqcombobox.h>
+#include <tqheader.h>
+#include <tqlabel.h>
+#include <tqlineedit.h>
+#include <tqlistview.h>
+#include <tqmultilineedit.h>
+#include <tqpushbutton.h>
+#include <tqspinbox.h>
+#include <tqlayout.h>
+#include <tqvariant.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.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( TQWidget* parent, const char* name, bool modal, WFlags fl )
+ : TQDialog( parent, name, modal, fl )
+{
+ if ( !name )
+ setName( "remoteManBase" );
+ resize( 670, 502 );
+ setCaption( i18n( "RemoteMan: Connection Manager" ) );
+ setSizeGripEnabled( true );
+ remoteManBaseLayout = new TQGridLayout( this );
+ remoteManBaseLayout->setSpacing( 6 );
+ remoteManBaseLayout->setMargin( 11 );
+
+ Layout23 = new TQVBoxLayout;
+ Layout23->setSpacing( 6 );
+ Layout23->setMargin( 0 );
+
+ TextLabel1 = new TQLabel( this, "TextLabel1" );
+ TextLabel1->setText( i18n( "Session name:" ) );
+ Layout23->addWidget( TextLabel1 );
+
+ sessionName = new TQLineEdit( this, "sessionName" );
+ Layout23->addWidget( sessionName );
+
+ remoteManBaseLayout->addLayout( Layout23, 0, 1 );
+
+ Layout12 = new TQHBoxLayout;
+ Layout12->setSpacing( 6 );
+ Layout12->setMargin( 0 );
+ TQSpacerItem* spacer = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum );
+ Layout12->addItem( spacer );
+
+ moreBtn = new TQPushButton( this, "moreBtn" );
+ moreBtn->setText( i18n( "&More" ) );
+ moreBtn->setAutoDefault( false );
+ moreBtn->setDefault( false );
+ Layout12->addWidget( moreBtn );
+
+ closeBtn = new TQPushButton( this, "closeBtn" );
+ closeBtn->setText( i18n( "&Close" ) );
+ closeBtn->setAutoDefault( false );
+ closeBtn->setDefault( false );
+ Layout12->addWidget( closeBtn );
+
+ remoteManBaseLayout->addMultiCellLayout( Layout12, 7, 7, 0, 1 );
+
+ sessions = new TQListView( this, "sessions" );
+ sessions->addColumn( i18n( "Sessions" ) );
+ sessions->header()->setClickEnabled( false, sessions->header()->count() - 1 );
+ sessions->header()->setResizeEnabled( false, sessions->header()->count() - 1 );
+ sessions->setMinimumSize( TQSize( 300, 400 ) );
+ sessions->setVScrollBarMode( TQListView::AlwaysOn );
+ sessions->setHScrollBarMode( TQListView::Auto );
+ sessions->setRootIsDecorated( true );
+
+ remoteManBaseLayout->addMultiCellWidget( sessions, 0, 6, 0, 0 );
+
+ Layout9 = new TQVBoxLayout;
+ Layout9->setSpacing( 6 );
+ Layout9->setMargin( 0 );
+
+ Layout10 = new TQGridLayout;
+ Layout10->setSpacing( 6 );
+ Layout10->setMargin( 0 );
+
+ TextLabel1_3_3 = new TQLabel( this, "TextLabel1_3_3" );
+ TextLabel1_3_3->setText( i18n( "Password:" ) );
+
+ Layout10->addWidget( TextLabel1_3_3, 0, 1 );
+
+ password = new TQLineEdit( this, "password" );
+
+ Layout10->addWidget( password, 1, 1 );
+
+ TextLabel1_3 = new TQLabel( this, "TextLabel1_3" );
+ TextLabel1_3->setText( i18n( "User name:" ) );
+
+ Layout10->addWidget( TextLabel1_3, 0, 0 );
+
+ userName = new TQLineEdit( this, "userName" );
+
+ Layout10->addWidget( userName, 1, 0 );
+ Layout9->addLayout( Layout10 );
+
+ anonymous = new TQCheckBox( this, "anonymous" );
+ anonymous->setText( i18n( "Anonymous" ) );
+ Layout9->addWidget( anonymous );
+
+ remoteManBaseLayout->addLayout( Layout9, 2, 1 );
+
+ Layout26 = new TQVBoxLayout;
+ Layout26->setSpacing( 6 );
+ Layout26->setMargin( 0 );
+
+ TextLabel1_3_2 = new TQLabel( this, "TextLabel1_3_2" );
+ TextLabel1_3_2->setText( i18n( "Remote directory:" ) );
+ Layout26->addWidget( TextLabel1_3_2 );
+
+ remoteDir = new TQLineEdit( this, "remoteDir" );
+ Layout26->addWidget( remoteDir );
+
+ remoteManBaseLayout->addLayout( Layout26, 4, 1 );
+
+ Layout27 = new TQVBoxLayout;
+ Layout27->setSpacing( 6 );
+ Layout27->setMargin( 0 );
+
+ TextLabel1_3_2_2 = new TQLabel( this, "TextLabel1_3_2_2" );
+ TextLabel1_3_2_2->setText( i18n( "Description:" ) );
+ Layout27->addWidget( TextLabel1_3_2_2 );
+
+ description = new TQMultiLineEdit( this, "description" );
+ Layout27->addWidget( description );
+
+ remoteManBaseLayout->addLayout( Layout27, 5, 1 );
+
+ layout = new TQGridLayout;
+ layout->setSpacing( 6 );
+ layout->setMargin( 0 );
+
+ removeBtn = new TQPushButton( this, "removeBtn" );
+ removeBtn->setText( i18n( "&Remove" ) );
+ removeBtn->setAutoDefault( false );
+ removeBtn->setDefault( false );
+
+ layout->addWidget( removeBtn, 0, 2 );
+
+ connectBtn = new TQPushButton( this, "connectBtn" );
+ connectBtn->setText( i18n( "Co&nnect" ) );
+ connectBtn->setAutoDefault( false );
+ connectBtn->setDefault( false );
+
+ layout->addMultiCellWidget( connectBtn, 1, 1, 0, 2 );
+
+ newGroupBtn = new TQPushButton( 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 TQPushButton( 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 TQGridLayout;
+ Layout11->setSpacing( 6 );
+ Layout11->setMargin( 0 );
+
+ TextLabel1_2 = new TQLabel( this, "TextLabel1_2" );
+ TextLabel1_2->setText( i18n( "Host:" ) );
+
+ Layout11->addMultiCellWidget( TextLabel1_2, 0, 0, 0, 1 );
+
+ TQStringList protocols = KProtocolInfo::protocols();
+
+ protocol = new TQComboBox( 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( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, protocol->sizePolicy().hasHeightForWidth() ) );
+
+ Layout11->addWidget( protocol, 1, 0 );
+
+ hostName = new TQLineEdit( this, "hostName" );
+ hostName->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)7, (TQSizePolicy::SizeType)0, hostName->sizePolicy().hasHeightForWidth() ) );
+ hostName->setMinimumSize( TQSize( 0, 0 ) );
+
+ Layout11->addWidget( hostName, 1, 1 );
+
+ portNum = new TQSpinBox( this, "portNum" );
+ portNum->setMaxValue( 99999 );
+ portNum->setValue( 21 );
+
+ Layout11->addWidget( portNum, 1, 2 );
+
+ TextLabel1_2_2 = new TQLabel( 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 TQLabel( this, "TextLabel1_4" );
+ TQFont 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( TQLabel::AlignVCenter | TQLabel::AlignRight ) );
+
+ remoteManBaseLayout->addWidget( TextLabel1_4, 3, 1 );
+
+ // signals and slots connections
+ connect( closeBtn, TQ_SIGNAL( clicked() ), this, TQ_SLOT( accept() ) );
+ connect( addBtn, TQ_SIGNAL( clicked() ), this, TQ_SLOT( addSession() ) );
+ connect( removeBtn, TQ_SIGNAL( clicked() ), this, TQ_SLOT( removeSession() ) );
+ connect( sessions, TQ_SIGNAL( selectionChanged(TQListViewItem*) ), this, TQ_SLOT( refreshData() ) );
+ connect( sessions, TQ_SIGNAL( selectionChanged() ), this, TQ_SLOT( refreshData() ) );
+ connect( sessions, TQ_SIGNAL( expanded(TQListViewItem*) ), this, TQ_SLOT( refreshData() ) );
+ connect( sessions, TQ_SIGNAL( currentChanged(TQListViewItem*) ), this, TQ_SLOT( refreshData() ) );
+ connect( sessions, TQ_SIGNAL( mouseButtonClicked(int,TQListViewItem*,const
+TQPoint&,int) ), this, TQ_SLOT( refreshData() ) );
+ connect( sessions, TQ_SIGNAL( collapsed(TQListViewItem*) ), this, TQ_SLOT( refreshData() ) );
+ connect( connectBtn, TQ_SIGNAL( clicked() ), this, TQ_SLOT( connection() ) );
+ connect( sessionName, TQ_SIGNAL( textChanged(const TQString&) ), this, TQ_SLOT( updateName(const TQString&) ) );
+ connect( newGroupBtn, TQ_SIGNAL( clicked() ), this, TQ_SLOT( addGroup() ) );
+ connect( anonymous, TQ_SIGNAL( clicked() ), this, TQ_SLOT( refreshData() ) );
+ connect( protocol, TQ_SIGNAL(activated(int)), this, TQ_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, TQt does it all for us
+}
+
+/*
+ * Main event handler. Reimplemented to handle application
+ * font changes
+ */
+bool remoteManBase::event( TQEvent* ev )
+{
+ bool ret = TQDialog::event( ev );
+ if ( ev->type() == TQEvent::ApplicationFontChange ) {
+ TQFont TextLabel1_4_font( TextLabel1_4->font() );
+ TextLabel1_4_font.setPointSize( 10 );
+ TextLabel1_4->setFont( TextLabel1_4_font );
+ }
+ return ret;
+}
+
+void remoteManBase::addSession()
+{
+ tqWarning( "remoteManBase::addSession(): Not implemented yet!" );
+}
+
+void remoteManBase::connection()
+{
+ tqWarning( "remoteManBase::connection(): Not implemented yet!" );
+}
+
+void remoteManBase::moreInfo()
+{
+ tqWarning( "remoteManBase::moreInfo(): Not implemented yet!" );
+}
+
+void remoteManBase::addGroup()
+{
+ tqWarning( "remoteManBase::addGroup(): Not implemented yet!" );
+}
+
+void remoteManBase::refreshData()
+{
+ tqWarning( "remoteManBase::refreshData(): Not implemented yet!" );
+}
+
+void remoteManBase::removeSession()
+{
+ tqWarning( "remoteManBase::removeSession(): Not implemented yet!" );
+}
+
+void remoteManBase::updateName(const TQString&)
+{
+ tqWarning( "remoteManBase::updateName(const TQString&): Not implemented yet!" );
+}
+
+#include "remotemanbase.moc"
diff --git a/src/app/RemoteMan/remotemanbase.h b/src/app/RemoteMan/remotemanbase.h
new file mode 100644
index 0000000..b9c9f67
--- /dev/null
+++ b/src/app/RemoteMan/remotemanbase.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+** 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 <tqvariant.h>
+#include <tqdialog.h>
+class TQVBoxLayout;
+class TQHBoxLayout;
+class TQGridLayout;
+class TQCheckBox;
+class TQComboBox;
+class TQLabel;
+class TQLineEdit;
+class TQListView;
+class TQListViewItem;
+class TQMultiLineEdit;
+class TQPushButton;
+class TQSpinBox;
+
+class remoteManBase : public TQDialog
+{
+ TQ_OBJECT
+
+
+public:
+ remoteManBase( TQWidget* parent = 0, const char* name = 0, bool modal = false, WFlags fl = 0 );
+ ~remoteManBase();
+
+ TQLabel* TextLabel1;
+ TQLineEdit* sessionName;
+ TQPushButton* moreBtn;
+ TQPushButton* closeBtn;
+ TQListView* sessions;
+ TQLabel* TextLabel1_3_3;
+ TQLineEdit* password;
+ TQLabel* TextLabel1_3;
+ TQLineEdit* userName;
+ TQCheckBox* anonymous;
+ TQLabel* TextLabel1_3_2;
+ TQLineEdit* remoteDir;
+ TQLabel* TextLabel1_3_2_2;
+ TQMultiLineEdit* description;
+ TQPushButton* removeBtn;
+ TQPushButton* connectBtn;
+ TQPushButton* newGroupBtn;
+ TQPushButton* addBtn;
+ TQLabel* TextLabel1_2;
+ TQComboBox* protocol;
+ TQLineEdit* hostName;
+ TQSpinBox* portNum;
+ TQLabel* TextLabel1_2_2;
+ TQLabel* 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 TQString&);
+
+protected:
+ TQGridLayout* remoteManBaseLayout;
+ TQVBoxLayout* Layout23;
+ TQHBoxLayout* Layout12;
+ TQVBoxLayout* Layout9;
+ TQGridLayout* Layout10;
+ TQVBoxLayout* Layout26;
+ TQVBoxLayout* Layout27;
+ TQGridLayout* layout;
+ TQGridLayout* Layout11;
+ bool event( TQEvent* );
+};
+
+#endif // REMOTEMANBASE_H
diff --git a/src/app/Search/Makefile.am b/src/app/Search/Makefile.am
new file mode 100644
index 0000000..e43b3de
--- /dev/null
+++ b/src/app/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/src/app/Search/krsearchdialog.cpp b/src/app/Search/krsearchdialog.cpp
new file mode 100644
index 0000000..af87f95
--- /dev/null
+++ b/src/app/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 <tqregexp.h>
+#include <tqfontmetrics.h>
+#include <tdemessagebox.h>
+#include <tdepopupmenu.h>
+#include <tqcursor.h>
+#include <tqclipboard.h>
+#include <tqheader.h>
+#include <kurldrag.h>
+#include <../kicons.h>
+
+class SearchListView : public TQListView
+{
+public:
+ SearchListView( TQWidget * parent, const char * name ) : TQListView( parent, name )
+ {
+ }
+
+ void startDrag()
+ {
+ KURL::List urls;
+
+ TQListViewItem * item = firstChild();
+ while( item )
+ {
+ if( item->isSelected() )
+ {
+ TQString 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" ), TQPoint( -7, 0 ) );
+ d->dragCopy();
+ }
+};
+
+
+
+KrSearchDialog *KrSearchDialog::SearchDialog = 0;
+
+TQString 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( TQString profile, TQWidget* parent, const char* name, bool modal, WFlags fl )
+ : TQDialog( parent, name, modal, fl ), query(0), searcher(0)
+{
+ setCaption( i18n( "Krusader::Search" ) );
+
+ TQGridLayout* searchBaseLayout = new TQGridLayout( this );
+ searchBaseLayout->setSpacing( 6 );
+ searchBaseLayout->setMargin( 11 );
+
+ // creating the dialog buttons ( Search, Stop, Close )
+
+ TQHBoxLayout* buttonsLayout = new TQHBoxLayout();
+ buttonsLayout->setSpacing( 6 );
+ buttonsLayout->setMargin( 0 );
+
+ profileManager = new ProfileManager( "SearcherProfile", this, "profileManager" );
+ buttonsLayout->addWidget( profileManager );
+
+ TQSpacerItem* spacer = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum );
+ buttonsLayout->addItem( spacer );
+
+ mainFeedToListBoxBtn = new TQPushButton( this, "mainFeedToListBoxBtn" );
+ mainFeedToListBoxBtn->setText( i18n( "Feed to listbox" ) );
+ mainFeedToListBoxBtn->setEnabled(false);
+ buttonsLayout->addWidget( mainFeedToListBoxBtn );
+
+ mainSearchBtn = new TQPushButton( this, "mainSearchBtn" );
+ mainSearchBtn->setText( i18n( "Search" ) );
+ mainSearchBtn->setDefault(true);
+ buttonsLayout->addWidget( mainSearchBtn );
+
+ mainStopBtn = new TQPushButton( this, "mainStopBtn" );
+ mainStopBtn->setEnabled( false );
+ mainStopBtn->setText( i18n( "Stop" ) );
+ buttonsLayout->addWidget( mainStopBtn );
+
+ mainCloseBtn = new TQPushButton( this, "mainCloseBtn" );
+ mainCloseBtn->setText( i18n( "Close" ) );
+ buttonsLayout->addWidget( mainCloseBtn );
+
+ searchBaseLayout->addLayout( buttonsLayout, 1, 0 );
+
+ // creating the searcher tabs
+
+ searcherTabs = new TQTabWidget( this, "searcherTabs" );
+
+ filterTabs = FilterTabs::addTo( searcherTabs, FilterTabs::Default | FilterTabs::HasRemoteContentSearch );
+ generalFilter = (GeneralFilter *)filterTabs->get( "GeneralFilter" );
+
+ resultTab = new TQWidget( searcherTabs, "resultTab" );
+ resultLayout = new TQGridLayout( resultTab );
+ resultLayout->setSpacing( 6 );
+ resultLayout->setMargin( 11 );
+
+ // creating the result tab
+
+ TQHBoxLayout* resultLabelLayout = new TQHBoxLayout();
+ resultLabelLayout->setSpacing( 6 );
+ resultLabelLayout->setMargin( 0 );
+
+ foundLabel = new TQLabel( resultTab, "foundLabel" );
+ foundLabel->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)1, foundLabel->sizePolicy().hasHeightForWidth() ) );
+ foundLabel->setFrameShape( TQLabel::StyledPanel );
+ foundLabel->setFrameShadow( TQLabel::Sunken );
+ foundLabel->setText( i18n( "Found 0 matches." ) );
+ resultLabelLayout->addWidget( foundLabel );
+
+ searchingLabel = new KSqueezedTextLabel( resultTab, "searchingLabel" );
+ searchingLabel->setFrameShape( TQLabel::StyledPanel );
+ searchingLabel->setFrameShadow( TQLabel::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( TQListView::Extended );
+
+ // fix the results list
+ // => make the results font smaller
+ TQFont 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, TQListView::Manual);
+
+ int i=TQFontMetrics(resultsList->font()).width("W");
+ int j=TQFontMetrics(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 );
+
+ TQHBoxLayout* foundTextLayout = new TQHBoxLayout();
+ foundTextLayout->setSpacing( 6 );
+ foundTextLayout->setMargin( 0 );
+
+ TQLabel *l1 = new TQLabel(resultTab);
+ l1->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)1, l1->sizePolicy().hasHeightForWidth() ) );
+ l1->setFrameShape( TQLabel::StyledPanel );
+ l1->setFrameShadow( TQLabel::Sunken );
+ l1->setText(i18n("Text found:"));
+ foundTextLayout->addWidget( l1 );
+
+ foundTextLabel = new KrSqueezedTextLabel(resultTab);
+ foundTextLabel->setFrameShape( TQLabel::StyledPanel );
+ foundTextLabel->setFrameShadow( TQLabel::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, TQ_SIGNAL( clicked() ), this, TQ_SLOT( startSearch() ) );
+ connect( mainStopBtn, TQ_SIGNAL( clicked() ), this, TQ_SLOT( stopSearch() ) );
+ connect( resultsList, TQ_SIGNAL( returnPressed(TQListViewItem*) ), this,
+ TQ_SLOT( resultDoubleClicked(TQListViewItem*) ) );
+ connect( resultsList, TQ_SIGNAL( doubleClicked(TQListViewItem*) ), this,
+ TQ_SLOT( resultDoubleClicked(TQListViewItem*) ) );
+ connect( resultsList, TQ_SIGNAL( currentChanged(TQListViewItem*) ), this,
+ TQ_SLOT( resultClicked(TQListViewItem*) ) );
+ connect( resultsList, TQ_SIGNAL( clicked(TQListViewItem*) ), this,
+ TQ_SLOT( resultClicked(TQListViewItem*) ) );
+ connect( resultsList, TQ_SIGNAL( rightButtonClicked(TQListViewItem*,const TQPoint&,int) ), this, TQ_SLOT( rightClickMenu(TQListViewItem*, const TQPoint&, int) ) );
+ connect( mainCloseBtn, TQ_SIGNAL( clicked() ), this, TQ_SLOT( closeDialog() ) );
+ connect( mainFeedToListBoxBtn, TQ_SIGNAL( clicked() ), this, TQ_SLOT( feedToListBox() ) );
+
+ connect( profileManager, TQ_SIGNAL( loadFromProfile( TQString ) ), filterTabs, TQ_SLOT( loadFromProfile( TQString ) ) );
+ connect( profileManager, TQ_SIGNAL( saveToProfile( TQString ) ), filterTabs, TQ_SLOT( saveToProfile( TQString ) ) );
+
+ // 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 )
+ TQDialog::accept();
+ else
+ TQDialog::reject();
+
+ this->deleteLater();
+}
+
+void KrSearchDialog::reject() {
+ closeDialog( false );
+}
+
+void KrSearchDialog::resizeEvent( TQResizeEvent *e )
+{
+ if( !isMaximized() )
+ {
+ sizeX = e->size().width();
+ sizeY = e->size().height();
+ }
+}
+
+void KrSearchDialog::found(TQString what, TQString where, TDEIO::filesize_t size, time_t mtime, TQString perm, TQString foundText){
+ // convert the time_t to struct tm
+ struct tm* t=localtime((time_t *)&mtime);
+ TQDateTime tmp(TQDate(t->tm_year+1900, t->tm_mon+1, t->tm_mday), TQTime(t->tm_hour, t->tm_min));
+ ResultListViewItem *it =new ResultListViewItem(resultsList, what,
+ where.replace(TQRegExp("\\\\"),"#"), size, tmp, perm);
+ TQString totals = TQString(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("");
+ tqApp->processEvents();
+
+ // start the search.
+ if (searcher != 0) {
+ delete searcher;
+ searcher = 0;
+ }
+ searcher = new KRSearchMod(query);
+ connect(searcher, TQ_SIGNAL(searching(const TQString&)),
+ searchingLabel, TQ_SLOT(setText(const TQString&)));
+ connect(searcher, TQ_SIGNAL(found(TQString,TQString,TDEIO::filesize_t,time_t,TQString,TQString)),
+ this, TQ_SLOT(found(TQString,TQString,TDEIO::filesize_t,time_t,TQString,TQString)));
+ connect(searcher, TQ_SIGNAL(finished()), this, TQ_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(TQListViewItem* i) {
+ ACTIVE_FUNC->openUrl(vfs::fromPathOrURL(i->text(1)),i->text(0));
+ showMinimized();
+}
+
+void KrSearchDialog::resultClicked(TQListViewItem* 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(TQCloseEvent *e)
+{ /* if searching is in progress we must not close the window */
+ if( isSearching ) /* because tqApp->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
+ TQDialog::closeEvent( e ); /* if no searching, let TQDialog handle the event */
+}
+
+void KrSearchDialog::keyPressEvent(TQKeyEvent *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() && TQApplication::clipboard()->text() != generalFilter->containsText->currentText())
+ TQApplication::clipboard()->setText(generalFilter->containsText->currentText());
+ editCurrent();
+ return;
+ }
+ else if( e->key() == Key_F3 )
+ {
+ if (!generalFilter->containsText->currentText().isEmpty() && TQApplication::clipboard()->text() != generalFilter->containsText->currentText())
+ TQApplication::clipboard()->setText(generalFilter->containsText->currentText());
+ viewCurrent();
+ return;
+ }
+ else if( Krusader::actCopy->shortcut().contains( pressedKey ) )
+ {
+ copyToClipBoard();
+ return;
+ }
+ }
+
+ TQDialog::keyPressEvent( e );
+}
+
+void KrSearchDialog::editCurrent()
+{
+ TQListViewItem *current = resultsList->currentItem();
+ if( current )
+ {
+ TQString 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()
+{
+ TQListViewItem *current = resultsList->currentItem();
+ if( current )
+ {
+ TQString 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(TQListViewItem *item, const TQPoint&, 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
+ TDEPopupMenu 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(TQCursor::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 );
+ TQString queryName;
+ do {
+ queryName = i18n("Search results")+TQString( " %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;
+ TQListViewItem * item = resultsList->firstChild();
+ while( item )
+ {
+ TQString 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( TQString("virt:/") + queryName );
+ v.vfs_refresh( url );
+ v.vfs_addFiles( &urlList, TDEIO::CopyJob::Copy, 0 );
+ //ACTIVE_FUNC->openUrl(url);
+ ACTIVE_MNG->slotNewTab(url.prettyURL());
+ closeDialog();
+}
+
+void KrSearchDialog::copyToClipBoard()
+{
+ KURL::List urls;
+
+ TQListViewItem * item = resultsList->firstChild();
+ while( item )
+ {
+ if( item->isSelected() )
+ {
+ TQString 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" ), TQPoint( -7, 0 ) );
+ TQApplication::clipboard()->setData( d );
+}
+
+#include "krsearchdialog.moc"
diff --git a/src/app/Search/krsearchdialog.h b/src/app/Search/krsearchdialog.h
new file mode 100644
index 0000000..273c95a
--- /dev/null
+++ b/src/app/Search/krsearchdialog.h
@@ -0,0 +1,184 @@
+/***************************************************************************
+ 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 <tqwidget.h>
+#include <ksqueezedtextlabel.h>
+#include <tqstringlist.h>
+#include <sys/types.h>
+#include <time.h>
+#include <tqstring.h>
+#include <tqtabwidget.h>
+#include <tqlistview.h>
+#include <tqstringlist.h>
+#include <tdeglobal.h>
+#include <tdelocale.h>
+
+class KrSearchDialog : public TQDialog {
+ TQ_OBJECT
+
+public:
+ KrSearchDialog(TQString profile = 0, TQWidget* 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(TQString what, TQString where, TDEIO::filesize_t size, time_t mtime, TQString perm, TQString foundText);
+ void closeDialog( bool isAccept = true );
+ void resultDoubleClicked(TQListViewItem*);
+ void resultClicked(TQListViewItem*);
+
+ virtual void keyPressEvent(TQKeyEvent *e);
+ virtual void closeEvent(TQCloseEvent *e);
+ virtual void rightClickMenu(TQListViewItem*, const TQPoint&, int);
+ virtual void resizeEvent( TQResizeEvent *e );
+
+protected slots:
+ void reject();
+
+private:
+ bool gui2query();
+ void editCurrent();
+ void viewCurrent();
+
+private:
+ ProfileManager *profileManager;
+
+ FilterTabs * filterTabs;
+ GeneralFilter * generalFilter;
+
+ TQPushButton* mainHelpBtn;
+ TQPushButton* mainSearchBtn;
+ TQPushButton* mainStopBtn;
+ TQPushButton* mainCloseBtn;
+ TQPushButton* mainFeedToListBoxBtn;
+
+ TQTabWidget* searcherTabs;
+ TQWidget* resultTab;
+ TQGridLayout* resultLayout;
+ TQLabel* foundLabel;
+ KrSqueezedTextLabel *foundTextLabel;
+ KSqueezedTextLabel *searchingLabel;
+
+ TQListView* resultsList;
+
+ KRQuery *query;
+ KRSearchMod *searcher;
+ TQStringList savedSearches;
+ bool isSearching;
+ bool closed;
+
+ static TQString 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 TQListViewItem
+{
+public:
+ ResultListViewItem( TQListView *resultsList, TQString name, TQString where, TDEIO::filesize_t size,
+ TQDateTime date, TQString perm ) : TQListViewItem( resultsList, name, where,
+ KRpermHandler::parseSize(size),
+ TDEGlobal::locale()->formatDateTime( date ), perm )
+ {
+ fileSize = size;
+ fileDate = date;
+ setDragEnabled( true );
+ }
+
+ void setFoundText(TQString text) { _foundText=text; }
+ const TQString& foundText() const { return _foundText; }
+
+ virtual int compare(TQListViewItem *i,int col,bool ascending ) const
+ {
+ if( col == 2 ) {
+ ResultListViewItem *other = (ResultListViewItem *)i;
+ TDEIO::filesize_t otherSize = other->getSize();
+
+ if( fileSize == otherSize )
+ return 0;
+ if( fileSize > otherSize )
+ return 1;
+ return -1;
+ }
+ if( col == 3 ) {
+ ResultListViewItem *other = (ResultListViewItem *)i;
+ TQDateTime otherDate = other->getDate();
+
+ if( fileDate == otherDate )
+ return 0;
+ if( fileDate > otherDate )
+ return 1;
+ return -1;
+ }
+ return TQListViewItem::compare( i, col, ascending );
+ }
+
+ TDEIO::filesize_t getSize() {
+ return fileSize;
+ }
+
+ TQDateTime getDate() {
+ return fileDate;
+ }
+
+private:
+ TDEIO::filesize_t fileSize;
+ TQDateTime fileDate;
+ TQString _foundText;
+};
+
+#endif
diff --git a/src/app/Search/krsearchmod.cpp b/src/app/Search/krsearchmod.cpp
new file mode 100644
index 0000000..3198197
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <tqdir.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <tqtextstream.h>
+#include <tqregexp.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, TQ_SIGNAL( status( const TQString & ) ),
+ this, TQ_SIGNAL( searching(const TQString&) ) );
+ connect( query, TQ_SIGNAL( processEvents( bool & ) ),
+ this, TQ_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 )
+{
+ TQString dir = urlToScan.path( 1 );
+
+ DIR* d = opendir( dir.local8Bit() );
+ if ( !d ) return ;
+
+ struct dirent* dirEnt;
+
+ while ( ( dirEnt = readdir( d ) ) != NULL )
+ {
+ TQString name = TQString::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 );
+
+ TQString mime = TQString();
+ 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, (TDEIO::filesize_t)stat_p.st_size, KRpermHandler::mode2TQString(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( TQDir( dir + name ).canonicalPath() ) );
+ else if ( S_ISDIR( stat_p.st_mode ) )
+ unScannedUrls.push( url );
+ }
+ if ( query->searchInArchives() )
+ {
+ TQString type = mime.right( 4 );
+ if ( mime.contains( "-rar" ) ) type = "-rar";
+
+ if ( KRarcHandler::arcSupported( type ) )
+ {
+ KURL archiveURL = url;
+ bool encrypted;
+ TQString 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, ( TDEIO::filesize_t ) stat_p.st_size, stat_p.st_mtime, KRpermHandler::mode2TQString( stat_p.st_mode ), query->foundText() );
+ }
+ delete vf;
+
+ if( timer.elapsed() >= EVENT_PROCESS_DELAY ) {
+ tqApp->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() )
+ {
+ TQString 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 ) {
+ tqApp->processEvents();
+ timer.start();
+ if( stopSearch ) return;
+ }
+ }
+}
+
+void KRSearchMod::slotProcessEvents( bool & stopped ) {
+ tqApp->processEvents();
+ stopped = stopSearch;
+}
+
+#include "krsearchmod.moc"
diff --git a/src/app/Search/krsearchmod.h b/src/app/Search/krsearchmod.h
new file mode 100644
index 0000000..781d0e5
--- /dev/null
+++ b/src/app/Search/krsearchmod.h
@@ -0,0 +1,86 @@
+/***************************************************************************
+ 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 <tqobject.h>
+#include <tqvaluestack.h>
+#include <tqstringlist.h>
+#include <tqdatetime.h>
+#include <time.h>
+#include <tdeio/global.h>
+#include <kurl.h>
+#include "../VFS/ftp_vfs.h"
+#include "../VFS/virt_vfs.h"
+
+
+class KRQuery;
+class ftp_vfs;
+
+class KRSearchMod : public TQObject {
+ TQ_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 TQString&);
+ void found(TQString what, TQString where, TDEIO::filesize_t size, time_t mtime, TQString perm, TQString textFound);
+
+private slots:
+ void slotProcessEvents( bool & stopped );
+
+private:
+ bool stopSearch;
+ TQValueStack<KURL> scannedUrls;
+ TQValueStack<KURL> unScannedUrls;
+ KRQuery *query;
+ TQStringList results;
+
+ ftp_vfs *remote_vfs;
+ virt_vfs *virtual_vfs;
+
+ TQTime timer;
+};
+
+#endif
diff --git a/src/app/Splitter/Makefile.am b/src/app/Splitter/Makefile.am
new file mode 100644
index 0000000..756ea94
--- /dev/null
+++ b/src/app/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/src/app/Splitter/combiner.cpp b/src/app/Splitter/combiner.cpp
new file mode 100644
index 0000000..0053686
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <tdemessagebox.h>
+#include <tdefileitem.h>
+#include <tdeio/job.h>
+#include <tqfileinfo.h>
+
+Combiner::Combiner( TQWidget* parent, KURL baseURLIn, KURL destinationURLIn, bool unixNamingIn ) :
+ TQProgressDialog( 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() | TQFileInfo::WriteUser;
+
+ combineReadJob = TDEIO::get( splURL, false, false );
+
+ connect(combineReadJob, TQ_SIGNAL(data(TDEIO::Job *, const TQByteArray &)),
+ this, TQ_SLOT(combineSplitFileDataReceived(TDEIO::Job *, const TQByteArray &)));
+ connect(combineReadJob, TQ_SIGNAL(result(TDEIO::Job*)),
+ this, TQ_SLOT(combineSplitFileFinished(TDEIO::Job *)));
+ }
+
+ exec();
+}
+
+void Combiner::combineSplitFileDataReceived(TDEIO::Job *, const TQByteArray &byteArray)
+{
+ splitFile += TQString( byteArray );
+}
+
+void Combiner::combineSplitFileFinished(TDEIO::Job *job)
+{
+ combineReadJob = 0;
+ TQString error;
+
+ if( job->error() )
+ error = i18n("Error at reading the CRC file (%1)!").arg( vfs::pathOrURL( splURL ) );
+ else
+ {
+ splitFile.remove( '\r' ); // Windows compatibility
+ TQStringList splitFileContent = TQStringList::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;
+ TQString token = splitFileContent[i].left( ndx ).stripWhiteSpace();
+ TQString 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
+ {
+ TQString name = readURL.fileName();
+ int pos = name.length()-1;
+ TQChar ch;
+
+ do
+ {
+ ch = name.at( pos ).latin1() + 1;
+ if( ch == TQChar( 'Z' + 1 ) )
+ ch = 'A';
+ if( ch == TQChar( 'z' + 1 ) )
+ ch = 'a';
+ name[ pos ] = ch;
+ pos--;
+ } while( pos >=0 && ch.upper() == TQChar( 'A' ) );
+
+ readURL.setFileName( name );
+ }
+ }
+ else
+ {
+ TQString index( "%1" ); /* determining the filename */
+ index = index.arg(++fileCounter).rightJustify( 3, '0' );
+ readURL = baseURL;
+ readURL.setFileName( baseURL.fileName() + "." + index );
+ }
+
+ /* creating a write job */
+ combineReadJob = TDEIO::get( readURL, false, false );
+
+ connect(combineReadJob, TQ_SIGNAL(data(TDEIO::Job *, const TQByteArray &)),
+ this, TQ_SLOT(combineDataReceived(TDEIO::Job *, const TQByteArray &)));
+ connect(combineReadJob, TQ_SIGNAL(result(TDEIO::Job*)),
+ this, TQ_SLOT(combineReceiveFinished(TDEIO::Job *)));
+ if( hasValidSplitFile )
+ connect(combineReadJob, TQ_SIGNAL(percent (TDEIO::Job *, unsigned long)),
+ this, TQ_SLOT(combineWritePercent(TDEIO::Job *, unsigned long)));
+
+}
+
+void Combiner::combineDataReceived(TDEIO::Job *, const TQByteArray &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 = TDEIO::put( writeURL, permissions, true, false, false );
+
+ connect(combineWriteJob, TQ_SIGNAL(dataReq(TDEIO::Job *, TQByteArray &)),
+ this, TQ_SLOT(combineDataSend(TDEIO::Job *, TQByteArray &)));
+ connect(combineWriteJob, TQ_SIGNAL(result(TDEIO::Job*)),
+ this, TQ_SLOT(combineSendFinished(TDEIO::Job *)));
+ }
+
+ if( combineWriteJob )
+ {
+ if( combineReadJob ) combineReadJob->suspend(); /* start writing */
+ combineWriteJob->resume();
+ }
+}
+
+void Combiner::combineReceiveFinished(TDEIO::Job *job)
+{
+ combineReadJob = 0; /* TDEIO 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 )
+ {
+ TQString crcResult = TQString( "%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(TDEIO::Job *, TQByteArray &byteArray)
+{
+ byteArray = transferArray;
+ transferArray = TQByteArray();
+
+ if( combineReadJob )
+ {
+ combineReadJob->resume(); /* start reading */
+ combineWriteJob->suspend();
+ }
+}
+
+void Combiner::combineSendFinished(TDEIO::Job *job)
+{
+ combineWriteJob = 0; /* TDEIO 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(TDEIO::Job *, unsigned long)
+{
+ int percent = (int)((((double)receivedSize / expectedSize ) * 100. ) + 0.5 );
+ setProgress( percent );
+}
+
+#include "combiner.moc"
diff --git a/src/app/Splitter/combiner.h b/src/app/Splitter/combiner.h
new file mode 100644
index 0000000..10abb0f
--- /dev/null
+++ b/src/app/Splitter/combiner.h
@@ -0,0 +1,93 @@
+/***************************************************************************
+ 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 <tqstring.h>
+#include <tqprogressdialog.h>
+#include <kurl.h>
+#include <tdeio/jobclasses.h>
+
+class Combiner : public TQProgressDialog
+{
+ TQ_OBJECT
+
+
+private:
+ KURL splURL;
+ KURL readURL;
+ KURL writeURL;
+
+ KURL baseURL;
+ KURL destinationURL;
+ CRC32 *crcContext;
+ TQByteArray transferArray;
+
+ TQString splitFile;
+ TQString error;
+
+
+ bool hasValidSplitFile;
+ TQString expectedFileName;
+ TDEIO::filesize_t expectedSize;
+ TQString expectedCrcSum;
+
+ int fileCounter;
+ int permissions;
+ TDEIO::filesize_t receivedSize;
+
+ TDEIO::TransferJob *combineReadJob;
+ TDEIO::TransferJob *combineWriteJob;
+
+ bool unixNaming;
+
+public:
+ Combiner( TQWidget* parent, KURL baseURLIn, KURL destinationURLIn, bool unixNamingIn=false );
+ ~Combiner();
+
+ void combine();
+
+public slots:
+ void combineSplitFileDataReceived(TDEIO::Job *, const TQByteArray &byteArray);
+ void combineSplitFileFinished(TDEIO::Job *job);
+ void combineDataReceived(TDEIO::Job *, const TQByteArray &);
+ void combineReceiveFinished(TDEIO::Job *);
+ void combineDataSend(TDEIO::Job *, TQByteArray &);
+ void combineSendFinished(TDEIO::Job *);
+ void combineWritePercent(TDEIO::Job *, unsigned long);
+
+private:
+ void openNextFile();
+ void combineAbortJobs();
+};
+
+#endif /* __COMBINER_H__ */
diff --git a/src/app/Splitter/crc32.cpp b/src/app/Splitter/crc32.cpp
new file mode 100644
index 0000000..b6b807b
--- /dev/null
+++ b/src/app/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/src/app/Splitter/crc32.h b/src/app/Splitter/crc32.h
new file mode 100644
index 0000000..696603a
--- /dev/null
+++ b/src/app/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/src/app/Splitter/splitter.cpp b/src/app/Splitter/splitter.cpp
new file mode 100644
index 0000000..c67e2d9
--- /dev/null
+++ b/src/app/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 <tqlayout.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <tdeio/job.h>
+#include <tdefileitem.h>
+#include <tqfileinfo.h>
+
+Splitter::Splitter( TQWidget* parent, KURL fileNameIn, KURL destinationDirIn ) :
+ TQProgressDialog( 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( TDEIO::filesize_t splitSizeIn )
+{
+ KFileItem file(KFileItem::Unknown, KFileItem::Unknown, fileName );
+ file.refresh();
+
+ permissions = file.permissions() | TQFileInfo::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 = TDEIO::get( fileName, false, false );
+
+ connect(splitReadJob, TQ_SIGNAL(data(TDEIO::Job *, const TQByteArray &)),
+ this, TQ_SLOT(splitDataReceived(TDEIO::Job *, const TQByteArray &)));
+ connect(splitReadJob, TQ_SIGNAL(result(TDEIO::Job*)),
+ this, TQ_SLOT(splitReceiveFinished(TDEIO::Job *)));
+ connect(splitReadJob, TQ_SIGNAL(percent (TDEIO::Job *, unsigned long)),
+ this, TQ_SLOT(splitReceivePercent(TDEIO::Job *, unsigned long)));
+
+ splitWriteJob = 0;
+ noValidWriteJob = true;
+
+ exec();
+}
+
+void Splitter::splitDataReceived(TDEIO::Job *, const TQByteArray &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(TDEIO::Job *job)
+{
+ splitReadJob = 0; /* TDEIO 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;
+ }
+
+ TQString crcResult = TQString( "%1" ).arg( crcContext->result(), 0, 16 ).upper().stripWhiteSpace()
+ .rightJustify(8, '0');
+
+ splitFile = TQString( "filename=%1\n" ).arg( fileName.fileName() )+
+ TQString( "size=%1\n" ) .arg( TDEIO::number( fileSize ) )+
+ TQString( "crc32=%1\n" ) .arg( crcResult );
+}
+
+void Splitter::splitReceivePercent (TDEIO::Job *, unsigned long percent)
+{
+ setProgress( percent );
+}
+
+void Splitter::splitCreateWriteJob()
+{
+ TQString index( "%1" ); /* making the splitted filename */
+ index = index.arg(++fileNumber).rightJustify( 3, '0' );
+ TQString outFileName = fileName.fileName() + "." + index;
+
+ writeURL = destinationDir;
+ writeURL.addPath( outFileName );
+
+ /* creating a write job */
+ splitWriteJob = TDEIO::put( writeURL, permissions, true, false, false );
+ outputFileSize = 0;
+ connect(splitWriteJob, TQ_SIGNAL(dataReq(TDEIO::Job *, TQByteArray &)),
+ this, TQ_SLOT(splitDataSend(TDEIO::Job *, TQByteArray &)));
+ connect(splitWriteJob, TQ_SIGNAL(result(TDEIO::Job*)),
+ this, TQ_SLOT(splitSendFinished(TDEIO::Job *)));
+ noValidWriteJob = false;
+}
+
+void Splitter::splitDataSend(TDEIO::Job *, TQByteArray &byteArray)
+{
+ int bufferLen = transferArray.size();
+
+ if( noValidWriteJob ) /* splitted file should be closed ? */
+ {
+ byteArray = TQByteArray(); /* 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 = TQByteArray();
+
+ if(splitReadJob)
+ {
+ splitReadJob->resume(); /* start reading */
+ splitWriteJob->suspend();
+ }
+ }
+}
+
+void Splitter::splitSendFinished(TDEIO::Job *job)
+{
+ splitWriteJob = 0; /* TDEIO 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 = TDEIO::put( writeURL, permissions, true, false, false );
+ connect(splitWriteJob, TQ_SIGNAL(dataReq(TDEIO::Job *, TQByteArray &)),
+ this, TQ_SLOT(splitFileSend(TDEIO::Job *, TQByteArray &)));
+ connect(splitWriteJob, TQ_SIGNAL(result(TDEIO::Job*)),
+ this, TQ_SLOT(splitFileFinished(TDEIO::Job *)));
+ }
+}
+
+void Splitter::splitAbortJobs()
+{
+ if( splitReadJob )
+ splitReadJob->kill();
+ if( splitWriteJob )
+ splitWriteJob->kill();
+
+ splitReadJob = splitWriteJob = 0;
+}
+
+void Splitter::splitFileSend(TDEIO::Job *, TQByteArray &byteArray)
+{
+ const char *content = splitFile.ascii();
+ byteArray.duplicate( content, strlen ( content ) );
+ splitFile = "";
+}
+
+void Splitter::splitFileFinished(TDEIO::Job *job)
+{
+ splitWriteJob = 0; /* TDEIO 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/src/app/Splitter/splitter.h b/src/app/Splitter/splitter.h
new file mode 100644
index 0000000..ce10f4f
--- /dev/null
+++ b/src/app/Splitter/splitter.h
@@ -0,0 +1,84 @@
+/***************************************************************************
+ 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 <tqstring.h>
+#include <tqprogressdialog.h>
+#include <kurl.h>
+#include <tdeio/jobclasses.h>
+
+class Splitter : public TQProgressDialog
+{
+ TQ_OBJECT
+
+
+private:
+ KURL fileName;
+ KURL destinationDir;
+ TDEIO::filesize_t splitSize;
+
+ TDEIO::filesize_t fileSize;
+ int permissions;
+ TQString splitFile;
+
+ KURL writeURL;
+ int fileNumber;
+ TDEIO::filesize_t outputFileSize;
+ bool noValidWriteJob;
+ CRC32 *crcContext;
+ TQByteArray transferArray;
+
+ TDEIO::TransferJob *splitReadJob;
+ TDEIO::TransferJob *splitWriteJob;
+
+public:
+ Splitter( TQWidget* parent, KURL fileNameIn, KURL destinationDirIn );
+ ~Splitter();
+
+ void split( TDEIO::filesize_t splitSizeIn );
+
+private:
+ void splitCreateWriteJob();
+ void splitAbortJobs();
+
+public slots:
+ void splitDataReceived(TDEIO::Job *, const TQByteArray &);
+ void splitDataSend(TDEIO::Job *, TQByteArray &);
+ void splitSendFinished(TDEIO::Job *);
+ void splitReceiveFinished(TDEIO::Job *);
+ void splitReceivePercent (TDEIO::Job *, unsigned long);
+ void splitFileSend(TDEIO::Job *, TQByteArray &);
+ void splitFileFinished(TDEIO::Job *);
+};
+
+#endif /* __SPLITTER_H__ */
diff --git a/src/app/Splitter/splittergui.cpp b/src/app/Splitter/splittergui.cpp
new file mode 100644
index 0000000..d2a4def
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <tqlayout.h>
+#include <tqlabel.h>
+#include <tdemessagebox.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( TQWidget* parent, KURL fileURL, KURL defaultDir ) :
+ TQDialog( parent, "Krusader::SplitterGUI", true, 0 ),
+ userDefinedSize ( 0x100000 ), lastSelectedDevice( 0 ), resultCode( TQDialog::Rejected )
+{
+ predefinedDeviceNum = sizeof( predefinedDevices ) / sizeof( PredefinedDevice );
+
+ TQGridLayout *grid = new TQGridLayout( this );
+ grid->setSpacing( 6 );
+ grid->setMargin( 11 );
+
+ TQLabel *splitterLabel = new TQLabel( 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 );
+
+ TQHBox *splitSizeLine = new TQHBox( this, "splitSizeLine" );
+
+ deviceCombo = new TQComboBox( splitSizeLine, "deviceCombo" );
+ for( int i=0; i != predefinedDeviceNum; i++ )
+ deviceCombo->insertItem( predefinedDevices[i].name );
+ deviceCombo->insertItem( i18n( "User Defined" ) );
+
+ TQLabel *spacer = new TQLabel( splitSizeLine );
+ spacer->setText( " " );
+ spacer->setSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Minimum );
+
+ TQLabel *bytesPerFile = new TQLabel( splitSizeLine, "BytesPerFile" );
+ bytesPerFile->setText( i18n( "Max file size:" ) );
+
+ spinBox = new SplitterSpinBox( splitSizeLine, "spinbox" );
+ spinBox->setMinimumWidth( 85 );
+ spinBox->setEnabled( false );
+
+ sizeCombo = new TQComboBox( splitSizeLine, "sizeCombo" );
+ sizeCombo->insertItem( i18n( "Byte" ) );
+ sizeCombo->insertItem( i18n( "kByte" ) );
+ sizeCombo->insertItem( i18n( "MByte" ) );
+ sizeCombo->insertItem( i18n( "GByte" ) );
+
+ grid->addWidget( splitSizeLine,2 ,0 );
+
+ TQFrame *separator = new TQFrame( this, "separatorLine" );
+ separator->setFrameStyle( TQFrame::HLine | TQFrame::Sunken );
+ separator->setFixedHeight( separator->sizeHint().height() );
+
+ grid->addWidget( separator,3 ,0 );
+
+ TQHBoxLayout *splitButtons = new TQHBoxLayout;
+ splitButtons->setSpacing( 6 );
+ splitButtons->setMargin( 0 );
+
+ TQSpacerItem* spacer2 = new TQSpacerItem( 0, 0, TQSizePolicy::Expanding, TQSizePolicy::Minimum );
+ splitButtons->addItem( spacer2 );
+
+ TQPushButton *splitBtn = new TQPushButton( this, "splitBtn" );
+ splitBtn->setText( i18n("&Split") );
+ splitButtons->addWidget( splitBtn );
+
+ TQPushButton *cancelBtn = new TQPushButton( this, "cancelBtn" );
+ cancelBtn->setText( i18n("&Cancel") );
+ splitButtons->addWidget( cancelBtn );
+
+ grid->addLayout( splitButtons,4 ,0 );
+
+ setCaption(i18n("Krusader::Splitter"));
+
+ connect( sizeCombo, TQ_SIGNAL( activated(int) ), this, TQ_SLOT( sizeComboActivated( int ) ) );
+ connect( deviceCombo, TQ_SIGNAL( activated(int) ), this, TQ_SLOT( predefinedComboActivated( int ) ) );
+ connect( cancelBtn, TQ_SIGNAL( clicked() ), this, TQ_SLOT( reject() ) );
+ connect( splitBtn , TQ_SIGNAL( clicked() ), this, TQ_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( TQKeyEvent *e )
+{
+ switch ( e->key() )
+ {
+ case Key_Enter :
+ case Key_Return :
+ emit splitPressed();
+ return;
+ default:
+ TQDialog::keyPressEvent( e );
+ }
+}
+
+#include "splittergui.moc"
diff --git a/src/app/Splitter/splittergui.h b/src/app/Splitter/splittergui.h
new file mode 100644
index 0000000..10f23bc
--- /dev/null
+++ b/src/app/Splitter/splittergui.h
@@ -0,0 +1,180 @@
+/***************************************************************************
+ 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 <tqdialog.h>
+#include <tqstring.h>
+#include <tqspinbox.h>
+#include <tqvalidator.h>
+#include <tqcombobox.h>
+#include <kurlrequester.h>
+#include <tdeio/global.h>
+
+#include "../VFS/vfs.h"
+
+struct PredefinedDevice
+{
+ TQString name;
+ TDEIO::filesize_t capacity;
+};
+
+ class SplitterSpinBox : public TQSpinBox
+ {
+ TQ_OBJECT
+
+ private:
+ TDEIO::filesize_t division;
+ TDEIO::filesize_t value;
+
+ public:
+ SplitterSpinBox ( TQWidget * parent = 0, const char * name = 0 ) : TQSpinBox( parent, name ), division( 1 ), value( 1 )
+ {
+ setMaxValue( 0x7FFFFFFF ); /* setting the minimum and maximum values */
+ setMinValue( 1 );
+ TQDoubleValidator *dval = new TQDoubleValidator( this );
+ setValidator ( dval );
+ }
+
+ void setLongValue( TDEIO::filesize_t valueIn ) {
+ value = valueIn;
+ if( value == 0 )
+ value++;
+ updateDisplay();
+ }
+
+ TDEIO::filesize_t longValue() {
+ TDEIO::filesize_t val = (TDEIO::filesize_t)( division * text().toDouble() + 0.5 ) ;
+ if( val == 0 )
+ val++;
+ return val;
+ }
+
+ TQString mapValueToText( int )
+ {
+ TQString frac("");
+
+ TDEIO::filesize_t int_part = value / division;
+ TDEIO::filesize_t frac_mod = value % division;
+
+ if( frac_mod )
+ {
+ TDEIO::filesize_t frac_part = (TDEIO::filesize_t)((1000. * frac_mod) /division + 0.5);
+
+ if( frac_part )
+ {
+ frac = TQString( "%1" ).arg( frac_part ).rightJustify( 3, '0' );
+ frac = "." + frac;
+ while( frac.endsWith("0") )
+ frac.truncate( frac.length() - 1 );
+ }
+ }
+
+ return TQString( "%1%2" ).arg( int_part ).arg( frac );
+ }
+
+ int mapTextToValue( bool * )
+ {
+ value = longValue();
+
+ if( value > 0x7FFFFFFF )
+ return 0x7FFFFFFF;
+ else
+ return value;
+ }
+
+ void setDivision( TDEIO::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();
+ }
+ };
+
+class SplitterGUI : TQDialog
+{
+ TQ_OBJECT
+
+
+private:
+ int predefinedDeviceNum;
+ TDEIO::filesize_t userDefinedSize;
+ int lastSelectedDevice;
+ int resultCode;
+
+ static PredefinedDevice predefinedDevices[];
+
+ SplitterSpinBox *spinBox;
+ TQComboBox *deviceCombo;
+ TQComboBox *sizeCombo;
+ KURLRequester *urlReq;
+
+public:
+ SplitterGUI( TQWidget* parent, KURL fileURL, KURL defaultDir );
+
+ KURL getDestinationDir() {return vfs::fromPathOrURL( urlReq->url() );}
+ TDEIO::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( TQKeyEvent *e );
+
+public:
+
+};
+
+#endif /* __SPLITTERGUI_H__ */
diff --git a/src/app/Synchronizer/Makefile.am b/src/app/Synchronizer/Makefile.am
new file mode 100755
index 0000000..f270b65
--- /dev/null
+++ b/src/app/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/src/app/Synchronizer/feedtolistboxdialog.cpp b/src/app/Synchronizer/feedtolistboxdialog.cpp
new file mode 100644
index 0000000..b69503f
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <tdemessagebox.h>
+#include <tqcheckbox.h>
+#include <tqlayout.h>
+#include <tqlineedit.h>
+#include <tqlabel.h>
+#include <tqhbox.h>
+#include <tqcombobox.h>
+#include <tqframe.h>
+
+#define S_LEFT 0
+#define S_RIGHT 1
+#define S_BOTH 2
+
+FeedToListBoxDialog::FeedToListBoxDialog(TQWidget *parent, const char *name, Synchronizer *sync,
+ TQListView *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;
+
+ TQListViewItemIterator 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 );
+ TQString queryName;
+ do {
+ queryName = i18n("Synchronize results")+TQString( " %1" ).arg( listBoxNum++ );
+ }while( v.vfs_search( queryName ) != 0 );
+ krConfig->writeEntry( "Feed To Listbox Counter", listBoxNum );
+
+ // creating the widget
+
+ TQWidget *widget=new TQWidget(this, "feedToListBoxMainWidget");
+ TQVBoxLayout *layout = new TQVBoxLayout( widget, 0, 10, "FeedToListBoxDialogLayout" );
+
+ TQLabel *label = new TQLabel( i18n("Here you can name the file collection"), widget, "fbLabel" );
+ layout->addWidget( label );
+
+ lineEdit = new TQLineEdit( widget, "fbLineEdit" );
+ lineEdit->setText( queryName );
+ lineEdit->selectAll();
+ layout->addWidget( lineEdit );
+
+ TQHBox *hbox = new TQHBox( widget, "fbHBox" );
+
+ TQLabel *label2 = new TQLabel( i18n( "Side to feed:" ), hbox, "fbSideLabel" );
+ label2->setSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed );
+
+ sideCombo = new TQComboBox( hbox, "fbSideCombo" );
+ sideCombo->setSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::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 );
+
+ TQFrame *line = new TQFrame( hbox, "fbVLine" );
+ line->setFrameStyle( TQFrame::VLine | TQFrame::Sunken );
+ line->setSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Expanding );
+
+ cbSelected = new TQCheckBox( i18n( "Selected files only" ), hbox, "cbSelected" );
+ cbSelected->setSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::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();
+ TQString name = lineEdit->text();
+ KURL::List urlList;
+
+ TQListViewItemIterator 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() ) {
+ TQString 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() ) {
+ TQString rightDirName = syncItem->rightDirectory().isEmpty() ? "" : syncItem->rightDirectory() + "/";
+ KURL leftURL = vfs::fromPathOrURL( synchronizer->rightBaseDirectory() + rightDirName + syncItem->rightName() );
+ urlList.push_back( leftURL );
+ }
+ }
+
+ KURL url = KURL::fromPathOrURL(TQString("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, TDEIO::CopyJob::Copy, 0 );
+ ACTIVE_MNG->slotNewTab(url.prettyURL());
+ accepted = true;
+ accept();
+}
+
+#include "feedtolistboxdialog.moc"
diff --git a/src/app/Synchronizer/feedtolistboxdialog.h b/src/app/Synchronizer/feedtolistboxdialog.h
new file mode 100644
index 0000000..8b10ff3
--- /dev/null
+++ b/src/app/Synchronizer/feedtolistboxdialog.h
@@ -0,0 +1,66 @@
+/***************************************************************************
+ 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 TQCheckBox;
+class TQLineEdit;
+class TQComboBox;
+class TQListView;
+
+class FeedToListBoxDialog : public KDialogBase {
+ TQ_OBJECT
+
+
+ public:
+ FeedToListBoxDialog( TQWidget*, const char*, Synchronizer *, TQListView *, bool);
+ virtual ~FeedToListBoxDialog() {};
+
+ bool isAccepted() {return accepted;};
+
+ protected:
+ void slotUser1();
+ void slotOk();
+
+ private:
+ Synchronizer * synchronizer;
+ TQListView * syncList;
+ TQCheckBox * cbSelected;
+ TQLineEdit * lineEdit;
+ TQComboBox * sideCombo;
+ bool equalAllowed;
+ bool accepted;
+};
+
+#endif /* __FEED_TO_LISTBOX_DIALOG__ */
diff --git a/src/app/Synchronizer/synchronizedialog.cpp b/src/app/Synchronizer/synchronizedialog.cpp
new file mode 100644
index 0000000..55cbde6
--- /dev/null
+++ b/src/app/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 <tqlayout.h>
+#include <tqhbox.h>
+#include <tdelocale.h>
+
+SynchronizeDialog::SynchronizeDialog( TQWidget* parent, const char* name, bool modal, WFlags fl,
+ Synchronizer *sync, int pleftCopyNr, TDEIO::filesize_t pleftCopySize,
+ int prightCopyNr, TDEIO::filesize_t prightCopySize, int pdeleteNr,
+ TDEIO::filesize_t pdeleteSize, int parThreads ) : TQDialog( 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") );
+
+ TQVBoxLayout *layout = new TQVBoxLayout( this, 11, 6, "SynchronizeDialogLayout" );
+
+ cbRightToLeft = new TQCheckBox( 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 TQLabel( "\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 TQCheckBox( 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 TQLabel( "\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 TQCheckBox( 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 TQLabel( "\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 TQProgressBar(1000, this);
+ progress->setCenterIndicator(true);
+ progress->setProgress( 0 );
+ progress->setMinimumWidth( 400 );
+ layout->addWidget( progress );
+
+ TQHBox *hbox = new TQHBox( this, "SynchronizeDialogHBox" );
+ hbox->setSpacing( 6 );
+
+ cbOverwrite = new TQCheckBox( i18n( "Confirm overwrites" ), this, "cbOverWrite" );
+ krConfig->setGroup("Synchronize");
+ cbOverwrite->setChecked( krConfig->readBoolEntry( "Confirm overwrites", _ConfirmOverWrites ) );
+ layout->addWidget( cbOverwrite );
+
+ TQSpacerItem* spacer = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum );
+ hbox->layout()->addItem( spacer );
+
+ btnStart = new TQPushButton( hbox, "btnStart" );
+ btnStart->setText( i18n( "&Start" ) );
+
+ btnPause = new TQPushButton( hbox, "btnPause" );
+ btnPause->setEnabled( false );
+ btnPause->setText( i18n( "&Pause" ) );
+
+ TQPushButton *btnClose = new TQPushButton( hbox, "btnClose" );
+ btnClose->setText( i18n( "&Close" ) );
+
+ layout->addWidget( hbox );
+
+ connect( btnStart, TQ_SIGNAL( clicked() ), this, TQ_SLOT( startSynchronization() ) );
+ connect( btnPause, TQ_SIGNAL( clicked() ), this, TQ_SLOT( pauseOrResume() ) );
+ connect( btnClose, TQ_SIGNAL( clicked() ), this, TQ_SLOT( reject() ) );
+
+ exec();
+}
+
+SynchronizeDialog::~SynchronizeDialog()
+{
+ krConfig->writeEntry("Confirm overwrites", cbOverwrite->isChecked() );
+}
+
+void SynchronizeDialog::startSynchronization()
+{
+ btnStart->setEnabled( false );
+ btnPause->setEnabled( syncStarted = true );
+ connect( synchronizer, TQ_SIGNAL( synchronizationFinished() ), this, TQ_SLOT( synchronizationFinished() ) );
+ connect( synchronizer, TQ_SIGNAL( processedSizes( int, TDEIO::filesize_t, int, TDEIO::filesize_t, int, TDEIO::filesize_t ) ),
+ this, TQ_SLOT( processedSizes( int, TDEIO::filesize_t, int, TDEIO::filesize_t, int, TDEIO::filesize_t) ) );
+ connect( synchronizer, TQ_SIGNAL( pauseAccepted() ), this, TQ_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()
+{
+ TQDialog::reject();
+}
+
+void SynchronizeDialog::processedSizes( int leftNr, TDEIO::filesize_t leftSize, int rightNr,
+ TDEIO::filesize_t rightSize, int delNr, TDEIO::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() ) );
+
+ TDEIO::filesize_t totalSum = leftCopySize + rightCopySize + deleteSize;
+ TDEIO::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/src/app/Synchronizer/synchronizedialog.h b/src/app/Synchronizer/synchronizedialog.h
new file mode 100644
index 0000000..9d5a16c
--- /dev/null
+++ b/src/app/Synchronizer/synchronizedialog.h
@@ -0,0 +1,92 @@
+/***************************************************************************
+ 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 <tqdialog.h>
+#include <tqpushbutton.h>
+#include <tqcheckbox.h>
+#include <tqlabel.h>
+#include <tqprogressbar.h>
+
+class SynchronizeDialog : TQDialog
+{
+ TQ_OBJECT
+
+
+ public:
+ SynchronizeDialog( TQWidget*, const char*, bool, WFlags, Synchronizer *sync,
+ int, TDEIO::filesize_t, int, TDEIO::filesize_t, int, TDEIO::filesize_t, int);
+ ~SynchronizeDialog();
+
+ inline bool wasSyncronizationStarted() { return syncStarted; }
+
+ public slots:
+ void startSynchronization();
+ void synchronizationFinished();
+ void processedSizes( int, TDEIO::filesize_t, int, TDEIO::filesize_t, int, TDEIO::filesize_t);
+ void pauseOrResume();
+ void pauseAccepted();
+
+ private:
+ TQProgressBar *progress;
+
+ TQCheckBox *cbRightToLeft;
+ TQCheckBox *cbLeftToRight;
+ TQCheckBox *cbDeletable;
+
+ TQLabel *lbRightToLeft;
+ TQLabel *lbLeftToRight;
+ TQLabel *lbDeletable;
+
+ TQCheckBox *cbOverwrite;
+
+ TQPushButton *btnStart;
+ TQPushButton *btnPause;
+
+ Synchronizer *synchronizer;
+
+ int leftCopyNr;
+ TDEIO::filesize_t leftCopySize;
+ int rightCopyNr;
+ TDEIO::filesize_t rightCopySize;
+ int deleteNr;
+ TDEIO::filesize_t deleteSize;
+
+ int parallelThreads;
+
+ bool isPause;
+ bool syncStarted;
+};
+
+#endif /* __SYNCHRONIZE_DIALOG__ */
diff --git a/src/app/Synchronizer/synchronizer.cpp b/src/app/Synchronizer/synchronizer.cpp
new file mode 100644
index 0000000..612f756
--- /dev/null
+++ b/src/app/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 <tdemessagebox.h>
+#include <tdelocale.h>
+#include <tqapplication.h>
+#include <tqregexp.h>
+#include <tqdir.h>
+#include <tqtimer.h>
+#include <tdeio/job.h>
+#include <kdialogbase.h>
+#include <tdeio/observer.h>
+#include <tdeio/renamedlg.h>
+#include <tdeio/skipdlg.h>
+#include <unistd.h>
+#include <tqeventloop.h>
+#include <tqpushbutton.h>
+#include <tqdatetime.h>
+#include <kprocess.h>
+#include <kdialogbase.h>
+#include <kprogress.h>
+#include <tqlayout.h>
+#include <kurlcompletion.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <utime.h>
+#include <pwd.h>
+#include <grp.h>
+#include <tqlabel.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 = TQString();
+ resultList.clear();
+ temporaryList.clear();
+ stack.clear();
+}
+
+int Synchronizer::compare( TQString leftURL, TQString rightURL, KRQuery *query, bool subDirs,
+ bool symLinks, bool igDate, bool asymm, bool cmpByCnt, bool igCase,
+ bool autoSc, TQStringList &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() )
+ tqApp->processEvents();
+ }
+ stack.clear();
+}
+
+void Synchronizer::compareDirectory( SynchronizerFileItem *parent, SynchronizerDirList * left_directory,
+ SynchronizerDirList * right_directory, const TQString &leftDir,
+ const TQString &rightDir )
+{
+ const TQString &leftURL = left_directory->url();
+ const TQString &rightURL = right_directory->url();
+ vfile * left_file;
+ vfile * right_file;
+
+ TQString 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()) )
+ {
+ TQString 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 {
+ TQString 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 ) );
+ }
+ }
+ }
+ }
+}
+
+TQString Synchronizer::getTaskTypeName( TaskType taskType )
+{
+ static TQString names[] = {"=","!=","<-","->","DEL","?","?","?","?","?"};
+
+ return names[taskType];
+}
+
+SynchronizerFileItem * Synchronizer::addItem( SynchronizerFileItem *parent, const TQString &leftFile,
+ const TQString &rightFile, const TQString &leftDir,
+ const TQString &rightDir, bool existsLeft, bool existsRight,
+ TDEIO::filesize_t leftSize, TDEIO::filesize_t rightSize,
+ time_t leftDate, time_t rightDate, const TQString &leftLink,
+ const TQString &rightLink, const TQString &leftOwner,
+ const TQString &rightOwner, const TQString &leftGroup,
+ const TQString &rightGroup, mode_t leftMode, mode_t rightMode,
+ const TQString &leftACL, const TQString &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) ) )
+ tqApp->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 TQString &file_name, const TQString &dir, TDEIO::filesize_t size,
+ time_t date, const TQString &link, const TQString &owner,
+ const TQString &group, mode_t mode, const TQString &acl, bool isDir,
+ bool isTemp )
+{
+ return addItem( parent, file_name, file_name, dir, dir, true, false, size, 0, date, 0, link, TQString(),
+ owner, TQString(), group, TQString(), mode, (mode_t)-1, acl, TQString(),
+ asymmetric ? TT_DELETE : TT_COPY_TO_RIGHT, isDir, isTemp );
+}
+
+SynchronizerFileItem * Synchronizer::addRightOnlyItem( SynchronizerFileItem *parent,
+ const TQString &file_name, const TQString &dir, TDEIO::filesize_t size,
+ time_t date, const TQString &link, const TQString &owner,
+ const TQString &group, mode_t mode, const TQString &acl, bool isDir,
+ bool isTemp )
+{
+ return addItem( parent, file_name, file_name, dir, dir, false, true, 0, size, 0, date, TQString(), link,
+ TQString(), owner, TQString(), group, (mode_t)-1, mode, TQString(), acl,
+ TT_COPY_TO_LEFT, isDir, isTemp );
+}
+
+SynchronizerFileItem * Synchronizer::addDuplicateItem( SynchronizerFileItem *parent,
+ const TQString &leftName, const TQString &rightName,
+ const TQString &leftDir, const TQString &rightDir,
+ TDEIO::filesize_t leftSize, TDEIO::filesize_t rightSize, time_t leftDate, time_t rightDate,
+ const TQString &leftLink, const TQString &rightLink,
+ const TQString &leftOwner, const TQString &rightOwner,
+ const TQString &leftGroup, const TQString &rightGroup,
+ mode_t leftMode, mode_t rightMode,
+ const TQString &leftACL, const TQString &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 TQString &dirName, bool isLeft )
+{
+ const TQString &url = directory->url();
+ vfile * file;
+ TQString 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() )
+ {
+ TQString leftDirName = ( item->leftDirectory() == "" ) ?
+ item->leftName() : item->leftDirectory() + "/" + item->leftName() ;
+ TQString 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, TDEIO::filesize_t *leftCopySize, int * rightCopyNr,
+ TDEIO::filesize_t *rightCopySize, int *deleteNr, TDEIO::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()
+{
+ TQString 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( TQWidget *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 )
+{
+ TQString leftDirName = task->leftDirectory();
+ if( !leftDirName.isEmpty() )
+ leftDirName += "/";
+ TQString 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() )
+ {
+ TDEIO::SimpleJob *job = TDEIO::mkdir( leftURL );
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(slotTaskFinished(TDEIO::Job*)));
+ jobMap[ job ] = task;
+ disableNewTasks = true;
+ }
+ else
+ {
+ KURL destURL( leftURL );
+ if( !task->destination().isNull() )
+ destURL = vfs::fromPathOrURL( task->destination() );
+
+ if( task->rightLink().isNull() ) {
+ TDEIO::FileCopyJob *job = TDEIO::file_copy(rightURL, destURL, -1,
+ overWrite || task->overWrite(), false, false );
+ connect(job,TQ_SIGNAL(processedSize (TDEIO::Job *, TDEIO::filesize_t )), this,
+ TQ_SLOT (slotProcessedSize (TDEIO::Job *, TDEIO::filesize_t )));
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(slotTaskFinished(TDEIO::Job*)));
+ jobMap[ job ] = task;
+ } else {
+ TDEIO::SimpleJob *job = TDEIO::symlink( task->rightLink(), destURL,
+ overWrite || task->overWrite(), false );
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(slotTaskFinished(TDEIO::Job*)));
+ jobMap[ job ] = task;
+ }
+ }
+ break;
+ case TT_COPY_TO_RIGHT:
+ if( task->isDir() )
+ {
+ TDEIO::SimpleJob *job = TDEIO::mkdir( rightURL );
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(slotTaskFinished(TDEIO::Job*)));
+ jobMap[ job ] = task;
+ disableNewTasks = true;
+ }
+ else
+ {
+ KURL destURL( rightURL );
+ if( !task->destination().isNull() )
+ destURL = vfs::fromPathOrURL( task->destination() );
+
+ if( task->leftLink().isNull() ) {
+ TDEIO::FileCopyJob *job = TDEIO::file_copy(leftURL, destURL, -1,
+ overWrite || task->overWrite(), false, false );
+ connect(job,TQ_SIGNAL(processedSize (TDEIO::Job *, TDEIO::filesize_t )), this,
+ TQ_SLOT (slotProcessedSize (TDEIO::Job *, TDEIO::filesize_t )));
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(slotTaskFinished(TDEIO::Job*)));
+ jobMap[ job ] = task;
+ } else {
+ TDEIO::SimpleJob *job = TDEIO::symlink( task->leftLink(), destURL,
+ overWrite || task->overWrite(), false );
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(slotTaskFinished(TDEIO::Job*)));
+ jobMap[ job ] = task;
+ }
+ }
+ break;
+ case TT_DELETE:
+ {
+ TDEIO::DeleteJob *job = TDEIO::del( leftURL, false );
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(slotTaskFinished(TDEIO::Job*)));
+ jobMap[ job ] = task;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void Synchronizer::slotTaskFinished(TDEIO::Job *job )
+{
+ inTaskFinished++;
+
+ SynchronizerFileItem * item = jobMap[ job ];
+ jobMap.remove( job );
+
+ TDEIO::filesize_t receivedSize = 0;
+
+ if( receivedMap.contains( job ) ) {
+ receivedSize = receivedMap[ job ];
+ receivedMap.remove( job );
+ }
+
+ if( disableNewTasks && item == lastTask )
+ disableNewTasks = false; // the blocker task finished
+
+ TQString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + "/";
+ TQString 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(TQFile::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(TQFile::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(TQFile::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(TQFile::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() == TDEIO::ERR_FILE_ALREADY_EXIST && item->task() != TT_DELETE )
+ {
+ TDEIO::RenameDlg_Result result;
+ TQString newDest;
+
+ if( autoSkip )
+ break;
+
+ if ( item->task() == TT_COPY_TO_LEFT )
+ {
+ TQWidget *mainWidget = tqApp->mainWidget(); // WORKAROUND, don't give focus to the main widget
+ tqApp->setMainWidget( syncDlgWidget );
+
+ result = Observer::self()->open_RenameDlg ( job, i18n("File Already Exists"),
+ vfs::pathOrURL( rightURL ), vfs::pathOrURL( leftURL ),
+ (TDEIO::RenameDlg_Mode)( TDEIO::M_OVERWRITE | TDEIO::M_SKIP | TDEIO::M_MULTI ), newDest,
+ item->rightSize(), item->leftSize(), (time_t)-1, (time_t)-1,
+ item->rightDate(), item->leftDate());
+
+ tqApp->setMainWidget( mainWidget );
+ }
+ else
+ {
+ TQWidget *mainWidget = tqApp->mainWidget(); // WORKAROUND, don't give focus to the main widget
+ tqApp->setMainWidget( syncDlgWidget );
+
+ result = Observer::self()->open_RenameDlg ( job, i18n("File Already Exists"),
+ vfs::pathOrURL( leftURL ), vfs::pathOrURL( rightURL ),
+ (TDEIO::RenameDlg_Mode)( TDEIO::M_OVERWRITE | TDEIO::M_SKIP | TDEIO::M_MULTI ), newDest,
+ item->leftSize(), item->rightSize(), (time_t)-1, (time_t)-1,
+ item->leftDate(), item->rightDate());
+
+ tqApp->setMainWidget( mainWidget );
+ }
+
+ switch ( result )
+ {
+ case TDEIO::R_RENAME:
+ item->setDestination( newDest );
+ executeTask( item );
+ inTaskFinished--;
+ return;
+ case TDEIO::R_OVERWRITE:
+ item->setOverWrite();
+ executeTask( item );
+ inTaskFinished--;
+ return;
+ case TDEIO::R_OVERWRITE_ALL:
+ overWrite = true;
+ executeTask( item );
+ inTaskFinished--;
+ return;
+ case TDEIO::R_AUTO_SKIP:
+ autoSkip = true;
+ case TDEIO::R_SKIP:
+ default:
+ break;
+ }
+ break;
+ }
+
+ if( job->error() != TDEIO::ERR_DOES_NOT_EXIST || item->task() != TT_DELETE )
+ {
+ if( autoSkip )
+ break;
+
+ TQString 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;
+ }
+
+ TQWidget *mainWidget = tqApp->mainWidget(); // WORKAROUND, don't give focus to the main widget
+ tqApp->setMainWidget( syncDlgWidget );
+
+ TDEIO::SkipDlg_Result result = Observer::self()->open_SkipDlg( job, true, error );
+
+ tqApp->setMainWidget( mainWidget );
+
+ switch( result )
+ {
+ case TDEIO::S_CANCEL:
+ executeTask( item ); /* simply retry */
+ inTaskFinished--;
+ return;
+ case TDEIO::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( TDEIO::Job * job , TDEIO::filesize_t size)
+{
+ TDEIO::filesize_t dl = 0, dr = 0, dd = 0;
+ SynchronizerFileItem * item = jobMap[ job ];
+
+ TDEIO::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();
+}
+
+TQString Synchronizer::leftBaseDirectory()
+{
+ return leftBaseDir;
+}
+
+TQString Synchronizer::rightBaseDirectory()
+{
+ return rightBaseDir;
+}
+
+class KgetProgressDialog : public KDialogBase
+{
+public:
+ KgetProgressDialog( TQWidget *parent=0, const char *name=0, const TQString &caption=TQString(),
+ const TQString &text=TQString(), bool modal=false) : KDialogBase( KDialogBase::Plain,
+ caption, KDialogBase::User1 | KDialogBase::Cancel, KDialogBase::Cancel, parent, name, modal )
+ {
+ showButton(KDialogBase::Close, false);
+
+ TQFrame* mainWidget = plainPage();
+ TQVBoxLayout* layout = new TQVBoxLayout(mainWidget, 10);
+
+ TQLabel *mLabel = new TQLabel(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;
+ TQString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + "/";
+ TQString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + "/";
+ TQString 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();
+ tqApp->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( !TQDir( destDir.left(i) ).exists() )
+ TQDir().mkdir( destDir.left(i) );
+
+ if( !item->isDir() && !downloadURL.isEmpty() )
+ {
+ if( TQFile( destURL.path() ).exists() )
+ TQFile( destURL.path() ).remove();
+
+ TQString source = downloadURL.prettyURL();
+ if( source.contains( '@' ) >= 2 ) /* is this an ftp proxy URL? */
+ {
+ int lastAt = source.findRev( '@' );
+ TQString startString = source.left( lastAt );
+ TQString endString = source.mid( lastAt );
+ startString.replace( "@", "%40" );
+ source = startString+endString;
+ }
+
+ TDEProcess p;
+
+ p << KrServices::fullPathName( "kget" ) << source << destURL.path();
+ if (!p.start(TDEProcess::Block))
+ KMessageBox::error(parentWidget,i18n("Error executing ")+KrServices::fullPathName( "kget" )+" !");
+ else
+ p.detach();
+ }
+
+ progDlg->progressBar()->setProgress( ++processedCount );
+
+ do
+ {
+ tqApp->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();
+ }
+}
+
+TQString Synchronizer::readLink( const vfile * file ) {
+ if( file->vfile_isSymLink() )
+ return file->vfile_getSymDest();
+ else
+ return TQString();
+}
+
+#include "synchronizer.moc"
diff --git a/src/app/Synchronizer/synchronizer.h b/src/app/Synchronizer/synchronizer.h
new file mode 100644
index 0000000..01f85ec
--- /dev/null
+++ b/src/app/Synchronizer/synchronizer.h
@@ -0,0 +1,205 @@
+/***************************************************************************
+ 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 <tqobject.h>
+#include <tqptrvector.h>
+#include <tqmap.h>
+#include <tqcolor.h>
+#include <tdeio/job.h>
+
+class KRQuery;
+class vfile;
+
+#define DECLARE_COLOR_NAME_ARRAY TQString COLOR_NAMES[] = { "Equals", "Differs", "LeftCopy", "RightCopy", "Delete", \
+ "Equals", "Equals", "Equals", "Equals", "Equals" }
+#define DECLARE_BACKGROUND_DFLTS TQColor BCKG_DFLTS[] = { TQColor(), TQColor(), TQColor(), TQColor(), TQt::red, \
+ TQColor(), TQColor(), TQColor(), TQColor(), TQColor() }
+#define DECLARE_FOREGROUND_DFLTS TQColor FORE_DFLTS[] = { TQt::black, TQt::red, TQt::blue, TQt::darkGreen, TQt::white, \
+ TQt::black, TQt::black, TQt::black, TQt::black, TQt::black }
+
+class Synchronizer : public TQObject
+{
+ TQ_OBJECT
+
+
+ private:
+ int displayUpdateCount; // the display is refreshed after every x-th change
+
+ public:
+ Synchronizer();
+ int compare( TQString leftURL, TQString rightURL, KRQuery *query, bool subDirs, bool symLinks,
+ bool igDate, bool asymm, bool cmpByCnt, bool igCase, bool autoSc, TQStringList &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 *, TDEIO::filesize_t *, int *, TDEIO::filesize_t *, int *, TDEIO::filesize_t * );
+ void synchronize( TQWidget *,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 * );
+
+ TQString leftBaseDirectory();
+ TQString rightBaseDirectory();
+ static TQString getTaskTypeName( TaskType taskType );
+
+ SynchronizerFileItem *getItemAt( unsigned ndx ) {return resultList.at(ndx);}
+
+ void setParentWidget( TQWidget * widget ) {parentWidget = widget;}
+ void compareContentResult( SynchronizerFileItem * item, bool result );
+
+ signals:
+ void comparedFileData( SynchronizerFileItem * );
+ void markChanged( SynchronizerFileItem *, bool );
+ void synchronizationFinished();
+ void processedSizes( int, TDEIO::filesize_t, int, TDEIO::filesize_t, int, TDEIO::filesize_t );
+ void pauseAccepted();
+ void statusInfo( TQString );
+
+ public slots:
+ void slotTaskFinished(TDEIO::Job*);
+ void slotProcessedSize( TDEIO::Job * , TDEIO::filesize_t );
+
+ private:
+ bool isDir( const vfile * file );
+ TQString readLink( const vfile * file );
+
+ void compareDirectory( SynchronizerFileItem *,SynchronizerDirList *, SynchronizerDirList *,
+ const TQString &leftDir, const TQString &rightDir );
+ void addSingleDirectory( SynchronizerFileItem *, SynchronizerDirList *, const TQString &, bool );
+ SynchronizerFileItem * addItem( SynchronizerFileItem *, const TQString &, const TQString &,
+ const TQString &, const TQString &, bool, bool, TDEIO::filesize_t,
+ TDEIO::filesize_t, time_t, time_t, const TQString &, const TQString &,
+ const TQString &, const TQString &, const TQString &, const TQString &,
+ mode_t, mode_t, const TQString &, const TQString &, TaskType, bool, bool);
+ SynchronizerFileItem * addLeftOnlyItem( SynchronizerFileItem *, const TQString &, const TQString &,
+ TDEIO::filesize_t, time_t, const TQString &, const TQString &,
+ const TQString &, mode_t, const TQString &, bool isDir = false, bool isTemp = false );
+ SynchronizerFileItem * addRightOnlyItem( SynchronizerFileItem *, const TQString &, const TQString &,
+ TDEIO::filesize_t, time_t, const TQString &, const TQString &,
+ const TQString &, mode_t, const TQString &, bool isDir = false, bool isTemp = false );
+ SynchronizerFileItem * addDuplicateItem( SynchronizerFileItem *, const TQString &, const TQString &,
+ const TQString &, const TQString &, TDEIO::filesize_t,
+ TDEIO::filesize_t, time_t, time_t, const TQString &,
+ const TQString &, const TQString &, const TQString &,
+ const TQString &, const TQString &, mode_t, mode_t, const TQString &,
+ const TQString &, 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
+ TQPtrList<SynchronizerFileItem> resultList; // the found files
+ TQPtrList<SynchronizerFileItem> temporaryList; // temporary files
+ TQString leftBaseDir; // the left-side base directory
+ TQString rightBaseDir; // the right-side base directory
+ TQStringList 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
+ TDEIO::filesize_t leftCopySize; // the total size copied to left
+ TDEIO::filesize_t rightCopySize; // the total size copied to right
+ TDEIO::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:
+ TQPtrList<SynchronizerTask> stack; // stack for comparing
+ TQMap<TDEIO::Job *,SynchronizerFileItem *> jobMap; // job maps
+ TQMap<TDEIO::Job *,TDEIO::filesize_t> receivedMap; // the received file size
+ SynchronizerFileItem *lastTask; // reference to the last stack
+ int inTaskFinished; // counter of quasy 'threads' in slotTaskFinished
+
+ TQStringList selectedFiles; // the selected files to compare
+ TQWidget *parentWidget; // the parent widget
+ TQWidget *syncDlgWidget; // the synchronizer dialog widget
+};
+
+#endif /* __SYNCHRONIZER_H__ */
diff --git a/src/app/Synchronizer/synchronizerdirlist.cpp b/src/app/Synchronizer/synchronizerdirlist.cpp
new file mode 100644
index 0000000..95bc89a
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <tdemessagebox.h>
+#include <tdefileitem.h>
+#include <klargefile.h>
+#include <tqapplication.h>
+#include <tqdir.h>
+#include <tdeversion.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( TQWidget *w, bool hidden ) : TQObject(), TQDict<vfile>(), fileIterator( 0 ),
+ parentWidget( w ), busy( false ), result( false ), ignoreHidden( hidden ), currentUrl() {
+ setAutoDelete( true );
+}
+
+SynchronizerDirList::~SynchronizerDirList() {
+ if( fileIterator )
+ delete fileIterator;
+}
+
+vfile * SynchronizerDirList::search( const TQString &name, bool ignoreCase ) {
+ if( !ignoreCase )
+ return (*this)[ name ];
+
+ vfile *item = first();
+ TQString 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 TQString &urlIn, bool wait ) {
+ if( busy )
+ return false;
+
+ currentUrl = urlIn;
+ KURL url = vfs::fromPathOrURL( urlIn );
+
+ if( fileIterator == 0 )
+ fileIterator = new TQDictIterator<vfile> ( *this );
+
+ clear();
+
+ if( url.isLocalFile() ) {
+ TQString 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;
+ TQString name;
+
+ while( (dirEnt=readdir(dir)) != NULL ){
+ name = TQString::fromLocal8Bit(dirEnt->d_name);
+
+ if (name=="." || name == "..") continue;
+ if (ignoreHidden && name.startsWith( "." ) ) continue;
+
+ TQString fullName = path + "/" + name;
+
+ KDE_struct_stat stat_p;
+ KDE_lstat(fullName.local8Bit(),&stat_p);
+
+ TQString perm = KRpermHandler::mode2TQString(stat_p.st_mode);
+
+ bool symLink= S_ISLNK(stat_p.st_mode);
+ TQString 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 ) {
+ TQString absSymDest = symlinkDest = TQString::fromLocal8Bit( symDest );
+
+ if( !absSymDest.startsWith( "/" ) )
+ absSymDest = TQDir::cleanDirPath( path + "/" + absSymDest );
+
+ if ( TQDir( absSymDest ).exists() )
+ perm[0] = 'd';
+ }
+ }
+
+ TQString mime = TQString();
+
+ 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 {
+ TDEIO::Job *job = TDEIO::listDir( url, false, true );
+ connect( job, TQ_SIGNAL( entries( TDEIO::Job*, const TDEIO::UDSEntryList& ) ),
+ this, TQ_SLOT( slotEntries( TDEIO::Job*, const TDEIO::UDSEntryList& ) ) );
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ),
+ this, TQ_SLOT( slotListResult( TDEIO::Job* ) ) );
+ busy = true;
+
+ if( !wait )
+ return true;
+
+ while( busy )
+ tqApp->processEvents();
+ return result;
+ }
+}
+
+void SynchronizerDirList::slotEntries( TDEIO::Job * job, const TDEIO::UDSEntryList& entries )
+{
+ TDEIO::UDSEntryListConstIterator it = entries.begin();
+ TDEIO::UDSEntryListConstIterator end = entries.end();
+
+ int rwx = -1;
+ TQString prot = (( TDEIO::ListJob *)job )->url().protocol();
+
+ if( prot == "krarc" || prot == "tar" || prot == "zip" )
+ rwx = PERM_ALL;
+
+ while( it != end )
+ {
+ KFileItem kfi( *it, (( TDEIO::ListJob *)job )->url(), true, true );
+ TQString key = kfi.text();
+ if( key != "." && key != ".." && (!ignoreHidden || !key.startsWith(".") ) ) {
+ mode_t mode = kfi.mode() | kfi.permissions();
+ TQString perm = KRpermHandler::mode2TQString( mode );
+ if ( kfi.isDir() )
+ perm[ 0 ] = 'd';
+
+ vfile *item = new vfile( kfi.text(), kfi.size(), perm, kfi.time( TDEIO::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( TDEIO::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/src/app/Synchronizer/synchronizerdirlist.h b/src/app/Synchronizer/synchronizerdirlist.h
new file mode 100644
index 0000000..9361a89
--- /dev/null
+++ b/src/app/Synchronizer/synchronizerdirlist.h
@@ -0,0 +1,73 @@
+/***************************************************************************
+ 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 <tqobject.h>
+#include <tqdict.h>
+#include "../VFS/vfile.h"
+#include <tdeio/job.h>
+
+
+class SynchronizerDirList : public TQObject, public TQDict<vfile>
+{
+ TQ_OBJECT
+
+
+public:
+ SynchronizerDirList( TQWidget *w, bool ignoreHidden );
+ ~SynchronizerDirList();
+
+ vfile * search( const TQString &name, bool ignoreCase = false );
+ vfile * first();
+ vfile * next();
+
+ inline const TQString & url() { return currentUrl; }
+ bool load( const TQString &urlIn, bool wait=false );
+
+public slots:
+
+ void slotEntries( TDEIO::Job * job, const TDEIO::UDSEntryList& entries );
+ void slotListResult( TDEIO::Job *job );
+
+signals:
+ void finished( bool err );
+
+private:
+ TQDictIterator<vfile> *fileIterator; //< Point to a dictionary of virtual files (vfile).
+ TQWidget *parentWidget;
+ bool busy;
+ bool result;
+ bool ignoreHidden;
+ TQString currentUrl;
+};
+
+#endif /* __SYNCHRONIZER_DIR_LIST_H__ */
diff --git a/src/app/Synchronizer/synchronizerfileitem.h b/src/app/Synchronizer/synchronizerfileitem.h
new file mode 100644
index 0000000..715fcc5
--- /dev/null
+++ b/src/app/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 <tqstring.h>
+#include <tdeio/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:
+ TQString m_leftName; // the left file name
+ TQString m_rightName; // the right file name
+ TQString m_leftDirectory;// the left relative directory path from the base
+ TQString 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
+ TDEIO::filesize_t m_leftSize; // the file size at the left directory
+ TDEIO::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
+ TQString m_leftLink; // the left file's symbolic link destination
+ TQString m_rightLink; // the right file's symbolic link destination
+ TQString m_leftOwner; // the left file's owner
+ TQString m_rightOwner; // the right file's owner
+ TQString m_leftGroup; // the left file's group
+ TQString m_rightGroup; // the right file's group
+ mode_t m_leftMode; // mode for left
+ mode_t m_rightMode; // mode for right
+ TQString m_leftACL; // ACL of the left file
+ TQString 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
+ TQString m_destination; // the destination URL at rename
+ bool m_temporary; // flag indicates temporary directory
+ TaskType m_originalTask; // the original task type
+
+ public:
+ SynchronizerFileItem(const TQString &leftNam, const TQString &rightNam, const TQString &leftDir,
+ const TQString &rightDir, bool mark, bool exL, bool exR, TDEIO::filesize_t leftSize,
+ TDEIO::filesize_t rightSize, time_t leftDate, time_t rightDate,
+ const TQString &leftLink, const TQString &rightLink, const TQString &leftOwner,
+ const TQString &rightOwner, const TQString &leftGroup, const TQString &rightGroup,
+ mode_t leftMode, mode_t rightMode, const TQString &leftACL, const TQString &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( TQString() ),
+ m_temporary( tmp ), m_originalTask( tsk ) {}
+
+ inline bool isMarked() {return m_marked;}
+ inline void setMarked( bool flag ) {m_marked = flag;}
+ inline const TQString & leftName() {return m_leftName;}
+ inline const TQString & rightName() {return m_rightName;}
+ inline const TQString & leftDirectory() {return m_leftDirectory;}
+ inline const TQString & rightDirectory() {return m_rightDirectory;}
+ inline bool existsInLeft() {return m_existsLeft;}
+ inline bool existsInRight() {return m_existsRight;}
+ inline bool overWrite() {return m_overWrite;}
+ inline TDEIO::filesize_t leftSize() {return m_leftSize;}
+ inline TDEIO::filesize_t rightSize() {return m_rightSize;}
+ inline time_t leftDate() {return m_leftDate;}
+ inline time_t rightDate() {return m_rightDate;}
+ inline const TQString & leftLink() {return m_leftLink;}
+ inline const TQString & rightLink() {return m_rightLink;}
+ inline const TQString & leftOwner() {return m_leftOwner;}
+ inline const TQString & rightOwner() {return m_rightOwner;}
+ inline const TQString & leftGroup() {return m_leftGroup;}
+ inline const TQString & rightGroup() {return m_rightGroup;}
+ inline mode_t leftMode() {return m_leftMode;}
+ inline mode_t rightMode() {return m_rightMode;}
+ inline const TQString & leftACL() {return m_leftACL;}
+ inline const TQString & 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 TQString & destination() {return m_destination;}
+ inline void setDestination(TQString 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, TQString );
+ SWAP( m_leftDirectory, m_rightDirectory, TQString );
+ SWAP( m_leftSize, m_rightSize, TDEIO::filesize_t );
+ SWAP( m_leftDate, m_rightDate, time_t );
+ SWAP( m_leftLink, m_rightLink, TQString );
+ SWAP( m_leftOwner, m_rightOwner, TQString );
+ SWAP( m_leftGroup, m_rightGroup, TQString );
+ SWAP( m_leftACL, m_rightACL, TQString );
+ REVERSE_TASK( m_originalTask, asym );
+ REVERSE_TASK( m_task, asym );}
+};
+
+#endif /* __SYNCHRONIZER_FILE_ITEM_H__ */
diff --git a/src/app/Synchronizer/synchronizergui.cpp b/src/app/Synchronizer/synchronizergui.cpp
new file mode 100644
index 0000000..3a0d2b4
--- /dev/null
+++ b/src/app/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 <tqlayout.h>
+#include <kurlrequester.h>
+#include <tdelocale.h>
+#include <tqgrid.h>
+#include <tdepopupmenu.h>
+#include <tqcursor.h>
+#include <time.h>
+#include <tdemessagebox.h>
+#include <tdeio/netaccess.h>
+#include <tqeventloop.h>
+#include <tqwhatsthis.h>
+#include <tqregexp.h>
+#include <tqheader.h>
+#include <tqspinbox.h>
+#include <kinputdialog.h>
+#include <kurldrag.h>
+#include <tqclipboard.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 TQListView
+{
+private:
+ Synchronizer *synchronizer;
+ bool isLeft;
+
+public:
+ SynchronizerListView( Synchronizer * sync, TQWidget * parent ) : TQListView( parent ), synchronizer( sync )
+ {
+ }
+
+ void contentsMouseMoveEvent ( TQMouseEvent * e )
+ {
+ isLeft = (( e->state() & ShiftButton ) == 0 );
+ TQListView::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() )
+ {
+ TQString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + "/";
+ KURL leftURL = vfs::fromPathOrURL( synchronizer->leftBaseDirectory() + leftDirName + item->leftName() );
+ urls.push_back( leftURL );
+ }
+ else if( !isLeft && item->existsInRight() )
+ {
+ TQString 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" ), TQPoint( -7, 0 ) );
+ d->dragCopy();
+ }
+};
+
+SynchronizerGUI::SynchronizerGUI(TQWidget* parent, KURL leftURL, KURL rightURL, TQStringList selList ) :
+ TQDialog( parent, "Krusader::SynchronizerGUI", false, 0 ) {
+ initGUI( parent, TQString(), leftURL, rightURL, selList );
+}
+
+SynchronizerGUI::SynchronizerGUI(TQWidget* parent, TQString profile ) :
+ TQDialog( parent, "Krusader::SynchronizerGUI", false, 0 ) {
+ initGUI( parent, profile, KURL(), KURL(), TQStringList() );
+}
+
+void SynchronizerGUI::initGUI(TQWidget* /* parent */, TQString profileName, KURL leftURL, KURL rightURL, TQStringList 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") );
+ TQGridLayout *synchGrid = new TQGridLayout( this );
+ synchGrid->setSpacing( 6 );
+ synchGrid->setMargin( 11 );
+
+ folderIcon = TQPixmap( ( const char** ) folder_data );
+ fileIcon = TQPixmap( ( const char** ) file_data );
+
+ synchronizerTabs = new TQTabWidget( this, "synchronizerTabs" );
+
+ /* ============================== Compare groupbox ============================== */
+
+ TQWidget *synchronizerTab = new TQWidget( this, "syncronizerTab" );
+ TQGridLayout *synchronizerGrid = new TQGridLayout( synchronizerTab );
+ synchronizerGrid->setSpacing( 6 );
+ synchronizerGrid->setMargin( 11 );
+
+ TQGroupBox *compareDirs = new TQGroupBox( synchronizerTab, "SyncCompareDirectories" );
+ compareDirs->setSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Fixed);
+ compareDirs->setTitle( i18n( "Directory Comparison" ) );
+ compareDirs->setColumnLayout(0, TQt::Vertical );
+ compareDirs->layout()->setSpacing( 0 );
+ compareDirs->layout()->setMargin( 0 );
+
+ TQGridLayout *grid = new TQGridLayout( compareDirs->layout() );
+ grid->setSpacing( 6 );
+ grid->setMargin( 11 );
+
+ leftDirLabel = new TQLabel( compareDirs, "leftDirLabel" );
+ leftDirLabel->setAlignment( TQt::AlignHCenter );
+ grid->addWidget( leftDirLabel, 0 ,0 );
+
+ TQLabel *filterLabel = new TQLabel( compareDirs, "filterLabel" );
+ filterLabel->setText( i18n( "File &Filter:" ) );
+ filterLabel->setAlignment( TQt::AlignHCenter );
+ grid->addWidget( filterLabel, 0 ,1 );
+
+ rightDirLabel = new TQLabel( compareDirs, "rightDirLabel" );
+ rightDirLabel->setAlignment( TQt::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(TQSizePolicy::Ignored,TQSizePolicy::Fixed);
+ TQStringList 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 );
+ TQWhatsThis::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(TQSizePolicy::Fixed,TQSizePolicy::Fixed);
+ list = krConfig->readListEntry("File Filter");
+ fileFilter->setHistoryItems(list);
+ fileFilter->setEditText("*");
+ grid->addWidget( fileFilter, 1 ,1 );
+ filterLabel->setBuddy( fileFilter );
+
+ TQString 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>");
+ TQWhatsThis::add(fileFilter, wtFilter);
+ TQWhatsThis::add(filterLabel, wtFilter);
+
+ rightLocation = new KHistoryCombo(compareDirs, "SynchronizerHistoryRight");
+ rightLocation->setMaxCount(25); // remember 25 items
+ rightLocation->setDuplicatesEnabled( false );
+ rightLocation->setEditable( true );
+ rightLocation->setSizePolicy(TQSizePolicy::Ignored,TQSizePolicy::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 );
+ TQWhatsThis::add( rightLocation, i18n( "The right base directory used during the synchronisation process." ) );
+ rightUrlReq->setEnabled( !hasSelectedFiles );
+ rightLocation->setEnabled( !hasSelectedFiles );
+ rightDirLabel->setBuddy( rightLocation );
+
+ TQHBox *optionBox = new TQHBox( compareDirs );
+ TQGrid *optionGrid = new TQGrid( 3, optionBox );
+ cbSubdirs = new TQCheckBox( i18n( "Recurse subdirectories" ), optionGrid, "cbSubdirs" );
+ cbSubdirs->setChecked( krConfig->readBoolEntry( "Recurse Subdirectories", _RecurseSubdirs ) );
+ TQWhatsThis::add( cbSubdirs, i18n( "Compare not only the base directories but their subdirectories as well." ) );
+ cbSymlinks = new TQCheckBox( i18n( "Follow symlinks" ), optionGrid, "cbSymlinks" );
+ cbSymlinks->setChecked( krConfig->readBoolEntry( "Follow Symlinks", _FollowSymlinks ) );
+ cbSymlinks->setEnabled( cbSubdirs->isChecked() );
+ TQWhatsThis::add( cbSymlinks, i18n( "Follow symbolic links during the compare process." ) );
+ cbByContent = new TQCheckBox( i18n( "Compare by content" ), optionGrid, "cbByContent" );
+ cbByContent->setChecked( krConfig->readBoolEntry( "Compare By Content", _CompareByContent ) );
+ TQWhatsThis::add( cbByContent, i18n( "Compare duplicated files with same size by content." ) );
+ cbIgnoreDate = new TQCheckBox( i18n( "Ignore Date" ), optionGrid, "cbIgnoreDate" );
+ cbIgnoreDate->setChecked( krConfig->readBoolEntry( "Ignore Date", _IgnoreDate ) );
+ TQWhatsThis::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 TQCheckBox( i18n( "Asymmetric" ), optionGrid, "cbAsymmetric" );
+ cbAsymmetric->setChecked( krConfig->readBoolEntry( "Asymmetric", _Asymmetric ) );
+ TQWhatsThis::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 TQCheckBox( i18n( "Ignore Case" ), optionGrid, "cbIgnoreCase" );
+ cbIgnoreCase->setChecked( krConfig->readBoolEntry( "Ignore Case", _IgnoreCase ) );
+ TQWhatsThis::add( cbIgnoreCase, i18n( "<p>Case insensitive filename compare.</p><p><b>Note</b>: useful when synchronizing Windows filesystems.</p>" ) );
+
+ /* =========================== Show options groupbox ============================= */
+
+ TQGroupBox *showOptions = new TQGroupBox( optionBox, "SyncOptionBox" );
+ showOptions->setTitle( i18n( "S&how options" ) );
+ showOptions->setSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed);
+ showOptions->setColumnLayout(0, TQt::Vertical );
+ showOptions->layout()->setSpacing( 0 );
+ showOptions->layout()->setMargin( 0 );
+ TQGridLayout *showOptionsLayout = new TQGridLayout( showOptions->layout() );
+ showOptionsLayout->setSpacing( 6 );
+ showOptionsLayout->setMargin( 11 );
+
+ TQPixmap showLeftToRight( ( const char** ) right_arrow_button_data );
+ TQPixmap showEquals ( ( const char** ) equals_button_data );
+ TQPixmap showDifferents ( ( const char** ) differents_button_data );
+ TQPixmap showRightToLeft( ( const char** ) left_arrow_button_data );
+ TQPixmap showDeletable ( ( const char** ) trash_button_data );
+
+ btnLeftToRight = new TQPushButton( showOptions, "btnLeftToRight" );
+ btnLeftToRight->setText( "" );
+ btnLeftToRight->setPixmap( showLeftToRight );
+ btnLeftToRight->setToggleButton( true );
+ btnLeftToRight->setOn( krConfig->readBoolEntry( "LeftToRight Button", _BtnLeftToRight ) );
+ btnLeftToRight->setAccel( CTRL + Key_L );
+ TQWhatsThis::add( btnLeftToRight, i18n( "Show files marked to <i>Copy from left to right</i> (CTRL+L)." ) );
+ showOptionsLayout->addWidget( btnLeftToRight, 0, 0);
+
+ btnEquals = new TQPushButton( showOptions, "btnEquals" );
+ btnEquals->setText( "" );
+ btnEquals->setPixmap( showEquals );
+ btnEquals->setToggleButton( true );
+ btnEquals->setOn( krConfig->readBoolEntry( "Equals Button", _BtnEquals ) );
+ btnEquals->setAccel( CTRL + Key_E );
+ TQWhatsThis::add( btnEquals, i18n( "Show files considered to be identical (CTRL+E)." ) );
+ showOptionsLayout->addWidget( btnEquals, 0, 1);
+
+ btnDifferents = new TQPushButton( showOptions, "btnDifferents" );
+ btnDifferents->setText( "" );
+ btnDifferents->setPixmap( showDifferents );
+ btnDifferents->setToggleButton( true );
+ btnDifferents->setOn( krConfig->readBoolEntry( "Differents Button", _BtnDifferents ) );
+ btnDifferents->setAccel( CTRL + Key_D );
+ TQWhatsThis::add( btnDifferents, i18n( "Show excluded files (CTRL+D)." ) );
+ showOptionsLayout->addWidget( btnDifferents, 0, 2);
+
+ btnRightToLeft = new TQPushButton( showOptions, "btnRightToLeft" );
+ btnRightToLeft->setText( "" );
+ btnRightToLeft->setPixmap( showRightToLeft );
+ btnRightToLeft->setToggleButton( true );
+ btnRightToLeft->setOn( krConfig->readBoolEntry( "RightToLeft Button", _BtnRightToLeft ) );
+ btnRightToLeft->setAccel( CTRL + Key_R );
+ TQWhatsThis::add( btnRightToLeft, i18n( "Show files marked to <i>Copy from right to left</i> (CTRL+R)." ) );
+ showOptionsLayout->addWidget( btnRightToLeft, 0, 3);
+
+ btnDeletable = new TQPushButton( showOptions, "btnDeletable" );
+ btnDeletable->setText( "" );
+ btnDeletable->setPixmap( showDeletable );
+ btnDeletable->setToggleButton( true );
+ btnDeletable->setOn( krConfig->readBoolEntry( "Deletable Button", _BtnDeletable ) );
+ btnDeletable->setAccel( CTRL + Key_T );
+ TQWhatsThis::add( btnDeletable, i18n( "Show files marked to delete. (CTRL+T)" ) );
+ showOptionsLayout->addWidget( btnDeletable, 0, 4);
+
+ btnDuplicates = new TQPushButton( showOptions, "btnDuplicates" );
+ btnDuplicates->setText( i18n("Duplicates") );
+ btnDuplicates->setMinimumHeight( btnLeftToRight->height() );
+ btnDuplicates->setToggleButton( true );
+ btnDuplicates->setOn( krConfig->readBoolEntry( "Duplicates Button", _BtnDuplicates ) );
+ TQWhatsThis::add( btnDuplicates, i18n( "Show files that exist on both sides." ) );
+ showOptionsLayout->addWidget( btnDuplicates, 0, 5);
+
+ btnSingles = new TQPushButton( showOptions, "btnSingles" );
+ btnSingles->setText( i18n("Singles") );
+ btnSingles->setMinimumHeight( btnLeftToRight->height() );
+ btnSingles->setToggleButton( true );
+ btnSingles->setOn( krConfig->readBoolEntry( "Singles Button", _BtnSingles ) );
+ TQWhatsThis::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
+ TQWhatsThis::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(TQListView::Extended);
+ syncList->setVScrollBarMode(TQScrollView::Auto);
+ syncList->setHScrollBarMode(TQScrollView::Auto);
+ syncList->setShowSortIndicator(false);
+ syncList->setSorting(-1);
+ syncList->setRootIsDecorated( true );
+ syncList->setTreeStepSize( 10 );
+ int i=TQFontMetrics(syncList->font()).width("W");
+ int j=TQFontMetrics(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,TQListView::Manual);
+ syncList->setColumnWidthMode(1,TQListView::Manual);
+ syncList->setColumnWidthMode(2,TQListView::Manual);
+ syncList->setColumnWidthMode(3,TQListView::Manual);
+ syncList->setColumnWidthMode(4,TQListView::Manual);
+ syncList->setColumnWidthMode(5,TQListView::Manual);
+ syncList->setColumnWidthMode(6,TQListView::Manual);
+ syncList->setColumnAlignment(1, TQt::AlignRight );
+ syncList->setColumnAlignment(3, TQt::AlignHCenter );
+ syncList->setColumnAlignment(5, TQt::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
+
+ TQGroupBox *optionsGroup = new TQGroupBox( generalFilter, "options" );
+ optionsGroup->setTitle( i18n( "&Options" ) );
+ optionsGroup->setColumnLayout(0, TQt::Vertical );
+ optionsGroup->layout()->setSpacing( 0 );
+ optionsGroup->layout()->setMargin( 0 );
+ TQGridLayout *optionsLayout = new TQGridLayout( optionsGroup->layout() );
+ optionsLayout->setAlignment( TQt::AlignTop );
+ optionsLayout->setSpacing( 6 );
+ optionsLayout->setMargin( 11 );
+
+ TQLabel * parallelThreadsLabel = new TQLabel( i18n( "Parallel threads:" ), optionsGroup );
+ optionsLayout->addWidget( parallelThreadsLabel, 0, 0 );
+ parallelThreadsSpinBox = new TQSpinBox( 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 );
+
+ TQLabel * equalityLabel = new TQLabel( i18n( "Equality threshold:" ), optionsGroup );
+ optionsLayout->addWidget( equalityLabel, 1, 0 );
+
+ equalitySpinBox = new TQSpinBox( optionsGroup, "equalitySpinBox" );
+ equalitySpinBox->setMaxValue( 9999 );
+ optionsLayout->addWidget( equalitySpinBox, 1, 1 );
+
+ equalityUnitCombo = new TQComboBox( optionsGroup, "equalityUnitCombo" );
+ equalityUnitCombo->insertItem( i18n( "sec" ) );
+ equalityUnitCombo->insertItem( i18n( "min" ) );
+ equalityUnitCombo->insertItem( i18n( "hour" ) );
+ equalityUnitCombo->insertItem( i18n( "day" ) );
+ optionsLayout->addWidget( equalityUnitCombo, 1, 2 );
+
+ TQLabel * timeShiftLabel = new TQLabel( i18n( "Time shift (right-left):" ), optionsGroup );
+ optionsLayout->addWidget( timeShiftLabel, 2, 0 );
+
+ timeShiftSpinBox = new TQSpinBox( optionsGroup, "timeShiftSpinBox" );
+ timeShiftSpinBox->setMinValue( -9999 );
+ timeShiftSpinBox->setMaxValue( 9999 );
+ optionsLayout->addWidget( timeShiftSpinBox, 2, 1 );
+
+ timeShiftUnitCombo = new TQComboBox( optionsGroup, "timeShiftUnitCombo" );
+ timeShiftUnitCombo->insertItem( i18n( "sec" ) );
+ timeShiftUnitCombo->insertItem( i18n( "min" ) );
+ timeShiftUnitCombo->insertItem( i18n( "hour" ) );
+ timeShiftUnitCombo->insertItem( i18n( "day" ) );
+ optionsLayout->addWidget( timeShiftUnitCombo, 2, 2 );
+
+ TQFrame *line = new TQFrame( optionsGroup );
+ line->setFrameStyle( TQFrame::HLine | TQFrame::Sunken );
+ optionsLayout->addMultiCellWidget( line, 3, 3, 0, 2 );
+
+ ignoreHiddenFilesCB = new TQCheckBox( i18n( "Ignore hidden files" ), optionsGroup );
+ optionsLayout->addMultiCellWidget( ignoreHiddenFilesCB, 4, 4, 0, 2 );
+
+ generalFilter->middleLayout->addWidget( optionsGroup );
+
+
+ /* ================================== Buttons =================================== */
+
+ TQHBoxLayout *buttons = new TQHBoxLayout;
+ buttons->setSpacing( 6 );
+ buttons->setMargin( 0 );
+
+ profileManager = new ProfileManager( "SynchronizerProfile", this, "profileManager" );
+ profileManager->setAccel( CTRL + Key_P );
+ TQWhatsThis::add( profileManager, i18n( "Profile manager (Ctrl+P)." ) );
+ buttons->addWidget( profileManager );
+
+ TQPixmap swapSides( ( const char** ) swap_sides_data );
+ btnSwapSides = new TQPushButton( this, "btnSwapSides" );
+ btnSwapSides->setPixmap( swapSides );
+ btnSwapSides->setAccel( CTRL + Key_S );
+ TQWhatsThis::add( btnSwapSides, i18n( "Swap sides (Ctrl+S)." ) );
+ buttons->addWidget( btnSwapSides );
+
+ statusLabel = new TQLabel( this, "statusLabel" );
+ buttons->addWidget( statusLabel );
+
+ TQSpacerItem* spacer = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum );
+ buttons->addItem( spacer );
+
+ btnCompareDirs = new TQPushButton( this, "btnCompareDirs" );
+ btnCompareDirs->setText( i18n( "Compare" ) );
+ btnCompareDirs->setDefault(true);
+ buttons->addWidget( btnCompareDirs );
+
+ krConfig->setGroup("Synchronize");
+ btnScrollResults = new TQPushButton( 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 TQPushButton( this, "btnStopComparing" );
+ btnStopComparing->setText( i18n( "Stop" ) );
+ btnStopComparing->setEnabled(false);
+ buttons->addWidget( btnStopComparing );
+
+ btnFeedToListBox = new TQPushButton( this, "btnFeedToListBox" );
+ btnFeedToListBox->setText( i18n( "Feed to listbox" ) );
+ btnFeedToListBox->setEnabled(false);
+ btnFeedToListBox->hide();
+ buttons->addWidget( btnFeedToListBox );
+
+ btnSynchronize = new TQPushButton( this, "btnSynchronize" );
+ btnSynchronize->setText( i18n( "Synchronize" ) );
+ btnSynchronize->setEnabled(false);
+ buttons->addWidget( btnSynchronize );
+
+ TQPushButton *btnCloseSync = new TQPushButton( this, "btnCloseSync" );
+ btnCloseSync->setText( i18n( "Close" ) );
+ buttons->addWidget( btnCloseSync );
+
+ synchGrid->addLayout( buttons, 1, 0 );
+
+ /* =============================== Connect table ================================ */
+
+ connect( syncList,TQ_SIGNAL(rightButtonPressed(TQListViewItem *, const TQPoint &, int)),
+ this, TQ_SLOT(rightMouseClicked(TQListViewItem *)));
+ connect( syncList,TQ_SIGNAL(doubleClicked(TQListViewItem *, const TQPoint &, int)),
+ this, TQ_SLOT(doubleClicked(TQListViewItem *)));
+
+ connect( syncList,TQ_SIGNAL(contextMenuRequested(TQListViewItem *, const TQPoint &, int)),
+ this, TQ_SLOT(rightMouseClicked(TQListViewItem *)));
+
+ connect( profileManager, TQ_SIGNAL( loadFromProfile( TQString ) ), this, TQ_SLOT( loadFromProfile( TQString ) ) );
+ connect( profileManager, TQ_SIGNAL( saveToProfile( TQString ) ), this, TQ_SLOT( saveToProfile( TQString ) ) );
+
+ connect( btnSwapSides, TQ_SIGNAL( clicked() ), this, TQ_SLOT( swapSides() ) );
+ connect( btnCompareDirs, TQ_SIGNAL( clicked() ), this, TQ_SLOT( compare() ) );
+ connect( btnStopComparing, TQ_SIGNAL( clicked() ), this, TQ_SLOT( stop() ) );
+ connect( btnFeedToListBox, TQ_SIGNAL( clicked() ), this, TQ_SLOT( feedToListBox() ) );
+ connect( btnSynchronize, TQ_SIGNAL( clicked() ), this, TQ_SLOT( synchronize() ) );
+ connect( btnScrollResults, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( setScrolling(bool) ) );
+ connect( btnCloseSync, TQ_SIGNAL( clicked() ), this, TQ_SLOT( closeDialog() ) );
+
+ connect( cbSubdirs, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( subdirsChecked( bool ) ) );
+ connect( cbAsymmetric, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( setPanelLabels() ) );
+
+ connect( &synchronizer, TQ_SIGNAL( comparedFileData( SynchronizerFileItem * ) ), this,
+ TQ_SLOT( addFile( SynchronizerFileItem * ) ) );
+ connect( &synchronizer, TQ_SIGNAL( markChanged( SynchronizerFileItem *, bool ) ), this,
+ TQ_SLOT( markChanged( SynchronizerFileItem *, bool ) ) );
+ connect( &synchronizer, TQ_SIGNAL( statusInfo( TQString ) ), this, TQ_SLOT( statusInfo( TQString ) ) );
+
+ connect( btnLeftToRight, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( refresh() ) );
+ connect( btnEquals, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( refresh() ) );
+ connect( btnDifferents, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( refresh() ) );
+ connect( btnRightToLeft, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( refresh() ) );
+ connect( btnDeletable, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( refresh() ) );
+ connect( btnDuplicates, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( refresh() ) );
+ connect( btnSingles, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( refresh() ) );
+
+ connect( fileFilter, TQ_SIGNAL( textChanged( const TQString & ) ), this, TQ_SLOT( connectFilters( const TQString & ) ) );
+ connect( generalFilter->searchFor, TQ_SIGNAL( textChanged( const TQString & ) ), this, TQ_SLOT( connectFilters( const TQString & ) ) );
+ connect( generalFilter->searchFor, TQ_SIGNAL( textChanged( const TQString & ) ), this, TQ_SLOT( setCompletion() ) );
+ connect( generalFilter->dontSearchIn, TQ_SIGNAL( checkValidity( TQString &, TQString & ) ),
+ this, TQ_SLOT( checkExcludeURLValidity( TQString &, TQString & ) ) );
+
+ connect( profileManager, TQ_SIGNAL( loadFromProfile( TQString ) ), filterTabs, TQ_SLOT( loadFromProfile( TQString ) ) );
+ connect( profileManager, TQ_SIGNAL( saveToProfile( TQString ) ), filterTabs, TQ_SLOT( saveToProfile( TQString ) ) );
+
+ 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 ++ ) {
+ TQString foreEntry = TQString( "Synchronizer " ) + COLOR_NAMES[ clr ] + TQString( " Foreground" );
+ TQString bckgEntry = TQString( "Synchronizer " ) + COLOR_NAMES[ clr ] + TQString( " Background" );
+
+ if( krConfig->readEntry( foreEntry ) == "KDE default" )
+ foreGrounds[ clr ] = TQColor();
+ else
+ foreGrounds[ clr ] = krConfig->readColorEntry( foreEntry, &FORE_DFLTS[ clr ] );
+
+ if( krConfig->readEntry( bckgEntry ) == "KDE default" )
+ backGrounds[ clr ] = TQColor();
+ 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( TQString &text, TQString &error )
+{
+ KURL url = vfs::fromPathOrURL( text );
+ if( KURL::isRelativeURL( url.url() ) )
+ return;
+
+ TQString 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;
+ }
+
+ TQString 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(TQListViewItem *itemIn)
+{
+ if (!itemIn)
+ return;
+
+ SyncViewItem *syncItem = (SyncViewItem *)itemIn;
+ SynchronizerFileItem *item = syncItem->synchronizerItemRef();
+ if( item && item->existsInLeft() && item->existsInRight() && !item->isDir() )
+ {
+ TQString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + "/";
+ TQString 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(TQListViewItem *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();
+ TQString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + "/";
+ TQString 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
+ TDEPopupMenu 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(TQCursor::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;
+ }
+
+ TQStringList 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 ) );
+
+ TQDialog::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 )
+{
+ TQString leftName="", rightName="", leftDate="", rightDate="", leftSize="", rightSize="";
+ bool isDir = item->isDir();
+
+ TQColor textColor = foreGrounds[ item->task() ];
+ TQColor 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 {
+ TQString 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 );
+}
+
+TQString SynchronizerGUI::convertTime(time_t time) const
+{
+ // convert the time_t to struct tm
+ struct tm* t=localtime((time_t *)&time);
+
+ TQDateTime tmp(TQDate(t->tm_year+1900, t->tm_mon+1, t->tm_mday), TQTime(t->tm_hour, t->tm_min));
+ return TDEGlobal::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;
+ TDEIO::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( TQResizeEvent *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;
+ TQDialog::resizeEvent( e );
+}
+
+void SynchronizerGUI::statusInfo( TQString info )
+{
+ statusLabel->setText( info );
+ tqApp->processEvents();
+}
+
+void SynchronizerGUI::swapSides()
+{
+ if( btnCompareDirs->isEnabled() )
+ {
+ TQString leftCurrent = leftLocation->currentText();
+ leftLocation->setCurrentText( rightLocation->currentText() );
+ rightLocation->setCurrentText( leftCurrent );
+ synchronizer.swapSides();
+ refresh();
+ }
+}
+
+void SynchronizerGUI::keyPressEvent( TQKeyEvent *e )
+{
+ switch ( e->key() )
+ {
+ case Key_M :
+ {
+ if( e->state() == ControlButton )
+ {
+ syncList->setFocus();
+ e->accept();
+ }
+ break;
+ }
+ case Key_F3 :
+ case Key_F4 :
+ {
+ e->accept();
+ TQListViewItem *listItem = syncList->currentItem();
+ if( listItem == 0 )
+ break;
+
+ bool isedit = e->key() == Key_F4;
+
+ SynchronizerFileItem *item = ((SyncViewItem *)listItem)->synchronizerItemRef();
+ TQString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + "/";
+ TQString 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();
+
+ TQListViewItem *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;
+ }
+ TQDialog::reject();
+ }
+ return;
+ }
+
+ TQDialog::keyPressEvent( e );
+}
+
+void SynchronizerGUI::loadFromProfile( TQString 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( TQString 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 TQString &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() )
+ {
+ TQString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + "/";
+ KURL leftURL = vfs::fromPathOrURL( synchronizer.leftBaseDirectory() + leftDirName + item->leftName() );
+ urls.push_back( leftURL );
+ }
+ else if( !isLeft && item->existsInRight() )
+ {
+ TQString 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" ), TQPoint( -7, 0 ) );
+ TQApplication::clipboard()->setData( d );
+}
+
+#include "synchronizergui.moc"
diff --git a/src/app/Synchronizer/synchronizergui.h b/src/app/Synchronizer/synchronizergui.h
new file mode 100644
index 0000000..c442b80
--- /dev/null
+++ b/src/app/Synchronizer/synchronizergui.h
@@ -0,0 +1,225 @@
+/***************************************************************************
+ 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 <tqdialog.h>
+#include <tqlistview.h>
+#include <kcombobox.h>
+#include <tqpixmap.h>
+#include <tqcheckbox.h>
+#include <tqmap.h>
+#include <tqlabel.h>
+#include <tqtabwidget.h>
+
+class TQSpinBox;
+
+class SynchronizerGUI : TQDialog
+{
+ TQ_OBJECT
+
+
+public:
+ class SyncViewItem : public TQListViewItem
+ {
+ private:
+ SynchronizerFileItem *syncItemRef;
+ SyncViewItem *lastItemRef;
+ TQColor textColor;
+ TQColor baseColor;
+
+ public:
+ SyncViewItem( SynchronizerFileItem *item, TQColor txt, TQColor base, TQListView * parent, TQListViewItem *after, TQString label1,
+ TQString label2 = TQString(), TQString label3 = TQString(), TQString label4 = TQString(),
+ TQString label5 = TQString(), TQString label6 = TQString(),
+ TQString label7 = TQString(), TQString label8 = TQString() ) :
+ TQListViewItem( 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, TQColor txt, TQColor base, TQListViewItem * parent, TQListViewItem *after, TQString label1,
+ TQString label2 = TQString(), TQString label3 = TQString(), TQString label4 = TQString(),
+ TQString label5 = TQString(), TQString label6 = TQString(),
+ TQString label7 = TQString(), TQString label8 = TQString() ) :
+ TQListViewItem( 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( TQColor fore, TQColor back ) {
+ textColor = fore;
+ baseColor = back;
+ }
+
+ void paintCell(TQPainter *p, const TQColorGroup &cg, int column, int width, int align)
+ {
+ TQColorGroup _cg = cg;
+ if( textColor.isValid() )
+ _cg.setColor(TQColorGroup::Text, textColor );
+ if( baseColor.isValid() )
+ _cg.setColor(TQColorGroup::Base, baseColor );
+ TQListViewItem::paintCell( p, _cg, column, width, align );
+ };
+ };
+
+public:
+ // if rightDirectory is null, leftDirectory is actually the profile name to load
+ SynchronizerGUI(TQWidget* parent, KURL leftDirectory, KURL rightDirectory = TQString(), TQStringList selList = TQStringList() );
+ SynchronizerGUI(TQWidget* parent, TQString profile );
+ ~SynchronizerGUI();
+
+ inline bool wasSynchronization() {return wasSync;}
+
+public slots:
+ void rightMouseClicked(TQListViewItem *);
+ void doubleClicked(TQListViewItem *);
+ void compare();
+ void synchronize();
+ void stop();
+ void feedToListBox();
+ void closeDialog();
+ void refresh();
+ void swapSides();
+ void loadFromProfile( TQString );
+ void saveToProfile( TQString );
+
+protected slots:
+ void reject();
+ void addFile( SynchronizerFileItem * );
+ void markChanged( SynchronizerFileItem *, bool );
+ void setScrolling( bool );
+ void statusInfo( TQString );
+ void subdirsChecked( bool );
+ void setPanelLabels();
+ void setCompletion();
+ void checkExcludeURLValidity( TQString &text, TQString &error );
+ void connectFilters( const TQString & );
+
+private:
+ void initGUI(TQWidget* parent, TQString profile, KURL leftURL, KURL rightURL, TQStringList selList);
+
+ TQString 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( TQKeyEvent * );
+ virtual void resizeEvent( TQResizeEvent *e );
+
+ ProfileManager *profileManager;
+ FilterTabs *filterTabs;
+ GeneralFilter *generalFilter;
+
+ TQTabWidget *synchronizerTabs;
+
+ KHistoryCombo *leftLocation;
+ KHistoryCombo *rightLocation;
+ KHistoryCombo *fileFilter;
+
+ TQListView *syncList;
+ Synchronizer synchronizer;
+
+ TQCheckBox *cbSubdirs;
+ TQCheckBox *cbSymlinks;
+ TQCheckBox *cbByContent;
+ TQCheckBox *cbIgnoreDate;
+ TQCheckBox *cbAsymmetric;
+ TQCheckBox *cbIgnoreCase;
+
+ TQPushButton *btnSwapSides;
+ TQPushButton *btnCompareDirs;
+ TQPushButton *btnStopComparing;
+ TQPushButton *btnSynchronize;
+ TQPushButton *btnFeedToListBox;
+ TQPushButton *btnScrollResults;
+
+ TQPushButton *btnLeftToRight;
+ TQPushButton *btnEquals;
+ TQPushButton *btnDifferents;
+ TQPushButton *btnRightToLeft;
+ TQPushButton *btnDeletable;
+ TQPushButton *btnDuplicates;
+ TQPushButton *btnSingles;
+
+ TQLabel *statusLabel;
+ TQLabel *leftDirLabel;
+ TQLabel *rightDirLabel;
+
+ TQStringList selectedFiles;
+
+ TQSpinBox *parallelThreadsSpinBox;
+ TQSpinBox *equalitySpinBox;
+ TQComboBox *equalityUnitCombo;
+ TQSpinBox *timeShiftSpinBox;
+ TQComboBox *timeShiftUnitCombo;
+ TQCheckBox *ignoreHiddenFilesCB;
+
+private:
+ TQPixmap fileIcon;
+ TQPixmap folderIcon;
+ bool isComparing;
+ bool wasClosed;
+ bool wasSync;
+ bool firstResize;
+ bool hasSelectedFiles;
+ SyncViewItem *lastItem;
+
+ int sizeX;
+ int sizeY;
+
+ TQColor foreGrounds[ TT_MAX ];
+ TQColor backGrounds[ TT_MAX ];
+};
+
+#endif /* __SYNCHRONIZERGUI_H__ */
diff --git a/src/app/Synchronizer/synchronizertask.cpp b/src/app/Synchronizer/synchronizertask.cpp
new file mode 100644
index 0000000..9a27584
--- /dev/null
+++ b/src/app/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 <tqtimer.h>
+#include <tqfile.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include "../VFS/vfs.h"
+
+CompareTask::CompareTask( SynchronizerFileItem *parentIn, const TQString &leftURL,
+ const TQString &rightURL, const TQString &leftDir,
+ const TQString &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 TQString &urlIn,
+ const TQString &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, TQ_SIGNAL( finished( bool ) ), this, TQ_SLOT( slotFinished( bool ) ));
+ m_dirList->load( m_url, false );
+
+ if( m_duplicate ) {
+ m_otherDirList = new SynchronizerDirList( parentWidget, ignoreHidden );
+ connect( m_otherDirList, TQ_SIGNAL( finished( bool ) ), this, TQ_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, TDEIO::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 TQFile( 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 TQFile( 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 TQTimer( this );
+ connect( timer, TQ_SIGNAL(timeout()), this, TQ_SLOT(sendStatusMessage()) );
+ timer->start( 1000, true );
+
+ localFileCompareCycle();
+ } else {
+ leftReadJob = TDEIO::get( leftURL, false, false );
+ rightReadJob = TDEIO::get( rightURL, false, false );
+
+ connect(leftReadJob, TQ_SIGNAL(data(TDEIO::Job *, const TQByteArray &)),
+ this, TQ_SLOT(slotDataReceived(TDEIO::Job *, const TQByteArray &)));
+ connect(rightReadJob, TQ_SIGNAL(data(TDEIO::Job *, const TQByteArray &)),
+ this, TQ_SLOT(slotDataReceived(TDEIO::Job *, const TQByteArray &)));
+ connect(leftReadJob, TQ_SIGNAL(result(TDEIO::Job*)),
+ this, TQ_SLOT(slotFinished(TDEIO::Job *)));
+ connect(rightReadJob, TQ_SIGNAL(result(TDEIO::Job*)),
+ this, TQ_SLOT(slotFinished(TDEIO::Job *)));
+
+ rightReadJob->suspend();
+
+ timer = new TQTimer( this );
+ connect( timer, TQ_SIGNAL(timeout()), this, TQ_SLOT(sendStatusMessage()) );
+ timer->start( 1000, true );
+ }
+}
+
+void CompareContentTask::localFileCompareCycle() {
+
+ bool different = false;
+
+ char leftBuffer[ 1440 ];
+ char rightBuffer[ 1440 ];
+
+ TQTime 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;
+ }
+
+ TQTimer::singleShot( 0, this, TQ_SLOT( localFileCompareCycle() ) );
+}
+
+
+void CompareContentTask::slotDataReceived(TDEIO::Job *job, const TQByteArray &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 );
+
+ TDEIO::TransferJob *otherJob = ( job == leftReadJob ) ? rightReadJob : leftReadJob;
+
+ if( otherJob == 0 )
+ {
+ if( compareArray.size() )
+ abortContentComparing();
+ }
+ else
+ {
+ if( !((TDEIO::TransferJob *)job)->isSuspended() )
+ {
+ ((TDEIO::TransferJob *)job)->suspend();
+ otherJob->resume();
+ }
+ }
+}
+
+void CompareContentTask::slotFinished(TDEIO::Job *job)
+{
+ TDEIO::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() != TDEIO::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);
+ TQString statstr = TQString( "%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/src/app/Synchronizer/synchronizertask.h b/src/app/Synchronizer/synchronizertask.h
new file mode 100644
index 0000000..2241a04
--- /dev/null
+++ b/src/app/Synchronizer/synchronizertask.h
@@ -0,0 +1,170 @@
+/***************************************************************************
+ 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 <tqobject.h>
+#include <tdeio/job.h>
+
+class Synchronizer;
+class SynchronizerDirList;
+class SynchronizerFileItem;
+class TQProgressDialog;
+class TQTimer;
+class TQFile;
+
+#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 TQObject {
+ TQ_OBJECT
+
+
+public:
+ SynchronizerTask() : TQObject(), m_state( ST_STATE_NEW ), m_statusMessage( TQString() ) {}
+ virtual ~SynchronizerTask() {};
+
+ inline int start( TQWidget *parentWidget ) { this->parentWidget = parentWidget; start(); return state(); }
+
+ inline int state() { return m_state; }
+
+ void setStatusMessage( const TQString & statMsg ) {
+ if( m_state == ST_STATE_PENDING || m_state == ST_STATE_STATUS )
+ m_state = ST_STATE_STATUS;
+ m_statusMessage = statMsg;
+ }
+
+ TQString status() {
+ if( m_state == ST_STATE_STATUS ) {
+ m_state = ST_STATE_PENDING;
+ return m_statusMessage;
+ }
+ return TQString();
+ }
+
+protected:
+ virtual void start() {};
+ int m_state;
+ TQString m_statusMessage;
+ TQWidget *parentWidget;
+};
+
+
+class CompareTask : public SynchronizerTask {
+ TQ_OBJECT
+
+
+public:
+ CompareTask( SynchronizerFileItem *parentIn, const TQString &leftURL,
+ const TQString &rightURL, const TQString &leftDir,
+ const TQString &rightDir, bool ignoreHidden );
+ CompareTask( SynchronizerFileItem *parentIn, const TQString &urlIn,
+ const TQString &dirIn, bool isLeftIn, bool ignoreHidden );
+ virtual ~CompareTask();
+
+ inline bool isDuplicate() { return m_duplicate; }
+ inline bool isLeft() { return !m_duplicate && m_isLeft; }
+ inline const TQString & leftURL() { return m_url; }
+ inline const TQString & rightURL() { return m_otherUrl; }
+ inline const TQString & leftDir() { return m_dir; }
+ inline const TQString & rightDir() { return m_otherDir; }
+ inline const TQString & url() { return m_url; }
+ inline const TQString & 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;
+ TQString m_url;
+ TQString m_dir;
+ TQString m_otherUrl;
+ TQString 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 {
+ TQ_OBJECT
+
+
+public:
+ CompareContentTask( Synchronizer *, SynchronizerFileItem *, const KURL &, const KURL &, TDEIO::filesize_t );
+ virtual ~CompareContentTask();
+
+public slots:
+ void slotDataReceived(TDEIO::Job *job, const TQByteArray &data);
+ void slotFinished(TDEIO::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)
+ TDEIO::filesize_t size; // the size of the compared files
+
+ bool errorPrinted; // flag indicates error
+ TDEIO::TransferJob *leftReadJob; // compare left read job
+ TDEIO::TransferJob *rightReadJob; // compare right read job
+ TQByteArray compareArray; // the array for comparing
+ SynchronizerFileItem *item; // the item for content compare
+ TQTimer *timer; // timer to show the process dialog at compare by content
+
+ TQFile *leftFile; // the left side local file
+ TQFile *rightFile; // the right side local file
+
+ TDEIO::filesize_t received; // the received size
+ Synchronizer *sync;
+};
+
+#endif /* __SYNCHRONIZER_TASK_H__ */
diff --git a/src/app/UserAction/Makefile.am b/src/app/UserAction/Makefile.am
new file mode 100644
index 0000000..691f60a
--- /dev/null
+++ b/src/app/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/src/app/UserAction/expander.cpp b/src/app/UserAction/expander.cpp
new file mode 100644
index 0000000..4b5a745
--- /dev/null
+++ b/src/app/UserAction/expander.cpp
@@ -0,0 +1,1242 @@
+//
+// 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 <tdemessagebox.h>
+#include <tdetempfile.h>
+#include <tqstringlist.h>
+#include <tqclipboard.h>
+
+#include <functional>
+using namespace std;
+
+#define NEED_PANEL if (panel==0) { panelMissingError(_expression,exp); return TQString(); }
+
+#include "tstring.h"
+
+TQValueList<const exp_placeholder*>& Expander::_placeholder()
+{
+ static TQValueList<const exp_placeholder*> ret;
+ return ret;
+}
+
+void exp_placeholder::panelMissingError(const TQString &s, Expander& exp)
+{
+ exp.setError( Error(Error::S_FATAL,Error::C_ARGUMENT,i18n("Needed panel specification missing in expander %1").arg(s)) );
+}
+
+TQStringList exp_placeholder::fileList(const ListPanel* const panel,const TQString& type,const TQString& mask,const bool ommitPath,const bool useUrl,Expander& exp,const TQString& error)
+{
+ TQStringList 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 TQString();
+ }
+ 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 TQStringList&, 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
+ */
+TQString bashquote( TQString 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 TQString evilstuff = "\\\"'`()[]{}!?;$&<>| \t\r\n"; // stuff that should get escaped
+
+ for ( unsigned int i = 0; i < evilstuff.length(); ++i )
+ s.replace( evilstuff[ i ], (TQString("\\") + evilstuff[ i ]) );
+
+ return s;
+}
+
+TQString separateAndQuote(TQStringList list,const TQString& 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 TQStringList& parameter, const bool& useUrl, Expander& exp ) const {
+ NEED_PANEL
+
+ TQString 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 TQStringList& 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 TQString();
+ }
+
+ return TagString(TQString("%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 TQStringList&, 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 TQStringList& parameter, const bool& useUrl, Expander& exp ) const {
+ NEED_PANEL
+
+ TQString item = panel->view->getCurrentItem();
+
+ TQString 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 TQStringList& parameter, const bool& useUrl, Expander& exp ) const {
+ NEED_PANEL
+
+ // get selected items from view
+ TQStringList items;
+ TQString mask;
+
+ if ( parameter.count() <= 3 || parameter[3].isEmpty() )
+ mask = "*";
+ else
+ mask = parameter[3];
+
+ return separateAndQuote(
+ fileList(panel,
+ parameter.empty() ? TQString() : 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 TQStringList& parameter, const bool& useUrl, Expander& exp ) const {
+ NEED_PANEL
+
+ // get selected items from view
+ TQStringList items;
+ TQString 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 TQString();
+ }
+
+ TQTextStream stream( tmpFile.file() );
+ stream << separateAndQuote(
+ fileList(panel,
+ parameter.empty() ? TQString() : 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 TQStringList& 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 TQString(); // 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 TQStringList& 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 TQString(); // 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 TQStringList& parameter, const bool&, Expander& exp ) const {
+ TQString 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 = TQString();
+ 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 TQString();
+ }
+}
+
+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: " << TDEApplication::clipboard()->text() << endl;
+ TQStringList 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 TQString();
+ }
+ if ( parameter.count() <= 1 || parameter[1].string().isEmpty() || TDEApplication::clipboard()->text().isEmpty() )
+ TDEApplication::clipboard()->setText( lst.join("\n") );
+ else
+ TDEApplication::clipboard()->setText( TDEApplication::clipboard()->text() + parameter[1].string() + lst.join("\n") );
+
+ return TQString(); // 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:
+ TQStringList 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 TQString();
+ }
+ KURL::List src;
+ for(TQStringList::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())
+ {
+ setError(exp, Error(Error::S_FATAL,Error::C_ARGUMENT,i18n("Expander: invalid URL's in %_Copy(\"src\", \"dest\")%") ));
+ return TQString();
+ }
+ for (const KURL &url : src)
+ {
+ if (!url.isValid())
+ {
+ setError(exp, Error(Error::S_FATAL,Error::C_ARGUMENT,i18n("Expander: invalid URL's in %_Copy(\"src\", \"dest\")%") ));
+ return TQString();
+ }
+ }
+
+ PreservingCopyJob::createCopyJob( PM_DEFAULT, src, dest, TDEIO::CopyJob::Copy, false, true );
+
+ return TQString(); // 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:
+ TQStringList 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 TQString();
+ }
+ KURL::List src;
+ for(TQStringList::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())
+ {
+ setError(exp, Error(Error::S_FATAL,Error::C_ARGUMENT,i18n("Expander: invalid URL's in %_Move(\"src\", \"dest\")%") ));
+ return TQString();
+ }
+ for (const KURL &url : src)
+ {
+ if (!url.isValid())
+ {
+ setError(exp, Error(Error::S_FATAL,Error::C_ARGUMENT,i18n("Expander: invalid URL's in %_Move(\"src\", \"dest\")%") ));
+ return TQString();
+ }
+ }
+
+ PreservingCopyJob::createCopyJob( PM_DEFAULT, src, dest, TDEIO::CopyJob::Move, false, true );
+
+ return TQString(); // 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 TQStringList& 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 TQString();
+ }
+
+ new SynchronizerGUI( 0, parameter[0] );
+
+ return TQString(); // 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 TQStringList& 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 TQString();
+ }
+
+ new KrSearchDialog( parameter[0], krApp );
+
+ return TQString(); // 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 TQStringList& 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 TQString();
+ }
+
+ MAIN_VIEW->profiles( parameter[0] );
+
+ return TQString(); // 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 TQStringList& parameter, const bool& useUrl, Expander& exp ) const {
+ NEED_PANEL
+
+ TQString mask;
+ if ( parameter.count() <= 2 || parameter[2].isEmpty() )
+ mask = "*";
+ else
+ mask = parameter[2];
+
+ TagString ret;
+ TQStringList l = fileList(panel,
+ parameter.empty() ? TQString() : 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 TQStringList& 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 TQString();
+ }
+
+ 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 << TQString( "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 TQString();
+ }
+
+ //MODE_OUT
+ panel->view->setSortMode( (KrViewProperties::SortSpec)mode );
+// krOut << "end: exp_ColSort::expFunc" << endl;
+ return TQString(); // 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 TQStringList& 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 TQString();
+ }
+
+ TQValueList<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 TQString(); // 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 TQStringList& 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 TQString();
+ }
+
+ TQString 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();
+
+ TQString jsReturn = TQString();
+ if ( parameter[1].lower() == "yes" ) // to stay compatible with the old-style parameter
+ jsReturn = "cmd";
+ else {
+ TQStringList jsVariables = TQStringList::split( ';', parameter[1] );
+ TQString jsVariable, jsValue;
+ for ( TQStringList::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 TQString();
+}
+#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 TQStringList& 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 TQString();
+ }
+
+ TQString 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 TQString(); // 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
+{
+ TQStringList 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 TQString();
+ }
+ 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 TQString& 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 TQString& stringToExpand, bool useUrl ) {
+ TagString result;
+ TQString exp = TQString();
+ 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 TQString();
+ }
+
+ 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 += TQString(TQChar('%'));
+ else {
+ TagStringList parameter = separateParameter( &exp, useUrl );
+ if ( error() )
+ return TQString();
+ 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 TQString();
+ }
+ 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 TQString();
+ }
+ } //else
+ idx = end + 1;
+ }
+ // copy the rest of the string
+ result += stringToExpand.mid( idx );
+// kdDebug() << "============== result '" << result << "'" << endl;
+ return result;
+}
+
+TQStringList Expander::splitEach( TagString stringToSplit ) {
+ if(stringToSplit.isSimple()) {
+// krOut << stringToSplit.string() << endl;
+ return stringToSplit.string();
+ }
+ pair<uint,TQStringList> pl=*stringToSplit.tagsBegin();
+ stringToSplit.eraseTag(stringToSplit.tagsBegin());
+ TQStringList ret;
+ for(TQStringList::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( TQString* const exp, bool useUrl ) {
+ TagStringList parameter;
+ TQStringList parameter1;
+ TQString 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 (TQStringList::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 TQString& 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/src/app/UserAction/expander.h b/src/app/UserAction/expander.h
new file mode 100644
index 0000000..3ae7f21
--- /dev/null
+++ b/src/app/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 TQString;
+#include <tqstring.h>
+#include <tqstringlist.h>
+#include <tqvaluelist.h>
+#include "tstring.h"
+// #include <tqstringlist.h>
+class ListPanel;
+class Expander;
+class Error;
+
+typedef TagString_t<TQStringList> TagString;
+typedef TQValueList<TagString> TagStringList;
+
+/**
+ * This holds informations about each parameter
+ */
+class exp_parameter {
+public:
+ exp_parameter() {}
+ inline exp_parameter( TQString desc, TQString pre, bool ness)
+ { _description = desc; _preset = pre; _nessesary = ness; }
+ inline TQString description() const ///< A description of the parameter
+ { return _description; }
+ inline TQString preset() const ///< the default of the parameter
+ { return _preset; }
+ inline bool nessesary() const ///< false if the parameter is optional
+ { return _nessesary; }
+
+private:
+ TQString _description;
+ TQString _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 TQStringList&, 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 TQString expression() const ///< The placeholder (without '%' or panel-prefix)
+ { return _expression; }
+ inline TQString 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 TQString &s, Expander& exp);
+ static TQStringList splitEach(const TagString& s);
+ static TQStringList fileList(const ListPanel* const panel,const TQString& type,const TQString& mask,const bool ommitPath,const bool useUrl,Expander&,const TQString&);
+ exp_placeholder();
+ exp_placeholder(const exp_placeholder& p);
+ ~exp_placeholder() { }
+ TQString _expression;
+ TQString _description;
+ TQValueList <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,TQString d) : s_(s), c_(c), desc_(d) {}
+ Cause cause() const { return c_; }
+ operator bool() const { return s_!=S_OK; }
+ const TQString& what() const { return desc_; }
+ private:
+ Severity s_;
+ Cause c_;
+ TQString 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_trinity", "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 TQString& 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 TQStringList& 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 TQString& 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 TQStringList 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( TQString* 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 TQString& str, int start );
+
+ void setError(const Error &e) { _err=e; }
+ friend class exp_placeholder;
+
+private:
+ static TQValueList <const exp_placeholder*>& _placeholder();
+ Error _err;
+ TQStringList resultList;
+};
+
+inline void exp_placeholder::setError(Expander& exp,const Error& e) { exp.setError(e); }
+inline TQStringList 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/src/app/UserAction/kraction.cpp b/src/app/UserAction/kraction.cpp
new file mode 100644
index 0000000..edfa1ac
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <kinputdialog.h>
+#include <tqtextedit.h>
+#include <tqvbox.h>
+#include <tqlayout.h>
+#include <tqsplitter.h>
+#include <tqpushbutton.h>
+#include <tqcheckbox.h>
+#include <tqfile.h>
+#include <tqlabel.h>
+#include <tdeaction.h>
+#include <kurl.h>
+#include <tdemessagebox.h>
+#include <tdefiledialog.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 <tqregexp.h>
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////// KrActionProcDlg /////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+#include <tqlayout.h>
+KrActionProcDlg::KrActionProcDlg( TQString caption, bool enableStderr, TQWidget *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") );
+
+ TQVBox *page = makeVBoxMainWidget();
+ // do we need to separate stderr and stdout?
+ if ( enableStderr ) {
+ TQSplitter *splitt = new TQSplitter( TQt::Vertical, page );
+ // create stdout
+ TQVBox *stdoutBox = new TQVBox( splitt, "stdout VBox" );
+ stdoutBox->setSpacing( 6 );
+ new TQLabel( i18n( "Standard Output (stdout)" ), stdoutBox );
+ _stdout = new TQTextEdit( stdoutBox );
+ _stdout->setReadOnly( true );
+ _stdout->setMinimumWidth( fontMetrics().maxWidth() * 40 );
+ // create stderr
+ TQVBox *stderrBox = new TQVBox( splitt, "stderr VBox" );
+ stderrBox->setSpacing( 6 );
+ new TQLabel( i18n( "Standard Error (stderr)" ), stderrBox );
+ _stderr = new TQTextEdit( stderrBox );
+ _stderr->setReadOnly( true );
+ _stderr->setMinimumWidth( fontMetrics().maxWidth() * 40 );
+ } else {
+ // create stdout
+ new TQLabel( i18n( "Output" ), page );
+ _stdout = new TQTextEdit( page );
+ _stdout->setReadOnly( true );
+ _stdout->setMinimumWidth( fontMetrics().maxWidth() * 40 );
+ }
+
+ _currentTextEdit = _stdout;
+ connect( _stdout, TQ_SIGNAL( clicked(int, int) ), TQ_SLOT( currentTextEditChanged() ) );
+ if (_stderr)
+ connect( _stderr, TQ_SIGNAL( clicked(int, int) ), TQ_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.
+ TQWidget* buttonBox = static_cast<TQWidget*>( actionButton(KDialogBase::Ok)->parent() );
+ TQBoxLayout* buttonBoxLayout = static_cast<TQBoxLayout*>( buttonBox->layout() );
+ TQCheckBox* useFixedFont = new TQCheckBox( i18n("Use font with fixed width"), buttonBox );
+ buttonBoxLayout->insertWidget( 0, useFixedFont );
+ useFixedFont->setChecked( startupState );
+ connect( useFixedFont, TQ_SIGNAL( toggled(bool) ), TQ_SLOT( toggleFixedFont(bool) ) );
+}
+
+void KrActionProcDlg::addStderr( TDEProcess *, char *buffer, int buflen ) {
+ if (_stderr)
+ _stderr->append( TQString::fromLatin1( buffer, buflen ) );
+ else {
+ _stdout->setItalic(true);
+ _stdout->append( TQString::fromLatin1( buffer, buflen ) );
+ _stdout->setItalic(false);
+ }
+}
+
+void KrActionProcDlg::addStdout( TDEProcess *, char *buffer, int buflen ) {
+ _stdout->append( TQString::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() {
+ TQString filename = KFileDialog::getSaveFileName(TQString(), i18n("*.txt|Text files\n*|all files"), this);
+ if ( filename.isEmpty() )
+ return;
+ TQFile 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;
+ }
+
+ TQTextStream stream( &file );
+ stream << _currentTextEdit->text();
+ file.close();
+}
+
+void KrActionProcDlg::currentTextEditChanged() {
+ if ( _stderr && _stderr->hasFocus() )
+ _currentTextEdit = _stderr;
+ else
+ _currentTextEdit = _stdout;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////// KrActionProc ////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KrActionProc::KrActionProc( KrActionBase* action ) : TQObject(), _action( action ), _proc( new TDEProcess(this) ), _output( 0 ) {
+ _proc->setUseShell( true );
+
+ connect( _proc, TQ_SIGNAL( processExited( TDEProcess* ) ),
+ this, TQ_SLOT( processExited( TDEProcess* ) ) ) ;
+}
+
+KrActionProc::~KrActionProc() {
+ delete _proc;
+}
+
+void KrActionProc::start( TQString cmdLine ) {
+ TQStringList list = cmdLine;
+ start( list );
+}
+
+void KrActionProc::start( TQStringList cmdLineList ) {
+ _proc->clearArguments();
+ TQString 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 ( TQStringList::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
+ TQKeyEvent keyEvent( TQEvent::KeyPress, 0, -1, 0, cmd+"\n");
+ TQApplication::sendEvent( MAIN_VIEW->konsole_part->widget(), &keyEvent );
+ } else { // will start a new process
+ // run in terminal
+ if ( _action->execType() == KrAction::Terminal ) {
+ krConfig->setGroup( "UserActions" );
+ TQString term = krConfig->readEntry( "Terminal", _UserActions_Terminal );
+
+ if ( _action->user().isEmpty() )
+ ( *_proc ) << term << cmd;
+ else
+// ( *_proc ) << "tdesu" << "-u" << *_properties->user() << "-c" << TDEProcess::quote("konsole --noclose -e " + TDEProcess::quote(cmd) );
+ ( *_proc ) << "tdesu" << "-u" << _action->user() << "-c" << TDEProcess::quote( term + " " + cmd );
+ } else { // no terminal, no output collection, start&forget
+ if ( _action->user().isEmpty() )
+ ( *_proc ) << cmd;
+ else
+ ( *_proc ) << "tdesu" << "-u" << _action->user() << "-c" << TDEProcess::quote(cmd);
+ }
+ _proc->start( TDEProcess::NotifyOnExit, ( TDEProcess::Communication ) ( TDEProcess::Stdout | TDEProcess::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, TQ_SIGNAL( receivedStderr( TDEProcess*, char*, int ) ), _output, TQ_SLOT( addStderr( TDEProcess*, char *, int ) ) );
+ connect( _proc, TQ_SIGNAL( receivedStdout( TDEProcess*, char*, int ) ), _output, TQ_SLOT( addStdout( TDEProcess*, char *, int ) ) );
+ connect( _output, TQ_SIGNAL( cancelClicked() ), this, TQ_SLOT( kill() ) );
+ _output->show();
+ for ( TQStringList::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 tdesu displays the terminal-output of the command
+ ( *_proc ) << "tdesu" << "-t" << "-u" << _action->user() << "-c" << TDEProcess::quote(cmd);
+ _proc->start( TDEProcess::NotifyOnExit, ( TDEProcess::Communication ) ( TDEProcess::Stdout | TDEProcess::Stderr ) );
+ }
+
+}
+
+void KrActionProc::processExited( TDEProcess * ) {
+ // 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( TDEActionCollection *parent, const char* name ) : TDEAction( parent, name ) {
+ connect(this, TQ_SIGNAL(activated()), this, TQ_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 ( TQStringList::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 ( TQStringList::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 ( TQStringList::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 ( TQStringList::Iterator it = _showonlyFile.begin(); it != _showonlyFile.end(); ++it ) {
+ TQRegExp regex = TQRegExp( *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 TQDomElement& 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 ( TQDomNode node = element.firstChild(); !node.isNull(); node = node.nextSibling() ) {
+ TQDomElement 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( TDEShortcut( e.text() ) );
+ else
+
+ // unknown but not empty
+ if ( ! e.tagName().isEmpty() )
+ krOut << "KrAction::xmlRead() - unrecognized tag found: <action name=\"" << name() << "\"><" << e.tagName() << ">" << endl;
+
+ } // for ( TQDomNode node = action->firstChild(); !node.isNull(); node = node.nextSibling() )
+
+ return true;
+} //KrAction::xmlRead
+
+TQDomElement KrAction::xmlDump( TQDomDocument& doc ) const {
+ TQDomElement actionElement = doc.createElement("action");
+ actionElement.setAttribute( "name", name() );
+
+#define TEXT_ELEMENT( TAGNAME, TEXT ) \
+ { \
+ TQDomElement 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() )
+
+ TQDomElement 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 TQDomElement& element ) {
+ TQString 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
+
+TQDomElement KrAction::dumpCommand( TQDomDocument& doc ) const {
+ TQDomElement 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 TQDomElement& element ) {
+ for ( TQDomNode node = element.firstChild(); ! node.isNull(); node = node.nextSibling() ) {
+ TQDomElement e = node.toElement();
+ if ( e.isNull() )
+ continue; // this should skip nodes which are not elements ( i.e. comments, <!-- -->, or text nodes)
+
+ TQStringList* 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 ( TQDomNode subnode = e.firstChild(); ! subnode.isNull(); subnode = subnode.nextSibling() ) {
+ TQDomElement subelement = subnode.toElement();
+ if ( subelement.tagName() == "show" )
+ showlist->append( subelement.text() );
+ } // for
+ } // if ( showlist )
+
+ } // for
+} //KrAction::readAvailability
+
+TQDomElement KrAction::dumpAvailability( TQDomDocument& doc ) const {
+ TQDomElement availabilityElement = doc.createElement("command");
+
+# define LIST_ELEMENT( TAGNAME, LIST ) \
+ { \
+ TQDomElement e = doc.createElement( TAGNAME ); \
+ for ( TQStringList::const_iterator it = LIST.constBegin(); it != LIST.constEnd(); ++it ) { \
+ TQDomElement 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/src/app/UserAction/kraction.h b/src/app/UserAction/kraction.h
new file mode 100644
index 0000000..095dcc8
--- /dev/null
+++ b/src/app/UserAction/kraction.h
@@ -0,0 +1,170 @@
+//
+// 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 <tdeaction.h>
+#include <kprocess.h>
+#include <kdialogbase.h>
+#include "kractionbase.h"
+
+class UserActionProperties;
+class TQTextEdit;
+class TDEActionCollection;
+class TQDomElement;
+class TQDomDocument;
+
+/**
+ * This subclass of TDEAction extends it with an individual executor and a struct UserActionProperties. It is used to integrate useractions into KDE's TDEAction-System
+ * @author Jonas Bähr (http://www.jonas-baehr.de)
+ */
+class KrAction: public TDEAction, public KrActionBase {
+ TQ_OBJECT
+
+ public:
+ KrAction( TDEActionCollection *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 TQDomElement& element );
+ TQDomElement xmlDump( TQDomDocument& doc ) const;
+
+ void setName( const char* ) { /* empty reimplementation to prevent a name-change */ };
+
+ TQString category() const { return _category; };
+ void setCategory( const TQString& category ) { _category = category; };
+
+ TQString command() const { return _command; };
+ void setCommand( const TQString& command ) { _command = command; };
+
+ TQString user() const { return _user; };
+ void setUser( const TQString& user ) { _user = user; };
+
+ TQString startpath() const { return _startpath; };
+ void setStartpath( const TQString& 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; };
+
+ TQStringList showonlyProtocol() const { return _showonlyProtocol; };
+ void setShowonlyProtocol( const TQStringList& showonlyProtocol ) { _showonlyProtocol = showonlyProtocol; };
+
+ TQStringList showonlyPath() const { return _showonlyPath; };
+ void setShowonlyPath( const TQStringList& showonlyPath ) { _showonlyPath = showonlyPath; };
+
+ TQStringList showonlyMime() const { return _showonlyMime; };
+ void setShowonlyMime( const TQStringList& showonlyMime ) { _showonlyMime = showonlyMime; };
+
+ TQStringList showonlyFile() const { return _showonlyFile; };
+ void setShowonlyFile( const TQStringList& showonlyFile ) { _showonlyFile = showonlyFile; };
+
+ bool doSubstitution() const {
+ return true;
+ }
+
+ TQString text() const {
+ return TDEAction::text();
+ }
+
+ public slots:
+ void exec() {
+ KrActionBase::exec();
+ }
+
+
+ private:
+ void readCommand( const TQDomElement& element );
+ TQDomElement dumpCommand( TQDomDocument& doc ) const;
+
+ void readAvailability( const TQDomElement& element );
+ TQDomElement dumpAvailability( TQDomDocument& doc ) const;
+
+ TQString _category;
+ TQString _command;
+ TQString _user;
+ TQString _startpath;
+ ExecType _execType;
+ bool _acceptURLs;
+ bool _confirmExecution;
+ TQStringList _showonlyProtocol;
+ TQStringList _showonlyPath;
+ TQStringList _showonlyMime;
+ TQStringList _showonlyFile;
+
+};
+
+class TQFont;
+/**
+ * This displays the output of a process
+ * @author Shie Erlich, Jonas Bähr
+ */
+class KrActionProcDlg: public KDialogBase {
+ TQ_OBJECT
+
+ public:
+ KrActionProcDlg( TQString caption, bool enableStderr = false, TQWidget *parent = 0 );
+
+ protected slots:
+ void addStderr( TDEProcess *proc, char *buffer, int buflen );
+ void addStdout( TDEProcess *proc, char *buffer, int buflen );
+ void toggleFixedFont( bool state );
+ void slotUser1(); ///< This is used to save the buffer to disc
+
+ private:
+ TQTextEdit *_stdout, *_stderr, *_currentTextEdit;
+ TQFont 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 TQObject {
+ TQ_OBJECT
+
+ public:
+
+ KrActionProc( KrActionBase* action );
+ virtual ~KrActionProc();
+ void start( TQString cmdLine );
+ void start( TQStringList cmdLineList );
+
+ protected slots:
+ void kill() { _proc->kill( SIGINT ); }
+ void processExited( TDEProcess *proc );
+
+ private:
+ KrActionBase* _action;
+ TDEProcess *_proc;
+ TQString _stdout;
+ TQString _stderr;
+ KrActionProcDlg *_output;
+};
+
+
+#endif //KRACTION_H
diff --git a/src/app/UserAction/kractionbase.cpp b/src/app/UserAction/kractionbase.cpp
new file mode 100644
index 0000000..6eb520d
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+
+#include <tqerrormessage.h>
+
+#include "kraction.h"
+#include "expander.h"
+#include "kractionbase.h"
+
+KrActionBase::~KrActionBase()
+{
+}
+
+void KrActionBase::exec() {
+ KrActionProc *proc;
+
+ // replace %% and prepare string
+ TQStringList 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 ( TQStringList::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)
+{
+ TQErrorMessage::qtHandler()->message(err.what());
+}
+
+KrActionProc* KrActionBase::actionProcFactoryMethod()
+{
+ return new KrActionProc(this);
+}
diff --git a/src/app/UserAction/kractionbase.h b/src/app/UserAction/kractionbase.h
new file mode 100644
index 0000000..6691a06
--- /dev/null
+++ b/src/app/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 <tqstring.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 TQString 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 TQString 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 TQString 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 TQString 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/src/app/UserAction/tstring.h b/src/app/UserAction/tstring.h
new file mode 100644
index 0000000..9b7d57d
--- /dev/null
+++ b/src/app/UserAction/tstring.h
@@ -0,0 +1,116 @@
+//
+// C++ Interface: tstring
+//
+// Description:
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#ifndef __TAGSTRING__H
+#define __TAGSTRING__H
+
+#include <tqstring.h>
+#include <tqvaluelist.h>
+#include <utility>
+#include <cassert>
+
+using namespace std;
+
+template <class T>
+class TagString_t
+{
+ TQString str;
+ typedef TQValueList<std::pair<uint,T> > taglist; // may change
+ taglist tags;
+public:
+ TagString_t(const TQString& s) : str(s) {}
+ TagString_t() {}
+ bool isSimple() const { return tags.empty(); }
+ const TQString& 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 TQString& s);
+ int find ( TQChar 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 TQString&);
+ 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 TQString& 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/src/app/UserAction/useraction.cpp b/src/app/UserAction/useraction.cpp
new file mode 100644
index 0000000..4e412bd
--- /dev/null
+++ b/src/app/UserAction/useraction.cpp
@@ -0,0 +1,212 @@
+//
+// 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 <tdepopupmenu.h>
+#include <kstandarddirs.h>
+#include <tdemessagebox.h>
+
+#include <tqstring.h>
+#include <tqdom.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 TDEActionCollection, 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 TDEActionCollection
+}
+
+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( TDEPopupMenu* menu ) {
+ for ( KrAction* action = _actions.first(); action; action = _actions.next() )
+ if ( ! action->isPlugged( menu ) )
+ action->plug( menu );
+}
+
+TQStringList UserAction::allCategories() {
+ TQStringList actionCategories;
+
+ for ( KrAction* action = _actions.first(); action; action = _actions.next() )
+ if ( actionCategories.find( action->category() ) == actionCategories.end() )
+ actionCategories.append( action->category() );
+
+ return actionCategories;
+}
+
+TQStringList UserAction::allNames() {
+ TQStringList actionNames;
+
+ for ( KrAction* action = _actions.first(); action; action = _actions.next() )
+ actionNames.append( action->name() );
+
+ return actionNames;
+}
+
+void UserAction::readAllFiles() {
+ TQString filename = locate( "data", ACTION_XML ); // locate returns the local file if it exists, else the global one is retrieved.
+ if ( ! filename.isEmpty() ) {
+ readFromFile( filename, renameDoublicated );
+ return;
+ }
+
+ filename = locate( "data", ACTION_XML_EXAMPLES );
+ if ( ! filename.isEmpty() )
+ readFromFile( filename, ignoreDoublicated ); // ignore samples which are already in the normal file
+}
+
+void UserAction::readFromFile( const TQString& filename, ReadMode mode, KrActionList* list ) {
+ TQDomDocument* doc = new TQDomDocument( ACTION_DOCTYPE );
+ TQFile 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 ) {
+ TQDomElement 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 TQDomElement& element, ReadMode mode, KrActionList* list ) {
+ for ( TQDomNode node = element.firstChild(); ! node.isNull(); node = node.nextSibling() ) {
+ TQDomElement 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" ) {
+ TQString 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;
+
+ TQString 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
+}
+
+TQDomDocument UserAction::createEmptyDoc() {
+ TQDomDocument doc = TQDomDocument( 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() {
+ TQString filename = locateLocal( "data", ACTION_XML );
+
+ TQDomDocument doc = createEmptyDoc();
+ TQDomElement 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 TQDomDocument& doc, const TQString& filename ) {
+ TQFile 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
+ TQDomProcessingInstruction instr = doc.createProcessingInstruction( "xml", ACTION_PROCESSINSTR );
+ doc.insertBefore( instr, doc.firstChild() );
+ }
+*/
+
+ TQTextStream ts( &file );
+ ts.setEncoding(ts.UnicodeUTF8);
+ ts << doc.toString();
+
+ file.close();
+ return true;
+}
+
+
+
+
diff --git a/src/app/UserAction/useraction.h b/src/app/UserAction/useraction.h
new file mode 100644
index 0000000..11ed68c
--- /dev/null
+++ b/src/app/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 <tqptrlist.h>
+
+class TQDomDocument;
+class TQDomElement;
+class TQString;
+class TQStringList;
+class KrAction;
+class KURL;
+class TDEPopupMenu;
+
+/**
+ * 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 TQPtrList<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 TDEPopupMenu with all available UserActions in the list
+ * @param popupmenu to populate
+ */
+ void populateMenu(TDEPopupMenu* menu);
+
+ TQStringList allCategories();
+ TQStringList 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 TQString& 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 TQDomElement& element, ReadMode mode = renameDoublicated, KrActionList* list = 0 );
+
+ /**
+ * creates an empty TQDomDocument for the UserActions
+ */
+ static TQDomDocument createEmptyDoc();
+ /**
+ * Writes a TQDomDocument 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 TQDomDocument& doc, const TQString& 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/src/app/UserAction/useractionpopupmenu.cpp b/src/app/UserAction/useractionpopupmenu.cpp
new file mode 100644
index 0000000..c100992
--- /dev/null
+++ b/src/app/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, TQWidget *parent ) : TDEPopupMenu( 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/src/app/UserAction/useractionpopupmenu.h b/src/app/UserAction/useractionpopupmenu.h
new file mode 100644
index 0000000..33ea818
--- /dev/null
+++ b/src/app/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 <tdepopupmenu.h>
+
+class KURL;
+
+class UserActionPopupMenu : public TDEPopupMenu {
+public:
+ UserActionPopupMenu( KURL currentURL, TQWidget *parent = 0 );
+};
+
+#endif // ifndef USERACTIONPOPUPMENU_H
diff --git a/src/app/UserMenu/Makefile.am b/src/app/UserMenu/Makefile.am
new file mode 100644
index 0000000..1d48899
--- /dev/null
+++ b/src/app/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/src/app/UserMenu/usermenu.cpp b/src/app/UserMenu/usermenu.cpp
new file mode 100644
index 0000000..5f9241a
--- /dev/null
+++ b/src/app/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 <tdelocale.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( TQWidget * parent, const char * name ) : TQWidget( parent, name ) {
+ _popup = new UserMenuGui(this);
+}
+
+void UserMenu::update() {
+ _popup->createMenu();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+UserMenuGui::UserMenuGui( UserMenu *, TQWidget * parent ) : TDEPopupMenu( 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/src/app/UserMenu/usermenu.h b/src/app/UserMenu/usermenu.h
new file mode 100644
index 0000000..f987b4d
--- /dev/null
+++ b/src/app/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 <tdepopupmenu.h>
+
+class TQWidget;
+class UserMenu;
+
+class UserMenuGui: public TDEPopupMenu {
+ public:
+ UserMenuGui( UserMenu* menu, TQWidget *parent = 0 );
+ void run();
+ void createMenu();
+
+ protected:
+ void readEntries();
+};
+
+class UserMenu : public TQWidget {
+ public:
+ UserMenu( TQWidget *parent = 0, const char *name = 0 );
+ void exec();
+ void update();
+
+ private:
+ UserMenuGui* _popup;
+};
+
+#endif
diff --git a/src/app/VFS/Makefile.am b/src/app/VFS/Makefile.am
new file mode 100644
index 0000000..63ef663
--- /dev/null
+++ b/src/app/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/src/app/VFS/arc_vfs.cpp b/src/app/VFS/arc_vfs.cpp
new file mode 100644
index 0000000..4af6c74
--- /dev/null
+++ b/src/app/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>
+// TQt includes
+#include <tqregexp.h>
+#include <tqdir.h>
+#include <tqdatetime.h>
+#include <tqfileinfo.h>
+// TDE includes
+#include <tdemessagebox.h>
+#include <tdelocale.h>
+#include <kprocess.h>
+#include <tdeio/jobclasses.h>
+#include <tqprogressdialog.h>
+#include <tdeglobalsettings.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(TQString origin,TQString type,TQObject* 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;
+ }
+
+ TQString password = TQString();
+ 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 ";
+ TQString 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(TQRegExp(" "),"\\ ");
+
+ 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(TDEProcess::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 ? TQString(KrServices::fullPathName( "rar" ) + " -r a ") : TQString("")) ;
+ 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
+TQString arc_vfs::vfs_workingDir(){
+ // get the path inside the archive
+ TQString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ if(path.left(1) != "/") path = "/"+path;
+ TQDir().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(TDEProcess::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(TDEProcess::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
+ TQFile temp(tmpDir+"/tempfilelist");
+ temp.open(IO_ReadOnly);
+ char buf[1000];
+ TQString 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 = TQString::fromLocal8Bit(buf);
+ if ( line.contains("----------") ) break;
+ parseLine(line.stripWhiteSpace(),&temp);
+
+ }
+ temp.close();
+ TQDir().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,TDEIO::CopyJob::CopyMode mode,TQObject* toNotify,TQString dir, PreserveMode /*pmode*/ ){
+ if ( addCmd.isEmpty() ) return;
+
+ // get the path inside the archive
+ TQString 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= TQString(tmpDir+path+dir).find('/',i+1) ){
+ TQDir().mkdir(TQString(tmpDir+path+dir).left(i));
+ }
+
+ changed = true; //rescan the archive
+
+ KURL dest;
+ dest.setPath(tmpDir+path+dir);
+
+ TDEIO::Job* job = new TDEIO::CopyJob(*fileUrls,dest,mode,false,true);
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(vfs_refresh(TDEIO::Job*)) );
+ if(mode == TDEIO::CopyJob::Move) // notify the other panel
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),toNotify,TQ_SLOT(vfs_refresh(TDEIO::Job*)) );
+}
+
+
+// remove a file from the vfs (physical)
+void arc_vfs::vfs_delFiles(TQStringList *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;
+
+ TDEIO::Job *job = new TDEIO::CopyJob(*filesUrls,TDEGlobalSettings::trashPath(),TDEIO::CopyJob::Move,false,true );
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(vfs_refresh(TDEIO::Job*)));
+ }
+ // else we have to delete the files from both the archive and the temp dir
+ else {
+ // change dir to the temp dir
+ TQString save = getcwd(0,0);
+ chdir(tmpDir.local8Bit());
+
+ TQStringList files;
+ TDEIO::filesize_t totalSizeVal = 0;
+ unsigned long totalFilesVal = 0;
+
+ // names -> urls
+ for(TQStringList::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,TQ_SIGNAL(receivedStdout(TDEProcess*,char*,int)),
+ krApp, TQ_SLOT(incProgress(TDEProcess*,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(TDEProcess::NotifyOnExit,TDEProcess::AllOutput);
+ proc2.start();
+ while( proc1.isRunning() || proc2.isRunning() ) tqApp->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
+TQString arc_vfs::vfs_getFile(TQString name){
+ // get the current file path
+ TQString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ if(path.left(1)=="/") path.remove(0,1);
+ if(path != "") path = path+"/";
+
+ TQStringList temp(name);
+ vfs_getFiles(&temp);
+
+ return tmpDir+"/"+path+name;
+}
+
+KURL::List* arc_vfs::vfs_getFiles(TQStringList* names){
+ KURL url;
+ KURL::List* urls = new KURL::List();
+
+ // get the current file path
+ TQString 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
+ TQString save = getcwd(0,0);
+ chdir(tmpDir.local8Bit());
+ // names -> urls
+ TQStringList files;
+ TDEIO::filesize_t totalSize = 0;
+ unsigned long totalFiles = 0;
+ for(TQStringList::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(TQStringList::Iterator file = files.begin(); file != files.end(); ++file ){
+ if ( (*file).right(1)=="/" ){
+ TQDir(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,TQ_SIGNAL(receivedStdout(TDEProcess*,char*,int)),
+ krApp, TQ_SLOT(incProgress(TDEProcess*,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(TDEProcess::NotifyOnExit,TDEProcess::AllOutput);
+ while( proc.isRunning() ) tqApp->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(TQString name){
+ TQString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ if(path.left(1)=="/") path.remove(0,1);
+ if(path != "") path = path+"/";
+
+ TQDir(tmpDir).mkdir(path+name);
+ changed = true; //rescan the archive
+ vfs_refresh(vfs_origin);
+}
+
+// rename file
+void arc_vfs::vfs_rename(TQString fileName,TQString newName){
+ KURL::List temp;
+ temp.append(vfs_getFile(fileName));
+ TQString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ if(path.left(1)=="/") path.remove(0,1);
+ if(path != "") path = path+"/";
+
+ TQDir(tmpDir).mkdir(path);
+ changed = true; //rescan the archive
+
+ KURL dest;
+ dest.setPath(tmpDir+path+"/"+newName);
+
+ TDEIO::Job* job = new TDEIO::CopyJob(temp,dest,TDEIO::CopyJob::Move,false,false);
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(vfs_refresh(TDEIO::Job*)) );
+}
+
+bool arc_vfs::vfs_refresh(TQString 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...
+ TQString 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
+TQString arc_vfs::nextWord(TQString &s,char d) {
+ s=s.stripWhiteSpace();
+ int j=s.find(d,0);
+ TQString temp=s.left(j); // find the leftmost word.
+ s.remove(0,j);
+ return temp;
+}
+
+void arc_vfs::getFilesToPack(TQStringList* filesToPack,TQString 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+"/";
+
+ DIR* dir = opendir(tmpDir.local8Bit()+"/"+dir_name.local8Bit());
+ if(!dir) return ;
+
+ struct dirent* dirEnt;
+ TQString 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 && TQDir(dir_name+name).entryList(TQDir::All | TQDir::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(TQStringList* filesToDelete,TQString){
+ // sync the extFiles - and find out which files were deleted
+ TQString 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(TQString dir_name){
+ 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+"/";
+
+ struct dirent* dirEnt;
+ TQString 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(){
+ TQString save = getcwd(0,0);
+ chdir(tmpDir.local8Bit());
+
+ // delete from the archive files that were unpacked and deleted
+ if( vfs_isWritable() ){
+ TQStringList filesToDelete;
+ getFilesToDelete(&filesToDelete);
+ if( !filesToDelete.isEmpty() ){
+ KShellProcess delProc;
+ krApp->startWaiting(i18n("Deleting Files..."),filesToDelete.count()+ignoreLines);
+ connect(&delProc,TQ_SIGNAL(receivedStdout(TDEProcess*,char*,int)),
+ krApp, TQ_SLOT(incProgress(TDEProcess*,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(TDEProcess::NotifyOnExit,TDEProcess::AllOutput);
+ while( delProc.isRunning() ) tqApp->processEvents();
+ delProc.clearArguments();
+ delProc << delCmd << "\""+arcFile+"\"";
+ }
+ }
+ krApp->stopWait();
+ }
+ }
+
+ // finaly repack tmpDir
+ if( vfs_isWritable() || vfs_type=="gzip" || vfs_type=="zip2" ){
+ TQStringList filesToPack;
+ getFilesToPack(&filesToPack);
+ if( !filesToPack.isEmpty() ){
+ KShellProcess addProc;
+ krApp->startWaiting(i18n("Repacking..."),filesToPack.count()+ignoreLines);
+ connect(&addProc,TQ_SIGNAL(receivedStdout(TDEProcess*,char*,int)),
+ krApp, TQ_SLOT(incProgress(TDEProcess*,char*,int)) );
+
+ if( vfs_type=="gzip" || vfs_type=="zip2" ){
+ addProc << addCmd << *filesToPack.at(0)<< ">" << "\""+arcFile+"\"";
+ addProc.start(TDEProcess::NotifyOnExit);
+ while( addProc.isRunning() ) tqApp->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(TDEProcess::NotifyOnExit,TDEProcess::AllOutput);
+ while( addProc.isRunning() ) tqApp->processEvents(); // busy wait - need to find something better...
+ addProc.clearArguments();
+ addProc << addCmd << "\""+arcFile+"\"";
+ }
+ }
+ }
+ krApp->stopWait();
+ }
+ }
+ chdir(save.local8Bit());
+}
+
+vfileDict* arc_vfs::findDir(TQString 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(TQString name){
+for(arc_dir* temp = dirList.first();temp != 0 ; temp = dirList.next()){
+ if(temp->name == name) return temp;
+ }
+ return 0;
+}
+
+TQString arc_vfs::changeDir(TQString name){
+ if(name.left(2) == "./") {
+ prefix = "./";
+ name.remove(0,2);
+ }
+
+ if(!name.contains('/')){
+ vfs_filesP = findDir("");
+ return name;
+ }
+ // seperate the path from the name
+ TQString 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
+ TQString Pname = path.mid(path.findRev('/')+1);
+ if(Pname.isEmpty()) return name;
+ TQString tempName = arcFile;
+ TQFileInfo qfi(tempName.replace(TQRegExp("\\"),""));
+ 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(TQString name ,TDEIO::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
+ TQString 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);
+
+ TQString 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 TQString& name, TQStringList *urls,TDEIO::filesize_t *totalSize,unsigned long *totalFiles ){
+ vfile* vf = vfs_search(name);
+ if ( vf == 0 ) return;
+
+ // get the path inside the archive
+ TQString 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+"/");
+ TQString 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(TQString line, TQFile* temp){
+ TQString name;
+ TDEIO::filesize_t size = 0;
+ TQString perm;
+ TQFileInfo qfi(arcFile);
+ time_t mtime = qfi.lastModified().toTime_t();
+ bool link = false;
+ uid_t owner = getuid();
+ gid_t group = getgid();
+ TQString 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::mode2TQString(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::mode2TQString(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);
+ TQString 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);
+ TQString 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);
+ TQString tempName = arcFile;
+ TQFileInfo qfi(tempName.replace(TQRegExp("\\"),""));
+ 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::mode2TQString(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;
+
+
+ TQString 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/src/app/VFS/arc_vfs.h b/src/app/VFS/arc_vfs.h
new file mode 100644
index 0000000..bb7dd0c
--- /dev/null
+++ b/src/app/VFS/arc_vfs.h
@@ -0,0 +1,131 @@
+/***************************************************************************
+ 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 <tqvaluestack.h>
+#include <kprocess.h>
+#include <tqfile.h>
+#include <tqprogressdialog.h>
+
+class arc_vfs : public vfs {
+ TQ_OBJECT
+
+ class arc_dir;
+ class extFile;
+public:
+ arc_vfs(TQString origin,TQString type,TQObject* panel,bool write);
+ ~arc_vfs();
+
+ // copy a file to the vfs (physical)
+ void vfs_addFiles(KURL::List *fileUrls,TDEIO::CopyJob::CopyMode mode,TQObject* toNotify=0,TQString dir = "", PreserveMode pmode = PM_DEFAULT );
+ // remove a file from the vfs (physical)
+ void vfs_delFiles(TQStringList *fileNames);
+ // return a path to the file
+ TQString vfs_getFile(TQString name);
+ KURL::List* vfs_getFiles(TQStringList* names);
+ // make dir
+ void vfs_mkdir(TQString name);
+ // rename file
+ void vfs_rename(TQString fileName,TQString newName);
+ // calculate space
+ void vfs_calcSpace(TQString name ,TDEIO::filesize_t *totalSize,unsigned long *totalFiles,unsigned long *totalDirs, bool* stop);
+ // return the working dir
+ TQString vfs_workingDir();
+
+public slots:
+ // actually reads files and stats
+ bool vfs_refresh(TQString origin);
+ void repack();
+
+protected:
+ TQString tmpDir; // the temp directory tha archive is using
+ TQString arcFile; // the archive file URL
+ bool changed; // true if repack changed the archive
+ TQPtrList<arc_dir> dirList;
+ TQValueList<extFile> extFiles; // the name, time & size of files unpacked from this archive
+
+ void processName(const TQString& name,TQStringList *urls,TDEIO::filesize_t *totalSize,unsigned long *totalFiles );
+ bool getDirs(); // fill the dir list
+ vfileDict* findDir(TQString name);
+ arc_dir* findArcDir(TQString name);
+ void getFilesToPack (TQStringList* filesToPack,TQString dir_name = "");
+ void getFilesToDelete(TQStringList* filesToDelete,TQString dir_name = "");
+ void getExtFiles( TQString dir_name="" );
+ TQString nextWord( TQString &s, char d=' ' );
+ TQString changeDir(TQString name);
+
+ void parseLine(TQString line,TQFile* temp);
+
+ TQString prefix;
+ TQString cmd; // the archiver main command
+ TQString listCmd; // the file listing option
+ TQString delCmd; // the delete option
+ TQString addCmd; // the add files option
+ TQString 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(TQString _name){
+ name = _name;
+ entries.setAutoDelete(true);
+ }
+ TQString 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(TQString u): url(u),time(0),size(0){}
+ extFile(TQString 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;
+ }
+ TQString url;
+ time_t time;
+ off_t size;
+ };
+
+
+
+};
+
+#endif
diff --git a/src/app/VFS/ftp_vfs.cpp b/src/app/VFS/ftp_vfs.cpp
new file mode 100644
index 0000000..2da0665
--- /dev/null
+++ b/src/app/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
+// TQt includes
+#include <tqdir.h>
+#include <tqregexp.h>
+#include <tqtimer.h>
+#include <tqeventloop.h>
+// TDE includes
+#include <tdeio/jobclasses.h>
+#include <tdelocale.h>
+#include <tdeio/job.h>
+#include <tdemessagebox.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( TQObject* panel ) : vfs( panel ), busy( false ) {
+ // set the writable attribute
+ isWritable = true;
+ vfs_type = FTP;
+}
+
+ftp_vfs::~ftp_vfs() {
+ busy = false;
+}
+
+void ftp_vfs::slotAddFiles( TDEIO::Job *, const TDEIO::UDSEntryList& entries ) {
+ int rwx = -1;
+
+ TQString prot = vfs_origin.protocol();
+ if( prot == "krarc" || prot == "tar" || prot == "zip" )
+ rwx = PERM_ALL;
+
+ TDEIO::UDSEntryListConstIterator it = entries.begin();
+ TDEIO::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
+ TQString name = kfi.text();
+ // ignore un-needed entries
+ if ( name.isEmpty() || name == "." || name == ".." ) continue;
+
+ TDEIO::filesize_t size = kfi.size();
+ time_t mtime = kfi.time( TDEIO::UDS_MODIFICATION_TIME );
+ bool symLink = kfi.isLink();
+ mode_t mode = kfi.mode() | kfi.permissions();
+ TQString perm = KRpermHandler::mode2TQString( mode );
+ // set the mimetype
+ TQString mime = kfi.mimetype();
+ TQString 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 {
+ TQString 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 TQString()
+ }
+ }
+#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( TDEIO::Job*, const KURL&, const KURL& newUrl ) {
+ vfs_origin = newUrl;
+ vfs_origin.adjustPath(-1);
+}
+
+void ftp_vfs::slotRedirection( TDEIO::Job *, const KURL &url ) {
+ // update the origin
+ vfs_origin = url;
+ vfs_origin.adjustPath(-1);
+}
+
+void ftp_vfs::slotListResult( TDEIO::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 ) {
+ TQString errorMsg = TQString();
+ 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);
+
+ //TQTimer::singleShot( 0,this,TQ_SLOT(startLister()) );
+ listError = false;
+ // Open the directory marked by origin
+ krConfig->setGroup( "Look&Feel" );
+ //vfs_origin.adjustPath(+1);
+ TDEIO::Job *job = TDEIO::listDir( vfs_origin, false, showHidden );
+ connect( job, TQ_SIGNAL( entries( TDEIO::Job*, const TDEIO::UDSEntryList& ) ),
+ this, TQ_SLOT( slotAddFiles( TDEIO::Job*, const TDEIO::UDSEntryList& ) ) );
+ connect( job, TQ_SIGNAL( redirection( TDEIO::Job*, const KURL& ) ),
+ this, TQ_SLOT( slotRedirection( TDEIO::Job*, const KURL& ) ) );
+ connect( job, TQ_SIGNAL( permanentRedirection( TDEIO::Job*, const KURL&, const KURL& ) ),
+ this, TQ_SLOT( slotPermanentRedirection( TDEIO::Job*, const KURL&, const KURL& ) ) );
+
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ),
+ this, TQ_SLOT( slotListResult( TDEIO::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, TDEIO::CopyJob::CopyMode mode, TQObject* toNotify, TQString 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 ( TQDir( destUrl.path( -1 ) ).exists() )
+ destUrl.setProtocol( "file" ); // if we get out from the archive change the protocol
+ }
+ }
+
+ TDEIO::Job* job = new TDEIO::CopyJob( *fileUrls, destUrl, mode, false, true );
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( vfs_refresh( TDEIO::Job* ) ) );
+ if ( mode == TDEIO::CopyJob::Move ) // notify the other panel
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), toNotify, TQ_SLOT( vfs_refresh( TDEIO::Job* ) ) );
+}
+
+// remove a file from the vfs (physical)
+void ftp_vfs::vfs_delFiles( TQStringList *fileNames ) {
+ KURL::List filesUrls;
+ KURL url;
+
+ // names -> urls
+ for ( uint i = 0 ; i < fileNames->count(); ++i ) {
+ TQString filename = ( *fileNames ) [ i ];
+ url = vfs_origin;
+ url.addPath( filename );
+ filesUrls.append( url );
+ }
+ TDEIO::Job *job = new TDEIO::DeleteJob( filesUrls, false, true );
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( vfs_refresh( TDEIO::Job* ) ) );
+}
+
+
+KURL::List* ftp_vfs::vfs_getFiles( TQStringList* names ) {
+ KURL url;
+ KURL::List* urls = new KURL::List();
+ for ( TQStringList::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 TQString& 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 TQString& name ) {
+ KURL url = vfs_origin;
+ url.addPath( name );
+
+ TDEIO::SimpleJob* job = TDEIO::mkdir( url );
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( vfs_refresh( TDEIO::Job* ) ) );
+}
+
+void ftp_vfs::vfs_rename( const TQString& fileName, const TQString& newName ) {
+ KURL::List fileUrls;
+ KURL oldUrl = vfs_origin;
+ oldUrl.addPath( fileName ) ;
+
+ fileUrls.append( oldUrl );
+
+ KURL newUrl = vfs_origin;
+ newUrl.addPath( newName );
+
+ TDEIO::Job *job = new TDEIO::CopyJob( fileUrls, newUrl, TDEIO::CopyJob::Move, true, true );
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( vfs_refresh( TDEIO::Job* ) ) );
+}
+
+TQString ftp_vfs::vfs_workingDir() {
+ return vfs_origin.url( -1 );
+}
+
+#include "ftp_vfs.moc"
diff --git a/src/app/VFS/ftp_vfs.h b/src/app/VFS/ftp_vfs.h
new file mode 100644
index 0000000..486efc9
--- /dev/null
+++ b/src/app/VFS/ftp_vfs.h
@@ -0,0 +1,80 @@
+/***************************************************************************
+ 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
+
+// TDE includes
+#include <kdirlister.h>
+// Krusader includes
+#include "vfs.h"
+
+class ftp_vfs : public vfs{
+ TQ_OBJECT
+
+public:
+ // the constructor simply uses the inherited constructor
+ ftp_vfs(TQObject* panel);
+ ~ftp_vfs();
+
+ /// Copy a file to the vfs (physical).
+ virtual void vfs_addFiles(KURL::List *fileUrls,TDEIO::CopyJob::CopyMode mode,TQObject* toNotify,TQString dir = "", PreserveMode pmode = PM_DEFAULT );
+ /// Remove a file from the vfs (physical)
+ virtual void vfs_delFiles(TQStringList *fileNames);
+ /// Return a list of URLs for multiple files
+ virtual KURL::List* vfs_getFiles(TQStringList* names);
+ /// Return a URL to a single file
+ virtual KURL vfs_getFile(const TQString& name);
+ /// Create a new directory
+ virtual void vfs_mkdir(const TQString& name);
+ /// Rename file
+ virtual void vfs_rename(const TQString& fileName,const TQString& newName);
+ /// Return the VFS working dir
+ TQString vfs_workingDir();
+
+public slots:
+ /// Handles new files from the dir lister
+ void slotAddFiles(TDEIO::Job * job, const TDEIO::UDSEntryList& entries);
+ /// Redirection signal handlers
+ void slotRedirection(TDEIO::Job *, const KURL &url);
+ void slotPermanentRedirection(TDEIO::Job*,const KURL&,const KURL& newUrl);
+ /// Called when the dir listing job is finished (for better or worst)
+ void slotListResult(TDEIO::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/src/app/VFS/krarchandler.cpp b/src/app/VFS/krarchandler.cpp
new file mode 100644
index 0000000..faba80b
--- /dev/null
+++ b/src/app/VFS/krarchandler.cpp
@@ -0,0 +1,785 @@
+/***************************************************************************
+ 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. *
+* *
+***************************************************************************/
+// TQt includes
+#include <tqtextstream.h>
+// TDE includes
+#include <kprocess.h>
+#include <tdetempfile.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <tdeio/passdlg.h>
+#include <tqfile.h>
+#include <kstandarddirs.h>
+#include <ktar.h>
+#include <tdeio/global.h>
+// Krusader includes
+#include "krarchandler.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include "../krservices.h"
+#include "../Dialogs/krpleasewait.h"
+
+static TQStringList arcProtocols = TQStringList::split(";", "tar;bzip;bzip2;gzip;krarc;zip;xz");
+
+TDEWallet::Wallet * KRarcHandler::wallet = 0;
+
+TQStringList KRarcHandler::supportedPackers() {
+ TQStringList 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" );
+ if ( KrServices::cmdExist( "xz" ) ) packers.append( "xz" );
+ // kdDebug() << "Supported Packers:" << endl;
+ //TQStringList::Iterator it;
+ //for( it = packers.begin(); it != packers.end(); ++it )
+ // kdDebug() << *it << endl;
+
+ return packers;
+ }
+
+bool KRarcHandler::arcSupported( TQString type ) {
+ // lst will contain the supported unpacker list...
+ krConfig->setGroup( "Archives" );
+ TQStringList 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 == "-txz" && 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;
+ else if ( type == "-xz" && lst.contains( "xz" ) )
+ return true;
+ // not supported : (
+ return false;
+ }
+
+bool KRarcHandler::arcHandled( TQString 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 == "-txz" && krConfig->readBoolEntry( "Do Xz" , _DoXz ) ) ||
+ ( 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 ) ) ||
+ ( type == "-xz" && krConfig->readBoolEntry( "Do Xz" , _DoXz ) ) )
+ return true;
+ else
+ return false;
+ }
+
+
+long KRarcHandler::arcFileCount( TQString archive, TQString type, TQString password ) {
+ int divideWith = 1;
+
+ // first check if supported
+ if ( !arcSupported( type ) ) return 0;
+
+ // bzip, gzip and xz archives contain only one file
+ if ( type == "zip2" || type == "gzip" || type == "-xz") return 1L;
+
+ // set the right lister to do the job
+ TQString 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 == "-txz" ) 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 if ( type == "-xz" ) lister = KrServices::fullPathName( "xz" ) + " -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"*/ TQString(), "krusader-unpack" ); // commented out as it created files in the current dir!
+ KrShellProcess list;
+ list << lister << KrServices::quote( archive ) << ">" << tmpFile.name() ;
+ if( type == "-ace" && TQFile( "/dev/ptmx" ).exists() ) // Don't remove, unace crashes if missing!!!
+ list<< "<" << "/dev/ptmx";
+ list.start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput );
+ while ( list.isRunning() ) {
+ usleep( 1000 );
+ tqApp->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;
+ }
+
+ TQTextStream *stream = tmpFile.textStream();
+ while ( stream && stream->readLine() != TQString() ) ++count;
+ tmpFile.unlink();
+
+ //make sure you call stopWait after this function return...
+ //krApp->stopWait();
+
+ return count / divideWith;
+ }
+
+bool KRarcHandler::unpack( TQString archive, TQString type, TQString password, TQString 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
+ TQString packer, cpioName = TQString();
+
+ // 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 == "-txz" ) 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 == "-xz" ) packer = KrServices::fullPathName( "xz" ) + " -cdk";
+ else if ( type == "-rpm" ) {
+ TQString tempDir = locateLocal("tmp",TQString());
+
+ cpioName = tempDir+"/contents.cpio";
+
+ KrShellProcess cpio;
+ cpio << KrServices::fullPathName( "rpm2cpio" ) << " " + KrServices::quote( archive ) << " > " << cpioName;
+ cpio.start(TDEProcess::Block, TDEProcess::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" ) {
+ TQString tempDir = locateLocal("tmp",TQString());
+
+ cpioName = tempDir+"/contents.tar";
+
+ KrShellProcess dpkg;
+ dpkg << KrServices::fullPathName( "dpkg" ) << " --fsys-tarfile " + KrServices::quote( archive ) << " > " << cpioName;
+ dpkg.start(TDEProcess::Block, TDEProcess::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" ){
+ TQString arcname = archive.mid(archive.findRev("/")+1);
+ if( arcname.contains(".") ) arcname = arcname.left(arcname.findRev("."));
+ proc << ">" << KrServices::quote( dest+"/"+arcname );
+ }
+ if( type == "-ace" && TQFile( "/dev/ptmx" ).exists() ) // Don't remove, unace crashes if missing!!!
+ proc << "<" << "/dev/ptmx";
+
+ TQString 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, TQ_SIGNAL( receivedStdout( TDEProcess*, char*, int ) ),
+ krApp, TQ_SLOT( incProgress( TDEProcess*, char*, int ) ) );
+ if( type == "-rpm" )
+ connect( &proc, TQ_SIGNAL( receivedStderr( TDEProcess*, char*, int ) ),
+ krApp, TQ_SLOT( incProgress( TDEProcess*, char*, int ) ) );
+ }
+
+ // start the unpacking process
+ proc.start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput );
+ while ( proc.isRunning() ) {
+ usleep( 1000 );
+ tqApp->processEvents();
+ if( krApp->wasWaitingCancelled() )
+ proc.kill();
+ }
+ ; // busy wait - need to find something better...
+ krApp->stopWait();
+ chdir( save.local8Bit() );
+
+ if( !cpioName.isEmpty() )
+ TQFile( 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( TQString archive, TQString type, TQString password, long count ) {
+ // choose the right packer for the job
+ TQString 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 == "-txz" ) 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 if ( type == "-xz" ) packer = KrServices::fullPathName( "xz" ) + " -tv";
+ 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" && TQFile( "/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, TQ_SIGNAL( receivedStdout( TDEProcess*, char*, int ) ),
+ krApp, TQ_SLOT( incProgress( TDEProcess*, char*, int ) ) );
+
+ // start the unpacking process
+ proc.start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput );
+ while ( proc.isRunning() ) {
+ usleep( 1000 );
+ tqApp->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( TQStringList fileNames, TQString type, TQString dest, long count, TQMap<TQString,TQString> extraProps ) {
+ // set the right packer to do the job
+ TQString 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 == "tar.xz" ) { packer = KrServices::fullPathName( "tar" ) + " -cvJf"; type = "-txz"; }
+ 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 if ( type == "xz" ) { packer = KrServices::fullPathName( "xz" ) + " -z"; type = "-xz"; }
+ else return false;
+
+ TQString password = TQString();
+
+ 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 = TQString();
+ }
+ }
+
+ if( extraProps.count( "VolumeSize" ) > 0 ) {
+ TQString sizeStr = extraProps[ "VolumeSize" ];
+ TDEIO::filesize_t size = sizeStr.toLongLong();
+
+ if( size >= 10000 ) {
+ if( type == "-arj" || type == "-rar" )
+ packer += TQString( " -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 += TQString( " -m%1" ).arg( rarLevels[ level ] );
+ }
+ else if( type == "-arj" ) {
+ static const int arjLevels[] = { 0, 4, 4, 3, 3, 2, 2, 1, 1 };
+ packer += TQString( " -m%1" ).arg( arjLevels[ level ] );
+ }
+ else if( type == "-zip" ) {
+ static const int zipLevels[] = { 0, 1, 2, 4, 5, 6, 7, 8, 9 };
+ packer += TQString( " -%1" ).arg( zipLevels[ level ] );
+ }
+ else if( type == "-7z" ) {
+ static const int sevenZipLevels[] = { 0, 1, 2, 4, 5, 6, 7, 8, 9 };
+ packer += TQString( " -mx%1" ).arg( sevenZipLevels[ level ] );
+ }
+ else if( type == "-xz" ) {
+ static const int xzLevels[] = { 0, 1, 2, 4, 5, 6, 7, 8, 9 };
+ packer += TQString( " -%1" ).arg( xzLevels[ level ] );
+ }
+ }
+
+ if( extraProps.count( "CommandLineSwitches" ) > 0 )
+ packer += TQString( " %1" ).arg( extraProps[ "CommandLineSwitches" ] );
+
+ // prepare to pack
+ KrShellProcess proc;
+ proc << packer << KrServices::quote( dest );
+
+ for ( TQStringList::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, TQ_SIGNAL( receivedStdout( TDEProcess*, char*, int ) ),
+ krApp, TQ_SLOT( incProgress( TDEProcess*, char*, int ) ) );
+
+ // start the packing process
+ proc.start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput );
+ while ( proc.isRunning() ) {
+ usleep( 1000 );
+ tqApp->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
+ }
+
+TQString KRarcHandler::getPassword( TQString path ) {
+ TQString password;
+
+ TQString key = "krarc-" + path;
+
+ if( !TDEWallet::Wallet::keyDoesNotExist(TDEWallet::Wallet::NetworkWallet(), TDEWallet::Wallet::PasswordFolder(), key ) ) {
+ if( !TDEWallet::Wallet::isOpen( TDEWallet::Wallet::NetworkWallet() ) && wallet != 0 ) {
+ delete wallet;
+ wallet = 0;
+ }
+ if( wallet == 0 )
+ wallet = TDEWallet::Wallet::openWallet( TDEWallet::Wallet::NetworkWallet() );
+ if ( wallet && wallet->hasFolder( TDEWallet::Wallet::PasswordFolder() ) ) {
+ wallet->setFolder( TDEWallet::Wallet::PasswordFolder() );
+ TQMap<TQString,TQString> map;
+ if ( wallet->readMap( key, map ) == 0 ) {
+ TQMap<TQString, TQString>::ConstIterator it = map.find( "password" );
+ if ( it != map.end() )
+ password = it.data();
+ }
+ }
+ }
+
+ bool keep = true;
+ TQString user = "archive";
+ TDEIO::PasswordDialog passDlg( i18n("This archive is encrypted, please supply the password:"),
+ user, true );
+ passDlg.setPassword( password );
+ if (passDlg.exec() == TDEIO::PasswordDialog::Accepted) {
+ password = passDlg.password();
+ if ( keep ) {
+ if( !TDEWallet::Wallet::isOpen( TDEWallet::Wallet::NetworkWallet() ) && wallet != 0 ) {
+ delete wallet;
+ wallet = 0;
+ }
+ if ( !wallet )
+ wallet = TDEWallet::Wallet::openWallet( TDEWallet::Wallet::NetworkWallet() );
+ if ( wallet ) {
+ bool ok = true;
+ if ( !wallet->hasFolder( TDEWallet::Wallet::PasswordFolder() ) )
+ ok = wallet->createFolder( TDEWallet::Wallet::PasswordFolder() );
+ if ( ok ) {
+ wallet->setFolder( TDEWallet::Wallet::PasswordFolder() );
+ TQMap<TQString,TQString> map;
+ map.insert( "login", "archive" );
+ map.insert( "password", password );
+ wallet->writeMap( key, map );
+ }
+ }
+ }
+ return password;
+ }
+
+ return "";
+}
+
+bool KRarcHandler::isArchive(const KURL& url) {
+ TQString protocol = url.protocol();
+ if (arcProtocols.find(protocol) != arcProtocols.end())
+ return true;
+ else return false;
+}
+
+TQString KRarcHandler::getType( bool &encrypted, TQString fileName, TQString mime, bool checkEncrypted ) {
+ TQString result = detectArchive( encrypted, fileName, checkEncrypted );
+ if( result.isNull() )
+ result = mime;
+ else
+ result = "-" + result;
+
+ if (result.endsWith("-7z"))
+ {
+ result = "-7z";
+ }
+ if (result.endsWith("-xz"))
+ {
+ result = "-xz";
+ }
+
+ return result.right( 4 );
+}
+
+
+bool KRarcHandler::checkStatus( TQString 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" || type == "-txz" || type == "-xz")
+ return exitCode == 0;
+ else if (type == "gzip" || type == "-xz")
+ return exitCode == 0 || exitCode == 2;
+ else
+ return exitCode == 0;
+}
+
+struct AutoDetectParams {
+ TQString type;
+ int location;
+ TQString detectionString;
+};
+
+TQString KRarcHandler::detectArchive( bool &encrypted, TQString 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" },
+ {"xz", 0, "\xfd" "7zXZ\x00" } };
+ static int autoDetectElems = sizeof( autoDetectParams ) / sizeof( AutoDetectParams );
+
+ encrypted = false;
+
+ TQFile 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++ ) {
+ TQString 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() ) {
+ TQString 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(TDEProcess::Block,TDEProcess::AllOutput);
+ encrypted = proc.isEncrypted();
+ }
+ }
+ else if( type == "xz" && (fileName.endsWith(".tar.xz") || fileName.endsWith(".txz")) )
+ type = "txz";
+ 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 TQString();
+}
+
+#include "krarchandler.moc"
+
diff --git a/src/app/VFS/krarchandler.h b/src/app/VFS/krarchandler.h
new file mode 100644
index 0000000..506162a
--- /dev/null
+++ b/src/app/VFS/krarchandler.h
@@ -0,0 +1,151 @@
+/***************************************************************************
+ 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 <tqstringlist.h>
+#include <tqobject.h>
+#include <kprocess.h>
+#include <kurl.h>
+#include <tdewallet.h>
+
+class KRarcHandler: public TQObject {
+ TQ_OBJECT
+
+public:
+ // return the number of files in the archive
+ static long arcFileCount(TQString archive, TQString type, TQString password);
+ // unpack an archive to destination directory
+ static bool unpack(TQString archive, TQString type, TQString password, TQString dest );
+ // pack an archive to destination directory
+ static bool pack(TQStringList fileNames, TQString type, TQString dest, long count, TQMap<TQString,TQString> extraProps );
+ // test an archive
+ static bool test(TQString archive, TQString type, TQString password, long count = 0L );
+ // true - if the right unpacker exist in the system
+ static bool arcSupported(TQString type);
+ // true - if supported and the user want us to handle this kind of archive
+ static bool arcHandled(TQString type);
+ // return the a list of supported packers
+ static TQStringList 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 TQString getType( bool &encrypted, TQString fileName, TQString mime, bool checkEncrypted = true );
+ // queries the password from the user
+ static TQString getPassword( TQString path );
+ // detects the archive type
+ static TQString detectArchive( bool &encrypted, TQString fileName, bool checkEncrypted = true );
+private:
+ // checks if the returned status is correct
+ static bool checkStatus( TQString type, int exitCode );
+
+ static TDEWallet::Wallet * wallet;
+};
+
+class KrShellProcess : public KShellProcess {
+ TQ_OBJECT
+
+public:
+ KrShellProcess() : KShellProcess(), errorMsg( TQString() ), outputMsg( TQString() ) {
+ connect(this,TQ_SIGNAL(receivedStderr(TDEProcess*,char*,int)),
+ this,TQ_SLOT(receivedErrorMsg(TDEProcess*,char*,int)) );
+ connect(this,TQ_SIGNAL(receivedStdout(TDEProcess*,char*,int)),
+ this,TQ_SLOT(receivedOutputMsg(TDEProcess*,char*,int)) );
+ }
+
+ TQString getErrorMsg() {
+ if( errorMsg.stripWhiteSpace().isEmpty() )
+ return outputMsg.right( 500 );
+ else
+ return errorMsg.right( 500 );
+ }
+
+public slots:
+ void receivedErrorMsg(TDEProcess*, char *buf, int len) {
+ errorMsg += TQString::fromLocal8Bit( buf, len );
+ if( errorMsg.length() > 500 )
+ errorMsg = errorMsg.right( 500 );
+ receivedOutputMsg( 0, buf, len );
+ }
+
+ void receivedOutputMsg(TDEProcess*, char *buf, int len) {
+ outputMsg += TQString::fromLocal8Bit( buf, len );
+ if( outputMsg.length() > 500 )
+ outputMsg = outputMsg.right( 500 );
+ }
+
+private:
+ TQString errorMsg;
+ TQString outputMsg;
+};
+
+class Kr7zEncryptionChecker : public KrShellProcess {
+ TQ_OBJECT
+
+
+public:
+ Kr7zEncryptionChecker() : KrShellProcess(), encrypted( false ), lastData() {
+ connect(this,TQ_SIGNAL(receivedStdout(TDEProcess*,char*,int)),
+ this,TQ_SLOT(processStdout(TDEProcess*,char*,int)) );
+ }
+
+public slots:
+ void processStdout( TDEProcess *proc,char *buf,int len ) {
+ TQByteArray d(len);
+ d.setRawData(buf,len);
+ TQString data = TQString( d );
+ d.resetRawData(buf,len);
+
+ TQString checkable = lastData + data;
+
+ TQStringList lines = TQStringList::split( '\n', checkable );
+ lastData = lines[ lines.count() - 1 ];
+ for( unsigned i=0; i != lines.count(); i++ ) {
+ TQString 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;
+ TQString lastData;
+};
+
+#endif
diff --git a/src/app/VFS/krdirwatch.cpp b/src/app/VFS/krdirwatch.cpp
new file mode 100644
index 0000000..fe4e2de
--- /dev/null
+++ b/src/app/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 "tqstringlist.h"
+#include <tqdir.h>
+
+KRdirWatch::KRdirWatch(int msec,bool dirOnly):
+ delay(msec),t(this), changed(false) {
+ if(dirOnly) dir.setFilter( TQDir::Dirs | TQDir::Hidden | TQDir::NoSymLinks );
+ watched.setAutoDelete(true);
+ connect(&t,TQ_SIGNAL(timeout()),this, TQ_SLOT(checkDirs()));
+ startScan();
+}
+
+KRdirWatch::~KRdirWatch(){
+ clearList();
+ stopScan();
+}
+
+void KRdirWatch::removeDir(TQString 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(TQString 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(TQDir::All | TQDir::AccessMask).count();
+ temp->lastModified = qfi.lastModified();
+
+ watched.append(temp);
+ if (!stopped) startScan();
+}
+
+// here we do the actual checking
+void KRdirWatch::checkDirs(){
+ t.stop();
+
+ TQString path;
+ unsigned long count;
+ TQDateTime 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(TQDir::All | TQDir::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/src/app/VFS/krdirwatch.h b/src/app/VFS/krdirwatch.h
new file mode 100644
index 0000000..e99618b
--- /dev/null
+++ b/src/app/VFS/krdirwatch.h
@@ -0,0 +1,80 @@
+/***************************************************************************
+ 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 <tqobject.h>
+#include <tqstring.h>
+#include <tqptrlist.h>
+#include <tqtimer.h>
+#include <tqdatetime.h>
+#include <tqdir.h>
+
+
+typedef struct krDirEntry_s{
+ TQString path;
+ unsigned long count; // number of files
+ TQDateTime lastModified;
+} krDirEntry ;
+
+class KRdirWatch : public TQObject {
+ TQ_OBJECT
+
+public:
+ KRdirWatch(int msec = 250 , bool dirOnly = false );
+ ~KRdirWatch();
+ void addDir(TQString path,bool checkPermissions = true );
+ void removeDir(TQString 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
+ TQPtrList<krDirEntry> watched;
+ TQTimer t;
+ TQDir dir;
+ TQFileInfo 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/src/app/VFS/krpermhandler.cpp b/src/app/VFS/krpermhandler.cpp
new file mode 100644
index 0000000..aa955aa
--- /dev/null
+++ b/src/app/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 <tdelocale.h>
+#include <tdeglobal.h>
+#include <klargefile.h>
+// TQt includes
+#include <tqdatetime.h>
+#include <tqdir.h>
+// krusader includes
+#include <tdeversion.h>
+#include "krpermhandler.h"
+#include "../resources.h"
+
+TQDict<uid_t> *KRpermHandler::passwdCache = 0L;
+TQDict<gid_t> *KRpermHandler::groupCache = 0L;
+TQIntDict<char> *KRpermHandler::currentGroups = 0L;
+TQIntDict<TQString> *KRpermHandler::uidCache = 0L;
+TQIntDict<TQString> *KRpermHandler::gidCache = 0L;
+
+char KRpermHandler::writeable( TQString 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( TQString 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( TQString 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( TQString localFile ) {
+ KDE_struct_stat stat_p;
+ if ( KDE_stat( localFile.local8Bit(), &stat_p ) == -1 ) return false;
+ mode_t m = stat_p.st_mode;
+ TQString perm = mode2TQString( m );
+ return writeable( perm, stat_p.st_gid, stat_p.st_uid );
+}
+
+bool KRpermHandler::fileReadable( TQString localFile ) {
+ KDE_struct_stat stat_p;
+ if ( KDE_stat( localFile.local8Bit(), &stat_p ) == -1 ) return false;
+ mode_t m = stat_p.st_mode;
+ TQString perm = mode2TQString( m );
+ return readable( perm, stat_p.st_gid, stat_p.st_uid );
+}
+
+bool KRpermHandler::fileExecutable( TQString localFile ) {
+ KDE_struct_stat stat_p;
+ if ( KDE_stat( localFile.local8Bit(), &stat_p ) == -1 ) return false;
+ mode_t m = stat_p.st_mode;
+ TQString perm = mode2TQString( m );
+ return executable( perm, stat_p.st_gid, stat_p.st_uid );
+}
+
+TQString KRpermHandler::mode2TQString( 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 TQString( 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 TQDict<uid_t>( 317 );
+ groupCache = new TQDict<gid_t>( 317 );
+ currentGroups = new TQIntDict<char>( 317 );
+ uidCache = new TQIntDict<TQString>( 317 );
+ gidCache = new TQIntDict<TQString>( 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 TQString( 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 TQString( 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 ( TQString fileOwner, TQString userName, TQString 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 ( TQString fileOwner, TQString userName, TQString 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( TQString fileOwner, TQString userName, TQString 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( TQString path ) {
+ DIR * dir = opendir( path.local8Bit() );
+ if ( !dir ) return false;
+ closedir( dir ); // bug fix Karai Csaba (ckarai)
+ return true;
+}
+
+bool KRpermHandler::fileExist( TQString 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( TQString path, TQString name ) {
+ if ( TQDir( 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;
+}
+
+TQString KRpermHandler::parseSize( TDEIO::filesize_t val ) {
+#if (TDE_VERSION_MAJOR >= 3) && (TDE_VERSION_MINOR >= 5)
+ return TDEGlobal::locale()->formatNumber(TQString::number(val), false, 0);
+#else
+ return TDEGlobal::locale()->formatNumber(val);
+#endif
+
+#if 0
+ TQString temp;
+ temp.sprintf( "%llu", val );
+ if ( temp.length() <= 3 ) return temp;
+ unsigned int i = temp.length() % 3;
+ if ( i == 0 ) i = 3;
+ TQString 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
+}
+
+TQString KRpermHandler::date2qstring( TQString date ) {
+ TQString 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::TQString2time( TQString date ) {
+ struct tm t;
+ t.tm_sec = 0;
+ t.tm_min = ( TQString( date[ 12 ] ) + TQString( date[ 13 ] ) ).toInt();
+ t.tm_hour = ( TQString( date[ 9 ] ) + TQString( date[ 10 ] ) ).toInt();
+ t.tm_mday = ( TQString( date[ 0 ] ) + TQString( date[ 1 ] ) ).toInt();
+ t.tm_mon = ( TQString( date[ 3 ] ) + TQString( date[ 4 ] ) ).toInt() - 1;
+ t.tm_year = ( TQString( date[ 6 ] ) + TQString( 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( TQString group ) {
+ gid_t * gid = groupCache->find( group );
+ if ( gid ) return * gid;
+ return getgid();
+}
+uid_t KRpermHandler::user2uid ( TQString user ) {
+ uid_t * uid = passwdCache->find( user );
+ if ( uid ) return * uid;
+ return getuid();
+}
+
+TQString KRpermHandler::gid2group( gid_t groupId ) {
+ TQString * group = gidCache->find( groupId );
+ if ( group ) return * group;
+ return TQString( "???" );
+}
+
+TQString KRpermHandler::uid2user ( uid_t userId ) {
+ TQString * user = uidCache->find( userId );
+ if ( user ) return * user;
+ return TQString( "???" );
+}
+
diff --git a/src/app/VFS/krpermhandler.h b/src/app/VFS/krpermhandler.h
new file mode 100644
index 0000000..02a2928
--- /dev/null
+++ b/src/app/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 <tqstring.h>
+#include <tqfileinfo.h>
+#include <sys/types.h>
+#include <tqdict.h>
+#include <tqintdict.h>
+#include <tdeio/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(TQString group);
+ static uid_t user2uid (TQString user);
+
+ static TQString gid2group(gid_t groupId);
+ static TQString uid2user (uid_t userId);
+
+ static char writeable (TQString perm, gid_t gid, uid_t uid, int rwx=-1);
+ static char readable (TQString perm, gid_t gid, uid_t uid, int rwx=-1);
+ static char executable(TQString perm, gid_t gid, uid_t uid, int rwx=-1);
+
+ static bool fileWriteable (TQString localFile);
+ static bool fileReadable (TQString localFile);
+ static bool fileExecutable(TQString localFile);
+
+ static char ftpWriteable ( TQString fileOwner, TQString userName, TQString perm );
+ static char ftpReadable ( TQString fileOwner, TQString userName, TQString perm );
+ static char ftpExecutable( TQString fileOwner, TQString userName, TQString perm );
+
+ static bool dirExist (TQString path);
+ static bool fileExist(TQString fullPath);
+ static bool fileExist(TQString Path, TQString name);
+
+ static TQString mode2TQString(mode_t m);
+ static TQString parseSize(TDEIO::filesize_t val);
+ static TQString date2qstring(TQString date);
+ static time_t TQString2time(TQString date);
+
+private:
+ // cache for passwd and group entries
+ static TQDict<uid_t> *passwdCache;
+ static TQDict<gid_t> *groupCache;
+ static TQIntDict<char> *currentGroups;
+ static TQIntDict<TQString> *uidCache;
+ static TQIntDict<TQString> *gidCache;
+};
+
+#endif
diff --git a/src/app/VFS/krquery.cpp b/src/app/VFS/krquery.cpp
new file mode 100644
index 0000000..7ceeca9
--- /dev/null
+++ b/src/app/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 <tqtextstream.h>
+#include <tqtextcodec.h>
+#include <tqregexp.h>
+#include <klargefile.h>
+#include <tdelocale.h>
+#include <kmimetype.h>
+#include <tqfile.h>
+#include <kurlcompletion.h>
+#include <tdeio/job.h>
+#include <tdefileitem.h>
+
+#define STATUS_SEND_DELAY 250
+#define MAX_LINE_LEN 500
+
+// set the defaults
+KRQuery::KRQuery(): TQObject(), matchesCaseSensitive(true), bNull( true ),
+ contain(TQString()),containCaseSensetive(true),
+ containWholeWord(false),containOnRemote(false),
+ minSize(0),maxSize(0),newerThen(0),olderThen(0),
+ owner(TQString()),group(TQString()),perm(TQString()),
+ type(TQString()),inArchive(false),recurse(true),
+ followLinksP(true), receivedBuffer( 0 ), processEventsConnected(0) {}
+
+// set the defaults
+KRQuery::KRQuery( const TQString &name, bool matchCase ) : TQObject(),
+ bNull( true ),contain(TQString()),containCaseSensetive(true),
+ containWholeWord(false), containOnRemote(false),
+ minSize(0),maxSize(0),newerThen(0),olderThen(0),
+ owner(TQString()),group(TQString()),perm(TQString()),
+ type(TQString()),inArchive(false),recurse(true),
+ followLinksP(true), receivedBuffer( 0 ), processEventsConnected(0) {
+ setNameFilter( name, matchCase );
+}
+
+KRQuery::KRQuery( const KRQuery & that ) : TQObject(), 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 ) {
+ TQString signalString = TQString( signal ).replace( " ", "" );
+ TQString processString = TQString( TQ_SIGNAL( processEvents( bool & ) ) ).replace( " ", "" );
+ if( signalString == processString )
+ processEventsConnected++;
+}
+
+void KRQuery::disconnectNotify ( const char * signal ) {
+ TQString signalString = TQString( signal ).replace( " ", "" );
+ TQString processString = TQString( TQ_SIGNAL( processEvents( bool & ) ) ).replace( " ", "" );
+ if( signalString == processString )
+ processEventsConnected--;
+}
+
+bool KRQuery::checkPerm( TQString filePerm ) const
+{
+ for ( int i = 0; i < 9; ++i )
+ if ( perm[ i ] != '?' && perm[ i ] != filePerm[ i + 1 ] ) return false;
+ return true;
+}
+
+bool KRQuery::checkType( TQString 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 TQString & name ) const {
+ return matchCommon( name, matches, excludes );
+}
+
+bool KRQuery::matchDirName( const TQString & name ) const {
+ return matchCommon( name, includedDirs, excludedDirs );
+}
+
+bool KRQuery::matchCommon( const TQString &nameIn, const TQStringList &matchList, const TQStringList &excludeList ) const
+{
+ if( excludeList.count() == 0 && matchList.count() == 0 ) /* true if there's no match condition */
+ return true;
+
+ TQString 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 )
+ {
+ TQRegExp( *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 )
+ {
+ TQRegExp( *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
+ TDEIO::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();
+ TQString perm = KRpermHandler::mode2TQString( mode );
+ if ( kfi->isDir() )
+ perm[ 0 ] = 'd';
+
+ vfile temp( kfi->text(), kfi->size(), perm, kfi->time( TDEIO::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(TQString& haystack, int start, int length) {
+ TQString before = haystack.left( start );
+ TQString text = haystack.mid( start, length );
+ TQString 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
+{
+ TQStringList list;
+
+ int start = 0;
+ int k = 0;
+ while( k < len )
+ {
+ if( buf[ k ] == 0 || buf[ k ] == '\n' )
+ {
+ if( k != start )
+ {
+ TQString line = TQTextCodec::codecForLocale()->toUnicode( buf + start, k - start );
+ if( !line.isEmpty() )
+ list << line;
+ }
+ start = k + 1;
+ }
+ k++;
+ }
+ if( start != k )
+ {
+ TQString line = TQTextCodec::codecForLocale()->toUnicode( buf + start, k - start );
+ if( !line.isEmpty() )
+ list << line;
+ }
+
+ for( unsigned int i=0; i != list.count(); i++ ) {
+ TQString line = list[ i ];
+
+ int ndx = 0;
+ if ( line.isNull() ) return false;
+ if ( containWholeWord )
+ {
+ while ( ( ndx = line.find( contain, ndx, containCaseSensetive ) ) != -1 )
+ {
+ TQChar before = line.at( ndx - 1 );
+ TQChar 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( TQString file ) const
+{
+ TQFile 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 = TQString(); // nothing was found
+ return false;
+}
+
+bool KRQuery::containsContent( KURL url ) const
+{
+ TDEIO::TransferJob *contentReader = TDEIO::get( url, false, false );
+ connect(contentReader, TQ_SIGNAL(data(TDEIO::Job *, const TQByteArray &)),
+ this, TQ_SLOT(containsContentData(TDEIO::Job *, const TQByteArray &)));
+ connect(contentReader, TQ_SIGNAL( result( TDEIO::Job* ) ),
+ this, TQ_SLOT(containsContentFinished( TDEIO::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(TDEIO::Job *job, const TQByteArray &array) {
+ receivedBytes += array.size();
+ if( checkBuffer( array.data(), array.size() ) ) {
+ containsContentResult = true;
+ containsContentFinished( job );
+ job->kill();
+ return;
+ }
+ checkTimer();
+}
+
+void KRQuery::containsContentFinished( TDEIO::Job * ) {
+ busy = false;
+}
+
+bool KRQuery::checkTimer() const {
+ if( timer.elapsed() >= STATUS_SEND_DELAY ) {
+ int pcnt = (int)(100.*(double)receivedBytes/(double)totalBytes + .5);
+ TQString message = i18n( "Searching content of '%1' (%2%)" )
+ .arg( fileName ).arg( pcnt );
+ timer.start();
+ emit ((KRQuery *)this)->status( message );
+ return true;
+ }
+ return false;
+}
+
+TQStringList KRQuery::split( TQString str )
+{
+ TQStringList list;
+ unsigned splitNdx = 0;
+ unsigned startNdx = 0;
+ bool quotation = false;
+
+ while( splitNdx < str.length() )
+ {
+ if( str[ splitNdx ] == '"' )
+ quotation = !quotation;
+
+ if( !quotation && str[ splitNdx ] == ' ')
+ {
+ TQString 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 )
+ {
+ TQString 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 TQString &text, bool cs )
+{
+ bNull = false;
+ matchesCaseSensitive = cs;
+ origFilter = text;
+
+ TQString matchText = text;
+ TQString 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 TQString &content, bool cs, bool wholeWord, bool remoteSearch )
+{
+ bNull = false;
+ contain = content;
+ containCaseSensetive = cs;
+ containWholeWord = wholeWord;
+ containOnRemote = remoteSearch;
+}
+
+void KRQuery::setMinimumFileSize( TDEIO::filesize_t minimumSize )
+{
+ bNull = false;
+ minSize = minimumSize;
+}
+
+void KRQuery::setMaximumFileSize( TDEIO::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 TQString &ownerIn )
+{
+ bNull = false;
+ owner = ownerIn;
+}
+
+void KRQuery::setGroup( const TQString &groupIn )
+{
+ bNull = false;
+ group = groupIn;
+}
+
+void KRQuery::setPermissions( const TQString &permIn )
+{
+ bNull = false;
+ perm = permIn;
+}
+
+void KRQuery::setMimeType( const TQString &typeIn, TQStringList 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 ) {
+ TQString 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 ) {
+ TQString url = urls[ i ].url();
+ KURL completed = vfs::fromPathOrURL( KURLCompletion::replacedPath( url, true, true ) );
+ whereNotToSearch.append( completed );
+ }
+}
+
+#include "krquery.moc"
diff --git a/src/app/VFS/krquery.h b/src/app/VFS/krquery.h
new file mode 100644
index 0000000..6481782
--- /dev/null
+++ b/src/app/VFS/krquery.h
@@ -0,0 +1,209 @@
+/***************************************************************************
+ 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 <tqstringlist.h>
+#include <tqdatetime.h>
+#include <time.h>
+#include <kurl.h>
+#include <tdeio/jobclasses.h>
+#include "vfile.h"
+
+class KFileItem;
+
+class KRQuery : public TQObject {
+ TQ_OBJECT
+
+
+public:
+ // null query
+ KRQuery();
+ // query only with name filter
+ KRQuery( const TQString &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 TDEIO 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 TQString &name ) const;// matching the filename only
+ // matching the name of the directory
+ bool matchDirName( const TQString &name ) const;
+
+ // sets the text for name filtering
+ void setNameFilter( const TQString &text, bool cs=true );
+ // returns the current filter mask
+ const TQString& 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 TQString &content, bool cs=true, bool wholeWord=false, bool remoteSearch=false );
+
+ // sets the minimum file size limit
+ void setMinimumFileSize( TDEIO::filesize_t );
+ // sets the maximum file size limit
+ void setMaximumFileSize( TDEIO::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 TQString &ownerIn );
+ // sets the group
+ void setGroup( const TQString &groupIn );
+ // sets the permissions
+ void setPermissions( const TQString &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 TQStringList customType
+ void setMimeType( const TQString &typeIn, TQStringList customList = TQStringList() );
+ // 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 TQString& 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:
+ TQStringList matches; // what to search
+ TQStringList excludes; // what to exclude
+ TQStringList includedDirs; // what dirs to include
+ TQStringList excludedDirs; // what dirs to exclude
+ bool matchesCaseSensitive;
+
+ bool bNull; // flag if the query is null
+
+ TQString contain; // file must contain this string
+ bool containCaseSensetive;
+ bool containWholeWord;
+ bool containOnRemote;
+
+ TDEIO::filesize_t minSize;
+ TDEIO::filesize_t maxSize;
+
+ time_t newerThen;
+ time_t olderThen;
+
+ TQString owner;
+ TQString group;
+ TQString perm;
+
+ TQString type;
+ TQStringList 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 TQString &name );
+ void processEvents( bool & stopped );
+
+private:
+ bool matchCommon( const TQString &, const TQStringList &, const TQStringList & ) const;
+ bool checkPerm(TQString perm) const;
+ bool checkType(TQString mime) const;
+ bool containsContent( TQString 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;
+ TQStringList split( TQString );
+
+private slots:
+ void containsContentData(TDEIO::Job *, const TQByteArray &);
+ void containsContentFinished(TDEIO::Job*);
+
+private:
+ TQString origFilter;
+ mutable bool busy;
+ mutable bool containsContentResult;
+ mutable char * receivedBuffer;
+ mutable int receivedBufferLen;
+ mutable TQString lastSuccessfulGrep;
+ mutable TQString fileName;
+ mutable TDEIO::filesize_t receivedBytes;
+ mutable TDEIO::filesize_t totalBytes;
+ mutable int processEventsConnected;
+ mutable TQTime timer;
+};
+
+#endif
diff --git a/src/app/VFS/krvfshandler.cpp b/src/app/VFS/krvfshandler.cpp
new file mode 100644
index 0000000..553c55d
--- /dev/null
+++ b/src/app/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 <tqdir.h>
+
+#include <kdebug.h>
+
+
+KrVfsHandler::KrVfsHandler(){
+}
+KrVfsHandler::~KrVfsHandler(){
+}
+
+vfs::VFS_TYPE KrVfsHandler::getVfsType(const KURL& url){
+ TQString protocol = url.protocol();
+
+ if( ( protocol == "krarc" || protocol == "tar" || protocol == "zip" ) &&
+ TQDir(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,TQObject* 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/src/app/VFS/krvfshandler.h b/src/app/VFS/krvfshandler.h
new file mode 100644
index 0000000..b061b53
--- /dev/null
+++ b/src/app/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 <tqobject.h>
+
+#include <kurl.h>
+
+#include "vfs.h"
+
+/**
+ *@author Shie Erlich & Rafi Yanai
+ */
+
+class KrVfsHandler : public TQObject {
+public:
+ KrVfsHandler();
+ ~KrVfsHandler();
+
+ static vfs::VFS_TYPE getVfsType(const KURL& url);
+ static vfs* getVfs(const KURL& url,TQObject* parent=0,vfs* oldVfs=0);
+};
+
+#endif
diff --git a/src/app/VFS/normal_vfs.cpp b/src/app/VFS/normal_vfs.cpp
new file mode 100644
index 0000000..f81ab9a
--- /dev/null
+++ b/src/app/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>
+// TQt includes
+#include <tqdir.h>
+#include <tqtimer.h>
+// TDE includes
+#include <tdemessagebox.h>
+#include <kmimetype.h>
+#include <tdeio/jobclasses.h>
+#include <tdelocale.h>
+#include <tdeglobalsettings.h>
+#include <kdebug.h>
+#include <klargefile.h>
+#include <tdefileitem.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(TQObject* panel):vfs(panel), watcher(0) {
+ vfs_type=NORMAL;
+}
+
+bool normal_vfs::populateVfsList(const KURL& origin, bool showHidden){
+ TQString path = origin.path(-1);
+
+ // set the writable attribute to true, if that's not the case - the TDEIO 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 ( !TQDir(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
+ TQString 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;
+ TQString name;
+
+ while( (dirEnt=readdir(dir)) != NULL ){
+ name = TQString::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,TQ_SIGNAL(dirty(const TQString&)),this,TQ_SLOT(vfs_slotDirty(const TQString&)));
+ connect(watcher,TQ_SIGNAL(created(const TQString&)),this, TQ_SLOT(vfs_slotCreated(const TQString&)));
+ connect(watcher,TQ_SIGNAL(deleted(const TQString&)),this, TQ_SLOT(vfs_slotDeleted(const TQString&)));
+ 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,TDEIO::CopyJob::CopyMode mode,TQObject* toNotify,TQString 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);
+
+ TDEIO::Job* job = PreservingCopyJob::createCopyJob( pmode, *fileUrls,dest,mode,false,true );
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(vfs_refresh()) );
+ if(mode == TDEIO::CopyJob::Move) // notify the other panel
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),toNotify,TQ_SLOT(vfs_refresh(TDEIO::Job*)) );
+ else
+ job->setAutoErrorHandlingEnabled( true );
+}
+
+// remove a file from the vfs (physical)
+void normal_vfs::vfs_delFiles(TQStringList *fileNames){
+ KURL::List filesUrls;
+ KURL url;
+ TQDir 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){
+ TQString filename = (*fileNames)[i];
+ vf = vfs_search(filename);
+ url.setPath( vfs_workingDir()+"/"+filename);
+ filesUrls.append(url);
+ }
+ TDEIO::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 = TDEIO::trash(filesUrls, true );
+#else
+ job = new TDEIO::CopyJob(filesUrls,TDEGlobalSettings::trashPath(),TDEIO::CopyJob::Move,false,true );
+#endif
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),SLOTS,TQ_SLOT(changeTrashIcon()));
+ }
+ else
+ job = new TDEIO::DeleteJob(filesUrls, false, true);
+
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(vfs_refresh(TDEIO::Job*)));
+}
+
+// return a path to the file
+KURL normal_vfs::vfs_getFile(const TQString& name){
+ TQString url;
+ if ( vfs_workingDir() == "/" ) url = "/"+name;
+ else url = vfs_workingDir()+"/"+name;
+
+ return vfs::fromPathOrURL(url);
+}
+
+KURL::List* normal_vfs::vfs_getFiles(TQStringList* names){
+ KURL::List* urls = new KURL::List();
+ for(TQStringList::Iterator name = names->begin(); name != names->end(); ++name){
+ urls->append( vfs_getFile(*name) );
+ }
+ return urls;
+}
+
+void normal_vfs::vfs_mkdir(const TQString& name){
+ if (!TQDir(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 TQString& fileName,const TQString& 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);
+
+ TDEIO::Job *job = new TDEIO::CopyJob(fileUrls,dest,TDEIO::CopyJob::Move,true,false );
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(vfs_refresh(TDEIO::Job*)));
+}
+
+vfile* normal_vfs::vfileFromName(const TQString& name){
+ TQString path = vfs_workingDir()+"/"+name;
+ TQCString fileName = path.local8Bit();
+
+ KDE_struct_stat stat_p;
+ KDE_lstat(fileName.data(),&stat_p);
+ TDEIO::filesize_t size = stat_p.st_size;
+ TQString perm = KRpermHandler::mode2TQString(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);
+ TQString mime=TQString();
+
+ 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 ( TQDir(TQString::fromLocal8Bit( symDest ) ).exists() ) perm[0] = 'd';
+ if ( !TQDir(vfs_workingDir()).exists( TQString::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,TQString::fromLocal8Bit( symDest ),stat_p.st_mode, rwx);
+ temp->vfile_setUrl( mimeUrl );
+ return temp;
+}
+
+void normal_vfs::getACL( vfile *file, TQString &acl, TQString &defAcl )
+{
+ acl = defAcl = TQString();
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+ TQCString 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
+}
+
+TQString normal_vfs::getACL( const TQString & 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.ascii(), 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 TQString();
+
+ char *aclString = acl_to_text( acl, 0 );
+ TQString ret = TQString::fromLatin1( aclString );
+ acl_free( (void*)aclString );
+ acl_free( acl );
+
+ return ret;
+#else
+ return TQString();
+#endif
+}
+
+void normal_vfs::vfs_slotRefresh()
+{
+ krConfig->setGroup("Advanced");
+ int maxRefreshFrequency = krConfig->readNumEntry("Max Refresh Frequency", 1000);
+ vfs_refresh();
+ disconnect( &refreshTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( vfs_slotRefresh() ) );
+ refreshTimer.start( maxRefreshFrequency, true );
+}
+
+bool normal_vfs::burstRefresh(const TQString& path ){
+ if( path == vfs_getOrigin().path(-1) ) {
+ if( !refreshTimer.isActive() ) {
+ // the directory itself is dirty - full refresh is needed
+ TQTimer::singleShot(0, this, TQ_SLOT( vfs_slotRefresh() ) ); // safety: dirty signal comes from KDirWatch!
+ return true;
+ }
+ disconnect( &refreshTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( vfs_slotRefresh() ) );
+ connect( &refreshTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( vfs_slotRefresh() ) );
+ postponedRefreshURL = fromPathOrURL(path);
+ return true;
+ }
+ return false;
+}
+
+void normal_vfs::vfs_slotDirty(const TQString& path){
+ if( disableRefresh ){
+ postponedRefreshURL = fromPathOrURL(path);
+ return;
+ }
+
+ if( burstRefresh( path ) )
+ return;
+
+ KURL url = fromPathOrURL(path);
+ TQString 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 TQString& path){
+ if( disableRefresh ){
+ postponedRefreshURL = fromPathOrURL(path);
+ return;
+ }
+
+ if( burstRefresh( path ) )
+ return;
+
+
+ KURL url = fromPathOrURL(path);
+ TQString 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 TQString& path){
+ if( disableRefresh ){
+ postponedRefreshURL = fromPathOrURL(path);
+ return;
+ }
+
+ if( burstRefresh( path ) )
+ return;
+
+
+ KURL url = fromPathOrURL(path);
+ TQString 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/src/app/VFS/normal_vfs.h b/src/app/VFS/normal_vfs.h
new file mode 100644
index 0000000..0df0ea6
--- /dev/null
+++ b/src/app/VFS/normal_vfs.h
@@ -0,0 +1,93 @@
+/***************************************************************************
+ 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
+
+// TQt includes
+#include <tqstring.h>
+// TDE includes
+#include <tdefileitem.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{
+ TQ_OBJECT
+
+public:
+ // the constructor simply uses the inherited constructor
+ normal_vfs(TQObject* panel);
+ ~normal_vfs(){if( watcher ) delete watcher;}
+
+ /// Copy a file to the vfs (physical).
+ virtual void vfs_addFiles(KURL::List *fileUrls,TDEIO::CopyJob::CopyMode mode,TQObject* toNotify,TQString dir = "", PreserveMode pmode = PM_DEFAULT );
+ /// Remove a file from the vfs (physical)
+ virtual void vfs_delFiles(TQStringList *fileNames);
+ /// Return a list of URLs for multiple files
+ virtual KURL::List* vfs_getFiles(TQStringList* names);
+ /// Return a URL to a single file
+ virtual KURL vfs_getFile(const TQString& name);
+ /// Create a new directory
+ virtual void vfs_mkdir(const TQString& name);
+ /// Rename file
+ virtual void vfs_rename(const TQString& fileName,const TQString& newName);
+
+ /// return the VFS working dir
+ virtual TQString vfs_workingDir() { return vfs_origin.path(-1); }
+
+ /// Get ACL permissions
+ static void getACL( vfile *file, TQString &acl, TQString &defAcl );
+
+public slots:
+ void vfs_slotRefresh();
+ void vfs_slotDirty(const TQString& path);
+ void vfs_slotCreated(const TQString& path);
+ void vfs_slotDeleted(const TQString& path);
+
+protected:
+ /// Re-reads files and stats and fills the vfile list
+ virtual bool populateVfsList(const KURL& origin, bool showHidden);
+
+ TQTimer refreshTimer; //< Timer to exclude sudden refreshes
+ KDirWatch *watcher; //< The internal dir watcher - use to detect changes in directories
+ vfile* vfileFromName(const TQString& name);
+
+private:
+ bool burstRefresh( const TQString &path );
+ static TQString getACL( const TQString & path, int type );
+};
+
+#endif
diff --git a/src/app/VFS/preservingcopyjob.cpp b/src/app/VFS/preservingcopyjob.cpp
new file mode 100644
index 0000000..04c3195
--- /dev/null
+++ b/src/app/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 <tdeio/job.h>
+#include <tdeio/jobclasses.h>
+#include <tdefileitem.h>
+#include <tqfile.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 = TQString();
+}
+
+Attributes::Attributes( time_t tIn, uid_t uIn, gid_t gIn, mode_t modeIn, const TQString & aclIn )
+{
+ time = tIn, uid = uIn, gid = gIn, mode = modeIn, acl = aclIn;
+}
+
+Attributes::Attributes( time_t tIn, TQString user, TQString group, mode_t modeIn, const TQString & aclIn )
+{
+ time = tIn;
+ uid = (uid_t)-1;
+ struct passwd* pw = getpwnam(TQFile::encodeName( user ));
+ if ( pw != 0L )
+ uid = pw->pw_uid;
+ gid = (gid_t)-1;
+ struct group* g = getgrnam(TQFile::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 ) : TDEIO::CopyJob( src, dest, mode, asMethod, showProgressInfo )
+{
+ if( dest.isLocalFile() )
+ {
+ connect( this, TQ_SIGNAL( aboutToCreate (TDEIO::Job *, const TQValueList< TDEIO::CopyInfo > &) ),
+ this, TQ_SLOT( slotAboutToCreate (TDEIO::Job *, const TQValueList< TDEIO::CopyInfo > &) ) );
+ connect( this, TQ_SIGNAL( copyingDone( TDEIO::Job *, const KURL &, const KURL &, bool, bool) ),
+ this, TQ_SLOT( slotCopyingDone( TDEIO::Job *, const KURL &, const KURL &, bool, bool) ) );
+ connect( this, TQ_SIGNAL( result( TDEIO::Job * ) ),
+ this, TQ_SLOT( slotFinished() ) );
+ }
+}
+
+void PreservingCopyJob::slotAboutToCreate( TDEIO::Job */*job*/, const TQValueList< TDEIO::CopyInfo > &files )
+{
+ for ( TQValueList< TDEIO::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 */
+
+ TQString 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 = TQString::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( "TDEIO::StatJob" ) ) { /* Unfortunately TDEIO forgets to set times when the file is in the */
+ KURL url = ((TDEIO::SimpleJob *)job)->url(); /* base directory. That's why we capture every StatJob and set the */
+ /* time manually. */
+ TDEIO::UDSEntry entry = static_cast<TDEIO::StatJob*>(job)->statResult();
+ KFileItem kfi(entry, url );
+
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+ fileAttributes[ url ] = Attributes( kfi.time( TDEIO::UDS_MODIFICATION_TIME ), kfi.user(), kfi.group(), kfi.mode(), kfi.ACL().asString() );
+#else
+ fileAttributes[ url ] = Attributes( kfi.time( TDEIO::UDS_MODIFICATION_TIME ), kfi.user(), kfi.group(), kfi.mode(), TQString() );
+#endif
+ }
+ }
+
+ CopyJob::slotResult( job );
+
+ for( unsigned j=0; j != subjobs.count(); j++ ) {
+ if( subjobs.at( j )->inherits( "TDEIO::ListJob" ) ) {
+ disconnect( subjobs.at( j ), TQ_SIGNAL( entries (TDEIO::Job *, const TDEIO::UDSEntryList &) ),
+ this, TQ_SLOT( slotListEntries (TDEIO::Job *, const TDEIO::UDSEntryList &) ) );
+ connect( subjobs.at( j ), TQ_SIGNAL( entries (TDEIO::Job *, const TDEIO::UDSEntryList &) ),
+ this, TQ_SLOT( slotListEntries (TDEIO::Job *, const TDEIO::UDSEntryList &) ) );
+ }
+ }
+}
+
+void PreservingCopyJob::slotListEntries(TDEIO::Job *job, const TDEIO::UDSEntryList &list) {
+ TDEIO::UDSEntryListConstIterator it = list.begin();
+ TDEIO::UDSEntryListConstIterator end = list.end();
+ for (; it != end; ++it) {
+ KURL url = ((TDEIO::SimpleJob *)job)->url();
+ TQString relName, user, group;
+ time_t mtime = (time_t)-1;
+ mode_t mode = 0755;
+ TQString acl;
+
+ TDEIO::UDSEntry::ConstIterator it2 = (*it).begin();
+ for( ; it2 != (*it).end(); it2++ ) {
+ switch ((*it2).m_uds) {
+ case TDEIO::UDS_NAME:
+ if( relName.isEmpty() )
+ relName = (*it2).m_str;
+ break;
+ case TDEIO::UDS_URL:
+ relName = KURL((*it2).m_str).fileName();
+ break;
+ case TDEIO::UDS_MODIFICATION_TIME:
+ mtime = (time_t)((*it2).m_long);
+ break;
+ case TDEIO::UDS_USER:
+ user = (*it2).m_str;
+ break;
+ case TDEIO::UDS_GROUP:
+ group = (*it2).m_str;
+ break;
+ case TDEIO::UDS_ACCESS:
+ mode = (*it2).m_long;
+ break;
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+ case TDEIO::UDS_ACL_STRING:
+ acl = (*it2).m_str;
+ break;
+#endif
+ }
+ }
+ url.addPath( relName );
+
+ fileAttributes[ url ] = Attributes( mtime, user, group, mode, acl );
+ }
+}
+
+void PreservingCopyJob::slotCopyingDone( TDEIO::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;
+ TQString 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 );
+ }
+}
+
+TDEIO::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 == TDEIO::CopyJob::Link )
+ pmode = PM_NONE;
+
+ switch( pmode )
+ {
+ case PM_PRESERVE_ATTR:
+ return new PreservingCopyJob( src, dest, mode, asMethod, showProgressInfo );
+ case PM_DEFAULT:
+ {
+ TQString 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 TDEIO::CopyJob( src, dest, mode, asMethod, showProgressInfo );
+ }
+ case PM_NONE:
+ default:
+ return new TDEIO::CopyJob( src, dest, mode, asMethod, showProgressInfo );
+ }
+}
+
+#include "preservingcopyjob.moc"
diff --git a/src/app/VFS/preservingcopyjob.h b/src/app/VFS/preservingcopyjob.h
new file mode 100644
index 0000000..e51783b
--- /dev/null
+++ b/src/app/VFS/preservingcopyjob.h
@@ -0,0 +1,85 @@
+/***************************************************************************
+ 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 <tdeio/jobclasses.h>
+#include <tqmap.h>
+#include <tqvaluelist.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 TQString & aclIn );
+ Attributes( time_t tIn, TQString user, TQString group, mode_t modeIn, const TQString & aclIn );
+
+ time_t time;
+ uid_t uid;
+ gid_t gid;
+ mode_t mode;
+ TQString acl;
+};
+
+class PreservingCopyJob : public TDEIO::CopyJob
+{
+ TQ_OBJECT
+
+
+public:
+
+ PreservingCopyJob( const KURL::List& src, const KURL& dest, CopyMode mode, bool asMethod, bool showProgressInfo );
+
+ static TDEIO::CopyJob *createCopyJob( PreserveMode pmode, const KURL::List& src, const KURL& dest, CopyMode mode, bool asMethod, bool showProgressInfo );
+
+public slots:
+ void slotAboutToCreate (TDEIO::Job *, const TQValueList< TDEIO::CopyInfo > &);
+ void slotCopyingDone( TDEIO::Job *, const KURL &, const KURL &, bool, bool);
+ void slotFinished();
+ virtual void slotResult( Job *job );
+ void slotListEntries(TDEIO::Job *job, const TDEIO::UDSEntryList &list);
+
+private:
+ TQMap<KURL, Attributes> fileAttributes;
+ TQMap<TDEIO::Job *, KURL> pendingJobs;
+ TQValueList<KURL> directoriesToStamp;
+ TQValueList<KURL> originalDirectories;
+};
+
+#endif /* __PRESERVING_COPY_JOB_H__ */
diff --git a/src/app/VFS/temp_vfs.cpp b/src/app/VFS/temp_vfs.cpp
new file mode 100644
index 0000000..4dc8185
--- /dev/null
+++ b/src/app/VFS/temp_vfs.cpp
@@ -0,0 +1,136 @@
+/***************************************************************************
+ 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. *
+ * *
+ ***************************************************************************/
+// TQt includes
+#include <tqdir.h>
+// TDE includes
+#include <tdemessagebox.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( TQString origin, TQString type, TQWidget* 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( tmpvfs_type == ISO ){
+ // unmount the ISO image
+ KShellProcess umount;
+ umount << "umount -f" << tmpDir;
+ umount.start(TDEProcess::Block);
+ }
+ // delete the temp dir
+ KShellProcess proc;
+ proc << "rm -rf" << tmpDir;
+ proc.start(TDEProcess::DontCare);
+}
+
+// return the working dir
+TQString temp_vfs::vfs_workingDir(){
+ // get the path inside the archive
+ TQString path = vfs_origin.path(-1);
+ path = path.mid(path.findRev('\\')+1);
+ if(path.left(1) != "/") path = "/"+path;
+ TQDir().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...
+ TQString 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(TQString origin, TQString type){
+ if (type == "-ace") {
+ tmpvfs_type = ACE;
+ }
+ else if (type == "-arj") {
+ tmpvfs_type = ARJ;
+ }
+
+ // 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, TQString(), tmpDir) ){
+ return;
+ }
+}
+
+void temp_vfs::handleRpm(TQString origin){
+ // then extract the cpio archive from the rpm
+ KShellProcess rpm;
+ rpm << "rpm2cpio"<<"\""+origin+"\""+" > "+tmpDir+"/contents.cpio";
+ rpm.start(TDEProcess::Block);
+ // and write a nice header
+ rpm.clearArguments();
+ rpm << "rpm -qip"<<"\""+origin+"\""+" > "+tmpDir+"/header.txt";
+ rpm.start(TDEProcess::Block);
+ // and a file list
+ rpm.clearArguments();
+ rpm << "rpm -lpq"<<"\""+origin+"\""+" > "+tmpDir+"/filelist.txt";
+ rpm.start(TDEProcess::Block);
+ tmpvfs_type = RPM;
+}
+
+void temp_vfs::handleIso(TQString origin){
+ // mount the ISO image
+ KShellProcess mount;
+ mount << KrServices::fullPathName( "mount" ) << "-o loop" << origin << tmpDir;
+ mount.start(TDEProcess::Block);
+ tmpvfs_type = ISO;
+}
diff --git a/src/app/VFS/temp_vfs.h b/src/app/VFS/temp_vfs.h
new file mode 100644
index 0000000..d35169b
--- /dev/null
+++ b/src/app/VFS/temp_vfs.h
@@ -0,0 +1,60 @@
+/***************************************************************************
+ 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:
+ enum TMPVFS_TYPE{ERROR=0,ACE,ARJ,RPM,ISO};
+
+ temp_vfs( TQString origin, TQString type, TQWidget* panel, bool writeable);
+ ~temp_vfs();
+ TQString 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(TQString origin, TQString type);
+ void handleRpm(TQString origin);
+ void handleIso(TQString origin);
+ TMPVFS_TYPE tmpvfs_type; //< the tmp vfs type.
+ TQString tmpDir;
+
+};
+
+#endif
diff --git a/src/app/VFS/vfile.cpp b/src/app/VFS/vfile.cpp
new file mode 100644
index 0000000..c333f45
--- /dev/null
+++ b/src/app/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>
+// TQt includes
+#include <tqdatetime.h>
+// TDE includes
+#include <kmimetype.h>
+#include <tdeversion.h>
+// Krusader includes
+#include "vfile.h"
+#include "krpermhandler.h"
+#include "normal_vfs.h"
+
+#include <kdebug.h>
+
+vfile::vfile(const TQString& name, // useful construtor
+ const TDEIO::filesize_t size,
+ const TQString& perm,
+ const time_t mtime,
+ const bool symLink,
+ const uid_t owner,
+ const gid_t group,
+ const TQString& mime,
+ const TQString& symDest,
+ const mode_t mode,
+ const int rwx)
+{
+ vfile_name=name;
+ vfile_size=size;
+ vfile_owner=TQString();
+ vfile_ownerId=owner;
+ vfile_group=TQString();
+ vfile_groupId=group;
+ vfile_userName=TQString();
+ 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 TQString& name, // useful construtor
+ const TDEIO::filesize_t size,
+ const TQString& perm,
+ const time_t mtime,
+ const bool symLink,
+ const TQString& owner,
+ const TQString& group,
+ const TQString& userName,
+ const TQString& mime,
+ const TQString& symDest,
+ const mode_t mode,
+ const int rwx,
+ const TQString& aclString,
+ const TQString& 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 TQString& vfile::vfile_getMime(bool fast){
+ if( vfile_mimeType == TQString() ){ // 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 TQString& vfile::vfile_getOwner(){
+ if( vfile_owner.isEmpty() )
+ vfile_owner=KRpermHandler::uid2user(vfile_getUid());
+ return vfile_owner;
+}
+
+const TQString& vfile::vfile_getGroup(){
+ if( vfile_group.isEmpty() )
+ vfile_group=KRpermHandler::gid2group(vfile_getGid());
+ return vfile_group;
+}
+
+const TQString& vfile::vfile_getACL(){
+ if( !vfile_acl_loaded )
+ vfile_loadACL();
+ return vfile_acl;
+}
+
+const TQString& 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 TDEIO::UDSEntry vfile::vfile_getEntry() {
+ TDEIO::UDSEntry entry;
+ TDEIO::UDSAtom atom;
+
+ atom.m_uds = TDEIO::UDS_NAME;
+ atom.m_str = vfile_getName();
+ entry.append(atom);
+
+ atom.m_uds = TDEIO::UDS_SIZE;
+ atom.m_long = vfile_getSize();
+ entry.append(atom);
+
+ atom.m_uds = TDEIO::UDS_MODIFICATION_TIME;
+ atom.m_long = vfile_getTime_t();
+ entry.append(atom);
+
+ atom.m_uds = TDEIO::UDS_USER;
+ atom.m_str = vfile_getOwner();
+ entry.append(atom);
+
+ atom.m_uds = TDEIO::UDS_GROUP;
+ atom.m_str = vfile_getGroup();
+ entry.append(atom);
+
+ atom.m_uds = TDEIO::UDS_MIME_TYPE;
+ atom.m_str = vfile_getMime();
+ entry.append(atom);
+
+ atom.m_uds = TDEIO::UDS_FILE_TYPE;
+ atom.m_long = vfile_getMode() & S_IFMT;
+ entry.append(atom);
+
+ atom.m_uds = TDEIO::UDS_ACCESS;
+ atom.m_long = vfile_getMode() & 07777; // keep permissions only
+ entry.append( atom );
+
+ atom.m_uds = TDEIO::UDS_MIME_TYPE;
+ atom.m_str = vfile_getMime();
+ entry.append(atom);
+
+ if( vfile_isSymLink() ){
+ atom.m_uds = TDEIO::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 = TDEIO::UDS_EXTENDED_ACL;
+ atom.m_long = 1;
+ entry.append( atom );
+
+ if( !vfile_acl.isNull() )
+ {
+ atom.m_uds = TDEIO::UDS_ACL_STRING;
+ atom.m_str = vfile_acl;
+ entry.append(atom);
+ }
+
+ if( !vfile_def_acl.isNull() )
+ {
+ atom.m_uds = TDEIO::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/src/app/VFS/vfile.h b/src/app/VFS/vfile.h
new file mode 100644
index 0000000..b2fc9e8
--- /dev/null
+++ b/src/app/VFS/vfile.h
@@ -0,0 +1,167 @@
+/***************************************************************************
+ 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
+
+// TQt includes
+#include <tqstring.h>
+#include <tqobject.h>
+// System includes
+#include <sys/types.h>
+// TDE includes
+#include <tdeio/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 TQObject{
+ TQ_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 TQString& name,
+ const TDEIO::filesize_t size,
+ const TQString& perm,
+ const time_t mtime,
+ const bool symLink,
+ const uid_t owner,
+ const gid_t group,
+ const TQString& mime,
+ const TQString& symDest,
+ const mode_t mode,
+ const int rwx = -1 );
+
+ vfile(const TQString& name,
+ const TDEIO::filesize_t size,
+ const TQString& perm,
+ const time_t mtime,
+ const bool symLink,
+ const TQString& owner,
+ const TQString& group,
+ const TQString& userName,
+ const TQString& mime,
+ const TQString& symDest,
+ const mode_t mode,
+ const int rwx = -1,
+ const TQString& aclString = TQString(),
+ const TQString& aclDfltString = TQString() );
+
+ 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 TQString& vfile_getName() const { return vfile_name; }
+ inline TDEIO::filesize_t vfile_getSize() const { return vfile_size; }
+ inline const TQString& vfile_getPerm() const { return vfile_perm; }
+ inline bool vfile_isDir() const { return vfile_isdir; }
+ inline bool vfile_isSymLink() const { return vfile_symLink; }
+ inline const TQString& 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 TQString& vfile_getMime(bool fast=false);
+ const TQString& vfile_getOwner();
+ const TQString& vfile_getGroup();
+ const TQString& vfile_getACL();
+ const TQString& vfile_getDefaultACL();
+ const TDEIO::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(TDEIO::filesize_t size) {vfile_size = size;}
+ inline void vfile_setUrl(const KURL& url) {vfile_url = url; }
+
+ inline void vfile_setIcon(const TQString& icn) {vfile_icon = icn; }
+ inline TQString vfile_getIcon();
+
+ virtual ~vfile(){}
+
+private:
+ void vfile_loadACL();
+
+protected:
+ // the file information list
+ TQString vfile_name; //< file name
+ TDEIO::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
+ TQString vfile_owner; //< file owner name
+ TQString vfile_group; //< file group name
+ TQString vfile_userName; //< the current username
+ TQString 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
+ TQString vfile_mimeType; //< file mimetype
+ TQString vfile_symDest; //< if it's a sym link - its detination
+ KURL vfile_url; //< file URL - empty by default
+ TQString 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
+ TQString vfile_acl; //< ACL permission string
+ TQString vfile_def_acl; //< ACL default string
+};
+
+
+TQString vfile::vfile_getIcon(){
+ if( vfile_icon.isEmpty() ){
+ TQString mime = this->vfile_getMime();
+ if ( mime == "Broken Link !" )
+ vfile_icon = "file_broken";
+ else {
+ vfile_icon = KMimeType::mimeType( mime ) ->icon( TQString(), true );
+ }
+ }
+ return vfile_icon;
+}
+
+#endif
diff --git a/src/app/VFS/vfs.cpp b/src/app/VFS/vfs.cpp
new file mode 100644
index 0000000..e6804e6
--- /dev/null
+++ b/src/app/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 <tqeventloop.h>
+#include <tdeapplication.h>
+#include <klargefile.h>
+#include <tqdir.h>
+#include "vfs.h"
+#include "../krusader.h"
+#include "../defaults.h"
+
+vfs::vfs(TQObject* 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,TQ_SIGNAL(startUpdate()),panel,TQ_SLOT(slotStartUpdate()));
+ connect(this,TQ_SIGNAL(incrementalRefreshFinished( const KURL& )),panel,TQ_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;
+}
+
+TDEIO::filesize_t vfs::vfs_totalSize(){
+ TDEIO::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(TDEIO::Job* job){
+ if(job && job->error()){
+ job->showErrorDialog(krApp);
+ }
+ return vfs_refresh(vfs_origin);
+}
+
+KURL vfs::fromPathOrURL( const TQString &originIn )
+{
+ TQString 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;
+}
+
+TQString 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 TQDictIterator<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);
+
+ TQString 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
+ TQDictIterator<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;
+ tqApp->eventLoop() ->processEvents( TQEventLoop::AllEvents | TQEventLoop::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( TDEIO::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( TQString name , TDEIO::filesize_t* totalSize, unsigned long* totalFiles, unsigned long* totalDirs, bool* stop ) {
+ calculateURLSize( vfs_getFile( name ), totalSize, totalFiles, totalDirs, stop );
+}
+
+void vfs::calculateURLSize( KURL url, TDEIO::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;
+ TDEIO::StatJob* statJob = TDEIO::stat( url, false );
+ connect( statJob, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( slotStatResultArrived( TDEIO::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, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( slotKdsResult( TDEIO::Job* ) ) );
+ while ( !(*stop) ){
+ // we are in a sepetate thread - so sleeping is OK
+ usleep(1000);
+ }
+}
+
+void vfs::vfs_calcSpaceLocal(TQString name ,TDEIO::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 TQFileInfo 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;
+
+ TQDir dir(name);
+ if ( !dir.exists() ) return;
+
+ ++(*totalDirs);
+ dir.setFilter(TQDir::All | TQDir::System | TQDir::Hidden);
+ dir.setSorting(TQDir::Name | TQDir::DirsFirst);
+
+ // recurse on all the files in the directory
+ TQFileInfoList* fileList = const_cast<TQFileInfoList*>(dir.entryInfoList());
+ for (TQFileInfo* 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( TDEIO::Job* job ) {
+ if( !job || job->error() ) entry = TDEIO::UDSEntry();
+ else entry = static_cast<TDEIO::StatJob*>(job)->statResult();
+ stat_busy = false;
+}
+
+#else
+void vfs::slotKdsResult(TDEIO::Job *job){/* empty */}
+void vfs::vfs_calcSpace( TQString /*name*/ , TDEIO::filesize_t* /*totalSize*/, unsigned long* /*totalFiles*/, unsigned long* /*totalDirs*/, bool* /*stop*/ ) {/* empty*/}
+#endif
+
+TQValueList<vfile*> vfs::vfs_search(const KRQuery& filter) {
+ TQValueList<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/src/app/VFS/vfs.h b/src/app/VFS/vfs.h
new file mode 100644
index 0000000..9253de0
--- /dev/null
+++ b/src/app/VFS/vfs.h
@@ -0,0 +1,187 @@
+/***************************************************************************
+ 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
+
+// TQt includes
+#include <tqstring.h>
+#include <tqvaluelist.h>
+#include <tqobject.h>
+#include <tqdict.h>
+// TDE includes
+#include <kurl.h>
+#include <tdeio/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 TQObject{
+ TQ_OBJECT
+
+public:
+ typedef TQDict<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(TQObject* panel, bool quiet=false);
+ virtual ~vfs();
+
+ /// Copy a file to the vfs (physical).
+ virtual void vfs_addFiles(KURL::List *fileUrls,TDEIO::CopyJob::CopyMode mode,TQObject* toNotify,TQString dir = "", PreserveMode pmode = PM_DEFAULT)=0;
+ /// Remove a file from the vfs (physical)
+ virtual void vfs_delFiles(TQStringList *fileNames)=0;
+ /// Return a list of URLs for multiple files
+ virtual KURL::List* vfs_getFiles(TQStringList* names)=0;
+ /// Return a URL to a single file
+ virtual KURL vfs_getFile(const TQString& name)=0;
+ /// Create a new directory
+ virtual void vfs_mkdir(const TQString& name)=0;
+ /// Rename file
+ virtual void vfs_rename(const TQString& fileName,const TQString& newName)=0;
+ /// Calculate the amount of space occupied by a file or directory (recursive).
+ virtual void vfs_calcSpace(TQString name ,TDEIO::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(TQString name ,TDEIO::filesize_t *totalSize,unsigned long *totalFiles,unsigned long *totalDirs, bool * stop);
+
+ /// Return the VFS working dir
+ virtual TQString 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 TQString& name){ return (*vfs_filesP)[name]; }
+ /// Return an empty vfile* list if not found
+ TQValueList<vfile*> vfs_search(const KRQuery& filter);
+ /// The total size of all the files in the VFS,
+ TDEIO::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 TQString &originIn );
+ static TQString 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(TDEIO::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(TDEIO::Job* job);
+ void incrementalRefreshFinished( const KURL& ); //< emitted when the incremental refresh was finished
+ void addedVfile(vfile* vf);
+ void deletedVfile(const TQString& 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(TQString name){ vfs_filesP->remove(name); }
+
+ /// Deletes a vfile from the list.
+ void calculateURLSize(KURL url,TDEIO::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(TDEIO::Job *job);
+ void slotStatResultArrived(TDEIO::Job *job);
+
+private:
+ vfileDict* vfs_filesP; //< Point to a lists of virtual files (vfile).
+ vfileDict* vfs_tempFilesP;//< Temporary files are stored here
+ TQDictIterator<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;
+ TDEIO::UDSEntry entry;
+ TDEIO::filesize_t* kds_totalSize;
+ unsigned long* kds_totalFiles;
+ unsigned long* kds_totalDirs;
+};
+
+#endif
diff --git a/src/app/VFS/virt_vfs.cpp b/src/app/VFS/virt_vfs.cpp
new file mode 100644
index 0000000..3c70231
--- /dev/null
+++ b/src/app/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 <tdefileitem.h>
+#include <tdeglobalsettings.h>
+#include <kurl.h>
+#include <tdemessagebox.h>
+#include <tdelocale.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"
+
+TQDict<KURL::List> virt_vfs::virtVfsDict;
+TDEConfig* virt_vfs::virt_vfs_db=0;
+
+virt_vfs::virt_vfs( TQObject* 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, TDEIO::CopyJob::CopyMode /*mode*/, TQObject* /*toNotify*/, TQString /*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( TQStringList *fileNames ) {
+ if ( path == "/" ) {
+ for ( uint i = 0 ; i < fileNames->count(); ++i ) {
+ TQString filename = ( *fileNames ) [ i ];
+ virtVfsDict[ "/" ] ->remove( TQString("virt:/")+filename );
+ virtVfsDict.remove( filename );
+ }
+ vfs_refresh();
+ return ;
+ }
+
+ KURL::List filesUrls;
+ KURL url;
+
+ // names -> urls
+ for ( uint i = 0 ; i < fileNames->count(); ++i ) {
+ TQString filename = ( *fileNames ) [ i ];
+ filesUrls.append( vfs_getFile( filename ) );
+ }
+ TDEIO::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 = TDEIO::trash( filesUrls, true );
+#else
+ job = new TDEIO::CopyJob( filesUrls, TDEGlobalSettings::trashPath(), TDEIO::CopyJob::Move, false, true );
+#endif
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), krApp, TQ_SLOT( changeTrashIcon() ) );
+ } else
+ job = new TDEIO::DeleteJob( filesUrls, false, true );
+
+ // refresh will remove the deleted files...
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( vfs_refresh( TDEIO::Job* ) ) );
+}
+
+void virt_vfs::vfs_removeFiles( TQStringList *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( TQStringList* names ) {
+ KURL url;
+ KURL::List* urls = new KURL::List();
+ for ( TQStringList::Iterator name = names->begin(); name != names->end(); ++name ) {
+ url = vfs_getFile( *name );
+ urls->append( url );
+ }
+ return urls;
+}
+
+KURL virt_vfs::vfs_getFile( const TQString& 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 TQString& 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( TQString( "virt:/" )+name );
+
+ vfs_refresh();
+}
+
+void virt_vfs::vfs_rename( const TQString& fileName, const TQString& newName ) {
+ KURL::List fileUrls;
+ KURL url , dest;
+
+ vfile* vf = vfs_search( fileName );
+ if ( !vf ) return ; // not found
+
+ if ( path == "/" ) {
+ virtVfsDict[ "/" ] ->append( TQString( "virt:/" ) + newName );
+ virtVfsDict[ "/" ] ->remove( TQString( "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 );
+
+ TDEIO::Job *job = new TDEIO::CopyJob( fileUrls, dest, TDEIO::CopyJob::Move, true, false );
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( vfs_refresh( TDEIO::Job* ) ) );
+}
+
+void virt_vfs::slotStatResult( TDEIO::Job* job ) {
+ if( !job || job->error() ) entry = TDEIO::UDSEntry();
+ else entry = static_cast<TDEIO::StatJob*>(job)->statResult();
+ busy = false;
+}
+
+vfile* virt_vfs::stat( const KURL& url ) {
+ if( url.protocol() == "virt" ){
+ TQString 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;
+ TDEIO::StatJob* statJob = TDEIO::stat( url, false );
+ connect( statJob, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( slotStatResult( TDEIO::Job* ) ) );
+ while ( busy && vfs_processEvents() );
+ if( entry.isEmpty() ) return 0; // statJob failed
+
+ kfi = new KFileItem(entry, url, true );
+ }
+
+ if ( !kfi->time( TDEIO::UDS_MODIFICATION_TIME ) ){
+ delete kfi;
+ return 0; // file not found
+ }
+
+ vfile *temp;
+
+ // get file statistics
+ TQString name;
+ if( url.isLocalFile() )
+ name = url.path();
+ else
+ name = url.prettyURL();
+
+ TDEIO::filesize_t size = kfi->size();
+ time_t mtime = kfi->time( TDEIO::UDS_MODIFICATION_TIME );
+ bool symLink = kfi->isLink();
+ mode_t mode = kfi->mode() | kfi->permissions();
+ TQString perm = KRpermHandler::mode2TQString( mode );
+// set the mimetype
+ TQString mime = TQString();
+ TQString 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 {
+ TQString 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;
+}
+
+TDEConfig* virt_vfs::getVirtDB(){
+ if( !virt_vfs_db ){
+ virt_vfs_db = new TDEConfig(VIRT_VFS_DB,false,"data");
+ }
+ return virt_vfs_db;
+}
+
+bool virt_vfs::save(){
+ TDEConfig* db = getVirtDB();
+
+ db->setGroup("virt_db");
+ TQDictIterator<KURL::List> it( virtVfsDict ); // See TQDictIterator
+ for( ; it.current(); ++it ){
+ KURL::List::iterator url;
+ TQStringList 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(){
+ TDEConfig* db = getVirtDB();
+ db->setGroup("virt_db");
+
+ TQMap<TQString, TQString> map = db->entryMap("virt_db");
+ TQMap<TQString, TQString>::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( TQString name , TDEIO::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/src/app/VFS/virt_vfs.h b/src/app/VFS/virt_vfs.h
new file mode 100644
index 0000000..6663e21
--- /dev/null
+++ b/src/app/VFS/virt_vfs.h
@@ -0,0 +1,77 @@
+/***************************************************************************
+ 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 <tdeconfig.h>
+
+#include "vfs.h"
+
+/**
+ *@author Shie Erlich & Rafi Yanai
+ */
+
+class virt_vfs : public vfs {
+TQ_OBJECT
+
+public:
+ virt_vfs(TQObject* panel, bool quiet=false);
+ ~virt_vfs();
+
+ /// Copy a file to the vfs (physical).
+ void vfs_addFiles(KURL::List *fileUrls,TDEIO::CopyJob::CopyMode mode,TQObject* toNotify,TQString dir = "", PreserveMode pmode = PM_DEFAULT );
+ /// Remove a file from the vfs (physical)
+ void vfs_delFiles(TQStringList *fileNames);
+ /// Remove a file from the collection (only its link, not the file)
+ void vfs_removeFiles(TQStringList *fileNames);
+ /// Return a list of URLs for multiple files
+ KURL::List* vfs_getFiles(TQStringList* names);
+ /// Return a URL to a single file
+ KURL vfs_getFile(const TQString& name);
+ /// Create a new directory
+ void vfs_mkdir(const TQString& name);
+ /// Rename file
+ void vfs_rename(const TQString& fileName,const TQString& newName);
+ /// Calculate the amount of space occupied by a file or directory (recursive).
+ virtual void vfs_calcSpace(TQString name ,TDEIO::filesize_t *totalSize,unsigned long *totalFiles,unsigned long *totalDirs, bool * stop);
+
+ /// Return the VFS working dir
+ TQString vfs_workingDir(){ return TQString(); }
+
+protected slots:
+ void slotStatResult(TDEIO::Job *job);
+
+protected:
+ /// Save the dictionary to file
+ bool save();
+ /// Restore the dictionary from file
+ bool restore();
+ /// return the URLs DB
+ TDEConfig* getVirtDB();
+
+ bool populateVfsList(const KURL& origin, bool showHidden);
+ vfile* stat(const KURL& url);
+
+ static TQDict<KURL::List> virtVfsDict;
+ static TDEConfig* virt_vfs_db;
+ bool busy;
+ TQString path;
+ TDEIO::UDSEntry entry;
+};
+
+#endif
diff --git a/src/app/VFS/virtualcopyjob.cpp b/src/app/VFS/virtualcopyjob.cpp
new file mode 100644
index 0000000..15be7fa
--- /dev/null
+++ b/src/app/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 <tdeio/observer.h>
+#include <tdeio/global.h>
+#include <tdeio/jobclasses.h>
+#include <kdirsize.h>
+
+#define REPORT_TIMEOUT 200
+
+VirtualCopyJob::VirtualCopyJob( const TQStringList *names, vfs * vfs, const KURL& dest, const KURL& baseURL,
+ PreserveMode pmode, TDEIO::CopyJob::CopyMode mode, bool asMethod, bool showProgressInfo ) :
+ TDEIO::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() ) ) {
+ TQString 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, TQ_SIGNAL( totalFiles( TDEIO::Job*, unsigned long ) ),
+ Observer::self(), TQ_SLOT( slotTotalFiles( TDEIO::Job*, unsigned long ) ) );
+ connect( this, TQ_SIGNAL( totalDirs( TDEIO::Job*, unsigned long ) ),
+ Observer::self(), TQ_SLOT( slotTotalDirs( TDEIO::Job*, unsigned long ) ) );
+ connect( this, TQ_SIGNAL( processedFiles( TDEIO::Job*, unsigned long ) ),
+ Observer::self(), TQ_SLOT( slotProcessedFiles( TDEIO::Job*, unsigned long ) ) );
+ connect( this, TQ_SIGNAL( processedDirs( TDEIO::Job*, unsigned long ) ),
+ Observer::self(), TQ_SLOT( slotProcessedDirs( TDEIO::Job*, unsigned long ) ) );
+ connect( this, TQ_SIGNAL( percent( TDEIO::Job*, unsigned long ) ),
+ Observer::self(), TQ_SLOT( slotPercent( TDEIO::Job*, unsigned long ) ) );
+ }
+
+ TQTimer::singleShot( 0, this, TQ_SLOT( slotStart() ) );
+}
+
+void VirtualCopyJob::slotStart() {
+ if( m_showProgressInfo ) {
+ if( m_mode == TDEIO::CopyJob::Move )
+ Observer::self()->slotMoving( this, m_baseURL, m_dest );
+ else
+ Observer::self()->slotCopying( this, m_baseURL, m_dest );
+ }
+
+ connect(&m_reportTimer,TQ_SIGNAL(timeout()),this,TQ_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, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( slotKdsResult( TDEIO::Job* ) ) );
+}
+
+void VirtualCopyJob::slotKdsResult( TDEIO::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;
+ }
+
+ TQDictIterator<KURL::List> diter( m_filesToCopy );
+
+ m_currentDir = diter.currentKey();
+ m_current = m_dest;
+ if( m_currentDir != "./" && !m_currentDir.isEmpty() )
+ m_current.addPath( m_currentDir );
+
+ TDEIO::Job *job = TDEIO::stat( m_current );
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( slotStatResult( TDEIO::Job* ) ) );
+}
+
+void VirtualCopyJob::slotStatResult( TDEIO::Job *job ) {
+ KURL url = (static_cast<TDEIO::SimpleJob*>(job) )->url();
+
+ if ( job && job->error() ) {
+ if( job->error() == TDEIO::ERR_DOES_NOT_EXIST && !url.equals( url.upURL(),true ) ) {
+ m_dirStack.push_back( url.fileName() );
+ TDEIO::Job *job = TDEIO::stat( url.upURL() );
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( slotStatResult( TDEIO::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();
+
+ TDEIO::Job *mkdir_job = TDEIO::mkdir( url );
+ connect( mkdir_job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( slotMkdirResult( TDEIO::Job* ) ) );
+ }
+ else
+ copyCurrentDir();
+}
+
+void VirtualCopyJob::slotMkdirResult( TDEIO::Job *job ) {
+ KURL url = (static_cast<TDEIO::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();
+
+ TDEIO::Job *mkdir_job = TDEIO::mkdir( url );
+ connect( mkdir_job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( slotMkdirResult( TDEIO::Job* ) ) );
+ }
+ else
+ copyCurrentDir();
+}
+
+void VirtualCopyJob::copyCurrentDir() {
+ m_state = ST_COPYING;
+
+ TDEIO::CopyJob * copy_job = PreservingCopyJob::createCopyJob( m_pmode, *m_filesToCopy[ m_currentDir ], m_current,
+ m_mode, m_asMethod, false );
+
+ connect( copy_job, TQ_SIGNAL( copying(TDEIO::Job *, const KURL &, const KURL &) ),
+ this, TQ_SLOT( slotCopying(TDEIO::Job *, const KURL &, const KURL &) ) );
+ connect( copy_job, TQ_SIGNAL( moving(TDEIO::Job *, const KURL &, const KURL &) ),
+ this, TQ_SLOT( slotMoving(TDEIO::Job *, const KURL &, const KURL &) ) );
+ connect( copy_job, TQ_SIGNAL( creatingDir(TDEIO::Job *, const KURL &) ),
+ this, TQ_SLOT( slotCreatingDir(TDEIO::Job *, const KURL &) ) );
+ connect( copy_job, TQ_SIGNAL( processedFiles (TDEIO::Job *, unsigned long) ),
+ this, TQ_SLOT( slotProcessedFiles (TDEIO::Job *, unsigned long) ) );
+ connect( copy_job, TQ_SIGNAL( processedDirs (TDEIO::Job *, unsigned long) ),
+ this, TQ_SLOT( slotProcessedDirs (TDEIO::Job *, unsigned long) ) );
+ connect( copy_job, TQ_SIGNAL( processedSize (TDEIO::Job *, TDEIO::filesize_t) ),
+ this, TQ_SLOT( slotProcessedSize (TDEIO::Job *, TDEIO::filesize_t) ) );
+ connect( copy_job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( slotCopyResult( TDEIO::Job* ) ) );
+}
+
+void VirtualCopyJob::slotCopyResult( TDEIO::Job *job ) {
+ if ( job && job->error() ) {
+ job->showErrorDialog( krApp );
+ }
+
+ directoryFinished( m_currentDir );
+ createNextDir();
+}
+
+void VirtualCopyJob::directoryFinished( const TQString &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(TDEIO::Job *, const KURL &from, const KURL &to) {
+ if( m_showProgressInfo )
+ Observer::self()->slotCopying( this, from, to );
+}
+
+void VirtualCopyJob::slotMoving(TDEIO::Job *, const KURL &from, const KURL &to) {
+ if( m_showProgressInfo )
+ Observer::self()->slotMoving( this, from, to );
+}
+
+void VirtualCopyJob::slotCreatingDir(TDEIO::Job *, const KURL &to) {
+ if( m_showProgressInfo )
+ Observer::self()->slotCreatingDir( this, to );
+}
+
+void VirtualCopyJob::slotProcessedFiles (TDEIO::Job *, unsigned long filenum) {
+ m_tempFiles = filenum;
+}
+
+void VirtualCopyJob::slotProcessedDirs (TDEIO::Job *, unsigned long subdirs) {
+ m_tempSubdirs = subdirs;
+}
+
+void VirtualCopyJob::slotProcessedSize (TDEIO::Job *, TDEIO::filesize_t size) {
+ m_tempSize = size;
+}
+
+#include "virtualcopyjob.moc"
diff --git a/src/app/VFS/virtualcopyjob.h b/src/app/VFS/virtualcopyjob.h
new file mode 100644
index 0000000..c9600ad
--- /dev/null
+++ b/src/app/VFS/virtualcopyjob.h
@@ -0,0 +1,126 @@
+/***************************************************************************
+ 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 <tdeio/job.h>
+#include "preservingcopyjob.h"
+#include <tqvaluelist.h>
+#include <tqtimer.h>
+#include <tqdict.h>
+#include <tqmap.h>
+
+class vfs;
+
+typedef enum {
+ ST_STARTING = 0,
+ ST_CALCULATING_TOTAL_SIZE = 1,
+ ST_CREATING_DIRECTORY = 2,
+ ST_COPYING = 3
+} State;
+
+class VirtualCopyJob : public TDEIO::Job
+{
+ TQ_OBJECT
+
+
+public:
+ VirtualCopyJob( const TQStringList *names, vfs * vfs, const KURL& dest, const KURL& baseURL,
+ PreserveMode pmode, TDEIO::CopyJob::CopyMode mode, bool asMethod, bool showProgressInfo );
+
+protected:
+ void statNextDir();
+ void createNextDir();
+ void copyCurrentDir();
+ void directoryFinished( const TQString & );
+
+protected slots:
+ void slotStart();
+ void slotReport();
+
+ void slotKdsResult( TDEIO::Job * );
+ void slotStatResult( TDEIO::Job * );
+ void slotMkdirResult( TDEIO::Job * );
+ void slotCopyResult( TDEIO::Job * );
+
+ void slotCopying(TDEIO::Job *, const KURL &, const KURL &);
+ void slotMoving(TDEIO::Job *, const KURL &, const KURL &);
+ void slotCreatingDir(TDEIO::Job *, const KURL &);
+
+ void slotProcessedFiles (TDEIO::Job *, unsigned long);
+ void slotProcessedDirs (TDEIO::Job *, unsigned long);
+ void slotProcessedSize (TDEIO::Job *, TDEIO::filesize_t);
+
+signals:
+ void totalFiles( TDEIO::Job *job, unsigned long files );
+ void totalDirs( TDEIO::Job *job, unsigned long dirs );
+ void processedFiles( TDEIO::Job *job, unsigned long files );
+ void processedDirs( TDEIO::Job *job, unsigned long dirs );
+
+private:
+ TDEIO::filesize_t m_totalSize;
+ unsigned long m_totalFiles;
+ unsigned long m_totalSubdirs;
+
+ TDEIO::filesize_t m_processedSize;
+ unsigned long m_processedFiles;
+ unsigned long m_processedSubdirs;
+
+ TDEIO::filesize_t m_tempSize;
+ unsigned long m_tempFiles;
+ unsigned long m_tempSubdirs;
+
+ TQValueList<KURL> m_dirsToGetSize;
+
+ TQDict<KURL::List> m_filesToCopy;
+
+ TQMap<TQString,int> m_size;
+ TQMap<TQString,int> m_filenum;
+ TQMap<TQString,int> m_subdirs;
+
+ KURL m_baseURL;
+ KURL m_dest;
+ PreserveMode m_pmode;
+ TDEIO::CopyJob::CopyMode m_mode;
+ bool m_asMethod;
+ bool m_showProgressInfo;
+
+ State m_state;
+
+ TQTimer m_reportTimer;
+
+ KURL m_current;
+ TQString m_currentDir;
+
+ TQStringList m_dirStack;
+};
+
+#endif /* __VIRTUAL_COPY_JOB_H__ */
diff --git a/src/app/alpa-yellow.color b/src/app/alpa-yellow.color
new file mode 100644
index 0000000..a7a9a45
--- /dev/null
+++ b/src/app/alpa-yellow.color
Binary files differ
diff --git a/src/app/bash.color b/src/app/bash.color
new file mode 100644
index 0000000..664b975
--- /dev/null
+++ b/src/app/bash.color
Binary files differ
diff --git a/src/app/calc.js b/src/app/calc.js
new file mode 100644
index 0000000..de43427
--- /dev/null
+++ b/src/app/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/src/app/calc.ui b/src/app/calc.ui
new file mode 100644
index 0000000..46326c8
--- /dev/null
+++ b/src/app/calc.ui
@@ -0,0 +1,267 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>calc</class>
+<widget class="TQWidget">
+ <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="TQLCDNumber" row="0" column="0">
+ <property name="name">
+ <cstring>display</cstring>
+ </property>
+ <property name="numDigits">
+ <number>18</number>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQPushButton" row="1" column="3">
+ <property name="name">
+ <cstring>plus</cstring>
+ </property>
+ <property name="text">
+ <string>+</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="0" column="4">
+ <property name="name">
+ <cstring>all_clear</cstring>
+ </property>
+ <property name="text">
+ <string>AC</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="2" column="3">
+ <property name="name">
+ <cstring>minus</cstring>
+ </property>
+ <property name="text">
+ <string>-</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="3" column="2" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>equals</cstring>
+ </property>
+ <property name="text">
+ <string>=</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="1" column="4">
+ <property name="name">
+ <cstring>clear</cstring>
+ </property>
+ <property name="text">
+ <string>CL</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="3" column="1">
+ <property name="name">
+ <cstring>zero</cstring>
+ </property>
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="1" column="0">
+ <property name="name">
+ <cstring>four</cstring>
+ </property>
+ <property name="text">
+ <string>4</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="0" column="1">
+ <property name="name">
+ <cstring>two</cstring>
+ </property>
+ <property name="text">
+ <string>2</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="1" column="1">
+ <property name="name">
+ <cstring>five</cstring>
+ </property>
+ <property name="text">
+ <string>5</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="0" column="2">
+ <property name="name">
+ <cstring>three</cstring>
+ </property>
+ <property name="text">
+ <string>3</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="2" column="0">
+ <property name="name">
+ <cstring>seven</cstring>
+ </property>
+ <property name="text">
+ <string>7</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="1" column="2">
+ <property name="name">
+ <cstring>six</cstring>
+ </property>
+ <property name="text">
+ <string>6</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="2" column="1">
+ <property name="name">
+ <cstring>eight</cstring>
+ </property>
+ <property name="text">
+ <string>8</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="2" column="2">
+ <property name="name">
+ <cstring>nine</cstring>
+ </property>
+ <property name="text">
+ <string>9</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="0" column="0">
+ <property name="name">
+ <cstring>one</cstring>
+ </property>
+ <property name="text">
+ <string>1</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQPushButton" 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/src/app/cr16-app-krusader_blue.png b/src/app/cr16-app-krusader_blue.png
new file mode 100644
index 0000000..1f690dc
--- /dev/null
+++ b/src/app/cr16-app-krusader_blue.png
Binary files differ
diff --git a/src/app/cr16-app-krusader_red.png b/src/app/cr16-app-krusader_red.png
new file mode 100644
index 0000000..15e9765
--- /dev/null
+++ b/src/app/cr16-app-krusader_red.png
Binary files differ
diff --git a/src/app/cr16-app-krusader_root.png b/src/app/cr16-app-krusader_root.png
new file mode 100644
index 0000000..d9b4b6c
--- /dev/null
+++ b/src/app/cr16-app-krusader_root.png
Binary files differ
diff --git a/src/app/cr16-app-krusader_user.png b/src/app/cr16-app-krusader_user.png
new file mode 100644
index 0000000..5ca2993
--- /dev/null
+++ b/src/app/cr16-app-krusader_user.png
Binary files differ
diff --git a/src/app/cr22-app-krusader_blue.png b/src/app/cr22-app-krusader_blue.png
new file mode 100644
index 0000000..f4c0116
--- /dev/null
+++ b/src/app/cr22-app-krusader_blue.png
Binary files differ
diff --git a/src/app/cr22-app-krusader_red.png b/src/app/cr22-app-krusader_red.png
new file mode 100644
index 0000000..ac1ee63
--- /dev/null
+++ b/src/app/cr22-app-krusader_red.png
Binary files differ
diff --git a/src/app/cr22-app-krusader_root.png b/src/app/cr22-app-krusader_root.png
new file mode 100644
index 0000000..566e665
--- /dev/null
+++ b/src/app/cr22-app-krusader_root.png
Binary files differ
diff --git a/src/app/cr22-app-krusader_shield.png b/src/app/cr22-app-krusader_shield.png
new file mode 100644
index 0000000..5ef7407
--- /dev/null
+++ b/src/app/cr22-app-krusader_shield.png
Binary files differ
diff --git a/src/app/cr22-app-krusader_user.png b/src/app/cr22-app-krusader_user.png
new file mode 100644
index 0000000..5896334
--- /dev/null
+++ b/src/app/cr22-app-krusader_user.png
Binary files differ
diff --git a/src/app/cr32-app-krusader_blue.png b/src/app/cr32-app-krusader_blue.png
new file mode 100644
index 0000000..35b18b4
--- /dev/null
+++ b/src/app/cr32-app-krusader_blue.png
Binary files differ
diff --git a/src/app/cr32-app-krusader_red.png b/src/app/cr32-app-krusader_red.png
new file mode 100644
index 0000000..77602e1
--- /dev/null
+++ b/src/app/cr32-app-krusader_red.png
Binary files differ
diff --git a/src/app/cr32-app-krusader_root.png b/src/app/cr32-app-krusader_root.png
new file mode 100644
index 0000000..d945e5d
--- /dev/null
+++ b/src/app/cr32-app-krusader_root.png
Binary files differ
diff --git a/src/app/cr32-app-krusader_shield.png b/src/app/cr32-app-krusader_shield.png
new file mode 100644
index 0000000..3995afa
--- /dev/null
+++ b/src/app/cr32-app-krusader_shield.png
Binary files differ
diff --git a/src/app/cr32-app-krusader_user.png b/src/app/cr32-app-krusader_user.png
new file mode 100644
index 0000000..89ba104
--- /dev/null
+++ b/src/app/cr32-app-krusader_user.png
Binary files differ
diff --git a/src/app/cr48-app-krusader_blue.png b/src/app/cr48-app-krusader_blue.png
new file mode 100644
index 0000000..06842c2
--- /dev/null
+++ b/src/app/cr48-app-krusader_blue.png
Binary files differ
diff --git a/src/app/cr48-app-krusader_red.png b/src/app/cr48-app-krusader_red.png
new file mode 100644
index 0000000..60c2002
--- /dev/null
+++ b/src/app/cr48-app-krusader_red.png
Binary files differ
diff --git a/src/app/cr48-app-krusader_root.png b/src/app/cr48-app-krusader_root.png
new file mode 100644
index 0000000..f9cee8b
--- /dev/null
+++ b/src/app/cr48-app-krusader_root.png
Binary files differ
diff --git a/src/app/cr48-app-krusader_shield.png b/src/app/cr48-app-krusader_shield.png
new file mode 100644
index 0000000..0838bd1
--- /dev/null
+++ b/src/app/cr48-app-krusader_shield.png
Binary files differ
diff --git a/src/app/cr48-app-krusader_user.png b/src/app/cr48-app-krusader_user.png
new file mode 100644
index 0000000..ce03e22
--- /dev/null
+++ b/src/app/cr48-app-krusader_user.png
Binary files differ
diff --git a/src/app/cr64-app-krusader_blue.png b/src/app/cr64-app-krusader_blue.png
new file mode 100644
index 0000000..c707f2f
--- /dev/null
+++ b/src/app/cr64-app-krusader_blue.png
Binary files differ
diff --git a/src/app/cr64-app-krusader_red.png b/src/app/cr64-app-krusader_red.png
new file mode 100644
index 0000000..5b70f5c
--- /dev/null
+++ b/src/app/cr64-app-krusader_red.png
Binary files differ
diff --git a/src/app/cr64-app-krusader_root.png b/src/app/cr64-app-krusader_root.png
new file mode 100644
index 0000000..e25fae6
--- /dev/null
+++ b/src/app/cr64-app-krusader_root.png
Binary files differ
diff --git a/src/app/cr64-app-krusader_shield.png b/src/app/cr64-app-krusader_shield.png
new file mode 100644
index 0000000..1ce0ba3
--- /dev/null
+++ b/src/app/cr64-app-krusader_shield.png
Binary files differ
diff --git a/src/app/cr64-app-krusader_user.png b/src/app/cr64-app-krusader_user.png
new file mode 100644
index 0000000..ef946ae
--- /dev/null
+++ b/src/app/cr64-app-krusader_user.png
Binary files differ
diff --git a/src/app/defaults.h b/src/app/defaults.h
new file mode 100644
index 0000000..55dacf4
--- /dev/null
+++ b/src/app/defaults.h
@@ -0,0 +1,308 @@
+/***************************************************************************
+ 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 <tdeglobalsettings.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 TQFont(TDEGlobalSettings::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 TQString("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
+// Do Xz //////////////
+#define _DoXz true
+// Allow Move Into Archive //
+#define _MoveIntoArchive false
+// Test Archives //////
+#define _TestArchives false
+// Test Before Unpack ////
+#define _TestBeforeUnpack true
+// Supported Packers // ====> a TQStringList 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 TQFont(TDEGlobalSettings::generalFont())
+// Font for output collection with fixed width ///////
+#define _UserActions_FixedFont new TQFont(TDEGlobalSettings::fixedFont())
+// Use for output collection fixed width font as default ///////
+#define _UserActions_UseFixedFont false
+
+/////////////////////// [Private]
+// Start Position /////
+#define _StartPosition new TQPoint(TQApplication::desktop()->width()/2 - mainView->sizeHint().width()/2,TQApplication::desktop()->height()/2 - 250)
+// Start Size /////////
+#define _StartSize new TQSize(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]
+// TQt Selection
+#define _TQtSelection 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/src/app/dos_navigator.color b/src/app/dos_navigator.color
new file mode 100644
index 0000000..423fbe3
--- /dev/null
+++ b/src/app/dos_navigator.color
Binary files differ
diff --git a/src/app/kicons.cpp b/src/app/kicons.cpp
new file mode 100644
index 0000000..fbf40ed
--- /dev/null
+++ b/src/app/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 <tqstring.h>
+
+TQPixmap FL_LOADICON(TQString name) {
+ krConfig->setGroup("Look&Feel");
+ int size = (krConfig->readEntry("Filelist Icon Size",_FilelistIconSize)).toInt();
+ if (size!=22)
+ return krLoader->loadIcon(name,TDEIcon::Desktop,size);
+ // else implied
+ return TQIconSet(krLoader->loadIcon(name,TDEIcon::Desktop,32)).pixmap(TQIconSet::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/src/app/kicons.h b/src/app/kicons.h
new file mode 100644
index 0000000..fd5eb7b
--- /dev/null
+++ b/src/app/kicons.h
@@ -0,0 +1,29 @@
+#ifndef KICONS_H
+#define KICONS_H
+
+#include <tqiconset.h>
+#include <tqpixmap.h>
+#include <kiconloader.h>
+#include <kicontheme.h>
+
+// can be used everywhere - EXCEPT in KFileList related calls, loads the icon according to
+// TDEIcon::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) TQIconSet(krLoader->loadIcon(X,TDEIcon::Desktop)).pixmap(TQIconSet::Small,true)
+
+// used only for calls within the tdefilelist framework, handles icon sizes
+TQPixmap FL_LOADICON(TQString 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/src/app/krservices.cpp b/src/app/krservices.cpp
new file mode 100644
index 0000000..330df14
--- /dev/null
+++ b/src/app/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>
+// TQt includes
+#include <tqdir.h>
+// TDE includes
+#include <kdebug.h>
+// Krusader includes
+#include "krservices.h"
+#include "krusader.h"
+
+TQMap<TQString,TQString>* KrServices::slaveMap=0;
+
+bool KrServices::cmdExist(TQString cmdName)
+{
+ TQString lastGroup = krConfig->group();
+
+ krConfig->setGroup( "Dependencies" );
+ if( TQFile( krConfig->readEntry( cmdName, TQString() )).exists() )
+ {
+ krConfig->setGroup( lastGroup );
+ return true;
+ }
+
+ krConfig->setGroup( lastGroup );
+ return !detectFullPathName( cmdName ).isEmpty();
+}
+
+TQString KrServices::detectFullPathName(TQString name)
+{
+ TQStringList path = TQStringList::split(":",getenv("PATH"));
+
+ for ( TQStringList::Iterator it = path.begin(); it != path.end(); ++it )
+ {
+ if( TQDir(*it).exists( name ) )
+ {
+ TQString dir = *it;
+ if( !dir.endsWith( "/" ) )
+ dir+="/";
+
+ return dir+name;
+ }
+ }
+
+ return "";
+}
+
+TQString KrServices::fullPathName( TQString name, TQString confName )
+{
+ TQString lastGroup = krConfig->group();
+ TQString supposedName;
+
+ if( confName.isNull() )
+ confName = name;
+
+ krConfig->setGroup( "Dependencies" );
+ if( TQFile( 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!
+TQStringList KrServices::separateArgs( TQString args )
+{
+ TQStringList argList;
+ int pointer = 0, tokenStart, len = args.length();
+ bool quoted = false;
+ TQChar quoteCh;
+
+ do{
+ while( pointer < len && args[ pointer ].isSpace() )
+ pointer++;
+
+ if( pointer >= len )
+ break;
+
+ tokenStart = pointer;
+
+ TQString 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;
+}
+
+TQString KrServices::registerdProtocol(TQString mimetype){
+ if( slaveMap == 0 ){
+ slaveMap = new TQMap<TQString,TQString>();
+
+ krConfig->setGroup( "Protocols" );
+ TQStringList protList = krConfig->readListEntry( "Handled Protocols" );
+ for( TQStringList::Iterator it = protList.begin(); it != protList.end(); it++ ){
+ TQStringList mimes = krConfig->readListEntry( TQString( "Mimes For %1" ).arg( *it ) );
+ for( TQStringList::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(TQTextStream *stream, TQStringList& target, bool keepEmptyLines) {
+ if (!stream) return false;
+ TQString line;
+ while ( !stream->atEnd() ) {
+ line = stream->readLine().stripWhiteSpace();
+ if (keepEmptyLines || !line.isEmpty()) target.append(line);
+ }
+ return true;
+}
+
+TQString KrServices::quote( TQString name ) {
+ if( !name.contains( '\'' ) )
+ return "'" + name + "'";
+ if( !name.contains( '"' ) && !name.contains( '$' ) )
+ return "\"" + name + "\"";
+ return escape( name );
+}
+
+TQStringList KrServices::quote( const TQStringList& names ) {
+ TQStringList result;
+ for (unsigned i=0; i<names.size(); ++i)
+ result.append(quote(names[i]));
+ return result;
+}
+
+TQString KrServices::escape( TQString name ) {
+ const TQString evilstuff = "\\\"'`()[]{}!?;$&<>| \t\r\n"; // stuff that should get escaped
+
+ for ( unsigned int i = 0; i < evilstuff.length(); ++i )
+ name.replace( evilstuff[ i ], (TQString("\\") + evilstuff[ i ]) );
+
+ return name;
+}
+
+
+// ------- KEasyProcess
+KEasyProcess::KEasyProcess(TQObject *parent, const char *name): TDEProcess(parent, name) {
+ init();
+}
+
+KEasyProcess::KEasyProcess(): TDEProcess() {
+ init();
+}
+
+void KEasyProcess::init() {
+ connect(this, TQ_SIGNAL(receivedStdout(TDEProcess *, char *, int)),
+ this, TQ_SLOT(receivedStdout(TDEProcess *, char *, int)));
+ connect(this, TQ_SIGNAL(receivedStderr(TDEProcess *, char *, int)),
+ this, TQ_SLOT(receivedStderr(TDEProcess *, char *, int)));
+}
+
+void KEasyProcess::receivedStdout (TDEProcess * /* proc */, char *buffer, int buflen) {
+ _stdout+=TQString::fromLocal8Bit(buffer, buflen);
+}
+
+void KEasyProcess::receivedStderr (TDEProcess * /* proc */, char *buffer, int buflen) {
+ _stderr+=TQString::fromLocal8Bit(buffer, buflen);
+}
diff --git a/src/app/krservices.h b/src/app/krservices.h
new file mode 100644
index 0000000..ddf3fe6
--- /dev/null
+++ b/src/app/krservices.h
@@ -0,0 +1,79 @@
+/***************************************************************************
+ 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 <tqstring.h>
+#include <tqstringlist.h>
+#include <tqmap.h>
+#include <kprocess.h>
+
+/**
+ *@author Shie Erlich & Rafi Yanai
+ */
+
+class KrServices {
+public:
+ KrServices(){}
+ ~KrServices(){}
+
+ static bool cmdExist(TQString cmdName);
+ static TQString detectFullPathName( TQString name );
+ static TQString fullPathName( TQString name, TQString confName = TQString() );
+ static TQStringList separateArgs( TQString args );
+ static TQString registerdProtocol(TQString mimetype);
+ static void clearProtocolCache();
+ static bool fileToStringList(TQTextStream *stream, TQStringList& target, bool keepEmptyLines=false);
+ static TQString quote( TQString name );
+ static TQStringList quote( const TQStringList& names );
+
+protected:
+ static TQString escape( TQString name );
+
+private:
+ static TQMap<TQString,TQString>* 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 TDEProcess {
+ TQ_OBJECT
+
+public:
+ KEasyProcess(TQObject *parent, const char *name=0);
+ KEasyProcess();
+ virtual ~KEasyProcess() {}
+
+ const TQString& getStdout() const { return _stdout; }
+ const TQString& getStderr() const { return _stderr; }
+
+protected slots:
+ void receivedStdout (TDEProcess *proc, char *buffer, int buflen);
+ void receivedStderr (TDEProcess *proc, char *buffer, int buflen);
+ void init();
+
+private:
+ TQString _stdout, _stderr;
+};
+
+#endif
diff --git a/src/app/krslots.cpp b/src/app/krslots.cpp
new file mode 100644
index 0000000..b6d45c6
--- /dev/null
+++ b/src/app/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 <tqdir.h>
+#include <tqpoint.h>
+#include <tqstringlist.h>
+#include <tqprogressdialog.h>
+#include <tqlistview.h>
+#include <tqpixmapcache.h>
+// TDE includes
+#include <tdelocale.h>
+#include <kprocess.h>
+#include <tdemessagebox.h>
+#include <klineeditdlg.h>
+#include <kdirnotify_stub.h>
+#include <tdeio/netaccess.h>
+#include <kedittoolbar.h>
+#include <tdeversion.h>
+#include <tdecmdlineargs.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(TQString filename) {
+ TQString mailProg;
+ TQStringList 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)+"\"" << TQString() +
+ "--attach "+"\"" + filename + "\"";
+ }
+
+ if (!proc.start(TDEProcess::DontCare))
+ KMessageBox::error(0,i18n("Error executing ")+mailProg+" !");
+ else proc.detach();
+}
+
+void KRslots::compareContent() {
+ TQStringList lstLeft, lstRight;
+ TQStringList* 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 TDEProcess
+{
+ TQString tmp1, tmp2;
+
+public:
+ KrProcess( TQString in1, TQString in2 )
+ {
+ tmp1 = in1;
+ tmp2 = in2;
+ }
+
+ virtual void processHasExited (int )
+ {
+ if( !tmp1.isEmpty() )
+ TDEIO::NetAccess::removeTempFile( tmp1 );
+ if( !tmp2.isEmpty() )
+ TDEIO::NetAccess::removeTempFile( tmp2 );
+ delete this;
+ }
+};
+
+void KRslots::compareContent( KURL url1, KURL url2 )
+{
+ TQString diffProg;
+ TQStringList 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;
+ }
+
+ TQString tmp1 = TQString(), tmp2 = TQString();
+
+ if (!url1.isLocalFile()) {
+ if( !TDEIO::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( !TDEIO::NetAccess::download( url2, tmp2, 0 ) ){
+ KMessageBox::sorry(krApp,i18n("Krusader is unable to download: ")+url2.fileName());
+ if( tmp1 != url1.path() )
+ TDEIO::NetAccess::removeTempFile( tmp1 );
+ return;
+ }
+ } else tmp2 = url2.path();
+
+ KrProcess *p = new KrProcess( tmp1 != url1.path() ? tmp1 : TQString(),
+ tmp2 != url2.path() ? tmp2 : TQString() );
+ *p << diffProg << tmp1 << tmp2;
+ if (!p->start(TDEProcess::DontCare))
+ KMessageBox::error(0,i18n("Error executing ")+diffProg+" !");
+}
+
+void KRslots::rightclickMenu() {
+ if( dynamic_cast<KrDetailedView*>(ACTIVE_PANEL->view) != 0 )
+ {
+ TQListViewItem * currentItem = dynamic_cast<TQListViewItem*>(ACTIVE_PANEL->view->getCurrentKrViewItem());
+ if( currentItem )
+ {
+ ACTIVE_PANEL->popRightClickMenu(
+ ACTIVE_PANEL->mapToGlobal(
+ dynamic_cast<TDEListView*>(ACTIVE_PANEL->view)->itemRect( currentItem ).topLeft()
+ )
+ );
+ }
+ }
+ else if( dynamic_cast<KrBriefView*>(ACTIVE_PANEL->view) != 0 )
+ {
+ TQIconViewItem * currentItem = dynamic_cast<TQIconViewItem*>(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)
+{
+ TQString filename = ACTIVE_PANEL->view->getCurrentItem();
+ if( filename == TQString() )
+ return;
+
+ if( full_path ){
+ TQString 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() ){
+ TQString 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 = TQString( " " ) + filename + TQString( " " );
+ TQKeyEvent keyEvent( TQEvent::KeyPress, 0, -1, 0, filename);
+ TQApplication::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 TQString& 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(TQDir::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 )
+ TQPixmapCache::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(){
+ TQValueList<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!"));
+
+ TQString host=remoteMan::getHost();
+ if (host==TQString()) 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(){
+ TQString save = getcwd(0,0);
+ chdir (TQDir::homeDirPath().local8Bit());
+
+ TDEProcess proc;
+ krConfig->setGroup("General");
+ TQString 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(TDEProcess::DontCare))
+ KMessageBox::sorry(krApp,i18n("Can't open ")+"\""+term+"\"");
+
+ chdir(save.local8Bit());
+}
+
+void KRslots::sysInfo(){
+ TDEProcess proc;
+ proc << "tdecmshell" << "System/ksysctrl";
+ if (!proc.start(TDEProcess::DontCare)){
+ KMessageBox::sorry(krApp,i18n("Can't find \"KsysCtrl\". Please install the TDE admin package"));
+ }
+}
+
+void KRslots::multiRename(){
+ TQStringList 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;
+ }
+ TQString pathToRename = lst[i+1];
+
+ TQStringList 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( TQFileInfo((*u).path()).isDir() ) proc << "-r";
+ proc << "\"" + (*u).path() + "\""; // patch thanks to Tobias Vogele
+ }
+
+ proc.start(TDEProcess::DontCare);
+ delete urls;
+}
+
+void KRslots::rootKrusader()
+{
+ if( !KrServices::cmdExist( "krusader" ) || !KrServices::cmdExist( "tdesu" ) )
+ {
+ KMessageBox::sorry( krApp, i18n( "Can't start root mode krusader, because krusader or tdesu is missing from the path. Please configure the dependencies in Konfigurator!" ) );
+ return;
+ }
+
+ KShellProcess proc;
+ proc << KrServices::fullPathName( "tdesu" ) << TQString("'") + KrServices::fullPathName( "krusader" ) +
+ " --left=\"" +MAIN_VIEW->left->func->files()->vfs_getOrigin().url() +
+ "\" --right=\""+MAIN_VIEW->right->func->files()->vfs_getOrigin().url() + "\"'";
+
+ proc.start(TDEProcess::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(TDEGlobalSettings::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()
+{
+ TQStringList list;
+ TQString 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() == TQDialog::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(){
+ TQStringList list;
+ KURL baseURL;
+ bool unixStyle = false;
+ bool windowsStyle = false;
+ TQString commonName = TQString();
+ 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 ( TQStringList::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 )
+ {
+ TQString name = url.fileName();
+ int extPos = name.findRev( '.' );
+ TQString 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
+ {
+ TQString shortName = *it;
+ TQChar 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() )
+ {
+ TQString shorter = commonName.left( commonName.length() - 1 );
+ TQString 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( TQStringList 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();
+ }
+ TDEConfigGroup 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/src/app/krslots.h b/src/app/krslots.h
new file mode 100644
index 0000000..7b7b75f
--- /dev/null
+++ b/src/app/krslots.h
@@ -0,0 +1,188 @@
+/***************************************************************************
+ 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 <tqobject.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 TQObject {
+ TQ_OBJECT
+
+
+ public:
+ enum compareMode { full } ;
+
+ KRslots(TQObject *parent): TQObject(parent, "KRslots") {}
+ ~KRslots() {}
+
+ public slots:
+ void createChecksum();
+ void matchChecksum();
+ void sendFileByEmail( TQString 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 TQString &, 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( TQStringList selected = TQStringList() );
+ 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( TQString p ) { MAIN_VIEW->slotCurrentChanged( p ); }
+ void slotSetActivePanel( ListPanel *p ) { MAIN_VIEW->slotSetActivePanel( p ); }
+
+
+ void jsConsole();
+};
+
+#endif
diff --git a/src/app/krusader.cpp b/src/app/krusader.cpp
new file mode 100644
index 0000000..b16f879
--- /dev/null
+++ b/src/app/krusader.cpp
@@ -0,0 +1,1263 @@
+/***************************************************************************
+ 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
+// TDE includes
+#include <tdemessagebox.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+#include <ksystemtray.h>
+#include <tdemenubar.h>
+#include <tdeapplication.h>
+#include <tdecmdlineargs.h>
+#include <tdeglobal.h>
+#include <tdelocale.h>
+#include <tdeaccelmanager.h>
+#include <twin.h>
+
+#if KDE_IS_VERSION(3,2,0)
+#include <tdeactionclasses.h>
+#endif
+
+#include <tdeversion.h>
+// TQt includes
+#include <tqpixmap.h>
+#include <tqstringlist.h>
+#include <tqdir.h>
+#include <tqprinter.h>
+#include <tqprogressdialog.h>
+#include <tqvaluelist.h>
+#include <tqwhatsthis.h>
+#include <tqwidgetlist.h>
+#include <tqdatetime.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;
+TDEAction *Krusader::actProperties = 0;
+TDEAction *Krusader::actPack = 0;
+TDEAction *Krusader::actUnpack = 0;
+TDEAction *Krusader::actTest = 0;
+TDEAction *Krusader::actCopy = 0;
+TDEAction *Krusader::actPaste = 0;
+TDEAction *Krusader::actCompare = 0;
+TDEAction *Krusader::actCalculate = 0;
+TDEAction *Krusader::actCreateChecksum = 0;
+TDEAction *Krusader::actMatchChecksum = 0;
+TDEAction *Krusader::actSelect = 0;
+TDEAction *Krusader::actSelectAll = 0;
+TDEAction *Krusader::actUnselect = 0;
+TDEAction *Krusader::actUnselectAll = 0;
+TDEAction *Krusader::actInvert = 0;
+TDEAction *Krusader::actCompDirs = 0;
+TDEAction *Krusader::actSync = 0;
+TDEAction *Krusader::actDiskUsage = 0;
+TDEAction *Krusader::actHomeTerminal = 0;
+TDEAction *Krusader::actFTPConnect = 0;
+TDEAction *Krusader::actFTPNewConnect = 0;
+TDEAction *Krusader::actFTPDisconnect = 0;
+TDEAction *Krusader::actProfiles = 0;
+TDEAction *Krusader::actMultiRename = 0;
+TDEAction *Krusader::actAllFilter = 0;
+TDEAction *Krusader::actExecFilter = 0;
+TDEAction *Krusader::actCustomFilter = 0;
+TDEAction *Krusader::actMountMan = 0;
+TDEAction *Krusader::actNewTool = 0;
+TDEAction *Krusader::actKonfigurator = 0;
+TDEAction *Krusader::actToolsSetup = 0;
+TDEAction *Krusader::actSwapPanels = 0;
+TDEAction *Krusader::actSwapSides = 0;
+TDEAction *Krusader::actBack = 0;
+TDEAction *Krusader::actRoot = 0;
+TDEAction *Krusader::actFind = 0;
+TDEAction *Krusader::actLocate = 0;
+TDEAction *Krusader::actSwitchFullScreenTE = 0;
+//TDEAction *Krusader::actAddBookmark = 0;
+TDEAction *Krusader::actSavePosition = 0;
+TDEAction *Krusader::actSelectColorMask = 0;
+TDEAction *Krusader::actOpenLeftBm = 0;
+TDEAction *Krusader::actOpenRightBm = 0;
+TDEAction *Krusader::actDirUp = 0;
+TDEAction *Krusader::actCmdlinePopup = 0;
+TDEAction *Krusader::actNewTab = 0;
+TDEAction *Krusader::actDupTab = 0;
+TDEAction *Krusader::actCloseTab = 0;
+TDEAction *Krusader::actNextTab = 0;
+TDEAction *Krusader::actPreviousTab = 0;
+TDEAction *Krusader::actSplit = 0;
+TDEAction *Krusader::actCombine = 0;
+TDEAction *Krusader::actUserMenu = 0;
+TDEAction *Krusader::actManageUseractions = 0;
+TDEAction *Krusader::actSyncDirs = 0;
+TDEAction *Krusader::actSyncBrowse = 0;
+TDEAction *Krusader::actF2 = 0;
+TDEAction *Krusader::actF3 = 0;
+TDEAction *Krusader::actF4 = 0;
+TDEAction *Krusader::actF5 = 0;
+TDEAction *Krusader::actF6 = 0;
+TDEAction *Krusader::actF7 = 0;
+TDEAction *Krusader::actF8 = 0;
+TDEAction *Krusader::actF9 = 0;
+TDEAction *Krusader::actF10 = 0;
+TDEAction *Krusader::actLocationBar = 0;
+TDEAction *Krusader::actPopularUrls = 0;
+TDEAction *Krusader::actJumpBack = 0;
+TDEAction *Krusader::actSetJumpBack = 0;
+TDEAction *Krusader::actDetailedView = 0;
+TDEAction *Krusader::actBriefView = 0;
+
+TDEToggleAction *Krusader::actToggleTerminal = 0;
+TDEToggleAction *Krusader::actVerticalMode = 0;
+TDERadioAction *Krusader::actSelectNewerAndSingle = 0;
+TDERadioAction *Krusader::actSelectSingle = 0;
+TDERadioAction *Krusader::actSelectNewer = 0;
+TDERadioAction *Krusader::actSelectDifferentAndSingle = 0;
+TDERadioAction *Krusader::actSelectDifferent = 0;
+TDERadioAction **Krusader::compareArray[] = {&actSelectNewerAndSingle, &actSelectNewer, &actSelectSingle,
+ &actSelectDifferentAndSingle, &actSelectDifferent, 0};
+TDERadioAction *Krusader::actExecStartAndForget = 0;
+TDERadioAction *Krusader::actExecCollectSeparate = 0;
+TDERadioAction *Krusader::actExecCollectTogether = 0;
+TDERadioAction *Krusader::actExecTerminalExternal = 0;
+TDERadioAction *Krusader::actExecTerminalEmbedded = 0;
+TDERadioAction **Krusader::execTypeArray[] =
+ {&actExecStartAndForget, &actExecCollectSeparate, &actExecCollectTogether,
+ &actExecTerminalExternal, &actExecTerminalEmbedded, 0};
+
+TDEPopupMenu *Krusader::userActionMenu = 0;
+UserAction *Krusader::userAction = 0;
+UserMenu *Krusader::userMenu = 0;
+KrBookmarkHandler *Krusader::bookman = 0;
+//TQTextOStream *Krusader::_krOut = TQTextOStream(::stdout);
+
+#ifdef __KJSEMBED__
+KrJS *Krusader::js = 0;
+TDEAction *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|TQt::WStyle_ContextHelp),
+ DCOPObject("Krusader-Interface"), status(NULL), sysTray( 0 ), isStarting( true ), isExiting( false ), directExit( false ) {
+ // parse command line arguments
+ TDECmdLineArgs * args = TDECmdLineArgs::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();
+
+ TQString message;
+ switch ( config->getConfigState() ) {
+ case TDEConfigBase::NoAccess :
+ message = "Krusader's configuration file can't be found. Default values will be used.";
+ break;
+ case TDEConfigBase::ReadOnly :
+ message = "Krusader's configuration file is in READ ONLY mode (why is that!?) Changed values will not be saved";
+ break;
+ case TDEConfigBase::ReadWrite :
+ message = "";
+ break;
+ }
+ if ( message != "" ) {
+ KMessageBox::error( krApp, message );
+ }
+
+ // create an icon loader
+ iconLoader = TDEGlobal::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" );
+ TQString defaultType = krConfig->readEntry( "Default Panel Type", _DefaultPanelType );
+
+ krConfig->setGroup( "Startup" );
+ TQStringList leftTabs = krConfig->readPathListEntry( "Left Tab Bar" );
+ TQStringList rightTabs = krConfig->readPathListEntry( "Right Tab Bar" );
+ TQStringList leftTabTypes = krConfig->readListEntry( "Left Tab Bar Types" );
+ TQStringList rightTabTypes = krConfig->readListEntry( "Right Tab Bar Types" );
+ TQValueList<int> leftTabProps = krConfig->readIntListEntry( "Left Tab Bar Props" );
+ TQValueList<int> rightTabProps = krConfig->readIntListEntry( "Right Tab Bar Props" );
+ int leftActiveTab = krConfig->readNumEntry( "Left Active Tab", 0 );
+ int rightActiveTab = krConfig->readNumEntry( "Right Active Tab", 0 );
+ TQString startProfile = krConfig->readEntry("Starter Profile Name", TQString() );
+ bool leftActive = krConfig->readBoolEntry( "Left Side Is Active", false );
+
+ // get command-line arguments
+ if ( args->isSet( "left" ) ) {
+ leftTabs = TQStringList::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 ] = TQDir::currentDirPath() + "/" + leftTabs[ i ];
+ }
+ startProfile = TQString();
+ }
+ if ( args->isSet( "right" ) ) {
+ rightTabs = TQStringList::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 ] = TQDir::currentDirPath() + "/" + rightTabs[ i ];
+ }
+ startProfile = TQString();
+ }
+
+ 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( TQDir::homeDirPath() );
+ leftTabTypes.push_back( defaultType );
+ leftTabProps.push_back( 0 );
+ }
+ if( rightTabs.count() == 0 )
+ {
+ rightTabs.push_back( TQDir::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 );
+ TQWhatsThis::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(), TDEIcon::Panel, 22 ) );
+ sysTray->hide();
+
+ connect( sysTray, TQ_SIGNAL( quitSelected() ), this, TQ_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
+ //TDEAcceleratorManager::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
+ TQString 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 ( !TQDir::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);
+
+ // Check whether Krusader is run for the first time under a new TDE version.
+ TQString lastVersion = config->readEntry("Last version");
+ if (lastVersion != TDE_VERSION_STRING)
+ {
+ config->writeEntry("Last version", TDE_VERSION_STRING);
+ if (!retval)
+ {
+ KMessageBox::information(krApp, i18n( "<qt><b>Welcome to Krusader!</b><p>As this is your first run "
+ "under TDE " TDE_VERSION_STRING ", your machine will now be checked for external applications updates. "
+ "Then the Konfigurator will be launched where you can customize Krusader to your needs.</p></qt>" ) );
+ }
+ retval = true;
+ }
+
+ config->sync();
+ return retval;
+}
+
+void Krusader::statusBarUpdate( TQString& 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 TDE default status bar instead of KrusaderStatus.
+ statusBar() ->message( mess, 5000 );
+}
+
+void Krusader::showEvent ( TQShowEvent * ) {
+ 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 ( TQHideEvent *e ) {
+ if( isExiting ) {
+ KParts::MainWindow::hideEvent( e );
+ sysTray->hide();
+ return;
+ }
+ TQString lastGroup = config->group();
+ config->setGroup( "Look&Feel" );
+ bool showTrayIcon = krConfig->readBoolEntry( "Minimize To Tray", _MinimizeToTray );
+ config->setGroup ( lastGroup );
+
+ bool isModalTopWidget = false;
+
+ TQWidget *actWnd = tqApp->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 ( TQMoveEvent *e ) {
+ oldPos = e->oldPos();
+ KParts::MainWindow::moveEvent( e );
+}
+
+void Krusader::resizeEvent ( TQResizeEvent *e ) {
+ oldSize = e->oldSize();
+ KParts::MainWindow::resizeEvent( e );
+}
+
+void Krusader::setupAccels() {
+ accels = new TDEAccel( this );
+ // SHIFT+F3
+ accels->insert( "F3_ViewDlg", i18n( "F3 View Dialog" ), TQString(),
+ SHIFT + Key_F3, SLOTS, TQ_SLOT( viewDlg() ) );
+ // Tab
+ accels->insert( "Tab-Switch panel", i18n( "Tab: switch panel" ), TQString(),
+ Key_Tab, mainView, TQ_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 TDEAction(i18n("S&yncronize Dirs"), 0, this, 0, actionCollection(), "sync dirs");
+ //actNewTool = 0;//new TDEAction(i18n("&Add a new tool"), 0, this, 0, actionCollection(), "add tool");
+ //actToolsSetup = 0;//new TDEAction(i18n("&Tools Menu Setup"), 0, 0, this, 0, actionCollection(), "tools setup");
+ //KStdAction::print(SLOTS, 0,actionCollection(),"std_print");
+ //KStdAction::showMenubar( SLOTS, TQ_SLOT( showMenubar() ), actionCollection(), "std_menubar" );
+
+
+ // second, the TDE standard action
+ //KStdAction::up( SLOTS, TQ_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, TQ_SLOT( home() ), actionCollection(), "std_home" )->setText( i18n("Home") ); /*->setShortcut(Key_QuoteLeft);*/
+ new TDEAction( i18n( "&Reload" ), "reload", CTRL + Key_R, SLOTS, TQ_SLOT( refresh() ), actionCollection(), "std_redisplay" );
+ actShowToolBar = KStdAction::showToolbar( SLOTS, TQ_SLOT( toggleToolbar() ), actionCollection(), "std_toolbar" );
+ new TDEToggleAction( i18n("Show Actions Toolbar"), 0, SLOTS, TQ_SLOT( toggleActionsToolbar() ),
+ actionCollection(), "toggle actions toolbar" );
+ actShowStatusBar = KStdAction::showStatusbar( SLOTS, TQ_SLOT( toggleStatusbar() ), actionCollection(), "std_statusbar" );
+ KStdAction::quit( this, TQ_SLOT( slotClose() ), actionCollection(), "std_quit" );
+ KStdAction::configureToolbars( SLOTS, TQ_SLOT( configToolbar() ), actionCollection(), "std_config_toolbar" );
+ KStdAction::keyBindings( SLOTS, TQ_SLOT( configKeys() ), actionCollection(), "std_config_keys" );
+
+ KStdAction::cut( SLOTS, TQ_SLOT( cut() ), actionCollection(), "std_cut" )->setText( i18n("Cut to Clipboard") );
+ (actCopy = KStdAction::copy( SLOTS, TQ_SLOT( copy() ), actionCollection(), "std_copy" ))->setText( i18n("Copy to Clipboard") );
+ (actPaste = KStdAction::paste( SLOTS, TQ_SLOT( paste() ), actionCollection(), "std_paste" ))->setText( i18n("Paste from Clipboard") );
+
+ // the toggle actions
+ actToggleFnkeys = new TDEToggleAction( i18n( "Show &FN Keys Bar" ), 0, SLOTS,
+ TQ_SLOT( toggleFnkeys() ), actionCollection(), "toggle fn bar" );
+ actToggleFnkeys->setChecked( true );
+ actToggleCmdline = new TDEToggleAction( i18n( "Show &Command Line" ), 0, SLOTS,
+ TQ_SLOT( toggleCmdline() ), actionCollection(), "toggle command line" );
+ actToggleCmdline->setChecked( true );
+ actToggleTerminal = new TDEToggleAction( i18n( "Show Terminal &Emulator" ), ALT + CTRL + Key_T, SLOTS,
+ TQ_SLOT( toggleTerminal() ), actionCollection(), "toggle terminal emulator" );
+ actToggleTerminal->setChecked( false );
+
+ actDetailedView = new TDEAction( i18n( "&Detailed View" ), ALT + SHIFT + Key_D, SLOTS,
+ TQ_SLOT( setDetailedView() ), actionCollection(), "detailed_view" );
+
+ actBriefView = new TDEAction( i18n( "&Brief View" ), ALT + SHIFT + Key_B, SLOTS,
+ TQ_SLOT( setBriefView() ), actionCollection(), "brief_view" );
+
+ actToggleHidden = new TDEToggleAction( i18n( "Show &Hidden Files" ), CTRL + Key_Period, SLOTS,
+ TQ_SLOT( toggleHidden() ), actionCollection(), "toggle hidden files" );
+ actSwapPanels = new TDEAction( i18n( "S&wap Panels" ), CTRL + Key_U, SLOTS,
+ TQ_SLOT( swapPanels() ), actionCollection(), "swap panels" );
+ actSwapSides = new TDEAction( i18n( "Sw&ap Sides" ), CTRL + SHIFT + Key_U, SLOTS,
+ TQ_SLOT( toggleSwapSides() ), actionCollection(), "toggle swap sides" );
+ krConfig->setGroup( "Look&Feel" );
+ actToggleHidden->setChecked( krConfig->readBoolEntry( "Show Hidden", _ShowHidden ) );
+
+ // and then the DONE actions
+ actCmdlinePopup = new TDEAction( i18n( "popup cmdline" ), 0, CTRL + Key_Slash, SLOTS,
+ TQ_SLOT( cmdlinePopup() ), actionCollection(), "cmdline popup" );
+ /* Shortcut disabled because of the Terminal Emulator bug. */
+ actDirUp = new TDEAction( i18n( "Up" ), "go-up", CTRL+Key_PageUp /*Key_Backspace*/, SLOTS, TQ_SLOT( dirUp() ), actionCollection(), "dirUp" );
+ new TDEAction( i18n( "&New Text File..." ), "document-new", SHIFT + Key_F4, SLOTS, TQ_SLOT( editDlg() ), actionCollection(), "edit_new_file" );
+ new TDEAction( i18n( "Start &Root Mode Krusader" ), "krusader_root", ALT + Key_K, SLOTS, TQ_SLOT( rootKrusader() ), actionCollection(), "root krusader" );
+
+ actTest = new TDEAction( i18n( "T&est Archive" ), "ark", ALT + Key_E,
+ SLOTS, TQ_SLOT( testArchive() ), actionCollection(), "test archives" );
+ //actFTPConnect = new TDEAction( i18n( "&Net Connections" ), "domtreeviewer", 0,
+ // SLOTS, TQ_SLOT( runRemoteMan() ), actionCollection(), "ftp connect" );
+ actFTPNewConnect = new TDEAction( i18n( "New Net &Connection..." ), "connect_creating", CTRL + Key_N,
+ SLOTS, TQ_SLOT( newFTPconnection() ), actionCollection(), "ftp new connection" );
+ actProfiles = new TDEAction( i18n( "Pro&files" ), "kr_profile", ALT + Key_L,
+ MAIN_VIEW, TQ_SLOT( profiles() ), actionCollection(), "profile" );
+ actCalculate = new TDEAction( i18n( "Calculate &Occupied Space" ), "kcalc", 0,
+ SLOTS, TQ_SLOT( calcSpace() ), actionCollection(), "calculate" );
+ actCreateChecksum = new TDEAction( i18n( "Create Checksum..." ), "application-octet-stream", 0,
+ SLOTS, TQ_SLOT( createChecksum() ), actionCollection(), "create checksum" );
+ actMatchChecksum = new TDEAction( i18n( "Verify Checksum..." ), "match_checksum", 0,
+ SLOTS, TQ_SLOT( matchChecksum() ), actionCollection(), "match checksum" );
+ actProperties = new TDEAction( i18n( "&Properties..." ), "edit", ALT+Key_Enter,
+ SLOTS, TQ_SLOT( properties() ), actionCollection(), "properties" );
+ actPack = new TDEAction( i18n( "Pac&k..." ), "kr_arc_pack", ALT + Key_P,
+ SLOTS, TQ_SLOT( slotPack() ), actionCollection(), "pack" );
+ actUnpack = new TDEAction( i18n( "&Unpack..." ), "kr_arc_unpack", ALT + Key_U,
+ SLOTS, TQ_SLOT( slotUnpack() ), actionCollection() , "unpack" );
+ actSplit = new TDEAction( i18n( "Sp&lit File..." ), "kr_split", CTRL + Key_P,
+ SLOTS, TQ_SLOT( slotSplit() ), actionCollection(), "split" );
+ actCombine = new TDEAction( i18n( "Com&bine Files..." ), "kr_combine", CTRL + Key_B,
+ SLOTS, TQ_SLOT( slotCombine() ), actionCollection() , "combine" );
+ actSelect = new TDEAction( i18n( "Select &Group..." ), "kr_select", CTRL + Key_Plus,
+ SLOTS, TQ_SLOT( markGroup() ), actionCollection(), "select group" );
+ actSelectAll = new TDEAction( i18n( "&Select All" ), "kr_selectall", ALT + Key_Plus,
+ SLOTS, TQ_SLOT( markAll() ), actionCollection(), "select all" );
+ actUnselect = new TDEAction( i18n( "&Unselect Group..." ), "kr_unselect", CTRL + Key_Minus,
+ SLOTS, TQ_SLOT( unmarkGroup() ), actionCollection(), "unselect group" );
+ actUnselectAll = new TDEAction( i18n( "U&nselect All" ), "kr_unselectall", ALT + Key_Minus,
+ SLOTS, TQ_SLOT( unmarkAll() ), actionCollection(), "unselect all" );
+ actInvert = new TDEAction( i18n( "&Invert Selection" ), "kr_invert", ALT + Key_Asterisk,
+ SLOTS, TQ_SLOT( invert() ), actionCollection(), "invert" );
+ actCompDirs = new TDEAction( i18n( "&Compare Directories" ), "view_left_right", ALT + Key_C,
+ SLOTS, TQ_SLOT( compareDirs() ), actionCollection(), "compare dirs" );
+ actSelectNewerAndSingle = new TDERadioAction( i18n( "&Select Newer and Single" ), 0,
+ SLOTS, TQ_SLOT( compareSetup() ), actionCollection(), "select_newer_and_single" );
+ actSelectNewer = new TDERadioAction( i18n( "Select &Newer" ), 0,
+ SLOTS, TQ_SLOT( compareSetup() ), actionCollection(), "select_newer" );
+ actSelectSingle = new TDERadioAction( i18n( "Select &Single" ), 0,
+ SLOTS, TQ_SLOT( compareSetup() ), actionCollection(), "select_single" );
+ actSelectDifferentAndSingle = new TDERadioAction( i18n( "Select Different &and Single" ), 0,
+ SLOTS, TQ_SLOT( compareSetup() ), actionCollection(), "select_different_and_single" );
+ actSelectDifferent = new TDERadioAction( i18n( "Select &Different" ), 0,
+ SLOTS, TQ_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( TDERadioAction ** ) ) -1 )
+ (*compareArray[ compareMode ])->setChecked( true );
+ actExecStartAndForget = new TDERadioAction(
+ i18n( "Start and &Forget" ), 0,
+ SLOTS, TQ_SLOT( execTypeSetup() ),
+ actionCollection(), "exec_start_and_forget" );
+ actExecCollectSeparate = new TDERadioAction(
+ i18n( "Display &Separated Standard and Error Output" ), 0,
+ SLOTS, TQ_SLOT( execTypeSetup() ),
+ actionCollection(), "exec_collect_separate" );
+ actExecCollectTogether = new TDERadioAction(
+ i18n( "Display &Mixed Standard and Error Output" ), 0,
+ SLOTS, TQ_SLOT( execTypeSetup() ),
+ actionCollection(), "exec_collect_together" );
+ actExecTerminalExternal = new TDERadioAction(
+ i18n( "Start in &New Terminal" ), 0,
+ SLOTS, TQ_SLOT( execTypeSetup() ),
+ actionCollection(), "exec_terminal_external" );
+ actExecTerminalEmbedded = new TDERadioAction(
+ i18n( "Send to &Embedded Terminal Emulator" ), 0,
+ SLOTS, TQ_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( TDERadioAction ** ) ) -1 )
+ (*execTypeArray[ cmdExecMode ])->setChecked( true );
+
+
+ actHomeTerminal = new TDEAction( i18n( "Start &Terminal" ), "terminal", 0,
+ SLOTS, TQ_SLOT( homeTerminal() ), actionCollection(), "terminal@home" );
+ actFTPDisconnect = new TDEAction( i18n( "Disconnect &from Net" ), "kr_ftp_disconnect", SHIFT + CTRL + Key_F,
+ SLOTS, TQ_SLOT( FTPDisconnect() ), actionCollection(), "ftp disconnect" );
+#if KDE_IS_VERSION(3,2,0) /* new mountman feature is available in kde 3.2 only! */
+ actMountMan = new TDEToolBarPopupAction( i18n( "&MountMan..." ), "kr_mountman", ALT + Key_Slash,
+ SLOTS, TQ_SLOT( runMountMan() ), actionCollection(), "mountman" );
+ connect( ( ( TDEToolBarPopupAction* ) actMountMan ) ->popupMenu(), TQ_SIGNAL( aboutToShow() ),
+ mountMan, TQ_SLOT( quickList() ) );
+#else
+ actMountMan = new TDEAction( i18n( "&MountMan..." ), "kr_mountman", ALT + Key_Slash,
+ SLOTS, TQ_SLOT( runMountMan() ), actionCollection(), "mountman" );
+#endif /* KDE 3.2 */
+
+ actFind = new TDEAction( i18n( "&Search..." ), "filefind", CTRL + Key_S,
+ SLOTS, TQ_SLOT( search() ), actionCollection(), "find" );
+ actLocate = new TDEAction( i18n( "&Locate..." ), "edit-find", SHIFT+CTRL + Key_L,
+ SLOTS, TQ_SLOT( locate() ), actionCollection(), "locate" );
+ actSyncDirs = new TDEAction( i18n( "Synchronize &Directories..." ), "kr_syncdirs", CTRL + Key_Y,
+ SLOTS, TQ_SLOT( slotSynchronizeDirs() ), actionCollection(), "sync dirs" );
+ actSyncBrowse = new TDEAction( i18n( "S&ynchron Directory Changes" ), "kr_syncbrowse_off", ALT + Key_Y,
+ SLOTS, TQ_SLOT( slotSyncBrowse() ), actionCollection(), "sync browse" );
+ actDiskUsage = new TDEAction( i18n( "D&isk Usage..." ), "kr_diskusage", ALT + Key_D,
+ SLOTS, TQ_SLOT( slotDiskUsage() ), actionCollection(), "disk usage" );
+ actKonfigurator = new TDEAction( i18n( "Configure &Krusader..." ), "configure", 0,
+ SLOTS, TQ_SLOT( startKonfigurator() ), actionCollection(), "konfigurator" );
+ actBack = new TDEAction( i18n( "Back" ), "back", 0,
+ SLOTS, TQ_SLOT( back() ), actionCollection(), "back" );
+ actRoot = new TDEAction( i18n( "Root" ), "go-top", CTRL + Key_Backspace,
+ SLOTS, TQ_SLOT( root() ), actionCollection(), "root" );
+ actSavePosition = new TDEAction( i18n( "Save &Position" ), 0,
+ krApp, TQ_SLOT( savePosition() ), actionCollection(), "save position" );
+ actAllFilter = new TDEAction( i18n( "&All Files" ), SHIFT + Key_F10,
+ SLOTS, TQ_SLOT( allFilter() ), actionCollection(), "all files" );
+ //actExecFilter = new TDEAction( i18n( "&Executables" ), SHIFT + Key_F11,
+ // SLOTS, TQ_SLOT( execFilter() ), actionCollection(), "exec files" );
+ actCustomFilter = new TDEAction( i18n( "&Custom" ), SHIFT + Key_F12,
+ SLOTS, TQ_SLOT( customFilter() ), actionCollection(), "custom files" );
+ actCompare = new TDEAction( i18n( "Compare b&y Content..." ), "application-vnd.tde.tdemultiple", 0,
+ SLOTS, TQ_SLOT( compareContent() ), actionCollection(), "compare" );
+ actMultiRename = new TDEAction( i18n( "Multi &Rename..." ), "edit_rename", SHIFT + Key_F9,
+ SLOTS, TQ_SLOT( multiRename() ), actionCollection(), "multirename" );
+ new TDEAction( i18n( "Right-click Menu" ), Key_Menu,
+ SLOTS, TQ_SLOT( rightclickMenu() ), actionCollection(), "rightclick menu" );
+ new TDEAction( i18n( "Right Bookmarks" ), ALT + Key_Right,
+ SLOTS, TQ_SLOT( openRightBookmarks() ), actionCollection(), "right bookmarks" );
+ new TDEAction( i18n( "Left Bookmarks" ), ALT + Key_Left,
+ SLOTS, TQ_SLOT( openLeftBookmarks() ), actionCollection(), "left bookmarks" );
+ new TDEAction( i18n( "Bookmarks" ), CTRL + Key_D,
+ SLOTS, TQ_SLOT( openBookmarks() ), actionCollection(), "bookmarks" );
+ new TDEAction( i18n( "Bookmark Current" ), CTRL + SHIFT + Key_D,
+ SLOTS, TQ_SLOT( bookmarkCurrent() ), actionCollection(), "bookmark current" );
+ new TDEAction( i18n( "History" ), CTRL + Key_H,
+ SLOTS, TQ_SLOT( openHistory() ), actionCollection(), "history" );
+ new TDEAction( i18n( "Sync Panels" ), ALT + Key_O,
+ SLOTS, TQ_SLOT( syncPanels() ), actionCollection(), "sync panels");
+ new TDEAction( i18n( "Left History" ), ALT + CTRL + Key_Left,
+ SLOTS, TQ_SLOT( openLeftHistory() ), actionCollection(), "left history" );
+ new TDEAction( i18n( "Right History" ), ALT + CTRL + Key_Right,
+ SLOTS, TQ_SLOT( openRightHistory() ), actionCollection(), "right history" );
+ new TDEAction( i18n( "Media" ), CTRL + Key_M,
+ SLOTS, TQ_SLOT( openMedia() ), actionCollection(), "media" );
+ new TDEAction( i18n( "Left Media" ), CTRL + SHIFT + Key_Left,
+ SLOTS, TQ_SLOT( openLeftMedia() ), actionCollection(), "left media" );
+ new TDEAction( i18n( "Right Media" ), CTRL + SHIFT + Key_Right,
+ SLOTS, TQ_SLOT( openRightMedia() ), actionCollection(), "right media" );
+ new TDEAction( i18n( "New Symlink..." ), CTRL + ALT + Key_S,
+ SLOTS, TQ_SLOT( newSymlink() ), actionCollection(), "new symlink");
+ new TDEToggleAction( i18n( "Toggle Popup Panel" ), ALT + Key_Down, SLOTS,
+ TQ_SLOT( togglePopupPanel() ), actionCollection(), "toggle popup panel" );
+ actVerticalMode = new TDEToggleAction( i18n( "Vertical Mode" ), "view_top_bottom", ALT + CTRL + Key_R, MAIN_VIEW,
+ TQ_SLOT( toggleVerticalMode() ), actionCollection(), "toggle vertical mode" );
+ actNewTab = new TDEAction( i18n( "New Tab" ), "tab_new", ALT + CTRL + Key_N, SLOTS,
+ TQ_SLOT( newTab() ), actionCollection(), "new tab" );
+ actDupTab = new TDEAction( i18n( "Duplicate Current Tab" ), "tab_duplicate", ALT + CTRL + SHIFT + Key_N, SLOTS,
+ TQ_SLOT( duplicateTab() ), actionCollection(), "duplicate tab" );
+ actCloseTab = new TDEAction( i18n( "Close Current Tab" ), "tab_remove", CTRL + Key_W, SLOTS,
+ TQ_SLOT( closeTab() ), actionCollection(), "close tab" );
+ actNextTab = new TDEAction( i18n( "Next Tab" ), SHIFT + Key_Right, SLOTS,
+ TQ_SLOT( nextTab() ), actionCollection(), "next tab" );
+ actPreviousTab = new TDEAction( i18n( "Previous Tab" ), SHIFT + Key_Left, SLOTS,
+ TQ_SLOT( previousTab() ), actionCollection(), "previous tab" );
+/*
+ actUserMenu = new TDEAction( i18n( "User Menu" ), ALT + Key_QuoteLeft, SLOTS,
+ TQ_SLOT( userMenu() ), actionCollection(), "user menu" );
+*/
+ actManageUseractions = new TDEAction( i18n( "Manage User Actions..." ), 0, SLOTS,
+ TQ_SLOT( manageUseractions() ), actionCollection(), "manage useractions" );
+ new KrRemoteEncodingMenu(i18n("Select Remote Charset"), "charset", actionCollection(), "changeremoteencoding");
+
+ // setup the Fn keys
+ actF2 = new TDEAction( i18n( "Start Terminal Here" ), "terminal", Key_F2,
+ SLOTS, TQ_SLOT( terminal() ) , actionCollection(), "F2_Terminal" );
+ actF3 = new TDEAction( i18n( "View File" ), Key_F3,
+ SLOTS, TQ_SLOT( view() ) , actionCollection(), "F3_View" );
+ actF4 = new TDEAction( i18n( "Edit File" ), Key_F4,
+ SLOTS, TQ_SLOT( edit() ) , actionCollection(), "F4_Edit" );
+ actF5 = new TDEAction( i18n( "Copy..." ), Key_F5,
+ SLOTS, TQ_SLOT( copyFiles() ) , actionCollection(), "F5_Copy" );
+ actF6 = new TDEAction( i18n( "Move..." ), Key_F6,
+ SLOTS, TQ_SLOT( moveFiles() ) , actionCollection(), "F6_Move" );
+ actF7 = new TDEAction( i18n( "New Directory..." ), "folder-new", Key_F7,
+ SLOTS, TQ_SLOT( mkdir() ) , actionCollection(), "F7_Mkdir" );
+ actF8 = new TDEAction( i18n( "Delete" ), "edit-delete", Key_F8,
+ SLOTS, TQ_SLOT( deleteFiles() ) , actionCollection(), "F8_Delete" );
+ actF9 = new TDEAction( i18n( "Rename" ), Key_F9,
+ SLOTS, TQ_SLOT( rename() ) , actionCollection(), "F9_Rename" );
+ actF10 = new TDEAction( i18n( "Quit" ), Key_F10,
+ this, TQ_SLOT( slotClose() ) , actionCollection(), "F10_Quit" );
+ actPopularUrls = new TDEAction( i18n("Popular URLs..."), CTRL+Key_Z,
+ popularUrls, TQ_SLOT( showDialog() ), actionCollection(), "Popular_Urls");
+ actLocationBar = new TDEAction( i18n("Go to Location Bar"), CTRL+Key_L,
+ SLOTS, TQ_SLOT( slotLocationBar() ), actionCollection(), "location_bar");
+ actJumpBack = new TDEAction( i18n("Jump Back"), "kr_jumpback", CTRL+Key_J,
+ SLOTS, TQ_SLOT( slotJumpBack() ), actionCollection(), "jump_back");
+ actSetJumpBack = new TDEAction( i18n("Set Jump Back Point"), "kr_setjumpback", CTRL+SHIFT+Key_J,
+ SLOTS, TQ_SLOT( slotSetJumpBack() ), actionCollection(), "set_jump_back");
+ actSwitchFullScreenTE = new TDEAction( i18n( "Toggle Fullwidget Terminal Emulator" ), 0, CTRL + Key_F,
+ MAIN_VIEW, TQ_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 TDEAction( i18n( "JavaScript Console..." ), ALT + CTRL + Key_J, SLOTS, TQ_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 ] );
+ TQValueList<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( TDEApplication::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(;;) {
+ TQWidgetList * list = TQApplication::topLevelWidgets();
+ TQWidget *activeModal = TQApplication::activeModalWidget();
+ TQWidget *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( "TQDialog" ) )
+ 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( TDEApplication::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( TQString msg, int count , bool cancel ) {
+ plzWait->startWaiting( msg , count, cancel );
+}
+
+bool Krusader::wasWaitingCancelled() const {
+ return plzWait->wasCancelled();
+}
+
+void Krusader::incProgress( TDEProcess *, 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 = (TDEPopupMenu*) guiFactory()->container( "useractionmenu", this );
+ if ( userActionMenu )
+ userAction->populateMenu( userActionMenu );
+
+ toolBar() ->applySettings( krConfig, "Private" );
+
+ toolBar("actionsToolBar") ->applySettings( krConfig, "Actions Toolbar" );
+ static_cast<TDEToggleAction*>(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
+ TDEConfigGroup grp(krConfig, "Private" );
+ TQValueList<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: TQStringList lst = supportedTools();
+// int i = lst.findIndex("DIFF");
+// if (i!=-1) pathToDiff=lst[i+1];
+TQStringList Krusader::supportedTools() {
+ TQStringList 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;
+}
+
+TQString Krusader::getTempDir() {
+ // try to make krusader temp dir
+ krConfig->setGroup( "General" );
+ TQString tmpDir = krConfig->readEntry( "Temp Directory", _TempDirectory );
+
+ if ( ! TQDir( tmpDir ).exists() ) {
+ for ( int i = 1 ; i != -1 ; i = tmpDir.find( '/', i + 1 ) )
+ TQDir().mkdir( tmpDir.left( i ) );
+ TQDir().mkdir( tmpDir );
+ chmod( tmpDir.local8Bit(), 0777 );
+ }
+
+ // add a secure sub dir under the user UID
+ TQString uid;
+ uid.sprintf( "%d", getuid() );
+ TQDir( tmpDir ).mkdir( uid );
+ tmpDir = tmpDir + "/" + uid + "/";
+ chmod( tmpDir.local8Bit(), S_IRUSR | S_IWUSR | S_IXUSR );
+ // add a random sub dir to use
+ while ( TQDir().exists( tmpDir ) )
+ tmpDir = tmpDir + kapp->randomString( 8 );
+ TQDir().mkdir( tmpDir );
+
+ if ( !TQDir( tmpDir ).isReadable() ) {
+ KMessageBox::error( krApp, "Could not create a temporary directory. Handling of Archives will not be possible until this is fixed." );
+ return TQString();
+ }
+ return tmpDir;
+}
+
+TQString Krusader::getTempFile() {
+ // try to make krusader temp dir
+ krConfig->setGroup( "General" );
+ TQString tmpDir = krConfig->readEntry( "Temp Directory", _TempDirectory );
+
+ if ( ! TQDir( tmpDir ).exists() ) {
+ for ( int i = 1 ; i != -1 ; i = tmpDir.find( '/', i + 1 ) )
+ TQDir().mkdir( tmpDir.left( i ) );
+ TQDir().mkdir( tmpDir );
+ chmod( tmpDir.local8Bit(), 0777 );
+ }
+
+ // add a secure sub dir under the user UID
+ TQString uid;
+ uid.sprintf( "%d", getuid() );
+ TQDir( tmpDir ).mkdir( uid );
+ tmpDir = tmpDir + "/" + uid + "/";
+ chmod( tmpDir.local8Bit(), S_IRUSR | S_IWUSR | S_IXUSR );
+
+ while ( TQDir().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 TQCString &fun, const TQByteArray &/* data */, TQCString &/* replyType */, TQByteArray &/* 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/src/app/krusader.desktop b/src/app/krusader.desktop
new file mode 100644
index 0000000..e471b8c
--- /dev/null
+++ b/src/app/krusader.desktop
@@ -0,0 +1,86 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Krusader
+Exec=krusader -caption "%c" %i %m
+Icon=krusader_user
+Terminal=false
+Type=Application
+X-DocPath=krusader/index.html
+Categories=FileManager;System;Qt;TDE;
+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/src/app/krusader.h b/src/app/krusader.h
new file mode 100644
index 0000000..f2c0b4b
--- /dev/null
+++ b/src/app/krusader.h
@@ -0,0 +1,275 @@
+
+/***************************************************************************
+ 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
+
+// TDE includes
+#include <tdeapplication.h>
+#include <tdeparts/mainwindow.h>
+#include <kstdaction.h>
+#include <tdeaction.h>
+#include <tdeconfig.h>
+#include <tdeaccel.h>
+#include <tqstringlist.h>
+#include <tqtextstream.h>
+#include <kdebug.h>
+#include <dcopobject.h>
+
+#ifdef __KJSEMBED__
+class KrJS;
+#endif
+
+class KrusaderStatus;
+class KRPleaseWaitHandler;
+class KrusaderView;
+class TDEProcess;
+class KRslots;
+class TDEIconLoader;
+class KSystemTray;
+class UserMenu;
+class UserAction;
+class Expander;
+class KMountMan;
+class KrBookmarkHandler;
+class PopularUrls;
+class QueueManager;
+
+//static TQTextOStream krOut(stdout);
+#define krOut kdDebug(50010)
+
+class Krusader : public KParts::MainWindow, public DCOPObject {
+ TQ_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 TQStringList supportedTools(); // find supported tools
+
+ virtual bool process (const TQCString &fun, const TQByteArray &data, TQCString &replyType, TQByteArray &replyData);
+ void moveToTop();
+
+ public slots:
+ // increase the internal progress bar
+ void incProgress( TDEProcess *, char *buffer, int buflen );
+ void statusBarUpdate( TQString& 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 ( TQShowEvent * );
+ void hideEvent ( TQHideEvent * );
+ void moveEvent ( TQMoveEvent * );
+ void resizeEvent ( TQResizeEvent * );
+
+ public:
+ static Krusader *App; // a kApp style pointer
+ KMountMan *mountMan; // krusader's Mount Manager
+ KrusaderView *mainView; // The GUI
+ TDEConfig *config; // allow everyone to access the config
+ TDEIconLoader *iconLoader; // the app's icon loader
+ PopularUrls *popularUrls; // holds a sorted list of the most popular urls visited
+ QueueManager *queueManager;
+ // Actions
+ static TDEAction *actProperties, *actPack, *actUnpack, *actTest, *actCompare, *actCmdlinePopup;
+ static TDEAction *actCalculate, *actSelect, *actUnselect, *actSelectAll, *actLocate, *actSwitchFullScreenTE;
+ static TDEAction *actUnselectAll, *actInvert, *actSync, *actDiskUsage, *actSavePosition, *actCompDirs;
+ static TDEAction *actHomeTerminal, *actFTPConnect, *actFTPNewConnect, *actFTPDisconnect, *actProfiles;
+ static TDEAction *actExecFilter, *actCustomFilter, *actMountMan, *actNewTool, *actSwapPanels, *actSwapSides;
+ static TDEAction *actKonfigurator, *actToolsSetup, *actBack, *actRoot, *actFind, *actDirUp;
+ static TDEAction *actSelectColorMask, *actMultiRename, *actAllFilter, *actOpenLeftBm, *actOpenRightBm;
+ static TDEAction *actNewTab, *actDupTab, *actCloseTab, *actPreviousTab, *actNextTab, *actSplit;
+ static TDEAction *actCombine, *actUserMenu, *actManageUseractions, *actSyncDirs, *actSyncBrowse;
+ static TDEAction *actF2, *actF3, *actF4, *actF5, *actF6, *actF7, *actF8, *actF9, *actF10;
+ static TDEAction *actPopularUrls, *actLocationBar, *actJumpBack, *actSetJumpBack, *actCreateChecksum, *actMatchChecksum;
+ static TDEAction *actDetailedView, *actBriefView, *actCopy, *actPaste;
+ static TDEToggleAction *actToggleTerminal, *actVerticalMode;
+ static TDERadioAction *actSelectNewerAndSingle, *actSelectNewer, *actSelectSingle,
+ *actSelectDifferentAndSingle, *actSelectDifferent;
+ /** actions for setting the execution mode of commands from commanddline */
+ static TDERadioAction *actExecStartAndForget,
+ *actExecCollectSeparate,*actExecCollectTogether,
+ *actExecTerminalExternal,*actExecTerminalEmbedded;
+ TDEToggleAction *actToggleFnkeys, *actToggleCmdline, *actShowToolBar,
+ *actShowStatusBar, *actToggleHidden, *actCompareDirs;
+
+ static TDERadioAction **compareArray[];
+ /** actions for setting the execution mode of commands from commanddline */
+ static TDERadioAction **execTypeArray[];
+
+ // return a path to a temp dir or file we can use.
+ TQString getTempDir();
+ TQString getTempFile();
+
+ // the internal progress bar variales + functions
+ KRPleaseWaitHandler* plzWait;
+ void startWaiting( TQString msg = "Please Wait", int count = 0 , bool cancel = false );
+ void stopWait();
+ bool wasWaitingCancelled() const;
+
+ KrusaderStatus *status;
+ KRslots *slot;
+ TDEAccel *accels; // global accelerators
+
+ static TDEPopupMenu *userActionMenu;
+ static UserMenu *userMenu;
+ static UserAction *userAction;
+ static KrBookmarkHandler *bookman;
+
+ #ifdef __KJSEMBED__
+ static KrJS *js;
+ static TDEAction *actShowJSConsole;
+ #endif
+
+ signals:
+ void changeMessage( TQString );
+
+ private:
+ KSystemTray *sysTray;
+ TQPoint oldPos;
+ TQSize 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/src/app/krusader_root-mode.desktop b/src/app/krusader_root-mode.desktop
new file mode 100644
index 0000000..a00274c
--- /dev/null
+++ b/src/app/krusader_root-mode.desktop
@@ -0,0 +1,90 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Krusader
+Name[de]=Krusader
+Name[cs]=Krusader
+Exec=krusader -caption "%c" %i %m
+Icon=krusader_root
+Terminal=false
+Type=Application
+X-DocPath=krusader/index.html
+Categories=Qt;TDE;X-TDE-System-su;
+OnlyShowIn=TDE;
+X-TDE-SubstituteUID=true
+X-TDE-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 - Super User Mode
+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/src/app/krusaderapp.h b/src/app/krusaderapp.h
new file mode 100644
index 0000000..a50f5c9
--- /dev/null
+++ b/src/app/krusaderapp.h
@@ -0,0 +1,32 @@
+#ifndef KRUSADERAPP_H
+#define KRUSADERAPP_H
+
+#include <tdeapplication.h>
+#include "X11/Xlib.h"
+
+// declare a dummy kapplication, just to get the X focusin focusout events
+class KrusaderApp: public TDEApplication {
+ TQ_OBJECT
+
+public:
+ KrusaderApp(): TDEApplication() {}
+ 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 TDEApplication::x11EventFilter(e);
+ }
+signals:
+ void windowActive();
+ void windowInactive();
+};
+
+
+#endif // KRUSADERAPP_H
diff --git a/src/app/krusaderui.rc b/src/app/krusaderui.rc
new file mode 100644
index 0000000..54c649e
--- /dev/null
+++ b/src/app/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/src/app/krusaderview.cpp b/src/app/krusaderview.cpp
new file mode 100644
index 0000000..33bc04a
--- /dev/null
+++ b/src/app/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. *
+* *
+***************************************************************************/
+
+// TQt includes
+#include <tqwhatsthis.h>
+#include <kstatusbar.h>
+#include <tdemenubar.h>
+#include <tdeshortcut.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 <tqclipboard.h>
+
+KrusaderView::KrusaderView( TQWidget *parent ) : TQWidget( parent, "KrusaderView" ), activePanel(0),
+ konsole_part( 0L ) {}
+
+void KrusaderView::start( TQStringList leftTabs, TQStringList leftTypes, TQValueList<int> leftProps, int leftActiveTab,
+ TQStringList rightTabs, TQStringList rightTypes, TQValueList<int> rightProps, int rightActiveTab,
+ bool leftSideActive ) {
+ ////////////////////////////////
+ // make a 1x1 mainLayout, it will auto-expand:
+ mainLayout = new TQGridLayout( this, 1, 1 );
+ // vertical splitter
+ vert_splitter = new TQSplitter( this ); // splits between panels and terminal/cmdline
+ vert_splitter->setOrientation( TQt::Vertical );
+ // horizontal splitter
+ horiz_splitter = new PercentalSplitter( vert_splitter );
+ ( terminal_dock = new TQHBox( 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();
+ TQWhatsThis::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" );
+ TQValueList<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();
+
+ tqApp->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( TQString p ) {
+ cmdLine->setCurrent( p );
+ if ( konsole_part != 0L && konsole_part->widget() != 0L ) {
+ TDEConfigGroupSaver grp(krConfig, "General");
+ if (krConfig->readBoolEntry("Send CDs", _SendCDs)) // hopefully, this is cached in tdeconfig
+ 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 ) {
+ TQWidget *focusW = tqApp->focusWidget();
+ // Create the part
+ konsole_part = ( KParts::ReadOnlyPart * )
+ factory->create( terminal_dock, "konsolepart",
+ "KParts::ReadOnlyPart" );
+ if( konsole_part ) { //loaded successfully
+ connect( konsole_part, TQ_SIGNAL( destroyed() ),
+ this, TQ_SLOT( killTerminalEmulator() ) );
+ tqApp->installEventFilter( this );
+ } else {
+ tqApp->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 ) {
+ TDEConfigGroupSaver 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 TQSplitter 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();
+ TQValueList<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
+ TQTimer::singleShot( 0, konsole_part->widget(), TQ_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() ) {
+ TDEConfigGroup 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 ( TQObject * watched, TQEvent * e ) {
+ if( e->type() == TQEvent::AccelOverride && konsole_part && konsole_part->widget() == watched ) {
+ TQKeyEvent *ke = (TQKeyEvent *)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() == TQEvent::KeyPress && konsole_part && konsole_part->widget() == watched ) {
+ TQKeyEvent *ke = (TQKeyEvent *)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 ) ) {
+
+ TQString filename = ACTIVE_PANEL->view->getCurrentItem();
+ if( filename == TQString() || filename == ".." )
+ return true;
+ if( ke->state() & ShiftButton ) {
+ TQString path=vfs::pathOrURL( ACTIVE_FUNC->files()->vfs_getOrigin(), 1 );
+ filename = path+filename;
+ }
+
+ filename = KrServices::quote( filename );
+
+ TQKeyEvent keyEvent( TQEvent::KeyPress, 0, -1, 0, TQString( " " ) + filename + TQString( " " ));
+ TQApplication::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 ) ) {
+ TQString text = TQApplication::clipboard()->text();
+ if ( ! text.isEmpty() )
+ {
+ text.replace("\n", "\r");
+ TQKeyEvent keyEvent(TQEvent::KeyPress, 0,-1,0, text);
+ TQApplication::sendEvent( konsole_part->widget(), &keyEvent );
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+TQValueList<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( TQString profileName )
+{
+ ProfileManager profileManager( "Panel" );
+ profileManager.hide();
+ connect( &profileManager, TQ_SIGNAL( saveToProfile( TQString ) ), this, TQ_SLOT( savePanelProfiles( TQString ) ) );
+ connect( &profileManager, TQ_SIGNAL( loadFromProfile( TQString ) ), this, TQ_SLOT( loadPanelProfiles( TQString ) ) );
+ if( profileName.isEmpty() )
+ profileManager.profilePopup();
+ else
+ profileManager.loadProfile( profileName );
+}
+
+void KrusaderView::loadPanelProfiles( TQString 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( TQString 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() == TQt::Vertical)
+ horiz_splitter->setOrientation(TQt::Horizontal);
+ else horiz_splitter->setOrientation(TQt::Vertical);
+}
+
+#include "krusaderview.moc"
diff --git a/src/app/krusaderview.h b/src/app/krusaderview.h
new file mode 100644
index 0000000..619868f
--- /dev/null
+++ b/src/app/krusaderview.h
@@ -0,0 +1,111 @@
+/***************************************************************************
+ 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
+
+// TDE includes
+#include <tdelistview.h>
+#include <tdelocale.h>
+#include <tdeaccel.h>
+#include <tdeapplication.h>
+#include <tdeparts/part.h>
+
+// TQt includes
+#include <tqlayout.h>
+#include <tqsplitter.h>
+#include <tqwidget.h>
+#include <tqpushbutton.h>
+#include <tqhbox.h>
+#include <tqvaluelist.h>
+
+class PanelManager;
+class ListPanel;
+
+// forward declaration
+class KFnKeys;
+class KCMDLine;
+
+class KrusaderView : public TQWidget {
+ TQ_OBJECT
+
+
+public:
+ KrusaderView(TQWidget *parent=0);
+ virtual ~KrusaderView(){}
+ void start(TQStringList leftTabs, TQStringList leftTypes, TQValueList<int> leftProps, int leftActiveTab,
+ TQStringList rightTabs, TQStringList rightTypes, TQValueList<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); }
+ TQValueList<int> getTerminalEmulatorSplitterSizes();
+ virtual bool eventFilter ( TQObject * watched, TQEvent * e );
+ /** if the KonsolePart for the Terminal Emulator is not yet loaded, load it */
+ void createTE();
+
+public slots:
+ void slotCurrentChanged(TQString 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( TQString profileName = TQString() );
+ void loadPanelProfiles( TQString group );
+ void savePanelProfiles( TQString 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
+ TQHBox *terminal_dock; // docking widget for terminal emulator
+ KParts::ReadOnlyPart *konsole_part; // the actual part pointer
+ TQSplitter *horiz_splitter, *vert_splitter;
+ TQValueList<int> verticalSplitterSizes;
+
+private:
+ TQGridLayout *mainLayout, *terminal_layout;
+};
+
+#endif
diff --git a/src/app/lo16-app-krusader.png b/src/app/lo16-app-krusader.png
new file mode 100644
index 0000000..6de4c84
--- /dev/null
+++ b/src/app/lo16-app-krusader.png
Binary files differ
diff --git a/src/app/lo32-app-krusader.png b/src/app/lo32-app-krusader.png
new file mode 100644
index 0000000..7ffbeb9
--- /dev/null
+++ b/src/app/lo32-app-krusader.png
Binary files differ
diff --git a/src/app/lo32-app-krusader2.png b/src/app/lo32-app-krusader2.png
new file mode 100644
index 0000000..912157e
--- /dev/null
+++ b/src/app/lo32-app-krusader2.png
Binary files differ
diff --git a/src/app/main.cpp b/src/app/main.cpp
new file mode 100644
index 0000000..3952ca2
--- /dev/null
+++ b/src/app/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. *
+ * *
+ ***************************************************************************/
+
+// TDE includes
+#include <tdecmdlineargs.h>
+#include <tdeaboutdata.h>
+#include <tdelocale.h>
+#include <kstandarddirs.h>
+#include <ksplashscreen.h>
+#include <unistd.h>
+#include <signal.h>
+#include <tqeventloop.h>
+
+// Krusader includes
+#include "krusader.h"
+#include "krslots.h"
+#include "krusaderapp.h"
+#include "defaults.h"
+#include <dcopclient.h>
+#include <tdestartupinfo.h>
+#include <stdlib.h>
+
+static const char *description =
+ I18N_NOOP("Krusader\nTwin-Panel File Manager for TDE");
+// INSERT A DESCRIPTION FOR YOUR APPLICATION HERE
+
+static TDECmdLineOptions 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);
+
+ TQApplication::eventLoop()->wakeUp();
+ TDEApplication::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
+ TQString versionName = TQString("%1 \"%2\"").arg(VERSION).arg(RELEASE_NAME);
+#else
+ TQString versionName = VERSION;
+#endif
+ TDEAboutData aboutData( "krusader", ( geteuid() ? I18N_NOOP("Krusader") :
+ I18N_NOOP("Krusader - ROOT PRIVILEGES")),
+ versionName.latin1(), description, TDEAboutData::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 TDEIO 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 ...
+ TDECmdLineArgs::init( argc, argv, &aboutData );
+ TDECmdLineArgs::addCmdLineOptions( options ); // Add our own options.
+
+ // check for command line arguments
+
+ // create the application
+ KrusaderApp app;
+
+ {
+ TDEConfigGroupSaver saver(app.config(), "Look&Feel");
+ bool singleInstanceMode = app.config()->readBoolEntry( "Single Instance Mode", _SingleInstanceMode );
+
+ // register with the dcop server
+ DCOPClient* client = TDEApplication::kApplication() ->dcopClient();
+ if ( !client->attach() )
+ exit( 0 );
+ TQCString regName = client->registerAs( TDEApplication::kApplication() ->name(), !singleInstanceMode );
+ if( singleInstanceMode && regName != TDEApplication::kApplication()->name() ) {
+ fprintf( stderr, "%s", i18n( "Application already running!\n" ).ascii() );
+
+ DCOPClient::mainClient()->send( TDEApplication::kApplication() ->name(), "Krusader-Interface",
+ "moveToTop()", TQByteArray() );
+ TDEStartupInfo::appStarted();
+
+ return 1;
+ }
+ }
+
+ // splash screen - if the user wants one
+ KSplashScreen *splash = 0;
+ { // don't remove bracket
+ TDEConfigGroupSaver saver(app.config(), "Look&Feel");
+ if (app.config()->readBoolEntry( "Show splashscreen", _ShowSplashScreen )) {
+ TQString splashFilename = locate( "data", "krusader/splash.png" );
+ TQPixmap 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
+ TQObject::connect(&app, TQ_SIGNAL(windowActive()), krusader.slot, TQ_SLOT(windowActive()));
+ TQObject::connect(&app, TQ_SIGNAL(windowInactive()), krusader.slot, TQ_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/src/app/midnight_cmd_AHamann.color b/src/app/midnight_cmd_AHamann.color
new file mode 100644
index 0000000..e5a82d6
--- /dev/null
+++ b/src/app/midnight_cmd_AHamann.color
Binary files differ
diff --git a/src/app/midnight_commander.color b/src/app/midnight_commander.color
new file mode 100644
index 0000000..f42b788
--- /dev/null
+++ b/src/app/midnight_commander.color
Binary files differ
diff --git a/src/app/midnight_commander.keymap b/src/app/midnight_commander.keymap
new file mode 100644
index 0000000..3e664d6
--- /dev/null
+++ b/src/app/midnight_commander.keymap
Binary files differ
diff --git a/src/app/midnight_commander.keymap.info b/src/app/midnight_commander.keymap.info
new file mode 100644
index 0000000..12e19e8
--- /dev/null
+++ b/src/app/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/src/app/mount.js b/src/app/mount.js
new file mode 100644
index 0000000..3aadcc8
--- /dev/null
+++ b/src/app/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/src/app/mount.ui b/src/app/mount.ui
new file mode 100644
index 0000000..628c009
--- /dev/null
+++ b/src/app/mount.ui
@@ -0,0 +1,195 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>mountDlg</class>
+<widget class="TQDialog">
+ <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="TQLayoutWidget" 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="TQPushButton">
+ <property name="name">
+ <cstring>buttonOk</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>buttonCancel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQLabel" 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="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>labelFilesystem</cstring>
+ </property>
+ <property name="text">
+ <string>Filesystem</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>labelMountpoint</cstring>
+ </property>
+ <property name="text">
+ <string>Mountpoint</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" 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>
+<layoutdefaults spacing="6" margin="11"/>
+<includes>
+ <include location="global" impldecl="in implementation">kcombobox.h</include>
+ <include location="global" impldecl="in implementation">klineedit.h</include>
+ <include location="global" impldecl="in implementation">kpushbutton.h</include>
+ <include location="global" impldecl="in implementation">kurlrequester.h</include>
+ <include location="local" impldecl="in implementation">mount.ui.h</include>
+</includes>
+</UI>
diff --git a/src/app/panelmanager.cpp b/src/app/panelmanager.cpp
new file mode 100644
index 0000000..be02706
--- /dev/null
+++ b/src/app/panelmanager.cpp
@@ -0,0 +1,352 @@
+#include <tqwidgetstack.h>
+#include <tqtoolbutton.h>
+#include <tdelocale.h>
+#include <tqimage.h>
+#include <kdebug.h>
+#include <tdeconfig.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( TQWidget *parent, bool left ) :
+TQWidget( parent, "PanelManager" ), _layout( 0 ), _left( left ),
+ _selfPtr( _left ? &MAIN_VIEW->left : &MAIN_VIEW->right ),
+ _otherPtr( _left ? &MAIN_VIEW->right : &MAIN_VIEW->left ) {
+ _layout = new TQGridLayout( this, 1, 1 );
+ _stack = new TQWidgetStack( this );
+
+ // new tab button
+ _newTab = new TQToolButton( this );
+ _newTab->setFixedSize( 22, 22 );
+ _newTab->setTextLabel( i18n( "Open a new tab in home" ) );
+ _newTab->setIconSet( SmallIcon( "tab_new" ) );
+ _newTab->adjustSize();
+ connect( _newTab, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotNewTab() ) );
+
+ // close tab button
+ _closeTab = new TQToolButton( this );
+ _closeTab->setFixedSize( 22, 22 );
+ _closeTab->setTextLabel( i18n( "Close current tab" ) );
+ _closeTab->setIconSet( SmallIcon( "tab_remove" ) );
+ _closeTab->adjustSize();
+ connect( _closeTab, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotCloseTab() ) );
+ _closeTab->setEnabled( false ); // disabled when there's only 1 tab
+
+ // tab-bar
+ _tabbar = new PanelTabBar( this );
+ connect( _tabbar, TQ_SIGNAL( changePanel( ListPanel* ) ), this, TQ_SLOT( slotChangePanel( ListPanel * ) ) );
+ connect( _tabbar, TQ_SIGNAL( closeCurrentTab() ), this, TQ_SLOT( slotCloseTab() ) );
+ connect( _tabbar, TQ_SIGNAL( newTab( const KURL& ) ), this, TQ_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( TQString 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, TQ_SIGNAL( activePanelChanged( ListPanel* ) ), this, TQ_SLOT( slotRefreshActions() ) );
+ return p;
+}
+
+void PanelManager::startPanel( ListPanel *panel, const KURL& path ) {
+ panel->start( path );
+}
+
+void PanelManager::saveSettings( TDEConfig *config, const TQString& key, bool localOnly ) {
+ TQStringList l;
+ TQStringList types;
+ TQValueList<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( TDEConfig *config, const TQString& key ) {
+ TQStringList l = config->readPathListEntry( key );
+ TQStringList types = config->readListEntry( key + " Types" );
+ TQValueList<int> props = config->readIntListEntry( key + " Props" );
+
+ if( l.count() < 1 )
+ return;
+
+ while( types.count() < l.count() )
+ {
+ TDEConfigGroupSaver 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, TQString 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( TQDir::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 )
+{
+ TQTab *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;
+ TQString type = oldPanel->getType();
+ ListPanel *newPanel = new ListPanel( type, _stack, _left );
+ _stack->addWidget( newPanel, i );
+ _stack->removeWidget( oldPanel );
+
+ disconnect( oldPanel );
+ connect( newPanel, TQ_SIGNAL( activePanelChanged( ListPanel* ) ), this, TQ_SLOT( slotRefreshActions() ) );
+ connect( newPanel, TQ_SIGNAL( pathChanged(ListPanel*) ), _tabbar, TQ_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(), TQ_SIGNAL( deleteAllowed() ), p, TQ_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/src/app/panelmanager.h b/src/app/panelmanager.h
new file mode 100644
index 0000000..599752b
--- /dev/null
+++ b/src/app/panelmanager.h
@@ -0,0 +1,79 @@
+#ifndef _PANEL_MANAGER_H
+#define _PANEL_MANAGER_H
+
+#include <tqwidget.h>
+#include <tqlayout.h>
+#include "paneltabbar.h"
+
+class TDEConfig;
+class ListPanel;
+class TQWidgetStack;
+class TQToolButton;
+
+/**
+ * Implements tabbed-browsing by managing a list of tabs and corrosponding panels.
+ */
+class PanelManager: public TQWidget {
+ TQ_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( TQWidget *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( TQString 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(TDEConfig *config, const TQString& key, bool localOnly = true );
+ void loadSettings(TDEConfig *config, const TQString& 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, TQString type = TQString(), 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 );
+
+ TQGridLayout *_layout;
+ TQHBoxLayout *_barLayout;
+ bool _left;
+ PanelTabBar *_tabbar;
+ TQWidgetStack *_stack;
+ TQToolButton *_newTab, *_closeTab;
+ ListPanel **_selfPtr, **_otherPtr;
+};
+
+
+#endif // _PANEL_MANAGER_H
diff --git a/src/app/paneltabbar.cpp b/src/app/paneltabbar.cpp
new file mode 100644
index 0000000..6e014aa
--- /dev/null
+++ b/src/app/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 <tdeaction.h>
+#include <tdelocale.h>
+#include <tdeshortcut.h>
+#include <tqevent.h>
+#include <tqwidgetstack.h>
+#include <tqfontmetrics.h>
+#include <tqtooltip.h>
+#include <kdebug.h>
+
+#define DISPLAY(X) (X.isLocalFile() ? X.path() : X.prettyURL())
+
+PanelTabBar::PanelTabBar(TQWidget *parent): TQTabBar(parent), _maxTabLength(0) {
+ _panelActionMenu = new TDEActionMenu( 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(TQTabBar::TriangularBelow);
+}
+
+void PanelTabBar::mousePressEvent( TQMouseEvent* e ) {
+ TQTab* clickedTab = selectTab( e->pos() );
+ if( !clickedTab ) { // clicked on nothing ...
+ TQTabBar::mousePressEvent(e);
+ return;
+ }
+ // else implied
+ setCurrentTab( clickedTab );
+ emit changePanel(dynamic_cast<PanelTab*>(clickedTab)->panel);
+
+ if ( e->button() == TQt::RightButton ) {
+ // show the popup menu
+ _panelActionMenu->popup( e->globalPos() );
+ } else
+ if ( e->button() == TQt::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() == TQt::MidButton) { // close the current tab
+ emit closeCurrentTab();
+ }
+ TQTabBar::mousePressEvent(e);
+}
+
+void PanelTabBar::insertAction( TDEAction* 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, TQ_SIGNAL(pathChanged(ListPanel*)),
+ this, TQ_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();
+}
+
+TQString PanelTabBar::squeeze(TQString text, int index) {
+ TQString originalText = text;
+
+ TQString 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
+ {
+ TQString 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;
+ }
+
+ TQFontMetrics fm(fontMetrics());
+
+ // set the real max length
+ _maxTabLength = (static_cast<TQWidget*>(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
+ TQString 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 ( TQResizeEvent *e ) {
+ TQTabBar::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(TQDragEnterEvent *e) {
+ TQTab *t = selectTab(e->pos());
+ if (!t) return;
+ if (tab(currentTab()) != t) {
+ setCurrentTab(t);
+ emit changePanel(dynamic_cast<PanelTab*>(t)->panel);
+ }
+}
+
+void PanelTabBar::dragMoveEvent(TQDragMoveEvent *e) {
+ TQTab *t = selectTab(e->pos());
+ if (!t) return;
+ if (tab(currentTab()) != t) {
+ setCurrentTab(t);
+ emit changePanel(dynamic_cast<PanelTab*>(t)->panel);
+ }
+}
+
+// -----------------------------> PanelTab <----------------------------
+
+PanelTab::PanelTab(const TQString & text): TQTab(text) {}
+PanelTab::PanelTab(const TQString & text, ListPanel *p): TQTab(text), panel(p) {}
+
+#include "paneltabbar.moc"
diff --git a/src/app/paneltabbar.h b/src/app/paneltabbar.h
new file mode 100644
index 0000000..56b2e58
--- /dev/null
+++ b/src/app/paneltabbar.h
@@ -0,0 +1,100 @@
+/*
+ * 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 <tqtabbar.h>
+#include <tqvaluelist.h>
+
+class TQMouseEvent;
+class TDEAction;
+class TDEActionMenu;
+class ListPanel;
+
+/**
+ * Extends TQTab to include a pointer to the panel contained in this tab
+ */
+class PanelTab: public TQTab {
+public:
+ PanelTab(const TQString & text);
+ PanelTab(const TQString & text, ListPanel *p);
+
+ ListPanel *panel;
+};
+
+/**
+ * This class extends TQTabBar 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 TQTabBar {
+ TQ_OBJECT
+
+public:
+ PanelTabBar( TQWidget *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( TQMouseEvent* );
+ void insertAction( TDEAction* );
+ TQString squeeze(TQString text, int index=-1);
+ virtual void dragEnterEvent(TQDragEnterEvent *);
+ virtual void dragMoveEvent(TQDragMoveEvent *);
+ virtual void resizeEvent ( TQResizeEvent *e );
+
+protected slots:
+ void closeTab();
+ void duplicateTab();
+
+private:
+ TDEActionMenu *_panelActionMenu;
+ bool _left;
+ int _maxTabLength;
+};
+
+#endif
diff --git a/src/app/recode.js b/src/app/recode.js
new file mode 100644
index 0000000..61cb5a3
--- /dev/null
+++ b/src/app/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/src/app/recode.ui b/src/app/recode.ui
new file mode 100644
index 0000000..4722943
--- /dev/null
+++ b/src/app/recode.ui
@@ -0,0 +1,286 @@
+<!DOCTYPE UI>
+<UI version="3.3" stdsetdef="1">
+<class>recodeDlg</class>
+<widget class="TQDialog">
+ <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="TQLayoutWidget" 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="TQPushButton">
+ <property name="name">
+ <cstring>buttonOk</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>buttonCancel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQLabel" row="0" column="1">
+ <property name="name">
+ <cstring>labelInHdr</cstring>
+ </property>
+ <property name="text">
+ <string>INPUT:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="2">
+ <property name="name">
+ <cstring>labelOutHdr</cstring>
+ </property>
+ <property name="text">
+ <string>OUTPUT:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" 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="TQLabel" 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="TQLabel" 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="TQLabel" 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="TQLabel" 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="TQCheckBox" 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="TQCheckBox" 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="TQCheckBox" 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"/>
+<includes>
+ <include location="global" impldecl="in implementation">kcombobox.h</include>
+ <include location="global" impldecl="in implementation">klineedit.h</include>
+ <include location="global" impldecl="in implementation">kpushbutton.h</include>
+ <include location="global" impldecl="in implementation">kurlrequester.h</include>
+</includes>
+</UI>
diff --git a/src/app/resources.h b/src/app/resources.h
new file mode 100644
index 0000000..bdcc1b1
--- /dev/null
+++ b/src/app/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/src/app/select_from_file.js b/src/app/select_from_file.js
new file mode 100644
index 0000000..3d00c32
--- /dev/null
+++ b/src/app/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/src/app/splash.png b/src/app/splash.png
new file mode 100644
index 0000000..44f9233
--- /dev/null
+++ b/src/app/splash.png
Binary files differ
diff --git a/src/app/total_cmd_pleasent.color b/src/app/total_cmd_pleasent.color
new file mode 100644
index 0000000..4f0681e
--- /dev/null
+++ b/src/app/total_cmd_pleasent.color
Binary files differ
diff --git a/src/app/total_commander.color b/src/app/total_commander.color
new file mode 100644
index 0000000..8f7d15a
--- /dev/null
+++ b/src/app/total_commander.color
Binary files differ
diff --git a/src/app/total_commander.keymap b/src/app/total_commander.keymap
new file mode 100644
index 0000000..c8a6687
--- /dev/null
+++ b/src/app/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/src/app/total_commander.keymap.info b/src/app/total_commander.keymap.info
new file mode 100644
index 0000000..0555574
--- /dev/null
+++ b/src/app/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/src/app/useraction_examples.xml b/src/app/useraction_examples.xml
new file mode 100644
index 0000000..0e9107d
--- /dev/null
+++ b/src/app/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-mounted</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-mounted</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/src/app/x-ace.desktop b/src/app/x-ace.desktop
new file mode 100644
index 0000000..501e33d
--- /dev/null
+++ b/src/app/x-ace.desktop
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Comment=ACE archive
+Hidden=false
+Icon=application-x-tarz
+MimeType=application/x-ace
+Patterns=*.ace;*.ACE
+Type=MimeType
diff --git a/src/iso/Makefile.am b/src/iso/Makefile.am
new file mode 100644
index 0000000..a0e73b5
--- /dev/null
+++ b/src/iso/Makefile.am
@@ -0,0 +1,64 @@
+kde_module_LTLIBRARIES = tdeio_iso.la
+
+
+INCLUDES = $(all_includes)
+
+
+#LDFLAGS =
+
+tdeio_iso_la_METASOURCES=AUTO
+
+tdeio_iso_la_SOURCES = kisodirectory.cpp kisofile.cpp qfilehack.cpp kiso.cpp iso.cpp
+tdeio_iso_la_LIBADD = libisofs/libisofs.la $(LIB_TQT) $(LIB_TDECORE) $(LIB_TDEIO)
+
+tdeio_iso_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+
+
+SUBDIRS = libisofs
+
+noinst_HEADERS = iso.h kiso.h qfilehack.h kisofile.h kisodirectory.h
+EXTRA_DIST = iso.protocol isoservice.desktop
+
+install-data-local:
+ $(mkinstalldirs) $(DESTDIR)$(kde_servicesdir)/
+ $(INSTALL_DATA) $(srcdir)/iso.protocol $(DESTDIR)$(kde_servicesdir)/iso.protocol
+ $(mkinstalldirs) $(DESTDIR)$(kde_datadir)/konqueror/servicemenus/
+ $(INSTALL_DATA) $(srcdir)/isoservice.desktop $(DESTDIR)$(kde_datadir)/konqueror/servicemenus/isoservice.desktop
+ $(mkinstalldirs) $(DESTDIR)$(kde_confdir)/
+ $(INSTALL_DATA) $(srcdir)/tdeio_isorc $(DESTDIR)$(kde_confdir)/tdeio_isorc
+
+uninstall-local:
+ -rm -f $(DESTDIR)$(kde_servicesdir)/iso.protocol
+ -rm -f $(DESTDIR)$(kde_datadir)/konqueror/servicemenus/isoservice.desktop
+ -rm -f $(DESTDIR)$(kde_confdir)/tdeio_isorc
+
+# These paths are KDE specific. Use them:
+# kde_appsdir Where your application's menu entry (.desktop) should go to.
+# 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_toolbardir Where general toolbar icons should go to (deprecated, use KDE_ICON).
+# 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 TQt/TDE widget styles should go to.
+# kde_designerdir Where TQt Designer plugins should go to.
+
+
+# make messages.po. Move this one to ../po/ and "make merge" in po
+# the -x is for skipping messages already translated in tdelibs
+messages:
+ LIST=`find . -name \*.h -o -name \*.cpp`; \
+ if test -n "$$LIST"; then \
+ $(XGETTEXT) -C -ki18n -x $(kde_includes)/kde.pot $$LIST -o ../po/iso.pot; \
+ fi
+
diff --git a/src/iso/iso.cpp b/src/iso/iso.cpp
new file mode 100644
index 0000000..5f6e3e0
--- /dev/null
+++ b/src/iso/iso.cpp
@@ -0,0 +1,525 @@
+/***************************************************************************
+ iso.cpp
+ -------------------
+ begin : Oct 25 2002
+ copyright : (C) 2002 by Szombathelyi Gy�gy
+ email : gyurco@users.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. *
+ * *
+ ***************************************************************************/
+
+ /* This file is heavily based on tar.cpp from tdebase
+ * (c) David Faure <faure@kde.org>
+ */
+
+#include <zlib.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <klargefile.h>
+#include <tqfile.h>
+#include <kurl.h>
+#include <kdebug.h>
+#include <tdeinstance.h>
+#include <kiso.h>
+#include <kmimemagic.h>
+
+#include <errno.h> // to be removed
+
+#include "libisofs/iso_fs.h"
+
+#include "kisofile.h"
+#include "kisodirectory.h"
+#include "iso.h"
+
+typedef struct {
+ char magic[8];
+ char uncompressed_len[4];
+ unsigned char header_size;
+ unsigned char block_size;
+ char reserved[2]; /* Reserved for future use, MBZ */
+} compressed_file_header;
+
+static const unsigned char zisofs_magic[8] = {
+ 0x37, 0xE4, 0x53, 0x96, 0xC9, 0xDB, 0xD6, 0x07
+};
+
+using namespace TDEIO;
+
+extern "C" { int kdemain(int argc, char **argv); }
+
+int kdemain( int argc, char **argv )
+{
+ TDEInstance instance( "tdeio_iso" );
+
+ kdDebug() << "Starting " << getpid() << endl;
+
+ if (argc != 4)
+ {
+ fprintf(stderr, "Usage: tdeio_iso protocol domain-socket1 domain-socket2\n");
+ exit(-1);
+ }
+
+ tdeio_isoProtocol slave(argv[2], argv[3]);
+ slave.dispatchLoop();
+
+ kdDebug() << "Done" << endl;
+ return 0;
+}
+
+
+tdeio_isoProtocol::tdeio_isoProtocol( const TQCString &pool, const TQCString &app ) : SlaveBase( "iso", pool, app )
+{
+ kdDebug() << "tdeio_isoProtocol::tdeio_isoProtocol" << endl;
+ m_isoFile = 0L;
+}
+
+tdeio_isoProtocol::~tdeio_isoProtocol()
+{
+ delete m_isoFile;
+}
+
+bool tdeio_isoProtocol::checkNewFile( TQString fullPath, TQString & path, int startsec )
+{
+ kdDebug() << "tdeio_isoProtocol::checkNewFile " << fullPath << " startsec: " <<
+ startsec << endl;
+
+ // Are we already looking at that file ?
+ if ( m_isoFile && startsec == m_isoFile->startSec() &&
+ m_isoFile->fileName() == fullPath.left(m_isoFile->fileName().length()) )
+ {
+ // Has it changed ?
+ struct stat statbuf;
+ if ( ::stat( TQFile::encodeName( m_isoFile->fileName() ), &statbuf ) == 0 )
+ {
+ if ( m_mtime == statbuf.st_mtime )
+ {
+ path = fullPath.mid( m_isoFile->fileName().length() );
+ kdDebug() << "tdeio_isoProtocol::checkNewFile returning " << path << endl;
+ return true;
+ }
+ }
+ }
+ kdDebug() << "Need to open a new file" << endl;
+
+ // Close previous file
+ if ( m_isoFile )
+ {
+ m_isoFile->close();
+ delete m_isoFile;
+ m_isoFile = 0L;
+ }
+
+ // Find where the iso file is in the full path
+ int pos = 0;
+ TQString isoFile;
+ path = TQString();
+
+ int len = fullPath.length();
+ if ( len != 0 && fullPath[ len - 1 ] != '/' )
+ fullPath += '/';
+
+ kdDebug() << "the full path is " << fullPath << endl;
+ while ( (pos=fullPath.find( '/', pos+1 )) != -1 )
+ {
+ TQString tryPath = fullPath.left( pos );
+ kdDebug() << fullPath << " trying " << tryPath << endl;
+
+ KDE_struct_stat statbuf;
+ if ( KDE_lstat( TQFile::encodeName(tryPath), &statbuf ) == 0 && !S_ISDIR(statbuf.st_mode) )
+ {
+ isoFile = tryPath;
+ m_mtime = statbuf.st_mtime;
+ m_mode = statbuf.st_mode;
+ path = fullPath.mid( pos + 1 );
+ kdDebug() << "fullPath=" << fullPath << " path=" << path << endl;
+ len = path.length();
+ if ( len > 1 )
+ {
+ if ( path[ len - 1 ] == '/' )
+ path.truncate( len - 1 );
+ }
+ else
+ path = TQString::fromLatin1("/");
+ kdDebug() << "Found. isoFile=" << isoFile << " path=" << path << endl;
+ break;
+ }
+ }
+ if ( isoFile.isEmpty() )
+ {
+ kdDebug() << "tdeio_isoProtocol::checkNewFile: not found" << endl;
+ return false;
+ }
+
+ // Open new file
+ kdDebug() << "Opening KIso on " << isoFile << endl;
+ m_isoFile = new KIso( isoFile );
+ m_isoFile->setStartSec(startsec);
+ if ( !m_isoFile->open( IO_ReadOnly ) )
+ {
+ kdDebug() << "Opening " << isoFile << " failed." << endl;
+ delete m_isoFile;
+ m_isoFile = 0L;
+ return false;
+ }
+
+ return true;
+}
+
+
+void tdeio_isoProtocol::createUDSEntry( const KArchiveEntry * isoEntry, UDSEntry & entry )
+{
+ UDSAtom atom;
+
+ entry.clear();
+ atom.m_uds = UDS_NAME;
+ atom.m_str = isoEntry->name();
+ entry.append(atom);
+
+ atom.m_uds = UDS_FILE_TYPE;
+ atom.m_long = isoEntry->permissions() & S_IFMT; // keep file type only
+ entry.append( atom );
+
+ atom.m_uds = UDS_ACCESS;
+ atom.m_long = isoEntry->permissions() & 07777; // keep permissions only
+ entry.append( atom );
+
+ atom.m_uds = UDS_SIZE;
+ if (isoEntry->isFile()) {
+ atom.m_long = ((KIsoFile *)isoEntry)->realsize();
+ if (!atom.m_long) atom.m_long = ((KIsoFile *)isoEntry)->size();
+ } else {
+ atom.m_long = 0L;
+ }
+ entry.append( atom );
+
+ atom.m_uds = UDS_USER;
+ atom.m_str = isoEntry->user();
+ entry.append( atom );
+
+ atom.m_uds = UDS_GROUP;
+ atom.m_str = isoEntry->group();
+ entry.append( atom );
+
+ atom.m_uds = UDS_MODIFICATION_TIME;
+ atom.m_long = isoEntry->date();
+ entry.append( atom );
+
+ atom.m_uds = UDS_ACCESS_TIME;
+ atom.m_long = isoEntry->isFile() ? ((KIsoFile *)isoEntry)->adate() :
+ ((KIsoDirectory *)isoEntry)->adate();
+ entry.append( atom );
+
+ atom.m_uds = UDS_CREATION_TIME;
+ atom.m_long = isoEntry->isFile() ? ((KIsoFile *)isoEntry)->cdate() :
+ ((KIsoDirectory *)isoEntry)->cdate();
+ entry.append( atom );
+
+ atom.m_uds = UDS_LINK_DEST;
+ atom.m_str = isoEntry->symlink();
+ entry.append( atom );
+}
+
+void tdeio_isoProtocol::listDir( const KURL & url )
+{
+ kdDebug() << "tdeio_isoProtocol::listDir " << url.url() << endl;
+
+ TQString path;
+ if ( !checkNewFile( url.path(), path, url.hasRef() ? url.htmlRef().toInt() : -1 ) )
+ {
+ TQCString _path( TQFile::encodeName(url.path()));
+ kdDebug() << "Checking (stat) on " << _path << endl;
+ struct stat buff;
+ if ( ::stat( _path.data(), &buff ) == -1 || !S_ISDIR( buff.st_mode ) ) {
+ error( TDEIO::ERR_DOES_NOT_EXIST, url.path() );
+ return;
+ }
+ // It's a real dir -> redirect
+ KURL redir;
+ redir.setPath( url.path() );
+ if (url.hasRef()) redir.setRef(url.htmlRef());
+ kdDebug() << "Ok, redirection to " << redir.url() << endl;
+ redirection( redir );
+ finished();
+ // And let go of the iso file - for people who want to unmount a cdrom after that
+ delete m_isoFile;
+ m_isoFile = 0L;
+ return;
+ }
+
+ if ( path.isEmpty() )
+ {
+ KURL redir( TQString::fromLatin1( "iso:/") );
+ kdDebug() << "url.path()==" << url.path() << endl;
+ if (url.hasRef()) redir.setRef(url.htmlRef());
+ redir.setPath( url.path() + TQString::fromLatin1("/") );
+ kdDebug() << "tdeio_isoProtocol::listDir: redirection " << redir.url() << endl;
+ redirection( redir );
+ finished();
+ return;
+ }
+
+ kdDebug() << "checkNewFile done" << endl;
+ const KArchiveDirectory* root = m_isoFile->directory();
+ const KArchiveDirectory* dir;
+ if (!path.isEmpty() && path != "/")
+ {
+ kdDebug() << TQString("Looking for entry %1").arg(path) << endl;
+ const KArchiveEntry* e = root->entry( path );
+ if ( !e )
+ {
+ error( TDEIO::ERR_DOES_NOT_EXIST, path );
+ return;
+ }
+ if ( ! e->isDirectory() )
+ {
+ error( TDEIO::ERR_IS_FILE, path );
+ return;
+ }
+ dir = (KArchiveDirectory*)e;
+ } else {
+ dir = root;
+ }
+
+ TQStringList l = dir->entries();
+ totalSize( l.count() );
+
+ UDSEntry entry;
+ TQStringList::Iterator it = l.begin();
+ for( ; it != l.end(); ++it )
+ {
+ kdDebug() << (*it) << endl;
+ const KArchiveEntry* isoEntry = dir->entry( (*it) );
+
+ createUDSEntry( isoEntry, entry );
+
+ listEntry( entry, false );
+ }
+
+ listEntry( entry, true ); // ready
+
+ finished();
+
+ kdDebug() << "tdeio_isoProtocol::listDir done" << endl;
+}
+
+void tdeio_isoProtocol::stat( const KURL & url )
+{
+ TQString path;
+ UDSEntry entry;
+
+ kdDebug() << "tdeio_isoProtocol::stat " << url.url() << endl;
+ if ( !checkNewFile( url.path(), path, url.hasRef() ? url.htmlRef().toInt() : -1 ) )
+ {
+ // We may be looking at a real directory - this happens
+ // when pressing up after being in the root of an archive
+ TQCString _path( TQFile::encodeName(url.path()));
+ kdDebug() << "tdeio_isoProtocol::stat (stat) on " << _path << endl;
+ struct stat buff;
+ if ( ::stat( _path.data(), &buff ) == -1 || !S_ISDIR( buff.st_mode ) ) {
+ kdDebug() << "isdir=" << S_ISDIR( buff.st_mode ) << " errno=" << strerror(errno) << endl;
+ error( TDEIO::ERR_DOES_NOT_EXIST, url.path() );
+ return;
+ }
+ // Real directory. Return just enough information for KRun to work
+ UDSAtom atom;
+ atom.m_uds = TDEIO::UDS_NAME;
+ atom.m_str = url.fileName();
+ entry.append( atom );
+ kdDebug() << "tdeio_isoProtocol::stat returning name=" << url.fileName() << endl;
+
+ atom.m_uds = TDEIO::UDS_FILE_TYPE;
+ atom.m_long = buff.st_mode & S_IFMT;
+ entry.append( atom );
+
+ statEntry( entry );
+
+ finished();
+
+ // And let go of the iso file - for people who want to unmount a cdrom after that
+ delete m_isoFile;
+ m_isoFile = 0L;
+ return;
+ }
+
+ const KArchiveDirectory* root = m_isoFile->directory();
+ const KArchiveEntry* isoEntry;
+ if ( path.isEmpty() )
+ {
+ path = TQString::fromLatin1( "/" );
+ isoEntry = root;
+ } else {
+ isoEntry = root->entry( path );
+ }
+ if ( !isoEntry )
+ {
+ error( TDEIO::ERR_DOES_NOT_EXIST, path );
+ return;
+ }
+ createUDSEntry( isoEntry, entry );
+ statEntry( entry );
+ finished();
+}
+
+void tdeio_isoProtocol::getFile( const KIsoFile *isoFileEntry, const TQString &path )
+{
+ unsigned long long size, pos = 0;
+ bool mime=false,zlib=false;
+ TQByteArray fileData, pointer_block, inbuf, outbuf;
+ char *pptr = 0;
+ compressed_file_header *hdr;
+ int block_shift;
+ unsigned long nblocks;
+ unsigned long fullsize = 0, block_size = 0, block_size2 = 0;
+ size_t ptrblock_bytes;
+ unsigned long cstart, cend, csize;
+ uLong bytes;
+
+ size = isoFileEntry->realsize();
+ if (size >= sizeof(sizeof(compressed_file_header))) zlib=true;
+ if (!size) size = isoFileEntry->size();
+ totalSize( size );
+ if (!size) mimeType("application/x-zerosize");
+
+ if (size && !m_isoFile->device()->isOpen()) m_isoFile->device()->open(IO_ReadOnly);
+
+ if (zlib) {
+ fileData=isoFileEntry->data(0, sizeof(compressed_file_header));
+ if ( fileData.size() == sizeof(compressed_file_header) &&
+ !memcmp(fileData.data(), zisofs_magic, sizeof (zisofs_magic)) ) {
+
+ hdr=(compressed_file_header*) fileData.data();
+ block_shift = hdr->block_size;
+ block_size = 1UL << block_shift;
+ block_size2 = block_size << 1;
+ fullsize = isonum_731(hdr->uncompressed_len);
+ nblocks = (fullsize + block_size - 1) >> block_shift;
+ ptrblock_bytes = (nblocks+1) * 4;
+ pointer_block=isoFileEntry->data( hdr->header_size << 2, ptrblock_bytes );
+ if (pointer_block.size() == ptrblock_bytes &&
+ inbuf.resize(block_size2) &&
+ outbuf.resize(block_size)) {
+
+ pptr = pointer_block.data();
+ } else {
+ error(TDEIO::ERR_COULD_NOT_READ, path);
+ return;
+ }
+ } else {
+ zlib=false;
+ }
+ }
+
+ while (pos<size) {
+ if (zlib) {
+ cstart = isonum_731(pptr);
+ pptr += 4;
+ cend = isonum_731(pptr);
+
+ csize = cend-cstart;
+
+ if ( csize == 0 ) {
+ outbuf.fill(0, -1);
+ } else {
+ if ( csize > block_size2 ) {
+ //err = EX_DATAERR;
+ break;
+ }
+
+ inbuf=isoFileEntry->data(cstart, csize);
+ if (inbuf.size() != csize) {
+ break;
+ }
+
+ bytes = block_size; // Max output buffer size
+ if ( (uncompress((Bytef*) outbuf.data(), &bytes, (Bytef*) inbuf.data(), csize)) != Z_OK ) {
+ break;
+ }
+ }
+
+ if ( ((fullsize > block_size) && (bytes != block_size))
+ || ((fullsize <= block_size) && (bytes < fullsize)) ) {
+
+ break;
+ }
+
+ if ( bytes > fullsize )
+ bytes = fullsize;
+ fileData.assign(outbuf);
+ fileData.resize(bytes);
+ fullsize -= bytes;
+ } else {
+ fileData=isoFileEntry->data(pos,65536);
+ if (fileData.size()==0) break;
+ }
+ if (!mime) {
+ KMimeMagicResult * result = KMimeMagic::self()->findBufferFileType( fileData, path );
+ kdDebug() << "Emitting mimetype " << result->mimeType() << endl;
+ mimeType( result->mimeType() );
+ mime=true;
+ }
+ data(fileData);
+ pos+=fileData.size();
+ processedSize(pos);
+ }
+
+ if (pos!=size) {
+ error(TDEIO::ERR_COULD_NOT_READ, path);
+ return;
+ }
+
+ fileData.resize(0);
+ data(fileData);
+ processedSize(pos);
+ finished();
+
+}
+
+void tdeio_isoProtocol::get( const KURL & url )
+{
+ kdDebug() << "tdeio_isoProtocol::get" << url.url() << endl;
+
+ TQString path;
+ if ( !checkNewFile( url.path(), path, url.hasRef() ? url.htmlRef().toInt() : -1 ) )
+ {
+ error( TDEIO::ERR_DOES_NOT_EXIST, url.path() );
+ return;
+ }
+
+ const KArchiveDirectory* root = m_isoFile->directory();
+ const KArchiveEntry* isoEntry = root->entry( path );
+
+ if ( !isoEntry )
+ {
+ error( TDEIO::ERR_DOES_NOT_EXIST, path );
+ return;
+ }
+ if ( isoEntry->isDirectory() )
+ {
+ error( TDEIO::ERR_IS_DIRECTORY, path );
+ return;
+ }
+
+ const KIsoFile* isoFileEntry = static_cast<const KIsoFile *>(isoEntry);
+ if ( !isoEntry->symlink().isEmpty() )
+ {
+ kdDebug() << "Redirection to " << isoEntry->symlink() << endl;
+ KURL realURL( url, isoEntry->symlink() );
+ kdDebug() << "realURL= " << realURL.url() << endl;
+ redirection( realURL.url() );
+ finished();
+ return;
+ }
+ getFile(isoFileEntry, path);
+ if (m_isoFile->device()->isOpen()) m_isoFile->device()->close();
+}
diff --git a/src/iso/iso.h b/src/iso/iso.h
new file mode 100644
index 0000000..b284e22
--- /dev/null
+++ b/src/iso/iso.h
@@ -0,0 +1,51 @@
+/***************************************************************************
+ iso.h
+ -------------------
+ begin : Oct 25 2002
+ copyright : (C) 2002 by Szombathelyi Gyrgy
+ email : gyurco@users.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. *
+ * *
+ ***************************************************************************/
+
+ /* This file is heavily based on tar.h from tdebase
+ * (c) David Faure <faure@kde.org>
+ */
+
+#ifndef _ISO_H
+#define _ISO_H
+
+#include <tdeio/slavebase.h>
+#include <sys/types.h>
+#include "kisofile.h"
+
+class KIso;
+
+class tdeio_isoProtocol : public TDEIO::SlaveBase
+{
+public:
+ tdeio_isoProtocol( const TQCString &pool, const TQCString &app );
+ virtual ~tdeio_isoProtocol();
+
+ virtual void listDir( const KURL & url );
+ virtual void stat( const KURL & url );
+ virtual void get( const KURL & url );
+
+protected:
+ void getFile( const KIsoFile *isoFileEntry, const TQString &path );
+ void createUDSEntry( const KArchiveEntry * isoEntry, TDEIO::UDSEntry & entry );
+ bool checkNewFile( TQString fullPath, TQString & path, int startsec );
+
+ KIso * m_isoFile;
+ time_t m_mtime;
+ int m_mode;
+};
+
+#endif
diff --git a/src/iso/iso.protocol b/src/iso/iso.protocol
new file mode 100644
index 0000000..77f7530
--- /dev/null
+++ b/src/iso/iso.protocol
@@ -0,0 +1,12 @@
+[Protocol]
+exec=tdeio_iso
+protocol=iso
+listing=Name,Type,Size,Date,AccessDate,CreationDate,Access,Owner,Group,Link
+input=filesystem
+output=filesystem
+reading=true
+source=true
+Icon=cd
+Description=A tdeioslave for ISO9660 filesystems
+MimeType=application/x-iso
+X-DocPath=tdeioslave/iso/index.html
diff --git a/src/iso/isoservice.desktop b/src/iso/isoservice.desktop
new file mode 100644
index 0000000..55b4b23
--- /dev/null
+++ b/src/iso/isoservice.desktop
@@ -0,0 +1,14 @@
+[Desktop Entry]
+Encoding=UTF-8
+Actions=OpenISO
+X-TDE-ServiceTypes=inode/blockdevice,application/x-iso
+
+[Desktop Action OpenISO]
+Comment=ISO9660 View
+Comment[hu]=ISO9660 Nézet
+Comment[fr]=Lecteur ISO9660
+Icon=cd
+Name=ISO9660 View
+Name[hu]=ISO9660 Nézet
+Name[fr]=Lecteur ISO9660
+Exec=kfmclient exec iso:%f
diff --git a/src/iso/kiso.cpp b/src/iso/kiso.cpp
new file mode 100644
index 0000000..1e8f192
--- /dev/null
+++ b/src/iso/kiso.cpp
@@ -0,0 +1,469 @@
+/***************************************************************************
+ kiso.cpp
+ -------------------
+ begin : Oct 25 2002
+ copyright : (C) 2002 by Szombathelyi Gy�gy
+ email : gyurco@users.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. *
+ * *
+ ***************************************************************************/
+
+ /* This file is heavily based on ktar.cpp from tdelibs (c) David Faure */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <grp.h>
+#include <pwd.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <tqcstring.h>
+#include <tqdir.h>
+#include <tqfile.h>
+#include <kdebug.h>
+#include <kurl.h>
+#include <kmimetype.h>
+#include <tdeconfig.h>
+#include <kfilterdev.h>
+#include <kfilterbase.h>
+
+#include "kiso.h"
+#include "libisofs/isofs.h"
+#include "qfilehack.h"
+
+
+#ifdef __linux__
+#undef __STRICT_ANSI__
+#include <linux/cdrom.h>
+#define __STRICT_ANSI__
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/////////////////////////// KIso ///////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+
+/**
+ * puts the track layout of the device 'fname' into 'tracks'
+ * tracks structure: start sector, track number, ...
+ * tracks should be 100*2 entry long (this is the maximum in the CD-ROM standard)
+ * currently it's linux only, porters are welcome
+ */
+static int getTracks(const char *fname,int *tracks) {
+ int ret=0;
+ memset(tracks,0,200*sizeof(int));
+
+#ifdef __linux__
+ int fd,i;
+ struct cdrom_tochdr tochead;
+ struct cdrom_tocentry tocentry;
+
+ kdDebug() << "getTracks open:" << fname << endl;
+ fd=open(fname, O_RDONLY | O_NONBLOCK);
+ if (fd > 0) {
+ if (ioctl(fd,CDROMREADTOCHDR,&tochead)!=-1) {
+ kdDebug() << "getTracks first track:" << tochead.cdth_trk0
+ << " last track " << tochead.cdth_trk1 << endl;
+ for (i=tochead.cdth_trk0;i<=tochead.cdth_trk1;i++) {
+ if (ret>99) break;
+ memset(&tocentry,0,sizeof(struct cdrom_tocentry));
+ tocentry.cdte_track=i;
+ tocentry.cdte_format=CDROM_LBA;
+ if (ioctl(fd,CDROMREADTOCENTRY,&tocentry)<0) break;
+ kdDebug() << "getTracks got track " << i << " starting at: " <<
+ tocentry.cdte_addr.lba << endl;
+ if ((tocentry.cdte_ctrl & 0x4) == 0x4) {
+ tracks[ret<<1]=tocentry.cdte_addr.lba;
+ tracks[(ret<<1)+1]=i;
+ ret++;
+ }
+ }
+ }
+ close(fd);
+ }
+
+#endif
+
+ return ret;
+}
+
+class KIso::KIsoPrivate
+{
+public:
+ KIsoPrivate() {}
+ TQStringList dirList;
+};
+
+KIso::KIso( const TQString& filename, const TQString & _mimetype )
+ : KArchive( 0L )
+{
+ m_startsec = -1;
+ m_filename = filename;
+ d = new KIsoPrivate;
+ TQString mimetype( _mimetype );
+ bool forced = true;
+ if ( mimetype.isEmpty() )
+ {
+ mimetype = KMimeType::findByFileContent( filename )->name();
+ kdDebug() << "KIso::KIso mimetype=" << mimetype << endl;
+
+ // Don't move to prepareDevice - the other constructor theoretically allows ANY filter
+ if ( mimetype == "application/x-tgz" || mimetype == "application/x-targz" || // the latter is deprecated but might still be around
+ mimetype == "application/x-webarchive" )
+ // that's a gzipped tar file, so ask for gzip filter
+ mimetype = "application/x-gzip";
+ else if ( mimetype == "application/x-tbz" ) // that's a bzipped2 tar file, so ask for bz2 filter
+ mimetype = "application/x-bzip2";
+ else if ( mimetype == "application/x-txz" ) // that's a xzipped tar file, so ask for xz filter
+ mimetype = "application/x-xz";
+ else
+ {
+ // Something else. Check if it's not really gzip though (e.g. for KOffice docs)
+ TQFile file( filename );
+ if ( file.open( IO_ReadOnly ) )
+ {
+ unsigned char firstByte = file.getch();
+ unsigned char secondByte = file.getch();
+ unsigned char thirdByte = file.getch();
+ if ( firstByte == 0037 && secondByte == 0213 )
+ mimetype = "application/x-gzip";
+ else if ( firstByte == 'B' && secondByte == 'Z' && thirdByte == 'h' )
+ mimetype = "application/x-bzip2";
+ else if ( firstByte == 'P' && secondByte == 'K' && thirdByte == 3 )
+ {
+ unsigned char fourthByte = file.getch();
+ if ( fourthByte == 4 )
+ mimetype = "application/x-zip";
+ }
+ else if ( firstByte == 0xfd && secondByte == '7' && thirdByte == 'z' )
+ {
+ unsigned char fourthByte = file.getch();
+ unsigned char fifthByte = file.getch();
+ unsigned char sixthByte = file.getch();
+ if ( fourthByte == 'X' && fifthByte == 'Z' && sixthByte == 0)
+ mimetype = "application/x-xz";
+ }
+ }
+ }
+ forced = false;
+ }
+
+ prepareDevice( filename, mimetype, forced );
+}
+
+void KIso::prepareDevice( const TQString & filename,
+ const TQString & mimetype, bool forced )
+{
+ /* 'hack' for TQt's false assumption that only S_ISREG is seekable */
+ if( "inode/blockdevice" == mimetype )
+ setDevice( new QFileHack( filename ) );
+ else
+ {
+ if("application/x-gzip" == mimetype || "application/x-bzip2" == mimetype ||
+ "application/x-xz" == mimetype)
+ forced = true;
+
+ TQIODevice *dev = KFilterDev::deviceForFile( filename, mimetype, forced );
+ if( dev )
+ setDevice( dev );
+ }
+
+}
+
+KIso::KIso( TQIODevice * dev )
+ : KArchive( dev )
+{
+ d = new KIsoPrivate;
+}
+
+KIso::~KIso()
+{
+ // mjarrett: Closes to prevent ~KArchive from aborting w/o device
+ if( isOpened() )
+ close();
+ if ( !m_filename.isEmpty() )
+ delete device(); // we created it ourselves
+ delete d;
+}
+
+/* callback function for libisofs */
+static int readf(char *buf, int start, int len,void *udata) {
+
+ TQIODevice* dev = ( static_cast<KIso*> (udata) )->device();
+
+ if (dev->at(start<<11)) {
+ if ((dev->readBlock(buf, len<<11)) != -1) return (len);
+ }
+ kdDebug() << "KIso::ReadRequest failed start: " << start << " len: " << len << endl;
+
+ return -1;
+}
+
+/* callback function for libisofs */
+static int mycallb(struct iso_directory_record *idr,void *udata) {
+
+ KIso *iso = static_cast<KIso*> (udata);
+ TQString path,user,group,symlink;
+ int i;
+ int access;
+ int time,cdate,adate;
+ rr_entry rr;
+ bool special=false;
+ KArchiveEntry *entry=NULL,*oldentry=NULL;
+ char z_algo[2],z_params[2];
+ int z_size=0;
+
+ if ((idr->flags[0] & 1) && !iso->showhidden) return 0;
+ if (iso->level) {
+ if (isonum_711(idr->name_len)==1) {
+ switch (idr->name[0]) {
+ case 0:
+ path+=(".");
+ special=true;
+ break;
+ case 1:
+ path+=("..");
+ special=true;
+ break;
+ }
+ }
+ if (iso->showrr && ParseRR(idr,&rr)>0) {
+ if (!special) path=rr.name;
+ symlink=rr.sl;
+ access=rr.mode;
+ time=rr.t_mtime;
+ adate=rr.t_atime;
+ cdate=rr.t_ctime;
+ user.setNum(rr.uid);
+ group.setNum(rr.gid);
+ z_algo[0]=rr.z_algo[0];z_algo[1]=rr.z_algo[1];
+ z_params[0]=rr.z_params[0];z_params[1]=rr.z_params[1];
+ z_size=rr.z_size;
+ } else {
+ access=iso->dirent->permissions() & ~S_IFMT;
+ adate=cdate=time=isodate_915(idr->date,0);
+ user=iso->dirent->user();
+ group=iso->dirent->group();
+ if (idr->flags[0] & 2) access |= S_IFDIR; else access |= S_IFREG;
+ if (!special) {
+ if (iso->joliet) {
+ for (i=0;i<(isonum_711(idr->name_len)-1);i+=2) {
+ TQChar ch( be2me_16(*((ushort*)&(idr->name[i]))) );
+ if (ch==';') break;
+ path+=ch;
+ }
+ } else {
+ for (i=0;i<isonum_711(idr->name_len);i++) {
+ if (idr->name[i]==';') break;
+ if (idr->name[i]) path+=(idr->name[i]);
+ }
+ }
+ if (path.endsWith(".")) path.setLength(path.length()-1);
+ }
+ }
+ if (iso->showrr) FreeRR(&rr);
+ if (idr->flags[0] & 2) {
+ entry = new KIsoDirectory( iso, path, access | S_IFDIR, time, adate, cdate,
+ user, group, symlink );
+ } else {
+ entry = new KIsoFile( iso, path, access, time, adate, cdate,
+ user, group, symlink, isonum_733(idr->extent)<<11,isonum_733(idr->size) );
+ if (z_size) (static_cast <KIsoFile*> (entry))->setZF(z_algo,z_params,z_size);
+
+ }
+ iso->dirent->addEntry(entry);
+ }
+ if ( (idr->flags[0] & 2) && (iso->level==0 || !special) ) {
+ if (iso->level) {
+ oldentry=iso->dirent;
+ iso->dirent=static_cast<KIsoDirectory*> (entry);
+ }
+ iso->level++;
+ ProcessDir(&readf,isonum_733(idr->extent),isonum_733(idr->size),&mycallb,udata);
+ iso->level--;
+ if (iso->level) iso->dirent=static_cast<KIsoDirectory*> (oldentry);
+ }
+ return 0;
+}
+
+void KIso::addBoot(struct el_torito_boot_descriptor* bootdesc) {
+
+ int i,size;
+ boot_head boot;
+ boot_entry *be;
+ TQString path;
+ KIsoFile *entry;
+
+ entry=new KIsoFile( this, "Catalog", dirent->permissions() & ~S_IFDIR,
+ dirent->date(), dirent->adate(), dirent->cdate(),
+ dirent->user(), dirent->group(), TQString(),
+ isonum_731(bootdesc->boot_catalog)<<11, 2048 );
+ dirent->addEntry(entry);
+ if (!ReadBootTable(&readf,isonum_731(bootdesc->boot_catalog),&boot,this)) {
+ i=1;
+ be=boot.defentry;
+ while (be) {
+ size=BootImageSize( isonum_711(((struct default_entry*) be->data)->media),
+ isonum_721(((struct default_entry*) be->data)->seccount));
+ path="Default Image";
+ if (i>1) path += " (" + TQString::number(i) + ")";
+ entry=new KIsoFile( this, path, dirent->permissions() & ~S_IFDIR,
+ dirent->date(), dirent->adate(), dirent->cdate(),
+ dirent->user(), dirent->group(), TQString(),
+ isonum_731(((struct default_entry*) be->data)->start)<<11, size<<9 );
+ dirent->addEntry(entry);
+ be=be->next;
+ i++;
+ }
+
+ FreeBootTable(&boot);
+ }
+}
+
+void KIso::readParams()
+{
+ TDEConfig *config;
+
+ config = new TDEConfig("tdeio_isorc");
+
+ showhidden=config->readBoolEntry("showhidden",false);
+ showrr=config->readBoolEntry("showrr",true);
+ delete config;
+}
+
+bool KIso::openArchive( int mode )
+{
+ iso_vol_desc *desc;
+ TQString path,tmp,uid,gid;
+ struct stat buf;
+ int tracks[2*100],trackno=0,i,access,c_b,c_i,c_j;
+ KArchiveDirectory *root;
+ struct iso_directory_record* idr;
+ struct el_torito_boot_descriptor* bootdesc;
+
+ if ( mode == IO_WriteOnly )
+ return false;
+
+ readParams();
+ d->dirList.clear();
+
+ tracks[0]=0;
+ if (m_startsec>0) tracks[0]=m_startsec;
+ kdDebug() << " m_startsec: " << m_startsec << endl;
+ /* We'll use the permission and user/group of the 'host' file except
+ * in Rock Ridge, where the permissions are stored on the file system
+ */
+ if (::stat( m_filename.local8Bit(), &buf )<0) {
+ /* defaults, if stat fails */
+ memset(&buf,0,sizeof(struct stat));
+ buf.st_mode=0777;
+ } else {
+ /* If it's a block device, try to query the track layout (for multisession) */
+ if (m_startsec == -1 && S_ISBLK(buf.st_mode))
+ trackno=getTracks(m_filename.latin1(),(int*) &tracks);
+ }
+ uid.setNum(buf.st_uid);
+ gid.setNum(buf.st_gid);
+ access = buf.st_mode & ~S_IFMT;
+
+ kdDebug() << "KIso::openArchive number of tracks: " << trackno << endl;
+
+ if (trackno==0) trackno=1;
+ for (i=0;i<trackno;i++) {
+
+ c_b=1;c_i=1;c_j=1;
+ root=rootDir();
+ if (trackno>1) {
+ path=TQString();
+ TQTextOStream(&path) << "Track " << tracks[(i<<1)+1];
+ root = new KIsoDirectory( this, path, access | S_IFDIR,
+ buf.st_mtime, buf.st_atime, buf.st_ctime, uid, gid, TQString() );
+ rootDir()->addEntry(root);
+ }
+
+ desc=ReadISO9660(&readf,tracks[i<<1],this);
+ if (!desc) {
+ kdDebug() << "KIso::openArchive no volume descriptors" << endl;
+ continue;
+ }
+
+ while (desc) {
+ switch (isonum_711(desc->data.type)) {
+ case ISO_VD_BOOT:
+
+ bootdesc=(struct el_torito_boot_descriptor*) &(desc->data);
+ if ( !memcmp(EL_TORITO_ID,bootdesc->system_id,ISODCL(8,39)) ) {
+ path="El Torito Boot";
+ if (c_b>1) path += " (" + TQString::number(c_b) + ")";
+
+ dirent = new KIsoDirectory( this, path, access | S_IFDIR,
+ buf.st_mtime, buf.st_atime, buf.st_ctime, uid, gid, TQString() );
+ root->addEntry(dirent);
+
+ addBoot(bootdesc);
+ c_b++;
+ }
+ break;
+
+ case ISO_VD_PRIMARY:
+ case ISO_VD_SUPPLEMENTARY:
+ idr=(struct iso_directory_record*) &( ((struct iso_primary_descriptor*) &desc->data)->root_directory_record);
+ joliet = JolietLevel(&desc->data);
+ if (joliet) {
+ TQTextOStream(&path) << "Joliet level " << joliet;
+ if (c_j>1) path += " (" + TQString::number(c_j) + ")";
+ } else {
+ path = "ISO9660";
+ if (c_i>1) path += " (" + TQString::number(c_i) + ")";
+ }
+ dirent = new KIsoDirectory( this, path, access | S_IFDIR,
+ buf.st_mtime, buf.st_atime, buf.st_ctime, uid, gid, TQString() );
+ root->addEntry(dirent);
+ level=0;
+ mycallb(idr, this );
+ if (joliet) c_j++; else c_i++;
+ break;
+ }
+ desc=desc->next;
+ }
+ free(desc);
+ }
+ device()->close();
+ return true;
+}
+
+bool KIso::closeArchive()
+{
+ d->dirList.clear();
+ return true;
+}
+
+bool KIso::writeDir( const TQString&, const TQString&, const TQString& )
+{
+ return false;
+}
+
+bool KIso::prepareWriting( const TQString&, const TQString&, const TQString&, uint)
+{
+ return false;
+}
+
+bool KIso::doneWriting( uint )
+{
+ return false;
+}
+
+void KIso::virtual_hook( int id, void* data )
+{ KArchive::virtual_hook( id, data ); }
+
diff --git a/src/iso/kiso.h b/src/iso/kiso.h
new file mode 100644
index 0000000..8eb42b0
--- /dev/null
+++ b/src/iso/kiso.h
@@ -0,0 +1,112 @@
+/***************************************************************************
+ kiso.h
+ -------------------
+ begin : Oct 25 2002
+ copyright : (C) 2002 by Szombathelyi Gy�gy
+ email : gyurco@users.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. *
+ * *
+ ***************************************************************************/
+
+ /* This file is heavily based on ktar.h from tdelibs
+ * (c) Torben Weis <weis@kde.org>, David Faure <faure@kde.org>
+ */
+
+#ifndef KISO_H
+#define KISO_H
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <tqdatetime.h>
+#include <tqstring.h>
+#include <tqstringlist.h>
+#include <tqdict.h>
+
+#include "kisofile.h"
+#include "kisodirectory.h"
+
+/**
+ * @short A class for reading (optionnally compressed) iso9660 files.
+ * @author Gy�gy Szombathelyi <gyurco@users.sourceforge.net>,
+ * Torben Weis <weis@kde.org>, David Faure <faure@kde.org>
+ */
+class KIso : public KArchive
+{
+public:
+ /**
+ * Creates an instance that operates on the given filename.
+ * using the compression filter associated to given mimetype.
+ *
+ * @param filename is a local path (e.g. "/home/weis/myfile.tgz")
+ * @param mimetype "application/x-gzip" or "application/x-bzip2"
+ * Do not use application/x-tgz or so. Only the compression layer !
+ * If the mimetype is ommitted, it will be determined from the filename.
+ */
+ KIso( const TQString& filename, const TQString & mimetype = TQString() );
+
+ /**
+ * Creates an instance that operates on the given device.
+ * The device can be compressed (KFilterDev) or not (TQFile, etc.).
+ * WARNING: don't assume that giving a TQFile here will decompress the file,
+ * in case it's compressed!
+ */
+ KIso( TQIODevice * dev );
+
+ /**
+ * If the .iso is still opened, then it will be
+ * closed automatically by the destructor.
+ */
+ virtual ~KIso();
+
+ /**
+ * The name of the os file, as passed to the constructor
+ * Null if you used the TQIODevice constructor.
+ */
+ TQString fileName() { return m_filename; }
+
+ bool writeDir( const TQString& , const TQString& , const TQString& );
+ bool prepareWriting( const TQString& , const TQString& , const TQString& , uint );
+ bool doneWriting( uint );
+
+ void setStartSec(int startsec) { m_startsec = startsec; }
+ int startSec() { return m_startsec; }
+
+ bool showhidden,showrr;
+ int level,joliet;
+ KIsoDirectory *dirent;
+protected:
+ /**
+ * Opens the archive for reading.
+ * Parses the directory listing of the archive
+ * and creates the KArchiveDirectory/KArchiveFile entries.
+ *
+ */
+ void readParams();
+ virtual bool openArchive( int mode );
+ virtual bool closeArchive();
+
+private:
+ /**
+ * @internal
+ */
+ void addBoot(struct el_torito_boot_descriptor* bootdesc);
+ void prepareDevice( const TQString & filename, const TQString & mimetype, bool forced = false );
+ int m_startsec;
+
+ TQString m_filename;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KIsoPrivate;
+ KIsoPrivate * d;
+};
+
+#endif
diff --git a/src/iso/kisodirectory.cpp b/src/iso/kisodirectory.cpp
new file mode 100644
index 0000000..74987a2
--- /dev/null
+++ b/src/iso/kisodirectory.cpp
@@ -0,0 +1,31 @@
+/***************************************************************************
+ kisodirectory.cpp - description
+ -------------------
+ begin : Wed Oct 30 2002
+ copyright : (C) 2002 by Szombathelyi Gyrgy
+ email : gyurco@users.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 "kisodirectory.h"
+
+KIsoDirectory::KIsoDirectory( KArchive* archive, const TQString& name, int access,
+ int date, int adate, int cdate, const TQString& user, const TQString& group,
+ const TQString& symlink) :
+ KArchiveDirectory(archive, name, access, date, user, group, symlink) {
+
+
+ m_adate=adate;
+ m_cdate=cdate;
+}
+
+KIsoDirectory::~KIsoDirectory(){
+}
diff --git a/src/iso/kisodirectory.h b/src/iso/kisodirectory.h
new file mode 100644
index 0000000..74045ac
--- /dev/null
+++ b/src/iso/kisodirectory.h
@@ -0,0 +1,40 @@
+/***************************************************************************
+ kisodirectory.h - description
+ -------------------
+ begin : Wed Oct 30 2002
+ copyright : (C) 2002 by Szombathelyi Gyrgy
+ email : gyurco@users.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 KISODIRECTORY_H
+#define KISODIRECTORY_H
+
+#include <tqstring.h>
+#include <karchive.h>
+
+/**
+ *@author Szombathelyi Gyrgy
+ */
+
+class KIsoDirectory : public KArchiveDirectory {
+public:
+ KIsoDirectory( KArchive* archive, const TQString& name, int access, int date,
+ int adate,int cdate, const TQString& user, const TQString& group,
+ const TQString& symlink);
+ ~KIsoDirectory();
+ int adate() const { return m_adate; }
+ int cdate() const { return m_cdate; }
+private:
+ int m_adate, m_cdate;
+};
+
+#endif
diff --git a/src/iso/kisofile.cpp b/src/iso/kisofile.cpp
new file mode 100644
index 0000000..afac16b
--- /dev/null
+++ b/src/iso/kisofile.cpp
@@ -0,0 +1,53 @@
+/***************************************************************************
+ kisofile.cpp - description
+ -------------------
+ begin : Wed Oct 30 2002
+ copyright : (C) 2002 by Szombathelyi Gy�gy
+ email : gyurco@users.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 "kisofile.h"
+#include <kdebug.h>
+
+KIsoFile::KIsoFile( KArchive* archive, const TQString& name, int access,
+ int date, int adate,int cdate, const TQString& user, const TQString& group,
+ const TQString& symlink,int pos, int size) :
+ KArchiveFile(archive, name, access, date, user, group, symlink, pos, size) {
+
+
+ m_adate=adate;
+ m_cdate=cdate;
+ m_algo[0]=0;m_algo[1]=0;m_parms[0]=0;m_parms[1]=0;m_realsize=0;
+}
+
+KIsoFile::~KIsoFile(){
+}
+
+void KIsoFile::setZF(char algo[2],char parms[2],int realsize) {
+ m_algo[0]=algo[0];m_algo[1]=algo[1];
+ m_parms[0]=parms[0];m_parms[1]=parms[1];
+ m_realsize=realsize;
+}
+
+TQByteArray KIsoFile::data(long long pos, int count) const {
+ TQByteArray r;
+ int rlen;
+
+ if ( archive()->device()->at(position()+pos) &&
+ r.resize( ((pos+count) < size()) ? count : size()-pos) ) {
+ rlen=archive()->device()->readBlock( r.data(), r.size() );
+ if (rlen ==- 1) r.resize(0);
+ else if (rlen != (int)r.size()) r.resize(rlen);
+ }
+
+ return r;
+}
diff --git a/src/iso/kisofile.h b/src/iso/kisofile.h
new file mode 100644
index 0000000..193509c
--- /dev/null
+++ b/src/iso/kisofile.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ kisofile.h - description
+ -------------------
+ begin : Wed Oct 30 2002
+ copyright : (C) 2002 by Szombathelyi Gy�gy
+ email : gyurco@users.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 KISOFILE_H
+#define KISOFILE_H
+
+#include <tqstring.h>
+#include <karchive.h>
+
+/**
+ *@author Szombathelyi Gy�gy
+ */
+
+class KIsoFile : public KArchiveFile {
+public:
+ KIsoFile( KArchive* archive, const TQString& name, int access, int date,
+ int adate,int cdate, const TQString& user, const TQString& group,
+ const TQString& symlink, int pos, int size);
+ ~KIsoFile();
+ void setZF(char algo[2],char parms[2],int realsize);
+ int adate() const { return m_adate; }
+ int cdate() const { return m_cdate; }
+ long long realsize() const { return m_realsize; }
+
+ virtual TQByteArray data(long long pos, int count) const;
+private:
+ /* hide this member function, it's broken by design, because the full
+ data often requires too much memory */
+ char m_algo[2],m_parms[2];
+ long long m_realsize;
+ int m_adate, m_cdate;
+ long long m_curpos;
+};
+
+#endif
diff --git a/src/iso/libisofs/COPYING b/src/iso/libisofs/COPYING
new file mode 100644
index 0000000..c7aea18
--- /dev/null
+++ b/src/iso/libisofs/COPYING
@@ -0,0 +1,280 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
diff --git a/src/iso/libisofs/ChangeLog b/src/iso/libisofs/ChangeLog
new file mode 100644
index 0000000..fb46b80
--- /dev/null
+++ b/src/iso/libisofs/ChangeLog
@@ -0,0 +1,6 @@
+0.1 -> 0.2
+
+- Critical directory parsing bug fixed
+- Call backs only if some sanity checks on the directory entry succeeds
+ (length checks to avoid buffer overrun if received corrupt data)
+- Preliminary El Torito boot specification support (No multiple boot entries yet)
diff --git a/src/iso/libisofs/Makefile.am b/src/iso/libisofs/Makefile.am
new file mode 100644
index 0000000..f859581
--- /dev/null
+++ b/src/iso/libisofs/Makefile.am
@@ -0,0 +1,18 @@
+noinst_LTLIBRARIES = libisofs.la
+
+
+INCLUDES = $(all_includes)
+
+
+#LDFLAGS =
+
+libisofs_la_METASOURCES=AUTO
+
+libisofs_la_SOURCES = isofs.c
+#libisofs_la_LIBADD = $(LIB_TDEIO)
+
+#libisofs_la_LDFLAGS = -module $(all_libraries) $(KDE_PLUGIN)
+
+
+
+noinst_HEADERS = bswap.h el_torito.h iso_fs.h isofs.h rock.h
diff --git a/src/iso/libisofs/README b/src/iso/libisofs/README
new file mode 100644
index 0000000..45d3bff
--- /dev/null
+++ b/src/iso/libisofs/README
@@ -0,0 +1,24 @@
+This is the 0.2 release of libisofs. For changes, see the ChangeLog.
+
+Libisofs implements the reading of the famous ISO-9660 (ECMA-119) file system,
+found on CD-ROM media. It also supports the Rock Ridge Interchange Protocol and
+Microsoft Joliet extensions. It allows user-mode programs to query the
+filesystem volume descriptors and traverse through the directory structure.
+Preliminary support for El-Torito boot CDs are added in version 0.2.
+
+To use it in your project, I recommend to copy bswap.h, isofs.h, iso_fs.h,
+el_torito.h rock.h and isofs.c to your sources, and include isofs.h in the
+appropriate places.
+
+Currently only the directory tables are parsed, the path tables are not.
+(The path tables contain redundant information.)
+
+Also a sample program can be compiled with the supplied Makefile. Simply
+execute 'make', it should create the executable file isofs.
+
+On big-endian systems, you need to define WORDS_BIGENDIAN (either in the
+compiler command-line, or if you defined HAVE_CONFIG_H, in config.h)
+
+
+Gyrgy Szombathelyi <gyurco@users.sourceforge.net>
+http://libcdrom.sourceforge.net/libisofs.html
diff --git a/src/iso/libisofs/bswap.h b/src/iso/libisofs/bswap.h
new file mode 100644
index 0000000..bda19c0
--- /dev/null
+++ b/src/iso/libisofs/bswap.h
@@ -0,0 +1,94 @@
+/* From the mplayer project (www.mplayerhq.hu) */
+
+#ifndef __BSWAP_H__
+#define __BSWAP_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_BYTESWAP_H
+#include <byteswap.h>
+#else
+
+#ifdef ARCH_X86
+inline static unsigned short ByteSwap16(unsigned short x)
+{
+ __asm("xchgb %b0,%h0" :
+ "=q" (x) :
+ "0" (x));
+ return x;
+}
+#define bswap_16(x) ByteSwap16(x)
+
+inline static unsigned int ByteSwap32(unsigned int x)
+{
+#if __CPU__ > 386
+ __asm("bswap %0":
+ "=r" (x) :
+#else
+ __asm("xchgb %b0,%h0\n"
+ " rorl $16,%0\n"
+ " xchgb %b0,%h0":
+ "=q" (x) :
+#endif
+ "0" (x));
+ return x;
+}
+#define bswap_32(x) ByteSwap32(x)
+
+inline static unsigned long long int ByteSwap64(unsigned long long int x)
+{
+ union { __extension__ unsigned long long int __ll;
+ unsigned int __l[2]; } __x;
+ asm("xchgl %0,%1":
+ "=r"(__x.__l[0]),"=r"(__x.__l[1]):
+ "0"(bswap_32((unsigned long)x)),"1"(bswap_32((unsigned long)(x>>32))));
+ return __x.__ll;
+}
+#define bswap_64(x) ByteSwap64(x)
+
+#else
+
+#define bswap_16(x) (((x) & 0x00ff) << 8 | ((x) & 0xff00) >> 8)
+
+
+/* code from bits/byteswap.h (C) 1997, 1998 Free Software Foundation, Inc. */
+#define bswap_32(x) \
+ ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
+ (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
+
+#define bswap_64(x) \
+ (__extension__ \
+ ({ union { __extension__ unsigned long long int __ll; \
+ unsigned int __l[2]; } __w, __r; \
+ __w.__ll = (x); \
+ __r.__l[0] = bswap_32 (__w.__l[1]); \
+ __r.__l[1] = bswap_32 (__w.__l[0]); \
+ __r.__ll; }))
+#endif /* !ARCH_X86 */
+
+#endif /* !HAVE_BYTESWAP_H */
+
+/*
+ be2me ... BigEndian to MachineEndian
+ le2me ... LittleEndian to MachineEndian
+*/
+
+#ifdef WORDS_BIGENDIAN
+#define be2me_16(x) (x)
+#define be2me_32(x) (x)
+#define be2me_64(x) (x)
+#define le2me_16(x) bswap_16(x)
+#define le2me_32(x) bswap_32(x)
+#define le2me_64(x) bswap_64(x)
+#else
+#define be2me_16(x) bswap_16(x)
+#define be2me_32(x) bswap_32(x)
+#define be2me_64(x) bswap_64(x)
+#define le2me_16(x) (x)
+#define le2me_32(x) (x)
+#define le2me_64(x) (x)
+#endif
+
+#endif
diff --git a/src/iso/libisofs/configure.in.in b/src/iso/libisofs/configure.in.in
new file mode 100644
index 0000000..78e5b1a
--- /dev/null
+++ b/src/iso/libisofs/configure.in.in
@@ -0,0 +1 @@
+AC_CHECK_HEADERS(byteswap.h)
diff --git a/src/iso/libisofs/el_torito.h b/src/iso/libisofs/el_torito.h
new file mode 100644
index 0000000..cba83f7
--- /dev/null
+++ b/src/iso/libisofs/el_torito.h
@@ -0,0 +1,63 @@
+#ifndef ELTORITO_H
+#define ELTORITO_H 1
+
+#include "iso_fs.h"
+
+#define EL_TORITO_ID "EL TORITO SPECIFICATION\0\0\0\0\0\0\0\0\0"
+
+struct el_torito_boot_descriptor {
+ char type [ISODCL ( 1, 1)]; /* 711 */
+ char id [ISODCL ( 2, 6)];
+ char version [ISODCL ( 7, 7)]; /* 711 */
+ char system_id [ISODCL ( 8, 39)]; /* achars */
+ char unused [ISODCL ( 40, 71)];
+ char boot_catalog [ISODCL ( 72, 75)]; /* 731 */
+};
+
+struct validation_entry {
+ char type [ISODCL ( 1, 1)]; /* 1 */
+ char platform [ISODCL ( 2, 2)];
+ char unused [ISODCL ( 3, 4)];
+ char id [ISODCL ( 5, 28)];
+ char cheksum [ISODCL ( 29, 30)];
+ char key [ISODCL ( 31, 31)]; /* 0x55 */
+ char key2 [ISODCL ( 32, 32)]; /* 0xaa */
+};
+
+struct default_entry {
+ char bootid [ISODCL ( 1, 1)];
+ char media [ISODCL ( 2, 2)];
+ char loadseg [ISODCL ( 3, 4)];
+ char systype [ISODCL ( 5, 5)];
+ char unused [ISODCL ( 6, 6)];
+ char seccount [ISODCL ( 7, 8)];
+ char start [ISODCL ( 9, 12)];
+ char unused2 [ISODCL ( 13, 32)];
+};
+
+struct section_header {
+ char headerid [ISODCL ( 1, 1)];
+ char platform [ISODCL ( 2, 2)];
+ char entries [ISODCL ( 3, 4)];
+ char id [ISODCL ( 5, 32)];
+};
+
+struct section_entry {
+ char bootid [ISODCL ( 1, 1)];
+ char media [ISODCL ( 2, 2)];
+ char loadseg [ISODCL ( 3, 4)];
+ char systype [ISODCL ( 5, 5)];
+ char unused [ISODCL ( 6, 6)];
+ char seccount [ISODCL ( 7, 8)];
+ char start [ISODCL ( 9, 12)];
+ char selcrit [ISODCL ( 13, 13)];
+ char vendor_selcrit [ISODCL ( 14, 32)];
+};
+
+struct section_entry_ext {
+ char extid [ISODCL ( 1, 1)];
+ char extrec [ISODCL ( 2, 2)];
+ char vendor_selcrit [ISODCL ( 3, 32)];
+};
+
+#endif
diff --git a/src/iso/libisofs/iso_fs.h b/src/iso/libisofs/iso_fs.h
new file mode 100644
index 0000000..43353b0
--- /dev/null
+++ b/src/iso/libisofs/iso_fs.h
@@ -0,0 +1,219 @@
+/* From the linux kernel */
+
+#ifndef _ISO_FS_H
+#define _ISO_FS_H 1
+
+#include "bswap.h"
+
+/*
+ * The isofs filesystem constants/structures
+ */
+
+/* This part borrowed from the bsd386 isofs */
+#define ISODCL(from, to) (to - from + 1)
+
+struct iso_volume_descriptor {
+ char type[ISODCL(1,1)]; /* 711 */
+ char id[ISODCL(2,6)];
+ char version[ISODCL(7,7)];
+ char data[ISODCL(8,2048)];
+};
+
+/* volume descriptor types */
+#define ISO_VD_BOOT 0
+#define ISO_VD_PRIMARY 1
+#define ISO_VD_SUPPLEMENTARY 2
+#define ISO_VD_END 255
+
+#define ISO_STANDARD_ID "CD001"
+
+struct iso_primary_descriptor {
+ char type [ISODCL ( 1, 1)]; /* 711 */
+ char id [ISODCL ( 2, 6)];
+ char version [ISODCL ( 7, 7)]; /* 711 */
+ char unused1 [ISODCL ( 8, 8)];
+ char system_id [ISODCL ( 9, 40)]; /* achars */
+ char volume_id [ISODCL ( 41, 72)]; /* dchars */
+ char unused2 [ISODCL ( 73, 80)];
+ char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
+ char unused3 [ISODCL ( 89, 120)];
+ char volume_set_size [ISODCL (121, 124)]; /* 723 */
+ char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
+ char logical_block_size [ISODCL (129, 132)]; /* 723 */
+ char path_table_size [ISODCL (133, 140)]; /* 733 */
+ char type_l_path_table [ISODCL (141, 144)]; /* 731 */
+ char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
+ char type_m_path_table [ISODCL (149, 152)]; /* 732 */
+ char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
+ char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
+ char volume_set_id [ISODCL (191, 318)]; /* dchars */
+ char publisher_id [ISODCL (319, 446)]; /* achars */
+ char preparer_id [ISODCL (447, 574)]; /* achars */
+ char application_id [ISODCL (575, 702)]; /* achars */
+ char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
+ char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
+ char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
+ char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
+ char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
+ char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
+ char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
+ char file_structure_version [ISODCL (882, 882)]; /* 711 */
+ char unused4 [ISODCL (883, 883)];
+ char application_data [ISODCL (884, 1395)];
+ char unused5 [ISODCL (1396, 2048)];
+};
+
+/* Almost the same as the primary descriptor but two fields are specified */
+struct iso_supplementary_descriptor {
+ char type [ISODCL ( 1, 1)]; /* 711 */
+ char id [ISODCL ( 2, 6)];
+ char version [ISODCL ( 7, 7)]; /* 711 */
+ char flags [ISODCL ( 8, 8)]; /* 853 */
+ char system_id [ISODCL ( 9, 40)]; /* achars */
+ char volume_id [ISODCL ( 41, 72)]; /* dchars */
+ char unused2 [ISODCL ( 73, 80)];
+ char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
+ char escape [ISODCL ( 89, 120)]; /* 856 */
+ char volume_set_size [ISODCL (121, 124)]; /* 723 */
+ char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
+ char logical_block_size [ISODCL (129, 132)]; /* 723 */
+ char path_table_size [ISODCL (133, 140)]; /* 733 */
+ char type_l_path_table [ISODCL (141, 144)]; /* 731 */
+ char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
+ char type_m_path_table [ISODCL (149, 152)]; /* 732 */
+ char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
+ char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
+ char volume_set_id [ISODCL (191, 318)]; /* dchars */
+ char publisher_id [ISODCL (319, 446)]; /* achars */
+ char preparer_id [ISODCL (447, 574)]; /* achars */
+ char application_id [ISODCL (575, 702)]; /* achars */
+ char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
+ char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
+ char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
+ char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
+ char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
+ char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
+ char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
+ char file_structure_version [ISODCL (882, 882)]; /* 711 */
+ char unused4 [ISODCL (883, 883)];
+ char application_data [ISODCL (884, 1395)];
+ char unused5 [ISODCL (1396, 2048)];
+};
+
+#define HS_STANDARD_ID "CDROM"
+
+struct hs_volume_descriptor {
+ char foo [ISODCL ( 1, 8)]; /* 733 */
+ char type [ISODCL ( 9, 9)]; /* 711 */
+ char id [ISODCL ( 10, 14)];
+ char version [ISODCL ( 15, 15)]; /* 711 */
+ char data[ISODCL(16,2048)];
+};
+
+
+struct hs_primary_descriptor {
+ char foo [ISODCL ( 1, 8)]; /* 733 */
+ char type [ISODCL ( 9, 9)]; /* 711 */
+ char id [ISODCL ( 10, 14)];
+ char version [ISODCL ( 15, 15)]; /* 711 */
+ char unused1 [ISODCL ( 16, 16)]; /* 711 */
+ char system_id [ISODCL ( 17, 48)]; /* achars */
+ char volume_id [ISODCL ( 49, 80)]; /* dchars */
+ char unused2 [ISODCL ( 81, 88)]; /* 733 */
+ char volume_space_size [ISODCL ( 89, 96)]; /* 733 */
+ char unused3 [ISODCL ( 97, 128)]; /* 733 */
+ char volume_set_size [ISODCL (129, 132)]; /* 723 */
+ char volume_sequence_number [ISODCL (133, 136)]; /* 723 */
+ char logical_block_size [ISODCL (137, 140)]; /* 723 */
+ char path_table_size [ISODCL (141, 148)]; /* 733 */
+ char type_l_path_table [ISODCL (149, 152)]; /* 731 */
+ char unused4 [ISODCL (153, 180)]; /* 733 */
+ char root_directory_record [ISODCL (181, 214)]; /* 9.1 */
+};
+
+/* We use this to help us look up the parent inode numbers. */
+
+struct iso_path_table{
+ char name_len[1]; /* 711 */
+ char ext_attr_length[1]; /* 711 */
+ char extent[4]; /* 731 */
+ char parent[2]; /* 721 */
+ char name[1];
+};
+
+/* high sierra is identical to iso, except that the date is only 6 bytes, and
+ there is an extra reserved byte after the flags */
+
+struct iso_directory_record {
+ char length [ISODCL (1, 1)]; /* 711 */
+ char ext_attr_length [ISODCL (2, 2)]; /* 711 */
+ char extent [ISODCL (3, 10)]; /* 733 */
+ char size [ISODCL (11, 18)]; /* 733 */
+ char date [ISODCL (19, 25)]; /* 7 by 711 */
+ char flags [ISODCL (26, 26)];
+ char file_unit_size [ISODCL (27, 27)]; /* 711 */
+ char interleave [ISODCL (28, 28)]; /* 711 */
+ char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
+ char name_len [ISODCL (33, 33)]; /* 711 */
+ char name [1];
+};
+
+/* 8 bit numbers */
+__inline unsigned char isonum_711(char *p);
+__inline char isonum_712(char *p);
+
+/* 16 bit numbers */
+__inline unsigned short isonum_721(char *p);
+__inline unsigned short isonum_722(char *p);
+__inline unsigned short isonum_723(char *p);
+
+/* 32 bit numbers */
+__inline unsigned int isonum_731(char *p);
+__inline unsigned int isonum_732(char *p);
+__inline unsigned int isonum_733(char *p);
+
+
+/* 8 bit numbers */
+__inline unsigned char isonum_711(char *p)
+{
+ return *(unsigned char *)p;
+}
+__inline char isonum_712(char *p)
+{
+ return *p;
+}
+
+/* 16 bit numbers */
+__inline unsigned short isonum_721(char *p)
+{
+ return le2me_16(*(unsigned short *)p);
+}
+__inline unsigned short isonum_722(char *p)
+{
+ return be2me_16(*(unsigned short *)p);
+}
+__inline unsigned short isonum_723(char *p)
+{
+ /* Ignore bigendian datum due to broken mastering programs */
+ return le2me_16(*(unsigned short *)p);
+}
+
+/* 32 bit numbers */
+__inline unsigned int isonum_731(char *p)
+{
+ return le2me_32(*(unsigned int *)p);
+}
+
+__inline unsigned int isonum_732(char *p)
+{
+ return be2me_32(*(unsigned int *)p);
+}
+
+__inline unsigned int isonum_733(char *p)
+{
+ /* Ignore bigendian datum due to broken mastering programs */
+ return le2me_32(*(unsigned int *)p);
+}
+
+#endif /*_ISOFS_H*/
+
diff --git a/src/iso/libisofs/isofs.c b/src/iso/libisofs/isofs.c
new file mode 100644
index 0000000..9b4307a
--- /dev/null
+++ b/src/iso/libisofs/isofs.c
@@ -0,0 +1,876 @@
+/***************************************************************************
+ isofs.c - libisofs
+ implementation
+ -------------------
+ begin : Oct 25 2002
+ copyright : (C) 2002 by Szombathelyi Gy�gy
+ email : gyurco@users.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 <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "isofs.h"
+
+/**************************************************************/
+
+
+/* internal function from the linux kernel (isofs fs) */
+static time_t getisotime(int year,int month,int day,int hour,
+ int minute,int second,int tz) {
+
+ int days, i;
+ time_t crtime;
+
+ year-=1970;
+
+ if (year < 0) {
+ crtime = 0;
+ } else {
+ int monlen[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
+
+ days = year * 365;
+ if (year > 2)
+ days += (year+1) / 4;
+ for (i = 1; i < month; i++)
+ days += monlen[i-1];
+ if (((year+2) % 4) == 0 && month > 2)
+ days++;
+ days += day - 1;
+ crtime = ((((days * 24) + hour) * 60 + minute) * 60)
+ + second;
+
+ /* sign extend */
+ if (tz & 0x80)
+ tz |= (-1 << 8);
+
+ /*
+ * The timezone offset is unreliable on some disks,
+ * so we make a sanity check. In no case is it ever
+ * more than 13 hours from GMT, which is 52*15min.
+ * The time is always stored in localtime with the
+ * timezone offset being what get added to GMT to
+ * get to localtime. Thus we need to subtract the offset
+ * to get to true GMT, which is what we store the time
+ * as internally. On the local system, the user may set
+ * their timezone any way they wish, of course, so GMT
+ * gets converted back to localtime on the receiving
+ * system.
+ *
+ * NOTE: mkisofs in versions prior to mkisofs-1.10 had
+ * the sign wrong on the timezone offset. This has now
+ * been corrected there too, but if you are getting screwy
+ * results this may be the explanation. If enough people
+ * complain, a user configuration option could be added
+ * to add the timezone offset in with the wrong sign
+ * for 'compatibility' with older discs, but I cannot see how
+ * it will matter that much.
+ *
+ * Thanks to kuhlmav@elec.canterbury.ac.nz (Volker Kuhlmann)
+ * for pointing out the sign error.
+ */
+ if (-52 <= tz && tz <= 52)
+ crtime -= tz * 15 * 60;
+ }
+ return crtime;
+
+}
+
+/**
+ * Returns the Unix from the ISO9660 9.1.5 time format
+ */
+time_t isodate_915(char * p, int hs) {
+
+ return getisotime(1900+p[0],p[1],p[2],p[3],p[4],p[5],hs==0 ? p[6] : 0);
+}
+
+/**
+ * Returns the Unix from the ISO9660 8.4.26.1 time format
+ * BUG: hundredth of seconds are ignored, because Unix time_t has one second
+ * resolution (I think it's no problem at all)
+ */
+time_t isodate_84261(char * p, int hs) {
+ int year,month,day,hour,minute,second;
+ year=(p[0]-'0')*1000 + (p[1]-'0')*100 + (p[2]-'0')*10 + p[3]-'0';
+ month=(p[4]-'0')*10 + (p[5]-'0');
+ day=(p[6]-'0')*10 + (p[7]-'0');
+ hour=(p[8]-'0')*10 + (p[9]-'0');
+ minute=(p[10]-'0')*10 + (p[11]-'0');
+ second=(p[12]-'0')*10 + (p[13]-'0');
+ return getisotime(year,month,day,hour,minute,second,hs==0 ? p[16] : 0);
+}
+
+void FreeBootTable(boot_head *boot) {
+ boot_entry *be,*next;
+
+ be=boot->defentry;
+ while (be) {
+ next=be->next;
+ free(be);
+ be=next;
+ }
+ boot->defentry=NULL;
+}
+
+int BootImageSize(int media,int len) {
+ int ret;
+
+ switch(media & 0xf) {
+ case 0:
+ ret=len; /* No emulation */
+ break;
+ case 1:
+ ret=80*2*15; /* 1.2 MB */
+ break;
+ case 2:
+ ret=80*2*18; /* 1.44 MB */
+ break;
+ case 3:
+ ret=80*2*36; /* 2.88 MB */
+ break;
+ case 4:
+ /* FIXME!!! */
+ ret=len; /* Hard Disk */
+ break;
+ default:
+ ret=len;
+ }
+ return ret;
+}
+
+static boot_entry *CreateBootEntry(char *be) {
+ boot_entry *entry;
+
+ entry = (boot_entry*) malloc(sizeof(boot_entry));
+ if (!entry) return NULL;
+ memset(entry, 0, sizeof(boot_entry));
+ memcpy(entry->data,be,0x20);
+ return entry;
+}
+
+int ReadBootTable(readfunc *read,int sector, boot_head *head, void *udata) {
+
+ char buf[2048], *c, *be;
+ int i,end=0;
+ unsigned short sum;
+ boot_entry *defcur=NULL,*deflast=NULL;
+ struct validation_entry *ventry=NULL;
+
+ head->sections=NULL;
+ head->defentry=NULL;
+ while (1) {
+ be = (char*) &buf;
+ if ( read(be, sector, 1, udata) != 1 ) goto err;
+
+ /* first entry needs to be a validation entry */
+ if (!ventry) {
+ ventry=(struct validation_entry *) be;
+ if ( isonum_711(ventry->type) !=1 ) goto err;
+ sum=0;
+ c = (char*) ventry;
+ for (i=0;i<16;i++) { sum += isonum_721(c); c+=2; }
+ if (sum) goto err;
+ memcpy(&head->ventry,be,0x20);
+ be += 0x20;
+ }
+
+ while (!end && (be < (char *)(&buf+1))) {
+ switch (isonum_711(be)) {
+ case 0x88:
+ defcur=CreateBootEntry(be);
+ if (!defcur) goto err;
+ if (deflast)
+ deflast->next=defcur;
+ else
+ head->defentry=defcur;
+ defcur->prev=deflast;
+ deflast=defcur;
+ break;
+ case 0x90:
+ case 0x91:
+ break;
+ default:
+ end=1;
+ break;
+ }
+ be += 0x20;
+ }
+ if (end) break;
+
+ sector ++;
+ }
+
+ return 0;
+
+err:
+ FreeBootTable(head);
+ return -1;
+}
+
+
+/**
+ * Creates the linked list of the volume descriptors
+ */
+iso_vol_desc *ReadISO9660(readfunc *read,int sector,void *udata) {
+
+ int i;
+ struct iso_volume_descriptor buf;
+ iso_vol_desc *first=NULL,*current=NULL,*prev=NULL;
+
+ for (i=0;i<100;i++) {
+ if (read( (char*) &buf, sector+i+16, 1, udata) != 1 ) {
+ FreeISO9660(first);
+ return NULL;
+ }
+ if (!memcmp(ISO_STANDARD_ID,&buf.id,5)) {
+ switch ( isonum_711(&buf.type[0]) ) {
+
+ case ISO_VD_BOOT:
+ case ISO_VD_PRIMARY:
+ case ISO_VD_SUPPLEMENTARY:
+ current=(iso_vol_desc*) malloc(sizeof(iso_vol_desc));
+ if (!current) {
+ FreeISO9660(first);
+ return NULL;
+ }
+ current->prev=prev;
+ current->next=NULL;
+ if (prev) prev->next=current;
+ memcpy(&(current->data),&buf,2048);
+ if (!first) first=current;
+ prev=current;
+ break;
+
+ case ISO_VD_END:
+ return first;
+ break;
+ }
+ } else if (!memcmp(HS_STANDARD_ID,(struct hs_volume_descriptor*) &buf,5)) {
+ /* High Sierra format not supported (yet) */
+ }
+ }
+
+ return first;
+}
+
+/**
+ * Frees the linked list of volume descriptors
+ */
+void FreeISO9660(iso_vol_desc *data) {
+
+ iso_vol_desc *current;
+
+
+ while (data) {
+ current=data;
+ data=current->next;
+ free(current);
+ }
+}
+
+/**
+ * Frees the strings in 'rrentry'
+ */
+void FreeRR(rr_entry *rrentry) {
+ if (rrentry->name) {
+ free(rrentry->name);
+ rrentry->name=NULL;
+ }
+ if (rrentry->sl) {
+ free(rrentry->sl);
+ rrentry->name=NULL;
+ }
+}
+
+static int str_nappend(char **d,char *s,int n) {
+ int i=0;
+ char *c;
+
+/* i=strnlen(s,n)+1; */
+ while (i<n && s[i]) i++;
+ i++;
+ if (*d) i+=(strlen(*d)+1);
+ c=(char*) malloc(i);
+ if (!c) return -ENOMEM;
+ if (*d) {
+ strcpy(c,*d);
+ strncat(c,s,n);
+
+ free(*d);
+ } else
+ strncpy(c,s,n);
+ c[i-1]=0;
+ *d=c;
+ return 0;
+}
+
+static int str_append(char **d,char *s) {
+ int i;
+ char *c;
+
+ i=strlen(s)+1;
+ if (*d) i+=(strlen(*d)+1);
+ c=(char*) malloc(i);
+ if (!c) return -ENOMEM;
+ if (*d) {
+ strcpy(c,*d);
+ strcat(c,s);
+ free(*d);
+ } else
+ strcpy(c,s);
+ c[i-1]=0;
+ *d=c;
+ return 0;
+}
+
+#define rrtlen(c) (((unsigned char) c & 0x80) ? 17 : 7)
+#define rrctime(f,c) ((unsigned char) f & 0x80) ? isodate_84261(c,0) : isodate_915(c,0)
+/**
+ * Parses the System Use area and fills rr_entry with values
+ */
+int ParseRR(struct iso_directory_record *idr, rr_entry *rrentry) {
+
+ int suspoffs,susplen,i,f,ret=0;
+ char *r, *c;
+ struct rock_ridge *rr;
+
+ suspoffs=33+isonum_711(idr->name_len);
+ if (!(isonum_711(idr->name_len) & 1)) suspoffs++;
+ susplen=isonum_711(idr->length)-suspoffs;
+ r= & (((char*) idr)[suspoffs]);
+ rr = (struct rock_ridge*) r;
+
+ memset(rrentry,0,sizeof(rr_entry));
+ rrentry->len = sizeof(rr_entry);
+
+ while (susplen > 0) {
+ if (isonum_711(&rr->len) > susplen || rr->len == 0) break;
+ if (rr->signature[0]=='N' && rr->signature[1]=='M') {
+ if (!(rr->u.NM.flags & 0x26) && rr->len>5 && !rrentry->name) {
+
+ if (str_nappend(&rrentry->name,rr->u.NM.name,isonum_711(&rr->len)-5)) {
+ FreeRR(rrentry); return -ENOMEM;
+ }
+ ret++;
+ }
+ } else if (rr->signature[0]=='P' && rr->signature[1]=='X' &&
+ (isonum_711(&rr->len)==44 || isonum_711(&rr->len)==36)) {
+ rrentry->mode=isonum_733(rr->u.PX.mode);
+ rrentry->nlink=isonum_733(rr->u.PX.n_links);
+ rrentry->uid=isonum_733(rr->u.PX.uid);
+ rrentry->gid=isonum_733(rr->u.PX.gid);
+ if (isonum_711(&rr->len)==44) rrentry->serno=isonum_733(rr->u.PX.serno);
+ ret++;
+ } else if (rr->signature[0]=='P' && rr->signature[1]=='N' &&
+ isonum_711(&rr->len)==20) {
+ rrentry->dev_major=isonum_733(rr->u.PN.dev_high);
+ rrentry->dev_minor=isonum_733(rr->u.PN.dev_low);
+ ret++;
+ } else if (rr->signature[0]=='P' && rr->signature[1]=='L' &&
+ isonum_711(&rr->len)==12) {
+ rrentry->pl=isonum_733(rr->u.PL.location);
+ ret++;
+ } else if (rr->signature[0]=='C' && rr->signature[1]=='L' &&
+ isonum_711(&rr->len)==12) {
+ rrentry->cl=isonum_733(rr->u.CL.location);
+ ret++;
+ } else if (rr->signature[0]=='R' && rr->signature[1]=='E' &&
+ isonum_711(&rr->len)==4) {
+ rrentry->re=1;
+ ret++;
+ } else if (rr->signature[0]=='S' && rr->signature[1]=='L' &&
+ isonum_711(&rr->len)>7) {
+ i = isonum_711(&rr->len)-5;
+ c = (char*) rr;
+ c += 5;
+ while (i>0) {
+ switch(c[0] & ~1) {
+ case 0x2:
+ if (str_append(&rrentry->sl,(char *)".")) {
+ FreeRR(rrentry); return -ENOMEM;
+ }
+ break;
+ case 0x4:
+ if (str_append(&rrentry->sl,(char *)"..")) {
+ FreeRR(rrentry); return -ENOMEM;
+ }
+ break;
+ }
+ if ( (c[0] & 0x08) == 0x08 || (c[1] && rrentry->sl &&
+ strlen(rrentry->sl)>1) ) {
+ if (str_append(&rrentry->sl,(char *)"/")) {
+ FreeRR(rrentry); return -ENOMEM;
+ }
+ }
+
+ if ((unsigned char)c[1]>0) {
+ if (str_nappend(&rrentry->sl,c+2,(unsigned char)c[1])) {
+ FreeRR(rrentry); return -ENOMEM;
+ }
+ }
+ i -= ((unsigned char)c[1] + 2);
+ c += ((unsigned char)c[1] + 2);
+ }
+ ret++;
+ } else if (rr->signature[0]=='T' && rr->signature[1]=='F' &&
+ isonum_711(&rr->len)>5) {
+
+ i = isonum_711(&rr->len)-5;
+ f = rr->u.TF.flags;
+ c = (char*) rr;
+ c += 5;
+
+ while (i >= rrtlen(f)) {
+ if (f & 1) {
+ rrentry->t_creat=rrctime(f,c);
+ f &= ~1;
+ } else if (f & 2) {
+ rrentry->t_mtime=rrctime(f,c);
+ f &= ~2;
+ } else if (f & 4) {
+ rrentry->t_atime=rrctime(f,c);
+ f &= ~4;
+ } else if (f & 8) {
+ rrentry->t_ctime=rrctime(f,c);
+ f &= ~8;
+ } else if (f & 16) {
+ rrentry->t_backup=rrctime(f,c);
+ f &= ~16;
+ } else if (f & 32) {
+ rrentry->t_expire=rrctime(f,c);
+ f &= ~32;
+ } else if (f & 64) {
+ rrentry->t_effect=rrctime(f,c);
+ f &= ~64;
+ }
+
+ i -= rrtlen(f);
+ c += rrtlen(f);
+ }
+ ret++;
+
+ } else if (rr->signature[0]=='Z' && rr->signature[1]=='F' &&
+ isonum_711(&rr->len)==16) {
+ /* Linux-specific extension: transparent decompression */
+ rrentry->z_algo[0]=rr->u.ZF.algorithm[0];
+ rrentry->z_algo[1]=rr->u.ZF.algorithm[1];
+ rrentry->z_params[0]=rr->u.ZF.parms[0];
+ rrentry->z_params[1]=rr->u.ZF.parms[1];
+ rrentry->z_size=isonum_733(rr->u.ZF.real_size);
+ ret++;
+ } else {
+/* printf("SUSP sign: %c%c\n",rr->signature[0],rr->signature[1]); */
+ }
+
+ susplen -= isonum_711(&rr->len);
+ r += isonum_711(&rr->len);
+ rr = (struct rock_ridge*) r;
+ }
+
+ return ret;
+}
+
+/**
+ * Iterates over the directory entries. The directory is in 'buf',
+ * the size of the directory is 'size'. 'callback' is called for each
+ * directory entry with the parameter 'udata'.
+ */
+int ProcessDir(readfunc *read,int extent,int size,dircallback *callback,void *udata) {
+
+ int pos=0,ret=0,siz;
+ char *buf;
+ struct iso_directory_record *idr;
+
+ if (size & 2047) {
+ siz=((size>>11)+1)<<11;
+ } else {
+ siz=size;
+ }
+
+ buf=(char*) malloc(siz);
+ if (!buf) return -ENOMEM;
+ if (read(buf,extent,siz>>11,udata)!=siz>>11) {
+ free(buf);
+ return -EIO;
+ }
+
+ while (size>0) {
+ idr=(struct iso_directory_record*) &buf[pos];
+ if (isonum_711(idr->length)==0) {
+
+ size-=(2048 - (pos & 0x7ff));
+ if (size<=2) break;
+ pos+=0x800;
+ pos&=0xfffff800;
+ idr=(struct iso_directory_record*) &buf[pos];
+ }
+ pos+=isonum_711(idr->length);
+ pos+=isonum_711(idr->ext_attr_length);
+ size-=isonum_711(idr->length);
+ size-=isonum_711(idr->ext_attr_length);
+ if (size<0) break;
+
+ if (isonum_711(idr->length)
+<33 ||
+ isonum_711(idr->length)<33+isonum_711(idr->name_len)) {
+ /* Invalid directory entry */
+ continue;
+ }
+ if ((ret=callback(idr,udata))) break;
+ }
+
+ free(buf);
+ return ret;
+}
+
+/**
+ * returns the joliet level from the volume descriptor
+ */
+int JolietLevel(struct iso_volume_descriptor *ivd) {
+ int ret=0;
+ struct iso_supplementary_descriptor *isd;
+
+ isd = (struct iso_supplementary_descriptor *) ivd;
+
+ if (isonum_711(ivd->type)==ISO_VD_SUPPLEMENTARY) {
+ if (isd->escape[0]==0x25 &&
+ isd->escape[1]==0x2f) {
+
+ switch (isd->escape[2]) {
+ case 0x40:
+ ret=1;
+ break;
+ case 0x43:
+ ret=2;
+ break;
+ case 0x45:
+ ret=3;
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+/********************************************************************/
+#ifdef ISOFS_MAIN
+
+#include <time.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <iconv.h>
+
+int level=0,joliet=0,dirs,files;
+iconv_t iconv_d;
+int fd;
+
+int readf(char *buf, int start, int len,void *udata) {
+ int ret;
+
+ if ((ret=lseek(fd, start << 11, SEEK_SET))<0) return ret;
+ ret=read(fd, buf, len << 11);
+ if (ret<0) return ret;
+ return (ret >> 11);
+}
+
+void dumpchars(char *c,int len) {
+ while (len>0) {
+ printf("%c",*c);
+ len--;
+ c++;
+ }
+}
+
+void sp(int num) {
+ int i;
+ for (i=0;i<num*5;i++) { printf(" "); };
+}
+
+void dumpflags(char flags) {
+ if (flags & 1) printf("HIDDEN ");
+ if (flags & 2) printf("DIR ");
+ if (flags & 4) printf("ASF ");
+}
+
+void dumpjoliet(char *c,int len) {
+
+ char outbuf[255];
+ size_t out;
+ int ret;
+ char *outptr;
+
+ outptr=(char*) &outbuf;
+ out=255;
+ if ((iconv(iconv_d,&c,&len,&outptr,&out))<0) {
+ printf("conversion error=%d",errno);
+ return;
+ }
+ ret=255-out;
+ dumpchars((char*) &outbuf,ret);
+}
+
+void dumpchardesc(char *c,int len) {
+
+ if (joliet)
+ dumpjoliet(c,len);
+ else {
+ dumpchars(c,len);
+ }
+}
+
+void dumpiso915time(char *t, int hs) {
+
+ time_t time;
+ char *c;
+
+ time=isodate_915(t,hs);
+ c=(char*) ctime(&time);
+ if (c && c[strlen(c)-1]==0x0a) c[strlen(c)-1]=0;
+ if (c) printf("%s",c);
+}
+
+void dumpiso84261time(char *t, int hs) {
+
+ time_t time;
+ char *c;
+
+ time=isodate_84261(t,hs);
+ c=(char*) ctime(&time);
+ if (c && c[strlen(c)-1]==0x0a) c[strlen(c)-1]=0;
+ if (c) printf("%s",c);
+}
+
+void dumpdirrec(struct iso_directory_record *dir) {
+
+ if (isonum_711(dir->name_len)==1) {
+ switch (dir->name[0]) {
+ case 0:
+ printf(".");
+ break;
+ case 1:
+ printf("..");
+ break;
+ default:
+ printf("%c",dir->name[0]);
+ break;
+ }
+ }
+ dumpchardesc(dir->name,isonum_711(dir->name_len));
+ printf(" size=%d",isonum_733(dir->size));
+ printf(" extent=%d ",isonum_733(dir->extent));
+ dumpflags(isonum_711(dir->flags));
+ dumpiso915time((char*) &(dir->date),0);
+}
+
+void dumprrentry(rr_entry *rr) {
+ printf(" NM=[%s] uid=%d gid=%d nlink=%d mode=%o ",
+ rr->name,rr->uid,rr->gid,rr->nlink,rr->mode);
+ if (S_ISCHR(rr->mode) || S_ISBLK(rr->mode))
+ printf("major=%d minor=%d ",rr->dev_major,rr->dev_minor);
+ if (rr->mode & S_IFLNK && rr->sl) printf("slink=%s ",rr->sl);
+/*
+ printf("\n");
+ if (rr->t_creat) printf("t_creat: %s",ctime(&rr->t_creat));
+ if (rr->st_mtime) printf("st_mtime: %s",ctime(&rr->st_mtime));
+ if (rr->st_atime) printf("st_atime: %s",ctime(&rr->st_atime));
+ if (rr->st_ctime) printf("st_ctime: %s",ctime(&rr->st_ctime));
+ if (rr->t_backup) printf("t_backup: %s",ctime(&rr->t_backup));
+ if (rr->t_expire) printf("t_expire: %s",ctime(&rr->t_expire));
+ if (rr->t_effect) printf("t_effect: %s",ctime(&rr->t_effect));
+*/
+}
+
+void dumpsusp(char *c, int len) {
+ dumpchars(c,len);
+}
+
+void dumpboot(struct el_torito_boot_descriptor *ebd) {
+ printf("version: %d\n",isonum_711(ebd->version));
+ printf("system id: ");dumpchars(ebd->system_id,ISODCL(8,39));printf("\n");
+ printf("boot catalog start: %d\n",isonum_731(ebd->boot_catalog));
+}
+
+void dumpdefentry(struct default_entry *de) {
+ printf("Default entry: \n");
+ printf(" bootid=%x\n",isonum_711(de->bootid));
+ printf(" media emulation=%d (",isonum_711(de->media));
+ switch(isonum_711(de->media) & 0xf) {
+ case 0:
+ printf("No emulation");
+ break;
+ case 1:
+ printf("1.2 Mb floppy");
+ break;
+ case 2:
+ printf("1.44 Mb floppy");
+ break;
+ case 3:
+ printf("2.88 Mb floppy");
+ break;
+ case 4:
+ printf("Hard Disk");
+ break;
+ default:
+ printf("Unknown/Invalid");
+ break;
+ }
+ printf(")\n");
+ printf(" loadseg=%d\n",isonum_721(de->loadseg));
+ printf(" systype=%d\n",isonum_711(de->systype));
+ printf(" start lba=%d count=%d\n",isonum_731(de->start),
+ isonum_721(de->seccount));
+}
+
+void dumpbootcat(boot_head *bh) {
+ boot_entry *be;
+
+ printf("System id: ");dumpchars(bh->ventry.id,ISODCL(28,5));printf("\n");
+ be=bh->defentry;
+ while (be) {
+ dumpdefentry(be->data);
+ be=be->next;
+ }
+}
+
+void dumpdesc(struct iso_primary_descriptor *ipd) {
+
+ printf("system id: ");dumpchardesc(ipd->system_id,ISODCL(9,40));printf("\n");
+ printf("volume id: ");dumpchardesc(ipd->volume_id,ISODCL(41,72));printf("\n");
+ printf("volume space size: %d\n",isonum_733(ipd->volume_space_size));
+ printf("volume set size: %d\n",isonum_723(ipd->volume_set_size));
+ printf("volume seq num: %d\n",isonum_723(ipd->volume_set_size));
+ printf("logical block size: %d\n",isonum_723(ipd->logical_block_size));
+ printf("path table size: %d\n",isonum_733(ipd->path_table_size));
+ printf("location of type_l path table: %d\n",isonum_731(ipd->type_l_path_table));
+ printf("location of optional type_l path table: %d\n",isonum_731(ipd->opt_type_l_path_table));
+ printf("location of type_m path table: %d\n",isonum_732(ipd->type_m_path_table));
+ printf("location of optional type_m path table: %d\n",isonum_732(ipd->opt_type_m_path_table));
+/*
+ printf("Root dir record:\n");dumpdirrec((struct iso_directory_record*) &ipd->root_directory_record);
+*/
+ printf("Volume set id: ");dumpchardesc(ipd->volume_set_id,ISODCL(191,318));printf("\n");
+ printf("Publisher id: ");dumpchardesc(ipd->publisher_id,ISODCL(319,446));printf("\n");
+ printf("Preparer id: ");dumpchardesc(ipd->preparer_id,ISODCL(447,574));printf("\n");
+ printf("Application id: ");dumpchardesc(ipd->application_id,ISODCL(575,702));printf("\n");
+ printf("Copyright id: ");dumpchardesc(ipd->copyright_file_id,ISODCL(703,739));printf("\n");
+ printf("Abstract file id: ");dumpchardesc(ipd->abstract_file_id,ISODCL(740,776));printf("\n");
+ printf("Bibliographic file id: ");dumpchardesc(ipd->bibliographic_file_id,ISODCL(777,813));printf("\n");
+ printf("Volume creation date: ");dumpiso84261time(ipd->creation_date,0);printf("\n");
+ printf("Volume modification date: ");dumpiso84261time(ipd->modification_date,0);printf("\n");
+ printf("Volume expiration date: ");dumpiso84261time(ipd->expiration_date,0);printf("\n");
+ printf("Volume effective date: ");dumpiso84261time(ipd->effective_date,0);printf("\n");
+ printf("File structure version: %d\n",isonum_711(ipd->file_structure_version));
+}
+
+int mycallb(struct iso_directory_record *idr,void *udata) {
+ rr_entry rrentry;
+
+ sp(level);dumpdirrec(idr);
+ if (level==0) printf(" (Root directory) ");
+ printf("\n");
+
+ if (ParseRR(idr,&rrentry)>0) {
+ sp(level);printf(" ");dumprrentry(&rrentry);printf("\n");
+ }
+ FreeRR(&rrentry);
+ if ( !(idr->flags[0] & 2) ) files++;
+ if ( (idr->flags[0] & 2) && (level==0 || isonum_711(idr->name_len)>1) ) {
+ level++;
+ dirs++;
+ ProcessDir(&readf,isonum_733(idr->extent),isonum_733(idr->size),&mycallb,udata);
+ level--;
+ }
+ return 0;
+}
+
+/************************************************/
+
+int main(int argc, char *argv[]) {
+
+ int i=1,sector=0;
+ iso_vol_desc *desc;
+ boot_head boot;
+
+ if (argc<2) {
+ fprintf(stderr,"\nUsage: %s iso-file-name or device [starting sector]\n\n",argv[0]);
+ return 0;
+ }
+ if (argc>=3) {
+ sector=atoi(argv[2]);
+ printf("Using starting sector number %d\n",sector);
+ }
+ fd=open(argv[1],O_RDONLY);
+ if (fd<0) {
+ fprintf(stderr,"open error\n");
+ return -1;
+ }
+ iconv_d=iconv_open("ISO8859-2","UTF16BE");
+ if (iconv_d==0) {
+ fprintf(stderr,"iconv open error\n");
+ return -1;
+ }
+
+ desc=ReadISO9660(&readf,sector,NULL);
+ if (!desc) {
+ printf("No volume descriptors\n");
+ return -1;
+ }
+ while (desc) {
+
+ printf("\n\n--------------- Volume descriptor (%d.) type %d: ---------------\n\n",
+ i,isonum_711(desc->data.type));
+ switch (isonum_711(desc->data.type)) {
+ case ISO_VD_BOOT: {
+
+ struct el_torito_boot_descriptor* bootdesc;
+ bootdesc=&(desc->data);
+ dumpboot(bootdesc);
+ if ( !memcmp(EL_TORITO_ID,bootdesc->system_id,ISODCL(8,39)) ) {
+
+ if (ReadBootTable(&readf,isonum_731(bootdesc->boot_catalog),&boot,NULL)) {
+ printf("Boot Catalog Error\n");
+ } else {
+ dumpbootcat(&boot);
+ FreeBootTable(&boot);
+ }
+ }
+ }
+ break;
+
+ case ISO_VD_PRIMARY:
+ case ISO_VD_SUPPLEMENTARY:
+ joliet=0;
+ joliet = JolietLevel(&desc->data);
+ printf("Joliet level: %d\n",joliet);
+ dumpdesc((struct iso_primary_descriptor*) &desc->data);
+ printf("\n\n--------------- Directory structure: -------------------\n\n");
+ dirs=0;files=0;
+ mycallb( &( ((struct iso_primary_descriptor*) &desc->data)->root_directory_record), NULL );
+ printf("\nnumber of directories: %d\n",dirs);
+ printf("\nnumber of files: %d\n",files);
+ break;
+
+ }
+ desc=desc->next;
+ i++;
+ }
+ iconv_close(iconv_d);
+ close(fd);
+ FreeISO9660(desc);
+ return 0;
+}
+
+#endif /* ISOFS_MAIN */
diff --git a/src/iso/libisofs/isofs.h b/src/iso/libisofs/isofs.h
new file mode 100644
index 0000000..52190e6
--- /dev/null
+++ b/src/iso/libisofs/isofs.h
@@ -0,0 +1,161 @@
+/***************************************************************************
+ isofs.h - include this file to use libisofs
+ -------------------
+ begin : Oct 25 2002
+ copyright : (C) 2002 by Szombathelyi Gy�gy
+ email : gyurco@users.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 ISOFS_H
+#define ISOFS_H
+
+#include <sys/time.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "iso_fs.h"
+#include "el_torito.h"
+#include "rock.h"
+
+typedef struct _rr_entry {
+ int len; /* length of structure */
+ char *name; /* Name from 'NM' */
+ char *sl; /* symbolic link data */
+ time_t t_creat;
+ time_t t_mtime;
+ time_t t_atime;
+ time_t t_ctime;
+ time_t t_backup;
+ time_t t_expire;
+ time_t t_effect;
+ int mode; /* POSIX file modes */
+ int nlink;
+ int uid;
+ int gid;
+ int serno;
+ int dev_major;
+ int dev_minor;
+ int pl; /* parent location */
+ int cl; /* child location */
+ int re; /* relocated */
+ char z_algo[2]; /* zizofs algorithm */
+ char z_params[2]; /* zizofs parameters */
+ int z_size; /* zizofs real_size */
+} rr_entry;
+
+typedef struct _iso_vol_desc {
+ struct _iso_vol_desc *next;
+ struct _iso_vol_desc *prev;
+ struct iso_volume_descriptor data;
+} iso_vol_desc;
+
+typedef struct _boot_entry {
+ struct _boot_entry *next;
+ struct _boot_entry *prev;
+ struct _boot_entry *parent;
+ struct _boot_entry *child;
+ char data[32];
+}
+ boot_entry;
+
+typedef struct _boot_head {
+ struct validation_entry ventry;
+ struct _boot_entry *defentry;
+ struct _boot_entry *sections;
+}
+ boot_head;
+
+/**
+ * this callback function needs to read 'len' sectors from 'start' into 'buf'
+ */
+typedef int readfunc(char *buf,int start, int len,void *);
+
+/**
+ * ProcessDir uses this callback
+ */
+typedef int dircallback(struct iso_directory_record *,void *);
+
+/**
+ * Returns the Unix from the ISO9660 9.1.5 (7 bytes) time format
+ * This function is from the linux kernel.
+ * Set 'hs' to non-zero if it's a HighSierra volume
+ */
+time_t isodate_915(char * p, int hs);
+
+/**
+ * Returns the Unix time from the ISO9660 8.4.26.1 (17 bytes) time format
+ * BUG: hundredth of seconds are ignored, because time_t has one second
+ * resolution (I think it's no problem at all)
+ * Set 'hs' to non-zero if it's a HighSierra volume
+ */
+time_t isodate_84261(char * p, int hs);
+
+/**
+ * Creates the linked list of the volume descriptors
+ * 'sector' is the starting sector number of where the filesystem start
+ * (starting sector of a session on a CD-ROM)
+ * If the function fails, returns NULL
+ * Don't forget to call FreeISO9660 after using the volume descriptor list!
+ */
+iso_vol_desc *ReadISO9660(readfunc *read,int sector,void *udata);
+
+/**
+ * Frees the linked list of volume descriptors
+.
+ */
+void FreeISO9660(iso_vol_desc *data);
+
+/**
+ * Iterates over the directory entries. The directory is in 'buf',
+ * the size of the directory is 'size'. 'callback' is called for each
+ * directory entry with the parameter 'udata'.
+ */
+int ProcessDir(readfunc *read,int extent,int size,dircallback *callback,void *udata);
+
+/**
+ * Parses the System Use area and fills rr_entry with values
+ */
+int ParseRR(struct iso_directory_record *idr, rr_entry *rrentry);
+
+/**
+ * Frees the strings in 'rrentry'
+ */
+void FreeRR(rr_entry *rrentry);
+
+/**
+ * returns the joliet level from the volume descriptor
+ */
+int JolietLevel(struct iso_volume_descriptor *ivd);
+
+/**
+ * Returns the size of the boot image (in 512 byte sectors)
+ */
+int BootImageSize(int media,int len);
+
+/**
+ * Frees the boot catalog entries in 'boot'. If you ever called ReadBootTable,
+ * then don't forget to call FreeBootTable!
+ */
+void FreeBootTable(boot_head *boot);
+
+/**
+ * Reads the boot catalog into 'head'. Don't forget to call FreeBootTable!
+ */
+int ReadBootTable(readfunc *read,int sector, boot_head *head, void *udata);
+
+#ifdef __cplusplus
+} //extern "C"
+#endif
+
+#endif
+
diff --git a/src/iso/libisofs/rock.h b/src/iso/libisofs/rock.h
new file mode 100644
index 0000000..e859192
--- /dev/null
+++ b/src/iso/libisofs/rock.h
@@ -0,0 +1,127 @@
+/* this header is from the linux kernel */
+
+#ifndef ROCK_H
+#define ROCK_H 1
+
+/* These structs are used by the system-use-sharing protocol, in which the
+ Rock Ridge extensions are embedded. It is quite possible that other
+ extensions are present on the disk, and this is fine as long as they
+ all use SUSP */
+
+struct SU_SP{
+ unsigned char magic[2];
+ unsigned char skip;
+};
+
+struct SU_CE{
+ char extent[8];
+ char offset[8];
+ char size[8];
+};
+
+struct SU_ER{
+ unsigned char len_id;
+ unsigned char len_des;
+ unsigned char len_src;
+ unsigned char ext_ver;
+ char data[1];
+};
+
+struct RR_RR{
+ char flags[1];
+};
+
+struct RR_PX{
+ char mode[8];
+ char n_links[8];
+ char uid[8];
+ char gid[8];
+ char serno[8];
+};
+
+struct RR_PN{
+ char dev_high[8];
+ char dev_low[8];
+};
+
+
+struct SL_component{
+ unsigned char flags;
+ unsigned char len;
+ char text[1];
+};
+
+struct RR_SL{
+ unsigned char flags;
+ struct SL_component link;
+};
+
+struct RR_NM{
+ unsigned char flags;
+ char name[1];
+};
+
+struct RR_CL{
+ char location[8];
+};
+
+struct RR_PL{
+ char location[8];
+};
+
+struct stamp{
+ char time[7];
+};
+
+struct RR_TF{
+ char flags;
+ struct stamp times[1]; /* Variable number of these beasts */
+};
+
+/* Linux-specific extension for transparent decompression */
+struct RR_ZF{
+ char algorithm[2];
+ char parms[2];
+ char real_size[8];
+};
+
+/* These are the bits and their meanings for flags in the TF structure. */
+#define TF_CREATE 1
+#define TF_MODIFY 2
+#define TF_ACCESS 4
+#define TF_ATTRIBUTES 8
+#define TF_BACKUP 16
+#define TF_EXPIRATION 32
+#define TF_EFFECTIVE 64
+#define TF_LONG_FORM 128
+
+struct rock_ridge{
+ char signature[2];
+ char len; /* 711 */
+ char version; /* 711 */
+ union{
+ struct SU_SP SP;
+ struct SU_CE CE;
+ struct SU_ER ER;
+ struct RR_RR RR;
+ struct RR_PX PX;
+ struct RR_PN PN;
+ struct RR_SL SL;
+ struct RR_NM NM;
+ struct RR_CL CL;
+ struct RR_PL PL;
+ struct RR_TF TF;
+ struct RR_ZF ZF;
+ } u;
+};
+
+#define RR_PX 1 /* POSIX attributes */
+#define RR_PN 2 /* POSIX devices */
+#define RR_SL 4 /* Symbolic link */
+#define RR_NM 8 /* Alternate Name */
+#define RR_CL 16 /* Child link */
+#define RR_PL 32 /* Parent link */
+#define RR_RE 64 /* Relocation directory */
+#define RR_TF 128 /* Timestamps */
+
+#endif /* ROCK_H */
diff --git a/src/iso/qfilehack.cpp b/src/iso/qfilehack.cpp
new file mode 100644
index 0000000..f4f788f
--- /dev/null
+++ b/src/iso/qfilehack.cpp
@@ -0,0 +1,40 @@
+/***************************************************************************
+ qfilehack.cpp - description
+ -------------------
+ begin : Tue Oct 29 2002
+ copyright : (C) 2002 by Szombathelyi Gyrgy
+ email : gyurco@users.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 "qfilehack.h"
+
+QFileHack::QFileHack(){
+}
+
+QFileHack::QFileHack( const TQString & name ) : TQFile(name) {
+}
+
+QFileHack::~QFileHack(){
+}
+
+bool QFileHack::open ( int m ) {
+ bool ret;
+
+#ifdef __linux__
+ m |= IO_Async; //On linux, set O_NONBLOCK, opens CD-ROMs faster
+#endif
+ ret=TQFile::open(m);
+ if (ret && isSequentialAccess() ) {
+ setType(IO_Direct);
+ }
+ return ret;
+}
diff --git a/src/iso/qfilehack.h b/src/iso/qfilehack.h
new file mode 100644
index 0000000..fe43217
--- /dev/null
+++ b/src/iso/qfilehack.h
@@ -0,0 +1,38 @@
+/***************************************************************************
+ qfilehack.h - description
+ -------------------
+ begin : Tue Oct 29 2002
+ copyright : (C) 2002 by Szombathelyi Gyrgy
+ email : gyurco@users.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 QFILEHACK_H
+#define QFILEHACK_H
+
+#include <tqfile.h>
+#include <tqstring.h>
+
+/**
+ *@author Szombathelyi Gyrgy
+ * TQt thinks if a file is not S_IFREG, you cannot seek in it. It's false (what about
+ * block devices for example?
+ */
+
+class QFileHack : public TQFile {
+public:
+ QFileHack();
+ QFileHack( const TQString & name );
+ ~QFileHack();
+ virtual bool open ( int m );
+};
+
+#endif
diff --git a/src/iso/tdeio_isorc b/src/iso/tdeio_isorc
new file mode 100644
index 0000000..3a87417
--- /dev/null
+++ b/src/iso/tdeio_isorc
@@ -0,0 +1,2 @@
+showhidden=false
+showrr=true
diff --git a/src/krArc/CMakeL10n.txt b/src/krArc/CMakeL10n.txt
new file mode 100644
index 0000000..30959a5
--- /dev/null
+++ b/src/krArc/CMakeL10n.txt
@@ -0,0 +1,3 @@
+##### create translation templates ##############
+
+tde_l10n_create_template( "messages/tdeio_krarc/" )
diff --git a/src/krArc/Makefile.am b/src/krArc/Makefile.am
new file mode 100644
index 0000000..5d7eeb6
--- /dev/null
+++ b/src/krArc/Makefile.am
@@ -0,0 +1,59 @@
+####### tdevelop will overwrite this part!!! (begin)##########
+kde_module_LTLIBRARIES = tdeio_krarc.la
+
+
+INCLUDES = $(all_includes)
+
+
+#LDFLAGS =
+
+tdeio_krarc_la_METASOURCES=AUTO
+
+tdeio_krarc_la_SOURCES = krarc.cpp
+tdeio_krarc_la_LIBADD = $(LIB_TQT) $(LIB_TDECORE) $(LIB_TDEIO)
+# $(LIB_TDEUI) $(LIB_TDECORE) $(LIB_TQT)
+
+tdeio_krarc_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+
+noinst_HEADERS = krarc.h
+
+EXTRA_DIST = krarc.protocol
+
+install-data-local:
+ $(mkinstalldirs) $(DESTDIR)$(kde_servicesdir)
+ $(INSTALL_DATA) $(srcdir)/krarc.protocol $(DESTDIR)$(kde_servicesdir)/krarc.protocol
+
+uninstall-local:
+ rm -f $(DESTDIR)$(kde_servicesdir)/krarc.protocol
+
+####### tdevelop will overwrite this part!!! (end)############
+# These paths are KDE specific. Use them:
+# kde_appsdir Where your application's menu entry (.desktop) should go to.
+# 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_toolbardir Where general toolbar icons should go to (deprecated, use KDE_ICON).
+# 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 TQt/TDE widget styles should go to.
+# kde_designerdir Where TQt Designer plugins should go to.
+
+
+# make messages.po. Move this one to ../po/ and "make merge" in po
+# the -x is for skipping messages already translated in tdelibs
+messages:
+ LIST=`find . -name \*.h -o -name \*.cpp`; \
+ if test -n "$$LIST"; then \
+ $(XGETTEXT) -C -ki18n -x $(kde_includes)/kde.pot $$LIST -o ../po/krarc.pot; \
+ fi
+
diff --git a/src/krArc/krarc.cpp b/src/krArc/krarc.cpp
new file mode 100644
index 0000000..a77eaea
--- /dev/null
+++ b/src/krArc/krarc.cpp
@@ -0,0 +1,1692 @@
+/***************************************************************************
+ krarc.cpp
+ -------------------
+ begin : Sat Jun 14 14:42:49 IDT 2003
+ copyright : (C) 2003 by Rafi Yanai & Shie Erlich
+ email : krusader@users.sf.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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <stdlib.h>
+
+#include <tqdir.h>
+#include <tqfile.h>
+#include <tqfileinfo.h>
+#include <tqregexp.h>
+#include <tqdir.h>
+
+#include <tdefileitem.h>
+#include <kdebug.h>
+#include <tdemessagebox.h>
+#include <tdeinstance.h>
+#include <tdelocale.h>
+#include <kurl.h>
+#include <tdetempfile.h>
+#include <klargefile.h>
+#include <kstandarddirs.h>
+#include <tdeio/job.h>
+#include <ktar.h>
+
+#include <iostream>
+#include "krarc.h"
+
+#define MAX_IPC_SIZE (1024*32)
+#define TRIES_WITH_PASSWORDS 3
+
+#if 0
+#define KRDEBUG(X...) do{ \
+ TQFile f("/tmp/debug"); \
+ f.open(IO_WriteOnly | IO_Append); \
+ TQTextStream stream( &f ); \
+ stream << "Pid:" << (int)getpid() << " " <<__FUNCTION__<<"(" <<__LINE__<<"): "; \
+ stream << X << endl; \
+ f.close(); \
+} while(0);
+#else
+#define KRDEBUG(X...)
+#endif
+
+using namespace TDEIO;
+extern "C" {
+
+int kdemain( int argc, char **argv ){
+ TDEInstance instance( "tdeio_krarc" );
+
+ if (argc != 4) {
+ kdWarning() << "Usage: tdeio_krarc protocol domain-socket1 domain-socket2" << endl;
+ exit(-1);
+ }
+
+ tdeio_krarcProtocol slave(argv[2], argv[3]);
+ slave.dispatchLoop();
+
+ return 0;
+}
+
+} // extern "C"
+
+tdeio_krarcProtocol::tdeio_krarcProtocol(const TQCString &pool_socket, const TQCString &app_socket)
+ : SlaveBase("tdeio_krarc", pool_socket, app_socket), archiveChanged(true), arcFile(0L),extArcReady(false),
+ password(TQString()) {
+
+ krConfig = new TDEConfig( "krusaderrc" );
+ krConfig->setGroup( "Dependencies" );
+
+ dirDict.setAutoDelete(true);
+
+ arcTempDir = locateLocal("tmp",TQString());
+ TQString dirName = "krArc"+TQDateTime::currentDateTime().toString(TQt::ISODate);
+ dirName.replace(TQRegExp(":"),"_");
+ TQDir(arcTempDir).mkdir(dirName);
+ arcTempDir = arcTempDir+dirName+"/";
+}
+
+/* ---------------------------------------------------------------------------------- */
+tdeio_krarcProtocol::~tdeio_krarcProtocol(){
+ // delete the temp directory
+ KrShellProcess proc;
+ proc << "rm -rf "<< arcTempDir;
+ proc.start(TDEProcess::Block);
+}
+
+/* ---------------------------------------------------------------------------------- */
+void tdeio_krarcProtocol::receivedData(TDEProcess*,char* buf,int len){
+ TQByteArray d(len);
+ d.setRawData(buf,len);
+ data(d);
+ d.resetRawData(buf,len);
+ processedSize(len);
+ decompressedLen += len;
+}
+
+void tdeio_krarcProtocol::mkdir(const KURL& url,int permissions){
+ KRDEBUG(url.path());
+
+ if( !setArcFile( url ) ) {
+ error(ERR_CANNOT_ENTER_DIRECTORY,url.path());
+ return;
+ }
+ if( newArchiveURL && !initDirDict(url) ){
+ error(ERR_CANNOT_ENTER_DIRECTORY,url.path());
+ return;
+ }
+
+ if( putCmd.isEmpty() ){
+ error(ERR_UNSUPPORTED_ACTION,
+ i18n("Creating directories is not supported with %1 archives").arg(arcType) );
+ return;
+ }
+
+ if( arcType == "arj" || arcType == "lha" ) {
+ TQString arcDir = url.path().mid(arcFile->url().path().length());
+ if( arcDir.right(1) != "/") arcDir = arcDir+"/";
+
+ if( dirDict.find( arcDir ) == 0 )
+ addNewDir( arcDir );
+ finished();
+ return;
+ }
+
+ //TQString tmpDir = arcTempDir+url.path();
+ TQString arcDir = findArcDirectory(url);
+ TQString tmpDir = arcTempDir + arcDir.mid(1) + url.path().mid(url.path().findRev("/")+1);
+ if( tmpDir.right(1) != "/" ) tmpDir = tmpDir+"/";
+
+ if( permissions == -1 ) permissions = 0777; //set default permissions
+ for( unsigned int i=arcTempDir.length();i<tmpDir.length(); i=tmpDir.find("/",i+1)){
+ ::mkdir(tmpDir.left(i).local8Bit(),permissions);
+ }
+
+ if( tmpDir.endsWith( "/" ) )
+ tmpDir.truncate( tmpDir.length() - 1 );
+
+ // pack the directory
+ KrShellProcess proc;
+ proc << putCmd << convertName( arcFile->url().path() ) + " " << convertFileName( tmpDir.mid(arcTempDir.length()) );
+ infoMessage(i18n("Creating %1 ...").arg( url.fileName() ) );
+ TQDir::setCurrent(arcTempDir);
+ proc.start(TDEProcess::Block,TDEProcess::AllOutput);
+
+ // delete the temp directory
+ TQDir().rmdir(arcTempDir);
+
+ if( !proc.normalExit() || !checkStatus( proc.exitStatus() ) ) {
+ error(ERR_COULD_NOT_WRITE,url.path() + "\n\n" + proc.getErrorMsg() );
+ return;
+ }
+
+ // force a refresh of archive information
+ initDirDict(url,true);
+ finished();
+}
+
+void tdeio_krarcProtocol::put(const KURL& url,int permissions,bool overwrite,bool resume){
+ KRDEBUG(url.path());
+ if( !setArcFile( url ) ) {
+ error(ERR_CANNOT_ENTER_DIRECTORY,url.path());
+ return;
+ }
+ if( newArchiveURL && !initDirDict(url) ){
+ error(ERR_CANNOT_ENTER_DIRECTORY,url.path());
+ return;
+ }
+
+ if( putCmd.isEmpty() ){
+ error(ERR_UNSUPPORTED_ACTION,
+ i18n("Writing to %1 archives is not supported").arg(arcType) );
+ return;
+ }
+ if( !overwrite && findFileEntry(url) ){
+ error( ERR_FILE_ALREADY_EXIST,url.path() );
+ return;
+ }
+
+ TQString arcDir = findArcDirectory(url);
+ TQString tmpFile = arcTempDir + arcDir.mid(1) + url.path().mid(url.path().findRev("/")+1);
+
+ TQString tmpDir = arcTempDir+arcDir.mid(1)+"/";
+ for( unsigned int i=arcTempDir.length();i<tmpDir.length(); i=tmpDir.find("/",i+1)){
+ TQDir("/").mkdir(tmpDir.left(i));
+ }
+ int fd;
+ if ( resume ) {
+ fd = KDE_open( tmpFile.local8Bit(), O_RDWR ); // append if resuming
+ KDE_lseek(fd, 0, SEEK_END); // Seek to end
+ } else {
+ // WABA: Make sure that we keep writing permissions ourselves,
+ // otherwise we can be in for a surprise on NFS.
+ mode_t initialMode;
+ if ( permissions != -1)
+ initialMode = permissions | S_IWUSR | S_IRUSR;
+ else
+ initialMode = 0666;
+
+ fd = KDE_open(tmpFile.local8Bit(), O_CREAT | O_TRUNC | O_WRONLY, initialMode);
+ }
+ TQByteArray buffer;
+ int readResult;
+ do{
+ dataReq();
+ readResult = readData(buffer);
+ write(fd,buffer.data(),buffer.size());
+ } while( readResult > 0 );
+ close(fd);
+ // pack the file
+ KrShellProcess proc;
+ proc << putCmd << convertName( arcFile->url().path() )+ " " <<convertFileName( tmpFile.mid(arcTempDir.length()) );
+ infoMessage(i18n("Packing %1 ...").arg( url.fileName() ) );
+ TQDir::setCurrent(arcTempDir);
+ proc.start(TDEProcess::Block,TDEProcess::AllOutput);
+ // remove the file
+ TQFile::remove(tmpFile);
+
+ if( !proc.normalExit() || !checkStatus( proc.exitStatus() ) ) {
+ error(ERR_COULD_NOT_WRITE,url.path() + "\n\n" + proc.getErrorMsg() );
+ return;
+ }
+ // force a refresh of archive information
+ initDirDict(url,true);
+ finished();
+}
+
+void tdeio_krarcProtocol::get(const KURL& url ){
+ get( url, TRIES_WITH_PASSWORDS );
+}
+
+void tdeio_krarcProtocol::get(const KURL& url, int tries ){
+ bool decompressToFile = false;
+ KRDEBUG(url.path());
+
+ if( !setArcFile( url ) ) {
+ error(ERR_CANNOT_ENTER_DIRECTORY,url.path());
+ return;
+ }
+ if( newArchiveURL && !initDirDict(url) ){
+ error(ERR_CANNOT_ENTER_DIRECTORY,url.path());
+ return;
+ }
+
+ if( getCmd.isEmpty() ){
+ error(ERR_UNSUPPORTED_ACTION,
+ i18n("Retrieving data from %1 archives is not supported").arg(arcType) );
+ return;
+ }
+ UDSEntry* entry = findFileEntry(url);
+ if( !entry ){
+ error(TDEIO::ERR_DOES_NOT_EXIST,url.path());
+ return;
+ }
+ if(KFileItem(*entry,url).isDir()){
+ error(TDEIO::ERR_IS_DIRECTORY,url.path());
+ return;
+ }
+ TDEIO::filesize_t expectedSize = KFileItem(*entry,url).size();
+ // for RPM files extract the cpio file first
+ if( !extArcReady && arcType == "rpm"){
+ KrShellProcess cpio;
+ cpio << "rpm2cpio" << convertName( arcFile->url().path(-1) ) << " > " << arcTempDir+"contents.cpio";
+ cpio.start(TDEProcess::Block,TDEProcess::AllOutput);
+ if( !cpio.normalExit() || cpio.exitStatus() != 0 ) {
+ error(ERR_COULD_NOT_READ,url.path() + "\n\n" + cpio.getErrorMsg() );
+ return;
+ }
+ extArcReady = true;
+ }
+ // for DEB files extract the tar file first
+ if ( !extArcReady && arcType == "deb" ) {
+ KrShellProcess dpkg;
+ dpkg << cmd + " --fsys-tarfile" << convertName( arcFile->url().path( -1 ) ) << " > " << arcTempDir + "contents.cpio";
+ dpkg.start( TDEProcess::Block, TDEProcess::AllOutput );
+ if( !dpkg.normalExit() || dpkg.exitStatus() != 0 ) {
+ error(ERR_COULD_NOT_READ,url.path() + "\n\n" + dpkg.getErrorMsg() );
+ return;
+ }
+ extArcReady = true;
+ }
+
+ // Use the external unpacker to unpack the file
+ TQString file = url.path().mid(arcFile->url().path().length()+1);
+ KrShellProcess proc;
+ if( extArcReady ){
+ proc << getCmd << arcTempDir+"contents.cpio " << convertName( "*"+file );
+ } else if( arcType == "arj" || arcType == "ace" || arcType == "7z" ) {
+ proc << getCmd << convertName( arcFile->url().path(-1) )+ " " << convertFileName( file );
+ if( arcType == "ace" && TQFile( "/dev/ptmx" ).exists() ) // Don't remove, unace crashes if missing!!!
+ proc << "<" << "/dev/ptmx";
+ file = url.fileName();
+ decompressToFile = true;
+ } else {
+ decompressedLen = 0;
+ // Determine the mimetype of the file to be retrieved, and emit it.
+ // This is mandatory in all slaves (for KRun/BrowserRun to work).
+ KMimeType::Ptr mt = KMimeType::findByURL( arcTempDir+file, 0, false /* NOT local URL */ );
+ emit mimeType( mt->name() );
+ proc << getCmd << convertName( arcFile->url().path() )+" ";
+ if( arcType != "gzip" && arcType != "bzip2" && arcType != "xz") proc << convertFileName( file );
+ connect(&proc,TQ_SIGNAL(receivedStdout(TDEProcess*,char*,int)),
+ this,TQ_SLOT(receivedData(TDEProcess*,char*,int)) );
+ }
+ infoMessage(i18n("Unpacking %1 ...").arg( url.fileName() ) );
+ // change the working directory to our arcTempDir
+ TQDir::setCurrent(arcTempDir);
+ proc.start(TDEProcess::Block,TDEProcess::AllOutput);
+
+ if( !extArcReady && !decompressToFile ) {
+ if( !proc.normalExit() || !checkStatus( proc.exitStatus() ) ||
+ ( arcType != "bzip2" && arcType != "xz" && expectedSize != decompressedLen ) ) {
+ if( encrypted && tries ) {
+ invalidatePassword();
+ get( url, tries - 1 );
+ return;
+ }
+ error( TDEIO::ERR_ACCESS_DENIED, url.path() + "\n\n" + proc.getErrorMsg() );
+ return;
+ }
+ }
+ else{
+ if( !proc.normalExit() || !checkStatus( proc.exitStatus() ) || !TQFileInfo( arcTempDir+file ).exists() ) {
+ if( decompressToFile )
+ TQFile(arcTempDir+file).remove();
+ if( encrypted && tries ) {
+ invalidatePassword();
+ get( url, tries - 1 );
+ return;
+ }
+ error( TDEIO::ERR_ACCESS_DENIED, url.path() );
+ return;
+ }
+ // the follwing block is ripped from KDE file TDEIO::Slave
+ // $Id: krarc.cpp,v 1.43 2007/01/13 13:39:51 ckarai Exp $
+ TQCString _path( TQFile::encodeName(arcTempDir+file) );
+ KDE_struct_stat buff;
+ if( KDE_lstat( _path.data(), &buff ) == -1 ) {
+ if ( errno == EACCES )
+ error( TDEIO::ERR_ACCESS_DENIED, url.path() );
+ else
+ error( TDEIO::ERR_DOES_NOT_EXIST, url.path() );
+ return;
+ }
+ if ( S_ISDIR( buff.st_mode ) ) {
+ error( TDEIO::ERR_IS_DIRECTORY, url.path() );
+ return;
+ }
+ if ( !S_ISREG(buff.st_mode) ) {
+ error( TDEIO::ERR_CANNOT_OPEN_FOR_READING, url.path() );
+ return;
+ }
+ int fd = KDE_open( _path.data(), O_RDONLY );
+ if ( fd < 0 ) {
+ error( TDEIO::ERR_CANNOT_OPEN_FOR_READING, url.path() );
+ return;
+ }
+ // Determine the mimetype of the file to be retrieved, and emit it.
+ // This is mandatory in all slaves (for KRun/BrowserRun to work).
+ KMimeType::Ptr mt = KMimeType::findByURL( arcTempDir+file, buff.st_mode, true /* local URL */ );
+ emit mimeType( mt->name() );
+
+ TDEIO::filesize_t processed_size = 0;
+
+ TQString resumeOffset = metaData("resume");
+ if ( !resumeOffset.isEmpty() ){
+ bool ok;
+ TDEIO::fileoffset_t offset = resumeOffset.toLongLong(&ok);
+ if (ok && (offset > 0) && (offset < buff.st_size)){
+ if (KDE_lseek(fd, offset, SEEK_SET) == offset){
+ canResume ();
+ processed_size = offset;
+ }
+ }
+ }
+
+ totalSize( buff.st_size );
+
+ char buffer[ MAX_IPC_SIZE ];
+ TQByteArray array;
+ while( 1 ){
+ int n = ::read( fd, buffer, MAX_IPC_SIZE );
+ if (n == -1){
+ if (errno == EINTR)
+ continue;
+ error( TDEIO::ERR_COULD_NOT_READ, url.path());
+ close(fd);
+ return;
+ }
+ if (n == 0)
+ break; // Finished
+
+ array.setRawData(buffer, n);
+ data( array );
+ array.resetRawData(buffer, n);
+
+ processed_size += n;
+ }
+
+ data( TQByteArray() );
+ close( fd );
+ processedSize( buff.st_size );
+ finished();
+
+ if( decompressToFile )
+ TQFile(arcTempDir+file).remove();
+ return;
+ }
+ // send empty buffer to mark EOF
+ data(TQByteArray());
+ finished();
+}
+
+void tdeio_krarcProtocol::del(KURL const & url, bool isFile){
+ KRDEBUG(url.path());
+
+ if( !setArcFile( url ) ) {
+ error(ERR_CANNOT_ENTER_DIRECTORY,url.path());
+ return;
+ }
+ if( newArchiveURL && !initDirDict(url) ){
+ error(ERR_CANNOT_ENTER_DIRECTORY,url.path());
+ return;
+ }
+
+ if( delCmd.isEmpty() ){
+ error(ERR_UNSUPPORTED_ACTION,
+ i18n("Deleting files from %1 archives is not supported").arg(arcType) );
+ return;
+ }
+ if( !findFileEntry(url) ){
+ if( ( arcType != "arj" && arcType != "lha" ) || isFile ) {
+ error(TDEIO::ERR_DOES_NOT_EXIST,url.path());
+ return;
+ }
+ }
+
+ TQString file = url.path().mid(arcFile->url().path().length()+1);
+ if( !isFile && file.right(1) != "/" ) {
+ if(arcType == "zip") file = file + "/";
+ }
+ KrShellProcess proc;
+ proc << delCmd << convertName( arcFile->url().path() )+" " << convertFileName( file );
+ infoMessage(i18n("Deleting %1 ...").arg( url.fileName() ) );
+ proc.start(TDEProcess::Block, TDEProcess::AllOutput);
+ if( !proc.normalExit() || !checkStatus( proc.exitStatus() ) ) {
+ error(ERR_COULD_NOT_WRITE,url.path() + "\n\n" + proc.getErrorMsg() );
+ return;
+ }
+ // force a refresh of archive information
+ initDirDict(url,true);
+ finished();
+}
+
+void tdeio_krarcProtocol::stat( const KURL & url ){
+ KRDEBUG(url.path());
+ if( !setArcFile( url ) ) {
+ error(ERR_CANNOT_ENTER_DIRECTORY,url.path());
+ return;
+ }
+ if( newArchiveURL && !initDirDict(url) ){
+ error(ERR_CANNOT_ENTER_DIRECTORY,url.path());
+ return;
+ }
+
+ if( listCmd.isEmpty() ){
+ error(ERR_UNSUPPORTED_ACTION,
+ i18n("Accessing files is not supported with the %1 archives").arg(arcType) );
+ return;
+ }
+ TQString path = url.path(-1);
+ KURL newUrl = url;
+
+ // but treat the archive itself as the archive root
+ if( path == arcFile->url().path(-1) ){
+ newUrl.setPath(path+"/");
+ path = newUrl.path();
+ }
+ // we might be stating a real file
+ if( TQFileInfo(path).exists() ){
+ KDE_struct_stat buff;
+ KDE_stat( path.local8Bit(), &buff );
+ TQString mime = KMimeType::findByPath(path,buff.st_mode)->name();
+ statEntry(KFileItem(path,mime,buff.st_mode).entry());
+ finished();
+ return;
+ }
+ UDSEntry* entry = findFileEntry(newUrl);
+ if( entry ){
+ statEntry( *entry );
+ finished();
+ } else error( TDEIO::ERR_DOES_NOT_EXIST, path );
+}
+
+void tdeio_krarcProtocol::copy (const KURL &url, const KURL &dest, int, bool overwrite) {
+ KRDEBUG(url.path());
+
+ // KDE HACK: opening the password dlg in copy causes error for the COPY, and further problems
+ // that's why encrypted files are not allowed to copy
+ if( !encrypted && dest.isLocalFile() )
+ do {
+ if( url.fileName() != dest.fileName() )
+ break;
+
+ //the file exists and we don't want to overwrite
+ if ((!overwrite) && ( TQFile( dest.path() ).exists() ) ) {
+ error(ERR_FILE_ALREADY_EXIST, TQFile::encodeName(dest.path()) );
+ return;
+ };
+
+ if( !setArcFile( url ) ) {
+ error(ERR_CANNOT_ENTER_DIRECTORY,url.path());
+ return;
+ }
+ if( newArchiveURL && !initDirDict(url) ){
+ error(ERR_CANNOT_ENTER_DIRECTORY,url.path());
+ return;
+ }
+
+ UDSEntry* entry = findFileEntry(url);
+ if( copyCmd.isEmpty() || !entry )
+ break;
+
+ TQString file = url.path().mid(arcFile->url().path().length()+1);
+
+ TQString destDir = dest.path( -1 );
+ if( !TQDir( destDir ).exists() ) {
+ int ndx = destDir.findRev( '/' );
+ if( ndx != -1 )
+ destDir.truncate( ndx+1 );
+ }
+
+ TQDir::setCurrent( destDir.local8Bit() );
+
+ KrShellProcess proc;
+ proc << copyCmd << convertName( arcFile->url().path(-1) )+" " << convertFileName( file );
+ if( arcType == "ace" && TQFile( "/dev/ptmx" ).exists() ) // Don't remove, unace crashes if missing!!!
+ proc << "<" << "/dev/ptmx";
+
+ infoMessage(i18n("Unpacking %1 ...").arg( url.fileName() ) );
+ proc.start(TDEProcess::Block, TDEProcess::AllOutput);
+ if( !proc.normalExit() || !checkStatus( proc.exitStatus() ) ) {
+ error(TDEIO::ERR_COULD_NOT_WRITE, dest.path(-1) + "\n\n" + proc.getErrorMsg() );
+ return;
+ }
+ if( !TQFileInfo( dest.path(-1) ).exists() ) {
+ error( TDEIO::ERR_COULD_NOT_WRITE, dest.path(-1) );
+ return;
+ }
+
+ processedSize( KFileItem(*entry,url).size() );
+ finished();
+ TQDir::setCurrent( "/" ); /* for being able to umount devices after copying*/
+ return;
+ }while( 0 );
+
+ error( ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, CMD_COPY));
+}
+
+void tdeio_krarcProtocol::listDir(const KURL& url){
+ KRDEBUG(url.path());
+ if( !setArcFile( url ) ) {
+ error(ERR_CANNOT_ENTER_DIRECTORY,url.path());
+ return;
+ }
+ if( listCmd.isEmpty() ){
+ error(ERR_UNSUPPORTED_ACTION,
+ i18n("Listing directories is not supported for %1 archives").arg(arcType) );
+ return;
+ }
+ TQString path = url.path();
+ if( path.right(1) != "/" ) path = path+"/";
+
+ // it might be a real dir !
+ if( TQFileInfo(path).exists() ){
+ if( TQFileInfo(path).isDir() ){
+ KURL redir;
+ redir.setPath( url.path() );
+ redirection(redir);
+ finished();
+ } else { // maybe it's an archive !
+ error(ERR_IS_FILE,path);
+ }
+ return;
+ }
+ if( !initDirDict(url) ){
+ error( ERR_CANNOT_ENTER_DIRECTORY, url.path());
+ return;
+ }
+ TQString arcDir = path.mid(arcFile->url().path().length());
+ arcDir.truncate(arcDir.findRev("/"));
+ if(arcDir.right(1) != "/") arcDir = arcDir+"/";
+
+ UDSEntryList* dirList = dirDict.find(arcDir);
+ if( dirList == 0 ){
+ error(ERR_CANNOT_ENTER_DIRECTORY,url.path());
+ return;
+ }
+ totalSize(dirList->size());
+ listEntries(*dirList);
+ finished();
+}
+
+bool tdeio_krarcProtocol::setArcFile(const KURL& url){
+ TQString path = url.path();
+ time_t currTime = time( 0 );
+ archiveChanged = true;
+ newArchiveURL = true;
+ // is the file already set ?
+ if( arcFile && arcFile->url().path(-1) == path.left(arcFile->url().path(-1).length()) ){
+ newArchiveURL = false;
+ // Has it changed ?
+ KFileItem* newArcFile = new KFileItem(arcFile->url(),TQString(),arcFile->mode());
+ if( !newArcFile->cmp( *arcFile ) ){
+ delete arcFile;
+ password = TQString();
+ extArcReady = false;
+ arcFile = newArcFile;
+ } else { // same old file
+ delete newArcFile;
+ archiveChanged = false;
+ if( encrypted && password.isNull() )
+ initArcParameters();
+ }
+ } else { // it's a new file...
+ extArcReady = false;
+ if( arcFile ){
+ delete arcFile;
+ password = TQString();
+ arcFile = 0L;
+ }
+ TQString newPath = path;
+ if(newPath.right(1) != "/") newPath = newPath+"/";
+ for(int pos=0; pos >= 0; pos = newPath.find("/",pos+1)){
+ TQFileInfo qfi(newPath.left(pos));
+ if( qfi.exists() && !qfi.isDir() ){
+ KDE_struct_stat stat_p;
+ KDE_lstat(newPath.left(pos).local8Bit(),&stat_p);
+ arcFile = new KFileItem(KURL::fromPathOrURL( newPath.left(pos) ),TQString(),stat_p.st_mode);
+ break;
+ }
+ }
+ if( !arcFile ){
+ error( ERR_DOES_NOT_EXIST,path );
+ return false; // file not found
+ }
+ }
+
+ /* FIX: file change can only be detected if the timestamp between the two consequent
+ changes is more than 1s. If the archive is continuously changing (check: move files
+ inside the archive), krarc may erronously think, that the archive file is unchanged,
+ because the timestamp is the same as the previous one. This situation can only occur
+ if the modification time equals with the current time. While this condition is true,
+ we can say, that the archive is changing, so content reread is always necessary
+ during that period. */
+ if( archiveChanging )
+ archiveChanged = true;
+ archiveChanging = ( currTime == arcFile->time( UDS_MODIFICATION_TIME ) );
+
+ arcPath = arcFile->url().path(-1);
+ arcType = detectArchive( encrypted, arcPath );
+
+ if( arcType == "tbz" )
+ arcType = "bzip2";
+ else if( arcType == "tgz" )
+ arcType = "gzip";
+ else if( arcType == "txz" )
+ arcType = "xz";
+
+ if( arcType.isEmpty() ) {
+ arcType = arcFile->mimetype();
+ arcType = arcType.mid(arcType.findRev("-")+1);
+
+ if( arcType == "jar" )
+ arcType = "zip";
+ }
+
+ return initArcParameters();
+}
+
+bool tdeio_krarcProtocol::initDirDict(const KURL&url, bool forced){
+ // set the archive location
+ //if( !setArcFile(url.path()) ) return false;
+ // no need to rescan the archive if it's not changed
+ if( !archiveChanged && !forced ) return true;
+ extArcReady = false;
+
+ if( !setArcFile( url ) )
+ return false; /* if the archive was changed refresh the file information */
+
+ // write the temp file
+ KrShellProcess proc;
+ KTempFile temp( TQString(), "tmp" );
+ temp.setAutoDelete(true);
+ if (arcType != "bzip2" && arcType != "xz") {
+ if( arcType == "rpm" )
+ proc << listCmd << convertName( arcPath ) <<" > " << temp.name();
+ else
+ proc << listCmd << convertName( arcFile->url().path(-1) ) <<" > " << temp.name();
+ if( arcType == "ace" && TQFile( "/dev/ptmx" ).exists() ) // Don't remove, unace crashes if missing!!!
+ proc << "<" << "/dev/ptmx";
+ proc.start(TDEProcess::Block,TDEProcess::AllOutput);
+ if( !proc.normalExit() || !checkStatus( proc.exitStatus() ) ) return false;
+ }
+ // clear the dir dictionary
+ dirDict.clear();
+
+ // add the "/" directory
+ UDSEntryList* root = new UDSEntryList();
+ dirDict.insert("/",root);
+ // and the "/" UDSEntry
+ UDSEntry entry;
+ UDSAtom atom;
+ atom.m_uds = UDS_NAME;
+ atom.m_str = ".";
+ entry.append(atom);
+ mode_t mode = parsePermString("drwxr-xr-x");
+ atom.m_uds = UDS_FILE_TYPE;
+ atom.m_long = mode & S_IFMT; // keep file type only
+ entry.append( atom );
+ atom.m_uds = UDS_ACCESS;
+ atom.m_long = mode & 07777; // keep permissions only
+ entry.append( atom );
+
+ root->append(entry);
+
+ if (arcType == "bzip2" || arcType == "xz"){
+ KRDEBUG("Got me here...");
+ parseLine(0,"",temp.file());
+ return true;
+ }
+
+ // parse the temp file
+ temp.file()->open(IO_ReadOnly);
+ char buf[1000];
+ TQString line;
+
+ int lineNo = 0;
+ bool invalidLine = false;
+ // the rar list is started with a ------ line.
+ if(arcType == "rar" || arcType == "arj" || arcType == "lha" || arcType == "7z" ){
+ while(temp.file()->readLine(buf,1000) != -1){
+ line = TQString::fromLocal8Bit(buf);
+ if( line.startsWith("----------") ) break;
+ }
+ }
+ while(temp.file()->readLine(buf,1000) != -1) {
+ line = TQString::fromLocal8Bit(buf);
+ if( arcType == "rar" ) {
+ // the rar list is ended with a ------ line.
+ if( line.startsWith("----------") ) {
+ invalidLine = !invalidLine;
+ continue;
+ }
+ if( invalidLine )
+ continue;
+ else{
+ temp.file()->readLine(buf,1000);
+ line = line+TQString::fromLocal8Bit(buf);
+ if( line[0]=='*' ) // encrypted archives starts with '*'
+ line[0]=' ';
+ }
+ }
+ if( arcType == "ace" ) {
+ // the ace list begins with a number.
+ if( !line[0].isDigit() ) continue;
+ }
+ if( arcType == "arj" ) {
+ // the arj list is ended with a ------ line.
+ if( line.startsWith("----------") ) {
+ invalidLine = !invalidLine;
+ continue;
+ }
+ if( invalidLine )
+ continue;
+ else {
+ temp.file()->readLine(buf,1000);
+ line = line+TQString::fromLocal8Bit(buf);
+ temp.file()->readLine(buf,1000);
+ line = line+TQString::fromLocal8Bit(buf);
+ temp.file()->readLine(buf,1000);
+ line = line+TQString::fromLocal8Bit(buf);
+ }
+ }
+ if( arcType == "lha" || arcType == "7z" ) {
+ // the arj list is ended with a ------ line.
+ if( line.startsWith("----------") ) break;
+ }
+ parseLine(lineNo++,line.stripWhiteSpace(),temp.file());
+ }
+ // close and delete our file
+ temp.file()->close();
+
+ archiveChanged = false;
+ return true;
+}
+
+TQString tdeio_krarcProtocol::findArcDirectory(const KURL& url){
+ TQString path = url.path();
+ if( path.right(1) == "/" ) path.truncate(path.length()-1);
+
+ if( !initDirDict(url) ){
+ return TQString();
+ }
+ TQString arcDir = path.mid(arcFile->url().path().length());
+ arcDir.truncate(arcDir.findRev("/"));
+ if(arcDir.right(1) != "/") arcDir = arcDir+"/";
+
+ return arcDir;
+}
+
+UDSEntry* tdeio_krarcProtocol::findFileEntry(const KURL& url){
+ TQString arcDir = findArcDirectory(url);
+ if( arcDir.isEmpty() ) return 0;
+
+ UDSEntryList* dirList = dirDict.find(arcDir);
+ if( !dirList ){
+ return 0;
+ }
+ TQString name = url.path();
+ if( arcFile->url().path(-1) == url.path(-1) ) name = "."; // the "/" case
+ else{
+ if( name.right(1) == "/" ) name.truncate(name.length()-1);
+ name = name.mid(name.findRev("/")+1);
+ }
+
+ UDSEntryList::iterator entry;
+ UDSEntry::iterator atom;
+
+ for ( entry = dirList->begin(); entry != dirList->end(); ++entry ){
+ for( atom = (*entry).begin(); atom != (*entry).end(); ++atom ){
+ if( (*atom).m_uds == UDS_NAME ){
+ if((*atom).m_str == name){
+ return &(*entry);
+ } else break;
+ }
+ }
+ }
+ return 0;
+}
+
+TQString tdeio_krarcProtocol::nextWord(TQString &s,char d) {
+ s=s.stripWhiteSpace();
+ int j=s.find(d,0);
+ TQString temp=s.left(j); // find the leftmost word.
+ s.remove(0,j);
+ return temp;
+}
+
+mode_t tdeio_krarcProtocol::parsePermString(TQString perm){
+ mode_t mode=0;
+ // file type
+ if(perm[0] == 'd') mode |= S_IFDIR;
+ if(perm[0] == 'l') mode |= S_IFLNK;
+ if(perm[0] == '-') mode |= S_IFREG;
+ // owner permissions
+ if(perm[1] != '-') mode |= S_IRUSR;
+ if(perm[2] != '-') mode |= S_IWUSR;
+ if(perm[3] != '-') mode |= S_IXUSR;
+ // group permissions
+ if(perm[4] != '-') mode |= S_IRGRP;
+ if(perm[5] != '-') mode |= S_IWGRP;
+ if(perm[6] != '-') mode |= S_IXGRP;
+ // other permissions
+ if(perm[7] != '-') mode |= S_IROTH;
+ if(perm[8] != '-') mode |= S_IWOTH;
+ if(perm[9] != '-') mode |= S_IXOTH;
+
+ return mode;
+}
+
+UDSEntryList* tdeio_krarcProtocol::addNewDir(TQString path){
+ UDSEntryList* dir;
+
+ // check if the current dir exists
+ dir = dirDict.find(path);
+ if(dir != 0) return dir; // dir exists- return it !
+
+ // set dir to the parent dir
+ dir = addNewDir(path.left(path.findRev("/",-2)+1));
+
+ // add a new entry in the parent dir
+ TQString name = path.mid(path.findRev("/",-2)+1);
+ name = name.left(name.length()-1);
+
+ UDSEntry entry;
+ UDSAtom atom;
+ atom.m_uds = UDS_NAME;
+ atom.m_str = name;
+ entry.append(atom);
+
+ mode_t mode = parsePermString("drwxr-xr-x");
+
+ atom.m_uds = UDS_FILE_TYPE;
+ atom.m_long = mode & S_IFMT; // keep file type only
+ entry.append( atom );
+
+ atom.m_uds = UDS_ACCESS;
+ atom.m_long = mode & 07777; // keep permissions only
+ entry.append( atom );
+
+ atom.m_uds = UDS_SIZE;
+ atom.m_long = 0;
+ entry.append( atom );
+
+ atom.m_uds = UDS_MODIFICATION_TIME;
+ atom.m_long = arcFile->time(UDS_MODIFICATION_TIME);
+ entry.append( atom );
+
+ dir->append(entry);
+
+ // create a new directory entry and add it..
+ dir = new UDSEntryList();
+ dirDict.insert(path,dir);
+
+ return dir;
+}
+
+void tdeio_krarcProtocol::parseLine(int lineNo, TQString line, TQFile*) {
+ UDSEntryList* dir;
+ UDSEntry entry;
+ UDSAtom atom;
+
+ TQString owner = TQString();
+ TQString group = TQString();
+ TQString symlinkDest = TQString();
+ TQString perm = TQString();
+ mode_t mode = 0666;
+ size_t size = 0;
+ time_t time = ::time(0);
+ TQString fullName = TQString();
+
+ if(arcType == "zip"){
+ // permissions
+ perm = nextWord(line);
+ // ignore the next 2 fields
+ nextWord(line); nextWord(line);
+ // size
+ size = nextWord(line).toLong();
+ // ignore the next 2 fields
+ nextWord(line);nextWord(line);
+ // date & time
+ TQString d = nextWord(line);
+ TQDate qdate(d.mid(0,4).toInt(),d.mid(4,2).toInt(),d.mid(6,2).toInt());
+ TQTime qtime(d.mid(9,2).toInt(),d.mid(11,2).toInt(),d.mid(13,2).toInt());
+ time = TQDateTime(qdate,qtime).toTime_t();
+ // full name
+ fullName = nextWord(line,'\n');
+
+ if(perm.length() != 10)
+ perm = (perm.at(0)=='d' || fullName.endsWith( "/" )) ? "drwxr-xr-x" : "-rw-r--r--" ;
+ mode = parsePermString(perm);
+ }
+ if(arcType == "rar") {
+ // full name
+ fullName = nextWord(line,'\n');
+ // size
+ size = nextWord(line).toLong();
+ // ignore the next 2 fields
+ nextWord(line); nextWord(line);
+ // date & time
+ TQString d = nextWord(line);
+ int year = 1900 + d.mid(6,2).toInt();
+ if( year < 1930 ) year+=100;
+ TQDate qdate( year, d.mid(3,2).toInt(), d.mid(0,2).toInt() );
+ TQString t = nextWord(line);
+ TQTime qtime(t.mid(0,2).toInt(),t.mid(3,2).toInt(),0);
+ time = TQDateTime(qdate,qtime).toTime_t();
+ // permissions
+ perm = nextWord(line);
+
+ if( perm.length() == 7 ) // windows rar permission format
+ {
+ bool isDir = ( perm.at(1).lower() == 'd' );
+ bool isReadOnly = ( perm.at(2).lower() == 'r' );
+
+ perm = isDir ? "drwxr-xr-x" : "-rw-r--r--";
+
+ if( isReadOnly )
+ perm.at( 2 ) = '-';
+ }
+
+ if(perm.length() != 10) perm = (perm.at(0)=='d')? "drwxr-xr-x" : "-rw-r--r--" ;
+ mode = parsePermString(perm);
+ }
+ if(arcType == "arj"){
+ nextWord(line);
+ // full name
+ fullName = nextWord(line,'\n');
+ // ignore the next 2 fields
+ nextWord(line); nextWord(line);
+ // size
+ size = nextWord(line).toLong();
+ // ignore the next 2 fields
+ nextWord(line); nextWord(line);
+ // date & time
+ TQString d = nextWord(line);
+ int year = 1900 + d.mid(0,2).toInt();
+ if( year < 1930 ) year+=100;
+ TQDate qdate( year, d.mid(3,2).toInt(), d.mid(6,2).toInt() );
+ TQString t = nextWord(line);
+ TQTime qtime(t.mid(0,2).toInt(),t.mid(3,2).toInt(),0);
+ time = TQDateTime(qdate,qtime).toTime_t();
+ // permissions
+ perm = nextWord(line);
+ if(perm.length() != 10) perm = (perm.at(0)=='d')? "drwxr-xr-x" : "-rw-r--r--" ;
+ mode = parsePermString(perm);
+ }
+ if(arcType == "rpm"){
+ // full name
+ fullName = nextWord(line);
+ // size
+ size = nextWord(line).toULong();
+ // date & time
+ time = nextWord(line).toULong();
+ // next field is md5sum, ignore it
+ nextWord(line);
+ // permissions
+ mode = nextWord(line).toULong(0,8);
+ // Owner & Group
+ owner = nextWord(line);
+ group = nextWord(line);
+ // symlink destination
+ if( S_ISLNK(mode) ){
+ // ignore the next 3 fields
+ nextWord(line); nextWord(line); nextWord(line);
+ symlinkDest = nextWord(line);
+ }
+ }
+ if( arcType == "gzip" ){
+ if( !lineNo ) return; //ignore the first line
+ // first field is uncompressed size - ignore it
+ nextWord(line);
+ // size
+ size = nextWord(line).toULong();
+ // ignore the next field
+ nextWord(line);
+ // full name
+ fullName = nextWord(line);
+ fullName = fullName.mid(fullName.findRev("/")+1);
+ }
+ if( arcType == "bzip2" ){
+ // There is no way to list bzip2 files, so we take our information from
+ // the archive itself...
+ fullName = arcFile->name();
+ if( fullName.endsWith("bz2") ) fullName.truncate(fullName.length()-4);
+ mode = arcFile->mode();
+ size = arcFile->size();
+ }
+ if(arcType == "lha"){
+ // permissions
+ perm = nextWord(line);
+ if(perm.length() != 10) perm = (perm.at(0)=='d')? "drwxr-xr-x" : "-rw-r--r--" ;
+ mode = parsePermString(perm);
+ // ignore the next field
+ nextWord(line);
+ // size
+ size = nextWord(line).toLong();
+ // ignore the next field
+ nextWord(line);
+ // date & time
+ int month = (TQStringList::split(',', "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec")).findIndex( nextWord(line) ) + 1;
+ int day = nextWord(line).toInt();
+ int year = TQDate::currentDate().year();
+ TQString third = nextWord(line);
+ TQTime qtime;
+
+ if( third.contains(":" ) )
+ qtime = TQTime::fromString( third );
+ else
+ year = third.toInt();
+
+ TQDate qdate(year, month, day );
+
+ time = TQDateTime(qdate, qtime).toTime_t();
+ // full name
+ fullName = nextWord(line,'\n');
+ }
+ if(arcType == "ace"){
+ // date & time
+ TQString d = nextWord(line);
+ int year = 1900 + d.mid(6,2).toInt();
+ if( year < 1930 ) year+=100;
+ TQDate qdate( year, d.mid(3,2).toInt(), d.mid(0,2).toInt() );
+ TQString t = nextWord(line);
+ TQTime qtime(t.mid(0,2).toInt(),t.mid(3,2).toInt(),0);
+ time = TQDateTime(qdate,qtime).toTime_t();
+ // ignore the next field
+ nextWord(line);
+ // size
+ size = nextWord(line).toLong();
+ // ignore the next field
+ nextWord(line);
+ // full name
+ fullName = nextWord(line,'\n');
+ if( fullName[ 0 ] == '*' ) // encrypted archives starts with '*'
+ fullName = fullName.mid( 1 );
+ }
+ if( arcType == "deb" ){
+ // permissions
+ perm = nextWord( line );
+ mode = parsePermString( perm );
+ // Owner & Group
+ owner = nextWord( line,'/' );
+ group = nextWord( line ).mid(1);
+ // size
+ size = nextWord( line ).toLong();
+ // date & time
+ TQString d = nextWord( line );
+ TQDate qdate( d.mid( 0, 4 ).toInt(), d.mid( 5, 2 ).toInt(), d.mid( 8, 2 ).toInt() );
+ TQString t = nextWord( line );
+ TQTime qtime( t.mid( 0, 2 ).toInt(), t.mid( 3, 2 ).toInt(), 0 );
+ time = TQDateTime( qdate, qtime ).toTime_t();
+ // full name
+ fullName = nextWord( line, '\n' ).mid( 1 );
+ //if ( fullName.right( 1 ) == "/" ) return;
+ if( fullName.contains("->") ){
+ symlinkDest = fullName.mid(fullName.find("->")+2);
+ fullName = fullName.left(fullName.find("->")-1);
+ }
+ }
+ if(arcType == "7z"){
+ // date & time
+ TQString d = nextWord(line);
+ TQDate qdate( d.mid(0,4).toInt(), d.mid(5,2).toInt(), d.mid(8,2).toInt() );
+ TQString t = nextWord(line);
+ TQTime qtime(t.mid(0,2).toInt(),t.mid(3,2).toInt(),t.mid(6,2).toInt() );
+ time = TQDateTime(qdate,qtime).toTime_t();
+
+ // permissions
+ perm = nextWord(line);
+ bool isDir = ( perm.at(0).lower() == 'd' );
+ bool isReadOnly = ( perm.at(1).lower() == 'r' );
+ perm = isDir ? "drwxr-xr-x" : "-rw-r--r--";
+ if( isReadOnly )
+ perm.at( 2 ) = '-';
+
+ mode = parsePermString(perm);
+
+ // size
+ size = nextWord(line).toLong();
+
+ // ignore the next 15 characters
+ line = line.mid( 15 );
+
+ // full name
+ fullName = nextWord(line,'\n');
+ }
+ if (arcType == "xz") {
+ fullName = arcFile->name();
+ if (fullName.endsWith("xz")) {
+ fullName.truncate(fullName.length() - 3);
+ }
+ mode = arcFile->mode();
+ size = arcFile->size();
+ }
+
+ if( fullName.right(1) == "/" ) fullName = fullName.left(fullName.length()-1);
+ if( !fullName.startsWith("/") ) fullName = "/"+fullName;
+ TQString path = fullName.left(fullName.findRev("/")+1);
+ // set/create the directory UDSEntryList
+ dir = dirDict.find(path);
+ if(dir == 0) dir = addNewDir(path);
+ TQString name = fullName.mid(fullName.findRev("/")+1);
+ // file name
+ atom.m_uds = UDS_NAME;
+ atom.m_str = name;
+ entry.append(atom);
+ // file type
+ atom.m_uds = UDS_FILE_TYPE;
+ atom.m_long = mode & S_IFMT; // keep file type only
+ entry.append( atom );
+ // file permissions
+ atom.m_uds = UDS_ACCESS;
+ atom.m_long = mode & 07777; // keep permissions only
+ entry.append( atom );
+ // file size
+ atom.m_uds = UDS_SIZE;
+ atom.m_long = size;
+ entry.append( atom );
+ // modification time
+ atom.m_uds = UDS_MODIFICATION_TIME;
+ atom.m_long = time;
+ entry.append( atom );
+ // link destination
+ if( !symlinkDest.isEmpty() ){
+ atom.m_uds = UDS_LINK_DEST;
+ atom.m_str = symlinkDest;
+ entry.append( atom );
+ }
+ if( S_ISDIR(mode) ){
+ fullName=fullName+"/";
+ if(dirDict.find(fullName) == 0)
+ dirDict.insert(fullName,new UDSEntryList());
+ else {
+ // try to overwrite an existing entry
+ UDSEntryList::iterator entryIt;
+ UDSEntry::iterator atomIt;
+
+ for ( entryIt = dir->begin(); entryIt != dir->end(); ++entryIt )
+ for( atomIt = (*entryIt).begin(); atomIt != (*entryIt).end(); ++atomIt )
+ if( (*atomIt).m_uds == UDS_NAME )
+ if((*atomIt).m_str == name) {
+ for( atomIt = (*entryIt).begin(); atomIt != (*entryIt).end(); ++atomIt ) {
+ switch( (*atomIt).m_uds ) {
+ case UDS_MODIFICATION_TIME:
+ (*atomIt).m_long = time;
+ break;
+ case UDS_ACCESS:
+ (*atomIt).m_long = mode & 07777;
+ break;
+ }
+ }
+ return;
+ }
+ return; // there is alreay an entry for this directory
+ }
+ }
+
+ // multi volume archives can add a file twice, use only one
+ UDSEntryList::iterator dirEntryIt;
+ UDSEntry::iterator dirAtomIt;
+ for ( dirEntryIt = dir->begin(); dirEntryIt != dir->end(); ++dirEntryIt )
+ for( dirAtomIt = (*dirEntryIt).begin(); dirAtomIt != (*dirEntryIt).end(); ++dirAtomIt )
+ if( (*dirAtomIt).m_uds == UDS_NAME && (*dirAtomIt).m_str == name )
+ return;
+
+ dir->append(entry);
+}
+
+bool tdeio_krarcProtocol::initArcParameters() {
+ KRDEBUG("arcType: "<<arcType);
+
+ if(arcType == "zip"){
+ cmd = fullPathName( "unzip" );
+ listCmd = fullPathName( "unzip" ) + " -ZTs-z-t-h ";
+ getCmd = fullPathName( "unzip" ) + " -p ";
+ copyCmd = fullPathName( "unzip" ) + " -jo ";
+
+ if( TDEStandardDirs::findExe( "zip" ).isEmpty() ) {
+ delCmd = TQString();
+ putCmd = TQString();
+ } else {
+ delCmd = fullPathName( "zip" ) + " -d ";
+ putCmd = fullPathName( "zip" ) + " -ry ";
+ }
+
+ if( !getPassword().isEmpty() ) {
+ getCmd += "-P '"+password+"' ";
+ copyCmd += "-P '"+password+"' ";
+ putCmd += "-P '"+password+"' ";
+ }
+ } else if (arcType == "rar") {
+ if( TDEStandardDirs::findExe( "rar" ).isEmpty() ) {
+ cmd = fullPathName( "unrar" );
+ listCmd = fullPathName( "unrar" ) + " -c- -v v ";
+ getCmd = fullPathName( "unrar" ) + " p -ierr -idp -c- -y ";
+ copyCmd = fullPathName( "unrar" ) + " e -y ";
+ delCmd = TQString();
+ putCmd = TQString();
+ } else {
+ cmd = fullPathName( "rar" );
+ listCmd = fullPathName( "rar" ) + " -c- -v v ";
+ getCmd = fullPathName( "rar" ) + " p -ierr -idp -c- -y ";
+ copyCmd = fullPathName( "rar" ) + " e -y ";
+ delCmd = fullPathName( "rar" ) + " d ";
+ putCmd = fullPathName( "rar" ) + " -r a ";
+ }
+ if( !getPassword().isEmpty() ) {
+ getCmd += "-p'"+password+"' ";
+ listCmd += "-p'"+password+"' ";
+ copyCmd += "-p'"+password+"' ";
+ if( !putCmd.isEmpty() ) {
+ putCmd += "-p'"+password+"' ";
+ delCmd += "-p'"+password+"' ";
+ }
+ }
+ } else if(arcType == "rpm") {
+ cmd = fullPathName( "rpm" );
+ listCmd = fullPathName( "rpm" ) + " --dump -lpq ";
+ getCmd = fullPathName( "cpio" ) + " --force-local --no-absolute-filenames -iuvdF";
+ delCmd = TQString();
+ putCmd = TQString();
+ copyCmd = TQString();
+ } else if(arcType == "gzip") {
+ cmd = fullPathName( "gzip" );
+ listCmd = fullPathName( "gzip" ) + " -l";
+ getCmd = fullPathName( "gzip" ) + " -dc";
+ copyCmd = TQString();
+ delCmd = TQString();
+ putCmd = TQString();
+ } else if(arcType == "bzip2") {
+ cmd = fullPathName( "bzip2" );
+ listCmd = fullPathName( "bzip2" );
+ getCmd = fullPathName( "bzip2" ) + " -dc";
+ copyCmd = TQString();
+ delCmd = TQString();
+ putCmd = TQString();
+ } else if(arcType == "arj"){
+ cmd = fullPathName( "arj" );
+ listCmd = fullPathName( "arj" ) + " v -y -v ";
+ getCmd = fullPathName( "arj" ) + " -jyov -v e ";
+ copyCmd = fullPathName( "arj" ) + " -jyov -v e ";
+ delCmd = fullPathName( "arj" ) + " d ";
+ putCmd = fullPathName( "arj" ) + " -r a ";
+ if( !getPassword().isEmpty() ) {
+ getCmd += "-g'"+password+"' ";
+ copyCmd += "-g'"+password+"' ";
+ putCmd += "-g'"+password+"' ";
+ }
+ } else if(arcType == "lha") {
+ cmd = fullPathName( "lha" );
+ listCmd = fullPathName( "lha" ) + " l ";
+ getCmd = fullPathName( "lha" ) + " pq ";
+ copyCmd = fullPathName( "lha" ) + " eif ";
+ delCmd = fullPathName( "lha" ) + " d ";
+ putCmd = fullPathName( "lha" ) + " a ";
+ } else if(arcType == "ace") {
+ cmd = fullPathName( "unace" );
+ listCmd = fullPathName( "unace" ) + " v";
+ getCmd = fullPathName( "unace" ) + " e -o ";
+ copyCmd = fullPathName( "unace" ) + " e -o ";
+ delCmd = TQString();
+ putCmd = TQString();
+ if( !getPassword().isEmpty() ) {
+ getCmd += "-p'"+password+"' ";
+ copyCmd += "-p'"+password+"' ";
+ }
+ } else if ( arcType == "deb" ) {
+ cmd = fullPathName("dpkg");
+ listCmd = fullPathName("dpkg")+" -c";
+ getCmd = fullPathName("tar")+" xvf ";
+ copyCmd = TQString();
+ delCmd = TQString();
+ putCmd = TQString();
+ } else if (arcType == "7z") {
+ cmd = fullPathName( "7z" );
+ if( TDEStandardDirs::findExe(cmd).isEmpty() )
+ cmd = fullPathName( "7za" );
+
+ listCmd = cmd + " l -y ";
+ getCmd = cmd + " e -y ";
+ copyCmd = cmd + " e -y ";
+ delCmd = cmd + " d -y ";
+ putCmd = cmd + " a -y ";
+ if( !getPassword().isEmpty() ) {
+ getCmd += "-p'"+password+"' ";
+ listCmd += "-p'"+password+"' ";
+ copyCmd += "-p'"+password+"' ";
+ if( !putCmd.isEmpty() ) {
+ putCmd += "-p'"+password+"' ";
+ delCmd += "-p'"+password+"' ";
+ }
+ }
+ } else if (arcType == "xz") {
+ cmd = fullPathName("xz");
+ listCmd = fullPathName("xz");
+ getCmd = fullPathName("xz") + "-dc";
+ copyCmd = TQString();
+ delCmd = TQString();
+ putCmd = TQString();
+ } else {
+ cmd = TQString();
+ listCmd = TQString();
+ getCmd = TQString();
+ copyCmd = TQString();
+ delCmd = TQString();
+ putCmd = TQString();
+ }
+
+ if( TDEStandardDirs::findExe(cmd).isEmpty() ){
+ error( TDEIO::ERR_CANNOT_LAUNCH_PROCESS,
+ cmd+
+ i18n("\nMake sure that the %1 binary are installed properly on your system.").arg(cmd));
+ KRDEBUG("Failed to find cmd: " << cmd);
+ return false;
+ }
+ return true;
+}
+
+bool tdeio_krarcProtocol::checkStatus( int exitCode ) {
+ KRDEBUG( exitCode );
+
+ if( arcType == "zip" || arcType == "rar" || arcType == "7z" )
+ return exitCode == 0 || exitCode == 1;
+ else if( arcType == "ace" || arcType == "bzip2" || arcType == "lha" || arcType == "rpm" || arcType == "arj" )
+ return exitCode == 0;
+ else if( arcType == "gzip"|| arcType == "xz" )
+ return exitCode == 0 || exitCode == 2;
+ else
+ return exitCode == 0;
+}
+
+struct AutoDetectParams {
+ TQString type;
+ int location;
+ TQString detectionString;
+};
+
+TQString tdeio_krarcProtocol::detectArchive( bool &encrypted, TQString fileName ) {
+ 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" },
+ {"xz", 0, "\xfd" "7zXZ\x00"} };
+ static int autoDetectElems = sizeof( autoDetectParams ) / sizeof( AutoDetectParams );
+
+ encrypted = false;
+
+ TQFile 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++ ) {
+ TQString 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() ) {
+ TQString 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( encryptedArchPath == fileName )
+ encrypted = true;
+ else { // we try to find whether the 7z archive is encrypted
+ // this is hard as the headers are also compresseds
+ TQString tester = fullPathName( "7z" );
+ if( TDEStandardDirs::findExe( tester ).isEmpty() ) {
+ tester = fullPathName( "7za" );
+ if( TDEStandardDirs::findExe( tester ).isEmpty() ) {
+ return type;
+ }
+ }
+
+ TQString testCmd = tester + " t -y ";
+ lastData = encryptedArchPath = "";
+
+ KrShellProcess proc;
+ proc << testCmd << convertName( fileName );
+ connect( &proc, TQ_SIGNAL( receivedStdout(TDEProcess*,char*,int) ),
+ this, TQ_SLOT( checkOutputForPassword( TDEProcess*,char*,int ) ) );
+ proc.start(TDEProcess::Block,TDEProcess::AllOutput);
+ encrypted = this->encrypted;
+
+ if( encrypted )
+ encryptedArchPath = fileName;
+ }
+ }
+ 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";
+ }
+ }
+ }
+
+ if (fileName.endsWith(".tar.xz"))
+ {
+ return "txz";
+ }
+ else if (fileName.endsWith(".xz"))
+ {
+ return "xz";
+ }
+
+ return TQString();
+}
+
+void tdeio_krarcProtocol::checkOutputForPassword( TDEProcess *proc,char *buf,int len ) {
+ TQByteArray d(len);
+ d.setRawData(buf,len);
+ TQString data = TQString( d );
+ d.resetRawData(buf,len);
+
+ TQString checkable = lastData + data;
+
+ TQStringList lines = TQStringList::split( '\n', checkable );
+ lastData = lines[ lines.count() - 1 ];
+ for( unsigned i=0; i != lines.count(); i++ ) {
+ TQString 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" ) ) {
+ KRDEBUG( "Encrypted 7z archive found!" );
+ encrypted = true;
+ proc->kill();
+ }
+ }
+}
+
+void tdeio_krarcProtocol::invalidatePassword() {
+ KRDEBUG( arcFile->url().path(-1) + "/" );
+
+ if( !encrypted )
+ return;
+
+ TDEIO::AuthInfo authInfo;
+ authInfo.caption= i18n( "Krarc Password Dialog" );
+ authInfo.username= "archive";
+ authInfo.readOnly = true;
+ authInfo.keepPassword = true;
+ authInfo.verifyPath = true;
+ TQString fileName = arcFile->url().path(-1);
+ authInfo.url = KURL::fromPathOrURL( "/" );
+ authInfo.url.setHost( fileName /*.replace('/','_')*/ );
+ authInfo.url.setProtocol( "krarc" );
+
+ password = TQString();
+
+ cacheAuthentication( authInfo );
+}
+
+TQString tdeio_krarcProtocol::getPassword() {
+ KRDEBUG( encrypted );
+
+ if( !password.isNull() )
+ return password;
+ if( !encrypted )
+ return (password = "" );
+
+ TDEIO::AuthInfo authInfo;
+ authInfo.caption= i18n( "Krarc Password Dialog" );
+ authInfo.username= "archive";
+ authInfo.readOnly = true;
+ authInfo.keepPassword = true;
+ authInfo.verifyPath = true;
+ TQString fileName = arcFile->url().path(-1);
+ authInfo.url = KURL::fromPathOrURL( "/" );
+ authInfo.url.setHost( fileName /*.replace('/','_')*/ );
+ authInfo.url.setProtocol( "krarc" );
+
+ if( checkCachedAuthentication( authInfo ) && !authInfo.password.isNull() ) {
+ KRDEBUG( authInfo.password );
+ return ( password = authInfo.password );
+ }
+
+ authInfo.password = TQString();
+
+ if ( openPassDlg( authInfo, i18n("Accessing the file requires password.") ) && !authInfo.password.isNull() ) {
+ KRDEBUG( authInfo.password );
+ return ( password = authInfo.password );
+ }
+
+ KRDEBUG( password );
+ return password;
+}
+
+TQString tdeio_krarcProtocol::fullPathName( TQString name ) {
+ TQString supposedName = krConfig->readEntry( name, name );
+ if( supposedName.isEmpty() )
+ supposedName = name;
+ return escape( supposedName );
+}
+
+TQString tdeio_krarcProtocol::convertFileName( TQString name ) {
+ if( arcType == "zip" )
+ name = name.replace( "[", "[[]" );
+ return convertName( name );
+}
+
+TQString tdeio_krarcProtocol::convertName( TQString name ) {
+ if( !name.contains( '\'' ) )
+ return "'" + name + "'";
+ if( !name.contains( '"' ) && !name.contains( '$' ) )
+ return "\"" + name + "\"";
+ return escape( name );
+}
+
+TQString tdeio_krarcProtocol::escape( TQString name ) {
+ const TQString evilstuff = "\\\"'`()[]{}!?;$&<>| "; // stuff that should get escaped
+
+ for ( unsigned int i = 0; i < evilstuff.length(); ++i )
+ name.replace( evilstuff[ i ], (TQString("\\") + evilstuff[ i ]) );
+
+ return name;
+}
+
+#include "krarc.moc"
diff --git a/src/krArc/krarc.h b/src/krArc/krarc.h
new file mode 100644
index 0000000..6b9ca6c
--- /dev/null
+++ b/src/krArc/krarc.h
@@ -0,0 +1,144 @@
+/***************************************************************************
+ krarc.h
+ -------------------
+ begin : Sat Jun 14 14:42:49 IDT 2003
+ copyright : (C) 2003 by Rafi Yanai & Shie Erlich
+ email : yanai@users.sf.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 __krarc_h__
+#define __krarc_h__
+
+#include <tqstring.h>
+#include <tqcstring.h>
+#include <tqdict.h>
+#include <tqfile.h>
+#include <sys/types.h>
+
+#include <kurl.h>
+#include <tdeio/global.h>
+#include <tdeio/slavebase.h>
+#include <kprocess.h>
+
+class TDEProcess;
+class KFileItem;
+class TQCString;
+
+class tdeio_krarcProtocol : public TQObject, public TDEIO::SlaveBase {
+TQ_OBJECT
+
+public:
+ tdeio_krarcProtocol(const TQCString &pool_socket, const TQCString &app_socket);
+ virtual ~tdeio_krarcProtocol();
+ virtual void stat( const KURL & url );
+ virtual void get(const KURL& url);
+ virtual void put(const KURL& url,int permissions,bool overwrite,bool resume);
+ virtual void mkdir(const KURL& url,int permissions);
+ virtual void listDir(const KURL& url);
+ virtual void del(KURL const & url, bool isFile);
+ virtual void copy (const KURL &src, const KURL &dest, int permissions, bool overwrite);
+
+public slots:
+ void receivedData(TDEProcess* proc,char* buf,int len);
+ void checkOutputForPassword( TDEProcess*,char*,int );
+
+protected:
+ virtual bool initDirDict(const KURL& url,bool forced = false);
+ virtual bool initArcParameters();
+ TQString detectArchive( bool &encrypted, TQString fileName );
+ virtual void parseLine(int lineNo, TQString line, TQFile* temp);
+ virtual bool setArcFile(const KURL& url);
+ virtual TQString getPassword();
+ virtual void invalidatePassword();
+
+ // archive specific commands
+ TQString cmd; ///< the archiver name.
+ TQString listCmd; ///< list files.
+ TQString getCmd; ///< unpack files command.
+ TQString delCmd; ///< delete files command.
+ TQString putCmd; ///< add file command.
+ TQString copyCmd; ///< copy to file command.
+
+private:
+ void get(const KURL& url, int tries);
+ /** checks if the exit code is OK. */
+ bool checkStatus( int exitCode );
+ /** service function for parseLine. */
+ TQString nextWord(TQString &s,char d=' ');
+ /** translate permittion string to mode_t. */
+ mode_t parsePermString(TQString perm);
+ /** return the name of the directory inside the archive. */
+ TQString findArcDirectory(const KURL& url);
+ /** find the UDSEntry of a file in a directory. */
+ TDEIO::UDSEntry* findFileEntry(const KURL& url);
+ /** add a new directory (file list container). */
+ TDEIO::UDSEntryList* addNewDir(TQString path);
+ TQString fullPathName( TQString name );
+ TQString convertFileName( TQString name );
+ static TQString convertName( TQString name );
+ static TQString escape( TQString name );
+
+ TQDict<TDEIO::UDSEntryList> dirDict; //< the directoris data structure.
+ bool encrypted; //< tells whether the archive is encrypted
+ bool archiveChanged; //< true if the archive was changed.
+ bool archiveChanging; //< true if the archive is currently changing.
+ bool newArchiveURL; //< true if new archive was entered for the protocol
+ TDEIO::filesize_t decompressedLen; //< the number of the decompressed bytes
+ KFileItem* arcFile; //< the archive file item.
+ TQString arcPath; //< the archive location
+ TQString arcTempDir; //< the currently used temp directory.
+ TQString arcType; //< the archive type.
+ bool extArcReady; //< Used for RPM & DEB files.
+ TQString password; //< Password for the archives
+ TDEConfig *krConfig; //< The configuration file for krusader
+
+ TQString lastData;
+ TQString encryptedArchPath;
+};
+
+class KrShellProcess : public KShellProcess {
+ TQ_OBJECT
+
+public:
+ KrShellProcess() : KShellProcess(), errorMsg( TQString() ), outputMsg( TQString() ) {
+ connect(this,TQ_SIGNAL(receivedStderr(TDEProcess*,char*,int)),
+ this,TQ_SLOT(receivedErrorMsg(TDEProcess*,char*,int)) );
+ connect(this,TQ_SIGNAL(receivedStdout(TDEProcess*,char*,int)),
+ this,TQ_SLOT(receivedOutputMsg(TDEProcess*,char*,int)) );
+ }
+
+ TQString getErrorMsg() {
+ if( errorMsg.stripWhiteSpace().isEmpty() )
+ return outputMsg.right( 500 );
+ else
+ return errorMsg.right( 500 );
+ }
+
+public slots:
+ void receivedErrorMsg(TDEProcess*, char *buf, int len) {
+ errorMsg += TQString::fromLocal8Bit( buf, len );
+ if( errorMsg.length() > 500 )
+ errorMsg = errorMsg.right( 500 );
+ receivedOutputMsg( 0, buf, len );
+ }
+
+ void receivedOutputMsg(TDEProcess*, char *buf, int len) {
+ outputMsg += TQString::fromLocal8Bit( buf, len );
+ if( outputMsg.length() > 500 )
+ outputMsg = outputMsg.right( 500 );
+ }
+
+private:
+ TQString errorMsg;
+ TQString outputMsg;
+};
+
+#endif
diff --git a/src/krArc/krarc.protocol b/src/krArc/krarc.protocol
new file mode 100644
index 0000000..ba363be
--- /dev/null
+++ b/src/krArc/krarc.protocol
@@ -0,0 +1,18 @@
+[Protocol]
+exec=tdeio_krarc
+protocol=krarc
+mimetype=application/x-archive
+input=filesystem
+output=filesystem
+listing=Name,Type,Size,Date,Access,Owner,Group,Link
+reading=true
+writing=true
+makedir=true
+deleting=true
+source=true
+linking=false
+moving=false
+copyToFile=true
+Icon=ark
+Description=Mutiple archive handler that currently supports: zip,rar.
+X-DocPath=tdeioslave/krarc/index.html
diff --git a/src/tar/Makefile.am b/src/tar/Makefile.am
new file mode 100644
index 0000000..d14e41e
--- /dev/null
+++ b/src/tar/Makefile.am
@@ -0,0 +1,22 @@
+## Makefile.am of tdebase/tdeioslave/tar
+
+INCLUDES = $(all_includes)
+AM_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TQT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = tdeio_tar.la
+
+tdeio_tar_la_SOURCES = tar.cpp
+tdeio_tar_la_LIBADD = $(LIB_TDESYCOCA)
+tdeio_tar_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+
+check_PROGRAMS = ktartest
+
+ktartest_SOURCES = ktartest.cpp
+ktartest_LDADD = $(LIB_TDESYCOCA)
+
+noinst_HEADERS = tar.h
+
+kdelnk_DATA = tar.protocol ar.protocol zip.protocol
+kdelnkdir = $(kde_servicesdir)
+
diff --git a/src/tar/ar.protocol b/src/tar/ar.protocol
new file mode 100644
index 0000000..f274f0b
--- /dev/null
+++ b/src/tar/ar.protocol
@@ -0,0 +1,12 @@
+[Protocol]
+exec=tdeio_tar
+protocol=ar
+mimetype=application/x-archive
+input=filesystem
+output=filesystem
+listing=Name,Type,Size,Date,Access,Owner,Group,Link
+reading=true
+source=true
+X-DocPath=tdeioslave/ar/index.html
+Icon=ar
+Class=:local
diff --git a/src/tar/ktartest.cpp b/src/tar/ktartest.cpp
new file mode 100644
index 0000000..2fe00d3
--- /dev/null
+++ b/src/tar/ktartest.cpp
@@ -0,0 +1,201 @@
+#include "ktar.h"
+#include <stdio.h>
+#include <tqfile.h>
+#include <tdeinstance.h>
+#include <kdebug.h>
+
+void recursive_print( const KTarDirectory * dir, const TQString & path )
+{
+ TQStringList l = dir->entries();
+ TQStringList::Iterator it = l.begin();
+ for( ; it != l.end(); ++it )
+ {
+ const KTarEntry* entry = dir->entry( (*it) );
+ printf("mode=%07o %s %s %s%s\n", entry->permissions(), entry->user().latin1(), entry->group().latin1(), path.latin1(), (*it).latin1());
+ if (entry->isDirectory())
+ recursive_print( (KTarDirectory *)entry, path+(*it)+"/" );
+ }
+}
+
+static void usage()
+{
+ printf("\n"
+ " Usage :\n"
+ " ./ktartest list /path/to/existing_file.tar.gz tests listing an existing tar.gz\n"
+ " ./ktartest get /path/to/existing_file.tar.gz filename tests extracting a file.\n"
+ " ./ktartest readwrite newfile.tar.gz will create the tar.gz, then close and reopen it.\n"
+ " ./ktartest maxlength newfile.tar.gz tests the maximum filename length allowed.\n"
+ " ./ktartest bytearray /path/to/existing_file.tar.gz tests KTarData\n");
+}
+
+int main( int argc, char** argv )
+{
+ if (argc < 3)
+ {
+ usage();
+ return 1;
+ }
+ TDEInstance instance("ktartest");
+
+ TQString command = argv[1];
+ kdDebug() << "main: command=" << command << endl;
+ if ( command == "list" )
+ {
+ KTarGz tar( argv[2] );
+
+ if ( !tar.open( IO_ReadOnly ) )
+ {
+ printf("Could not open %s for reading\n", argv[1] );
+ return 1;
+ }
+
+ const KTarDirectory* dir = tar.directory();
+
+ //printf("calling recursive_print\n");
+ recursive_print( dir, "" );
+ //printf("recursive_print called\n");
+
+ tar.close();
+
+ return 0;
+ }
+ else if ( command == "get" )
+ {
+ if ( argc != 4 )
+ {
+ usage();
+ return 1;
+ }
+
+ KTarGz tar( argv[2] );
+
+ if ( !tar.open( IO_ReadOnly ) )
+ {
+ printf("Could not open %s for reading\n", argv[1] );
+ return 1;
+ }
+
+ const KTarDirectory* dir = tar.directory();
+
+ const KTarEntry* e = dir->entry( argv[3] );
+ Q_ASSERT( e && e->isFile() );
+ const KTarFile* f = (KTarFile*)e;
+
+ TQByteArray arr( f->data() );
+ printf("SIZE=%i\n",arr.size() );
+ TQString str( arr );
+ printf("DATA=%s\n", str.latin1());
+
+ /*
+ // This is what KGzipDev::readAll could do, if TQIODevice::readAll was virtual....
+ TQByteArray array(1024);
+ int n;
+ while ( ( n = dev.readBlock( array.data(), array.size() ) ) )
+ {
+ kdDebug() << "readBlock returned " << n << endl << endl;
+ TQCString s(array,n+1); // Terminate with 0 before printing
+ printf("%s", s.data());
+ }
+ dev.close();
+ */
+
+
+ tar.close();
+ }
+ else if (command == "readwrite" )
+ {
+ kdDebug() << " --- readwrite --- " << endl;
+ KTarGz tar( argv[2] );
+
+ if ( !tar.open( IO_WriteOnly ) )
+ {
+ printf("Could not open %s for writing\n", argv[1]);
+ return 1;
+ }
+
+ tar.writeFile( "empty", "weis", "users", 0, "" );
+ tar.writeFile( "test1", "weis", "users", 5, "Hallo" );
+ tar.writeFile( "test2", "weis", "users", 8, "Hallo Du" );
+ tar.writeFile( "mydir/test3", "weis", "users", 13, "Noch so einer" );
+ tar.writeFile( "my/dir/test3", "dfaure", "hackers", 29, "I don't speak German (David)" );
+
+#define SIZE1 100
+ // Now a medium file : 100 null bytes
+ char medium[ SIZE1 ];
+ memset( medium, 0, SIZE1 );
+ tar.writeFile( "mediumfile", "user", "group", SIZE1, medium );
+ // Another one, with an absolute path
+ tar.writeFile( "/dir/subdir/mediumfile2", "user", "group", SIZE1, medium );
+
+ // Now a huge file : 20000 null bytes
+ int n = 20000;
+ char * huge = new char[ n ];
+ memset( huge, 0, n );
+ tar.writeFile( "hugefile", "user", "group", n, huge );
+ delete [] huge;
+
+ tar.close();
+
+ printf("-----------------------\n");
+
+ if ( !tar.open( IO_ReadOnly ) )
+ {
+ printf("Could not open %s for reading\n", argv[1] );
+ return 1;
+ }
+
+ const KTarDirectory* dir = tar.directory();
+ recursive_print(dir, "");
+
+ const KTarEntry* e = dir->entry( "mydir/test3" );
+ Q_ASSERT( e && e->isFile() );
+ const KTarFile* f = (KTarFile*)e;
+
+ TQByteArray arr( f->data() );
+ printf("SIZE=%i\n",arr.size() );
+ TQString str( arr );
+ printf("DATA=%s\n", str.latin1());
+
+ tar.close();
+
+ return 0;
+ }
+ else if ( command == "maxlength" )
+ {
+ KTarGz tar( argv[2] );
+
+ if ( !tar.open( IO_WriteOnly ) )
+ {
+ printf("Could not open %s for writing\n", argv[1]);
+ return 1;
+ }
+ // Generate long filenames of each possible length bigger than 98...
+ for (int i = 98; i < 500 ; i++ )
+ {
+ TQString str, num;
+ str.fill( 'a', i-10 );
+ num.setNum( i );
+ num = num.rightJustify( 10, '0' );
+ tar.writeFile( str+num, "testu", "testg", 3, "hum" );
+ }
+ // Result of this test : it fails at 482 (instead of 154 previously).
+ // Ok, I think we can do with that :)
+ tar.close();
+ printf("Now run 'tar tvzf %s'\n", argv[2]);
+ return 0;
+ }
+ else if ( command == "bytearray" )
+ {
+ TQFile file( argv[2] );
+ if ( !file.open( IO_ReadOnly ) )
+ return 1;
+ KTarGz tar( &file );
+ tar.open( IO_ReadOnly );
+ const KTarDirectory* dir = tar.directory();
+ recursive_print( dir, "" );
+ return 0;
+ }
+ else
+ printf("Unknown command\n");
+}
+
diff --git a/src/tar/tar.cpp b/src/tar/tar.cpp
new file mode 100644
index 0000000..33acab2
--- /dev/null
+++ b/src/tar/tar.cpp
@@ -0,0 +1,482 @@
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <tqfile.h>
+#include <tqfileinfo.h>
+#include <tqptrqueue.h>
+#include <kurl.h>
+#include <kdebug.h>
+#include <tdeinstance.h>
+#include <ktar.h>
+#include <kzip.h>
+#include <kar.h>
+#include <kmimemagic.h>
+#include <tdelocale.h>
+#include <tdeversion.h>
+
+#include <errno.h> // to be removed
+
+#include "tar.h"
+
+using namespace TDEIO;
+
+#if KDE_IS_VERSION(3,4,0)
+extern "C" { int TDE_EXPORT kdemain( int argc, char **argv ); }
+#else
+extern "C" { int kdemain( int argc, char **argv ); }
+#endif
+
+int kdemain( int argc, char **argv ) {
+ TDEInstance instance( "tdeio_tar" );
+
+ kdDebug( 7109 ) << "Starting " << getpid() << endl;
+
+ if ( argc != 4 ) {
+ fprintf( stderr, "Usage: tdeio_tar protocol domain-socket1 domain-socket2\n" );
+ exit( -1 );
+ }
+
+ ArchiveProtocol slave( argv[ 2 ], argv[ 3 ] );
+ slave.dispatchLoop();
+
+ kdDebug( 7109 ) << "Done" << endl;
+ return 0;
+}
+
+ArchiveProtocol::ArchiveProtocol( const TQCString &pool, const TQCString &app ) : SlaveBase( "tar", pool, app ) {
+ kdDebug( 7109 ) << "ArchiveProtocol::ArchiveProtocol" << endl;
+ m_archiveFile = 0L;
+}
+
+ArchiveProtocol::~ArchiveProtocol() {
+ delete m_archiveFile;
+}
+
+void ArchiveProtocol::put( const KURL& url, int, bool, bool resume ){
+ if( resume ){
+ error(ERR_UNSUPPORTED_ACTION,i18n("This protocol does not support resuming") );
+ return;
+ }
+
+ TQByteArray tempBuffer;
+ TQPtrQueue<TQByteArray> buffer;
+ buffer.setAutoDelete(true);
+ int readResult=0;
+ int size = 0;
+ TQByteArray* temp;
+ do{
+ dataReq();
+ temp = new TQByteArray();
+ readResult = readData(*temp);
+ buffer.enqueue(temp);
+ size += temp->size();
+ } while( readResult > 0 );
+
+ TQString filename = url.path().mid(m_archiveName.length()+1);
+
+ if( !m_archiveFile->prepareWriting(filename,user,group,size) ){
+ error(ERR_UNSUPPORTED_ACTION,
+ i18n("Writing to %1 is not supported").arg(filename) );
+ return;
+ }
+ while( (temp=buffer.dequeue()) ){
+ m_archiveFile->writeData(temp->data(),temp->size());
+ }
+ m_archiveFile->doneWriting(size);
+
+ finished();
+}
+
+void ArchiveProtocol::mkdir(const KURL& url,int){
+ TQString filename = url.path().mid(m_archiveName.length()+1);
+ m_archiveFile->writeDir(filename,user,group);
+ finished();
+}
+
+bool ArchiveProtocol::checkNewFile( const KURL & url, TQString & path ) {
+ TQString fullPath = url.path();
+ kdDebug( 7109 ) << "ArchiveProtocol::checkNewFile " << fullPath << endl;
+
+
+ // Are we already looking at that file ?
+ if ( m_archiveFile && m_archiveName == fullPath.left( m_archiveName.length() ) ) {
+ // Has it changed ?
+ struct stat statbuf;
+ if ( ::stat( TQFile::encodeName( m_archiveName ), &statbuf ) == 0 ) {
+ if ( m_mtime == statbuf.st_mtime ) {
+ path = fullPath.mid( m_archiveName.length() );
+ kdDebug( 7109 ) << "ArchiveProtocol::checkNewFile returning " << path << endl;
+ return true;
+ }
+ }
+ }
+ kdDebug( 7109 ) << "Need to open a new file" << endl;
+
+ // Close previous file
+ if ( m_archiveFile ) {
+ m_archiveFile->close();
+ delete m_archiveFile;
+ m_archiveFile = 0L;
+ }
+
+ // Find where the tar file is in the full path
+ int pos = 0;
+ TQString archiveFile;
+ path = TQString();
+
+ int len = fullPath.length();
+ if ( len != 0 && fullPath[ len - 1 ] != '/' )
+ fullPath += '/';
+
+ kdDebug( 7109 ) << "the full path is " << fullPath << endl;
+ while ( ( pos = fullPath.find( '/', pos + 1 ) ) != -1 ) {
+ TQString tryPath = fullPath.left( pos );
+ kdDebug( 7109 ) << fullPath << " trying " << tryPath << endl;
+ struct stat statbuf;
+ if ( ::stat( TQFile::encodeName( tryPath ), &statbuf ) == 0 && !S_ISDIR( statbuf.st_mode ) ) {
+ archiveFile = tryPath;
+ m_mtime = statbuf.st_mtime;
+ user = TQFileInfo(archiveFile).owner();
+ group = TQFileInfo(archiveFile).group();
+ path = fullPath.mid( pos + 1 );
+ kdDebug( 7109 ) << "fullPath=" << fullPath << " path=" << path << endl;
+ len = path.length();
+ if ( len > 1 ) {
+ if ( path[ len - 1 ] == '/' )
+ path.truncate( len - 1 );
+ } else
+ path = TQString::fromLatin1( "/" );
+ kdDebug( 7109 ) << "Found. archiveFile=" << archiveFile << " path=" << path << endl;
+ break;
+ }
+ }
+ if ( archiveFile.isEmpty() ) {
+ kdDebug( 7109 ) << "ArchiveProtocol::checkNewFile: not found" << endl;
+ return false;
+ }
+
+ // Open new file
+ if ( url.protocol() == "tar" ) {
+ kdDebug( 7109 ) << "Opening KTar on " << archiveFile << endl;
+ m_archiveFile = new KTar( archiveFile );
+ } else if ( url.protocol() == "ar" ) {
+ kdDebug( 7109 ) << "Opening KAr on " << archiveFile << endl;
+ m_archiveFile = new KAr( archiveFile );
+ } else if ( url.protocol() == "zip" ) {
+ kdDebug( 7109 ) << "Opening KZip on " << archiveFile << endl;
+ m_archiveFile = new KZip( archiveFile );
+ } else {
+ kdWarning( 7109 ) << "Protocol " << url.protocol() << " not supported by this IOSlave" << endl;
+ return false;
+ }
+
+ if ( !m_archiveFile->open( IO_ReadWrite ) ) {
+ kdDebug( 7109 ) << "Opening " << archiveFile << "failed." << endl;
+ delete m_archiveFile;
+ m_archiveFile = 0L;
+ return false;
+ }
+
+ m_archiveName = archiveFile;
+ return true;
+}
+
+
+void ArchiveProtocol::createUDSEntry( const KArchiveEntry * archiveEntry, UDSEntry & entry ) {
+ UDSAtom atom;
+ entry.clear();
+ atom.m_uds = UDS_NAME;
+ atom.m_str = archiveEntry->name();
+ entry.append( atom );
+
+ atom.m_uds = UDS_FILE_TYPE;
+ atom.m_long = archiveEntry->permissions() & S_IFMT; // keep file type only
+ entry.append( atom );
+
+ atom.m_uds = UDS_SIZE;
+ atom.m_long = archiveEntry->isFile() ? ( ( KArchiveFile * ) archiveEntry ) ->size() : 0L ;
+ entry.append( atom );
+
+ atom.m_uds = UDS_MODIFICATION_TIME;
+ atom.m_long = archiveEntry->date();
+ entry.append( atom );
+
+ atom.m_uds = UDS_ACCESS;
+ atom.m_long = archiveEntry->permissions() & 07777; // keep permissions only
+ entry.append( atom );
+
+ atom.m_uds = UDS_USER;
+ atom.m_str = archiveEntry->user();
+ entry.append( atom );
+
+ atom.m_uds = UDS_GROUP;
+ atom.m_str = archiveEntry->group();
+ entry.append( atom );
+
+ atom.m_uds = UDS_LINK_DEST;
+ atom.m_str = archiveEntry->symlink();
+ entry.append( atom );
+}
+
+void ArchiveProtocol::listDir( const KURL & url ) {
+ kdDebug( 7109 ) << "ArchiveProtocol::listDir " << url.url() << endl;
+
+ TQString path;
+ if ( !checkNewFile( url, path ) ) {
+ TQCString _path( TQFile::encodeName( url.path() ) );
+ kdDebug( 7109 ) << "Checking (stat) on " << _path << endl;
+ struct stat buff;
+ if ( ::stat( _path.data(), &buff ) == -1 || !S_ISDIR( buff.st_mode ) ) {
+ error( TDEIO::ERR_DOES_NOT_EXIST, url.prettyURL() );
+ return ;
+ }
+ // It's a real dir -> redirect
+ KURL redir;
+ redir.setPath( url.path() );
+ kdDebug( 7109 ) << "Ok, redirection to " << redir.url() << endl;
+ redirection( redir );
+ finished();
+ // And let go of the tar file - for people who want to unmount a cdrom after that
+ delete m_archiveFile;
+ m_archiveFile = 0L;
+ return ;
+ }
+
+ if ( path.isEmpty() ) {
+ KURL redir( url.protocol() + TQString::fromLatin1( ":/" ) );
+ kdDebug( 7109 ) << "url.path()==" << url.path() << endl;
+ redir.setPath( url.path() + TQString::fromLatin1( "/" ) );
+ kdDebug( 7109 ) << "ArchiveProtocol::listDir: redirection " << redir.url() << endl;
+ redirection( redir );
+ finished();
+ return ;
+ }
+
+ kdDebug( 7109 ) << "checkNewFile done" << endl;
+ const KArchiveDirectory* root = m_archiveFile->directory();
+ const KArchiveDirectory* dir;
+ if ( !path.isEmpty() && path != "/" ) {
+ kdDebug( 7109 ) << TQString( "Looking for entry %1" ).arg( path ) << endl;
+ const KArchiveEntry* e = root->entry( path );
+ if ( !e ) {
+ error( TDEIO::ERR_DOES_NOT_EXIST, url.prettyURL() );
+ return ;
+ }
+ if ( ! e->isDirectory() ) {
+ error( TDEIO::ERR_IS_FILE, url.prettyURL() );
+ return ;
+ }
+ dir = ( KArchiveDirectory* ) e;
+ } else {
+ dir = root;
+ }
+
+ TQStringList l = dir->entries();
+ totalSize( l.count() );
+
+ UDSEntry entry;
+ TQStringList::Iterator it = l.begin();
+ for ( ; it != l.end(); ++it ) {
+ kdDebug( 7109 ) << ( *it ) << endl;
+ const KArchiveEntry* archiveEntry = dir->entry( ( *it ) );
+
+ createUDSEntry( archiveEntry, entry );
+
+ listEntry( entry, false );
+ }
+
+ listEntry( entry, true ); // ready
+
+ finished();
+
+ kdDebug( 7109 ) << "ArchiveProtocol::listDir done" << endl;
+}
+
+void ArchiveProtocol::stat( const KURL & url ) {
+ TQString path;
+ UDSEntry entry;
+ if ( !checkNewFile( url, path ) ) {
+ // We may be looking at a real directory - this happens
+ // when pressing up after being in the root of an archive
+ TQCString _path( TQFile::encodeName( url.path() ) );
+ kdDebug( 7109 ) << "ArchiveProtocol::stat (stat) on " << _path << endl;
+ struct stat buff;
+ if ( ::stat( _path.data(), &buff ) == -1 || !S_ISDIR( buff.st_mode ) ) {
+ kdDebug( 7109 ) << "isdir=" << S_ISDIR( buff.st_mode ) << " errno=" << strerror( errno ) << endl;
+ error( TDEIO::ERR_DOES_NOT_EXIST, url.path() );
+ return ;
+ }
+ // Real directory. Return just enough information for KRun to work
+ UDSAtom atom;
+ atom.m_uds = TDEIO::UDS_NAME;
+ atom.m_str = url.fileName();
+ entry.append( atom );
+ kdDebug( 7109 ) << "ArchiveProtocol::stat returning name=" << url.fileName() << endl;
+
+ atom.m_uds = TDEIO::UDS_FILE_TYPE;
+ atom.m_long = buff.st_mode & S_IFMT;
+ entry.append( atom );
+
+ statEntry( entry );
+
+ finished();
+
+ // And let go of the tar file - for people who want to unmount a cdrom after that
+ delete m_archiveFile;
+ m_archiveFile = 0L;
+ return ;
+ }
+
+ const KArchiveDirectory* root = m_archiveFile->directory();
+ const KArchiveEntry* archiveEntry;
+ if ( path.isEmpty() ) {
+ path = TQString::fromLatin1( "/" );
+ archiveEntry = root;
+ } else {
+ archiveEntry = root->entry( path );
+ }
+ if ( !archiveEntry ) {
+ error( TDEIO::ERR_DOES_NOT_EXIST, url.prettyURL() );
+ return ;
+ }
+
+ createUDSEntry( archiveEntry, entry );
+ statEntry( entry );
+
+ finished();
+}
+
+void ArchiveProtocol::get( const KURL & url ) {
+ kdDebug( 7109 ) << "ArchiveProtocol::get" << url.url() << endl;
+
+ TQString path;
+ if ( !checkNewFile( url, path ) ) {
+ error( TDEIO::ERR_DOES_NOT_EXIST, url.prettyURL() );
+ return ;
+ }
+
+ const KArchiveDirectory* root = m_archiveFile->directory();
+ const KArchiveEntry* archiveEntry = root->entry( path );
+
+ if ( !archiveEntry ) {
+ error( TDEIO::ERR_DOES_NOT_EXIST, url.prettyURL() );
+ return ;
+ }
+ if ( archiveEntry->isDirectory() ) {
+ error( TDEIO::ERR_IS_DIRECTORY, url.prettyURL() );
+ return ;
+ }
+ const KArchiveFile* archiveFileEntry = static_cast<const KArchiveFile *>( archiveEntry );
+ if ( !archiveEntry->symlink().isEmpty() ) {
+ kdDebug( 7109 ) << "Redirection to " << archiveEntry->symlink() << endl;
+ KURL realURL( url, archiveEntry->symlink() );
+ kdDebug( 7109 ) << "realURL= " << realURL.url() << endl;
+ redirection( realURL );
+ finished();
+ return ;
+ }
+
+ totalSize( archiveFileEntry->size() );
+
+ TQByteArray completeData = archiveFileEntry->data();
+
+ KMimeMagicResult * result = KMimeMagic::self() ->findBufferFileType( completeData, path );
+ kdDebug( 7109 ) << "Emitting mimetype " << result->mimeType() << endl;
+ mimeType( result->mimeType() );
+
+ data( completeData );
+
+ processedSize( archiveFileEntry->size() );
+ data( TQByteArray() );
+
+ finished();
+}
+
+/*
+ In case someone wonders how the old filter stuff looked like : :)
+void TARProtocol::slotData(void *_p, int _len)
+{
+ switch (m_cmd) {
+ case CMD_PUT:
+ assert(m_pFilter);
+ m_pFilter->send(_p, _len);
+ break;
+ default:
+ abort();
+ break;
+ }
+}
+
+void TARProtocol::slotDataEnd()
+{
+ switch (m_cmd) {
+ case CMD_PUT:
+ assert(m_pFilter && m_pJob);
+ m_pFilter->finish();
+ m_pJob->dataEnd();
+ m_cmd = CMD_NONE;
+ break;
+ default:
+ abort();
+ break;
+ }
+}
+
+void TARProtocol::jobData(void *_p, int _len)
+{
+ switch (m_cmd) {
+ case CMD_GET:
+ assert(m_pFilter);
+ m_pFilter->send(_p, _len);
+ break;
+ case CMD_COPY:
+ assert(m_pFilter);
+ m_pFilter->send(_p, _len);
+ break;
+ default:
+ abort();
+ }
+}
+
+void TARProtocol::jobDataEnd()
+{
+ switch (m_cmd) {
+ case CMD_GET:
+ assert(m_pFilter);
+ m_pFilter->finish();
+ dataEnd();
+ break;
+ case CMD_COPY:
+ assert(m_pFilter);
+ m_pFilter->finish();
+ m_pJob->dataEnd();
+ break;
+ default:
+ abort();
+ }
+}
+
+void TARProtocol::filterData(void *_p, int _len)
+{
+debug("void TARProtocol::filterData");
+ switch (m_cmd) {
+ case CMD_GET:
+ data(_p, _len);
+ break;
+ case CMD_PUT:
+ assert (m_pJob);
+ m_pJob->data(_p, _len);
+ break;
+ case CMD_COPY:
+ assert(m_pJob);
+ m_pJob->data(_p, _len);
+ break;
+ default:
+ abort();
+ }
+}
+*/
+
diff --git a/src/tar/tar.h b/src/tar/tar.h
new file mode 100644
index 0000000..ca229d2
--- /dev/null
+++ b/src/tar/tar.h
@@ -0,0 +1,48 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ 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 _TAR_H
+#define _TAR_H
+
+#include <tdeio/slavebase.h>
+#include <sys/types.h>
+
+class ArchiveProtocol : public TDEIO::SlaveBase {
+public:
+ ArchiveProtocol( const TQCString &pool, const TQCString &app );
+ virtual ~ArchiveProtocol();
+
+ virtual void listDir( const KURL & url );
+ virtual void stat( const KURL & url );
+ virtual void get( const KURL & url );
+ virtual void put( const KURL& url, int permissions, bool overwrite, bool resume );
+ virtual void mkdir(const KURL& url,int permissions);
+
+protected:
+ void createUDSEntry( const KArchiveEntry * tarEntry, TDEIO::UDSEntry & entry );
+ bool checkNewFile( const KURL & url, TQString & path );
+
+ KArchive * m_archiveFile;
+ TQString m_archiveName;
+ TQString user;
+ TQString group;
+ time_t m_mtime;
+};
+
+#endif
diff --git a/src/tar/tar.protocol b/src/tar/tar.protocol
new file mode 100644
index 0000000..a72791e
--- /dev/null
+++ b/src/tar/tar.protocol
@@ -0,0 +1,12 @@
+[Protocol]
+exec=tdeio_tar
+protocol=tar
+mimetype=application/x-tar
+input=filesystem
+output=filesystem
+listing=Name,Type,Size,Date,Access,Owner,Group,Link
+reading=true
+source=true
+X-DocPath=tdeioslave/tar/index.html
+Icon=application-x-tar
+Class=:local
diff --git a/src/tar/zip.protocol b/src/tar/zip.protocol
new file mode 100644
index 0000000..e796e39
--- /dev/null
+++ b/src/tar/zip.protocol
@@ -0,0 +1,12 @@
+[Protocol]
+exec=tdeio_tar
+protocol=zip
+mimetype=application/x-zip
+input=filesystem
+output=filesystem
+listing=Name,Type,Size,Date,Access,Owner,Group,Link
+reading=true
+source=true
+X-DocPath=tdeioslave/zip/index.html
+Icon=application-vnd.tde.overlay.zip
+Class=:local
diff --git a/src/tdeconf_update/Makefile.am b/src/tdeconf_update/Makefile.am
new file mode 100644
index 0000000..f440f5f
--- /dev/null
+++ b/src/tdeconf_update/Makefile.am
@@ -0,0 +1,3 @@
+update_DATA = krusader_tqt_selection.upd
+
+updatedir = $(datadir)/apps/tdeconf_update
diff --git a/src/tdeconf_update/krusader_tqt_selection.upd b/src/tdeconf_update/krusader_tqt_selection.upd
new file mode 100644
index 0000000..b9d343d
--- /dev/null
+++ b/src/tdeconf_update/krusader_tqt_selection.upd
@@ -0,0 +1,4 @@
+Id=krusader_qt_selection_renaming
+File=krusaderrc
+Group=Custom Selection Mode
+Key=QT Selection,TQt Selection
diff --git a/src/virt/CMakeL10n.txt b/src/virt/CMakeL10n.txt
new file mode 100644
index 0000000..e878b92
--- /dev/null
+++ b/src/virt/CMakeL10n.txt
@@ -0,0 +1,3 @@
+##### create translation templates ##############
+
+tde_l10n_create_template( "messages/tdeio_virt/" )
diff --git a/src/virt/Makefile.am b/src/virt/Makefile.am
new file mode 100644
index 0000000..39c0cd9
--- /dev/null
+++ b/src/virt/Makefile.am
@@ -0,0 +1,17 @@
+## Makefile.am of tdebase/tdeioslave/tar
+
+INCLUDES = $(all_includes)
+AM_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TQT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = tdeio_virt.la
+
+tdeio_virt_la_SOURCES = virt.cpp
+tdeio_virt_la_LIBADD = $(LIB_TDESYCOCA)
+tdeio_virt_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_TQT) $(LIB_TDECORE)
+
+noinst_HEADERS = virt.h
+
+kdelnk_DATA = virt.protocol
+kdelnkdir = $(kde_servicesdir)
+
diff --git a/src/virt/virt.cpp b/src/virt/virt.cpp
new file mode 100644
index 0000000..c94b282
--- /dev/null
+++ b/src/virt/virt.cpp
@@ -0,0 +1,305 @@
+/***************************************************************************
+ virt.cpp
+ -------------------
+ 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 <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <tqfile.h>
+#include <kurl.h>
+#include <kdebug.h>
+#include <tdelocale.h>
+#include <tdeversion.h>
+#include <tdeinstance.h>
+#include <tdemessagebox.h>
+
+#include "virt.h"
+
+using namespace TDEIO;
+
+#define VIRT_VFS_DB "virt_vfs.db"
+#define VIRT_PROTOCOL "virt"
+
+#if KDE_IS_VERSION(3,4,0)
+extern "C" { int TDE_EXPORT kdemain( int argc, char **argv ); }
+#else
+extern "C" { int kdemain( int argc, char **argv ); }
+#endif
+
+#define KrDEBUG(X...){\
+ FILE* f = fopen("/tmp/tdeio_virt.log","a+");\
+ fprintf(f,X);\
+ fclose(f);\
+}
+
+TQDict<KURL::List> VirtProtocol::kioVirtDict;
+TDEConfig* VirtProtocol::tdeio_virt_db;
+
+int kdemain( int argc, char **argv ) {
+ TDEInstance instance( "tdeio_virt" );
+
+ if ( argc != 4 ) {
+ fprintf( stderr, "Usage: tdeio_virt protocol domain-socket1 domain-socket2\n" );
+ exit( -1 );
+ }
+
+ VirtProtocol slave( argv[ 2 ], argv[ 3 ] );
+ slave.dispatchLoop();
+
+ return 0;
+}
+
+VirtProtocol::VirtProtocol( const TQCString &pool, const TQCString &app ) : SlaveBase( "virt", pool, app ) {
+ tdeio_virt_db = new TDEConfig(VIRT_VFS_DB,false,"data");
+}
+
+VirtProtocol::~VirtProtocol() {
+ delete tdeio_virt_db;
+}
+
+void VirtProtocol::del(KURL const & /*url */, bool /* isFile */ ){
+// KRDEBUG(url.path());
+
+ messageBox(TDEIO::SlaveBase::QuestionYesNo,
+ "",
+ i18n("Virtulal delete"),
+ i18n("remove from virtual space"),
+ i18n("really delete")
+ );
+
+ finished();
+}
+
+void VirtProtocol::copy( const KURL &src, const KURL &dest, int /* permissions */, bool /* overwrite */ ){
+ TQString path = dest.path( -1 ).mid( 1 );
+ path = path.left(path.findRev("/"));
+ if ( path.isEmpty() ) path = "/";
+
+ if( addDir(path) ){
+ kioVirtDict[ path ]->append(src);
+ save();
+ }
+
+ finished();
+}
+
+bool VirtProtocol::addDir(TQString& path){
+
+ if( kioVirtDict[ path ] ) return true;
+
+ TQString updir;
+ if( !path.contains("/") ) updir = "/";
+ else updir = path.left(path.findRev("/"));
+ TQString name = path.mid(path.findRev("/")+1);
+
+ if( addDir(updir) ){
+ KURL url;
+ if( updir == "/" ) url = TQString("virt:/")+name;
+ else url = TQString("virt:/")+updir+"/"+name;
+ kioVirtDict[ updir ]->append( url );
+
+ KURL::List* temp = new KURL::List();
+ kioVirtDict.replace( path, temp );
+
+ return true;
+ }
+ return false;
+}
+
+void VirtProtocol::mkdir(const KURL& url,int){
+ if( url.protocol() != VIRT_PROTOCOL ){
+ redirection(url);
+ finished();
+ return;
+ }
+
+ TQString path = url.path( -1 ).mid( 1 );
+ if ( path.isEmpty() ) path = "/";
+
+ if( kioVirtDict[ path ] ){
+ error( TDEIO::ERR_DIR_ALREADY_EXIST, url.path() );
+ return;
+ }
+
+ addDir(path);
+
+ save();
+
+ finished();
+}
+
+void VirtProtocol::listDir( const KURL & url ) {
+ if( url.protocol() != VIRT_PROTOCOL ){
+ redirection(url);
+ finished();
+ return;
+ }
+
+ load();
+
+ TQString path = url.path( -1 ).mid( 1 );
+ if ( path.isEmpty() ) path = "/";
+
+ KURL::List* urlList = kioVirtDict[ path ];
+ if ( !urlList ) {
+ error(ERR_CANNOT_ENTER_DIRECTORY,url.path());
+ return;
+ }
+
+ UDSEntryList dirList;
+ KURL::List::iterator it;
+ for ( it = urlList->begin() ; it != urlList->end() ; ++it ) {
+ KURL entry_url = *it;
+ // translate url->UDS_ENTRY
+ UDSEntry entry;
+ if( entry_url.protocol() == VIRT_PROTOCOL ){
+ local_entry(entry_url,entry);
+ } else {
+ UDSAtom atom;
+
+ atom.m_uds = UDS_NAME;
+ atom.m_str = url.isLocalFile() ? url.path() : entry_url.prettyURL();
+ entry.append(atom);
+
+ atom.m_uds = UDS_URL;
+ atom.m_str = entry_url.url();
+ entry.append(atom);
+ }
+
+ dirList.append(entry);
+ }
+
+ totalSize(dirList.size());
+ listEntries(dirList);
+
+ finished();
+}
+
+void VirtProtocol::stat( const KURL & url ) {
+ if( url.protocol() != VIRT_PROTOCOL ){
+ redirection(url);
+ finished();
+ return;
+ }
+
+ UDSEntry entry;
+ local_entry(url,entry);
+
+ statEntry(entry);
+
+ finished();
+}
+
+void VirtProtocol::get( const KURL & url ) {
+ if( url.protocol() != VIRT_PROTOCOL ){
+ redirection(url);
+ finished();
+ return;
+ }
+
+ finished();
+}
+
+bool VirtProtocol::rewriteURL(const KURL& /* src */, KURL&){
+ return true;
+}
+
+bool VirtProtocol::save(){
+ lock();
+
+ TDEConfig* db = new TDEConfig(VIRT_VFS_DB,false,"data");;
+
+ db->setGroup("virt_db");
+ TQDictIterator<KURL::List> it( kioVirtDict ); // See TQDictIterator
+ for( ; it.current(); ++it ){
+ KURL::List::iterator url;
+ TQStringList entry;
+ for ( url = it.current()->begin() ; url != it.current()->end() ; ++url ) {
+ entry.append( (*url).url() );
+ }
+ db->writeEntry(it.currentKey(),entry);
+ }
+
+ db->sync();
+ delete(db);
+
+ unlock();
+
+ return true;
+}
+
+bool VirtProtocol::load(){
+ lock();
+
+ TDEConfig* db = new TDEConfig(VIRT_VFS_DB,false,"data");
+ db->setGroup("virt_db");
+
+ TQMap<TQString, TQString> map = db->entryMap("virt_db");
+ TQMap<TQString, TQString>::Iterator it;
+ KURL::List* urlList;
+ for ( it = map.begin(); it != map.end(); ++it ) {
+ urlList = new KURL::List( db->readListEntry(it.key()) );
+ kioVirtDict.replace( it.key(),urlList );
+ }
+
+ if( !kioVirtDict["/" ]){
+ urlList = new KURL::List();
+ kioVirtDict.replace( "/", urlList );
+ }
+
+ unlock();
+
+ delete(db);
+
+ return true;
+}
+
+void VirtProtocol::local_entry(const KURL& url,UDSEntry& entry){
+ TQString path = url.path( -1 ).mid( 1 );
+ if ( path.isEmpty() ) path = "/";
+
+ UDSAtom atom;
+
+ atom.m_uds = UDS_NAME;
+ atom.m_str = url.fileName();
+ entry.append(atom);
+
+ atom.m_uds = UDS_URL;
+ atom.m_str = url.url();
+ entry.append(atom);
+
+ atom.m_uds = UDS_FILE_TYPE;
+ atom.m_long = S_IFDIR;
+ entry.append(atom);
+
+ atom.m_uds = UDS_ACCESS;
+ atom.m_long = 0700;
+ entry.append(atom);
+
+ atom.m_uds = UDS_MIME_TYPE;
+ atom.m_str = "inode/system_directory";
+ entry.append(atom);
+}
+
+bool VirtProtocol::lock(){
+ return true;
+}
+
+bool VirtProtocol::unlock(){
+ return true;
+}
diff --git a/src/virt/virt.h b/src/virt/virt.h
new file mode 100644
index 0000000..8f5bc79
--- /dev/null
+++ b/src/virt/virt.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+ virt.h
+ -------------------
+ 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_H
+#define _VIRT_H
+
+#include <sys/types.h>
+#include <tqdict.h>
+#include <tdeconfig.h>
+#include <tdeio/slavebase.h>
+
+class VirtProtocol : public TDEIO::SlaveBase {
+public:
+ VirtProtocol( const TQCString &pool, const TQCString &app );
+ virtual ~VirtProtocol();
+
+ virtual void listDir ( const KURL & url );
+ virtual void stat ( const KURL & url );
+ virtual void get ( const KURL & url );
+ virtual void mkdir(const KURL& url,int permissions);
+ virtual void copy( const KURL &src, const KURL &dest, int permissions, bool overwrite );
+ virtual void del (KURL const & url, bool isFile);
+
+protected:
+ bool lock();
+ bool unlock();
+ bool save();
+ bool load();
+
+ void local_entry(const KURL& url,TDEIO::UDSEntry& entry);
+ bool addDir(TQString& path);
+
+
+ static TQDict<KURL::List> kioVirtDict;
+ static TDEConfig* tdeio_virt_db;
+
+ bool rewriteURL(const KURL&, KURL&);
+
+};
+
+#endif
diff --git a/src/virt/virt.protocol b/src/virt/virt.protocol
new file mode 100644
index 0000000..b23b509
--- /dev/null
+++ b/src/virt/virt.protocol
@@ -0,0 +1,19 @@
+[Protocol]
+exec=tdeio_virt
+protocol=virt
+input=filesystem
+output=filesystem
+listing=Name,Type,Size,Date,AccessDate,Access,Owner,Group,Link
+reading=true
+writing=true
+makedir=true
+deleting=true
+linking=true
+moving=true
+Icon=computer
+maxInstances=4
+copyFromFile=true
+X-DocPath=tdeioslave/virt/index.html
+Class=:local
+#deleteRecursive=true
+#fileNameUsedForCopying=Name